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.
This commit is contained in:
sos 2000-02-04 10:20:22 +00:00
parent ffc4c1858f
commit e12f0fb097
8 changed files with 172 additions and 85 deletions

View File

@ -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;
/* 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))
/*
* 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;
/* if drive is busy it didn't interrupt */
if (((scp->status = inb(scp->ioaddr + ATA_STATUS))&ATA_S_BUSY)==ATA_S_BUSY)
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);
/* 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:

View File

@ -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));

View File

@ -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;
}
}
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;
}
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;
}
}
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 */

View File

@ -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 {

View File

@ -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) {

View File

@ -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);

View File

@ -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 */

View File

@ -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
};