From owner-freebsd-current Fri Nov 29 12:45:30 2002 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7A0A237B401 for ; Fri, 29 Nov 2002 12:45:05 -0800 (PST) Received: from spider.deepcore.dk (cpe.atm2-0-56339.0x50c6aa0a.abnxx2.customer.tele.dk [80.198.170.10]) by mx1.FreeBSD.org (Postfix) with ESMTP id D05DD43E88 for ; Fri, 29 Nov 2002 12:44:52 -0800 (PST) (envelope-from sos@spider.deepcore.dk) Received: (from sos@localhost) by spider.deepcore.dk (8.12.5/8.12.6) id gATKipVT018982 for current@freebsd.org; Fri, 29 Nov 2002 21:44:51 +0100 (CET) (envelope-from sos) From: Soeren Schmidt Message-Id: <200211292044.gATKipVT018982@spider.deepcore.dk> Subject: ATA patches for PC98 - Please test! To: current@freebsd.org Date: Fri, 29 Nov 2002 21:44:51 +0100 (CET) X-Mailer: ELM [version 2.4ME+ PL98b (25)] MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=ISO-8859-1 Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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; ctlrlock_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; ctlrlock_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; ctlrlock_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 + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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