I'm trying to get this into 5.0 (I know its late, but life's tough)

This brings ATA support to the PC98 arch will all bells and whistles.

I want to thank the PC98 core team for getting me a PC98 machine
to do this work on, without that it would probably newer have happend..

Please get back to me with any success/failures on this ASAP...

Enjoy!


Index: sys/conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.738
diff -u -r1.738 files
--- sys/conf/files      28 Nov 2002 01:17:48 -0000      1.738
+++ sys/conf/files      28 Nov 2002 20:01:52 -0000
@@ -290,6 +290,7 @@
 dev/asr/asr.c          optional asr pci
 dev/ata/ata-all.c      optional ata
 dev/ata/ata-isa.c      optional ata isa
+dev/ata/ata-cbus.c     optional ata pc98
 dev/ata/ata-card.c     optional ata card
 dev/ata/ata-card.c     optional ata pccard
 dev/ata/ata-pci.c      optional ata pci
Index: sys/dev/ata/ata-all.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v
retrieving revision 1.158
diff -u -r1.158 ata-all.c
--- sys/dev/ata/ata-all.c       7 Nov 2002 22:23:46 -0000       1.158
+++ sys/dev/ata/ata-all.c       31 Oct 2002 18:32:25 -0000
@@ -134,7 +134,9 @@
                   (int)rman_get_start(ch->r_altio),
                   (ch->r_bmio) ? (int)rman_get_start(ch->r_bmio) : 0);
 
+    ch->lock_func(ch, ATA_LF_LOCK);
     ata_reset(ch);
+    ch->lock_func(ch, ATA_LF_UNLOCK);
 
     ch->device[MASTER].channel = ch;
     ch->device[MASTER].unit = ATA_MASTER;
@@ -186,6 +188,7 @@
      * otherwise attach what the probe has found in ch->devices.
      */
     if (!ata_delayed_attach) {
+       ch->lock_func(ch, ATA_LF_LOCK);
        if (ch->devices & ATA_ATA_SLAVE)
            if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
                ch->devices &= ~ATA_ATA_SLAVE;
@@ -213,6 +216,7 @@
 #ifdef DEV_ATAPICAM
        atapi_cam_attach_bus(ch);
 #endif
+       ch->lock_func(ch, ATA_LF_UNLOCK);
     }
     return 0;
 }
@@ -228,6 +232,7 @@
        return ENXIO;
 
     /* make sure channel is not busy */
+    ch->lock_func(ch, ATA_LF_LOCK);
     ATA_SLEEPLOCK_CH(ch, ATA_CONTROL);
 
     s = splbio();
@@ -274,13 +279,23 @@
     ch->r_bmio = NULL;
     ch->r_irq = NULL;
     ATA_UNLOCK_CH(ch);
+    ch->lock_func(ch, ATA_LF_UNLOCK);
     return 0;
 }
 
 int
 ata_resume(device_t dev)
 {
-    return ata_reinit(device_get_softc(dev));
+    struct ata_channel *ch;
+    int error;
+
+    if (!dev || !(ch = device_get_softc(dev)))
+       return ENXIO;
+
+    ch->lock_func(ch, ATA_LF_LOCK);
+    error = ata_reinit(ch);
+    ch->lock_func(ch, ATA_LF_UNLOCK);
+    return error;
 }
 
 static int
@@ -313,9 +328,10 @@
        case ATAREINIT:
            if (!device || !(ch = device_get_softc(device)))
                return ENXIO;
+           ch->lock_func(ch, ATA_LF_LOCK);
            ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE);
-           if ((error = ata_reinit(ch)))
-               ATA_UNLOCK_CH(ch);
+           error = ata_reinit(ch);
+           ch->lock_func(ch, ATA_LF_UNLOCK);
            return error;
 
        case ATAGMODE:
@@ -339,6 +355,7 @@
            if (!device || !(ch = device_get_softc(device)))
                return ENXIO;
 
+           ch->lock_func(ch, ATA_LF_LOCK);
            if ((iocmd->device == MASTER || iocmd->device == -1) &&
                iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) {
                ata_change_mode(&ch->device[MASTER],iocmd->u.mode.mode[MASTER]);
@@ -354,6 +371,7 @@
            }
            else
                iocmd->u.mode.mode[SLAVE] = -1;
+           ch->lock_func(ch, ATA_LF_UNLOCK);
            return 0;
 
        case ATAGPARM:
@@ -386,6 +404,7 @@
            if (!device || !(ch = device_get_softc(device)))
                return ENXIO;
 
