OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [mtd/] [maps/] [pcmciamtd.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * $Id: pcmciamtd.c,v 1.1.1.1 2004-04-15 01:51:53 phoenix Exp $
3
 *
4
 * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
5
 *
6
 * Author: Simon Evans <spse@secret.org.uk>
7
 *
8
 * Copyright (C) 2002 Simon Evans
9
 *
10
 * Licence: GPL
11
 *
12
 */
13
 
14
#include <linux/module.h>
15
#include <linux/slab.h>
16
#include <linux/timer.h>
17
#include <asm/io.h>
18
#include <asm/system.h>
19
 
20
#include <pcmcia/version.h>
21
#include <pcmcia/cs_types.h>
22
#include <pcmcia/cs.h>
23
#include <pcmcia/cistpl.h>
24
#include <pcmcia/ds.h>
25
 
26
#include <linux/mtd/map.h>
27
 
28
#ifdef CONFIG_MTD_DEBUG
29
static int debug = CONFIG_MTD_DEBUG_VERBOSE;
30
MODULE_PARM(debug, "i");
31
MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
32
#undef DEBUG
33
#define DEBUG(n, format, arg...) \
34
        if (n <= debug) {        \
35
                printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
36
        }
37
 
38
#else
39
#undef DEBUG
40
#define DEBUG(n, arg...)
41
static const int debug = 0;
42
#endif
43
 
44
#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg)
45
#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
46
#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg)
47
 
48
 
49
#define DRIVER_DESC     "PCMCIA Flash memory card driver"
50
#define DRIVER_VERSION  "$Revision: 1.1.1.1 $"
51
 
52
/* Size of the PCMCIA address space: 26 bits = 64 MB */
53
#define MAX_PCMCIA_ADDR 0x4000000
54
 
55
struct pcmciamtd_dev {
56
        dev_link_t      link;           /* PCMCIA link */
57
        dev_node_t      node;           /* device node */
58
        caddr_t         win_base;       /* ioremapped address of PCMCIA window */
59
        unsigned int    win_size;       /* size of window */
60
        unsigned int    offset;         /* offset into card the window currently points at */
61
        struct map_info pcmcia_map;
62
        struct mtd_info *mtd_info;
63
        int             vpp;
64
        char            mtd_name[sizeof(struct cistpl_vers_1_t)];
65
};
66
 
67
 
68
static dev_info_t dev_info = "pcmciamtd";
69
static dev_link_t *dev_list;
70
 
71
/* Module parameters */
72
 
73
/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
74
static int buswidth = 2;
75
 
76
/* Speed of memory accesses, in ns */
77
static int mem_speed;
78
 
79
/* Force the size of an SRAM card */
80
static int force_size;
81
 
82
/* Force Vpp */
83
static int vpp;
84
 
85
/* Set Vpp */
86
static int setvpp;
87
 
88
/* Force card to be treated as FLASH, ROM or RAM */
89
static int mem_type;
90
 
91
MODULE_LICENSE("GPL");
92
MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
93
MODULE_DESCRIPTION(DRIVER_DESC);
94
MODULE_PARM(buswidth, "i");
95
MODULE_PARM_DESC(buswidth, "Set buswidth (1=8 bit, 2=16 bit, default=2)");
96
MODULE_PARM(mem_speed, "i");
97
MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
98
MODULE_PARM(force_size, "i");
99
MODULE_PARM_DESC(force_size, "Force size of card in MB (1-64)");
100
MODULE_PARM(setvpp, "i");
101
MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");
102
MODULE_PARM(vpp, "i");
103
MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");
104
MODULE_PARM(mem_type, "i");
105
MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
106
 
107
 
108
 
109
static inline void cs_error(client_handle_t handle, int func, int ret)
110
{
111
        error_info_t err = { func, ret };
112
        CardServices(ReportError, handle, &err);
113
}
114
 
115
 
116
/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */
117
 
118
static caddr_t remap_window(struct map_info *map, unsigned long to)
119
{
120
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
121
        window_handle_t win = (window_handle_t)map->map_priv_2;
122
        memreq_t mrq;
123
        int ret;
124
 
125
        if(!(dev->link.state & DEV_PRESENT)) {
126
                DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
127
                return 0;
128
        }
129
 
130
        mrq.CardOffset = to & ~(dev->win_size-1);
131
        if(mrq.CardOffset != dev->offset) {
132
                DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
133
                      dev->offset, mrq.CardOffset);
134
                mrq.Page = 0;
135
                if( (ret = CardServices(MapMemPage, win, &mrq)) != CS_SUCCESS) {
136
                        cs_error(dev->link.handle, MapMemPage, ret);
137
                        return NULL;
138
                }
139
                dev->offset = mrq.CardOffset;
140
        }
141
        return dev->win_base + (to & (dev->win_size-1));
142
}
143
 
