add rb532 support
SVN-Revision: 3956
This commit is contained in:
parent
0eb990ad63
commit
726e4fbdde
15 changed files with 10096 additions and 0 deletions
|
@ -43,6 +43,12 @@ config LINUX_2_6_BRCM
|
||||||
Build firmware images for Broadcom based routers
|
Build firmware images for Broadcom based routers
|
||||||
(e.g. Netgear WGT634u)
|
(e.g. Netgear WGT634u)
|
||||||
|
|
||||||
|
config LINUX_2_6_RB532
|
||||||
|
bool "Mikrotik RB532 [2.6]"
|
||||||
|
select mipsel
|
||||||
|
select LINUX_2_6
|
||||||
|
select PCI_SUPPORT
|
||||||
|
|
||||||
config LINUX_2_4_AR7
|
config LINUX_2_4_AR7
|
||||||
bool "TI AR7 [2.4]"
|
bool "TI AR7 [2.4]"
|
||||||
select mipsel
|
select mipsel
|
||||||
|
|
|
@ -14,6 +14,7 @@ $(eval $(call kernel_template,2.4,brcm,2_4_BRCM))
|
||||||
$(eval $(call kernel_template,2.4,ar7,2_4_AR7))
|
$(eval $(call kernel_template,2.4,ar7,2_4_AR7))
|
||||||
$(eval $(call kernel_template,2.4,x86,2_4_X86))
|
$(eval $(call kernel_template,2.4,x86,2_4_X86))
|
||||||
$(eval $(call kernel_template,2.6,brcm,2_6_BRCM))
|
$(eval $(call kernel_template,2.6,brcm,2_6_BRCM))
|
||||||
|
$(eval $(call kernel_template,2.6,rb532,2_6_RB532))
|
||||||
$(eval $(call kernel_template,2.6,x86,2_6_X86))
|
$(eval $(call kernel_template,2.6,x86,2_6_X86))
|
||||||
$(eval $(call kernel_template,2.4,ar531x,2_4_AR531X))
|
$(eval $(call kernel_template,2.4,ar531x,2_4_AR531X))
|
||||||
$(eval $(call kernel_template,2.6,aruba,2_6_ARUBA))
|
$(eval $(call kernel_template,2.6,aruba,2_6_ARUBA))
|
||||||
|
|
50
openwrt/target/linux/image/rb532/Makefile
Normal file
50
openwrt/target/linux/image/rb532/Makefile
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
include ../image.mk
|
||||||
|
|
||||||
|
LOADADDR = 0x81000000 # RAM start + 16M
|
||||||
|
KERNEL_ENTRY = 0x80101000
|
||||||
|
RAMSIZE = 0x00100000 # 1MB
|
||||||
|
IMAGE_COPY = 1
|
||||||
|
|
||||||
|
LOADER_MAKEOPTS= \
|
||||||
|
KDIR=$(KDIR) \
|
||||||
|
LOADADDR=$(LOADADDR) \
|
||||||
|
KERNEL_ENTRY=$(KERNEL_ENTRY) \
|
||||||
|
RAMSIZE=$(RAMSIZE) \
|
||||||
|
IMAGE_COPY=$(IMAGE_COPY)
|
||||||
|
|
||||||
|
define Build/Clean
|
||||||
|
$(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Image/Prepare
|
||||||
|
cat $(KDIR)/vmlinux | $(STAGING_DIR)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
|
||||||
|
$(MAKE) -C ../generic/lzma-loader $(LOADER_MAKEOPTS) clean compile
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Image/BuildKernel
|
||||||
|
$(CP) $(KDIR)/loader.elf $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-vmlinux
|
||||||
|
endef
|
||||||
|
|
||||||
|
PARTITION1=\x80\x01\x01\x00\x27\x01\x20\x7b\x20\x00\x00\x00\xe0\x1e\x00\x00# 4 MB (kernel part)
|
||||||
|
PARTITION2=\x00\x00\x01\x7c\x83\x01\xa0\x64\x00\x1f\x00\x00\x40\x7a\x00\x00# 16 MB (rootfs part)
|
||||||
|
|
||||||
|
define Image/Build/jffs2-128k
|
||||||
|
( \
|
||||||
|
echo -ne OWRT | dd bs=$$$$((0x1be)) conv=sync; \
|
||||||
|
( \
|
||||||
|
echo -ne '$(strip $(PARTITION1))'; \
|
||||||
|
echo -ne '$(strip $(PARTITION2))'; \
|
||||||
|
) | dd bs=$$$$((0x40)) conv=sync; \
|
||||||
|
echo -ne '\x55\xaa'; \
|
||||||
|
dd if=/dev/zero bs=$$$$((0x3e00)) conv=sync count=1; \
|
||||||
|
dd if=$(KDIR)/loader.elf bs=$$$$((0x3dc000)) conv=sync; \
|
||||||
|
cat $(KDIR)/root.$(1); \
|
||||||
|
echo -ne '\xde\xad\xc0\xde'; \
|
||||||
|
) > $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(1).bin
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Image/Build
|
||||||
|
$(call Image/Build/$(1),$(1))
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildImage))
|
18
openwrt/target/linux/rb532-2.6/Makefile
Normal file
18
openwrt/target/linux/rb532-2.6/Makefile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
LINUX_VERSION:=2.6.16.19
|
||||||
|
LINUX_RELEASE:=1
|
||||||
|
LINUX_KERNEL_MD5SUM:=b1e3c65992b0049fdbee825eb2a856af
|
||||||
|
|
||||||
|
include ../rules.mk
|
||||||
|
include ./config
|
||||||
|
|
||||||
|
include ../generic-$(KERNEL)/modules.mk
|
||||||
|
include ../kernel.mk
|
||||||
|
|
||||||
|
$(LINUX_DIR)/.patched: $(LINUX_DIR)/.unpacked
|
||||||
|
[ -d ../generic-$(KERNEL)/patches ] && $(PATCH) $(LINUX_DIR) ../generic-$(KERNEL)/patches
|
||||||
|
[ -d ./patches ] && $(PATCH) $(LINUX_DIR) ./patches
|
||||||
|
@$(CP) config $(LINUX_DIR)/.config
|
||||||
|
touch $@
|
||||||
|
|
1518
openwrt/target/linux/rb532-2.6/config
Normal file
1518
openwrt/target/linux/rb532-2.6/config
Normal file
File diff suppressed because it is too large
Load diff
5679
openwrt/target/linux/rb532-2.6/patches/100-rb5xx_support.patch
Normal file
5679
openwrt/target/linux/rb532-2.6/patches/100-rb5xx_support.patch
Normal file
File diff suppressed because it is too large
Load diff
1375
openwrt/target/linux/rb532-2.6/patches/110-korina_ethernet.patch
Normal file
1375
openwrt/target/linux/rb532-2.6/patches/110-korina_ethernet.patch
Normal file
File diff suppressed because it is too large
Load diff
990
openwrt/target/linux/rb532-2.6/patches/120-cf.patch
Normal file
990
openwrt/target/linux/rb532-2.6/patches/120-cf.patch
Normal file
|
@ -0,0 +1,990 @@
|
||||||
|
diff -urN linux.old/drivers/block/Kconfig linux.dev/drivers/block/Kconfig
|
||||||
|
--- linux.old/drivers/block/Kconfig 2006-06-08 20:20:52.000000000 +0200
|
||||||
|
+++ linux.dev/drivers/block/Kconfig 2006-06-08 22:14:58.000000000 +0200
|
||||||
|
@@ -453,4 +453,12 @@
|
||||||
|
This driver provides Support for ATA over Ethernet block
|
||||||
|
devices like the Coraid EtherDrive (R) Storage Blade.
|
||||||
|
|
||||||
|
+config BLK_DEV_CF_MIPS
|
||||||
|
+ bool "CF slot of RB532 board"
|
||||||
|
+ depends on MIKROTIK_RB500
|
||||||
|
+ default y
|
||||||
|
+ help
|
||||||
|
+ The Routerboard 532 has a CF slot on it. Enable the special block
|
||||||
|
+ device driver for it.
|
||||||
|
+
|
||||||
|
endmenu
|
||||||
|
diff -urN linux.old/drivers/block/rb500/ata.c linux.dev/drivers/block/rb500/ata.c
|
||||||
|
--- linux.old/drivers/block/rb500/ata.c 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ linux.dev/drivers/block/rb500/ata.c 2006-06-09 01:58:40.000000000 +0200
|
||||||
|
@@ -0,0 +1,474 @@
|
||||||
|
+#include <linux/kernel.h> /* printk() */
|
||||||
|
+#include <linux/module.h> /* module to be loadable */
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
+#include <linux/sched.h>
|
||||||
|
+#include <linux/pci.h>
|
||||||
|
+#include <linux/ioport.h> /* request_mem_region() */
|
||||||
|
+#include <asm/unaligned.h> /* ioremap() */
|
||||||
|
+#include <asm/io.h> /* ioremap() */
|
||||||
|
+#include <asm/rc32434/rb.h>
|
||||||
|
+
|
||||||
|
+#include "ata.h"
|
||||||
|
+
|
||||||
|
+#define REQUEST_MEM_REGION 0
|
||||||
|
+#define DEBUG 1
|
||||||
|
+
|
||||||
|
+#if DEBUG
|
||||||
|
+#define DEBUGP printk
|
||||||
|
+#else
|
||||||
|
+#define DEBUGP(format, args...)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define SECS 1000000 /* unit for wait_not_busy() is 1us */
|
||||||
|
+
|
||||||
|
+unsigned cf_head = 0;
|
||||||
|
+unsigned cf_cyl = 0;
|
||||||
|
+unsigned cf_spt = 0;
|
||||||
|
+unsigned cf_sectors = 0;
|
||||||
|
+static unsigned cf_block_size = 1;
|
||||||
|
+static void *baddr = 0;
|
||||||
|
+
|
||||||
|
+#define DBUF32 ((volatile u32 *)((unsigned long)dev->baddr | ATA_DBUF_OFFSET))
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void cf_do_tasklet(unsigned long dev_l);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static inline void wareg(u8 val, unsigned reg, struct cf_mips_dev* dev)
|
||||||
|
+{
|
||||||
|
+ writeb(val, dev->baddr + ATA_REG_OFFSET + reg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline u8 rareg(unsigned reg, struct cf_mips_dev* dev)
|
||||||
|
+{
|
||||||
|
+ return readb(dev->baddr + ATA_REG_OFFSET + reg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int get_gpio_bit(gpio_func ofs, struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ return (gpio_get(ofs) >> dev->pin) & 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void set_gpio_bit(int bit, gpio_func ofs, struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ gpio_set(ofs, (1 << dev->pin), ((bit & 1) << dev->pin));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int cfrdy(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ return get_gpio_bit(DATA, dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void prepare_cf_irq(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ set_gpio_bit(1, ILEVEL, dev); /* interrupt on cf ready (not busy) */
|
||||||
|
+ set_gpio_bit(0, ISTAT, dev); /* clear interrupt status */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int cf_present(struct cf_mips_dev* dev)
|
||||||
|
+{
|
||||||
|
+ /* TODO: read and configure CIS into memory mapped mode
|
||||||
|
+ * TODO: parse CISTPL_CONFIG on CF+ cards to get base address (0x200)
|
||||||
|
+ * TODO: maybe adjust power saving setting for Hitachi Microdrive
|
||||||
|
+ */
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ /* setup CFRDY GPIO as input */
|
||||||
|
+ set_gpio_bit(0, FUNC, dev);
|
||||||
|
+ set_gpio_bit(0, CFG, dev);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < 0x10; ++i) {
|
||||||
|
+ if (rareg(i,dev) != 0xff)
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int is_busy(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ return !cfrdy(dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int wait_not_busy(int to_us, int wait_for_busy,struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ int us_passed = 0;
|
||||||
|
+ if (wait_for_busy && !is_busy(dev)) {
|
||||||
|
+ /* busy must appear within 400ns,
|
||||||
|
+ * but it may dissapear before we see it
|
||||||
|
+ * => must not wait for busy in a loop
|
||||||
|
+ */
|
||||||
|
+ ndelay(400);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ do {
|
||||||
|
+ if (us_passed)
|
||||||
|
+ udelay(1); /* never reached in async mode */
|
||||||
|
+ if (!is_busy(dev)) {
|
||||||
|
+ if (us_passed > 1 * SECS) {
|
||||||
|
+ printk(KERN_WARNING "cf-mips: not busy ok (after %dus)"
|
||||||
|
+ ", status 0x%02x\n", us_passed, (unsigned) rareg(ATA_REG_ST,dev));
|
||||||
|
+ }
|
||||||
|
+ return CF_TRANS_OK;
|
||||||
|
+ }
|
||||||
|
+ if (us_passed == 1 * SECS) {
|
||||||
|
+ printk(KERN_WARNING "cf-mips: wait not busy %dus..\n", to_us);
|
||||||
|
+ }
|
||||||
|
+ if (dev->async_mode) {
|
||||||
|
+ dev->to_timer.expires = jiffies + (to_us * HZ / SECS);
|
||||||
|
+ dev->irq_enable_time = jiffies;
|
||||||
|
+ prepare_cf_irq(dev);
|
||||||
|
+ if (is_busy(dev)) {
|
||||||
|
+ add_timer(&dev->to_timer);
|
||||||
|
+ enable_irq(dev->irq);
|
||||||
|
+ return CF_TRANS_IN_PROGRESS;
|
||||||
|
+ }
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ ++us_passed;
|
||||||
|
+ } while (us_passed < to_us);
|
||||||
|
+
|
||||||
|
+ printk(KERN_ERR "cf-mips: wait not busy timeout (%dus)"
|
||||||
|
+ ", status 0x%02x, state %d\n",
|
||||||
|
+ to_us, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static irqreturn_t cf_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
|
+{
|
||||||
|
+ /* While tasklet has not disabled irq, irq will be retried all the time
|
||||||
|
+ * because of ILEVEL matching GPIO pin status => deadlock.
|
||||||
|
+ * To avoid this, we change ILEVEL to 0.
|
||||||
|
+ */
|
||||||
|
+ struct cf_mips_dev *dev=dev_id;
|
||||||
|
+
|
||||||
|
+ set_gpio_bit(0, ILEVEL, dev);
|
||||||
|
+ set_gpio_bit(0, ISTAT, dev);
|
||||||
|
+
|
||||||
|
+ del_timer(&dev->to_timer);
|
||||||
|
+ tasklet_schedule(&dev->tasklet);
|
||||||
|
+ return IRQ_HANDLED;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int do_reset(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ printk(KERN_INFO "cf-mips: resetting..\n");
|
||||||
|
+
|
||||||
|
+ wareg(ATA_REG_DC_SRST, ATA_REG_DC,dev);
|
||||||
|
+ udelay(1); /* FIXME: how long should we wait here? */
|
||||||
|
+ wareg(0, ATA_REG_DC,dev);
|
||||||
|
+
|
||||||
|
+ return wait_not_busy(30 * SECS, 1,dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int set_multiple(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ if (dev->block_size <= 1)
|
||||||
|
+ return CF_TRANS_OK;
|
||||||
|
+
|
||||||
|
+ wareg(dev->block_size, ATA_REG_SC,dev);
|
||||||
|
+ wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
|
||||||
|
+ wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
|
||||||
|
+
|
||||||
|
+ return wait_not_busy(10 * SECS, 1,dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int set_cmd(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ //DEBUGP(KERN_INFO "cf-mips: ata cmd 0x%02x\n", dev->tcmd);
|
||||||
|
+ // sector_count should be <=24 bits..
|
||||||
|
+ BUG_ON(dev->tsect_start>=0x10000000);
|
||||||
|
+ // This way, it addresses 2^24 * 512 = 128G
|
||||||
|
+
|
||||||
|
+ if (dev->tsector_count) {
|
||||||
|
+ wareg(dev->tsector_count & 0xff, ATA_REG_SC,dev);
|
||||||
|
+ wareg(dev->tsect_start & 0xff, ATA_REG_SN,dev);
|
||||||
|
+ wareg((dev->tsect_start >> 8) & 0xff, ATA_REG_CL,dev);
|
||||||
|
+ wareg((dev->tsect_start >> 16) & 0xff, ATA_REG_CH,dev);
|
||||||
|
+ }
|
||||||
|
+ wareg(((dev->tsect_start >> 24) & 0x0f) | ATA_REG_DH_BASE | ATA_REG_DH_LBA,
|
||||||
|
+ ATA_REG_DH,dev); /* select drive on all commands */
|
||||||
|
+ wareg(dev->tcmd, ATA_REG_CMD,dev);
|
||||||
|
+ return wait_not_busy(10 * SECS, 1,dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int do_trans(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ int res;
|
||||||
|
+ unsigned st;
|
||||||
|
+ int transfered;
|
||||||
|
+
|
||||||
|
+ //printk("do_trans: %d sectors left\n",dev->tsectors_left);
|
||||||
|
+ while (dev->tsectors_left) {
|
||||||
|
+ transfered = 0;
|
||||||
|
+
|
||||||
|
+ st = rareg(ATA_REG_ST,dev);
|
||||||
|
+ if (!(st & ATA_REG_ST_DRQ)) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: do_trans without DRQ (status 0x%x)!\n", st);
|
||||||
|
+ if (st & ATA_REG_ST_ERR) {
|
||||||
|
+ int errId = rareg(ATA_REG_ERR,dev);
|
||||||
|
+ printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
|
||||||
|
+ (dev->tread ? "read" : "write"), st, errId);
|
||||||
|
+ }
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+ do { /* Fill/read the buffer one block */
|
||||||
|
+ u32 *qbuf, *qend;
|
||||||
|
+ qbuf = (u32 *)dev->tbuf;
|
||||||
|
+ qend = qbuf + CF_SECT_SIZE / sizeof(u32);
|
||||||
|
+ if (dev->tread) {
|
||||||
|
+ while (qbuf!=qend)
|
||||||
|
+ put_unaligned(*DBUF32,qbuf++);
|
||||||
|
+ //*(qbuf++) = *DBUF32;
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ while(qbuf!=qend)
|
||||||
|
+ *DBUF32 = get_unaligned(qbuf++);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev->tsectors_left--;
|
||||||
|
+ dev->tbuf += CF_SECT_SIZE;
|
||||||
|
+ dev->tbuf_size -= CF_SECT_SIZE;
|
||||||
|
+ transfered++;
|
||||||
|
+ } while (transfered != dev->block_size && dev->tsectors_left > 0);
|
||||||
|
+
|
||||||
|
+ res = wait_not_busy(10 * SECS, 1,dev);
|
||||||
|
+ if (res != CF_TRANS_OK)
|
||||||
|
+ return res;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ st = rareg(ATA_REG_ST,dev);
|
||||||
|
+ if (st & (ATA_REG_ST_DRQ | ATA_REG_ST_DWF | ATA_REG_ST_ERR)) {
|
||||||
|
+ if (st & ATA_REG_ST_DRQ) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: DRQ after all %d sectors are %s"
|
||||||
|
+ ", status 0x%x\n", dev->tsector_count, (dev->tread ? "read" : "written"), st);
|
||||||
|
+ } else if (st & ATA_REG_ST_DWF) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: write fault, status 0x%x\n", st);
|
||||||
|
+ } else {
|
||||||
|
+ int errId = rareg(ATA_REG_ERR,dev);
|
||||||
|
+ printk(KERN_ERR "cf-mips: %s error, status 0x%x, errid 0x%x\n",
|
||||||
|
+ (dev->tread ? "read" : "write"), st, errId);
|
||||||
|
+ }
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+ return CF_TRANS_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int cf_do_state(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ int res;
|
||||||
|
+ switch (dev->tstate) { /* fall through everywhere */
|
||||||
|
+ case TS_IDLE:
|
||||||
|
+ dev->tstate = TS_READY;
|
||||||
|
+ if (is_busy(dev)) {
|
||||||
|
+ dev->tstate = TS_AFTER_RESET;
|
||||||
|
+ res = do_reset(dev);
|
||||||
|
+ if (res != CF_TRANS_OK)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ case TS_AFTER_RESET:
|
||||||
|
+ if (dev->tstate == TS_AFTER_RESET) {
|
||||||
|
+ dev->tstate = TS_READY;
|
||||||
|
+ res = set_multiple(dev);
|
||||||
|
+ if (res != CF_TRANS_OK)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ case TS_READY:
|
||||||
|
+ dev->tstate = TS_CMD;
|
||||||
|
+ res = set_cmd(dev);
|
||||||
|
+ if (res != CF_TRANS_OK)
|
||||||
|
+ break;;
|
||||||
|
+ case TS_CMD:
|
||||||
|
+ dev->tstate = TS_TRANS;
|
||||||
|
+ case TS_TRANS:
|
||||||
|
+ res = do_trans(dev);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ printk(KERN_ERR "cf-mips: BUG: unknown tstate %d\n", dev->tstate);
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+ if (res != CF_TRANS_IN_PROGRESS)
|
||||||
|
+ dev->tstate = TS_IDLE;
|
||||||
|
+ return res;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void cf_do_tasklet(unsigned long dev_l)
|
||||||
|
+{
|
||||||
|
+ struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
|
||||||
|
+ int res;
|
||||||
|
+
|
||||||
|
+ disable_irq(dev->irq);
|
||||||
|
+
|
||||||
|
+ if (dev->tstate == TS_IDLE)
|
||||||
|
+ return; /* can happen when irq is first registered */
|
||||||
|
+
|
||||||
|
+#if 0
|
||||||
|
+ DEBUGP(KERN_WARNING "cf-mips: not busy ok (tasklet) status 0x%02x\n",
|
||||||
|
+ (unsigned) rareg(ATA_REG_ST,dev));
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ res = cf_do_state(dev);
|
||||||
|
+ if (res == CF_TRANS_IN_PROGRESS)
|
||||||
|
+ return;
|
||||||
|
+ cf_async_trans_done(dev,res);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void cf_async_timeout(unsigned long dev_l)
|
||||||
|
+{
|
||||||
|
+ struct cf_mips_dev* dev=(struct cf_mips_dev*) dev_l;
|
||||||
|
+ disable_irq(dev->irq);
|
||||||
|
+ /* Perhaps send abort to the device? */
|
||||||
|
+ printk(KERN_ERR "cf-mips: wait not busy timeout (%lus)"
|
||||||
|
+ ", status 0x%02x, state %d\n",
|
||||||
|
+ jiffies - dev->irq_enable_time, (unsigned) rareg(ATA_REG_ST,dev), dev->tstate);
|
||||||
|
+ dev->tstate = TS_IDLE;
|
||||||
|
+ cf_async_trans_done(dev,CF_TRANS_FAILED);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
|
||||||
|
+ char* buffer, int is_write)
|
||||||
|
+{
|
||||||
|
+ BUG_ON(dev->tstate!=TS_IDLE);
|
||||||
|
+ if (nsect > ATA_MAX_SECT_PER_CMD) {
|
||||||
|
+ printk(KERN_WARNING "cf-mips: sector count %lu out of range\n",nsect);
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+ if (sector + nsect > dev->sectors) {
|
||||||
|
+ printk(KERN_WARNING "cf-mips: sector %lu out of range\n",sector);
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+ dev->tbuf = buffer;
|
||||||
|
+ dev->tbuf_size = nsect*512;
|
||||||
|
+ dev->tsect_start = sector;
|
||||||
|
+ dev->tsector_count = nsect;
|
||||||
|
+ dev->tsectors_left = dev->tsector_count;
|
||||||
|
+ dev->tread = (is_write)?0:1;
|
||||||
|
+
|
||||||
|
+ dev->tcmd = (dev->block_size == 1 ?
|
||||||
|
+ (is_write ? ATA_CMD_WRITE_SECTORS : ATA_CMD_READ_SECTORS) :
|
||||||
|
+ (is_write ? ATA_CMD_WRITE_MULTIPLE : ATA_CMD_READ_MULTIPLE));
|
||||||
|
+
|
||||||
|
+ return cf_do_state(dev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int do_identify(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ u16 sbuf[CF_SECT_SIZE >> 1];
|
||||||
|
+ int res;
|
||||||
|
+ char tstr[17]; //serial
|
||||||
|
+ BUG_ON(dev->tstate!=TS_IDLE);
|
||||||
|
+ dev->tbuf = (char *) sbuf;
|
||||||
|
+ dev->tbuf_size = CF_SECT_SIZE;
|
||||||
|
+ dev->tsect_start = 0;
|
||||||
|
+ dev->tsector_count = 0;
|
||||||
|
+ dev->tsectors_left = 1;
|
||||||
|
+ dev->tread = 1;
|
||||||
|
+ dev->tcmd = ATA_CMD_IDENTIFY_DRIVE;
|
||||||
|
+
|
||||||
|
+ DEBUGP(KERN_INFO "cf-mips: identify drive..\n");
|
||||||
|
+ res = cf_do_state(dev);
|
||||||
|
+ if (res == CF_TRANS_IN_PROGRESS) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: BUG: async identify cmd\n");
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+ if (res != CF_TRANS_OK)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ dev->head = sbuf[3];
|
||||||
|
+ dev->cyl = sbuf[1];
|
||||||
|
+ dev->spt = sbuf[6];
|
||||||
|
+ dev->sectors = ((unsigned long) sbuf[7] << 16) | sbuf[8];
|
||||||
|
+ dev->dtype=sbuf[0];
|
||||||
|
+ memcpy(tstr,&sbuf[12],16);
|
||||||
|
+ tstr[16]=0;
|
||||||
|
+ printk(KERN_INFO "cf-mips: %s detected, C/H/S=%d/%d/%d sectors=%u (%uMB) Serial=%s\n",
|
||||||
|
+ (sbuf[0] == 0x848A ? "CF card" : "ATA drive"), dev->cyl, dev->head,
|
||||||
|
+ dev->spt, dev->sectors, dev->sectors >> 11,tstr);
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void init_multiple(struct cf_mips_dev * dev)
|
||||||
|
+{
|
||||||
|
+ int res;
|
||||||
|
+ DEBUGP(KERN_INFO "cf-mips: detecting block size\n");
|
||||||
|
+
|
||||||
|
+ dev->block_size = 128; /* max block size = 128 sectors (64KB) */
|
||||||
|
+ do {
|
||||||
|
+ wareg(dev->block_size, ATA_REG_SC,dev);
|
||||||
|
+ wareg(ATA_REG_DH_BASE | ATA_REG_DH_LBA, ATA_REG_DH,dev);
|
||||||
|
+ wareg(ATA_CMD_SET_MULTIPLE, ATA_REG_CMD,dev);
|
||||||
|
+
|
||||||
|
+ res = wait_not_busy(10 * SECS, 1,dev);
|
||||||
|
+ if (res != CF_TRANS_OK) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: failed to detect block size: busy!\n");
|
||||||
|
+ dev->block_size = 1;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if ((rareg(ATA_REG_ST,dev) & ATA_REG_ST_ERR) == 0)
|
||||||
|
+ break;
|
||||||
|
+ dev->block_size /= 2;
|
||||||
|
+ } while (dev->block_size > 1);
|
||||||
|
+
|
||||||
|
+ printk(KERN_INFO "cf-mips: multiple sectors = %d\n", dev->block_size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int cf_init(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ tasklet_init(&dev->tasklet,cf_do_tasklet,(unsigned long)dev);
|
||||||
|
+ dev->baddr = ioremap_nocache((unsigned long)dev->base, CFDEV_BUF_SIZE);
|
||||||
|
+ if (!dev->baddr) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: cf_init: ioremap for (%lx,%x) failed\n",
|
||||||
|
+ (unsigned long) dev->base, CFDEV_BUF_SIZE);
|
||||||
|
+ return -EBUSY;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!cf_present(dev)) {
|
||||||
|
+ printk(KERN_WARNING "cf-mips: cf card not present\n");
|
||||||
|
+ iounmap(dev->baddr);
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (do_reset(dev) != CF_TRANS_OK) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: cf reset failed\n");
|
||||||
|
+ iounmap(dev->baddr);
|
||||||
|
+ return -EBUSY;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!do_identify(dev)) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: cf identify failed\n");
|
||||||
|
+ iounmap(dev->baddr);
|
||||||
|
+ return -EBUSY;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/* set_apm_level(ATA_APM_WITH_STANDBY); */
|
||||||
|
+ init_multiple(dev);
|
||||||
|
+
|
||||||
|
+ init_timer(&dev->to_timer);
|
||||||
|
+ dev->to_timer.function = cf_async_timeout;
|
||||||
|
+ dev->to_timer.data = (unsigned long)dev;
|
||||||
|
+
|
||||||
|
+ prepare_cf_irq(dev);
|
||||||
|
+ if (request_irq(dev->irq, cf_irq_handler, 0, "CF Mips", dev)) {
|
||||||
|
+ printk(KERN_ERR "cf-mips: failed to get irq\n");
|
||||||
|
+ iounmap(dev->baddr);
|
||||||
|
+ return -EBUSY;
|
||||||
|
+ }
|
||||||
|
+ /* Disable below would be odd, because request will enable, and the tasklet
|
||||||
|
+ will disable it itself */
|
||||||
|
+ //disable_irq(dev->irq);
|
||||||
|
+
|
||||||
|
+ dev->async_mode = 1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void cf_cleanup(struct cf_mips_dev *dev)
|
||||||
|
+{
|
||||||
|
+ iounmap(dev->baddr);
|
||||||
|
+ free_irq(dev->irq, NULL);
|
||||||
|
+#if REQUEST_MEM_REGION
|
||||||
|
+ release_mem_region((unsigned long)dev->base, CFDEV_BUF_SIZE);
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*eof*/
|
||||||
|
diff -urN linux.old/drivers/block/rb500/ata.h linux.dev/drivers/block/rb500/ata.h
|
||||||
|
--- linux.old/drivers/block/rb500/ata.h 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ linux.dev/drivers/block/rb500/ata.h 2006-06-09 00:15:23.000000000 +0200
|
||||||
|
@@ -0,0 +1,132 @@
|
||||||
|
+#ifndef __CFMIPS_ATA_H__
|
||||||
|
+#define __CFMIPS_ATA_H__
|
||||||
|
+
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
+
|
||||||
|
+#define CFG_DC_DEV1 (void*)0xb8010010
|
||||||
|
+#define CFG_DC_DEVBASE 0x0
|
||||||
|
+#define CFG_DC_DEVMASK 0x4
|
||||||
|
+#define CFG_DC_DEVC 0x8
|
||||||
|
+#define CFG_DC_DEVTC 0xC
|
||||||
|
+
|
||||||
|
+#define CFDEV_BUF_SIZE 0x1000
|
||||||
|
+#define ATA_CIS_OFFSET 0x200
|
||||||
|
+#define ATA_REG_OFFSET 0x800
|
||||||
|
+#define ATA_DBUF_OFFSET 0xC00
|
||||||
|
+
|
||||||
|
+#define ATA_REG_FEAT 0x1
|
||||||
|
+#define ATA_REG_SC 0x2
|
||||||
|
+#define ATA_REG_SN 0x3
|
||||||
|
+#define ATA_REG_CL 0x4
|
||||||
|
+#define ATA_REG_CH 0x5
|
||||||
|
+#define ATA_REG_DH 0x6
|
||||||
|
+#define ATA_REG_DH_BASE 0xa0
|
||||||
|
+#define ATA_REG_DH_LBA 0x40
|
||||||
|
+#define ATA_REG_DH_DRV 0x10
|
||||||
|
+#define ATA_REG_CMD 0x7
|
||||||
|
+#define ATA_REG_ST 0x7
|
||||||
|
+#define ATA_REG_ST_BUSY 0x80
|
||||||
|
+#define ATA_REG_ST_RDY 0x40
|
||||||
|
+#define ATA_REG_ST_DWF 0x20
|
||||||
|
+#define ATA_REG_ST_DSC 0x10
|
||||||
|
+#define ATA_REG_ST_DRQ 0x08
|
||||||
|
+#define ATA_REG_ST_CORR 0x04
|
||||||
|
+#define ATA_REG_ST_ERR 0x01
|
||||||
|
+#define ATA_REG_ERR 0xd
|
||||||
|
+#define ATA_REG_DC 0xe
|
||||||
|
+#define ATA_REG_DC_IEN 0x02
|
||||||
|
+#define ATA_REG_DC_SRST 0x04
|
||||||
|
+
|
||||||
|
+#define ATA_CMD_READ_SECTORS 0x20
|
||||||
|
+#define ATA_CMD_WRITE_SECTORS 0x30
|
||||||
|
+#define ATA_CMD_EXEC_DRIVE_DIAG 0x90
|
||||||
|
+#define ATA_CMD_READ_MULTIPLE 0xC4
|
||||||
|
+#define ATA_CMD_WRITE_MULTIPLE 0xC5
|
||||||
|
+#define ATA_CMD_SET_MULTIPLE 0xC6
|
||||||
|
+#define ATA_CMD_IDENTIFY_DRIVE 0xEC
|
||||||
|
+#define ATA_CMD_SET_FEATURES 0xEF
|
||||||
|
+
|
||||||
|
+#define ATA_FEATURE_ENABLE_APM 0x05
|
||||||
|
+#define ATA_FEATURE_DISABLE_APM 0x85
|
||||||
|
+#define ATA_APM_DISABLED 0x00
|
||||||
|
+#define ATA_APM_MIN_POWER 0x01
|
||||||
|
+#define ATA_APM_WITH_STANDBY 0x7f
|
||||||
|
+#define ATA_APM_WITHOUT_STANDBY 0x80
|
||||||
|
+#define ATA_APM_MAX_PERFORMANCE 0xfe
|
||||||
|
+
|
||||||
|
+#define CF_SECT_SIZE 0x200
|
||||||
|
+/* That is the ratio CF_SECT_SIZE/512 (the kernel sector size) */
|
||||||
|
+#define CF_KERNEL_MUL 1
|
||||||
|
+#define ATA_MAX_SECT_PER_CMD 0x100
|
||||||
|
+
|
||||||
|
+#define CF_TRANS_FAILED 0
|
||||||
|
+#define CF_TRANS_OK 1
|
||||||
|
+#define CF_TRANS_IN_PROGRESS 2
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+enum trans_state {
|
||||||
|
+ TS_IDLE = 0,
|
||||||
|
+ TS_AFTER_RESET,
|
||||||
|
+ TS_READY,
|
||||||
|
+ TS_CMD,
|
||||||
|
+ TS_TRANS
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+//
|
||||||
|
+// #if DEBUG
|
||||||
|
+// static unsigned long busy_time;
|
||||||
|
+// #endif
|
||||||
|
+
|
||||||
|
+/** Struct to hold the cfdev
|
||||||
|
+Actually, all the data here only has one instance. However, for
|
||||||
|
+reasons of programming conformity, it is passed around as a pointer
|
||||||
|
+*/
|
||||||
|
+struct cf_mips_dev {
|
||||||
|
+ void *base; /* base address for I/O */
|
||||||
|
+ void *baddr; /* remapped address */
|
||||||
|
+
|
||||||
|
+ int pin; /* gpio pin */
|
||||||
|
+ int irq; /* gpio irq */
|
||||||
|
+
|
||||||
|
+ unsigned head;
|
||||||
|
+ unsigned cyl;
|
||||||
|
+ unsigned spt;
|
||||||
|
+ unsigned sectors;
|
||||||
|
+
|
||||||
|
+ unsigned short block_size;
|
||||||
|
+ unsigned dtype ; // ATA or CF
|
||||||
|
+ struct request_queue *queue;
|
||||||
|
+ struct gendisk *gd;
|
||||||
|
+
|
||||||
|
+ /* Transaction state */
|
||||||
|
+ enum trans_state tstate;
|
||||||
|
+ char *tbuf;
|
||||||
|
+ unsigned long tbuf_size;
|
||||||
|
+ sector_t tsect_start;
|
||||||
|
+ unsigned tsector_count;
|
||||||
|
+ unsigned tsectors_left;
|
||||||
|
+ int tread;
|
||||||
|
+ unsigned tcmd;
|
||||||
|
+ int async_mode;
|
||||||
|
+ unsigned long irq_enable_time;
|
||||||
|
+
|
||||||
|
+ struct request *active_req; /* A request is being carried out. Is that different from tstate? */
|
||||||
|
+ int users;
|
||||||
|
+ struct timer_list to_timer;
|
||||||
|
+ struct tasklet_struct tasklet;
|
||||||
|
+
|
||||||
|
+ /** This lock ensures that the requests to this device are all done
|
||||||
|
+ atomically. Transfers can run in parallel, requests are all queued
|
||||||
|
+ one-by-one */
|
||||||
|
+ spinlock_t lock;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
|
||||||
|
+ char* buffer, int is_write);
|
||||||
|
+int cf_init(struct cf_mips_dev* dev);
|
||||||
|
+void cf_cleanup(struct cf_mips_dev* dev);
|
||||||
|
+
|
||||||
|
+void cf_async_trans_done(struct cf_mips_dev* dev, int result);
|
||||||
|
+// void *cf_get_next_buf(unsigned long *buf_size);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff -urN linux.old/drivers/block/rb500/bdev.c linux.dev/drivers/block/rb500/bdev.c
|
||||||
|
--- linux.old/drivers/block/rb500/bdev.c 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ linux.dev/drivers/block/rb500/bdev.c 2006-06-15 16:29:04.000000000 +0200
|
||||||
|
@@ -0,0 +1,340 @@
|
||||||
|
+/* CF-mips driver
|
||||||
|
+ This is a block driver for the direct (mmaped) interface to the CF-slot,
|
||||||
|
+ found in Routerboard.com's RB532 board
|
||||||
|
+ See SDK provided from routerboard.com.
|
||||||
|
+
|
||||||
|
+ Module adapted By P.Christeas <p_christeas@yahoo.com>, 2005-6.
|
||||||
|
+ Cleaned up and adapted to platform_device by Felix Fietkau <nbd@openwrt.org>
|
||||||
|
+
|
||||||
|
+ This work is redistributed under the terms of the GNU General Public License.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/init.h>
|
||||||
|
+#include <linux/time.h>
|
||||||
|
+#include <linux/wait.h>
|
||||||
|
+#include <linux/fs.h>
|
||||||
|
+#include <linux/genhd.h>
|
||||||
|
+#include <linux/blkdev.h>
|
||||||
|
+#include <linux/blkpg.h>
|
||||||
|
+#include <linux/hdreg.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+
|
||||||
|
+#include <asm/uaccess.h>
|
||||||
|
+#include <asm/io.h>
|
||||||
|
+
|
||||||
|
+#include <asm/rc32434/rb.h>
|
||||||
|
+
|
||||||
|
+#ifdef DEBUG
|
||||||
|
+#define DEBUGP printk
|
||||||
|
+#define DLEVEL 1
|
||||||
|
+#else
|
||||||
|
+#define DEBUGP(format, args...)
|
||||||
|
+#define DLEVEL 0
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define CF_MIPS_MAJOR 13
|
||||||
|
+#define MAJOR_NR CF_MIPS_MAJOR
|
||||||
|
+#define CF_MAX_PART 16 /* max 15 partitions */
|
||||||
|
+
|
||||||
|
+#include "ata.h"
|
||||||
|
+
|
||||||
|
+//extern struct block_device_operations cf_bdops;
|
||||||
|
+
|
||||||
|
+// static struct hd_struct cf_parts[CF_MAX_PART];
|
||||||
|
+// static int cf_part_sizes[CF_MAX_PART];
|
||||||
|
+// static int cf_hsect_sizes[CF_MAX_PART];
|
||||||
|
+// static int cf_max_sectors[CF_MAX_PART];
|
||||||
|
+// static int cf_blksize_sizes[CF_MAX_PART];
|
||||||
|
+
|
||||||
|
+// static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
+
|
||||||
|
+// volatile int cf_busy = 0;
|
||||||
|
+
|
||||||
|
+static struct request *active_req = NULL;
|
||||||
|
+
|
||||||
|
+static int cf_open (struct inode *, struct file *);
|
||||||
|
+static int cf_release (struct inode *, struct file *);
|
||||||
|
+static int cf_ioctl (struct inode *, struct file *, unsigned, unsigned long);
|
||||||
|
+
|
||||||
|
+static void cf_request(request_queue_t * q);
|
||||||
|
+static int cf_transfer(const struct request *req);
|
||||||
|
+
|
||||||
|
+/*long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
|
||||||
|
+long (*compat_ioctl) (struct file *, unsigned, unsigned long);*/
|
||||||
|
+// int (*direct_access) (struct block_device *, sector_t, unsigned long *);
|
||||||
|
+// int (*media_changed) (struct gendisk *);
|
||||||
|
+// int (*revalidate_disk) (struct gendisk *);
|
||||||
|
+
|
||||||
|
+static struct block_device_operations cf_bdops = {
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .open = cf_open,
|
||||||
|
+ .release = cf_release,
|
||||||
|
+ .ioctl = cf_ioctl,
|
||||||
|
+ .media_changed = NULL,
|
||||||
|
+ .unlocked_ioctl = NULL,
|
||||||
|
+ .revalidate_disk = NULL,
|
||||||
|
+ .compat_ioctl = NULL,
|
||||||
|
+ .direct_access = NULL
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+int cf_mips_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct gendisk* cf_gendisk=NULL;
|
||||||
|
+ struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
|
||||||
|
+ struct cf_mips_dev *dev;
|
||||||
|
+ struct resource *r;
|
||||||
|
+ int reg_result;
|
||||||
|
+
|
||||||
|
+ reg_result = register_blkdev(MAJOR_NR, "cf-mips");
|
||||||
|
+ if (reg_result < 0) {
|
||||||
|
+ printk(KERN_WARNING "cf-mips: can't get major %d\n", MAJOR_NR);
|
||||||
|
+ return reg_result;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev = (struct cf_mips_dev *)kmalloc(sizeof(struct cf_mips_dev),GFP_KERNEL);
|
||||||
|
+ if (!dev)
|
||||||
|
+ goto out_err;
|
||||||
|
+ memset(dev, 0, sizeof(struct cf_mips_dev));
|
||||||
|
+ cdev->dev = dev;
|
||||||
|
+
|
||||||
|
+ dev->pin = cdev->gpio_pin;
|
||||||
|
+ dev->irq = platform_get_irq_byname(pdev, "cf_irq");
|
||||||
|
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cf_membase");
|
||||||
|
+ dev->base = (void *) r->start;
|
||||||
|
+
|
||||||
|
+ if (cf_init(dev)) goto out_err;
|
||||||
|
+ printk("init done");
|
||||||
|
+
|
||||||
|
+ spin_lock_init(&dev->lock);
|
||||||
|
+ dev->queue = blk_init_queue(cf_request,&dev->lock);
|
||||||
|
+ if (!dev->queue){
|
||||||
|
+ printk(KERN_ERR "cf-mips: no mem for queue\n");
|
||||||
|
+ goto out_err;
|
||||||
|
+ }
|
||||||
|
+ blk_queue_max_sectors(dev->queue,ATA_MAX_SECT_PER_CMD);
|
||||||
|
+
|
||||||
|
+ /* For memory devices, it is always better to avoid crossing segments
|
||||||
|
+ inside the same request. */
|
||||||
|
+/* if (dev->dtype==0x848A){
|
||||||
|
+ printk(KERN_INFO "Setting boundary for cf to 0x%x",(dev->block_size*512)-1);
|
||||||
|
+ blk_queue_segment_boundary(dev->queue, (dev->block_size*512)-1);
|
||||||
|
+ }*/
|
||||||
|
+
|
||||||
|
+ dev->gd = alloc_disk(CF_MAX_PART);
|
||||||
|
+ cf_gendisk = dev->gd;
|
||||||
|
+ cdev->gd = dev->gd;
|
||||||
|
+ if (!cf_gendisk) goto out_err; /* Last of these goto's */
|
||||||
|
+
|
||||||
|
+ cf_gendisk->major = MAJOR_NR;
|
||||||
|
+ cf_gendisk->first_minor = 0;
|
||||||
|
+ cf_gendisk->queue=dev->queue;
|
||||||
|
+ BUG_ON(cf_gendisk->minors != CF_MAX_PART);
|
||||||
|
+ strcpy(cf_gendisk->disk_name,"cfa");
|
||||||
|
+ strcpy(cf_gendisk->devfs_name,"cf/card0");
|
||||||
|
+ cf_gendisk->fops = &cf_bdops;
|
||||||
|
+ cf_gendisk->flags = 0 ; /* is not yet GENHD_FL_REMOVABLE */
|
||||||
|
+ cf_gendisk->private_data=dev;
|
||||||
|
+
|
||||||
|
+ set_capacity(cf_gendisk,dev->sectors * CF_KERNEL_MUL);
|
||||||
|
+
|
||||||
|
+ /* Let the disk go live */
|
||||||
|
+ add_disk(cf_gendisk);
|
||||||
|
+#if 0
|
||||||
|
+ result = cf_init();
|
||||||
|
+
|
||||||
|
+ /* default cfg for all partitions */
|
||||||
|
+ memset(cf_parts, 0, sizeof (cf_parts[0]) * CF_MAX_PART);
|
||||||
|
+ memset(cf_part_sizes, 0, sizeof (cf_part_sizes[0]) * CF_MAX_PART);
|
||||||
|
+ for (i = 0; i < CF_MAX_PART; ++i) {
|
||||||
|
+ cf_hsect_sizes[i] = CF_SECT_SIZE;
|
||||||
|
+ cf_max_sectors[i] = ATA_MAX_SECT_PER_CMD;
|
||||||
|
+ cf_blksize_sizes[i] = BLOCK_SIZE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* setup info for whole disk (partition 0) */
|
||||||
|
+ cf_part_sizes[0] = cf_sectors / 2;
|
||||||
|
+ cf_parts[0].nr_sects = cf_sectors;
|
||||||
|
+
|
||||||
|
+ blk_size[MAJOR_NR] = cf_part_sizes;
|
||||||
|
+ blksize_size[MAJOR_NR] = cf_blksize_sizes;
|
||||||
|
+ max_sectors[MAJOR_NR] = cf_max_sectors;
|
||||||
|
+ hardsect_size[MAJOR_NR] = cf_hsect_sizes;
|
||||||
|
+ read_ahead[MAJOR_NR] = 8; /* (4kB) */
|
||||||
|
+
|
||||||
|
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
|
||||||
|
+
|
||||||
|
+ add_gendisk(&cf_gendisk);
|
||||||
|
+#endif
|
||||||
|
+// printk(KERN_INFO "cf-mips partition check: \n");
|
||||||
|
+// register_disk(cf_gendisk, MKDEV(MAJOR_NR, 0), CF_MAX_PART,
|
||||||
|
+// &cf_bdops, dev->sectors);
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+out_err:
|
||||||
|
+ if (dev->queue){
|
||||||
|
+ blk_cleanup_queue(dev->queue);
|
||||||
|
+ }
|
||||||
|
+ if (reg_result) {
|
||||||
|
+ unregister_blkdev(MAJOR_NR, "cf-mips");
|
||||||
|
+ return reg_result;
|
||||||
|
+ }
|
||||||
|
+ if (dev){
|
||||||
|
+ cf_cleanup(dev);
|
||||||
|
+ kfree(dev);
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+cf_mips_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct cf_device *cdev = (struct cf_device *) pdev->dev.platform_data;
|
||||||
|
+ struct cf_mips_dev *dev = (struct cf_mips_dev *) cdev->dev;
|
||||||
|
+
|
||||||
|
+ unregister_blkdev(MAJOR_NR, "cf-mips");
|
||||||
|
+ blk_cleanup_queue(dev->queue);
|
||||||
|
+
|
||||||
|
+ del_gendisk(dev->gd);
|
||||||
|
+ cf_cleanup(dev);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static struct platform_driver cf_driver = {
|
||||||
|
+ .driver.name = "rb500-cf",
|
||||||
|
+ .probe = cf_mips_probe,
|
||||||
|
+ .remove = cf_mips_remove,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int __init cf_mips_init(void)
|
||||||
|
+{
|
||||||
|
+ printk(KERN_INFO "cf-mips module loaded\n");
|
||||||
|
+ return platform_driver_register(&cf_driver);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void cf_mips_cleanup(void)
|
||||||
|
+{
|
||||||
|
+ platform_driver_unregister(&cf_driver);
|
||||||
|
+ printk(KERN_INFO "cf-mips module removed\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+module_init(cf_mips_init);
|
||||||
|
+module_exit(cf_mips_cleanup);
|
||||||
|
+
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+MODULE_ALIAS_BLOCKDEV_MAJOR(CF_MIPS_MAJOR);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int cf_open(struct inode *inode, struct file *filp)
|
||||||
|
+{
|
||||||
|
+ struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
|
||||||
|
+ int minor = MINOR(inode->i_rdev);
|
||||||
|
+
|
||||||
|
+ if (minor >= CF_MAX_PART)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ //DEBUGP(KERN_INFO "cf-mips module opened, minor %d\n", minor);
|
||||||
|
+ spin_lock(&dev->lock);
|
||||||
|
+ dev->users++;
|
||||||
|
+ spin_unlock(&dev->lock);
|
||||||
|
+ filp->private_data=dev;
|
||||||
|
+
|
||||||
|
+ /* dirty workaround to set CFRDY GPIO as an input when some other
|
||||||
|
+ program sets it as an output */
|
||||||
|
+ gpio_set(CFG, (1 << dev->pin), 0);
|
||||||
|
+ return 0; /* success */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int cf_release(struct inode *inode, struct file *filp)
|
||||||
|
+{
|
||||||
|
+ int minor = MINOR(inode->i_rdev);
|
||||||
|
+ struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
|
||||||
|
+ spin_lock(&dev->lock);
|
||||||
|
+ dev->users--;
|
||||||
|
+ spin_unlock(&dev->lock);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int cf_ioctl(struct inode *inode, struct file *filp,
|
||||||
|
+ unsigned int cmd, unsigned long arg)
|
||||||
|
+{
|
||||||
|
+ unsigned minor = MINOR(inode->i_rdev);
|
||||||
|
+ struct cf_mips_dev *dev=inode->i_bdev->bd_disk->private_data;
|
||||||
|
+
|
||||||
|
+ DEBUGP(KERN_INFO "cf_ioctl cmd %u\n", cmd);
|
||||||
|
+ switch (cmd) {
|
||||||
|
+ case BLKRRPART: /* re-read partition table */
|
||||||
|
+ if (!capable(CAP_SYS_ADMIN))
|
||||||
|
+ return -EACCES;
|
||||||
|
+ printk(KERN_INFO "cf-mips partition check: \n");
|
||||||
|
+ register_disk(dev->gd);
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ case HDIO_GETGEO:
|
||||||
|
+ {
|
||||||
|
+ struct hd_geometry geo;
|
||||||
|
+ geo.cylinders = dev->cyl;
|
||||||
|
+ geo.heads = dev->head;
|
||||||
|
+ geo.sectors = dev->spt;
|
||||||
|
+ geo.start = (*dev->gd->part)[minor].start_sect;
|
||||||
|
+ if (copy_to_user((void *) arg, &geo, sizeof (geo)))
|
||||||
|
+ return -EFAULT;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -EINVAL; /* unknown command */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void cf_request(request_queue_t * q)
|
||||||
|
+{
|
||||||
|
+ struct cf_mips_dev* dev;
|
||||||
|
+
|
||||||
|
+ struct request * req;
|
||||||
|
+ int status;
|
||||||
|
+
|
||||||
|
+ /* We could have q->queuedata = dev , but haven't yet. */
|
||||||
|
+ if (active_req)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ while ((req=elv_next_request(q))!=NULL){
|
||||||
|
+ dev=req->rq_disk->private_data;
|
||||||
|
+ status=cf_transfer(req);
|
||||||
|
+ if (status==CF_TRANS_IN_PROGRESS){
|
||||||
|
+ active_req=req;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ end_request(req,status);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int cf_transfer(const struct request *req)
|
||||||
|
+{
|
||||||
|
+ struct cf_mips_dev* dev=req->rq_disk->private_data;
|
||||||
|
+
|
||||||
|
+ if (!blk_fs_request(req)){
|
||||||
|
+ if (printk_ratelimit())
|
||||||
|
+ printk(KERN_WARNING "cf-mips: skipping non-fs request 0x%x\n",req->cmd[0]);
|
||||||
|
+ return CF_TRANS_FAILED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return cf_do_transfer(dev,req->sector,req->current_nr_sectors,req->buffer,rq_data_dir(req));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void cf_async_trans_done(struct cf_mips_dev * dev,int result)
|
||||||
|
+{
|
||||||
|
+ struct request *req;
|
||||||
|
+
|
||||||
|
+ spin_lock(&dev->lock);
|
||||||
|
+ req=active_req;
|
||||||
|
+ active_req=NULL;
|
||||||
|
+ end_request(req,result);
|
||||||
|
+ spin_unlock(&dev->lock);
|
||||||
|
+
|
||||||
|
+ spin_lock(&dev->lock);
|
||||||
|
+ cf_request(dev->queue);
|
||||||
|
+ spin_unlock(&dev->lock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
diff -urN linux.old/drivers/block/rb500/Makefile linux.dev/drivers/block/rb500/Makefile
|
||||||
|
--- linux.old/drivers/block/rb500/Makefile 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ linux.dev/drivers/block/rb500/Makefile 2006-06-08 22:14:58.000000000 +0200
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+## Makefile for the RB532 CF port
|
||||||
|
+
|
||||||
|
+obj-y += bdev.o ata.o
|
||||||
|
diff -urN linux.old/drivers/Makefile linux.dev/drivers/Makefile
|
||||||
|
--- linux.old/drivers/Makefile 2006-06-08 20:20:52.000000000 +0200
|
||||||
|
+++ linux.dev/drivers/Makefile 2006-06-08 22:14:58.000000000 +0200
|
||||||
|
@@ -73,3 +73,4 @@
|
||||||
|
obj-y += firmware/
|
||||||
|
obj-$(CONFIG_CRYPTO) += crypto/
|
||||||
|
obj-$(CONFIG_SUPERH) += sh/
|
||||||
|
+obj-$(CONFIG_BLK_DEV_CF_MIPS) += block/rb500/
|
||||||
|
\ No newline at end of file
|
|
@ -0,0 +1,308 @@
|
||||||
|
diff -urN linux.old/fs/partitions/check.c linux.dev/fs/partitions/check.c
|
||||||
|
--- linux.old/fs/partitions/check.c 2006-05-31 02:31:44.000000000 +0200
|
||||||
|
+++ linux.dev/fs/partitions/check.c 2006-06-15 01:27:17.000000000 +0200
|
||||||
|
@@ -29,6 +29,7 @@
|
||||||
|
#include "ldm.h"
|
||||||
|
#include "mac.h"
|
||||||
|
#include "msdos.h"
|
||||||
|
+#include "openwrt.h"
|
||||||
|
#include "osf.h"
|
||||||
|
#include "sgi.h"
|
||||||
|
#include "sun.h"
|
||||||
|
@@ -48,6 +49,9 @@
|
||||||
|
* Probe partition formats with tables at disk address 0
|
||||||
|
* that also have an ADFS boot block at 0xdc0.
|
||||||
|
*/
|
||||||
|
+#ifdef CONFIG_OPENWRT_PARTITION
|
||||||
|
+ openwrt_partition,
|
||||||
|
+#endif
|
||||||
|
#ifdef CONFIG_ACORN_PARTITION_ICS
|
||||||
|
adfspart_check_ICS,
|
||||||
|
#endif
|
||||||
|
diff -urN linux.old/fs/partitions/Kconfig linux.dev/fs/partitions/Kconfig
|
||||||
|
--- linux.old/fs/partitions/Kconfig 2006-05-31 02:31:44.000000000 +0200
|
||||||
|
+++ linux.dev/fs/partitions/Kconfig 2006-06-15 01:27:17.000000000 +0200
|
||||||
|
@@ -14,6 +14,12 @@
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+config OPENWRT_PARTITION
|
||||||
|
+ bool "OpenWrt partition support" if PARTITION_ADVANCED
|
||||||
|
+ default y
|
||||||
|
+ help
|
||||||
|
+ Support the custom OpenWrt partition map
|
||||||
|
+
|
||||||
|
config ACORN_PARTITION
|
||||||
|
bool "Acorn partition support" if PARTITION_ADVANCED
|
||||||
|
default y if ARCH_ACORN
|
||||||
|
diff -urN linux.old/fs/partitions/Makefile linux.dev/fs/partitions/Makefile
|
||||||
|
--- linux.old/fs/partitions/Makefile 2006-05-31 02:31:44.000000000 +0200
|
||||||
|
+++ linux.dev/fs/partitions/Makefile 2006-06-15 01:27:17.000000000 +0200
|
||||||
|
@@ -11,6 +11,7 @@
|
||||||
|
obj-$(CONFIG_MAC_PARTITION) += mac.o
|
||||||
|
obj-$(CONFIG_LDM_PARTITION) += ldm.o
|
||||||
|
obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
|
||||||
|
+obj-$(CONFIG_OPENWRT_PARTITION) += openwrt.o
|
||||||
|
obj-$(CONFIG_OSF_PARTITION) += osf.o
|
||||||
|
obj-$(CONFIG_SGI_PARTITION) += sgi.o
|
||||||
|
obj-$(CONFIG_SUN_PARTITION) += sun.o
|
||||||
|
diff -urN linux.old/fs/partitions/openwrt.c linux.dev/fs/partitions/openwrt.c
|
||||||
|
--- linux.old/fs/partitions/openwrt.c 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ linux.dev/fs/partitions/openwrt.c 2006-06-15 01:27:17.000000000 +0200
|
||||||
|
@@ -0,0 +1,246 @@
|
||||||
|
+/*
|
||||||
|
+ * fs/partitions/openwrt.c
|
||||||
|
+ *
|
||||||
|
+ * Code extracted from drivers/block/genhd.c
|
||||||
|
+ * and fs/partitions/msdos.c
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
|
||||||
|
+ * Copyright (C) 1991-1998 Linus Torvalds
|
||||||
|
+ *
|
||||||
|
+ * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
|
||||||
|
+ * in the early extended-partition checks and added DM partitions
|
||||||
|
+ *
|
||||||
|
+ * Support for DiskManager v6.0x added by Mark Lord,
|
||||||
|
+ * with information provided by OnTrack. This now works for linux fdisk
|
||||||
|
+ * and LILO, as well as loadlin and bootln. Note that disks other than
|
||||||
|
+ * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
|
||||||
|
+ *
|
||||||
|
+ * More flexible handling of extended partitions - aeb, 950831
|
||||||
|
+ *
|
||||||
|
+ * Check partition table on IDE disks for common CHS translations
|
||||||
|
+ *
|
||||||
|
+ * Re-organised Feb 1998 Russell King
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/config.h>
|
||||||
|
+
|
||||||
|
+#include "check.h"
|
||||||
|
+#include "openwrt.h"
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Many architectures don't like unaligned accesses, while
|
||||||
|
+ * the nr_sects and start_sect partition table entries are
|
||||||
|
+ * at a 2 (mod 4) address.
|
||||||
|
+ */
|
||||||
|
+#include <asm/unaligned.h>
|
||||||
|
+
|
||||||
|
+#define SYS_IND(p) (get_unaligned(&p->sys_ind))
|
||||||
|
+#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
|
||||||
|
+ get_unaligned(&p->nr_sects); \
|
||||||
|
+ le32_to_cpu(__a); \
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
|
||||||
|
+ get_unaligned(&p->start_sect); \
|
||||||
|
+ le32_to_cpu(__a); \
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+static inline int is_extended_partition(struct partition *p)
|
||||||
|
+{
|
||||||
|
+ return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
|
||||||
|
+ SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
|
||||||
|
+ SYS_IND(p) == LINUX_EXTENDED_PARTITION);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define MSDOS_LABEL_MAGIC1 0x55
|
||||||
|
+#define MSDOS_LABEL_MAGIC2 0xAA
|
||||||
|
+
|
||||||
|
+static inline int
|
||||||
|
+msdos_magic_present(unsigned char *p)
|
||||||
|
+{
|
||||||
|
+ return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int
|
||||||
|
+openwrt_magic_present(unsigned char *p)
|
||||||
|
+{
|
||||||
|
+ return (p[0] == 'O' &&
|
||||||
|
+ p[1] == 'W' &&
|
||||||
|
+ p[2] == 'R' &&
|
||||||
|
+ p[3] == 'T');
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Create devices for each logical partition in an extended partition.
|
||||||
|
+ * The logical partitions form a linked list, with each entry being
|
||||||
|
+ * a partition table with two entries. The first entry
|
||||||
|
+ * is the real data partition (with a start relative to the partition
|
||||||
|
+ * table start). The second is a pointer to the next logical partition
|
||||||
|
+ * (with a start relative to the entire extended partition).
|
||||||
|
+ * We do not create a Linux partition for the partition tables, but
|
||||||
|
+ * only for the actual data partitions.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+parse_extended(struct parsed_partitions *state, struct block_device *bdev,
|
||||||
|
+ u32 first_sector, u32 first_size)
|
||||||
|
+{
|
||||||
|
+ struct partition *p;
|
||||||
|
+ Sector sect;
|
||||||
|
+ unsigned char *data;
|
||||||
|
+ u32 this_sector, this_size;
|
||||||
|
+ int sector_size = bdev_hardsect_size(bdev) / 512;
|
||||||
|
+ int loopct = 0; /* number of links followed
|
||||||
|
+ without finding a data partition */
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ this_sector = first_sector;
|
||||||
|
+ this_size = first_size;
|
||||||
|
+
|
||||||
|
+ while (1) {
|
||||||
|
+ if (++loopct > 100)
|
||||||
|
+ return;
|
||||||
|
+ if (state->next == state->limit)
|
||||||
|
+ return;
|
||||||
|
+ data = read_dev_sector(bdev, this_sector, §);
|
||||||
|
+ if (!data)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (!msdos_magic_present(data + 510))
|
||||||
|
+ goto done;
|
||||||
|
+
|
||||||
|
+ p = (struct partition *) (data + 0x1be);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Usually, the first entry is the real data partition,
|
||||||
|
+ * the 2nd entry is the next extended partition, or empty,
|
||||||
|
+ * and the 3rd and 4th entries are unused.
|
||||||
|
+ * However, DRDOS sometimes has the extended partition as
|
||||||
|
+ * the first entry (when the data partition is empty),
|
||||||
|
+ * and OS/2 seems to use all four entries.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * First process the data partition(s)
|
||||||
|
+ */
|
||||||
|
+ for (i=0; i<4; i++, p++) {
|
||||||
|
+ u32 offs, size, next;
|
||||||
|
+ if (!NR_SECTS(p) || is_extended_partition(p))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ /* Check the 3rd and 4th entries -
|
||||||
|
+ these sometimes contain random garbage */
|
||||||
|
+ offs = START_SECT(p)*sector_size;
|
||||||
|
+ size = NR_SECTS(p)*sector_size;
|
||||||
|
+ next = this_sector + offs;
|
||||||
|
+ if (i >= 2) {
|
||||||
|
+ if (offs + size > this_size)
|
||||||
|
+ continue;
|
||||||
|
+ if (next < first_sector)
|
||||||
|
+ continue;
|
||||||
|
+ if (next + size > first_sector + first_size)
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ put_partition(state, state->next, next, size);
|
||||||
|
+ if (SYS_IND(p) == LINUX_RAID_PARTITION)
|
||||||
|
+ state->parts[state->next].flags = 1;
|
||||||
|
+ loopct = 0;
|
||||||
|
+ if (++state->next == state->limit)
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+ /*
|
||||||
|
+ * Next, process the (first) extended partition, if present.
|
||||||
|
+ * (So far, there seems to be no reason to make
|
||||||
|
+ * parse_extended() recursive and allow a tree
|
||||||
|
+ * of extended partitions.)
|
||||||
|
+ * It should be a link to the next logical partition.
|
||||||
|
+ */
|
||||||
|
+ p -= 4;
|
||||||
|
+ for (i=0; i<4; i++, p++)
|
||||||
|
+ if (NR_SECTS(p) && is_extended_partition(p))
|
||||||
|
+ break;
|
||||||
|
+ if (i == 4)
|
||||||
|
+ goto done; /* nothing left to do */
|
||||||
|
+
|
||||||
|
+ this_sector = first_sector + START_SECT(p) * sector_size;
|
||||||
|
+ this_size = NR_SECTS(p) * sector_size;
|
||||||
|
+ put_dev_sector(sect);
|
||||||
|
+ }
|
||||||
|
+done:
|
||||||
|
+ put_dev_sector(sect);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev)
|
||||||
|
+{
|
||||||
|
+ int sector_size = bdev_hardsect_size(bdev) / 512;
|
||||||
|
+ Sector sect;
|
||||||
|
+ unsigned char *data;
|
||||||
|
+ struct partition *p;
|
||||||
|
+ int slot;
|
||||||
|
+ u32 last_block = 0;
|
||||||
|
+ u32 size = 0;
|
||||||
|
+ int firstfree = 5;
|
||||||
|
+
|
||||||
|
+ data = read_dev_sector(bdev, 0, §);
|
||||||
|
+ if (!data)
|
||||||
|
+ return -1;
|
||||||
|
+ if (!openwrt_magic_present(data)) {
|
||||||
|
+ printk("No OpenWrt partition table detected\n");
|
||||||
|
+ put_dev_sector(sect);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Now that the 55aa signature is present, this is probably
|
||||||
|
+ * either the boot sector of a FAT filesystem or a DOS-type
|
||||||
|
+ * partition table. Reject this in case the boot indicator
|
||||||
|
+ * is not 0 or 0x80.
|
||||||
|
+ */
|
||||||
|
+ p = (struct partition *) (data + 0x1be);
|
||||||
|
+ for (slot = 1; slot <= 4; slot++, p++) {
|
||||||
|
+ if (p->boot_ind != 0 && p->boot_ind != 0x80) {
|
||||||
|
+ put_dev_sector(sect);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p = (struct partition *) (data + 0x1be);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Look for partitions in two passes:
|
||||||
|
+ * First find the primary and DOS-type extended partitions.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ state->next = 6;
|
||||||
|
+ for (slot = 1 ; slot <= 4 ; slot++, p++) {
|
||||||
|
+ u32 start = START_SECT(p)*sector_size;
|
||||||
|
+ size = NR_SECTS(p)*sector_size;
|
||||||
|
+ if (!size) {
|
||||||
|
+ if (firstfree > slot)
|
||||||
|
+ firstfree = slot;
|
||||||
|
+
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (is_extended_partition(p)) {
|
||||||
|
+ /* prevent someone doing mkfs or mkswap on an
|
||||||
|
+ extended partition, but leave room for LILO */
|
||||||
|
+ last_block = start + size;
|
||||||
|
+ put_partition(state, slot, start, size == 1 ? 1 : 2);
|
||||||
|
+ printk(" <");
|
||||||
|
+ parse_extended(state, bdev, start, size);
|
||||||
|
+ printk(" >");
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ last_block = start + size;
|
||||||
|
+ put_partition(state, slot, start, size);
|
||||||
|
+ }
|
||||||
|
+ if (last_block + 1024 < (size = get_capacity(bdev->bd_disk)))
|
||||||
|
+ put_partition(state, firstfree, last_block, size - last_block);
|
||||||
|
+
|
||||||
|
+ printk("\n");
|
||||||
|
+
|
||||||
|
+ put_dev_sector(sect);
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
diff -urN linux.old/fs/partitions/openwrt.h linux.dev/fs/partitions/openwrt.h
|
||||||
|
--- linux.old/fs/partitions/openwrt.h 1970-01-01 01:00:00.000000000 +0100
|
||||||
|
+++ linux.dev/fs/partitions/openwrt.h 2006-06-15 01:27:17.000000000 +0200
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+/*
|
||||||
|
+ * fs/partitions/openwrt.h
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev);
|
||||||
|
+
|
|
@ -0,0 +1,48 @@
|
||||||
|
diff -ur linux.old/fs/jffs2/scan.c linux.dev/fs/jffs2/scan.c
|
||||||
|
--- linux.old/fs/jffs2/scan.c 2006-05-31 02:31:44.000000000 +0200
|
||||||
|
+++ linux.dev/fs/jffs2/scan.c 2006-06-15 02:20:32.000000000 +0200
|
||||||
|
@@ -120,8 +120,11 @@
|
||||||
|
/* reset summary info for next eraseblock scan */
|
||||||
|
jffs2_sum_reset_collected(s);
|
||||||
|
|
||||||
|
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
||||||
|
- buf_size, s);
|
||||||
|
+ if (c->flags & (1 << 7))
|
||||||
|
+ ret = BLK_STATE_ALLFF;
|
||||||
|
+ else
|
||||||
|
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
||||||
|
+ buf_size, s);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
@@ -222,6 +225,12 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (c->flags & (1 << 7)) {
|
||||||
|
+ printk("jffs2_scan_medium(): erasing all blocks after the end marker...\n");
|
||||||
|
+ jffs2_erase_pending_blocks(c, -1);
|
||||||
|
+ printk("jffs2_scan_medium(): done.\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (jffs2_sum_active() && s)
|
||||||
|
kfree(s);
|
||||||
|
|
||||||
|
@@ -389,6 +398,17 @@
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if ((buf[0] == 0xde) &&
|
||||||
|
+ (buf[1] == 0xad) &&
|
||||||
|
+ (buf[2] == 0xc0) &&
|
||||||
|
+ (buf[3] == 0xde)) {
|
||||||
|
+ /* end of filesystem. erase everything after this point */
|
||||||
|
+ printk("jffs2_scan_eraseblock(): End of filesystem marker found at 0x%x\n", jeb->offset);
|
||||||
|
+ c->flags |= (1 << 7);
|
||||||
|
+
|
||||||
|
+ return BLK_STATE_ALLFF;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
|
||||||
|
ofs = 0;
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
--- linux.old/arch/mips/pci/pci.c 2006-04-19 08:10:14.000000000 +0200
|
||||||
|
+++ linux.dev/arch/mips/pci/pci.c 2006-06-14 20:23:18.000000000 +0200
|
||||||
|
@@ -65,8 +65,10 @@
|
||||||
|
/*
|
||||||
|
* Put everything into 0x00-0xff region modulo 0x400
|
||||||
|
*/
|
||||||
|
+#ifndef CONFIG_MIKROTIK_RB500
|
||||||
|
if (start & 0x300)
|
||||||
|
start = (start + 0x3ff) & ~0x3ff;
|
||||||
|
+#endif
|
||||||
|
} else if (res->flags & IORESOURCE_MEM) {
|
||||||
|
/* Make sure we start at our min on all hoses */
|
||||||
|
if (start < PCIBIOS_MIN_MEM + hose->mem_resource->start)
|
46
openwrt/target/linux/rb532-2.6/patches/210-pci_fixes.patch
Normal file
46
openwrt/target/linux/rb532-2.6/patches/210-pci_fixes.patch
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
diff -urN linux.old/drivers/pci/probe.c linux.dev/drivers/pci/probe.c
|
||||||
|
--- linux.old/drivers/pci/probe.c 2006-06-08 20:21:20.000000000 +0200
|
||||||
|
+++ linux.dev/drivers/pci/probe.c 2006-06-08 20:19:40.000000000 +0200
|
||||||
|
@@ -760,15 +760,22 @@
|
||||||
|
u32 l;
|
||||||
|
u8 hdr_type;
|
||||||
|
int delay = 1;
|
||||||
|
-
|
||||||
|
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
|
||||||
|
- return NULL;
|
||||||
|
-
|
||||||
|
- /* some broken boards return 0 or ~0 if a slot is empty: */
|
||||||
|
- if (l == 0xffffffff || l == 0x00000000 ||
|
||||||
|
- l == 0x0000ffff || l == 0xffff0000)
|
||||||
|
- return NULL;
|
||||||
|
-
|
||||||
|
+ do {
|
||||||
|
+ if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
|
||||||
|
+ return NULL;
|
||||||
|
+ /* some broken boards return 0 or ~0 if a slot is empty: */
|
||||||
|
+ if (l == 0xffffffff || l == 0x00000000 ||
|
||||||
|
+ l == 0x0000ffff || l == 0xffff0000){
|
||||||
|
+ if (delay > 4)
|
||||||
|
+ return NULL;
|
||||||
|
+ /* But that could also be the previous dev not settled */
|
||||||
|
+ pr_debug("PCI: retrying scan at 0x%x, because config is 0x%x\n",devfn,l);
|
||||||
|
+ msleep(delay);
|
||||||
|
+ delay *=2;
|
||||||
|
+ l=0;
|
||||||
|
+ }
|
||||||
|
+ }while (l==0);
|
||||||
|
+
|
||||||
|
/* Configuration request Retry Status */
|
||||||
|
while (l == 0xffff0001) {
|
||||||
|
msleep(delay);
|
||||||
|
@@ -903,7 +910,10 @@
|
||||||
|
|
||||||
|
/* Go find them, Rover! */
|
||||||
|
for (devfn = 0; devfn < 0x100; devfn += 8)
|
||||||
|
+ {
|
||||||
|
+ if (bus->number == 0 && (devfn >> 3) > 21) break;
|
||||||
|
pci_scan_slot(bus, devfn);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After performing arch-dependent fixup of the bus, look behind
|
18
openwrt/target/linux/rb532-2.6/patches/220-serial_fix.patch
Normal file
18
openwrt/target/linux/rb532-2.6/patches/220-serial_fix.patch
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
diff -urN linux.old/drivers/serial/8250.c linux.dev/drivers/serial/8250.c
|
||||||
|
--- linux.old/drivers/serial/8250.c 2006-06-08 20:21:20.000000000 +0200
|
||||||
|
+++ linux.dev/drivers/serial/8250.c 2006-06-08 20:19:40.000000000 +0200
|
||||||
|
@@ -351,6 +351,13 @@
|
||||||
|
default:
|
||||||
|
outb(value, up->port.iobase + offset);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#if defined(CONFIG_IDT_EB434) || defined(CONFIG_MIKROTIK_RB500)
|
||||||
|
+ __SLOW_DOWN_IO;
|
||||||
|
+ __SLOW_DOWN_IO;
|
||||||
|
+ __SLOW_DOWN_IO;
|
||||||
|
+ __SLOW_DOWN_IO;
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
13
openwrt/target/linux/rb532-2.6/patches/230-dma_limit.patch
Normal file
13
openwrt/target/linux/rb532-2.6/patches/230-dma_limit.patch
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
diff -urN linux.old/arch/mips/mm/init.c linux.dev/arch/mips/mm/init.c
|
||||||
|
--- linux.old/arch/mips/mm/init.c 2006-06-08 20:21:20.000000000 +0200
|
||||||
|
+++ linux.dev/arch/mips/mm/init.c 2006-06-08 20:19:40.000000000 +0200
|
||||||
|
@@ -149,7 +149,7 @@
|
||||||
|
kmap_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||||
|
+ max_dma = virt_to_phys((char *) (256 * 1024 * 1024)) >> PAGE_SHIFT;
|
||||||
|
low = max_low_pfn;
|
||||||
|
high = highend_pfn;
|
||||||
|
|
||||||
|
|
13
openwrt/target/linux/rb532-2.6/patches/240-via_hack.patch
Normal file
13
openwrt/target/linux/rb532-2.6/patches/240-via_hack.patch
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
diff -urN linux.old/drivers/net/via-rhine.c linux.dev/drivers/net/via-rhine.c
|
||||||
|
--- linux.old/drivers/net/via-rhine.c 2006-06-08 20:21:20.000000000 +0200
|
||||||
|
+++ linux.dev/drivers/net/via-rhine.c 2006-06-08 20:19:40.000000000 +0200
|
||||||
|
@@ -142,7 +142,7 @@
|
||||||
|
These may be modified when a driver module is loaded. */
|
||||||
|
|
||||||
|
static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
|
||||||
|
-static int max_interrupt_work = 20;
|
||||||
|
+static int max_interrupt_work = 20000;
|
||||||
|
|
||||||
|
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
|
||||||
|
Setting to > 1518 effectively disables this feature. */
|
||||||
|
|
Loading…
Reference in a new issue