+           ch->lock_func(ch, ATA_LF_LOCK);
            ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE);
            
            if (iocmd->device == SLAVE)
@@ -399,6 +418,7 @@
            id2 = ata_drawersensor(atadev, 0, 0x4f, 0);
            if (id1 != 0xa3 || id2 != 0x5c) {
                ATA_UNLOCK_CH(ch);
+               ch->lock_func(ch, ATA_LF_UNLOCK);
                return ENXIO;
            }
 
@@ -419,6 +439,7 @@
            iocmd->u.enclosure.v12 = ata_drawersensor(atadev, 0, 0x24, 0) * 61;
 
            ATA_UNLOCK_CH(ch);
+           ch->lock_func(ch, ATA_LF_UNLOCK);
            return 0;
        }
 
@@ -547,6 +568,7 @@
     for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
        if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
            continue;
+       ch->lock_func(ch, ATA_LF_LOCK);
        if (ch->devices & ATA_ATA_SLAVE)
            if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
                ch->devices &= ~ATA_ATA_SLAVE;
@@ -559,6 +581,7 @@
        if (ch->devices & ATA_ATAPI_MASTER)
            if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY))
                ch->devices &= ~ATA_ATAPI_MASTER;
+       ch->lock_func(ch, ATA_LF_UNLOCK);
     }
 
 #ifdef DEV_ATADISK
@@ -566,10 +589,12 @@
     for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
        if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
            continue;
+       ch->lock_func(ch, ATA_LF_LOCK);
        if (ch->devices & ATA_ATA_MASTER)
            ad_attach(&ch->device[MASTER]);
        if (ch->devices & ATA_ATA_SLAVE)
            ad_attach(&ch->device[SLAVE]);
+       ch->lock_func(ch, ATA_LF_UNLOCK);
     }
     ata_raid_attach();
 #endif
@@ -577,6 +602,7 @@
     for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
        if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
            continue;
+       ch->lock_func(ch, ATA_LF_LOCK);
 #if DEV_ATAPIALL
        if (ch->devices & ATA_ATAPI_MASTER)
            atapi_attach(&ch->device[MASTER]);
@@ -586,6 +612,7 @@
 #ifdef DEV_ATAPICAM
        atapi_cam_attach_bus(ch);
 #endif
+       ch->lock_func(ch, ATA_LF_UNLOCK);
     }
 }
 
@@ -598,7 +625,7 @@
      * device or our twin ATA channel, so call ch->intr_func to figure 
      * out if it is really an interrupt we should process here
      */
-    if (ch->intr_func && ch->intr_func(ch))
+    if (!ch->intr_func(ch))
        return;
 
     /* if drive is busy it didn't interrupt */
@@ -638,14 +665,20 @@
        return;
     }
 
+    if (ch->active & ATA_WAIT_INTR) {
+       ATA_UNLOCK_CH(ch);
+       return;
+    }
+
     if ((ch->flags & ATA_QUEUED) &&
        ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_SERVICE) { 
        ATA_FORCELOCK_CH(ch, ATA_ACTIVE);
        if (ata_service(ch) == ATA_OP_CONTINUES)
            return;
     }
-    ATA_UNLOCK_CH(ch);
     ch->running = NULL;
+    ATA_UNLOCK_CH(ch);
+    ch->lock_func(ch, ATA_LF_UNLOCK);
     ata_start(ch);
     return;
 }
@@ -661,6 +694,7 @@
 #endif
     int s;
 
+    ch->lock_func(ch, ATA_LF_LOCK);
     if (!ATA_LOCK_CH(ch, ATA_ACTIVE))
        return;
 
@@ -703,6 +737,7 @@
     }
 #endif
     ATA_UNLOCK_CH(ch);
+    ch->lock_func(ch, ATA_LF_UNLOCK);
     splx(s);
 }
 
@@ -841,10 +876,13 @@
 {
     int devices, misdev, newdev;
 
-    if (!ch->r_io || !ch->r_altio || !ch->r_irq)
+    ATA_FORCELOCK_CH(ch, ATA_CONTROL);
+
+    if (!ch->r_io || !ch->r_altio || !ch->r_irq) {
+       ATA_UNLOCK_CH(ch);
        return ENXIO;
+    }
 
-    ATA_FORCELOCK_CH(ch, ATA_CONTROL);
     ch->running = NULL;
     devices = ch->devices;
     ata_printf(ch, -1, "resetting devices ..\n");
@@ -1262,7 +1300,7 @@
     ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE);
     ata_dmainit(atadev, pmode, wmode, umode);
     ATA_UNLOCK_CH(atadev->channel);