144
 
145
static u8 pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
146
{
147
        caddr_t addr;
148
        u8 d;
149
 
150
        addr = remap_window(map, ofs);
151
        if(!addr)
152
                return 0;
153
 
154
        d = readb(addr);
155
        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d);
156
        return d;
157
}
158
 
159
 
160
static u16 pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
161
{
162
        caddr_t addr;
163
        u16 d;
164
 
165
        addr = remap_window(map, ofs);
166
        if(!addr)
167
                return 0;
168
 
169
        d = readw(addr);
170
        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d);
171
        return d;
172
}
173
 
174
 
175
static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len)
176
{
177
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
178
        unsigned long win_size = dev->win_size;
179
 
180
        DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
181
        while(len) {
182
                int toread = win_size - (from & (win_size-1));
183
                caddr_t addr;
184
 
185
                if(toread > len)
186
                        toread = len;
187
 
188
                addr = remap_window(map, from);
189
                if(!addr)
190
                        return;
191
 
192
                DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
193
                memcpy_fromio(to, addr, toread);
194
                len -= toread;
195
                to += toread;
196
                from += toread;
197
        }
198
}
199
 
200
 
201
static void pcmcia_write8_remap(struct map_info *map, u8 d, unsigned long adr)
202
{
203
        caddr_t addr = remap_window(map, adr);
204
 
205
        if(!addr)
206
                return;
207
 
208
        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02x", adr, addr, d);
209
        writeb(d, addr);
210
}
211
 
212
 
213
static void pcmcia_write16_remap(struct map_info *map, u16 d, unsigned long adr)
214
{
215
        caddr_t addr = remap_window(map, adr);
216
        if(!addr)
217
                return;
218
 
219
        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04x", adr, addr, d);
220
        writew(d, addr);
221
}
222
 
223
 
224
static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len)
225
{
226
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
227
        unsigned long win_size = dev->win_size;
228
 
229
        DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
230
        while(len) {
231
                int towrite = win_size - (to & (win_size-1));
232
                caddr_t addr;
233
 
234
                if(towrite > len)
235
                        towrite = len;
236
 
237
                addr = remap_window(map, to);
238
                if(!addr)
239
                        return;
240
 
241
                DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
242
                memcpy_toio(addr, from, towrite);
243
                len -= towrite;
244
                to += towrite;
245
                from += towrite;
246
        }
247
}
248
 
249
 
250
/* read/write{8,16} copy_{from,to} routines with direct access */
251
 
252
#define DEV_REMOVED(x)  (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
253
 
254
static u8 pcmcia_read8(struct map_info *map, unsigned long ofs)
255
{
256
        caddr_t win_base = (caddr_t)map->map_priv_2;
257
        u8 d;
258
 
259
        if(DEV_REMOVED(map))
260
                return 0;
261
 
262
        d = readb(win_base + ofs);
263
        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d);
264
        return d;
265
}
266
 
267
 
268
static u16 pcmcia_read16(struct map_info *map, unsigned long ofs)
269
{
270
        caddr_t win_base = (caddr_t)map->map_priv_2;
271
        u16 d;
272
 
273
        if(DEV_REMOVED(map))
274
                return 0;
275
 
276
        d = readw(win_base + ofs);
277
        DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d);
278
        return d;
279
}
280
 
281
 
282
static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
283
{
284
        caddr_t win_base = (caddr_t)map->map_priv_2;
285
 
286
        if(DEV_REMOVED(map))
287
                return;
288
 
289
        DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
290
        memcpy_fromio(to, win_base + from, len);
291
}
292
 
293
 
294
static void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr)
295
{
296
        caddr_t win_base = (caddr_t)map->map_priv_2;
297
 
298
        if(DEV_REMOVED(map))
299
                return;
300
 
301
        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%02x", adr, win_base + adr, d);
302
        writeb(d, win_base + adr);
303
}
304
 
