[PATCH] 2.4 IDE driver code for m68k

Geert Uytterhoeven (geert@linux-m68k.org)
Sun, 13 Apr 2003 15:05:13 +0200


IDE driver and architecture specific updates for m68k:
- Atari Falcon IDE: Add falconide_intr_lock
- Amiga A1200/A4000 Gayle IDE: Set hwif->mmio = 2 to prevent the generic IDE
code from messing with resources
- Q40 IDE: Fix resource handling, so the interface shows up in /proc/ioports
while we do use MMIO ops (from Richard Zidlicky)
- ide_ioreg_t is unsigned long
- Always use MMIO IDE operations, since so far no single m68k platform uses
ISA/PCI I/O space for IDE.
- Make ide_{get,release}_lock() handling completely Atari Falcon-specific
- Define ide_ack_intr() and set IDE_ARCH_ACK_INTR

--- linux-2.4.21-pre7/drivers/ide/legacy/falconide.c Thu Feb 27 10:15:46 2003
+++ linux-m68k-2.4.21-pre7/drivers/ide/legacy/falconide.c Sun Mar 30 22:22:40 2003
@@ -49,6 +49,14 @@


/*
+ * falconide_intr_lock is used to obtain access to the IDE interrupt,
+ * which is shared between several drivers.
+ */
+
+int falconide_intr_lock;
+
+
+ /*
* Probe for a Falcon IDE interface
*/

--- linux-2.4.21-pre7/drivers/ide/legacy/gayle.c Thu Feb 27 10:15:46 2003
+++ linux-m68k-2.4.21-pre7/drivers/ide/legacy/gayle.c Sun Mar 30 22:22:40 2003
@@ -125,6 +125,7 @@
ide_ioreg_t base, ctrlport, irqport;
ide_ack_intr_t *ack_intr;
hw_regs_t hw;
+ ide_hwif_t *hwif;
int index;
unsigned long phys_base, res_start, res_n;

@@ -154,11 +155,12 @@

ide_setup_ports(&hw, base, gayle_offsets,
ctrlport, irqport, ack_intr,
-// gaule_iops,
+// &gayle_iops,
IRQ_AMIGA_PORTS);

- index = ide_register_hw(&hw, NULL);
+ index = ide_register_hw(&hw, &hwif);
if (index != -1) {
+ hwif->mmio = 2;
switch (i) {
case 0:
printk("ide%d: Gayle IDE interface (A%d style)\n", index,
--- linux-2.4.21-pre7/drivers/ide/legacy/q40ide.c Thu Feb 27 10:15:46 2003
+++ linux-m68k-2.4.21-pre7/drivers/ide/legacy/q40ide.c Wed Apr 9 14:41:28 2003
@@ -31,7 +31,7 @@
#define PCIDE_BASE5 0x1e0
#define PCIDE_BASE6 0x160

-static const q40ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = {
+static const ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = {
PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5,
PCIDE_BASE6 */
};
@@ -41,23 +41,21 @@
* Offsets from one of the above bases
*/

+/* used to do addr translation here but it is easier to do in setup ports */
+/*#define IDE_OFF_B(x) ((unsigned long)Q40_ISA_IO_B((IDE_##x##_OFFSET)))*/

-/* HD_DATA was redefined in asm-m68k/ide.h */
-#undef HD_DATA
-#define HD_DATA 0x1f0
-
-
-#define PCIDE_REG(x) ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1))
+#define IDE_OFF_B(x) ((ide_ioreg_t)((IDE_##x##_OFFSET)))
+#define IDE_OFF_W(x) ((ide_ioreg_t)((IDE_##x##_OFFSET)))

static const int pcide_offsets[IDE_NR_PORTS] = {
- PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR),
- PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS),
- PCIDE_REG(CMD)
+ IDE_OFF_W(DATA), IDE_OFF_B(ERROR), IDE_OFF_B(NSECTOR), IDE_OFF_B(SECTOR),
+ IDE_OFF_B(LCYL), IDE_OFF_B(HCYL), 6 /*IDE_OFF_B(CURRENT)*/, IDE_OFF_B(STATUS),
+ 518/*IDE_OFF(CMD)*/
};

-static int q40ide_default_irq(q40ide_ioreg_t base)
+static int q40ide_default_irq(ide_ioreg_t base)
{
- switch (base) {
+ switch (base) {
case 0x1f0: return 14;
case 0x170: return 15;
case 0x1e8: return 11;
@@ -67,14 +65,58 @@
}


+/*
+ * This is very similar to ide_setup_ports except that addresses
+ * are pretranslated for q40 ISA access
+ */
+void q40_ide_setup_ports ( hw_regs_t *hw,
+ ide_ioreg_t base, int *offsets,
+ ide_ioreg_t ctrl, ide_ioreg_t intr,
+ ide_ack_intr_t *ack_intr,
+/*
+ * ide_io_ops_t *iops,
+ */
+ int irq)
+{
+ int i;

- /*
- * Probe for Q40 IDE interfaces
- */
+ for (i = 0; i < IDE_NR_PORTS; i++) {
+ /* BIG FAT WARNING:
+ assumption: only DATA port is ever used in 16 bit mode */
+ if ( i==0 )
+ hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]);
+ else
+ hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]);
+ }
+
+ hw->irq = irq;
+ hw->dma = NO_DMA;
+ hw->ack_intr = ack_intr;
+/*
+ * hw->iops = iops;
+ */
+}
+
+
+
+/*
+ * the static array is needed to have the name reported in /proc/ioports,
+ * hwif->name unfortunately isnīt available yet
+ */
+static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
+ "ide0", "ide1"
+};
+
+/*
+ * Probe for Q40 IDE interfaces
+ */