-    ata_start(atadev->channel); /* XXX SOS */
+    ata_start(atadev->channel);
 }
 
 int
Index: sys/dev/ata/ata-all.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-all.h,v
retrieving revision 1.54
diff -u -r1.54 ata-all.h
--- sys/dev/ata/ata-all.h       1 Oct 2002 15:21:57 -0000       1.54
+++ sys/dev/ata/ata-all.h       31 Oct 2002 18:32:25 -0000
@@ -112,6 +112,7 @@
 #define ATA_ALTSTAT                    0x00    /* alternate status register */
 #define ATA_ALTOFFSET                  0x206   /* alternate registers offset */
 #define ATA_PCCARD_ALTOFFSET           0x0e    /* do for PCCARD devices */
+#define ATA_PC98_ALTOFFSET             0x10c   /* do for PC98 devices */
 #define                ATA_A_IDS               0x02    /* disable interrupts */
 #define                ATA_A_RESET             0x04    /* RESET controller */
 #define                ATA_A_4BIT              0x08    /* 4 head bits */
@@ -119,9 +120,11 @@
 /* misc defines */
 #define ATA_PRIMARY                    0x1f0
 #define ATA_SECONDARY                  0x170
+#define        ATA_PC98_BANK                   0x432
 #define ATA_IOSIZE                     0x08
 #define ATA_ALTIOSIZE                  0x01
 #define ATA_BMIOSIZE                   0x08
+#define        ATA_PC98_BANKIOSIZE             0x01
 #define ATA_OP_FINISHED                        0x00
 #define ATA_OP_CONTINUES               0x01
 #define ATA_IOADDR_RID                 0
@@ -223,7 +226,7 @@
 
     u_int8_t                   status;         /* last controller status */
     u_int8_t                   error;          /* last controller error */
-    int                                active;         /* active processing request */
+    int                                active;         /* ATA channel state control */
 #define                ATA_IDLE                0x0000
 #define                ATA_IMMEDIATE           0x0001
 #define                ATA_WAIT_INTR           0x0002
@@ -234,6 +237,10 @@
 #define                ATA_ACTIVE_ATAPI        0x0040
 #define                ATA_CONTROL             0x0080
 
+    void (*lock_func)(struct ata_channel *, int);/* controller lock function */
+#define                ATA_LF_LOCK             0x0001
+#define                ATA_LF_UNLOCK           0x0002
+
     TAILQ_HEAD(, ad_request)   ata_queue;      /* head of ATA queue */
     TAILQ_HEAD(, atapi_request) atapi_queue;   /* head of ATAPI queue */
     void                       *running;       /* currently running request */
@@ -253,7 +260,6 @@
 int ata_attach(device_t);
 int ata_detach(device_t);
 int ata_resume(device_t);
-
 void ata_start(struct ata_channel *);
 void ata_reset(struct ata_channel *);
 int ata_reinit(struct ata_channel *);
@@ -283,18 +289,16 @@
 int ata_dmadone(struct ata_device *);
 
 /* macros for locking a channel */
-#define ATA_LOCK_CH(ch, value)\
+#define ATA_LOCK_CH(ch, value) \
        atomic_cmpset_int(&(ch)->active, ATA_IDLE, (value))
 
-#define ATA_SLEEPLOCK_CH(ch, value)\
-       while (!atomic_cmpset_int(&(ch)->active, ATA_IDLE, (value)))\
+#define ATA_SLEEPLOCK_CH(ch, value) \
+       while (!atomic_cmpset_int(&(ch)->active, ATA_IDLE, (value))) \
            tsleep((caddr_t)&(ch), PRIBIO, "atalck", 1);
 
-#define ATA_FORCELOCK_CH(ch, value)\
-       (ch)->active = value;
+#define ATA_FORCELOCK_CH(ch, value) (ch)->active = value
 
-#define ATA_UNLOCK_CH(ch)\
-       (ch)->active = ATA_IDLE
+#define ATA_UNLOCK_CH(ch) (ch)->active = ATA_IDLE
 
 /* macros to hide busspace uglyness */
 #define ATA_INB(res, offset) \