305
 
306
static void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr)
307
{
308
        caddr_t win_base = (caddr_t)map->map_priv_2;
309
 
310
        if(DEV_REMOVED(map))
311
                return;
312
 
313
        DEBUG(3, "adr = 0x%08lx (%p)  data = 0x%04x", adr, win_base + adr, d);
314
        writew(d, win_base + adr);
315
}
316
 
317
 
318
static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
319
{
320
        caddr_t win_base = (caddr_t)map->map_priv_2;
321
 
322
        if(DEV_REMOVED(map))
323
                return;
324
 
325
        DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
326
        memcpy_toio(win_base + to, from, len);
327
}
328
 
329
 
330
static void pcmciamtd_set_vpp(struct map_info *map, int on)
331
{
332
        struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
333
        dev_link_t *link = &dev->link;
334
        modconf_t mod;
335
        int ret;
336
 
337
        mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
338
        mod.Vcc = 0;
339
        mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
340
 
341
        DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
342
        ret = CardServices(ModifyConfiguration, link->handle, &mod);
343
        if(ret != CS_SUCCESS) {
344
                cs_error(link->handle, ModifyConfiguration, ret);
345
        }
346
}
347
 
348
 
349
/* After a card is removed, pcmciamtd_release() will unregister the
350
 * device, and release the PCMCIA configuration.  If the device is
351
 * still open, this will be postponed until it is closed.
352
 */
353
 
354
static void pcmciamtd_release(u_long arg)
355
{
356
        dev_link_t *link = (dev_link_t *)arg;
357
        struct pcmciamtd_dev *dev = link->priv;
358
 
359
        DEBUG(3, "link = 0x%p", link);
360
 
361
        if (link->win) {
362
                if(dev->win_base) {
363
                        iounmap(dev->win_base);
364
                        dev->win_base = NULL;
365
                }
366
                CardServices(ReleaseWindow, link->win);
367
        }
368
        CardServices(ReleaseConfiguration, link->handle);
369
        link->state &= ~DEV_CONFIG;
370
}
371
 
372
 
373
static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
374
{
375
        int rc;
376
        tuple_t tuple;
377
        cisparse_t parse;
378
        u_char buf[64];
379
 
380
        tuple.Attributes = 0;
381
        tuple.TupleData = (cisdata_t *)buf;
382
        tuple.TupleDataMax = sizeof(buf);
383
        tuple.TupleOffset = 0;
384
        tuple.DesiredTuple = RETURN_FIRST_TUPLE;
385
 
386
        rc = CardServices(GetFirstTuple, link->handle, &tuple);
387
        while(rc == CS_SUCCESS) {
388
                rc = CardServices(GetTupleData, link->handle, &tuple);
389
                if(rc != CS_SUCCESS) {
390
                        cs_error(link->handle, GetTupleData, rc);
391
                        break;
392
                }
393
                rc = CardServices(ParseTuple, link->handle, &tuple, &parse);
394
                if(rc != CS_SUCCESS) {
395
                        cs_error(link->handle, ParseTuple, rc);
396
                        break;
397
                }
398
 
399
                switch(tuple.TupleCode) {
400
                case  CISTPL_FORMAT: {
401
                        cistpl_format_t *t = &parse.format;
402
                        (void)t; /* Shut up, gcc */
403
                        DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
404
                              t->type, t->edc, t->offset, t->length);
405
                        break;
406
 
407
                }
408
 
409
                case CISTPL_DEVICE: {
410
                        cistpl_device_t *t = &parse.device;
411
                        int i;
412
                        DEBUG(2, "Common memory:");
413
                        dev->pcmcia_map.size = t->dev[0].size;
414
                        for(i = 0; i < t->ndev; i++) {
415
                                DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
416
                                DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
417
                                DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
418
                                DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
419
                        }
420
                        break;
421
                }
422
 
423
                case CISTPL_VERS_1: {
424
                        cistpl_vers_1_t *t = &parse.version_1;
425
                        int i;
426
                        if(t->ns) {
427
                                dev->mtd_name[0] = '\0';
428
                                for(i = 0; i < t->ns; i++) {
429
                                        if(i)
430
                                                strcat(dev->mtd_name, " ");
431
                                        strcat(dev->mtd_name, t->str+t->ofs[i]);
432
                                }
433
                        }
434
                        DEBUG(2, "Found name: %s", dev->mtd_name);
435
                        break;
436
                }
437
 
438
                case CISTPL_JEDEC_C: {
439
                        cistpl_jedec_t *t = &parse.jedec;
440
                        int i;
441
                        for(i = 0; i < t->nid; i++) {
442
                                DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info);
443
                        }
444
                        break;
445
                }
446
 
447
                case CISTPL_DEVICE_GEO: {
448
                        cistpl_device_geo_t *t = &parse.device_geo;
449
                        int i;
450
                        dev->pcmcia_map.buswidth = t->geo[0].buswidth;
451
                        for(i = 0; i < t->ngeo; i++) {
452
                                DEBUG(2, "region: %d buswidth = %u", i, t->geo[i].buswidth);
453
                                DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
454
                                DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
455
                                DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
456
                                DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
457
                                DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
458
                        }
459
                        break;
460
                }
461
 
462
                default:
463
                        DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
464
                }