void q40ide_init(void)
{
int i;
+ ide_hwif_t *hwif;
+ int index;
+ const char *name;

if (!MACH_IS_Q40)
return ;
@@ -82,12 +124,27 @@
for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
hw_regs_t hw;

- ide_setup_ports(&hw,(ide_ioreg_t) pcide_bases[i], (int *)pcide_offsets,
- pcide_bases[i]+0x206,
- 0, NULL,
-// pcide_iops,
+ name = q40_ide_names[i];
+ if (!request_region(pcide_bases[i], 8, name)) {
+ printk("could not reserve ports %lx-%lx for %s\n",
+ pcide_bases[i],pcide_bases[i]+8,name);
+ continue;
+ }
+ if (!request_region(pcide_bases[i]+0x206, 1, name)) {
+ printk("could not reserve port %lx for %s\n",
+ pcide_bases[i]+0x206,name);
+ release_region(pcide_bases[i], 8);
+ continue;
+ }
+ q40_ide_setup_ports(&hw, (ide_ioreg_t)pcide_bases[i],
+ (int *)pcide_offsets,
+ (ide_ioreg_t)pcide_bases[i]+0x206, 0, NULL,
+// m68kide_iops,
q40ide_default_irq(pcide_bases[i]));
- ide_register_hw(&hw, NULL);
+ index = ide_register_hw(&hw, &hwif);
+ // **FIXME**
+ if (index != -1)
+ hwif->mmio = 2;
}
}

--- linux-2.4.21-pre7/include/asm-m68k/hdreg.h Fri Dec 20 13:21:32 2002
+++ linux-m68k-2.4.21-pre7/include/asm-m68k/hdreg.h Sun Mar 30 22:22:40 2003
@@ -7,8 +7,6 @@
#ifndef _M68K_HDREG_H
#define _M68K_HDREG_H

-typedef unsigned int q40ide_ioreg_t;
-typedef unsigned char * ide_ioreg_t;
-//typedef unsigned long ide_ioreg_t;
+typedef unsigned long ide_ioreg_t;

#endif /* _M68K_HDREG_H */
--- linux-2.4.21-pre7/include/asm-m68k/ide.h Fri Dec 20 13:21:32 2002
+++ linux-m68k-2.4.21-pre7/include/asm-m68k/ide.h Sun Mar 30 22:22:40 2003
@@ -50,9 +50,6 @@
#define MAX_HWIFS 4 /* same as the other archs */
#endif

-/*
- * FIXME: IOPS struct calls needed for taskfile.
- */