Index: sys/dev/ata/ata-disk.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-disk.c,v
retrieving revision 1.136
diff -u -r1.136 ata-disk.c
--- sys/dev/ata/ata-disk.c      20 Sep 2002 19:35:56 -0000      1.136
+++ sys/dev/ata/ata-disk.c      31 Oct 2002 18:32:25 -0000
@@ -123,7 +123,13 @@
     adp->heads = atadev->param->heads;
     adp->sectors = atadev->param->sectors;
     adp->total_secs = atadev->param->cylinders * adp->heads * adp->sectors;    
-    adp->max_iosize = 256 * DEV_BSIZE;
+#ifdef PC98
+    if (adp->total_secs < 17 * 8 * 65536) {
+       adp->sectors = 17;
+       adp->heads = 8;
+    }
+#endif
+
     bioq_init(&adp->queue);
 
     lbasize = (u_int32_t)atadev->param->lba_size_1 |
@@ -183,6 +189,8 @@
     else
        ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1);
 
+    adp->max_iosize = 256 * DEV_BSIZE;
+
     /* use tagged queueing if allowed and supported */
     if (ata_tags && ad_tagsupported(adp)) {
        adp->num_tags = atadev->param->queuelen;
@@ -276,10 +284,12 @@
 {
     struct ad_softc *adp = dev->si_drv1;
 
+    adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK);
     ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL);
     if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
        ata_prtdev(adp->device, "flushing cache on close failed\n");
     ATA_UNLOCK_CH(adp->device->channel);
+    adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK);
     return 0;
 }
 
@@ -312,7 +322,9 @@
     if (!once) {
        /* force PIO mode for dumps */
        adp->device->mode = ATA_PIO;
+       adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK);
        ata_reinit(adp->device->channel);
+       adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK);
        once = 1;
     }
 
Index: sys/dev/ata/ata-dma.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-dma.c,v
retrieving revision 1.105
diff -u -r1.105 ata-dma.c
--- sys/dev/ata/ata-dma.c       1 Oct 2002 15:21:08 -0000       1.105
+++ sys/dev/ata/ata-dma.c       29 Nov 2002 20:09:19 -0000
@@ -1259,6 +1259,148 @@
        atadev->mode = ATA_PIO0 + apiomode;
        return;
 
