1 diff -urN linux.old/drivers/block/Kconfig linux.dev/drivers/block/Kconfig
2 --- linux.old/drivers/block/Kconfig 2006-10-26 02:43:39.000000000 +0200
3 +++ linux.dev/drivers/block/Kconfig 2006-10-26 00:11:14.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/Makefile linux.dev/drivers/block/Makefile
18 --- linux.old/drivers/block/Makefile 2006-06-18 03:49:35.000000000 +0200
19 +++ linux.dev/drivers/block/Makefile 2006-10-26 02:44:10.000000000 +0200
21 obj-$(CONFIG_VIODASD) += viodasd.o
22 obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
23 obj-$(CONFIG_BLK_DEV_UB) += ub.o
24 +obj-$(CONFIG_BLK_DEV_CF_MIPS) += rb500/
26 diff -urN linux.old/drivers/block/rb500/ata.c linux.dev/drivers/block/rb500/ata.c
27 --- linux.old/drivers/block/rb500/ata.c 1970-01-01 01:00:00.000000000 +0100
28 +++ linux.dev/drivers/block/rb500/ata.c 2006-10-26 00:11:14.000000000 +0200
30 +#include <linux/kernel.h> /* printk() */
31 +#include <linux/module.h> /* module to be loadable */
32 +#include <linux/delay.h>
33 +#include <linux/sched.h>
34 +#include <linux/pci.h>
35 +#include <linux/ioport.h> /* request_mem_region() */
36 +#include <asm/unaligned.h> /* ioremap() */
37 +#include <asm/io.h> /* ioremap() */
38 +#include <asm/rc32434/rb.h>
42 +#define REQUEST_MEM_REGION 0
46 +#define DEBUGP printk
48 +#define DEBUGP(format, args...)
51 +#define SECS 1000000 /* unit for wait_not_busy() is 1us */
53 +unsigned cf_head = 0;
56 +unsigned cf_sectors = 0;
57 +static unsigned cf_block_size = 1;
58 +static void *baddr = 0;
60 +#define DBUF32 ((volatile u32 *)((unsigned long)dev->baddr | ATA_DBUF_OFFSET))
63 +static void cf_do_tasklet(unsigned long dev_l);
66 +static inline void wareg(u8 val, unsigned reg, struct cf_mips_dev* dev)
68 + writeb(val, dev->baddr + ATA_REG_OFFSET + reg);
71 +static inline u8 rareg(unsigned reg, struct cf_mips_dev* dev)
73 + return readb(dev->baddr + ATA_REG_OFFSET + reg);
76 +static inline int get_gpio_bit(gpio_func ofs, struct cf_mips_dev *dev)
78 + return (gpio_get(ofs) >> dev->pin) & 1;
81 +static inline void set_gpio_bit(int bit, gpio_func ofs, struct cf_mips_dev *dev)
83 + gpio_set(ofs, (1 << dev->pin), ((bit & 1) << dev->pin));
86 +static inline int cfrdy(struct cf_mips_dev *dev)
88 + return get_gpio_bit(DATA, dev);
91 +static inline void prepare_cf_irq(struct cf_mips_dev *dev)
93 + set_gpio_bit(1, ILEVEL, dev); /* interrupt on cf ready (not busy) */
94 + set_gpio_bit(0, ISTAT, dev); /* clear interrupt status */
97 +static inline int cf_present(struct cf_mips_dev* dev)
99 + /* TODO: read and configure CIS into memory mapped mode
100 + * TODO: parse CISTPL_CONFIG on CF+ cards to get base address (0x200)
101 + * TODO: maybe adjust power saving setting for Hitachi Microdrive
105 + /* setup CFRDY GPIO as input */
106 + set_gpio_bit(0, FUNC, dev);
107 + set_gpio_bit(0, CFG, dev);
109 + for (i = 0; i < 0x10; ++i) {
110 + if (rareg(i,dev) != 0xff)
116 +static inline int is_busy(struct cf_mips_dev *dev)
118 + return !cfrdy(dev);
121 +static int wait_not_busy(int to_us, int wait_for_busy,struct cf_mips_dev *dev)
124 + if (wait_for_busy && !is_busy(dev)) {
125 + /* busy must appear within 400ns,
126 + * but it may dissapear before we see it
127 + * => must not wait for busy in a loop
134 + udelay(1); /* never reached in async mode */
135 + if (!is_busy(dev)) {
136 + if (us_passed > 1 * SECS) {
137 + printk(KERN_WARNING "cf-mips: not busy ok (after %dus)"
138 + ", status 0x%02x\n", us_passed, (unsigned) rareg(ATA_REG_ST,dev));
140 + return CF_TRANS_OK;
142 + if (us_passed == 1 * SECS) {
143 + printk(KERN_WARNING "cf-mips: wait not busy %dus..\n", to_us);
145 + if (dev->async_mode) {
146 + dev->to_timer.expires = jiffies + (to_us * HZ / SECS);
147 + dev->irq_enable_time = jiffies;
148 + prepare_cf_irq(dev);
149 + if (is_busy(dev)) {
150 + add_timer(&dev->to_timer);
151 + enable_irq(dev->irq);
152 + return CF_TRANS_IN_PROGRESS;
157 + } while (us_passed < to_us);
159 + printk(KERN_ERR "cf-mips: wait not busy timeout (%dus)"
160 + ", status 0x%02x, state %d\n",
161 + to_us, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
162 + return CF_TRANS_FAILED;
165 +static irqreturn_t cf_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
167 + /* While tasklet has not disabled irq, irq will be retried all the time
168 + * because of ILEVEL matching GPIO pin status => deadlock.
169 + * To avoid this, we change ILEVEL to 0.
171 + struct cf_mips_dev *dev=dev_id;
173 + set_gpio_bit(0, ILEVEL, dev);
174 + set_gpio_bit(0, ISTAT, dev);
176 + del_timer(&dev->to_timer);
177 + tasklet_schedule(&dev->tasklet);
178 + return IRQ_HANDLED;
181 +static int do_reset(struct cf_mips_dev *dev)
183 + printk(KERN_INFO "cf-mips: resetting..\n");
185 + wareg(ATA_REG_DC_SRST, ATA_REG_DC,dev);
186 + udelay(1); /* FIXME: how long should we wait here? */
187 + wareg(0, ATA_REG_DC,dev);
189 + return wait_not_busy(30 * SECS, 1,dev);
192 +static int set_multiple(struct cf_mips_dev *dev)
194 + if (dev->block_size <= 1)
195 + return CF_TRANS_OK;
197 + wareg(dev->block_size, ATA_REG_SC,dev);
198 + wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
199 + wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
201 + return wait_not_busy(10 * SECS, 1,dev);
204 +static int set_cmd(struct cf_mips_dev *dev)
206 + //DEBUGP(KERN_INFO "cf-mips: ata cmd 0x%02x\n", dev->tcmd);
207 + // sector_count should be <=24 bits..
208 + BUG_ON(dev->tsect_start>=0x10000000);
209 + // This way, it addresses 2^24 * 512 = 128G
211 + if (dev->tsector_count) {
212 + wareg(dev->tsector_count & 0xff, ATA_REG_SC,dev);
213 + wareg(dev->tsect_start & 0xff, ATA_REG_SN,dev);
214 + wareg((dev->tsect_start >> 8) & 0xff, ATA_REG_CL,dev);
215 + wareg((dev->tsect_start >> 16) & 0xff, ATA_REG_CH,dev);
217 + wareg(((dev->tsect_start >> 24) & 0x0f) | ATA_REG_DH_BASE | ATA_REG_DH_LBA,
218 + ATA_REG_DH,dev); /* select drive on all commands */
219 + wareg(dev->tcmd, ATA_REG_CMD,dev);
220 + return wait_not_busy(10 * SECS, 1,dev);
223 +static int do_trans(struct cf_mips_dev *dev)
229 + //printk("do_trans: %d sectors left\n",dev->tsectors_left);
230 + while (dev->tsectors_left) {
233 + st = rareg(ATA_REG_ST,dev);
234 + if (!(st & ATA_REG_ST_DRQ)) {
235 + printk(KERN_ERR "cf-mips: do_trans without DRQ (status 0x%x)!\n", st);
236 + if (st & ATA_REG_ST_ERR) {
237 + int errId = rareg(ATA_REG_ERR,dev);
238 + printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
239 + (dev->tread ? "read" : "write"), st, errId);
241 + return CF_TRANS_FAILED;
243 + do { /* Fill/read the buffer one block */
245 + qbuf = (u32 *)dev->tbuf;
246 + qend = qbuf + CF_SECT_SIZE / sizeof(u32);
249 + put_unaligned(*DBUF32,qbuf++);
250 + //*(qbuf++) = *DBUF32;
254 + *DBUF32 = get_unaligned(qbuf++);
257 + dev->tsectors_left--;
258 + dev->tbuf += CF_SECT_SIZE;
259 + dev->tbuf_size -= CF_SECT_SIZE;
261 + } while (transfered != dev->block_size && dev->tsectors_left > 0);
263 + res = wait_not_busy(10 * SECS, 1,dev);
264 + if (res != CF_TRANS_OK)
268 + st = rareg(ATA_REG_ST,dev);
269 + if (st & (ATA_REG_ST_DRQ | ATA_REG_ST_DWF | ATA_REG_ST_ERR)) {
270 + if (st & ATA_REG_ST_DRQ) {
271 + printk(KERN_ERR "cf-mips: DRQ after all %d sectors are %s"
272 + ", status 0x%x\n", dev->tsector_count, (dev->tread ? "read" : "written"), st);
273 + } else if (st & ATA_REG_ST_DWF) {
274 + printk(KERN_ERR "cf-mips: write fault, status 0x%x\n", st);
276 + int errId = rareg(ATA_REG_ERR,dev);
277 + printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
278 + (dev->tread ? "read" : "write"), st, errId);
280 + return CF_TRANS_FAILED;
282 + return CF_TRANS_OK;
285 +static int cf_do_state(struct cf_mips_dev *dev)
288 + switch (dev->tstate) { /* fall through everywhere */
290 + dev->tstate = TS_READY;
291 + if (is_busy(dev)) {
292 + dev->tstate = TS_AFTER_RESET;
293 + res = do_reset(dev);
294 + if (res != CF_TRANS_OK)
297 + case TS_AFTER_RESET:
298 + if (dev->tstate == TS_AFTER_RESET) {
299 + dev->tstate = TS_READY;
300 + res = set_multiple(dev);
301 + if (res != CF_TRANS_OK)
305 + dev->tstate = TS_CMD;
306 + res = set_cmd(dev);
307 + if (res != CF_TRANS_OK)
310 + dev->tstate = TS_TRANS;
312 + res = do_trans(dev);
315 + printk(KERN_ERR "cf-mips: BUG: unknown tstate %d\n", dev->tstate);
316 + return CF_TRANS_FAILED;
318 + if (res != CF_TRANS_IN_PROGRESS)
319 + dev->tstate = TS_IDLE;
323 +static void cf_do_tasklet(unsigned long dev_l)
325 + struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
328 + disable_irq(dev->irq);
330 + if (dev->tstate == TS_IDLE)
331 + return; /* can happen when irq is first registered */
334 + DEBUGP(KERN_WARNING "cf-mips: not busy ok (tasklet) status 0x%02x\n",
335 + (unsigned) rareg(ATA_REG_ST,dev));
338 + res = cf_do_state(dev);
339 + if (res == CF_TRANS_IN_PROGRESS)
341 + cf_async_trans_done(dev,res);
344 +static void cf_async_timeout(unsigned long dev_l)
346 + struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
347 + disable_irq(dev->irq);
348 + /* Perhaps send abort to the device? */
349 + printk(KERN_ERR "cf-mips: wait not busy timeout (%lus)"
350 + ", status 0x%02x, state %d\n",
351 + jiffies - dev->irq_enable_time, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
352 + dev->tstate = TS_IDLE;
353 + cf_async_trans_done(dev,CF_TRANS_FAILED);
356 +int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
357 + char* buffer, int is_write)
359 + BUG_ON(dev->tstate!=TS_IDLE);
360 + if (nsect > ATA_MAX_SECT_PER_CMD) {
361 + printk(KERN_WARNING "cf-mips: sector count %lu out of range\n",nsect);
362 + return CF_TRANS_FAILED;
364 + if (sector + nsect > dev->sectors) {
365 + printk(KERN_WARNING "cf-mips: sector %lu out of range\n",sector);
366 + return CF_TRANS_FAILED;
368 + dev->tbuf = buffer;
369 + dev->tbuf_size = nsect*512;
370 + dev->tsect_start = sector;
371 + dev->tsector_count = nsect;
372 + dev->tsectors_left = dev->tsector_count;
373 + dev->tread = (is_write)?0:1;
375 + dev->tcmd = (dev->block_size == 1 ?
376 + (is_write ? ATA_CMD_WRITE_SECTORS : ATA_CMD_READ_SECTORS) :
377 + (is_write ? ATA_CMD_WRITE_MULTIPLE : ATA_CMD_READ_MULTIPLE));
379 + return cf_do_state(dev);
382 +static int do_identify(struct cf_mips_dev *dev)
384 + u16 sbuf[CF_SECT_SIZE >> 1];
386 + char tstr[17]; //serial
387 + BUG_ON(dev->tstate!=TS_IDLE);
388 + dev->tbuf = (char *) sbuf;
389 + dev->tbuf_size = CF_SECT_SIZE;
390 + dev->tsect_start = 0;
391 + dev->tsector_count = 0;
392 + dev->tsectors_left = 1;
394 + dev->tcmd = ATA_CMD_IDENTIFY_DRIVE;
396 + DEBUGP(KERN_INFO "cf-mips: identify drive..\n");
397 + res = cf_do_state(dev);
398 + if (res == CF_TRANS_IN_PROGRESS) {
399 + printk(KERN_ERR "cf-mips: BUG: async identify cmd\n");
400 + return CF_TRANS_FAILED;
402 + if (res != CF_TRANS_OK)
405 + dev->head = sbuf[3];
406 + dev->cyl = sbuf[1];
407 + dev->spt = sbuf[6];
408 + dev->sectors = ((unsigned long) sbuf[7] << 16) | sbuf[8];
409 + dev->dtype=sbuf[0];
410 + memcpy(tstr,&sbuf[12],16);
412 + printk(KERN_INFO "cf-mips: %s detected, C/H/S=%d/%d/%d sectors=%u (%uMB) Serial=%s\n",
413 + (sbuf[0] == 0x848A ? "CF card" : "ATA drive"), dev->cyl, dev->head,
414 + dev->spt, dev->sectors, dev->sectors >> 11,tstr);
418 +static void init_multiple(struct cf_mips_dev * dev)
421 + DEBUGP(KERN_INFO "cf-mips: detecting block size\n");
423 + dev->block_size = 128; /* max block size = 128 sectors (64KB) */
425 + wareg(dev->block_size, ATA_REG_SC,dev);
426 + wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
427 + wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
429 + res = wait_not_busy(10 * SECS, 1,dev);
430 + if (res != CF_TRANS_OK) {
431 + printk(KERN_ERR "cf-mips: failed to detect block size: busy!\n");
432 + dev->block_size = 1;
435 + if ((rareg(ATA_REG_ST,dev) & ATA_REG_ST_ERR) == 0)
437 + dev->block_size /= 2;
438 + } while (dev->block_size > 1);
440 + printk(KERN_INFO "cf-mips: multiple sectors = %d\n", dev->block_size);
443 +int cf_init(struct cf_mips_dev *dev)
445 + tasklet_init(&dev->tasklet,cf_do_tasklet,(unsigned long)dev);
446 + dev->baddr = ioremap_nocache((unsigned long)dev->base, CFDEV_BUF_SIZE);
448 + printk(KERN_ERR "cf-mips: cf_init: ioremap for (%lx,%x) failed\n",
449 + (unsigned long) dev->base, CFDEV_BUF_SIZE);
453 + if (!cf_present(dev)) {
454 + printk(KERN_WARNING "cf-mips: cf card not present\n");
455 + iounmap(dev->baddr);
459 + if (do_reset(dev) != CF_TRANS_OK) {
460 + printk(KERN_ERR "cf-mips: cf reset failed\n");
461 + iounmap(dev->baddr);
465 + if (!do_identify(dev)) {
466 + printk(KERN_ERR "cf-mips: cf identify failed\n");
467 + iounmap(dev->baddr);
471 +/* set_apm_level(ATA_APM_WITH_STANDBY); */
472 + init_multiple(dev);
474 + init_timer(&dev->to_timer);
475 + dev->to_timer.function = cf_async_timeout;
476 + dev->to_timer.data = (unsigned long)dev;
478 + prepare_cf_irq(dev);
479 + if (request_irq(dev->irq, cf_irq_handler, 0, "CF Mips", dev)) {
480 + printk(KERN_ERR "cf-mips: failed to get irq\n");
481 + iounmap(dev->baddr);
484 + /* Disable below would be odd, because request will enable, and the tasklet
485 + will disable it itself */
486 + //disable_irq(dev->irq);
488 + dev->async_mode = 1;
493 +void cf_cleanup(struct cf_mips_dev *dev)
495 + iounmap(dev->baddr);
496 + free_irq(dev->irq, NULL);
497 +#if REQUEST_MEM_REGION
498 + release_mem_region((unsigned long)dev->base, CFDEV_BUF_SIZE);
504 diff -urN linux.old/drivers/block/rb500/ata.h linux.dev/drivers/block/rb500/ata.h
505 --- linux.old/drivers/block/rb500/ata.h 1970-01-01 01:00:00.000000000 +0100
506 +++ linux.dev/drivers/block/rb500/ata.h 2006-10-26 00:11:14.000000000 +0200
508 +#ifndef __CFMIPS_ATA_H__
509 +#define __CFMIPS_ATA_H__
511 +#include <linux/interrupt.h>
513 +#define CFG_DC_DEV1 (void*)0xb8010010
514 +#define CFG_DC_DEVBASE 0x0
515 +#define CFG_DC_DEVMASK 0x4
516 +#define CFG_DC_DEVC 0x8
517 +#define CFG_DC_DEVTC 0xC
519 +#define CFDEV_BUF_SIZE 0x1000
520 +#define ATA_CIS_OFFSET 0x200
521 +#define ATA_REG_OFFSET 0x800
522 +#define ATA_DBUF_OFFSET 0xC00
524 +#define ATA_REG_FEAT 0x1
525 +#define ATA_REG_SC 0x2
526 +#define ATA_REG_SN 0x3
527 +#define ATA_REG_CL 0x4
528 +#define ATA_REG_CH 0x5
529 +#define ATA_REG_DH 0x6
530 +#define ATA_REG_DH_BASE 0xa0
531 +#define ATA_REG_DH_LBA 0x40
532 +#define ATA_REG_DH_DRV 0x10
533 +#define ATA_REG_CMD 0x7
534 +#define ATA_REG_ST 0x7
535 +#define ATA_REG_ST_BUSY 0x80
536 +#define ATA_REG_ST_RDY 0x40
537 +#define ATA_REG_ST_DWF 0x20
538 +#define ATA_REG_ST_DSC 0x10
539 +#define ATA_REG_ST_DRQ 0x08
540 +#define ATA_REG_ST_CORR 0x04
541 +#define ATA_REG_ST_ERR 0x01
542 +#define ATA_REG_ERR 0xd
543 +#define ATA_REG_DC 0xe
544 +#define ATA_REG_DC_IEN 0x02
545 +#define ATA_REG_DC_SRST 0x04
547 +#define ATA_CMD_READ_SECTORS 0x20
548 +#define ATA_CMD_WRITE_SECTORS 0x30
549 +#define ATA_CMD_EXEC_DRIVE_DIAG 0x90
550 +#define ATA_CMD_READ_MULTIPLE 0xC4
551 +#define ATA_CMD_WRITE_MULTIPLE 0xC5
552 +#define ATA_CMD_SET_MULTIPLE 0xC6
553 +#define ATA_CMD_IDENTIFY_DRIVE 0xEC
554 +#define ATA_CMD_SET_FEATURES 0xEF
556 +#define ATA_FEATURE_ENABLE_APM 0x05
557 +#define ATA_FEATURE_DISABLE_APM 0x85
558 +#define ATA_APM_DISABLED 0x00
559 +#define ATA_APM_MIN_POWER 0x01
560 +#define ATA_APM_WITH_STANDBY 0x7f
561 +#define ATA_APM_WITHOUT_STANDBY 0x80
562 +#define ATA_APM_MAX_PERFORMANCE 0xfe
564 +#define CF_SECT_SIZE 0x200
565 +/* That is the ratio CF_SECT_SIZE/512 (the kernel sector size) */
566 +#define CF_KERNEL_MUL 1
567 +#define ATA_MAX_SECT_PER_CMD 0x100
569 +#define CF_TRANS_FAILED 0
570 +#define CF_TRANS_OK 1
571 +#define CF_TRANS_IN_PROGRESS 2
584 +// static unsigned long busy_time;
587 +/** Struct to hold the cfdev
588 +Actually, all the data here only has one instance. However, for
589 +reasons of programming conformity, it is passed around as a pointer
591 +struct cf_mips_dev {
592 + void *base; /* base address for I/O */
593 + void *baddr; /* remapped address */
595 + int pin; /* gpio pin */
596 + int irq; /* gpio irq */
603 + unsigned short block_size;
604 + unsigned dtype ; // ATA or CF
605 + struct request_queue *queue;
606 + struct gendisk *gd;
608 + /* Transaction state */
609 + enum trans_state tstate;
611 + unsigned long tbuf_size;
612 + sector_t tsect_start;
613 + unsigned tsector_count;
614 + unsigned tsectors_left;
618 + unsigned long irq_enable_time;
620 + struct request *active_req; /* A request is being carried out. Is that different from tstate? */
622 + struct timer_list to_timer;
623 + struct tasklet_struct tasklet;
625 + /** This lock ensures that the requests to this device are all done
626 + atomically. Transfers can run in parallel, requests are all queued
631 +int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
632 + char* buffer, int is_write);
633 +int cf_init(struct cf_mips_dev* dev);
634 +void cf_cleanup(struct cf_mips_dev* dev);
636 +void cf_async_trans_done(struct cf_mips_dev* dev, int result);
637 +// void *cf_get_next_buf(unsigned long *buf_size);
640 diff -urN linux.old/drivers/block/rb500/bdev.c linux.dev/drivers/block/rb500/bdev.c
641 --- linux.old/drivers/block/rb500/bdev.c 1970-01-01 01:00:00.000000000 +0100
642 +++ linux.dev/drivers/block/rb500/bdev.c 2006-10-26 00:11:14.000000000 +0200
645 + This is a block driver for the direct (mmaped) interface to the CF-slot,
646 + found in Routerboard.com's RB532 board
647 + See SDK provided from routerboard.com.
649 + Module adapted By P.Christeas <p_christeas@yahoo.com>, 2005-6.
650 + Cleaned up and adapted to platform_device by Felix Fietkau <nbd@openwrt.org>
652 + This work is redistributed under the terms of the GNU General Public License.
655 +#include <linux/kernel.h>
656 +#include <linux/module.h>
657 +#include <linux/init.h>
658 +#include <linux/time.h>
659 +#include <linux/wait.h>
660 +#include <linux/fs.h>
661 +#include <linux/genhd.h>
662 +#include <linux/blkdev.h>
663 +#include <linux/blkpg.h>
664 +#include <linux/hdreg.h>
665 +#include <linux/platform_device.h>
667 +#include <asm/uaccess.h>
670 +#include <asm/rc32434/rb.h>
673 +#define DEBUGP printk
676 +#define DEBUGP(format, args...)
680 +#define CF_MIPS_MAJOR 13
681 +#define MAJOR_NR CF_MIPS_MAJOR
682 +#define CF_MAX_PART 16 /* max 15 partitions */
686 +//extern struct block_device_operations cf_bdops;
688 +// static struct hd_struct cf_parts[CF_MAX_PART];
689 +// static int cf_part_sizes[CF_MAX_PART];
690 +// static int cf_hsect_sizes[CF_MAX_PART];
691 +// static int cf_max_sectors[CF_MAX_PART];
692 +// static int cf_blksize_sizes[CF_MAX_PART];
694 +// static spinlock_t lock = SPIN_LOCK_UNLOCKED;
696 +// volatile int cf_busy = 0;
698 +static struct request *active_req = NULL;
700 +static int cf_open (struct inode *, struct file *);
701 +static int cf_release (struct inode *, struct file *);
702 +static int cf_ioctl (struct inode *, struct file *, unsigned, unsigned long);
704 +static void cf_request(request_queue_t * q);
705 +static int cf_transfer(const struct request *req);
707 +/*long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
708 +long (*compat_ioctl) (struct file *, unsigned, unsigned long);*/
709 +// int (*direct_access) (struct block_device *, sector_t, unsigned long *);
710 +// int (*media_changed) (struct gendisk *);
711 +// int (*revalidate_disk) (struct gendisk *);
713 +static struct block_device_operations cf_bdops = {
714 + .owner = THIS_MODULE,
716 + .release = cf_release,
718 + .media_changed = NULL,
719 + .unlocked_ioctl = NULL,
720 + .revalidate_disk = NULL,
721 + .compat_ioctl = NULL,
722 + .direct_access = NULL
726 +int cf_mips_probe(struct platform_device *pdev)
728 + struct gendisk* cf_gendisk=NULL;
729 + struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
730 + struct cf_mips_dev *dev;
731 + struct resource *r;
734 + reg_result = register_blkdev(MAJOR_NR, "cf-mips");
735 + if (reg_result < 0) {
736 + printk(KERN_WARNING "cf-mips: can't get major %d\n", MAJOR_NR);
740 + dev = (struct cf_mips_dev *)kmalloc(sizeof(struct cf_mips_dev),GFP_KERNEL);
743 + memset(dev, 0, sizeof(struct cf_mips_dev));
746 + dev->pin = cdev->gpio_pin;
747 + dev->irq = platform_get_irq_byname(pdev, "cf_irq");
748 + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cf_membase");
749 + dev->base = (void *) r->start;
751 + if (cf_init(dev)) goto out_err;
752 + printk("init done");
754 + spin_lock_init(&dev->lock);
755 + dev->queue = blk_init_queue(cf_request,&dev->lock);
757 + printk(KERN_ERR "cf-mips: no mem for queue\n");
760 + blk_queue_max_sectors(dev->queue,ATA_MAX_SECT_PER_CMD);
762 + /* For memory devices, it is always better to avoid crossing segments
763 + inside the same request. */
764 +/* if (dev->dtype==0x848A){
765 + printk(KERN_INFO "Setting boundary for cf to 0x%x",(dev->block_size*512)-1);
766 + blk_queue_segment_boundary(dev->queue, (dev->block_size*512)-1);
769 + dev->gd = alloc_disk(CF_MAX_PART);
770 + cf_gendisk = dev->gd;
771 + cdev->gd = dev->gd;
772 + if (!cf_gendisk) goto out_err; /* Last of these goto's */
774 + cf_gendisk->major = MAJOR_NR;
775 + cf_gendisk->first_minor = 0;
776 + cf_gendisk->queue=dev->queue;
777 + BUG_ON(cf_gendisk->minors != CF_MAX_PART);
778 + strcpy(cf_gendisk->disk_name,"cfa");
779 + strcpy(cf_gendisk->devfs_name,"cf/card0");
780 + cf_gendisk->fops = &cf_bdops;
781 + cf_gendisk->flags = 0 ; /* is not yet GENHD_FL_REMOVABLE */
782 + cf_gendisk->private_data=dev;
784 + set_capacity(cf_gendisk,dev->sectors * CF_KERNEL_MUL);
786 + /* Let the disk go live */
787 + add_disk(cf_gendisk);
789 + result = cf_init();
791 + /* default cfg for all partitions */
792 + memset(cf_parts, 0, sizeof (cf_parts[0]) * CF_MAX_PART);
793 + memset(cf_part_sizes, 0, sizeof (cf_part_sizes[0]) * CF_MAX_PART);
794 + for (i = 0; i < CF_MAX_PART; ++i) {
795 + cf_hsect_sizes[i] = CF_SECT_SIZE;
796 + cf_max_sectors[i] = ATA_MAX_SECT_PER_CMD;
797 + cf_blksize_sizes[i] = BLOCK_SIZE;
800 + /* setup info for whole disk (partition 0) */
801 + cf_part_sizes[0] = cf_sectors / 2;
802 + cf_parts[0].nr_sects = cf_sectors;
804 + blk_size[MAJOR_NR] = cf_part_sizes;
805 + blksize_size[MAJOR_NR] = cf_blksize_sizes;
806 + max_sectors[MAJOR_NR] = cf_max_sectors;
807 + hardsect_size[MAJOR_NR] = cf_hsect_sizes;
808 + read_ahead[MAJOR_NR] = 8; /* (4kB) */
810 + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
812 + add_gendisk(&cf_gendisk);
814 +// printk(KERN_INFO "cf-mips partition check: \n");
815 +// register_disk(cf_gendisk, MKDEV(MAJOR_NR, 0), CF_MAX_PART,
816 +// &cf_bdops, dev->sectors);
821 + blk_cleanup_queue(dev->queue);
824 + unregister_blkdev(MAJOR_NR, "cf-mips");
835 +cf_mips_remove(struct platform_device *pdev)
837 + struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
838 + struct cf_mips_dev *dev = (struct cf_mips_dev *) cdev->dev;
840 + unregister_blkdev(MAJOR_NR, "cf-mips");
841 + blk_cleanup_queue(dev->queue);
843 + del_gendisk(dev->gd);
849 +static struct platform_driver cf_driver = {
850 + .driver.name = "rb500-cf",
851 + .probe = cf_mips_probe,
852 + .remove = cf_mips_remove,
855 +static int __init cf_mips_init(void)
857 + printk(KERN_INFO "cf-mips module loaded\n");
858 + return platform_driver_register(&cf_driver);
861 +static void cf_mips_cleanup(void)
863 + platform_driver_unregister(&cf_driver);
864 + printk(KERN_INFO "cf-mips module removed\n");
867 +module_init(cf_mips_init);
868 +module_exit(cf_mips_cleanup);
870 +MODULE_LICENSE("GPL");
871 +MODULE_ALIAS_BLOCKDEV_MAJOR(CF_MIPS_MAJOR);
874 +static int cf_open(struct inode *inode, struct file *filp)
876 + struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
877 + int minor = MINOR(inode->i_rdev);
879 + if (minor >= CF_MAX_PART)
881 + //DEBUGP(KERN_INFO "cf-mips module opened, minor %d\n", minor);
882 + spin_lock(&dev->lock);
884 + spin_unlock(&dev->lock);
885 + filp->private_data=dev;
887 + /* dirty workaround to set CFRDY GPIO as an input when some other
888 + program sets it as an output */
889 + gpio_set(CFG, (1 << dev->pin), 0);
890 + return 0; /* success */
893 +static int cf_release(struct inode *inode, struct file *filp)
895 + int minor = MINOR(inode->i_rdev);
896 + struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
897 + spin_lock(&dev->lock);
899 + spin_unlock(&dev->lock);
903 +static int cf_ioctl(struct inode *inode, struct file *filp,
904 + unsigned int cmd, unsigned long arg)
906 + unsigned minor = MINOR(inode->i_rdev);
907 + struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
909 + DEBUGP(KERN_INFO "cf_ioctl cmd %u\n", cmd);
911 + case BLKRRPART: /* re-read partition table */
912 + if (!capable(CAP_SYS_ADMIN))
914 + printk(KERN_INFO "cf-mips partition check: \n");
915 + register_disk(dev->gd);
920 + struct hd_geometry geo;
921 + geo.cylinders = dev->cyl;
922 + geo.heads = dev->head;
923 + geo.sectors = dev->spt;
924 + geo.start = (*dev->gd->part)[minor].start_sect;
925 + if (copy_to_user((void *) arg, &geo, sizeof (geo)))
931 + return -EINVAL; /* unknown command */
934 +static void cf_request(request_queue_t * q)
936 + struct cf_mips_dev* dev;
938 + struct request * req;
941 + /* We could have q->queuedata = dev , but haven't yet. */
945 + while ((req=elv_next_request(q))!=NULL){
946 + dev=req->rq_disk->private_data;
947 + status=cf_transfer(req);
948 + if (status==CF_TRANS_IN_PROGRESS){
952 + end_request(req,status);
956 +static int cf_transfer(const struct request *req)
958 + struct cf_mips_dev* dev=req->rq_disk->private_data;
960 + if (!blk_fs_request(req)){
961 + if (printk_ratelimit())
962 + printk(KERN_WARNING "cf-mips: skipping non-fs request 0x%x\n",req->cmd[0]);
963 + return CF_TRANS_FAILED;
966 + return cf_do_transfer(dev,req->sector,req->current_nr_sectors,req->buffer,rq_data_dir(req));
969 +void cf_async_trans_done(struct cf_mips_dev * dev,int result)
971 + struct request *req;
973 + spin_lock(&dev->lock);
976 + end_request(req,result);
977 + spin_unlock(&dev->lock);
979 + spin_lock(&dev->lock);
980 + cf_request(dev->queue);
981 + spin_unlock(&dev->lock);
984 diff -urN linux.old/drivers/block/rb500/Makefile linux.dev/drivers/block/rb500/Makefile
985 --- linux.old/drivers/block/rb500/Makefile 1970-01-01 01:00:00.000000000 +0100
986 +++ linux.dev/drivers/block/rb500/Makefile 2006-10-26 00:11:14.000000000 +0200
988 +## Makefile for the RB532 CF port
990 +obj-y += bdev.o ata.o