Port-amiga archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

IDE-doubler support (patch, testers wanted)



Attached is a patch to add support for 'standard' IDE-doublers to
NetBSD-current. Testers (both with IDE-doubler hardware and without) are
very much wanted, especially people with A4000s.

Please note that I don't know of a way to determine if IDE-doubler is
present or not on runtime - DO NOT TRY TO BOOT MISCONFIGURED KERNEL as
it will most probably hang, crash, burn and eat your breakfast.

Should probably add a boot flag to enable/disable this, as it would be
good if we could ship INSTALL/GENERIC kernels with the code in but
disabled by default. Of course if anyone can come up with a way to
determine if an IDE-doubler is present, that is even better.

There are some issues with this (because IDE-doubling on amiga is such
an *ugly* hack), I've seen my CD-ROM not get detected after a soft
reboot (probably left in somekinda interesting state and since we can't
reset the bus...).

I haven't really stresstested this more than checking that I can mount
CDs and md5sums match on the data read from CD, but I believe it should
work pretty reliably as long as you don't get a bus hang (we still can't
reset the bus).

Here's a dmesg for showoff purposes:

NetBSD 1.6L (FOOBAR) #0: Mon Jan 13 22:26:21 EET 2003
    
lonewolf%omoikane.cs-intra.net@localhost:/scratch/nb/idedoubler/src/sys/arch/amiga/compile/FOOBAR
Amiga 1200 (68060 rev.1 CPU/MMU/FPU)
total memory = 65536 KB
avail memory = 59496 KB
using 422 buffers containing 3376 KB of memory
memory segment 0 at 78000000 size 04000000
memory segment 1 at 00000000 size 00200000
mainbus0 (root)
clock0 at mainbus0: CIA B system hz 100 hardware hz 709379
Calibrating delay loop... 21/1024 us
a2kbbc0 at mainbus0
ser0 at mainbus0: input fifo 512 output fifo 32
par0 at mainbus0
kbd0 at mainbus0: CIA A type Amiga
ms0 at mainbus0
grfcc0 at mainbus0
grf0 at grfcc0: width 640 height 400 colors 4
ite0 at grf0: rows 50 cols 80 repeat at (30/100)s next at (10/100)s has keyboard
fdc0 at mainbus0: dmabuf pa 0x1de874: dmabuf ka 0x8d98874
fd0 at fdc0 unit 0: 3.5dd 80 cyl, 2 head, 11 sec [9 sec], 512 bytes/sec
wdc0 at mainbus0: Gayle IDE (A1200 style) with IDE-doubler
wd0 at wdc0 channel 0 drive 0: <Maxtor 2B020H1>
wd0: drive supports 16-sector PIO transfers, LBA addressing
wd0: 19541 MB, 16383 cyl, 16 head, 63 sec, 512 bytes/sect x 40020624 sectors
wd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 5 (Ultra/100)
wdc0: unable to reset (no aux registers)
atapibus0 at wdc0 channel 1: 2 targets
cd0 at atapibus0 drive 1: <MEMOREX  CD-MAXX52, MT1198 B Firmware, MB1.0> cdrom 
removable
cd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 2 (Ultra/33)
wdc0: unable to reset (no aux registers)
zbus0 at mainbus0
bzivsc at zbus0: pa 0xea0000 man/pro 8512/17 not configured
4 views configured
root on wd0a dumps on wd0b
root file system type: ffs

-- 
Ilpo Ruotsalainen - <lonewolf%iki.fi@localhost> - http://www.iki.fi/lonewolf/
Index: sys/dev/ic/wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.120
diff --unified -r1.120 wdc.c
--- sys/dev/ic/wdc.c    2003/01/01 00:10:19     1.120
+++ sys/dev/ic/wdc.c    2003/01/13 20:36:05
@@ -228,29 +228,35 @@
 
        if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
                chp->wdc->select(chp,0);
-       /* assert SRST, wait for reset to complete */
-       bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
-           WDSD_IBM);
-       delay(10);
-       bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
-           WDCTL_RST | WDCTL_IDS); 
-       DELAY(1000);
-       bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
-           WDCTL_IDS);
-       delay(1000);
-       (void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
-       bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
-       delay(10);
-
-       ret_value = __wdcwait_reset(chp, ret_value);
-       WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n",
-           chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", chp->channel,
-           ret_value), DEBUG_PROBE);
-
-       /* if reset failed, there's nothing here */
-       if (ret_value == 0)
-               return 0;
 