+    case 0x00091191:   /* Acard ATP865R controller */
+    case 0x00081191:   /* Acard ATP865 controller */
+       if (ATAPI_DEVICE(atadev))
+           break;
+       if (udmamode >= 6) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up UDMA6 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+               
+               reg44 &= ~(0x000f << (devno << 2));
+               reg44 |= (0x0007 << (devno << 2));
+               pci_write_config(parent, 0x44, reg44, 2);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + devno, 0x031, 1);
+               ata_dmacreate(atadev, apiomode, ATA_UDMA6);
+               return;
+           }
+       }
+       if (udmamode >= 5) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up UDMA5 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+               
+               reg44 &= ~(0x000f << (devno << 2));
+               reg44 |= (0x0006 << (devno << 2));
+               pci_write_config(parent, 0x44, reg44, 2);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + devno, 0x031, 1);
+               ata_dmacreate(atadev, apiomode, ATA_UDMA5);
+               return;
+           }
+       }
+       /* FALLTHROUGH */
+
+    case 0x00071191:   /* Acard ATP860R controller */
+    case 0x00061191:   /* Acard ATP860 controller */
+       if (ATAPI_DEVICE(atadev))
+           break;
+       if (udmamode >= 4) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up UDMA4 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+               
+               reg44 &= ~(0x000f << (devno << 2));
+               reg44 |= (0x0005 << (devno << 2));
+               pci_write_config(parent, 0x44, reg44, 2);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + devno, 0x031, 1);
+               ata_dmacreate(atadev, apiomode, ATA_UDMA4);
+               return;
+           }
+       }
+       if (udmamode >= 2) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up UDMA2 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+               
+               reg44 &= ~(0x000f << (devno << 2));
+               reg44 |= (0x0003 << (devno << 2));
+               pci_write_config(parent, 0x44, reg44, 2);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + devno, 0x031, 1);
+               ata_dmacreate(atadev, apiomode, ATA_UDMA2);
+               return;
+           }
+       }
+       if (wdmamode >= 2 && apiomode >= 4) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up WDMA2 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+               
+               reg44 &= ~(0x000f << (devno << 2));
+               pci_write_config(parent, 0x44, reg44, 2);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + devno, 0x031, 1);
+               ata_dmacreate(atadev, apiomode, ATA_WDMA2);
+               return;
+           }
+       }
+       /* we could set PIO mode timings, but we assume the BIOS did that */
+       break;
+
+    case 0x00051191:   /* Acard ATP850UF controller */
+       if (ATAPI_DEVICE(atadev))
+           break;
+       if (udmamode >= 2) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up UDMA2 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int8_t reg54 = pci_read_config(parent, 0x54, 1);
+               
+               reg54 |= (0x03 << (devno << 1));
+               pci_write_config(parent, 0x54, reg54, 1);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
+               ata_dmacreate(atadev, apiomode, ATA_UDMA2);
+               return;
+           }
+       }
+       if (wdmamode >= 2 && apiomode >= 4) {
+           error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+                               ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
+           if (bootverbose)
+               ata_prtdev(atadev, "%s setting up WDMA2 mode on Acard chip\n",
+                          (error) ? "failed" : "success");
+           if (!error) {
+               u_int8_t reg54 = pci_read_config(parent, 0x54, 1);
+               
+               reg54 &= ~(0x03 << (devno << 1));
+               pci_write_config(parent, 0x54, reg54, 1);
+               pci_write_config(parent, 0x4a, 0xa6, 1);
+               pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
+               ata_dmacreate(atadev, apiomode, ATA_WDMA2);
+               return;
+           }
+       }
+       /* we could set PIO mode timings, but we assume the BIOS did that */
+       break;
+
     case 0x000116ca:   /* Cenatek Rocket Drive controller */
        if (wdmamode >= 0 &&
            (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & 
Index: sys/dev/ata/ata-isa.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-isa.c,v
retrieving revision 1.9
diff -u -r1.9 ata-isa.c
--- sys/dev/ata/ata-isa.c       20 Sep 2002 18:08:57 -0000      1.9
+++ sys/dev/ata/ata-isa.c       31 Oct 2002 18:32:25 -0000
@@ -53,6 +53,17 @@
 };
 
 static int
+ata_isa_intrnoop(struct ata_channel *ch)
+{
+    return 1;
+
+}
+static void
+ata_isa_locknoop(struct ata_channel *ch, int type)
+{
+}
+
+static int
 ata_isa_probe(device_t dev)
 {
     struct ata_channel *ch = device_get_softc(dev);
@@ -80,6 +91,8 @@
     bus_release_resource(dev, SYS_RES_IOPORT, rid, io);
     ch->unit = 0;
     ch->flags |= ATA_USE_16BIT;
+    ch->intr_func = ata_isa_intrnoop;
+    ch->lock_func = ata_isa_locknoop;
     return ata_probe(dev);
 }
 
Index: sys/dev/ata/ata-pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-pci.c,v
retrieving revision 1.50
diff -u -r1.50 ata-pci.c
--- sys/dev/ata/ata-pci.c       8 Oct 2002 18:25:10 -0000       1.50
+++ sys/dev/ata/ata-pci.c       29 Nov 2002 20:06:16 -0000
@@ -52,6 +52,7 @@
     int bmaddr;
     struct resource *irq;
     int irqcnt;
+    int lock;
 };
 
 /* misc defines */
@@ -314,10 +315,25 @@
     case 0x00081103:
        switch (pci_get_revid(dev)) {
        case 0x07:
+           if (pci_get_function(dev) == 0)
+               return "HighPoint HPT374 ATA133 controller (channel 0+1)";
+           if (pci_get_function(dev) == 1)
+               return "HighPoint HPT374 ATA133 controller (channel 2+3)";
            return "HighPoint HPT374 ATA133 controller";
        }
        return NULL;
 
+    case 0x00051191:
+       return "Acard ATP850UF ATA-33 controller";
+
+    case 0x00061191:
+    case 0x00071191:
+       return "Acard ATP860 ATA-66 controller";
+
+    case 0x00081191:
+    case 0x00091191:
+       return "Acard ATP865 ATA-133 controller";
+
     case 0x000116ca:
        return "Cenatek Rocket Drive controller";
 
@@ -354,17 +370,14 @@
 static int
 ata_pci_add_child(device_t dev, int unit)
 {
-    device_t child;
-
     /* check if this is located at one of the std addresses */
     if (ATA_MASTERDEV(dev)) {
-       if (!(child = device_add_child(dev, "ata", unit)))
+       if (!device_add_child(dev, "ata", unit))
            return ENOMEM;
     }
     else {
-       if (!(child =
-             device_add_child(dev, "ata",
-                              devclass_find_free_unit(ata_devclass, 2))))
+       if (!device_add_child(dev, "ata",
+                             devclass_find_free_unit(ata_devclass, 2)))
            return ENOMEM;
     }
     return 0;
@@ -539,6 +552,7 @@
                             SYS_RES_IOPORT, rid, controller->bmio);
        controller->bmio = NULL;
     }
