1 diff -urN linux.old/drivers/block/Kconfig linux.dev/drivers/block/Kconfig
2 --- linux.old/drivers/block/Kconfig 2006-06-08 20:20:52.000000000 +0200
3 +++ linux.dev/drivers/block/Kconfig 2006-06-08 22:14:58.000000000 +0200
5 This driver provides Support for ATA over Ethernet block
6 devices like the Coraid EtherDrive (R) Storage Blade.
8 +config BLK_DEV_CF_MIPS
9 + bool "CF slot of RB532 board"
10 + depends on MIKROTIK_RB500
13 + The Routerboard 532 has a CF slot on it. Enable the special block
14 + device driver for it.
17 diff -urN linux.old/drivers/block/rb500/ata.c linux.dev/drivers/block/rb500/ata.c
18 --- linux.old/drivers/block/rb500/ata.c 1970-01-01 01:00:00.000000000 +0100
19 +++ linux.dev/drivers/block/rb500/ata.c 2006-06-09 01:58:40.000000000 +0200
21 +#include <linux/kernel.h> /* printk() */
22 +#include <linux/module.h> /* module to be loadable */
23 +#include <linux/delay.h>
24 +#include <linux/sched.h>
25 +#include <linux/pci.h>
26 +#include <linux/ioport.h> /* request_mem_region() */
27 +#include <asm/unaligned.h> /* ioremap() */
28 +#include <asm/io.h> /* ioremap() */
29 +#include <asm/rc32434/rb.h>
33 +#define REQUEST_MEM_REGION 0
37 +#define DEBUGP printk
39 +#define DEBUGP(format, args...)
42 +#define SECS 1000000 /* unit for wait_not_busy() is 1us */
44 +unsigned cf_head = 0;
47 +unsigned cf_sectors = 0;
48 +static unsigned cf_block_size = 1;
49 +static void *baddr = 0;
51 +#define DBUF32 ((volatile u32 *)((unsigned long)dev->baddr | ATA_DBUF_OFFSET))
54 +static void cf_do_tasklet(unsigned long dev_l);
57 +static inline void wareg(u8 val, unsigned reg, struct cf_mips_dev* dev)
59 + writeb(val, dev->baddr + ATA_REG_OFFSET + reg);
62 +static inline u8 rareg(unsigned reg, struct cf_mips_dev* dev)
64 + return readb(dev->baddr + ATA_REG_OFFSET + reg);
67 +static inline int get_gpio_bit(gpio_func ofs, struct cf_mips_dev *dev)
69 + return (gpio_get(ofs) >> dev->pin) & 1;
72 +static inline void set_gpio_bit(int bit, gpio_func ofs, struct cf_mips_dev *dev)
74 + gpio_set(ofs, (1 << dev->pin), ((bit & 1) << dev->pin));
77 +static inline int cfrdy(struct cf_mips_dev *dev)
79 + return get_gpio_bit(DATA, dev);
82 +static inline void prepare_cf_irq(struct cf_mips_dev *dev)
84 + set_gpio_bit(1, ILEVEL, dev); /* interrupt on cf ready (not busy) */
85 + set_gpio_bit(0, ISTAT, dev); /* clear interrupt status */
88 +static inline int cf_present(struct cf_mips_dev* dev)
90 + /* TODO: read and configure CIS into memory mapped mode
91 + * TODO: parse CISTPL_CONFIG on CF+ cards to get base address (0x200)
92 + * TODO: maybe adjust power saving setting for Hitachi Microdrive
96 + /* setup CFRDY GPIO as input */
97 + set_gpio_bit(0, FUNC, dev);
98 + set_gpio_bit(0, CFG, dev);
100 + for (i = 0; i < 0x10; ++i) {
101 + if (rareg(i,dev) != 0xff)
107 +static inline int is_busy(struct cf_mips_dev *dev)
109 + return !cfrdy(dev);
112 +static int wait_not_busy(int to_us, int wait_for_busy,struct cf_mips_dev *dev)
115 + if (wait_for_busy && !is_busy(dev)) {
116 + /* busy must appear within 400ns,
117 + * but it may dissapear before we see it
118 + * => must not wait for busy in a loop
125 + udelay(1); /* never reached in async mode */
126 + if (!is_busy(dev)) {
127 + if (us_passed > 1 * SECS) {
128 + printk(KERN_WARNING "cf-mips: not busy ok (after %dus)"
129 + ", status 0x%02x\n", us_passed, (unsigned) rareg(ATA_REG_ST,dev));
131 + return CF_TRANS_OK;
133 + if (us_passed == 1 * SECS) {
134 + printk(KERN_WARNING "cf-mips: wait not busy %dus..\n", to_us);
136 + if (dev->async_mode) {
137 + dev->to_timer.expires = jiffies + (to_us * HZ / SECS);
138 + dev->irq_enable_time = jiffies;
139 + prepare_cf_irq(dev);
140 + if (is_busy(dev)) {
141 + add_timer(&dev->to_timer);
142 + enable_irq(dev->irq);
143 + return CF_TRANS_IN_PROGRESS;
148 + } while (us_passed < to_us);
150 + printk(KERN_ERR "cf-mips: wait not busy timeout (%dus)"
151 + ", status 0x%02x, state %d\n",
152 + to_us, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
153 + return CF_TRANS_FAILED;
156 +static irqreturn_t cf_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
158 + /* While tasklet has not disabled irq, irq will be retried all the time
159 + * because of ILEVEL matching GPIO pin status => deadlock.
160 + * To avoid this, we change ILEVEL to 0.
162 + struct cf_mips_dev *dev=dev_id;
164 + set_gpio_bit(0, ILEVEL, dev);
165 + set_gpio_bit(0, ISTAT, dev);
167 + del_timer(&dev->to_timer);
168 + tasklet_schedule(&dev->tasklet);
169 + return IRQ_HANDLED;
172 +static int do_reset(struct cf_mips_dev *dev)
174 + printk(KERN_INFO "cf-mips: resetting..\n");
176 + wareg(ATA_REG_DC_SRST, ATA_REG_DC,dev);
177 + udelay(1); /* FIXME: how long should we wait here? */
178 + wareg(0, ATA_REG_DC,dev);
180 + return wait_not_busy(30 * SECS, 1,dev);
183 +static int set_multiple(struct cf_mips_dev *dev)
185 + if (dev->block_size <= 1)
186 + return CF_TRANS_OK;
188 + wareg(dev->block_size, ATA_REG_SC,dev);
189 + wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
190 + wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
192 + return wait_not_busy(10 * SECS, 1,dev);
195 +static int set_cmd(struct cf_mips_dev *dev)
197 + //DEBUGP(KERN_INFO "cf-mips: ata cmd 0x%02x\n", dev->tcmd);
198 + // sector_count should be <=24 bits..
199 + BUG_ON(dev->tsect_start>=0x10000000);
200 + // This way, it addresses 2^24 * 512 = 128G
202 + if (dev->tsector_count) {
203 + wareg(dev->tsector_count & 0xff, ATA_REG_SC,dev);
204 + wareg(dev->tsect_start & 0xff, ATA_REG_SN,dev);
205 + wareg((dev->tsect_start >> 8) & 0xff, ATA_REG_CL,dev);
206 + wareg((dev->tsect_start >> 16) & 0xff, ATA_REG_CH,dev);
208 + wareg(((dev->tsect_start >> 24) & 0x0f) | ATA_REG_DH_BASE | ATA_REG_DH_LBA,
209 + ATA_REG_DH,dev); /* select drive on all commands */
210 + wareg(dev->tcmd, ATA_REG_CMD,dev);
211 + return wait_not_busy(10 * SECS, 1,dev);
214 +static int do_trans(struct cf_mips_dev *dev)
220 + //printk("do_trans: %d sectors left\n",dev->tsectors_left);
221 + while (dev->tsectors_left) {
224 + st = rareg(ATA_REG_ST,dev);
225 + if (!(st & ATA_REG_ST_DRQ)) {
226 + printk(KERN_ERR "cf-mips: do_trans without DRQ (status 0x%x)!\n", st);
227 + if (st & ATA_REG_ST_ERR) {
228 + int errId = rareg(ATA_REG_ERR,dev);
229 + printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
230 + (dev->tread ? "read" : "write"), st, errId);
232 + return CF_TRANS_FAILED;
234 + do { /* Fill/read the buffer one block */
236 + qbuf = (u32 *)dev->tbuf;
237 + qend = qbuf + CF_SECT_SIZE / sizeof(u32);
240 + put_unaligned(*DBUF32,qbuf++);
241 + //*(qbuf++) = *DBUF32;
245 + *DBUF32 = get_unaligned(qbuf++);
248 + dev->tsectors_left--;
249 + dev->tbuf += CF_SECT_SIZE;
250 + dev->tbuf_size -= CF_SECT_SIZE;
252 + } while (transfered != dev->block_size && dev->tsectors_left > 0);
254 + res = wait_not_busy(10 * SECS, 1,dev);
255 + if (res != CF_TRANS_OK)
259 + st = rareg(ATA_REG_ST,dev);
260 + if (st & (ATA_REG_ST_DRQ | ATA_REG_ST_DWF | ATA_REG_ST_ERR)) {
261 + if (st & ATA_REG_ST_DRQ) {
262 + printk(KERN_ERR "cf-mips: DRQ after all %d sectors are %s"
263 + ", status 0x%x\n", dev->tsector_count, (dev->tread ? "read" : "written"), st);
264 + } else if (st & ATA_REG_ST_DWF) {
265 + printk(KERN_ERR "cf-mips: write fault, status 0x%x\n", st);
267 + int errId = rareg(ATA_REG_ERR,dev);
268 + printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
269 + (dev->tread ? "read" : "write"), st, errId);
271 + return CF_TRANS_FAILED;
273 + return CF_TRANS_OK;
276 +static int cf_do_state(struct cf_mips_dev *dev)
279 + switch (dev->tstate) { /* fall through everywhere */
281 + dev->tstate = TS_READY;
282 + if (is_busy(dev)) {
283 + dev->tstate = TS_AFTER_RESET;
284 + res = do_reset(dev);
285 + if (res != CF_TRANS_OK)
288 + case TS_AFTER_RESET:
289 + if (dev->tstate == TS_AFTER_RESET) {
290 + dev->tstate = TS_READY;
291 + res = set_multiple(dev);
292 + if (res != CF_TRANS_OK)
296 + dev->tstate = TS_CMD;
297 + res = set_cmd(dev);
298 + if (res != CF_TRANS_OK)
301 + dev->tstate = TS_TRANS;
303 + res = do_trans(dev);
306 + printk(KERN_ERR "cf-mips: BUG: unknown tstate %d\n", dev->tstate);
307 + return CF_TRANS_FAILED;
309 + if (res != CF_TRANS_IN_PROGRESS)
310 + dev->tstate = TS_IDLE;
314 +static void cf_do_tasklet(unsigned long dev_l)
316 + struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
319 + disable_irq(dev->irq);
321 + if (dev->tstate == TS_IDLE)
322 + return; /* can happen when irq is first registered */
325 + DEBUGP(KERN_WARNING "cf-mips: not busy ok (tasklet) status 0x%02x\n",
326 + (unsigned) rareg(ATA_REG_ST,dev));
329 + res = cf_do_state(dev);
330 + if (res == CF_TRANS_IN_PROGRESS)
332 + cf_async_trans_done(dev,res);
335 +static void cf_async_timeout(unsigned long dev_l)
337 + struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
338 + disable_irq(dev->irq);
339 + /* Perhaps send abort to the device? */
340 + printk(KERN_ERR "cf-mips: wait not busy timeout (%lus)"
341 + ", status 0x%02x, state %d\n",
342 + jiffies - dev->irq_enable_time, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
343 + dev->tstate = TS_IDLE;
344 + cf_async_trans_done(dev,CF_TRANS_FAILED);
347 +int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
348 + char* buffer, int is_write)
350 + BUG_ON(dev->tstate!=TS_IDLE);
351 + if (nsect > ATA_MAX_SECT_PER_CMD) {
352 + printk(KERN_WARNING "cf-mips: sector count %lu out of range\n",nsect);
353 + return CF_TRANS_FAILED;
355 + if (sector + nsect > dev->sectors) {
356 + printk(KERN_WARNING "cf-mips: sector %lu out of range\n",sector);
357 + return CF_TRANS_FAILED;
359 + dev->tbuf = buffer;
360 + dev->tbuf_size = nsect*512;
361 + dev->tsect_start = sector;
362 + dev->tsector_count = nsect;
363 + dev->tsectors_left = dev->tsector_count;
364 + dev->tread = (is_write)?0:1;
366 + dev->tcmd = (dev->block_size == 1 ?
367 + (is_write ? ATA_CMD_WRITE_SECTORS : ATA_CMD_READ_SECTORS) :
368 + (is_write ? ATA_CMD_WRITE_MULTIPLE : ATA_CMD_READ_MULTIPLE));
370 + return cf_do_state(dev);
373 +static int do_identify(struct cf_mips_dev *dev)
375 + u16 sbuf[CF_SECT_SIZE >> 1];
377 + char tstr[17]; //serial
378 + BUG_ON(dev->tstate!=TS_IDLE);
379 + dev->tbuf = (char *) sbuf;
380 + dev->tbuf_size = CF_SECT_SIZE;
381 + dev->tsect_start = 0;
382 + dev->tsector_count = 0;
383 + dev->tsectors_left = 1;
385 + dev->tcmd = ATA_CMD_IDENTIFY_DRIVE;
387 + DEBUGP(KERN_INFO "cf-mips: identify drive..\n");
388 + res = cf_do_state(dev);
389 + if (res == CF_TRANS_IN_PROGRESS) {
390 + printk(KERN_ERR "cf-mips: BUG: async identify cmd\n");
391 + return CF_TRANS_FAILED;
393 + if (res != CF_TRANS_OK)
396 + dev->head = sbuf[3];
397 + dev->cyl = sbuf[1];
398 + dev->spt = sbuf[6];
399 + dev->sectors = ((unsigned long) sbuf[7] << 16) | sbuf[8];
400 + dev->dtype=sbuf[0];
401 + memcpy(tstr,&sbuf[12],16);
403 + printk(KERN_INFO "cf-mips: %s detected, C/H/S=%d/%d/%d sectors=%u (%uMB) Serial=%s\n",
404 + (sbuf[0] == 0x848A ? "CF card" : "ATA drive"), dev->cyl, dev->head,
405 + dev->spt, dev->sectors, dev->sectors >> 11,tstr);
409 +static void init_multiple(struct cf_mips_dev * dev)
412 + DEBUGP(KERN_INFO "cf-mips: detecting block size\n");
414 + dev->block_size = 128; /* max block size = 128 sectors (64KB) */
416 + wareg(dev->block_size, ATA_REG_SC,dev);
417 + wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
418 + wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
420 + res = wait_not_busy(10 * SECS, 1,dev);
421 + if (res != CF_TRANS_OK) {
422 + printk(KERN_ERR "cf-mips: failed to detect block size: busy!\n");
423 + dev->block_size = 1;
426 + if ((rareg(ATA_REG_ST,dev) & ATA_REG_ST_ERR) == 0)
428 + dev->block_size /= 2;
429 + } while (dev->block_size > 1);
431 + printk(KERN_INFO "cf-mips: multiple sectors = %d\n", dev->block_size);
434 +int cf_init(struct cf_mips_dev *dev)
436 + tasklet_init(&dev->tasklet,cf_do_tasklet,(unsigned long)dev);
437 + dev->baddr = ioremap_nocache((unsigned long)dev->base, CFDEV_BUF_SIZE);
439 + printk(KERN_ERR "cf-mips: cf_init: ioremap for (%lx,%x) failed\n",
440 + (unsigned long) dev->base, CFDEV_BUF_SIZE);
444 + if (!cf_present(dev)) {
445 + printk(KERN_WARNING "cf-mips: cf card not present\n");
446 + iounmap(dev->baddr);
450 + if (do_reset(dev) != CF_TRANS_OK) {
451 + printk(KERN_ERR "cf-mips: cf reset failed\n");
452 + iounmap(dev->baddr);
456 + if (!do_identify(dev)) {
457 + printk(KERN_ERR "cf-mips: cf identify failed\n");
458 + iounmap(dev->baddr);
462 +/* set_apm_level(ATA_APM_WITH_STANDBY); */
463 + init_multiple(dev);
465 + init_timer(&dev->to_timer);
466 + dev->to_timer.function = cf_async_timeout;
467 + dev->to_timer.data = (unsigned long)dev;
469 + prepare_cf_irq(dev);
470 + if (request_irq(dev->irq, cf_irq_handler, 0, "CF Mips", dev)) {
471 + printk(KERN_ERR "cf-mips: failed to get irq\n");
472 + iounmap(dev->baddr);
475 + /* Disable below would be odd, because request will enable, and the tasklet
476 + will disable it itself */
477 + //disable_irq(dev->irq);
479 + dev->async_mode = 1;
484 +void cf_cleanup(struct cf_mips_dev *dev)
486 + iounmap(dev->baddr);
487 + free_irq(dev->irq, NULL);
488 +#if REQUEST_MEM_REGION
489 + release_mem_region((unsigned long)dev->base, CFDEV_BUF_SIZE);
495 diff -urN linux.old/drivers/block/rb500/ata.h linux.dev/drivers/block/rb500/ata.h
496 --- linux.old/drivers/block/rb500/ata.h 1970-01-01 01:00:00.000000000 +0100
497 +++ linux.dev/drivers/block/rb500/ata.h 2006-06-09 00:15:23.000000000 +0200
499 +#ifndef __CFMIPS_ATA_H__
500 +#define __CFMIPS_ATA_H__
502 +#include <linux/interrupt.h>
504 +#define CFG_DC_DEV1 (void*)0xb8010010
505 +#define CFG_DC_DEVBASE 0x0
506 +#define CFG_DC_DEVMASK 0x4
507 +#define CFG_DC_DEVC 0x8
508 +#define CFG_DC_DEVTC 0xC
510 +#define CFDEV_BUF_SIZE 0x1000
511 +#define ATA_CIS_OFFSET 0x200
512 +#define ATA_REG_OFFSET 0x800
513 +#define ATA_DBUF_OFFSET 0xC00
515 +#define ATA_REG_FEAT 0x1
516 +#define ATA_REG_SC 0x2
517 +#define ATA_REG_SN 0x3
518 +#define ATA_REG_CL 0x4
519 +#define ATA_REG_CH 0x5
520 +#define ATA_REG_DH 0x6
521 +#define ATA_REG_DH_BASE 0xa0
522 +#define ATA_REG_DH_LBA 0x40
523 +#define ATA_REG_DH_DRV 0x10
524 +#define ATA_REG_CMD 0x7
525 +#define ATA_REG_ST 0x7
526 +#define ATA_REG_ST_BUSY 0x80
527 +#define ATA_REG_ST_RDY 0x40
528 +#define ATA_REG_ST_DWF 0x20
529 +#define ATA_REG_ST_DSC 0x10
530 +#define ATA_REG_ST_DRQ 0x08
531 +#define ATA_REG_ST_CORR 0x04
532 +#define ATA_REG_ST_ERR 0x01
533 +#define ATA_REG_ERR 0xd
534 +#define ATA_REG_DC 0xe
535 +#define ATA_REG_DC_IEN 0x02
536 +#define ATA_REG_DC_SRST 0x04
538 +#define ATA_CMD_READ_SECTORS 0x20
539 +#define ATA_CMD_WRITE_SECTORS 0x30
540 +#define ATA_CMD_EXEC_DRIVE_DIAG 0x90
541 +#define ATA_CMD_READ_MULTIPLE 0xC4
542 +#define ATA_CMD_WRITE_MULTIPLE 0xC5
543 +#define ATA_CMD_SET_MULTIPLE 0xC6
544 +#define ATA_CMD_IDENTIFY_DRIVE 0xEC
545 +#define ATA_CMD_SET_FEATURES 0xEF
547 +#define ATA_FEATURE_ENABLE_APM 0x05
548 +#define ATA_FEATURE_DISABLE_APM 0x85
549 +#define ATA_APM_DISABLED 0x00
550 +#define ATA_APM_MIN_POWER 0x01
551 +#define ATA_APM_WITH_STANDBY 0x7f
552 +#define ATA_APM_WITHOUT_STANDBY 0x80
553 +#define ATA_APM_MAX_PERFORMANCE 0xfe
555 +#define CF_SECT_SIZE 0x200
556 +/* That is the ratio CF_SECT_SIZE/512 (the kernel sector size) */
557 +#define CF_KERNEL_MUL 1
558 +#define ATA_MAX_SECT_PER_CMD 0x100
560 +#define CF_TRANS_FAILED 0
561 +#define CF_TRANS_OK 1
562 +#define CF_TRANS_IN_PROGRESS 2
575 +// static unsigned long busy_time;
578 +/** Struct to hold the cfdev
579 +Actually, all the data here only has one instance. However, for
580 +reasons of programming conformity, it is passed around as a pointer
582 +struct cf_mips_dev {
583 + void *base; /* base address for I/O */
584 + void *baddr; /* remapped address */
586 + int pin; /* gpio pin */
587 + int irq; /* gpio irq */
594 + unsigned short block_size;
595 + unsigned dtype ; // ATA or CF
596 + struct request_queue *queue;
597 + struct gendisk *gd;
599 + /* Transaction state */
600 + enum trans_state tstate;
602 + unsigned long tbuf_size;
603 + sector_t tsect_start;
604 + unsigned tsector_count;
605 + unsigned tsectors_left;
609 + unsigned long irq_enable_time;
611 + struct request *active_req; /* A request is being carried out. Is that different from tstate? */
613 + struct timer_list to_timer;
614 + struct tasklet_struct tasklet;
616 + /** This lock ensures that the requests to this device are all done
617 + atomically. Transfers can run in parallel, requests are all queued
622 +int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
623 + char* buffer, int is_write);
624 +int cf_init(struct cf_mips_dev* dev);
625 +void cf_cleanup(struct cf_mips_dev* dev);
627 +void cf_async_trans_done(struct cf_mips_dev* dev, int result);
628 +// void *cf_get_next_buf(unsigned long *buf_size);
631 diff -urN linux.old/drivers/block/rb500/bdev.c linux.dev/drivers/block/rb500/bdev.c
632 --- linux.old/drivers/block/rb500/bdev.c 1970-01-01 01:00:00.000000000 +0100
633 +++ linux.dev/drivers/block/rb500/bdev.c 2006-06-15 16:29:04.000000000 +0200
636 + This is a block driver for the direct (mmaped) interface to the CF-slot,
637 + found in Routerboard.com's RB532 board
638 + See SDK provided from routerboard.com.
640 + Module adapted By P.Christeas <p_christeas@yahoo.com>, 2005-6.
641 + Cleaned up and adapted to platform_device by Felix Fietkau <nbd@openwrt.org>
643 + This work is redistributed under the terms of the GNU General Public License.
646 +#include <linux/kernel.h>
647 +#include <linux/module.h>
648 +#include <linux/init.h>
649 +#include <linux/time.h>
650 +#include <linux/wait.h>
651 +#include <linux/fs.h>
652 +#include <linux/genhd.h>
653 +#include <linux/blkdev.h>
654 +#include <linux/blkpg.h>
655 +#include <linux/hdreg.h>
656 +#include <linux/platform_device.h>
658 +#include <asm/uaccess.h>
661 +#include <asm/rc32434/rb.h>
664 +#define DEBUGP printk
667 +#define DEBUGP(format, args...)
671 +#define CF_MIPS_MAJOR 13
672 +#define MAJOR_NR CF_MIPS_MAJOR
673 +#define CF_MAX_PART 16 /* max 15 partitions */
677 +//extern struct block_device_operations cf_bdops;
679 +// static struct hd_struct cf_parts[CF_MAX_PART];
680 +// static int cf_part_sizes[CF_MAX_PART];
681 +// static int cf_hsect_sizes[CF_MAX_PART];
682 +// static int cf_max_sectors[CF_MAX_PART];
683 +// static int cf_blksize_sizes[CF_MAX_PART];
685 +// static spinlock_t lock = SPIN_LOCK_UNLOCKED;
687 +// volatile int cf_busy = 0;
689 +static struct request *active_req = NULL;
691 +static int cf_open (struct inode *, struct file *);
692 +static int cf_release (struct inode *, struct file *);
693 +static int cf_ioctl (struct inode *, struct file *, unsigned, unsigned long);
695 +static void cf_request(request_queue_t * q);
696 +static int cf_transfer(const struct request *req);
698 +/*long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
699 +long (*compat_ioctl) (struct file *, unsigned, unsigned long);*/
700 +// int (*direct_access) (struct block_device *, sector_t, unsigned long *);
701 +// int (*media_changed) (struct gendisk *);
702 +// int (*revalidate_disk) (struct gendisk *);
704 +static struct block_device_operations cf_bdops = {
705 + .owner = THIS_MODULE,
707 + .release = cf_release,
709 + .media_changed = NULL,
710 + .unlocked_ioctl = NULL,
711 + .revalidate_disk = NULL,
712 + .compat_ioctl = NULL,
713 + .direct_access = NULL
717 +int cf_mips_probe(struct platform_device *pdev)
719 + struct gendisk* cf_gendisk=NULL;
720 + struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
721 + struct cf_mips_dev *dev;
722 + struct resource *r;
725 + reg_result = register_blkdev(MAJOR_NR, "cf-mips");
726 + if (reg_result < 0) {
727 + printk(KERN_WARNING "cf-mips: can't get major %d\n", MAJOR_NR);
731 + dev = (struct cf_mips_dev *)kmalloc(sizeof(struct cf_mips_dev),GFP_KERNEL);
734 + memset(dev, 0, sizeof(struct cf_mips_dev));
737 + dev->pin = cdev->gpio_pin;
738 + dev->irq = platform_get_irq_byname(pdev, "cf_irq");
739 + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cf_membase");
740 + dev->base = (void *) r->start;
742 + if (cf_init(dev)) goto out_err;
743 + printk("init done");
745 + spin_lock_init(&dev->lock);
746 + dev->queue = blk_init_queue(cf_request,&dev->lock);
748 + printk(KERN_ERR "cf-mips: no mem for queue\n");
751 + blk_queue_max_sectors(dev->queue,ATA_MAX_SECT_PER_CMD);
753 + /* For memory devices, it is always better to avoid crossing segments
754 + inside the same request. */
755 +/* if (dev->dtype==0x848A){
756 + printk(KERN_INFO "Setting boundary for cf to 0x%x",(dev->block_size*512)-1);
757 + blk_queue_segment_boundary(dev->queue, (dev->block_size*512)-1);
760 + dev->gd = alloc_disk(CF_MAX_PART);
761 + cf_gendisk = dev->gd;
762 + cdev->gd = dev->gd;
763 + if (!cf_gendisk) goto out_err; /* Last of these goto's */
765 + cf_gendisk->major = MAJOR_NR;
766 + cf_gendisk->first_minor = 0;
767 + cf_gendisk->queue=dev->queue;
768 + BUG_ON(cf_gendisk->minors != CF_MAX_PART);
769 + strcpy(cf_gendisk->disk_name,"cfa");
770 + strcpy(cf_gendisk->devfs_name,"cf/card0");
771 + cf_gendisk->fops = &cf_bdops;
772 + cf_gendisk->flags = 0 ; /* is not yet GENHD_FL_REMOVABLE */
773 + cf_gendisk->private_data=dev;
775 + set_capacity(cf_gendisk,dev->sectors * CF_KERNEL_MUL);
777 + /* Let the disk go live */
778 + add_disk(cf_gendisk);
780 + result = cf_init();
782 + /* default cfg for all partitions */
783 + memset(cf_parts, 0, sizeof (cf_parts[0]) * CF_MAX_PART);
784 + memset(cf_part_sizes, 0, sizeof (cf_part_sizes[0]) * CF_MAX_PART);
785 + for (i = 0; i < CF_MAX_PART; ++i) {
786 + cf_hsect_sizes[i] = CF_SECT_SIZE;
787 + cf_max_sectors[i] = ATA_MAX_SECT_PER_CMD;
788 + cf_blksize_sizes[i] = BLOCK_SIZE;
791 + /* setup info for whole disk (partition 0) */
792 + cf_part_sizes[0] = cf_sectors / 2;
793 + cf_parts[0].nr_sects = cf_sectors;
795 + blk_size[MAJOR_NR] = cf_part_sizes;
796 + blksize_size[MAJOR_NR] = cf_blksize_sizes;
797 + max_sectors[MAJOR_NR] = cf_max_sectors;
798 + hardsect_size[MAJOR_NR] = cf_hsect_sizes;
799 + read_ahead[MAJOR_NR] = 8; /* (4kB) */
801 + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
803 + add_gendisk(&cf_gendisk);
805 +// printk(KERN_INFO "cf-mips partition check: \n");
806 +// register_disk(cf_gendisk, MKDEV(MAJOR_NR, 0), CF_MAX_PART,
807 +// &cf_bdops, dev->sectors);
812 + blk_cleanup_queue(dev->queue);
815 + unregister_blkdev(MAJOR_NR, "cf-mips");
826 +cf_mips_remove(struct platform_device *pdev)
828 + struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
829 + struct cf_mips_dev *dev = (struct cf_mips_dev *) cdev->dev;
831 + unregister_blkdev(MAJOR_NR, "cf-mips");
832 + blk_cleanup_queue(dev->queue);
834 + del_gendisk(dev->gd);
840 +static struct platform_driver cf_driver = {
841 + .driver.name = "rb500-cf",
842 + .probe = cf_mips_probe,
843 + .remove = cf_mips_remove,
846 +static int __init cf_mips_init(void)
848 + printk(KERN_INFO "cf-mips module loaded\n");
849 + return platform_driver_register(&cf_driver);
852 +static void cf_mips_cleanup(void)
854 + platform_driver_unregister(&cf_driver);
855 + printk(KERN_INFO "cf-mips module removed\n");
858 +module_init(cf_mips_init);
859 +module_exit(cf_mips_cleanup);
861 +MODULE_LICENSE("GPL");
862 +MODULE_ALIAS_BLOCKDEV_MAJOR(CF_MIPS_MAJOR);
865 +static int cf_open(struct inode *inode, struct file *filp)
867 + struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
868 + int minor = MINOR(inode->i_rdev);
870 + if (minor >= CF_MAX_PART)
872 + //DEBUGP(KERN_INFO "cf-mips module opened, minor %d\n", minor);
873 + spin_lock(&dev->lock);
875 + spin_unlock(&dev->lock);
876 + filp->private_data=dev;
878 + /* dirty workaround to set CFRDY GPIO as an input when some other
879 + program sets it as an output */
880 + gpio_set(CFG, (1 << dev->pin), 0);
881 + return 0; /* success */
884 +static int cf_release(struct inode *inode, struct file *filp)
886 + int minor = MINOR(inode->i_rdev);
887 + struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
888 + spin_lock(&dev->lock);
890 + spin_unlock(&dev->lock);
894 +static int cf_ioctl(struct inode *inode, struct file *filp,
895 + unsigned int cmd, unsigned long arg)
897 + unsigned minor = MINOR(inode->i_rdev);
898 + struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
900 + DEBUGP(KERN_INFO "cf_ioctl cmd %u\n", cmd);
902 + case BLKRRPART: /* re-read partition table */
903 + if (!capable(CAP_SYS_ADMIN))
905 + printk(KERN_INFO "cf-mips partition check: \n");
906 + register_disk(dev->gd);
911 + struct hd_geometry geo;
912 + geo.cylinders = dev->cyl;
913 + geo.heads = dev->head;
914 + geo.sectors = dev->spt;
915 + geo.start = (*dev->gd->part)[minor].start_sect;
916 + if (copy_to_user((void *) arg, &geo, sizeof (geo)))
922 + return -EINVAL; /* unknown command */
925 +static void cf_request(request_queue_t * q)
927 + struct cf_mips_dev* dev;
929 + struct request * req;
932 + /* We could have q->queuedata = dev , but haven't yet. */
936 + while ((req=elv_next_request(q))!=NULL){
937 + dev=req->rq_disk->private_data;
938 + status=cf_transfer(req);
939 + if (status==CF_TRANS_IN_PROGRESS){
943 + end_request(req,status);
947 +static int cf_transfer(const struct request *req)
949 + struct cf_mips_dev* dev=req->rq_disk->private_data;
951 + if (!blk_fs_request(req)){
952 + if (printk_ratelimit())
953 + printk(KERN_WARNING "cf-mips: skipping non-fs request 0x%x\n",req->cmd[0]);
954 + return CF_TRANS_FAILED;
957 + return cf_do_transfer(dev,req->sector,req->current_nr_sectors,req->buffer,rq_data_dir(req));
960 +void cf_async_trans_done(struct cf_mips_dev * dev,int result)
962 + struct request *req;
964 + spin_lock(&dev->lock);
967 + end_request(req,result);
968 + spin_unlock(&dev->lock);
970 + spin_lock(&dev->lock);
971 + cf_request(dev->queue);
972 + spin_unlock(&dev->lock);
975 diff -urN linux.old/drivers/block/rb500/Makefile linux.dev/drivers/block/rb500/Makefile
976 --- linux.old/drivers/block/rb500/Makefile 1970-01-01 01:00:00.000000000 +0100
977 +++ linux.dev/drivers/block/rb500/Makefile 2006-06-08 22:14:58.000000000 +0200
979 +## Makefile for the RB532 CF port
981 +obj-y += bdev.o ata.o
982 diff -urN linux.old/drivers/Makefile linux.dev/drivers/Makefile
983 --- linux.old/drivers/Makefile 2006-06-08 20:20:52.000000000 +0200
984 +++ linux.dev/drivers/Makefile 2006-06-08 22:14:58.000000000 +0200
987 obj-$(CONFIG_CRYPTO) += crypto/
988 obj-$(CONFIG_SUPERH) += sh/
989 +obj-$(CONFIG_BLK_DEV_CF_MIPS) += block/rb500/
990 \ No newline at end of file