465
 
466
                rc = CardServices(GetNextTuple, link->handle, &tuple, &parse);
467
        }
468
        if(!dev->pcmcia_map.size)
469
                dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
470
 
471
        if(!dev->pcmcia_map.buswidth)
472
                dev->pcmcia_map.buswidth = 2;
473
 
474
        if(force_size) {
475
                dev->pcmcia_map.size = force_size << 20;
476
                DEBUG(2, "size forced to %dM", force_size);
477
        }
478
 
479
        if(buswidth) {
480
                dev->pcmcia_map.buswidth = buswidth;
481
                DEBUG(2, "buswidth forced to %d", buswidth);
482
        }
483
 
484
        dev->pcmcia_map.name = dev->mtd_name;
485
        if(!dev->mtd_name[0]) {
486
                strcpy(dev->mtd_name, "PCMCIA Memory card");
487
                *new_name = 1;
488
        }
489
 
490
        DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
491
              dev->pcmcia_map.size, dev->pcmcia_map.buswidth << 3, dev->mtd_name);
492
}
493
 
494
 
495
/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
496
 * is received, to configure the PCMCIA socket, and to make the
497
 * MTD device available to the system.
498
 */
499
 
500
#define CS_CHECK(fn, args...) \
501
while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
502
 
503
static void pcmciamtd_config(dev_link_t *link)
504
{
505
        struct pcmciamtd_dev *dev = link->priv;
506
        struct mtd_info *mtd = NULL;
507
        cs_status_t status;
508
        win_req_t req;
509
        int last_ret = 0, last_fn = 0;
510
        int ret;
511
        int i;
512
        config_info_t t;
513
        static char *probes[] = { "jedec_probe", "cfi_probe" };
514
        cisinfo_t cisinfo;
515
        int new_name = 0;
516
 
517
        DEBUG(3, "link=0x%p", link);
518
 
519
        /* Configure card */
520
        link->state |= DEV_CONFIG;
521
 
522
        DEBUG(2, "Validating CIS");
523
        ret = CardServices(ValidateCIS, link->handle, &cisinfo);
524
        if(ret != CS_SUCCESS) {
525
                cs_error(link->handle, GetTupleData, ret);
526
        } else {
527
                DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
528
        }
529
 
530
        card_settings(dev, link, &new_name);
531
 
532
        dev->pcmcia_map.read8 = pcmcia_read8_remap;
533
        dev->pcmcia_map.read16 = pcmcia_read16_remap;
534
        dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
535
        dev->pcmcia_map.write8 = pcmcia_write8_remap;
536
        dev->pcmcia_map.write16 = pcmcia_write16_remap;
537
        dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
538
        if(setvpp == 1)
539
                dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
540
 
541
        /* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum
542
           that PCMCIA can support (64Mb) - this is ideal and we aim for a window the size of the
543
           whole card - otherwise we try smaller windows until we succeed */
544
 
545
        req.Attributes =  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
546
        req.Attributes |= (dev->pcmcia_map.buswidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
547
        req.Base = 0;
548
        req.AccessSpeed = mem_speed;
549
        link->win = (window_handle_t)link->handle;
550
        req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
551
        dev->win_size = 0;
552
 
553
        do {
554
                int ret;
555
                DEBUG(2, "requesting window with size = %dKB memspeed = %d",
556
                      req.Size >> 10, req.AccessSpeed);
557
                link->win = (window_handle_t)link->handle;
558
                ret = CardServices(RequestWindow, &link->win, &req);
559
                DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
560
                if(ret) {
561
                        req.Size >>= 1;
562
                } else {
563
                        DEBUG(2, "Got window of size %dKB", req.Size >> 10);
564
                        dev->win_size = req.Size;
565
                        break;
566
                }
567
        } while(req.Size >= 0x1000);
568
 
569
        DEBUG(2, "dev->win_size = %d", dev->win_size);
570
 
571
        if(!dev->win_size) {
572
                err("Cant allocate memory window");
573
                pcmciamtd_release((u_long)link);
574
                return;
575
        }
576
        DEBUG(1, "Allocated a window of %dKB", dev->win_size >> 10);
577
 
578
        /* Get write protect status */
579
        CS_CHECK(GetStatus, link->handle, &status);
580
        DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
581
              status.CardState, (unsigned long)link->win);
582
        dev->win_base = ioremap(req.Base, req.Size);
583
        if(!dev->win_base) {
584
                err("ioremap(%lu, %u) failed", req.Base, req.Size);
585
                pcmciamtd_release((u_long)link);
586
                return;
587
        }
588
        DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
589
              dev, req.Base, dev->win_base, req.Size);