+       if (chp->wdc && ((chp->wdc->cap & WDC_CAPABILITY_NO_AUX) == 0))
+       {
+               /* assert SRST, wait for reset to complete */
+               bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
+                               WDSD_IBM);
+               delay(10);
+               bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
+                               WDCTL_RST | WDCTL_IDS); 
+               DELAY(1000);
+               bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
+                               WDCTL_IDS);
+               delay(1000);
+               (void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
+               bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
+                               WDCTL_4BIT);
+               delay(10);
+
+               ret_value = __wdcwait_reset(chp, ret_value);
+               WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n",
+                               chp->wdc ? chp->wdc->sc_dev.dv_xname :
+                               "wdcprobe",
+                               chp->channel, ret_value), DEBUG_PROBE);
+
+               /* if reset failed, there's nothing here */
+               if (ret_value == 0)
+                       return 0;
+       }
+
        /*
         * Test presence of drives. First test register signatures looking for
         * ATAPI devices. If it's not an ATAPI and reset said there may be
@@ -759,6 +765,13 @@
        int verb;
 {
        int drv_mask1, drv_mask2;
+
+       if (chp->wdc->cap & WDC_CAPABILITY_NO_AUX)
+       {
+               printf("%s: unable to reset (no aux registers)\n",
+                               chp->wdc->sc_dev.dv_xname);
+               return 1;
+       }
 
        if (chp->wdc->cap & WDC_CAPABILITY_SELECT)
                chp->wdc->select(chp,0);
Index: sys/dev/ic/wdcvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdcvar.h,v
retrieving revision 1.34
diff --unified -r1.34 wdcvar.h
--- sys/dev/ic/wdcvar.h 2002/01/13 17:24:29     1.34
+++ sys/dev/ic/wdcvar.h 2003/01/13 20:36:05
@@ -103,6 +103,7 @@
 #define WDC_CAPABILITY_SINGLE_DRIVE 0x0800 /* Don't probe second drive */
 #define WDC_CAPABILITY_NOIRQ  0x1000   /* Controller never interrupts */
 #define WDC_CAPABILITY_SELECT  0x2000  /* Controller selects target */
+#define WDC_CAPABILITY_NO_AUX 0x4000   /* Controller doesn't have aux ports */
        u_int8_t      PIO_cap; /* highest PIO mode supported */
        u_int8_t      DMA_cap; /* highest DMA mode supported */
        u_int8_t      UDMA_cap; /* highest UDMA mode supported */
Index: sys/arch/amiga/dev/wdc_amiga.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amiga/dev/wdc_amiga.c,v
retrieving revision 1.10
diff --unified -r1.10 wdc_amiga.c
--- sys/arch/amiga/dev/wdc_amiga.c      2002/10/02 04:55:53     1.10
+++ sys/arch/amiga/dev/wdc_amiga.c      2003/01/13 20:36:05
@@ -59,14 +59,21 @@
 #include <dev/ata/atavar.h>
 #include <dev/ic/wdcvar.h>
 
+#include "opt_idedoubler.h"
+
+#ifdef IDEDOUBLER
+#define NUM_CHANNELS 2
+#else
+#define NUM_CHANNELS 1
+#endif
+
 struct wdc_amiga_softc {
-       struct wdc_softc sc_wdcdev;
-       struct  channel_softc *wdc_chanptr;
-       struct  channel_softc wdc_channel;
-       struct isr sc_isr;
+       struct  wdc_softc sc_wdcdev;
+       struct  channel_softc *wdc_chanptrs[NUM_CHANNELS];
+       struct  channel_softc wdc_channels[NUM_CHANNELS];
+       struct  isr sc_isr;
        volatile u_char *sc_intreg;
-       struct bus_space_tag cmd_iot;
-       struct bus_space_tag ctl_iot;
+       struct  bus_space_tag sc_iot;
        char    sc_a1200;
 };
 