+    controller->lock = -1;
 
     /*
      * the Cypress chip is a mess, it contains two ATA functions, but 
@@ -574,16 +588,16 @@
     case 0x00081103:   /* HighPoint HPT374 */
        if (((dmastat = ata_dmastatus(ch)) &
            (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != ATA_BMSTAT_INTERRUPT)
-           return 1;
+           return 0;
        ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT);
        DELAY(1);
-       return 0;
+       return 1;
 
     case 0x06481095:   /* CMD 648 */
     case 0x06491095:   /* CMD 649 */
        if (!(pci_read_config(device_get_parent(ch->dev), 0x71, 1) &
              (ch->unit ? 0x08 : 0x04)))
-           return 1;
+           return 0;
        break;
 
     case 0x4d33105a:   /* Promise Ultra/Fasttrak 33 */
@@ -593,7 +607,7 @@
     case 0x4d30105a:   /* Promise Ultra/Fasttrak 100 */
        if (!(ATA_INL(ch->r_bmio, (ch->unit ? 0x14 : 0x1c)) &
              (ch->unit ? 0x00004000 : 0x00000400)))
-           return 1;
+           return 0;
        break;
 
     case 0x4d68105a:   /* Promise TX2 ATA100 */
@@ -604,17 +618,70 @@
     case 0x7275105a:   /* Promise TX2 ATA133 */
        ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b);
        if (!(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x20))
-           return 1;
+           return 0;
        break;
+
+    case 0x00051191:   /* Acard ATP850UF */
+       {
+           struct ata_pci_controller *scp =
+               device_get_softc(device_get_parent(ch->dev));
+
+           if (ch->unit != scp->lock)
+               return 0;
+       }
+       /* FALLTHROUGH */
+
+    case 0x00061191:   /* Acard ATP860 */
+    case 0x00071191:   /* Acard ATP860R */
+    case 0x00081191:   /* Acard ATP865 */
+    case 0x00091191:   /* Acard ATP865R */
+       if (ch->flags & ATA_DMA_ACTIVE) {
+           if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT))
+               return 0;
+           ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT);
+           DELAY(1);
+           ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT,
+                    ATA_INB(ch->r_bmio, ATA_BMCMD_PORT)&~ATA_BMCMD_START_STOP);
+           DELAY(1);
+       }
+       return 1;
     }
 
     if (ch->flags & ATA_DMA_ACTIVE) {
        if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT))
-           return 1;
+           return 0;
        ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT);
        DELAY(1);
     }
-    return 0;
+    return 1;
+}
+
+static void
+ata_pci_locknoop(struct ata_channel *ch, int type)
+{
+}
+
+static void
+ata_pci_serialize(struct ata_channel *ch, int flags)
+{
+    struct ata_pci_controller *scp =
+       device_get_softc(device_get_parent(ch->dev));
+
+    switch (flags) {
+    case ATA_LF_LOCK:
+       if (scp->lock == ch->unit)
+           break;
+       while (!atomic_cmpset_int(&scp->lock, -1, ch->unit))
+           tsleep((caddr_t)ch->lock_func, PRIBIO, "atalck", 1);
+       break;
+
+    case ATA_LF_UNLOCK:
+       if (scp->lock == -1 || scp->lock != ch->unit)
+           break;
+       scp->lock = -1;
+       break;
+    }
+    return;
 }
 
 static int
@@ -864,8 +931,16 @@
            ch->unit = i;
     }
     free(children, M_TEMP);
-    ch->chiptype = pci_get_devid(device_get_parent(dev));
+
     ch->intr_func = ata_pci_intr;
+    ch->chiptype = pci_get_devid(device_get_parent(dev));
+    switch (ch->chiptype) {
+    case 0x00051191:
+       ch->lock_func = ata_pci_serialize;
+       break;
+    default:
+       ch->lock_func = ata_pci_locknoop;
+    }
     return ata_probe(dev);
 }
 
Index: sys/pc98/conf/GENERIC
===================================================================
RCS file: /home/ncvs/src/sys/pc98/conf/GENERIC,v
retrieving revision 1.220
diff -u -r1.220 GENERIC
--- sys/pc98/conf/GENERIC       31 Oct 2002 12:14:05 -0000      1.220
+++ sys/pc98/conf/GENERIC       27 Nov 2002 10:06:46 -0000
@@ -78,11 +78,18 @@
 # Floppy drives
 device         fdc
 
