aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/alauda.c
diff options
context:
space:
mode:
authorJörn Engel <joern@logfs.org>2007-08-29 11:57:11 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-08-29 12:37:23 -0400
commite208520ed664db0f7584048ae09e5d2afda43714 (patch)
treed8ebe693f239e05e81724c580714759037b1d9f0 /drivers/mtd/nand/alauda.c
parent62d24d91109c3bcd5a5d3fe6cbe354e65e787300 (diff)
[MTD] [NAND] Driver for Olympus MAUSB-10 and Fujifilm DPC-R1 card readers
Unlike most stuff on the market the chip inside these two allows raw flash access and doesn't implement and FTL, leaving that functionality to the device driver. Raw flash access in a cheap USB cardreader! An MTD test device one can attach to a PC! What a deal! The command set of the chip is not documented, so information was obtained from the existing mass-storage driver (drivers/usb/storage/alauda.c), its documentation (http://alauda.sourceforge.net/wikka.php?wakka=BulkCommandReference), additional reverse engineering and comparison with a vendor driver for a related chip (http://www.ratocsystems.com/english/download/driver/linux/sma03u.html). Signed-off-by: Joern Engel <joern@logfs.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/nand/alauda.c')
-rw-r--r--drivers/mtd/nand/alauda.c742
1 files changed, 742 insertions, 0 deletions
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
new file mode 100644
index 000000000000..2c29854b4241
--- /dev/null
+++ b/drivers/mtd/nand/alauda.c
@@ -0,0 +1,742 @@
1/*
2 * MTD driver for Alauda chips
3 *
4 * Copyright (C) 2007 Joern Engel <joern@logfs.org>
5 *
6 * Based on drivers/usb/usb-skeleton.c which is:
7 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
8 * and on drivers/usb/storage/alauda.c, which is:
9 * (c) 2005 Daniel Drake <dsd@gentoo.org>
10 *
11 * Idea and initial work by Arnd Bergmann <arnd@arndb.de>
12 */
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18#include <linux/kref.h>
19#include <linux/usb.h>
20#include <linux/mutex.h>
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/nand_ecc.h>
23
24/* Control commands */
25#define ALAUDA_GET_XD_MEDIA_STATUS 0x08
26#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a
27#define ALAUDA_GET_XD_MEDIA_SIG 0x86
28
29/* Common prefix */
30#define ALAUDA_BULK_CMD 0x40
31
32/* The two ports */
33#define ALAUDA_PORT_XD 0x00
34#define ALAUDA_PORT_SM 0x01
35
36/* Bulk commands */
37#define ALAUDA_BULK_READ_PAGE 0x84
38#define ALAUDA_BULK_READ_OOB 0x85 /* don't use, there's a chip bug */
39#define ALAUDA_BULK_READ_BLOCK 0x94
40#define ALAUDA_BULK_ERASE_BLOCK 0xa3
41#define ALAUDA_BULK_WRITE_PAGE 0xa4
42#define ALAUDA_BULK_WRITE_BLOCK 0xb4
43#define ALAUDA_BULK_RESET_MEDIA 0xe0
44
45/* Address shifting */
46#define PBA_LO(pba) ((pba & 0xF) << 5)
47#define PBA_HI(pba) (pba >> 3)
48#define PBA_ZONE(pba) (pba >> 11)
49
50#define TIMEOUT HZ
51
52static struct usb_device_id alauda_table [] = {
53 { USB_DEVICE(0x0584, 0x0008) }, /* Fujifilm DPC-R1 */
54 { USB_DEVICE(0x07b4, 0x010a) }, /* Olympus MAUSB-10 */
55 { }
56};
57MODULE_DEVICE_TABLE(usb, alauda_table);
58
59struct alauda_card {
60 u8 id; /* id byte */
61 u8 chipshift; /* 1<<chipshift total size */
62 u8 pageshift; /* 1<<pageshift page size */
63 u8 blockshift; /* 1<<blockshift block size */
64};
65
66struct alauda {
67 struct usb_device *dev;
68 struct usb_interface *interface;
69 struct mtd_info *mtd;
70 struct alauda_card *card;
71 struct mutex card_mutex;
72 u32 pagemask;
73 u32 bytemask;
74 u32 blockmask;
75 unsigned int write_out;
76 unsigned int bulk_in;
77 unsigned int bulk_out;
78 u8 port;
79 struct kref kref;
80};
81
82static struct alauda_card alauda_card_ids[] = {
83 /* NAND flash */
84 { 0x6e, 20, 8, 12}, /* 1 MB */
85 { 0xe8, 20, 8, 12}, /* 1 MB */
86 { 0xec, 20, 8, 12}, /* 1 MB */
87 { 0x64, 21, 8, 12}, /* 2 MB */
88 { 0xea, 21, 8, 12}, /* 2 MB */
89 { 0x6b, 22, 9, 13}, /* 4 MB */
90 { 0xe3, 22, 9, 13}, /* 4 MB */
91 { 0xe5, 22, 9, 13}, /* 4 MB */
92 { 0xe6, 23, 9, 13}, /* 8 MB */
93 { 0x73, 24, 9, 14}, /* 16 MB */
94 { 0x75, 25, 9, 14}, /* 32 MB */
95 { 0x76, 26, 9, 14}, /* 64 MB */
96 { 0x79, 27, 9, 14}, /* 128 MB */
97 { 0x71, 28, 9, 14}, /* 256 MB */
98
99 /* MASK ROM */
100 { 0x5d, 21, 9, 13}, /* 2 MB */
101 { 0xd5, 22, 9, 13}, /* 4 MB */
102 { 0xd6, 23, 9, 13}, /* 8 MB */
103 { 0x57, 24, 9, 13}, /* 16 MB */
104 { 0x58, 25, 9, 13}, /* 32 MB */
105 { }
106};
107
108static struct alauda_card *get_card(u8 id)
109{
110 struct alauda_card *card;
111
112 for (card = alauda_card_ids; card->id; card++)
113 if (card->id == id)
114 return card;
115 return NULL;
116}
117
118static void alauda_delete(struct kref *kref)
119{
120 struct alauda *al = container_of(kref, struct alauda, kref);
121
122 if (al->mtd) {
123 del_mtd_device(al->mtd);
124 kfree(al->mtd);
125 }
126 usb_put_dev(al->dev);
127 kfree(al);
128}
129
130static int alauda_get_media_status(struct alauda *al, void *buf)
131{
132 int ret;
133
134 mutex_lock(&al->card_mutex);
135 ret = usb_control_msg(al->dev, usb_rcvctrlpipe(al->dev, 0),
136 ALAUDA_GET_XD_MEDIA_STATUS, 0xc0, 0, 1, buf, 2, HZ);
137 mutex_unlock(&al->card_mutex);
138 return ret;
139}
140
141static int alauda_ack_media(struct alauda *al)
142{
143 int ret;
144
145 mutex_lock(&al->card_mutex);
146 ret = usb_control_msg(al->dev, usb_sndctrlpipe(al->dev, 0),
147 ALAUDA_ACK_XD_MEDIA_CHANGE, 0x40, 0, 1, NULL, 0, HZ);
148 mutex_unlock(&al->card_mutex);
149 return ret;
150}
151
152static int alauda_get_media_signatures(struct alauda *al, void *buf)
153{
154 int ret;
155
156 mutex_lock(&al->card_mutex);
157 ret = usb_control_msg(al->dev, usb_rcvctrlpipe(al->dev, 0),
158 ALAUDA_GET_XD_MEDIA_SIG, 0xc0, 0, 0, buf, 4, HZ);
159 mutex_unlock(&al->card_mutex);
160 return ret;
161}
162
163static void alauda_reset(struct alauda *al)
164{
165 u8 command[] = {
166 ALAUDA_BULK_CMD, ALAUDA_BULK_RESET_MEDIA, 0, 0,
167 0, 0, 0, 0, al->port
168 };
169 mutex_lock(&al->card_mutex);
170 usb_bulk_msg(al->dev, al->bulk_out, command, 9, NULL, HZ);
171 mutex_unlock(&al->card_mutex);
172}
173
174static void correct_data(void *buf, void *read_ecc,
175 int *corrected, int *uncorrected)
176{
177 u8 calc_ecc[3];
178 int err;
179
180 nand_calculate_ecc(NULL, buf, calc_ecc);
181 err = nand_correct_data(NULL, buf, read_ecc, calc_ecc);
182 if (err) {
183 if (err > 0)
184 (*corrected)++;
185 else
186 (*uncorrected)++;
187 }
188}
189
190struct alauda_sg_request {
191 struct urb *urb[3];
192 struct completion comp;
193};
194
195static void alauda_complete(struct urb *urb)
196{
197 struct completion *comp = urb->context;
198
199 if (comp)
200 complete(comp);
201}
202
203static int __alauda_read_page(struct mtd_info *mtd, loff_t from, void *buf,
204 void *oob)
205{
206 struct alauda_sg_request sg;
207 struct alauda *al = mtd->priv;
208 u32 pba = from >> al->card->blockshift;
209 u32 page = (from >> al->card->pageshift) & al->pagemask;
210 u8 command[] = {
211 ALAUDA_BULK_CMD, ALAUDA_BULK_READ_PAGE, PBA_HI(pba),
212 PBA_ZONE(pba), 0, PBA_LO(pba) + page, 1, 0, al->port
213 };
214 int i, err;
215
216 for (i=0; i<3; i++)
217 sg.urb[i] = NULL;
218
219 err = -ENOMEM;
220 for (i=0; i<3; i++) {
221 sg.urb[i] = usb_alloc_urb(0, GFP_NOIO);
222 if (!sg.urb[i])
223 goto out;
224 }
225 init_completion(&sg.comp);
226 usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9,
227 alauda_complete, NULL);
228 usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, buf, mtd->writesize,
229 alauda_complete, NULL);
230 usb_fill_bulk_urb(sg.urb[2], al->dev, al->bulk_in, oob, 16,
231 alauda_complete, &sg.comp);
232
233 mutex_lock(&al->card_mutex);
234 for (i=0; i<3; i++) {
235 err = usb_submit_urb(sg.urb[i], GFP_NOIO);
236 if (err)
237 goto cancel;
238 }
239 if (!wait_for_completion_timeout(&sg.comp, TIMEOUT)) {
240 err = -ETIMEDOUT;
241cancel:
242 for (i=0; i<3; i++) {
243 usb_kill_urb(sg.urb[i]);
244 }
245 }
246 mutex_unlock(&al->card_mutex);
247
248out:
249 usb_free_urb(sg.urb[0]);
250 usb_free_urb(sg.urb[1]);
251 usb_free_urb(sg.urb[2]);
252 return err;
253}
254
255static int alauda_read_page(struct mtd_info *mtd, loff_t from,
256 void *buf, u8 *oob, int *corrected, int *uncorrected)
257{
258 int err;
259
260 err = __alauda_read_page(mtd, from, buf, oob);
261 if (err)
262 return err;
263 correct_data(buf, oob+13, corrected, uncorrected);
264 correct_data(buf+256, oob+8, corrected, uncorrected);
265 return 0;
266}
267
268static int alauda_write_page(struct mtd_info *mtd, loff_t to, void *buf,
269 void *oob)
270{
271 struct alauda_sg_request sg;
272 struct alauda *al = mtd->priv;
273 u32 pba = to >> al->card->blockshift;
274 u32 page = (to >> al->card->pageshift) & al->pagemask;
275 u8 command[] = {
276 ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_PAGE, PBA_HI(pba),
277 PBA_ZONE(pba), 0, PBA_LO(pba) + page, 32, 0, al->port
278 };
279 int i, err;
280
281 for (i=0; i<3; i++)
282 sg.urb[i] = NULL;
283
284 err = -ENOMEM;
285 for (i=0; i<3; i++) {
286 sg.urb[i] = usb_alloc_urb(0, GFP_NOIO);
287 if (!sg.urb[i])
288 goto out;
289 }
290 init_completion(&sg.comp);
291 usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9,
292 alauda_complete, NULL);
293 usb_fill_bulk_urb(sg.urb[1], al->dev, al->write_out, buf,mtd->writesize,
294 alauda_complete, NULL);
295 usb_fill_bulk_urb(sg.urb[2], al->dev, al->write_out, oob, 16,
296 alauda_complete, &sg.comp);
297
298 mutex_lock(&al->card_mutex);
299 for (i=0; i<3; i++) {
300 err = usb_submit_urb(sg.urb[i], GFP_NOIO);
301 if (err)
302 goto cancel;
303 }
304 if (!wait_for_completion_timeout(&sg.comp, TIMEOUT)) {
305 err = -ETIMEDOUT;
306cancel:
307 for (i=0; i<3; i++) {
308 usb_kill_urb(sg.urb[i]);
309 }
310 }
311 mutex_unlock(&al->card_mutex);
312
313out:
314 usb_free_urb(sg.urb[0]);
315 usb_free_urb(sg.urb[1]);
316 usb_free_urb(sg.urb[2]);
317 return err;
318}
319
320static int alauda_erase_block(struct mtd_info *mtd, loff_t ofs)
321{
322 struct alauda_sg_request sg;
323 struct alauda *al = mtd->priv;
324 u32 pba = ofs >> al->card->blockshift;
325 u8 command[] = {
326 ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba),
327 PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, al->port
328 };
329 u8 buf[2];
330 int i, err;
331
332 for (i=0; i<2; i++)
333 sg.urb[i] = NULL;
334
335 err = -ENOMEM;
336 for (i=0; i<2; i++) {
337 sg.urb[i] = usb_alloc_urb(0, GFP_NOIO);
338 if (!sg.urb[i])
339 goto out;
340 }
341 init_completion(&sg.comp);
342 usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9,
343 alauda_complete, NULL);
344 usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, buf, 2,
345 alauda_complete, &sg.comp);
346
347 mutex_lock(&al->card_mutex);
348 for (i=0; i<2; i++) {
349 err = usb_submit_urb(sg.urb[i], GFP_NOIO);
350 if (err)
351 goto cancel;
352 }
353 if (!wait_for_completion_timeout(&sg.comp, TIMEOUT)) {
354 err = -ETIMEDOUT;
355cancel:
356 for (i=0; i<2; i++) {
357 usb_kill_urb(sg.urb[i]);
358 }
359 }
360 mutex_unlock(&al->card_mutex);
361
362out:
363 usb_free_urb(sg.urb[0]);
364 usb_free_urb(sg.urb[1]);
365 return err;
366}
367
368static int alauda_read_oob(struct mtd_info *mtd, loff_t from, void *oob)
369{
370 static u8 ignore_buf[512]; /* write only */
371
372 return __alauda_read_page(mtd, from, ignore_buf, oob);
373}
374
375static int popcount8(u8 c)
376{
377 int ret = 0;
378
379 for ( ; c; c>>=1)
380 ret += c & 1;
381 return ret;
382}
383
384static int alauda_isbad(struct mtd_info *mtd, loff_t ofs)
385{
386 u8 oob[16];
387 int err;
388
389 err = alauda_read_oob(mtd, ofs, oob);
390 if (err)
391 return err;
392
393 /* A block is marked bad if two or more bits are zero */
394 return popcount8(oob[5]) >= 7 ? 0 : 1;
395}
396
397static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len,
398 size_t *retlen, u_char *buf)
399{
400 struct alauda *al = mtd->priv;
401 void *bounce_buf;
402 int err, corrected=0, uncorrected=0;
403
404 bounce_buf = kmalloc(mtd->writesize, GFP_KERNEL);
405 if (!bounce_buf)
406 return -ENOMEM;
407
408 *retlen = len;
409 while (len) {
410 u8 oob[16];
411 u32 byte = from & al->bytemask;
412 size_t cplen = min(len, mtd->writesize - byte);
413
414 err = alauda_read_page(mtd, from, bounce_buf, oob,
415 &corrected, &uncorrected);
416 if (err)
417 goto out;
418
419 memcpy(buf, bounce_buf + byte, cplen);
420 buf += cplen;
421 from += cplen;
422 len -= cplen;
423 }
424 err = 0;
425 if (corrected)
426 err = -EUCLEAN;
427 if (uncorrected)
428 err = -EBADMSG;
429out:
430 kfree(bounce_buf);
431 return err;
432}
433
434static int alauda_read(struct mtd_info *mtd, loff_t from, size_t len,
435 size_t *retlen, u_char *buf)
436{
437 struct alauda *al = mtd->priv;
438 int err, corrected=0, uncorrected=0;
439
440 if ((from & al->bytemask) || (len & al->bytemask))
441 return alauda_bounce_read(mtd, from, len, retlen, buf);
442
443 *retlen = len;
444 while (len) {
445 u8 oob[16];
446
447 err = alauda_read_page(mtd, from, buf, oob,
448 &corrected, &uncorrected);
449 if (err)
450 return err;
451
452 buf += mtd->writesize;
453 from += mtd->writesize;
454 len -= mtd->writesize;
455 }
456 err = 0;
457 if (corrected)
458 err = -EUCLEAN;
459 if (uncorrected)
460 err = -EBADMSG;
461 return err;
462}
463
464static int alauda_write(struct mtd_info *mtd, loff_t to, size_t len,
465 size_t *retlen, const u_char *buf)
466{
467 struct alauda *al = mtd->priv;
468 int err;
469
470 if ((to & al->bytemask) || (len & al->bytemask))
471 return -EINVAL;
472
473 *retlen = len;
474 while (len) {
475 u32 page = (to >> al->card->pageshift) & al->pagemask;
476 u8 oob[16] = { 'h', 'e', 'l', 'l', 'o', 0xff, 0xff, 0xff,
477 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
478
479 /* don't write to bad blocks */
480 if (page == 0) {
481 err = alauda_isbad(mtd, to);
482 if (err) {
483 return -EIO;
484 }
485 }
486 nand_calculate_ecc(mtd, buf, &oob[13]);
487 nand_calculate_ecc(mtd, buf+256, &oob[8]);
488
489 err = alauda_write_page(mtd, to, (void*)buf, oob);
490 if (err)
491 return err;
492
493 buf += mtd->writesize;
494 to += mtd->writesize;
495 len -= mtd->writesize;
496 }
497 return 0;
498}
499
500static int __alauda_erase(struct mtd_info *mtd, struct erase_info *instr)
501{
502 struct alauda *al = mtd->priv;
503 u32 ofs = instr->addr;
504 u32 len = instr->len;
505 int err;
506
507 if ((ofs & al->blockmask) || (len & al->blockmask))
508 return -EINVAL;
509
510 while (len) {
511 /* don't erase bad blocks */
512 err = alauda_isbad(mtd, ofs);
513 if (err > 0)
514 err = -EIO;
515 if (err < 0)
516 return err;
517
518 err = alauda_erase_block(mtd, ofs);
519 if (err < 0)
520 return err;
521
522 ofs += mtd->erasesize;
523 len -= mtd->erasesize;
524 }
525 return 0;
526}
527
528static int alauda_erase(struct mtd_info *mtd, struct erase_info *instr)
529{
530 int err;
531
532 err = __alauda_erase(mtd, instr);
533 instr->state = err ? MTD_ERASE_FAILED : MTD_ERASE_DONE;
534 mtd_erase_callback(instr);
535 return err;
536}
537
538static int alauda_init_media(struct alauda *al)
539{
540 u8 buf[4], *b0=buf, *b1=buf+1;
541 struct alauda_card *card;
542 struct mtd_info *mtd;
543 int err;
544
545 mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
546 if (!mtd)
547 return -ENOMEM;
548
549 for (;;) {
550 err = alauda_get_media_status(al, buf);
551 if (err < 0)
552 goto error;
553 if (*b0 & 0x10)
554 break;
555 msleep(20);
556 }
557
558 err = alauda_ack_media(al);
559 if (err)
560 goto error;
561
562 msleep(10);
563
564 err = alauda_get_media_status(al, buf);
565 if (err < 0)
566 goto error;
567
568 if (*b0 != 0x14) {
569 /* media not ready */
570 err = -EIO;
571 goto error;
572 }
573 err = alauda_get_media_signatures(al, buf);
574 if (err < 0)
575 goto error;
576
577 card = get_card(*b1);
578 if (!card) {
579 printk(KERN_ERR"Alauda: unknown card id %02x\n", *b1);
580 err = -EIO;
581 goto error;
582 }
583 printk(KERN_INFO"pagesize=%x\nerasesize=%x\nsize=%xMiB\n",
584 1<<card->pageshift, 1<<card->blockshift,
585 1<<(card->chipshift-20));
586 al->card = card;
587 al->pagemask = (1 << (card->blockshift - card->pageshift)) - 1;
588 al->bytemask = (1 << card->pageshift) - 1;
589 al->blockmask = (1 << card->blockshift) - 1;
590
591 mtd->name = "alauda";
592 mtd->size = 1<<card->chipshift;
593 mtd->erasesize = 1<<card->blockshift;
594 mtd->writesize = 1<<card->pageshift;
595 mtd->type = MTD_NANDFLASH;
596 mtd->flags = MTD_CAP_NANDFLASH;
597 mtd->read = alauda_read;
598 mtd->write = alauda_write;
599 mtd->erase = alauda_erase;
600 mtd->block_isbad = alauda_isbad;
601 mtd->priv = al;
602 mtd->owner = THIS_MODULE;
603
604 err = add_mtd_device(mtd);
605 if (err) {
606 err = -ENFILE;
607 goto error;
608 }
609
610 al->mtd = mtd;
611 alauda_reset(al); /* no clue whether this is necessary */
612 return 0;
613error:
614 kfree(mtd);
615 return err;
616}
617
618static int alauda_check_media(struct alauda *al)
619{
620 u8 buf[2], *b0 = buf, *b1 = buf+1;
621 int err;
622
623 err = alauda_get_media_status(al, buf);
624 if (err < 0)
625 return err;
626
627 if ((*b1 & 0x01) == 0) {
628 /* door open */
629 return -EIO;
630 }
631 if ((*b0 & 0x80) || ((*b0 & 0x1F) == 0x10)) {
632 /* no media ? */
633 return -EIO;
634 }
635 if (*b0 & 0x08) {
636 /* media change ? */
637 return alauda_init_media(al);
638 }
639 return 0;
640}
641
642static int alauda_probe(struct usb_interface *interface,
643 const struct usb_device_id *id)
644{
645 struct alauda *al;
646 struct usb_host_interface *iface;
647 struct usb_endpoint_descriptor *ep,
648 *ep_in=NULL, *ep_out=NULL, *ep_wr=NULL;
649 int i, err = -ENOMEM;
650
651 al = kzalloc(2*sizeof(*al), GFP_KERNEL);
652 if (!al)
653 goto error;
654
655 kref_init(&al->kref);
656 usb_set_intfdata(interface, al);
657
658 al->dev = usb_get_dev(interface_to_usbdev(interface));
659 al->interface = interface;
660
661 iface = interface->cur_altsetting;
662 for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
663 ep = &iface->endpoint[i].desc;
664
665 if (usb_endpoint_is_bulk_in(ep)) {
666 ep_in = ep;
667 } else if (usb_endpoint_is_bulk_out(ep)) {
668 if (i==0)
669 ep_wr = ep;
670 else
671 ep_out = ep;
672 }
673 }
674 err = -EIO;
675 if (!ep_wr || !ep_in || !ep_out)
676 goto error;
677
678 al->write_out = usb_sndbulkpipe(al->dev,
679 ep_wr->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
680 al->bulk_in = usb_rcvbulkpipe(al->dev,
681 ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
682 al->bulk_out = usb_sndbulkpipe(al->dev,
683 ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
684
685 /* second device is identical up to now */
686 memcpy(al+1, al, sizeof(*al));
687
688 mutex_init(&al[0].card_mutex);
689 mutex_init(&al[1].card_mutex);
690
691 al[0].port = ALAUDA_PORT_XD;
692 al[1].port = ALAUDA_PORT_SM;
693
694 info("alauda probed");
695 alauda_check_media(al);
696 alauda_check_media(al+1);
697
698 return 0;
699
700error:
701 if (al)
702 kref_put(&al->kref, alauda_delete);
703 return err;
704}
705
706static void alauda_disconnect(struct usb_interface *interface)
707{
708 struct alauda *al;
709
710 al = usb_get_intfdata(interface);
711 usb_set_intfdata(interface, NULL);
712
713 /* FIXME: prevent more I/O from starting */
714
715 /* decrement our usage count */
716 if (al)
717 kref_put(&al->kref, alauda_delete);
718
719 info("alauda gone");
720}
721
722static struct usb_driver alauda_driver = {
723 .name = "alauda",
724 .probe = alauda_probe,
725 .disconnect = alauda_disconnect,
726 .id_table = alauda_table,
727};
728
729static int __init alauda_init(void)
730{
731 return usb_register(&alauda_driver);
732}
733
734static void __exit alauda_exit(void)
735{
736 usb_deregister(&alauda_driver);
737}
738
739module_init(alauda_init);
740module_exit(alauda_exit);
741
742MODULE_LICENSE("GPL");