@@ -89,51 +96,83 @@
 wdc_amiga_attach(struct device *parent, struct device *self, void *aux)
 {
        struct wdc_amiga_softc *sc = (void *)self;
+       int i;
 
-       printf("\n");
+       printf(": Gayle IDE");
 
        if (is_a4000()) {
-               sc->cmd_iot.base = (u_long)ztwomap(0xdd2020 + 2);
+               printf(" (A4000 style)");
+               sc->sc_iot.base = (u_long)ztwomap(0xdd2020 + 2);
                sc->sc_intreg = (u_char *)ztwomap(0xdd2020 + 0x1000);
                sc->sc_a1200 = 0;
        } else {
-               sc->cmd_iot.base = (u_long) ztwomap(0xda0000 + 2);
-               sc->ctl_iot.base = (u_long) ztwomap(0xda4000);
+               printf(" (A1200 style)");
+               sc->sc_iot.base = (u_long) ztwomap(0xda0000 + 2);
                gayle_init();
                sc->sc_intreg = &gayle.intreq;
                sc->sc_a1200 = 1;
        }
-       sc->cmd_iot.absm = sc->ctl_iot.absm = &amiga_bus_stride_4swap;
-       sc->wdc_channel.cmd_iot = &sc->cmd_iot;
-       sc->wdc_channel.ctl_iot = &sc->ctl_iot;
-
-       if (bus_space_map(sc->wdc_channel.cmd_iot, 0, 0x40, 0,
-                         &sc->wdc_channel.cmd_ioh)) {
-               printf("%s: couldn't map registers\n",
-                   sc->sc_wdcdev.sc_dev.dv_xname);
+       sc->sc_iot.absm = &amiga_bus_stride_4swap;
+
+       if (bus_space_map(&sc->sc_iot,
+             0, 0x40, 0, &sc->wdc_channels[0].cmd_ioh))
+       {
+               printf("%s: could not map registers\n",
+                               sc->sc_wdcdev.sc_dev.dv_xname);
                return;
        }
 
-       if (sc->sc_a1200)
-               sc->wdc_channel.ctl_ioh = sc->ctl_iot.base;
-       else if (bus_space_subregion(sc->wdc_channel.cmd_iot,
-           sc->wdc_channel.cmd_ioh, 0x406, 1, &sc->wdc_channel.ctl_ioh))
+#ifndef IDEDOUBLER
+       printf("\n");
+       
+       sc->wdc_channels[0].cmd_iot = sc->wdc_channels[0].ctl_iot = &sc->sc_iot;
+
+       if (bus_space_subregion(sc->wdc_channels[0].cmd_iot,
+                               sc->wdc_channels[0].cmd_ioh,
+                               0x406, 1, &sc->wdc_channels[0].ctl_ioh))
+       {
+               printf("%s: could not map registers\n",
+                               sc->sc_wdcdev.sc_dev.dv_xname);
                return;
+       }
 
        sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16;
+#else
+       printf(" with IDE-doubler\n");
+
+       sc->wdc_channels[0].cmd_iot = sc->wdc_channels[1].cmd_iot = &sc->sc_iot;
+
+       if (bus_space_subregion(sc->wdc_channels[0].cmd_iot,
+                               sc->wdc_channels[0].cmd_ioh,
+                               0x400, 0x40, &sc->wdc_channels[1].cmd_ioh))
+       {
+               printf("%s: could not map registers\n",
+                               sc->sc_wdcdev.sc_dev.dv_xname);
+               return;
+       }
+
+       sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_NO_AUX;
+#endif
+
        sc->sc_wdcdev.PIO_cap = 0;
-       sc->wdc_chanptr = &sc->wdc_channel;
-       sc->sc_wdcdev.channels = &sc->wdc_chanptr;
-       sc->sc_wdcdev.nchannels = 1;
-       sc->wdc_channel.channel = 0;
-       sc->wdc_channel.wdc = &sc->sc_wdcdev;
-       sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
-           M_DEVBUF, M_NOWAIT);
-       if (sc->wdc_channel.ch_queue == NULL) {
-           printf("%s: can't allocate memory for command queue",
-               sc->sc_wdcdev.sc_dev.dv_xname);
-           return;
+       sc->sc_wdcdev.channels = sc->wdc_chanptrs;
+       sc->sc_wdcdev.nchannels = NUM_CHANNELS;
+
+       for (i=0; i<NUM_CHANNELS; i++)
+       {
+               sc->wdc_channels[i].channel = i;
+               sc->wdc_channels[i].wdc = &sc->sc_wdcdev;
+               sc->wdc_channels[i].ch_queue = malloc(
+                   sizeof(struct channel_queue), M_DEVBUF, M_NOWAIT);
+               if (sc->wdc_channels[i].ch_queue == NULL) {
+                       printf("%s: can't allocate memory for command queue",
+                                       sc->sc_wdcdev.sc_dev.dv_xname);
+                       return;
+               }
+
+               sc->wdc_chanptrs[i] = &sc->wdc_channels[i];
        }
+
        sc->sc_isr.isr_intr = wdc_amiga_intr;
        sc->sc_isr.isr_arg = sc;
        sc->sc_isr.isr_ipl = 2;
@@ -142,7 +181,8 @@
        if (sc->sc_a1200)
                gayle.intena |= GAYLE_INT_IDE;
 
-       wdcattach(&sc->wdc_channel);
+       for (i=0; i<NUM_CHANNELS; i++)
+               wdcattach(&sc->wdc_channels[i]);
 }
 
 int
@@ -150,12 +190,24 @@
 {
        struct wdc_amiga_softc *sc = (struct wdc_amiga_softc *)arg;
        u_char intreq = *sc->sc_intreg;
-       int ret = 0;
+       int i;
+       int ret = 0, chanret;
 
        if (intreq & GAYLE_INT_IDE) {
                if (sc->sc_a1200)
                        gayle.intreq = 0x7c | (intreq & 0x03);
-               ret = wdcintr(&sc->wdc_channel);
+
+               for (i=0; i<NUM_CHANNELS; i++)
+               {
+                       chanret = wdcintr(&sc->wdc_channels[i]);
+
+                       if (chanret == 0)
+                               ;
+                       else if (chanret == 1)
+                               ret = 1;
+                       else if (ret == 0)
+                               ret = chanret;
+               }
        }
 
        return ret;
Index: sys/arch/amiga/conf/files.amiga
===================================================================
RCS file: /cvsroot/src/sys/arch/amiga/conf/files.amiga,v
retrieving revision 1.127
diff --unified -r1.127 files.amiga
--- sys/arch/amiga/conf/files.amiga     2002/11/03 02:29:38     1.127
+++ sys/arch/amiga/conf/files.amiga     2003/01/13 20:36:06
@@ -29,6 +29,8 @@
 defflag                                P5PPC68KBOARD
 defflag                                LEV6_DEFER
 
+defflag                                IDEDOUBLER
+
 defparam                       IOBZCLOCK
 
 device mainbus {}


Home | Main Index | Thread Index | Old Index