1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-17 10:26:15 +00:00

Fix the breakage that snatched the ioports from the fdc device.

Fix promise support.
This commit is contained in:
Søren Schmidt 2000-09-24 18:19:43 +00:00
parent a898bb8d0d
commit 511e9e7251
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=66326
5 changed files with 65 additions and 34 deletions

View File

@ -124,7 +124,7 @@ ata_isa_probe(device_t dev)
/* alloctate the altport range */
if (bus_get_resource(dev, SYS_RES_IOPORT, 1, &tmp, &tmp)) {
bus_set_resource(dev, SYS_RES_IOPORT, 1,
rman_get_start(port) + ATA_ALTPORT,
rman_get_start(port) + ATA_ALTOFFSET,
ATA_ALTIOSIZE);
}
bus_release_resource(dev, SYS_RES_IOPORT, 0, port);
@ -172,7 +172,7 @@ ata_pccard_probe(device_t dev)
*/
if (len <= ATA_IOSIZE) {
bus_set_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID,
rman_get_start(port) + ATA_ALTPORT, ATA_ALTIOSIZE);
rman_get_start(port) + ATA_ALTOFFSET, ATA_ALTIOSIZE);
}
bus_release_resource(dev, SYS_RES_IOPORT, 0, port);
scp->unit = device_get_unit(dev);
@ -538,7 +538,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
case ATA_ALTADDR_RID:
if (masterdev) {
myrid = 0;
start = (unit == 0 ? IO_WD1 : IO_WD2) + ATA_ALTPORT;
start = (unit == 0 ? IO_WD1 : IO_WD2) + ATA_ALTOFFSET;
end = start + ATA_ALTIOSIZE - 1;
count = ATA_ALTIOSIZE;
}
@ -787,10 +787,14 @@ ata_probe(device_t dev)
rid = ATA_ALTADDR_RID;
altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
ATA_ALTIOSIZE, RF_ACTIVE);
if (altio)
altioaddr = rman_get_start(altio);
if (altio) {
if (pci_get_progif(device_get_parent(dev)) & PCIP_STORAGE_IDE_MASTERDEV)
altioaddr = rman_get_start(altio);
else
altioaddr = rman_get_start(altio) + 0x02;
}
else
altioaddr = ioaddr + ATA_IOSIZE - 2; /* pccard ?? XXX */
altioaddr = ioaddr + ATA_IOSIZE;
rid = ATA_BMADDR_RID;
bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
@ -969,7 +973,7 @@ ata_getparam(struct ata_softc *scp, int device, u_int8_t command)
DELAY(1);
/* enable interrupt */
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_4BIT);
outb(scp->altioaddr, ATA_A_4BIT);
DELAY(1);
/* apparently some devices needs this repeated */
@ -1107,7 +1111,7 @@ ata_intr(void *data)
DELAY(1);
/* if drive is busy it didn't interrupt */
if (inb(scp->altioaddr + ATA_ALTSTAT) & ATA_S_BUSY)
if (inb(scp->altioaddr) & ATA_S_BUSY)
return;
/* clear interrupt and get status */
@ -1226,9 +1230,9 @@ ata_reset(struct ata_softc *scp, int *mask)
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(1);
inb(scp->ioaddr + ATA_STATUS);
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_IDS | ATA_A_RESET);
outb(scp->altioaddr, ATA_A_IDS | ATA_A_RESET);
DELAY(10000);
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_IDS);
outb(scp->altioaddr, ATA_A_IDS);
DELAY(10000);
inb(scp->ioaddr + ATA_ERROR);
DELAY(3000);
@ -1269,7 +1273,7 @@ ata_reset(struct ata_softc *scp, int *mask)
DELAY(100);
}
DELAY(1);
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_4BIT);
outb(scp->altioaddr, ATA_A_4BIT);
if (status0 & ATA_S_BUSY)
*mask &= ~0x01;
if (status1 & ATA_S_BUSY)
@ -1368,17 +1372,18 @@ int
ata_wait(struct ata_softc *scp, int device, u_int8_t mask)
{
int timeout = 0;
int statio = scp->ioaddr + ATA_STATUS;
DELAY(1);
while (timeout < 5000000) { /* timeout 5 secs */
scp->status = inb(scp->altioaddr + ATA_ALTSTAT);
scp->status = inb(statio);
/* if drive fails status, reselect the drive just to be sure */
if (scp->status == 0xff) {
ata_printf(scp, device, "no status, reselecting device\n");
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device);
DELAY(1);
scp->status = inb(scp->altioaddr + ATA_ALTSTAT);
scp->status = inb(statio);
}
/* are we done ? */
@ -1404,7 +1409,7 @@ ata_wait(struct ata_softc *scp, int device, u_int8_t mask)
/* Wait 50 msec for bits wanted. */
timeout = 5000;
while (timeout--) {
scp->status = inb(scp->altioaddr + ATA_ALTSTAT);
scp->status = inb(statio);
if ((scp->status & mask) == mask) {
if (scp->status & ATA_S_ERROR)
scp->error = inb(scp->ioaddr + ATA_ERROR);
@ -1430,7 +1435,7 @@ ata_command(struct ata_softc *scp, int device, u_int8_t command,
/* disable interrupt from device */
if (scp->flags & ATA_QUEUED)
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_IDS | ATA_A_4BIT);
outb(scp->altioaddr, ATA_A_IDS | ATA_A_4BIT);
/* select device */
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device);
@ -1461,7 +1466,7 @@ ata_command(struct ata_softc *scp, int device, u_int8_t command,
/* enable interrupt */
if (scp->flags & ATA_QUEUED)
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_4BIT);
outb(scp->altioaddr, ATA_A_4BIT);
if (await(PRIBIO, 10 * hz)) {
ata_printf(scp, device, "ata_command: timeout waiting for intr\n");
@ -1497,7 +1502,7 @@ ata_command(struct ata_softc *scp, int device, u_int8_t command,
}
/* enable interrupt */
if (scp->flags & ATA_QUEUED)
outb(scp->altioaddr + ATA_ALTCTRL, ATA_A_4BIT);
outb(scp->altioaddr, ATA_A_4BIT);
return error;
}

View File

@ -74,13 +74,17 @@
#define ATA_C_READ_DMA 0xc8 /* read w/DMA command */
#define ATA_C_WRITE_DMA 0xca /* write w/DMA command */
#define ATA_C_WRITE_DMA_QUEUED 0xcc /* write w/DMA QUEUED command */
#define ATA_C_FLUSHCACHE 0xe7 /* flush cache to disk */
#define ATA_C_ATA_IDENTIFY 0xec /* get ATA params */
#define ATA_C_SETFEATURES 0xef /* features command */
#define ATA_C_F_SETXFER 0x03 /* set transfer mode */
#define ATA_C_F_ENAB_WCACHE 0x02 /* enable write cache */
#define ATA_C_F_ENAB_SRVIRQ 0x5e /* enable service interrupt */
#define ATA_C_F_DIS_WCACHE 0x82 /* disable write cache */
#define ATA_C_F_ENAB_RCACHE 0xaa /* enable readahead cache */
#define ATA_C_F_DIS_RCACHE 0x55 /* disable readahead cache */
#define ATA_C_F_ENAB_RELIRQ 0x5d /* enable release interrupt */
#define ATA_C_F_DIS_RELIRQ 0xdd /* disable release interrupt */
#define ATA_C_F_ENAB_SRVIRQ 0x5e /* enable service interrupt */
#define ATA_C_F_DIS_SRVIRQ 0xde /* disable service interrupt */
#define ATA_STATUS 0x07 /* status register */
@ -95,15 +99,12 @@
#define ATA_S_READY 0x40 /* drive ready */
#define ATA_S_BUSY 0x80 /* busy */
#define ATA_ALTSTAT 0x02 /* alternate status register */
#define ATA_ALTCTRL 0X02 /* alternate device control */
#define ATA_ALTOFFSET 0x206 /* alternate registers offset */
#define ATA_ALTIOSIZE 0x01 /* alternate registers size */
#define ATA_A_IDS 0x02 /* disable interrupts */
#define ATA_A_RESET 0x04 /* RESET controller */
#define ATA_A_4BIT 0x08 /* 4 head bits */
#define ATA_ALTPORT 0x204 /* alternate registers offset */
#define ATA_ALTIOSIZE 0x01 /* alternate registers size */
/* misc defines */
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x10

View File

@ -1,3 +1,4 @@
#define ATA_FLUSHCACHE_ON
/*-
* Copyright (c) 1998,1999,2000 Søren Schmidt
* All rights reserved.
@ -316,7 +317,17 @@ ad_start(struct ad_softc *adp)
if (!bp)
return;
/* if tagged queueing enabled get free tag */
#ifdef ATA_FLUSHCACHE_ON
/*
* if BIO_ORDERED is set cache should be flushed, if there are
* any outstanding requests, hold off and wait for them to finish
*/
if (adp->flags & AD_F_TAG_ENABLED &&
bp->bio_flags & BIO_ORDERED && adp->outstanding > 0)
return;
#endif
/* if tagged queueing enabled get next free tag */
if (adp->flags & AD_F_TAG_ENABLED) {
while (tag <= adp->num_tags && adp->tags[tag])
tag++;
@ -337,7 +348,8 @@ ad_start(struct ad_softc *adp)
request->bytecount = bp->bio_bcount;
request->data = bp->bio_data;
request->tag = tag;
request->flags = (bp->bio_cmd == BIO_READ) ? ADR_F_READ : 0;
if (bp->bio_cmd == BIO_READ)
request->flags |= ADR_F_READ;
if (adp->controller->mode[ATA_DEV(adp->unit)] >= ATA_DMA) {
if (!(request->dmatab = ata_dmaalloc(adp->controller, adp->unit)))
adp->controller->mode[ATA_DEV(adp->unit)] = ATA_PIO;
@ -442,6 +454,8 @@ ad_transfer(struct ad_request *request)
}
#if 0
/*
* wait for data transfer phase
*
* well this should be here acording to specs, but
* promise controllers doesn't like it, they lockup!
* thats probably why tags doesn't work on the promise
@ -455,12 +469,6 @@ ad_transfer(struct ad_request *request)
#endif
}
/* check for possible error from controller */
if (adp->controller->status & ATA_S_ERROR) {
printf("ad%d: error executing transfer cmd\n", adp->lun);
goto transfer_failed;
}
/* start transfer, return and wait for interrupt */
ata_dmastart(adp->controller, adp->unit,
request->dmatab, request->flags & ADR_F_READ);
@ -534,6 +542,9 @@ ad_interrupt(struct ad_request *request)
struct ad_softc *adp = request->device;
int dma_stat = 0;
if (request->flags & ADR_F_FLUSHCACHE)
goto finish;
/* finish DMA transfer */
if (request->flags & ADR_F_DMA_USED)
dma_stat = ata_dmadone(adp->controller);
@ -632,6 +643,18 @@ ad_interrupt(struct ad_request *request)
untimeout((timeout_t *)ad_timeout, request, request->timeout_handle);
request->bp->bio_resid = request->bytecount;
#ifdef ATA_FLUSHCACHE_ON
if (request->bp->bio_flags & BIO_ORDERED) {
request->flags |= ADR_F_FLUSHCACHE;
if (ata_command(adp->controller, adp->unit, ATA_C_FLUSHCACHE,
0, 0, 0, 0, 0, ATA_IMMEDIATE))
printf("ad%d: flushing cache failed\n", adp->lun);
else
return ATA_OP_CONTINUES;
}
#endif
finish:
devstat_end_transaction_bio(&adp->stats, request->bp);
biodone(request->bp);
ad_free(request);
@ -670,10 +693,11 @@ ad_service(struct ad_softc *adp, int change)
DELAY(1);
}
}
adp->controller->status = inb(adp->controller->altioaddr + ATA_ALTSTAT);
adp->controller->status = inb(adp->controller->altioaddr);
/* do we have a SERVICE request from the drive ? */
if (adp->flags & AD_F_TAG_ENABLED &&
adp->outstanding > 0 &&
adp->controller->status & ATA_S_SERVICE) {
struct ad_request *request;
int tag;

View File

@ -43,6 +43,7 @@ struct ad_request {
#define ADR_F_DMA_USED 0x0004
#define ADR_F_QUEUED 0x0008
#define ADR_F_FORCE_PIO 0x0010
#define ADR_F_FLUSHCACHE 0x0020
caddr_t data; /* pointer to data buf */
struct bio *bp; /* associated bio ptr */

View File

@ -524,7 +524,7 @@ ata_dmainit(struct ata_softc *scp, int device,
(device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
break;
if (udmamode >=5 &&
if (udmamode >= 5 &&
(scp->chiptype == 0x4d30105a || scp->chiptype == 0x0d30105a) &&
!(pci_read_config(parent, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) {
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
@ -539,7 +539,7 @@ ata_dmainit(struct ata_softc *scp, int device,
return;
}
}
if (udmamode >=4 && (scp->chiptype == 0x4d38105a ||
if (udmamode >= 4 && (scp->chiptype == 0x4d38105a ||
scp->chiptype == 0x4d30105a || scp->chiptype == 0x0d30105a) &&
!(pci_read_config(parent, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) {
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,