590
 
591
        dev->offset = 0;
592
        dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
593
        dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
594
 
595
        DEBUG(2, "Getting configuration");
596
        CS_CHECK(GetConfigurationInfo, link->handle, &t);
597
        DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
598
        dev->vpp = (vpp) ? vpp : t.Vpp1;
599
        link->conf.Attributes = 0;
600
        link->conf.Vcc = t.Vcc;
601
        if(setvpp == 2) {
602
                link->conf.Vpp1 = dev->vpp;
603
                link->conf.Vpp2 = dev->vpp;
604
        } else {
605
                link->conf.Vpp1 = 0;
606
                link->conf.Vpp2 = 0;
607
        }
608
 
609
        link->conf.IntType = INT_MEMORY;
610
        link->conf.ConfigBase = t.ConfigBase;
611
        link->conf.Status = t.Status;
612
        link->conf.Pin = t.Pin;
613
        link->conf.Copy = t.Copy;
614
        link->conf.ExtStatus = t.ExtStatus;
615
        link->conf.ConfigIndex = 0;
616
        link->conf.Present = t.Present;
617
        DEBUG(2, "Setting Configuration");
618
        ret = CardServices(RequestConfiguration, link->handle, &link->conf);
619
        if(ret != CS_SUCCESS) {
620
                cs_error(link->handle, RequestConfiguration, ret);
621
        }
622
 
623
        if(mem_type == 1) {
624
                mtd = do_map_probe("map_ram", &dev->pcmcia_map);
625
        } else if(mem_type == 2) {
626
                mtd = do_map_probe("map_rom", &dev->pcmcia_map);
627
        } else {
628
                for(i = 0; i < sizeof(probes) / sizeof(char *); i++) {
629
                        DEBUG(1, "Trying %s", probes[i]);
630
                        mtd = do_map_probe(probes[i], &dev->pcmcia_map);
631
                        if(mtd)
632
                                break;
633
 
634
                        DEBUG(1, "FAILED: %s", probes[i]);
635
                }
636
        }
637
 
638
        if(!mtd) {
639
                DEBUG(1, "Cant find an MTD");
640
                pcmciamtd_release((u_long)link);
641
                return;
642
        }
643
 
644
        dev->mtd_info = mtd;
645
        mtd->module = THIS_MODULE;
646
 
647
        if(new_name) {
648
                int size = 0;
649
                char unit = ' ';
650
                /* Since we are using a default name, make it better by adding in the
651
                   size */
652
                if(mtd->size < 1048576) { /* <1MB in size, show size in K */
653
                        size = mtd->size >> 10;
654
                        unit = 'K';
655
                } else {
656
                        size = mtd->size >> 20;
657
                        unit = 'M';
658
                }
659
                snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%cB %s", size, unit, "PCMCIA Memory card");
660
        }
661
 
662
        /* If the memory found is fits completely into the mapped PCMCIA window,
663
           use the faster non-remapping read/write functions */
