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>