static __inline__ int ide_default_irq(ide_ioreg_t base)
{
@@ -69,7 +66,9 @@
* Set up a hw structure for a specified data port, control port and IRQ.
* This should follow whatever the default interface uses.
*/
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
+ ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
{
if (data_port || ctrl_port)
printk("ide_init_hwif_ports: must not be called\n");
@@ -83,170 +82,94 @@
{
}

-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *device, void *dev_id)
-{
-#ifdef CONFIG_AMIGA
- if (MACH_IS_AMIGA)
- return request_irq(irq, handler, 0, device, dev_id);
-#endif /* CONFIG_AMIGA */
-#ifdef CONFIG_Q40
- if (MACH_IS_Q40)
- return request_irq(irq, handler, 0, device, dev_id);
-#endif /* CONFIG_Q40*/
-#ifdef CONFIG_MAC
- if (MACH_IS_MAC)
- return request_irq(irq, handler, 0, device, dev_id);
-#endif /* CONFIG_MAC */
- return 0;
-}
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-#ifdef CONFIG_AMIGA
- if (MACH_IS_AMIGA)
- free_irq(irq, dev_id);
-#endif /* CONFIG_AMIGA */
-#ifdef CONFIG_Q40
- if (MACH_IS_Q40)
- free_irq(irq, dev_id);
-#endif /* CONFIG_Q40*/
-#ifdef CONFIG_MAC
- if (MACH_IS_MAC)
- free_irq(irq, dev_id);
-#endif /* CONFIG_MAC */
-}
-
/*
- * We should really implement those some day.
- */
-static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
-{
- return 0;
-}
-
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
-{
-#ifdef CONFIG_Q40
- if (MACH_IS_Q40)
- request_region((q40ide_ioreg_t)from,extent,name);
-#endif
-}
-
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
-{
-#ifdef CONFIG_Q40
- if (MACH_IS_Q40)
- release_region((q40ide_ioreg_t)from,extent);
-#endif
-}
-
-#undef SUPPORT_SLOW_DATA_PORTS
-#define SUPPORT_SLOW_DATA_PORTS 0
-
-#undef SUPPORT_VLB_SYNC
-#define SUPPORT_VLB_SYNC 0
-
-/* this definition is used only on startup .. */
-#undef HD_DATA
-#define HD_DATA NULL
-
-
-/*
- * get rid of defs from io.h
- * ide still has some private and conflicting versions
+ * Get rid of defs from io.h - ide has its private and conflicting versions
+ * Since so far no single m68k platform uses ISA/PCI I/O space for IDE, we
+ * always use the `raw' MMIO versions
*/
+#undef inb
+#undef inw
#undef insw
+#undef inl
#undef insl
+#undef outb
+#undef outw
#undef outsw
+#undef outl
#undef outsl
-
-
-/*
- * define IO method and translation,
- * so far only Q40 has ide-if on ISA
- */
-#ifndef CONFIG_Q40
-
-#define ADDR_TRANS_B(_addr_) (_addr_)
-#define ADDR_TRANS_W(_addr_) (_addr_)
-#define ADDR_TRANS_L(_addr_) (_addr_)
-
-#else
-
-#define ADDR_TRANS_B(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_B(_addr_)) : (_addr_))
-#define ADDR_TRANS_W(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_W(_addr_)) : (_addr_))
-#define ADDR_TRANS_L(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_L(_addr_)) : (_addr_))
-#endif
-
-#define HAVE_ARCH_OUT_BYTE 1
-
-#define OUT_BYTE(v,p) out_8(ADDR_TRANS_B((p)), (v))
-#define OUT_WORD(v,p) out_be16(ADDR_TRANS_W((p)), (v))
-#define OUT_LONG(v,p) out_be32(ADDR_TRANS_L((p)), (v))
-
-#define HAVE_ARCH_IN_BYTE 1
-
-#define IN_BYTE(p) in_8(ADDR_TRANS_B((p)))
-#define IN_WORD(p) in_be16(ADDR_TRANS_W((p)))
-#define IN_LONG(p) in_be32(ADDR_TRANS_L((p)))
-
-#define insw(port, buf, nr) raw_insw(ADDR_TRANS_W(port), buf, nr)
-#define outsw(port, buf, nr) raw_outsw(ADDR_TRANS_W(port), buf, nr)
-
-#define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1)
-#define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1)
-
-
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+
+#define inb in_8
+#define inw in_be16
+#define insw(port, addr, n) raw_insw((u16 *)port, addr, n)
+#define inl in_be32
+#define insl(port, addr, n) raw_insl((u32 *)port, addr, n)
+#define outb(val, port) out_8(port, val)
+#define outw(val, port) out_be16(port, val)
+#define outsw(port, addr, n) raw_outsw((u16 *)port, addr, n)
+#define outl(val, port) out_be32(port, val)
+#define outsl(port, addr, n) raw_outsl((u32 *)port, addr, n)
+#define readb in_8
+#define readw in_be16
+#define __ide_mm_insw(port, addr, n) raw_insw((u16 *)port, addr, n)
+#define readl in_be32
+#define __ide_mm_insl(port, addr, n) raw_insl((u32 *)port, addr, n)
+#define writeb(val, port) out_8(port, val)
+#define writew(val, port) out_be16(port, val)
+#define __ide_mm_outsw(port, addr, n) raw_outsw((u16 *)port, addr, n)
+#define writel(val, port) out_be32(port, val)
+#define __ide_mm_outsl(port, addr, n) raw_outsl((u32 *)port, addr, n)
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
-
-#define insl_swapw(data_reg, buffer, wcount) \
- insw_swapw(data_reg, buffer, (wcount)<<1)
-#define outsl_swapw(data_reg, buffer, wcount) \
- outsw_swapw(data_reg, buffer, (wcount)<<1)
-
-#define insw_swapw(port, buf, nr) raw_insw_swapw(ADDR_TRANS_W(port), buf, nr)
-#define outsw_swapw(port, buf, nr) raw_outsw_swapw(ADDR_TRANS_W(port),buf,nr)
-
-#endif /* CONFIG_ATARI || CONFIG_Q40 */
+#define insw_swapw(port, addr, n) raw_insw_swapw((u16 *)port, addr, n)
+#define outsw_swapw(port, addr, n) raw_outsw_swapw((u16 *)port, addr, n)
+#endif