664
        if(mtd->size <= dev->win_size) {
665
                DEBUG(1, "Using non remapping memory functions");
666
                dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
667
                dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
668
                dev->pcmcia_map.read8 = pcmcia_read8;
669
                dev->pcmcia_map.read16 = pcmcia_read16;
670
                dev->pcmcia_map.copy_from = pcmcia_copy_from;
671
                dev->pcmcia_map.write8 = pcmcia_write8;
672
                dev->pcmcia_map.write16 = pcmcia_write16;
673
                dev->pcmcia_map.copy_to = pcmcia_copy_to;
674
        }
675
 
676
        if(add_mtd_device(mtd)) {
677
                map_destroy(mtd);
678
                dev->mtd_info = NULL;
679
                err("Couldnt register MTD device");
680
                pcmciamtd_release((u_long)link);
681
                return;
682
        }
683
        snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
684
        info("mtd%d: %s", mtd->index, mtd->name);
685
        link->state &= ~DEV_CONFIG_PENDING;
686
        link->dev = &dev->node;
687
        return;
688
 
689
 cs_failed:
690
        cs_error(link->handle, last_fn, last_ret);
691
        err("CS Error, exiting");
692
        pcmciamtd_release((u_long)link);
693
        return;
694
}
695
 
696
 
697
/* The card status event handler.  Mostly, this schedules other
698
 * stuff to run after an event is received.  A CARD_REMOVAL event
699
 * also sets some flags to discourage the driver from trying
700
 * to talk to the card any more.
701
 */
702
 
703
static int pcmciamtd_event(event_t event, int priority,
704
                        event_callback_args_t *args)
705
{
706
        dev_link_t *link = args->client_data;
707
 
708
        DEBUG(1, "event=0x%06x", event);
709
        switch (event) {
710
        case CS_EVENT_CARD_REMOVAL:
711
                DEBUG(2, "EVENT_CARD_REMOVAL");
712
                link->state &= ~DEV_PRESENT;
713
                if (link->state & DEV_CONFIG) {
714
                        struct pcmciamtd_dev *dev = link->priv;
715
                        if(dev->mtd_info) {
716
                                del_mtd_device(dev->mtd_info);
717
                                info("mtd%d: Removed", dev->mtd_info->index);
718
                        }
719
                        mod_timer(&link->release, jiffies + HZ/20);
720
                }
721
                break;
722
        case CS_EVENT_CARD_INSERTION:
723
                DEBUG(2, "EVENT_CARD_INSERTION");
724
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
725
                pcmciamtd_config(link);
726
                break;
727
        case CS_EVENT_PM_SUSPEND:
728
                DEBUG(2, "EVENT_PM_SUSPEND");
729
                link->state |= DEV_SUSPEND;
730
                /* Fall through... */
731
        case CS_EVENT_RESET_PHYSICAL:
732
                DEBUG(2, "EVENT_RESET_PHYSICAL");
733
                /* get_lock(link); */
734
                break;
735
        case CS_EVENT_PM_RESUME:
736
                DEBUG(2, "EVENT_PM_RESUME");
737
                link->state &= ~DEV_SUSPEND;
738
                /* Fall through... */
739
        case CS_EVENT_CARD_RESET:
740
                DEBUG(2, "EVENT_CARD_RESET");
741
                /* free_lock(link); */
742
                break;
743
        default:
744
                DEBUG(2, "Unknown event %d", event);
745
        }
746
        return 0;
747
}
748
 
749
 
750
/* This deletes a driver "instance".  The device is de-registered
751
 * with Card Services.  If it has been released, all local data
752
 * structures are freed.  Otherwise, the structures will be freed
753
 * when the device is released.
754
 */
755
 
756
static void pcmciamtd_detach(dev_link_t *link)
757
{
758
        DEBUG(3, "link=0x%p", link);
759
 
760
        del_timer(&link->release);
761
 
762
        if(link->state & DEV_CONFIG) {
763
                pcmciamtd_release((u_long)link);
764
        }
765
 
766
        if (link->handle) {
767
                int ret;
768
                DEBUG(2, "Deregistering with card services");
769
                ret = CardServices(DeregisterClient, link->handle);
770
                if (ret != CS_SUCCESS)
771
                        cs_error(link->handle, DeregisterClient, ret);
772
        }
773
 
774
        link->state |= DEV_STALE_LINK;
775
}
776
 
