Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Nov 2002 21:44:51 +0100 (CET)
From:      Soeren Schmidt <sos@spider.deepcore.dk>
To:        current@freebsd.org
Subject:   ATA patches for PC98 - Please test!
Message-ID:  <200211292044.gATKipVT018982@spider.deepcore.dk>

next in thread | raw e-mail | index | archive | help

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 <sos@FreeBSD.org>
+ * 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 majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200211292044.gATKipVT018982>