Add support for detaching PCI controllers.
This adds support for cardbus ATA/SATA controllers. I get roughly the same transfer speeds as on true PCI controllers. Nice to be able to add a couble of "real" disks to a laptop :)
This commit is contained in:
parent
a745e2bbf1
commit
dc99d6d221
@ -69,7 +69,6 @@ static struct cdevsw ata_cdevsw = {
|
||||
static void ata_shutdown(void *, int);
|
||||
static int ata_getparam(struct ata_device *, u_int8_t);
|
||||
static void ata_identify_devices(struct ata_channel *);
|
||||
static void ata_fail_requests(struct ata_channel *ch,struct ata_device *device);
|
||||
static void ata_boot_attach(void);
|
||||
static void bswap(int8_t *, int);
|
||||
static void btrim(int8_t *, int);
|
||||
@ -710,24 +709,6 @@ ata_identify_devices(struct ata_channel *ch)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ata_fail_requests(struct ata_channel *ch, struct ata_device *device)
|
||||
{
|
||||
struct ata_request *request;
|
||||
|
||||
mtx_lock(&ch->queue_mtx);
|
||||
while ((request = TAILQ_FIRST(&ch->ata_queue))) {
|
||||
if (device == NULL || request->device == device) {
|
||||
TAILQ_REMOVE(&ch->ata_queue, request, chain);
|
||||
request->result = ENXIO;
|
||||
mtx_unlock(&ch->queue_mtx);
|
||||
ata_finish(request);
|
||||
mtx_lock(&ch->queue_mtx);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&ch->queue_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
ata_boot_attach(void)
|
||||
{
|
||||
|
@ -332,6 +332,7 @@ struct ata_channel {
|
||||
#define ATA_ATAPI_DMA_RO 0x08
|
||||
#define ATA_48BIT_ACTIVE 0x10
|
||||
#define ATA_IMMEDIATE_MODE 0x20
|
||||
#define ATA_HWGONE 0x40
|
||||
|
||||
struct ata_device device[2]; /* devices on this channel */
|
||||
#define MASTER 0x00
|
||||
@ -396,6 +397,7 @@ int ata_controlcmd(struct ata_device *atadev, u_int8_t command, u_int16_t featur
|
||||
int ata_atapicmd(struct ata_device *atadev, u_int8_t *ccb, caddr_t data, int count, int flags, int timeout);
|
||||
void ata_queue_request(struct ata_request *request);
|
||||
void ata_finish(struct ata_request *request);
|
||||
void ata_fail_requests(struct ata_channel *ch, struct ata_device *device);
|
||||
char *ata_cmd2str(struct ata_request *request);
|
||||
|
||||
/* ata-lowlevel.c: */
|
||||
|
@ -512,7 +512,7 @@ ata_cyrix_chipinit(device_t dev)
|
||||
if (ata_setup_interrupt(dev))
|
||||
return ENXIO;
|
||||
|
||||
if (ctlr->r_io1)
|
||||
if (ctlr->r_res1)
|
||||
ctlr->setmode = ata_cyrix_setmode;
|
||||
else
|
||||
ctlr->setmode = ata_generic_setmode;
|
||||
@ -1145,14 +1145,14 @@ ata_promise_chipinit(device_t dev)
|
||||
switch (ctlr->chip->cfg1) {
|
||||
case PRNEW:
|
||||
/* setup clocks */
|
||||
ATA_OUTB(ctlr->r_io1, 0x11, ATA_INB(ctlr->r_io1, 0x11) | 0x0a);
|
||||
ATA_OUTB(ctlr->r_res1, 0x11, ATA_INB(ctlr->r_res1, 0x11) | 0x0a);
|
||||
|
||||
ctlr->dmainit = ata_promise_new_dmainit;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PROLD:
|
||||
/* enable burst mode */
|
||||
ATA_OUTB(ctlr->r_io1, 0x1f, ATA_INB(ctlr->r_io1, 0x1f) | 0x01);
|
||||
ATA_OUTB(ctlr->r_res1, 0x1f, ATA_INB(ctlr->r_res1, 0x1f) | 0x01);
|
||||
|
||||
if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
|
||||
ata_promise_old_intr, ctlr, &ctlr->handle))) {
|
||||
@ -1170,21 +1170,23 @@ ata_promise_chipinit(device_t dev)
|
||||
break;
|
||||
|
||||
case PRMIO:
|
||||
rid = 0x1c;
|
||||
if (!(ctlr->r_io2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
|
||||
0, ~0, 1, RF_ACTIVE)))
|
||||
ctlr->r_type2 = SYS_RES_MEMORY;
|
||||
ctlr->r_rid2 = 0x1c;
|
||||
if (!(ctlr->r_res2 =
|
||||
bus_alloc_resource(dev, ctlr->r_type2, &ctlr->r_rid2,
|
||||
0, ~0, 1, RF_ACTIVE)))
|
||||
return ENXIO;
|
||||
|
||||
ctlr->dmainit = ata_promise_mio_dmainit;
|
||||
ctlr->allocate = ata_promise_mio_allocate;
|
||||
|
||||
if (ctlr->chip->cfg2 & PRDUAL) {
|
||||
ctlr->channels = ((ATA_INL(ctlr->r_io2, 0x48) & 0x01) > 0) +
|
||||
((ATA_INL(ctlr->r_io2, 0x48) & 0x02) > 0) + 2;
|
||||
ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x01) > 0) +
|
||||
((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 2;
|
||||
}
|
||||
else if (ctlr->chip->cfg2 & PRSATA) {
|
||||
ATA_OUTL(ctlr->r_io2, 0x06c, 0x00ff0033);
|
||||
ctlr->channels = ((ATA_INL(ctlr->r_io2, 0x48) & 0x02) > 0) + 3;
|
||||
ATA_OUTL(ctlr->r_res2, 0x06c, 0x00ff0033);
|
||||
ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 3;
|
||||
}
|
||||
else
|
||||
ctlr->channels = 4;
|
||||
@ -1208,18 +1210,18 @@ ata_promise_mio_allocate(device_t dev, struct ata_channel *ch)
|
||||
int i;
|
||||
|
||||
for (i = ATA_DATA; i <= ATA_STATUS; i++) {
|
||||
ch->r_io[i].res = ctlr->r_io2;
|
||||
ch->r_io[i].res = ctlr->r_res2;
|
||||
ch->r_io[i].offset = 0x200 + (i << 2) + (ch->unit << 7);
|
||||
}
|
||||
ch->r_io[ATA_ALTSTAT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_ALTSTAT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_ALTSTAT].offset = 0x238 + (ch->unit << 7);
|
||||
ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMCMD_PORT].offset = 0x260 + (ch->unit << 7);
|
||||
ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMDTP_PORT].offset = 0x244 + (ch->unit << 7);
|
||||
ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMDEVSPEC_0].offset = ((ch->unit + 1) << 2);
|
||||
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
|
||||
|
||||
ATA_IDX_OUTL(ch, ATA_BMCMD_PORT,
|
||||
(ATA_IDX_INL(ch, ATA_BMCMD_PORT) & ~0x00003f9f) |
|
||||
@ -1242,7 +1244,7 @@ ata_promise_old_intr(void *data)
|
||||
for (unit = 0; unit < 2; unit++) {
|
||||
if (!(ch = ctlr->interrupt[unit].argument))
|
||||
continue;
|
||||
if (ATA_INL(ctlr->r_io1, 0x1c) & (ch->unit ? 0x00004000 : 0x00000400)) {
|
||||
if (ATA_INL(ctlr->r_res1, 0x1c) & (ch->unit ? 0x00004000 : 0x00000400)) {
|
||||
if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
|
||||
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
|
||||
|
||||
@ -1292,7 +1294,7 @@ ata_promise_mio_intr(void *data)
|
||||
u_int32_t irq_vector;
|
||||
int unit;
|
||||
|
||||
irq_vector = ATA_INL(ctlr->r_io2, 0x0040);
|
||||
irq_vector = ATA_INL(ctlr->r_res2, 0x0040);
|
||||
for (unit = 0; unit < ctlr->channels; unit++) {
|
||||
if (irq_vector & (1 << (unit + 1))) {
|
||||
if ((ch = ctlr->interrupt[unit].argument)) {
|
||||
@ -1398,9 +1400,9 @@ ata_promise_new_dmastart(struct ata_channel *ch)
|
||||
device_get_softc(device_get_parent(ch->dev));
|
||||
|
||||
if (ch->flags & ATA_48BIT_ACTIVE) {
|
||||
ATA_OUTB(ctlr->r_io1, 0x11,
|
||||
ATA_INB(ctlr->r_io1, 0x11) | (ch->unit ? 0x08 : 0x02));
|
||||
ATA_OUTL(ctlr->r_io1, 0x20,
|
||||
ATA_OUTB(ctlr->r_res1, 0x11,
|
||||
ATA_INB(ctlr->r_res1, 0x11) | (ch->unit ? 0x08 : 0x02));
|
||||
ATA_OUTL(ctlr->r_res1, 0x20,
|
||||
((ch->dma->flags & ATA_DMA_READ) ? 0x05000000 : 0x06000000) |
|
||||
(ch->dma->cur_iosize >> 1));
|
||||
}
|
||||
@ -1421,9 +1423,9 @@ ata_promise_new_dmastop(struct ata_channel *ch)
|
||||
int error;
|
||||
|
||||
if (ch->flags & ATA_48BIT_ACTIVE) {
|
||||
ATA_OUTB(ctlr->r_io1, 0x11,
|
||||
ATA_INB(ctlr->r_io1, 0x11) & ~(ch->unit ? 0x08 : 0x02));
|
||||
ATA_OUTL(ctlr->r_io1, 0x20, 0);
|
||||
ATA_OUTB(ctlr->r_res1, 0x11,
|
||||
ATA_INB(ctlr->r_res1, 0x11) & ~(ch->unit ? 0x08 : 0x02));
|
||||
ATA_OUTL(ctlr->r_res1, 0x20, 0);
|
||||
}
|
||||
error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT);
|
||||
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
|
||||
@ -1630,9 +1632,11 @@ ata_sii_chipinit(device_t dev)
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
rid = 0x24;
|
||||
if (!(ctlr->r_io2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
|
||||
0, ~0, 1, RF_ACTIVE)))
|
||||
ctlr->r_type2 = SYS_RES_MEMORY;
|
||||
ctlr->r_rid2 = 0x24;
|
||||
if (!(ctlr->r_res2 =
|
||||
bus_alloc_resource(dev, ctlr->r_type2, &ctlr->r_rid2,
|
||||
0, ~0, 1, RF_ACTIVE)))
|
||||
return ENXIO;
|
||||
|
||||
if (ctlr->chip->cfg2 & SIISETCLK) {
|
||||
@ -1644,23 +1648,12 @@ ata_sii_chipinit(device_t dev)
|
||||
ctlr->chip->text);
|
||||
}
|
||||
|
||||
if (ctlr->chip->cfg2 & SII4CH)
|
||||
ctlr->channels = 4;
|
||||
|
||||
/* enable interrupt as BIOS might not */
|
||||
pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);
|
||||
|
||||
/* setup chipset defaults as BIOS might not */
|
||||
#if 0
|
||||
pci_write_config(dev, 0xa2, 0x328a, 2);
|
||||
pci_write_config(dev, 0xa4, 0x328a328a, 4);
|
||||
pci_write_config(dev, 0xa8, 0x22082208, 4);
|
||||
pci_write_config(dev, 0xac, 0x40094009, 4);
|
||||
pci_write_config(dev, 0xe2, 0x328a, 2);
|
||||
pci_write_config(dev, 0xe4, 0x328a328a, 4);
|
||||
pci_write_config(dev, 0xe8, 0x22082208, 4);
|
||||
pci_write_config(dev, 0xec, 0x40094009, 4);
|
||||
#endif
|
||||
if (ctlr->chip->cfg2 & SII4CH)
|
||||
ctlr->channels = 4;
|
||||
|
||||
ctlr->allocate = ata_sii_mio_allocate;
|
||||
if (ctlr->chip->max_dma >= ATA_SA150)
|
||||
ctlr->setmode = ata_sata_setmode;
|
||||
@ -1697,22 +1690,22 @@ ata_sii_mio_allocate(device_t dev, struct ata_channel *ch)
|
||||
int i;
|
||||
|
||||
for (i = ATA_DATA; i <= ATA_STATUS; i++) {
|
||||
ch->r_io[i].res = ctlr->r_io2;
|
||||
ch->r_io[i].res = ctlr->r_res2;
|
||||
ch->r_io[i].offset = 0x80 + i + (unit01 << 6) + (unit10 << 9);
|
||||
}
|
||||
ch->r_io[ATA_ALTSTAT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_ALTSTAT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_ALTSTAT].offset = 0x8a + (unit01 << 6) + (unit10 << 9);
|
||||
ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMCMD_PORT].offset = 0x00 + (unit01 << 3) + (unit10 << 9);
|
||||
ch->r_io[ATA_BMSTAT_PORT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMSTAT_PORT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMSTAT_PORT].offset = 0x02 + (unit01 << 3) + (unit10 << 9);
|
||||
ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMDTP_PORT].offset = 0x04 + (unit01 << 3) + (unit10 << 9);
|
||||
ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMDEVSPEC_0].offset = 0xa1 + (unit01 << 6) + (unit10 << 9);
|
||||
ch->r_io[ATA_BMDEVSPEC_1].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_BMDEVSPEC_1].res = ctlr->r_res2;
|
||||
ch->r_io[ATA_BMDEVSPEC_1].offset = 0x100 + (unit01 << 7) + (unit10 << 9);
|
||||
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_io2;
|
||||
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
|
||||
|
||||
if (ctlr->chip->max_dma >= ATA_SA150) {
|
||||
ch->flags |= ATA_NO_SLAVE;
|
||||
@ -1723,7 +1716,6 @@ ata_sii_mio_allocate(device_t dev, struct ata_channel *ch)
|
||||
if (ctlr->chip->cfg2 & SIIBUG)
|
||||
ch->dma->boundary = 8 * 1024;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,8 @@ ata_generic_hw(struct ata_channel *ch)
|
||||
static int
|
||||
ata_transaction(struct ata_request *request)
|
||||
{
|
||||
/* safety check, device might have been detached FIXME SOS */
|
||||
if (!request->device->param) {
|
||||
/* safetybelt for HW that went away */
|
||||
if (!request->device->param || request->device->channel->flags&ATA_HWGONE) {
|
||||
request->result = ENXIO;
|
||||
return ATA_OP_FINISHED;
|
||||
}
|
||||
|
@ -154,21 +154,9 @@ static int
|
||||
ata_pci_attach(device_t dev)
|
||||
{
|
||||
struct ata_pci_controller *ctlr = device_get_softc(dev);
|
||||
u_int8_t class, subclass;
|
||||
u_int32_t type, cmd;
|
||||
u_int32_t cmd;
|
||||
int unit;
|
||||
|
||||
/* set up vendor-specific stuff */
|
||||
type = pci_get_devid(dev);
|
||||
class = pci_get_class(dev);
|
||||
subclass = pci_get_subclass(dev);
|
||||
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
|
||||
|
||||
if (!(cmd & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN))) {
|
||||
device_printf(dev, "ATA channel disabled by BIOS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do chipset specific setups only needed once */
|
||||
if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK)
|
||||
ctlr->channels = 2;
|
||||
@ -178,18 +166,19 @@ ata_pci_attach(device_t dev)
|
||||
ctlr->dmainit = ata_pci_dmainit;
|
||||
ctlr->locking = ata_pci_locknoop;
|
||||
|
||||
#ifdef __sparc64__
|
||||
/* if needed try to enable busmastering */
|
||||
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
|
||||
if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
|
||||
pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2);
|
||||
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
|
||||
}
|
||||
#endif
|
||||
/* if busmastering configured get the I/O resource */
|
||||
if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
|
||||
int rid = ATA_BMADDR_RID;
|
||||
|
||||
ctlr->r_io1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
/* if busmastering mode "stuck" use it */
|
||||
if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
|
||||
ctlr->r_type1 = SYS_RES_IOPORT;
|
||||
ctlr->r_rid1 = ATA_BMADDR_RID;
|
||||
ctlr->r_res1 = bus_alloc_resource(dev, ctlr->r_type1, &ctlr->r_rid1,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
}
|
||||
|
||||
ctlr->chipinit(dev);
|
||||
@ -199,9 +188,34 @@ ata_pci_attach(device_t dev)
|
||||
device_add_child(dev, "ata", ATA_MASTERDEV(dev) ?
|
||||
unit : devclass_find_free_unit(ata_devclass, 2));
|
||||
|
||||
return bus_generic_attach(dev);
|
||||
}
|
||||
return bus_generic_attach(dev); }
|
||||
|
||||
static int
|
||||
ata_pci_detach(device_t dev)
|
||||
{
|
||||
struct ata_pci_controller *ctlr = device_get_softc(dev);
|
||||
struct ata_channel *ch;
|
||||
int unit;
|
||||
|
||||
/* mark HW as gone, we dont want to issue commands to HW no longer there */
|
||||
for (unit = 0; unit < ctlr->channels; unit++) {
|
||||
if ((ch = ctlr->interrupt[unit].argument))
|
||||
ch->flags |= ATA_HWGONE;
|
||||
}
|
||||
|
||||
bus_generic_detach(dev);
|
||||
|
||||
if (ctlr->r_irq) {
|
||||
bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ctlr->r_irq);
|
||||
}
|
||||
if (ctlr->r_res2)
|
||||
bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
|
||||
if (ctlr->r_res1)
|
||||
bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1, ctlr->r_res1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ata_pci_print_child(device_t dev, device_t child)
|
||||
@ -420,9 +434,9 @@ ata_pci_allocate(device_t dev, struct ata_channel *ch)
|
||||
ch->r_io[ATA_ALTSTAT].offset = 0;
|
||||
ch->r_io[ATA_IDX_ADDR].res = io;
|
||||
|
||||
if (ctlr->r_io1) {
|
||||
if (ctlr->r_res1) {
|
||||
for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) {
|
||||
ch->r_io[i].res = ctlr->r_io1;
|
||||
ch->r_io[i].res = ctlr->r_res1;
|
||||
ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE);
|
||||
}
|
||||
|
||||
@ -481,6 +495,7 @@ static device_method_t ata_pci_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, ata_pci_probe),
|
||||
DEVMETHOD(device_attach, ata_pci_attach),
|
||||
DEVMETHOD(device_detach, ata_pci_detach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
@ -514,6 +529,9 @@ ata_pcisub_probe(device_t dev)
|
||||
device_t *children;
|
||||
int count, error, i;
|
||||
|
||||
/* take care of green memory */
|
||||
bzero(ch, sizeof(struct ata_channel));
|
||||
|
||||
/* find channel number on this controller */
|
||||
device_get_children(device_get_parent(dev), &children, &count);
|
||||
for (i = 0; i < count; i++) {
|
||||
@ -528,6 +546,8 @@ ata_pcisub_probe(device_t dev)
|
||||
ch->device[MASTER].setmode = ctlr->setmode;
|
||||
ch->device[SLAVE].setmode = ctlr->setmode;
|
||||
ch->locking = ctlr->locking;
|
||||
if (ch->reset)
|
||||
ch->reset(ch);
|
||||
return ata_probe(dev);
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,12 @@ struct ata_chip_id {
|
||||
|
||||
/* structure describing a PCI ATA controller */
|
||||
struct ata_pci_controller {
|
||||
struct resource *r_io1;
|
||||
struct resource *r_io2;
|
||||
int r_type1;
|
||||
int r_rid1;
|
||||
struct resource *r_res1;
|
||||
int r_type2;
|
||||
int r_rid2;
|
||||
struct resource *r_res2;
|
||||
struct resource *r_irq;
|
||||
void *handle;
|
||||
struct ata_chip_id *chip;
|
||||
|
@ -459,6 +459,39 @@ ata_timeout(struct ata_request *request)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ata_fail_requests(struct ata_channel *ch, struct ata_device *device)
|
||||
{
|
||||
struct ata_request *request;
|
||||
|
||||
/* fail all requests queued on this channel */
|
||||
mtx_lock(&ch->queue_mtx);
|
||||
while ((request = TAILQ_FIRST(&ch->ata_queue))) {
|
||||
if (!device || request->device == device) {
|
||||
TAILQ_REMOVE(&ch->ata_queue, request, chain);
|
||||
request->result = ENXIO;
|
||||
if (request->callback)
|
||||
(request->callback)(request);
|
||||
else
|
||||
sema_post(&request->done);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&ch->queue_mtx);
|
||||
|
||||
/* if we have a request "in flight" fail it as well */
|
||||
if ((!device || request->device == device) && (request = ch->running)) {
|
||||
untimeout((timeout_t *)ata_timeout, request, request->timeout_handle);
|
||||
ATA_UNLOCK_CH(request->device->channel);
|
||||
request->device->channel->locking(request->device->channel,
|
||||
ATA_LF_UNLOCK);
|
||||
request->result = ENXIO;
|
||||
if (request->callback)
|
||||
(request->callback)(request);
|
||||
else
|
||||
sema_post(&request->done);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
ata_cmd2str(struct ata_request *request)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user