777
 
778
/* pcmciamtd_attach() creates an "instance" of the driver, allocating
779
 * local data structures for one device.  The device is registered
780
 * with Card Services.
781
 */
782
 
783
static dev_link_t *pcmciamtd_attach(void)
784
{
785
        struct pcmciamtd_dev *dev;
786
        dev_link_t *link;
787
        client_reg_t client_reg;
788
        int ret;
789
 
790
        /* Create new memory card device */
791
        dev = kmalloc(sizeof(*dev), GFP_KERNEL);
792
        if (!dev) return NULL;
793
        DEBUG(1, "dev=0x%p", dev);
794
 
795
        memset(dev, 0, sizeof(*dev));
796
        link = &dev->link;
797
        link->priv = dev;
798
 
799
        init_timer(&link->release);
800
        link->release.function = &pcmciamtd_release;
801
        link->release.data = (u_long)link;
802
 
803
        link->conf.Attributes = 0;
804
        link->conf.IntType = INT_MEMORY;
805
 
806
        link->next = dev_list;
807
        dev_list = link;
808
 
809
        /* Register with Card Services */
810
        client_reg.dev_info = &dev_info;
811
        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
812
        client_reg.EventMask =
813
                CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
814
                CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
815
                CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
816
        client_reg.event_handler = &pcmciamtd_event;
817
        client_reg.Version = 0x0210;
818
        client_reg.event_callback_args.client_data = link;
819
        DEBUG(2, "Calling RegisterClient");
820
        ret = CardServices(RegisterClient, &link->handle, &client_reg);
821
        if (ret != 0) {
822
                cs_error(link->handle, RegisterClient, ret);
823
                pcmciamtd_detach(link);
824
                return NULL;
825
        }
826
        DEBUG(2, "link = %p", link);
827
        return link;
828
}
829
 
830
 
831
static int __init init_pcmciamtd(void)
832
{
833
        servinfo_t serv;
834
 
835
        info(DRIVER_DESC " " DRIVER_VERSION);
836
        CardServices(GetCardServicesInfo, &serv);
837
        if (serv.Revision != CS_RELEASE_CODE) {
838
                err("Card Services release does not match!");
839
                return -1;
840
        }
841
 
842
        if(buswidth && buswidth != 1 && buswidth != 2) {
843
                info("bad buswidth (%d), using default", buswidth);
844
                buswidth = 2;
845
        }
846
        if(force_size && (force_size < 1 || force_size > 64)) {
847
                info("bad force_size (%d), using default", force_size);
848
                force_size = 0;
849
        }
850
        if(mem_type && mem_type != 1 && mem_type != 2) {
851
                info("bad mem_type (%d), using default", mem_type);
852
                mem_type = 0;
853
        }
854
        register_pccard_driver(&dev_info, &pcmciamtd_attach, &pcmciamtd_detach);
855
        return 0;
856
}
857
 
858
 
859
static void __exit exit_pcmciamtd(void)
860
{
861
        DEBUG(1, DRIVER_DESC " unloading");
862
        unregister_pccard_driver(&dev_info);
863
 
864
        while(dev_list) {
865
                dev_link_t *link = dev_list;
866
 
867
                dev_list = link->next;
868
                if (link) {
869
                        struct pcmciamtd_dev *dev = link->priv;
870
 
871
                        if(dev) {
872
                                if(link->state & DEV_PRESENT) {
873
                                        if (!(link->state & DEV_STALE_LINK)) {
874
                                                pcmciamtd_detach(link);
875
                                        }
876
                                        link->state &= ~DEV_PRESENT;
877
                                        if(dev->mtd_info) {
878
                                                del_mtd_device(dev->mtd_info);
879
                                                info("mtd%d: Removed",
880
                                                     dev->mtd_info->index);
881
                                        }
882
                                }
883
                                if(dev->mtd_info) {
884
                                        DEBUG(2, "Destroying map for mtd%d",
885
                                              dev->mtd_info->index);
886
                                        map_destroy(dev->mtd_info);
887
                                }
888
                                kfree(dev);
889
                        }
890
                }
891
        }
892
}
893
 
894
module_init(init_pcmciamtd);
895
module_exit(exit_pcmciamtd);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.