-# IDE controller and disks
-device         wdc     1
+# ATA and ATAPI devices
+device         ata
+device         atadisk                 # ATA disk drives
+device         atapicd                 # ATAPI CDROM drives
+device         atapifd                 # ATAPI floppy drives
+device         atapist                 # ATAPI tape drives
+options                ATA_STATIC_ID           # Static device numbering
 
+# IDE controller and disks
+#device                wdc     1
 # ATAPI devices on wdc
-device         wcd     1       #IDE CD-ROM
+#device                wcd     1       #IDE CD-ROM
 #device                wfd     1       #IDE Floppy (e.g. LS-120)
 #device                wst     1       #IDE Tape (e.g. Travan)
 
--- /dev/null   Fri Nov 29 21:35:31 2002
+++ sys/dev/ata/ata-cbus.c      Thu Oct 31 19:32:25 2002
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 2002 Søren Schmidt <[EMAIL PROTECTED]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_ata.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <isa/isavar.h>
+#include <dev/ata/ata-all.h>
+
+/* local vars */
+static bus_addr_t ata_pc98_ports[] = {
+    0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe
+};
+
+struct ata_cbus_controller {
+    struct resource *io;
+    struct resource *altio;
+    struct resource *bankio;
+    struct resource *irq;
+    int current_bank;
+};
+
+static int
+ata_cbus_probe(device_t dev)
+{
+    struct resource *io;
+    int rid;
+    u_long tmp;
+
+    /* allocate the ioport range */
+    rid = ATA_IOADDR_RID;
+    io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports,
+                            ATA_IOSIZE, RF_ACTIVE);
+    if (!io)
+       return ENOMEM;
+    isa_load_resourcev(io, ata_pc98_ports, ATA_IOSIZE);
+
+    /* calculate & set the altport range */
+    rid = ATA_IOADDR_RID + ATA_IOSIZE + 1;
+    if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &tmp, &tmp)) {
+       bus_set_resource(dev, SYS_RES_IOPORT, rid,
+                        rman_get_start(io)+ATA_PC98_ALTOFFSET, ATA_ALTIOSIZE);
+    }
+
+    /* calculate & set the bank range */
+    rid = ATA_IOADDR_RID + ATA_IOSIZE + ATA_ALTIOSIZE + 1;
+    if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &tmp, &tmp)) {
+       bus_set_resource(dev, SYS_RES_IOPORT, rid,
+                        ATA_PC98_BANK, ATA_PC98_BANKIOSIZE);
+    }
+
+    bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
+    return 0;
+}
+
+static int
+ata_cbus_attach(device_t dev)
+{
+    struct ata_cbus_controller *scp = device_get_softc(dev);
+    int rid;
+
+    /* allocate resources */
+    rid = ATA_IOADDR_RID;
+    scp->io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports,
+                                 ATA_IOSIZE, RF_ACTIVE);
+    if (!scp->io)
+       return ENOMEM;
+    isa_load_resourcev(scp->io, ata_pc98_ports, ATA_IOSIZE);
+
+    rid = ATA_IOADDR_RID + ATA_IOSIZE + 1;
+    scp->altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+                                   rman_get_start(scp->io)+ATA_PC98_ALTOFFSET,
+                                   ~0, ATA_ALTIOSIZE, RF_ACTIVE);
+    if (!scp->altio)
+       return ENOMEM;
+
+    rid = ATA_IOADDR_RID + ATA_IOSIZE + ATA_ALTIOSIZE + 1;
+    scp->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+                                    ATA_PC98_BANK, ~0,
+                                    ATA_PC98_BANKIOSIZE, RF_ACTIVE);
+    if (!scp->bankio)
+       return ENOMEM;
+
+    rid = 0;
+    scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+                                 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+
+    scp->current_bank = -1;
+    if (!device_add_child(dev, "ata", 0))
+       return ENOMEM;
+    if (!device_add_child(dev, "ata", 1))
+       return ENOMEM;
+
+    return bus_generic_attach(dev);
+}
+
+static struct resource *
+ata_cbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
+                       u_long start, u_long end, u_long count, u_int flags)
+{
+    struct ata_cbus_controller *scp = device_get_softc(dev);
+
+    if (type == SYS_RES_IOPORT) {
+       switch (*rid) {
+       case ATA_IOADDR_RID:
+           return scp->io;
+       case ATA_ALTADDR_RID:
+           return scp->altio;
+       }
+    }
+    if (type == SYS_RES_IRQ) {
+       return scp->irq;
+    }
+    return 0;
+}
+
+static int
+ata_cbus_release_resource(device_t dev, device_t child,
+                         int type, int rid, struct resource *r)
+{
+    return 0; 
+}
+
+static int
+ata_cbus_setup_intr(device_t dev, device_t child, struct resource *irq,
+              int flags, driver_intr_t *intr, void *arg,
+              void **cookiep)
+{
+    return BUS_SETUP_INTR(device_get_parent(dev), dev, irq,
+                         flags, intr, arg, cookiep);
+}
+
+static int
+ata_cbus_print_child(device_t dev, device_t child)
+{
+    struct ata_channel *ch = device_get_softc(child);
+    int retval = 0;
+
+    retval += bus_print_child_header(dev, child);
+    retval += printf(" at bank %d", ch->unit);
+    retval += bus_print_child_footer(dev, child);
+    return retval;
+}
+
+static int
+ata_cbus_intr(struct ata_channel *ch)
+{  
+    struct ata_cbus_controller *scp =
+       device_get_softc(device_get_parent(ch->dev));
+
+    return (ch->unit == scp->current_bank);
+}
+
+static void
+ata_cbus_banking(struct ata_channel *ch, int flags)
+{
+    struct ata_cbus_controller *scp =
+       device_get_softc(device_get_parent(ch->dev));
+
+    switch (flags) {
+    case ATA_LF_LOCK:
+       if (scp->current_bank == ch->unit)
+           break;
+       while (!atomic_cmpset_int(&scp->current_bank, -1, ch->unit))
+           tsleep((caddr_t)ch->lock_func, PRIBIO, "atalck", 1);
+       bus_space_write_1(rman_get_bustag(scp->bankio),
+                         rman_get_bushandle(scp->bankio), 0, ch->unit);
+       break;
+
+    case ATA_LF_UNLOCK:
+       if (scp->current_bank == -1 || scp->current_bank != ch->unit)
+           break;
+       scp->current_bank = -1;
+       break;
+    }
+    return;
+}
+
+static device_method_t ata_cbus_methods[] = {
+    /* device_interface */
+    DEVMETHOD(device_probe,    ata_cbus_probe),
+    DEVMETHOD(device_attach,   ata_cbus_attach),
+
+    /* bus methods */
+    DEVMETHOD(bus_alloc_resource,      ata_cbus_alloc_resource),
+    DEVMETHOD(bus_release_resource,    ata_cbus_release_resource),
+    DEVMETHOD(bus_setup_intr,          ata_cbus_setup_intr),
+    DEVMETHOD(bus_print_child,         ata_cbus_print_child),
+    { 0, 0 }
+};
+
+static driver_t ata_cbus_driver = {
+    "atacbus",
+    ata_cbus_methods,
+    sizeof(struct ata_cbus_controller),
+};
+
+static devclass_t ata_cbus_devclass;
+
+DRIVER_MODULE(atacbus, isa, ata_cbus_driver, ata_cbus_devclass, 0, 0);
+
+static int
+ata_cbussub_probe(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+    device_t *children;
+    int count, i;
+
+    /* find channel number on this controller */
+    device_get_children(device_get_parent(dev), &children, &count);
+    for (i = 0; i < count; i++) {
+       if (children[i] == dev) 
+           ch->unit = i;
+    }
+    free(children, M_TEMP);
+    ch->flags |= ATA_USE_16BIT;
+    ch->intr_func = ata_cbus_intr;
+    ch->lock_func = ata_cbus_banking;
+    return ata_probe(dev);
+}
+
+static device_method_t ata_cbussub_methods[] = {
+    /* device interface */
+    DEVMETHOD(device_probe,    ata_cbussub_probe),
+    DEVMETHOD(device_attach,   ata_attach),
+    DEVMETHOD(device_detach,   ata_detach),
+    DEVMETHOD(device_resume,   ata_resume),
+    { 0, 0 }
+};
+
+static driver_t ata_cbussub_driver = {
+    "ata",
+    ata_cbussub_methods,
+    sizeof(struct ata_channel),
+};
+
+DRIVER_MODULE(ata, atacbus, ata_cbussub_driver, ata_devclass, 0, 0);
-Søren

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to