static struct ata_chip_id *ata_match_chip(device_t dev, struct ata_chip_id *index);
static struct ata_chip_id *ata_find_chip(device_t dev, struct ata_chip_id *index, int slot);
static int ata_setup_interrupt(device_t dev);
+static void ata_teardown_interrupt(device_t dev);
static int ata_serialize(device_t dev, int flags);
static void ata_print_cable(device_t dev, u_int8_t *who);
static int ata_atapi(device_t dev);
ctlr->r_rid2 = PCIR_BAR(0);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2,
- RF_ACTIVE)))
+ RF_ACTIVE))) {
+ ata_teardown_interrupt(dev);
return ENXIO;
+ }
ctlr->channels = 4;
ctlr->allocate = ata_intel_31244_allocate;
ctlr->reset = ata_intel_31244_reset;
pci_write_config(dev, 0x40, 0x80c0a131, 4);
pci_write_config(dev, 0x80, 0x01200000, 4);
- if ((error = ata_ahci_chipinit(dev)))
+ if ((error = ata_ahci_chipinit(dev))) {
+ ata_teardown_interrupt(dev);
return error;
+ }
ctlr->allocate = ata_jmicron_allocate;
ctlr->reset = ata_jmicron_reset;
ctlr->r_type1 = SYS_RES_MEMORY;
ctlr->r_rid1 = PCIR_BAR(0);
if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
- &ctlr->r_rid1, RF_ACTIVE)))
+ &ctlr->r_rid1, RF_ACTIVE))) {
+ ata_teardown_interrupt(dev);
return ENXIO;
+ }
/* mask all host controller interrupts */
ATA_OUTL(ctlr->r_res1, 0x01d64, 0x00000000);
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = PCIR_BAR(5);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
- &ctlr->r_rid2, RF_ACTIVE)))
+ &ctlr->r_rid2, RF_ACTIVE))){
+ ata_teardown_interrupt(dev);
return ENXIO;
+ }
ctlr->channels = ctlr->chip->cfg2;
ctlr->allocate = ata_serverworks_allocate;
ctlr->r_type1 = SYS_RES_MEMORY;
ctlr->r_rid1 = PCIR_BAR(0);
if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
- &ctlr->r_rid1, RF_ACTIVE)))
+ &ctlr->r_rid1, RF_ACTIVE))){
+ ata_teardown_interrupt(dev);
return ENXIO;
+ }
ctlr->r_rid2 = PCIR_BAR(2);
ctlr->r_type2 = SYS_RES_MEMORY;
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE))){
bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
+ ata_teardown_interrupt(dev);
return ENXIO;
}
ctlr->allocate = ata_siiprb_allocate;
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = PCIR_BAR(5);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
- &ctlr->r_rid2, RF_ACTIVE)))
+ &ctlr->r_rid2, RF_ACTIVE))){
+ ata_teardown_interrupt(dev);
return ENXIO;
+ }
if (ctlr->chip->cfg2 & SIISETCLK) {
if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
ctlr->setmode = ata_sata_setmode;
return 0;
default:
+ ata_teardown_interrupt(dev);
return ENXIO;
}
ctlr->setmode = ata_sis_setmode;
if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
ata_generic_intr, ctlr, &ctlr->handle, NULL))) {
device_printf(dev, "unable to setup interrupt\n");
+ bus_release_resource(dev, SYS_RES_IRQ, rid, ctlr->r_irq);
+ ctlr->r_irq = 0;
return ENXIO;
}
}
return 0;
}
+static void
+ata_teardown_interrupt(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (!ctlr->legacy) {
+ 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);
+ ctlr->r_irq = 0;
+ }
+ }
+}
+
struct ata_serialize {
struct spinlock locked_mtx;
int locked_ch;