diff options
author | sos <sos@FreeBSD.org> | 2000-02-04 10:20:22 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2000-02-04 10:20:22 +0000 |
commit | e12f0fb0979f70fe1dad3927cc2b802c8755434a (patch) | |
tree | 18d7acac9e61bb96f1244b86d34b83980960c823 /sys | |
parent | ffc4c1858f3d68a6cfee5b63ce40cb00620dc359 (diff) | |
download | FreeBSD-src-e12f0fb0979f70fe1dad3927cc2b802c8755434a.zip FreeBSD-src-e12f0fb0979f70fe1dad3927cc2b802c8755434a.tar.gz |
fix support for shared IRQ's.
fix support for multiple HPT & Promise controllers.
support mixed 33/66 devices on the Promise 66 controllers.
fix the refcount stuff in the atapi drivers.
misc cleanups.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ata/ata-all.c | 71 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 142 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 2 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 17 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 14 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.h | 3 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 2 |
8 files changed, 171 insertions, 84 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 3ae7336..3a497e5 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -328,7 +328,8 @@ ata_pciattach(device_t dev) /* is this controller busmaster DMA capable ? */ if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { /* is busmastering support turned on ? */ - if ((pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4) & 5) == 5) { + if ((cmd & (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) == + (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) { /* is there a valid port range to connect to ? */ if ((bmaddr_1 = pci_read_config(dev, 0x20, 4) & IOMASK)) bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; @@ -355,12 +356,18 @@ ata_pciattach(device_t dev) pci_write_config(dev, 0x53, (pci_read_config(dev, 0x53, 1) & ~0x01) | 0x02, 1); break; + case 0x4d38105a: /* Promise 66's need their clock changed */ + outb(bmaddr_1 + 0x11, inb(bmaddr_1 + 0x11) | 0x0a); + /* FALLTHROUGH */ - case 0x4d33105a: - case 0x4d38105a: /* Promise's need burst mode to be turned on */ + case 0x4d33105a: /* Promise's need burst mode to be turned on */ outb(bmaddr_1 + 0x1f, inb(bmaddr_1 + 0x1f) | 0x01); break; + case 0x00041103: /* HPT366 turn of fast interrupt prediction */ + pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x80), 1); + break; + case 0x05711106: case 0x74091022: /* VIA 82C586, 82C596, 82C686 & AMD 756 default setup */ /* set prefetch, postwrite */ @@ -381,10 +388,17 @@ ata_pciattach(device_t dev) pci_write_config(dev, 0x60, DEV_BSIZE, 2); pci_write_config(dev, 0x68, DEV_BSIZE, 2); - /* prepare for ATA-66 on the 82C686 */ - if (ata_find_dev(dev, 0x06861106)) + /* set the chiptype to the hostchip ID, makes life easier */ + if (ata_find_dev(dev, 0x05861106)) + type = 0x05861106; + if (ata_find_dev(dev, 0x05961106)) + type = 0x05961106; + if (ata_find_dev(dev, 0x06861106)) { + type = 0x06861106; + /* prepare for ATA-66 on the 82C686 */ pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 4) | 0x070f070f, 4); + } break; } @@ -736,15 +750,40 @@ static void ataintr(void *data) { struct ata_softc *scp = (struct ata_softc *)data; + u_int8_t dmastat; + + /* + * since we might share the IRQ with another device, and in some + * case with our twin channel, we only want to process interrupts + * that we know this channel generated. + */ + switch (scp->chiptype) { +#if NPCI > 0 + case 0x00041103: /* HighPoint HPT366 */ + if (!((dmastat = ata_dmastatus(scp)) & ATA_BMSTAT_INTERRUPT)) + return; + outb(scp->bmaddr + ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); + break; - /* check if this interrupt is for us (shared PCI interrupts) */ - /* if DMA active look at the dmastatus */ - if ((scp->flags & ATA_DMA_ACTIVE) && - !(ata_dmastatus(scp) & ATA_BMSTAT_INTERRUPT)) + case 0x4d33105a: /* Promise 33's */ + case 0x4d38105a: /* Promise 66's */ + if (!(inl((pci_read_config(scp->dev, 0x20, 4) & IOMASK) + 0x1c) & + ((scp->unit) ? 0x00004000 : 0x00000400))) return; + /* FALLTHROUGH */ +#endif + default: + if (scp->flags & ATA_DMA_ACTIVE) { + if (!(dmastat = ata_dmastatus(scp)) & ATA_BMSTAT_INTERRUPT) + return; + else + outb(scp->bmaddr+ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + } + } + DELAY(1); - /* if drive is busy it didn't interrupt */ - if (((scp->status = inb(scp->ioaddr + ATA_STATUS))&ATA_S_BUSY)==ATA_S_BUSY) + /* get status, if drive is busy it didn't interrupt so return */ + if ((scp->status = inb(scp->ioaddr + ATA_STATUS)) & ATA_S_BUSY) return; /* find & call the responsible driver to process this interrupt */ @@ -794,8 +833,12 @@ ataintr(void *data) void ata_start(struct ata_softc *scp) { +#if NATADISK > 0 struct ad_request *ad_request; +#endif +#if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0 struct atapi_request *atapi_request; +#endif if (scp->active != ATA_IDLE) return; @@ -1099,8 +1142,14 @@ active2str(int32_t active) switch (active) { case ATA_IDLE: return("ATA_IDLE"); + case ATA_IMMEDIATE: + return("ATA_IMMEDIATE"); case ATA_WAIT_INTR: return("ATA_WAIT_INTR"); + case ATA_WAIT_READY: + return("ATA_WAIT_READY"); + case ATA_ACTIVE: + return("ATA_ACTIVE"); case ATA_ACTIVE_ATA: return("ATA_ACTIVE_ATA"); case ATA_ACTIVE_ATAPI: diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index f7d596c..8329b46 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -459,10 +459,10 @@ ad_interrupt(struct ad_request *request) /* did any real errors happen ? */ if ((adp->controller->status & ATA_S_ERROR) || - (request->flags & AR_F_DMA_USED && dma_stat != ATA_BMSTAT_INTERRUPT)) { + ((request->flags & AR_F_DMA_USED) && (dma_stat & ATA_BMSTAT_ERROR))) { oops: printf("ad%d: %s %s ERROR blk# %d", adp->lun, - (adp->controller->error & ATA_E_ICRC) ? "UDMA CRC" : "HARD", + (adp->controller->error & ATA_E_ICRC) ? "UDMA ICRC" : "HARD", (request->flags & AR_F_READ) ? "READ" : "WRITE", request->blockaddr + (request->donecount / DEV_BSIZE)); diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index f91ce77..1751648 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -255,40 +255,37 @@ ata_dmainit(struct ata_softc *scp, int32_t device, /* we could set PIO mode timings, but we assume the BIOS did that */ break; - case 0x05711106: /* VIA 82C571, 82C586, 82C596 & 82C686 */ - case 0x74091022: /* AMD 756 */ - /* UDMA modes on 82C686 */ - if (ata_find_dev(scp->dev, 0x06861106)) { - if (udmamode >= 4) { - error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_printf(scp, device, - "%s setting up UDMA4 mode on VIA chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0xe8, 1); - scp->mode[ATA_DEV(device)] = ATA_UDMA4; - return; - } + case 0x06861106: /* VIA 82C686 */ + if (udmamode >= 4) { + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_printf(scp, device, + "%s setting up UDMA4 mode on VIA chip\n", + (error) ? "failed" : "success"); + if (!error) { + pci_write_config(scp->dev, 0x53 - devno, 0xe8, 1); + scp->mode[ATA_DEV(device)] = ATA_UDMA4; + return; } - if (udmamode >= 2) { - error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_printf(scp, device, - "%s setting up UDMA2 mode on VIA chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0xea, 1); - scp->mode[ATA_DEV(device)] = ATA_UDMA2; - return; - } + } + if (udmamode >= 2) { + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_printf(scp, device, + "%s setting up UDMA2 mode on VIA chip\n", + (error) ? "failed" : "success"); + if (!error) { + pci_write_config(scp->dev, 0x53 - devno, 0xea, 1); + scp->mode[ATA_DEV(device)] = ATA_UDMA2; + return; } } + goto via_generic; - /* UDMA4 mode on AMD 756 */ - if (udmamode >= 4 && scp->chiptype == 0x74091022) { + case 0x74091022: /* AMD 756 */ + if (udmamode >= 4) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) @@ -301,11 +298,15 @@ ata_dmainit(struct ata_softc *scp, int32_t device, return; } } + /* FALLTHROUGH */ + + case 0x05961106: /* VIA 82C596 */ + case 0x05861106: /* VIA 82C586 */ /* UDMA2 mode only on 82C586 > rev1, 82C596, AMD 756 */ - if ((udmamode >= 2 && ata_find_dev(scp->dev, 0x05861106) && + if ((udmamode >= 2 && scp->chiptype == 0x05861106 && pci_read_config(scp->dev, 0x08, 1) >= 0x01) || - (udmamode >= 2 && ata_find_dev(scp->dev, 0x05961106)) || + (udmamode >= 2 && scp->chiptype == 0x05961106) || (udmamode >= 2 && scp->chiptype == 0x74091022)) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); @@ -319,6 +320,10 @@ ata_dmainit(struct ata_softc *scp, int32_t device, return; } } + /* FALLTHROUGH */ + + case 0x05711106: /* VIA 82C571 */ +via_generic: if (wdmamode >= 2 && apiomode >= 4) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); @@ -382,7 +387,6 @@ ata_dmainit(struct ata_softc *scp, int32_t device, "%s setting up UDMA4 mode on Promise chip\n", (error) ? "failed" : "success"); if (!error) { - outb(scp->bmaddr+0x11, inl(scp->bmaddr+0x11) | scp->unit ? 8:2); promise_timing(scp, devno, ATA_UDMA4); scp->mode[ATA_DEV(device)] = ATA_UDMA4; return; @@ -512,8 +516,16 @@ ata_dmainit(struct ata_softc *scp, int32_t device, } } } + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ata_pio2mode(apiomode), ATA_C_F_SETXFER,ATA_WAIT_READY); if (bootverbose) - ata_printf(scp, device, "using PIO mode set by BIOS\n"); + ata_printf(scp, device, "%s setting up PIO%d mode on generic chip\n", + (error) ? "failed" : "success", apiomode < 0 ? 0 : apiomode); + if (!error) + scp->mode[ATA_DEV(device)] = ata_pio2mode(apiomode); + else + if (bootverbose) + ata_printf(scp, device, "using PIO mode set by BIOS\n"); } int32_t @@ -586,17 +598,55 @@ ata_dmastatus(struct ata_softc *scp) static void promise_timing(struct ata_softc *scp, int32_t devno, int32_t mode) { - u_int32_t timing; - switch (mode) { - default: - case ATA_PIO0: timing = 0x004ff329; break; - case ATA_PIO1: timing = 0x004fec25; break; - case ATA_PIO2: timing = 0x004fe823; break; - case ATA_PIO3: timing = 0x004fe622; break; - case ATA_PIO4: timing = 0x004fe421; break; - case ATA_WDMA2: timing = 0x004367f3; break; - case ATA_UDMA2: timing = 0x004127f3; break; - case ATA_UDMA4: timing = 0x004127f3; break; + u_int32_t timing = 0; + struct promise_timing { + u_int8_t pa:4; + u_int8_t prefetch:1; + u_int8_t iordy:1; + u_int8_t errdy:1; + u_int8_t syncin:1; + u_int8_t pb:5; + u_int8_t mb:3; + u_int8_t mc:4; + u_int8_t dmaw:1; + u_int8_t dmar:1; + u_int8_t iordyp:1; + u_int8_t dmarqp:1; + u_int8_t reserved:8; + } *t = (struct promise_timing*)&timing; + + t->iordy = 1; t->iordyp = 1; + if (mode >= ATA_DMA) { + t->prefetch = 1; t->errdy = 1; t->syncin = 1; + } + + switch (scp->chiptype) { + case 0x4d33105a: /* Promise 33's */ + switch (mode) { + default: + case ATA_PIO0: t->pa = 9; t->pb = 19; t->mb = 7; t->mc = 15; break; + case ATA_PIO1: t->pa = 5; t->pb = 12; t->mb = 7; t->mc = 15; break; + case ATA_PIO2: t->pa = 3; t->pb = 8; t->mb = 7; t->mc = 15; break; + case ATA_PIO3: t->pa = 2; t->pb = 6; t->mb = 7; t->mc = 15; break; + case ATA_PIO4: t->pa = 1; t->pb = 4; t->mb = 7; t->mc = 15; break; + case ATA_WDMA2: t->pa = 3; t->pb = 7; t->mb = 3; t->mc = 3; break; + case ATA_UDMA2: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; + } + break; + + case 0x4d38105a: /* Promise 66's */ + switch (mode) { + default: + case ATA_PIO0: t->pa = 15; t->pb = 31; t->mb = 7; t->mc = 15; break; + case ATA_PIO1: t->pa = 10; t->pb = 24; t->mb = 7; t->mc = 15; break; + case ATA_PIO2: t->pa = 6; t->pb = 16; t->mb = 7; t->mc = 15; break; + case ATA_PIO3: t->pa = 4; t->pb = 12; t->mb = 7; t->mc = 15; break; + case ATA_PIO4: t->pa = 2; t->pb = 8; t->mb = 7; t->mc = 15; break; + case ATA_WDMA2: t->pa = 6; t->pb = 14; t->mb = 6; t->mc = 6; break; + case ATA_UDMA2: t->pa = 6; t->pb = 14; t->mb = 2; t->mc = 2; break; + case ATA_UDMA4: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; + } + break; } pci_write_config(scp->dev, 0x60 + (devno << 2), timing, 4); } @@ -647,7 +697,7 @@ hpt366_timing(struct ata_softc *scp, int32_t devno, int32_t mode) default: timing = 0x0120d9d9; } } - pci_write_config(scp->dev, 0x40 + (devno << 2) , timing, 4); + pci_write_config(scp->dev, 0x40 + (devno << 2) , (timing & ~0x80000000), 4); } #else /* NPCI > 0 */ diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 0f3c98e..cb4be28 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -285,7 +285,7 @@ atapi_interrupt(struct atapi_request *request) dma_stat = ata_dmadone(atp->controller); atp->flags &= ~ATAPI_F_DMA_USED; if ((atp->controller->status & (ATA_S_ERROR | ATA_S_DWF)) || - dma_stat != ATA_BMSTAT_INTERRUPT) { + dma_stat & ATA_BMSTAT_ERROR) { request->result = inb(atp->controller->ioaddr + ATA_ERROR); } else { diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index 8c4325d..9b6c453 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -69,7 +69,7 @@ static struct cdevsw acd_cdevsw = { /* maj */ 117, /* dump */ nodump, /* psize */ nopsize, - /* flags */ D_DISK, + /* flags */ D_DISK | D_TRACKCLOSE, /* bmaj */ 31 }; @@ -207,7 +207,6 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats) acd->lun = lun; acd->flags &= ~(F_WRITTEN|F_DISK_OPEN|F_TRACK_OPEN); acd->block_size = 2048; - acd->refcnt = 0; acd->slot = -1; acd->changer_info = NULL; acd->atp->flags |= ATAPI_F_MEDIA_CHANGED; @@ -458,7 +457,7 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) cdp->flags |= F_WRITING; } - if (!cdp->refcnt) { + if (!cdp->refcnt++) { acd_prevent_allow(cdp, 1); cdp->flags |= F_LOCKED; if (!(flags & O_NONBLOCK) && !(flags & FWRITE)) @@ -466,7 +465,6 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) else atapi_test_ready(cdp->atp); } - cdp->refcnt++; return 0; } @@ -475,10 +473,7 @@ acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { struct acd_softc *cdp = dev->si_drv1; - cdp->refcnt--; - - /* are we the last open ?? */ - if (!cdp->refcnt) + if (!--cdp->refcnt) acd_prevent_allow(cdp, 0); cdp->flags &= ~(F_LOCKED | F_WRITING); @@ -1396,8 +1391,6 @@ acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai) int16_t length; int8_t ccb[16]; - printf("dvd_report_key: format=0x%x\n", ai->format); - switch (ai->format) { case DVD_REPORT_AGID: case DVD_REPORT_ASF: @@ -1488,8 +1481,6 @@ acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai) int16_t length; int8_t ccb[16]; - printf("dvd_send_key: format=0x%x\n", ai->format); - bzero(&d, sizeof(d)); switch (ai->format) { @@ -1532,8 +1523,6 @@ acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s) int32_t error = 0; int8_t ccb[16]; - printf("dvd_read_structure: format=0x%x\n", s->format); - bzero(&d, sizeof(d)); switch(s->format) { diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index 5358afb..51a4e06 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -65,8 +65,8 @@ static struct cdevsw afd_cdevsw = { /* maj */ 118, /* dump */ nodump, /* psize */ nopsize, - /* flags */ D_DISK, - /* bmaj */ 32, + /* flags */ D_DISK | D_TRACKCLOSE, + /* bmaj */ 32 }; static struct cdevsw afddisk_cdevsw; @@ -215,7 +215,8 @@ afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) atapi_test_ready(fdp->atp); - afd_prevent_allow(fdp, 1); + if (!fdp->refcnt++) + afd_prevent_allow(fdp, 1); if (afd_sense(fdp)) printf("afd%d: sense media type failed\n", fdp->lun); @@ -237,7 +238,8 @@ afdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { struct afd_softc *fdp = dev->si_drv1; - afd_prevent_allow(fdp, 0); + if (!--fdp->refcnt) + afd_prevent_allow(fdp, 0); return 0; } @@ -248,12 +250,12 @@ afdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) switch (cmd) { case CDIOCEJECT: - if ((fdp->flags & F_OPEN) && fdp->refcnt) + if (fdp->refcnt > 1) return EBUSY; return afd_eject(fdp, 0); case CDIOCCLOSE: - if ((fdp->flags & F_OPEN) && fdp->refcnt) + if (fdp->refcnt > 1) return 0; return afd_eject(fdp, 1); diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h index 2f4e990..fcef411 100644 --- a/sys/dev/ata/atapi-fd.h +++ b/sys/dev/ata/atapi-fd.h @@ -73,9 +73,6 @@ struct afd_cappage { struct afd_softc { struct atapi_softc *atp; /* controller structure */ int32_t lun; /* logical device unit */ - int32_t flags; /* device state flags */ -#define F_OPEN 0x0001 /* the device is opened */ - int32_t refcnt; /* the number of raw opens */ int32_t transfersize; /* max size of each transfer */ struct buf_queue_head buf_queue; /* queue of i/o requests */ diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index 4f470b8..93e42e9 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -64,7 +64,7 @@ static struct cdevsw ast_cdevsw = { /* maj */ 119, /* dump */ nodump, /* psize */ nopsize, - /* flags */ D_TAPE, + /* flags */ D_TAPE | D_TRACKCLOSE, /* bmaj */ -1 }; |