-/* Q40 and Atari have byteswapped IDE bus and since many interesting
+/* Q40 and Atari have byteswapped IDE busses and since many interesting
* values in the identification string are text, chars and words they
- * happened to be almost correct without swapping.. However *_capacity
+ * happened to be almost correct without swapping.. However *_capacity
* is needed for drives over 8 GB. RZ */
#if defined(CONFIG_Q40) || defined(CONFIG_ATARI)
#define M68K_IDE_SWAPW (MACH_IS_Q40 || MACH_IS_ATARI)
#endif

-#ifdef CONFIG_ATARI
-#define IDE_ARCH_LOCK 1
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+#define IDE_ARCH_LOCK
+
+extern int falconide_intr_lock;

-static __inline__ void ide_release_lock (int *ide_lock)
+static __inline__ void ide_release_lock(void)
{
if (MACH_IS_ATARI) {
- if (*ide_lock == 0) {
+ if (falconide_intr_lock == 0) {
printk("ide_release_lock: bug\n");
return;
}
- *ide_lock = 0;
+ falconide_intr_lock = 0;
stdma_release();
}
}

-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
+static __inline__ void ide_get_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
{
if (MACH_IS_ATARI) {
- if (*ide_lock == 0) {
+ if (falconide_intr_lock == 0) {
if (in_interrupt() > 0)
panic( "Falcon IDE hasn't ST-DMA lock in interrupt" );
stdma_lock(handler, data);
- *ide_lock = 1;
+ falconide_intr_lock = 1;
}
}
}
-#endif /* CONFIG_ATARI */
+#endif /* CONFIG_BLK_DEV_FALCON_IDE */

-#endif /* __KERNEL__ */
+#define IDE_ARCH_ACK_INTR
+#define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)

+#endif /* __KERNEL__ */
#endif /* _M68K_IDE_H */

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/