void gdt_pci_attach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = aux; struct gdt_softc *sc = (void *)self; bus_space_tag_t dpmemt, iomemt, iot; bus_space_handle_t dpmemh, iomemh, ioh; bus_addr_t dpmembase, iomembase, iobase; bus_size_t dpmemsize, iomemsize, iosize; u_int16_t prod; u_int32_t status = 0; #define DPMEM_MAPPED 1 #define IOMEM_MAPPED 2 #define IO_MAPPED 4 #define INTR_ESTABLISHED 8 int retries; u_int8_t protocol; pci_intr_handle_t ih; const char *intrstr; printf(": "); sc->sc_class = 0; if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX) { prod = PCI_PRODUCT(pa->pa_id); switch (prod) { case PCI_PRODUCT_VORTEX_GDT_60x0: case PCI_PRODUCT_VORTEX_GDT_6000B: sc->sc_class = GDT_PCI; break; case PCI_PRODUCT_VORTEX_GDT_6x10: case PCI_PRODUCT_VORTEX_GDT_6x20: case PCI_PRODUCT_VORTEX_GDT_6530: case PCI_PRODUCT_VORTEX_GDT_6550: case PCI_PRODUCT_VORTEX_GDT_6x17: case PCI_PRODUCT_VORTEX_GDT_6x27: case PCI_PRODUCT_VORTEX_GDT_6537: case PCI_PRODUCT_VORTEX_GDT_6557: case PCI_PRODUCT_VORTEX_GDT_6x15: case PCI_PRODUCT_VORTEX_GDT_6x25: case PCI_PRODUCT_VORTEX_GDT_6535: case PCI_PRODUCT_VORTEX_GDT_6555: sc->sc_class = GDT_PCINEW; break; case PCI_PRODUCT_VORTEX_GDT_6x17RP: case PCI_PRODUCT_VORTEX_GDT_6x27RP: case PCI_PRODUCT_VORTEX_GDT_6537RP: case PCI_PRODUCT_VORTEX_GDT_6557RP: case PCI_PRODUCT_VORTEX_GDT_6x11RP: case PCI_PRODUCT_VORTEX_GDT_6x21RP: case PCI_PRODUCT_VORTEX_GDT_6x17RD: case PCI_PRODUCT_VORTEX_GDT_6x27RD: case PCI_PRODUCT_VORTEX_GDT_6537RD: case PCI_PRODUCT_VORTEX_GDT_6557RD: case PCI_PRODUCT_VORTEX_GDT_6x11RD: case PCI_PRODUCT_VORTEX_GDT_6x21RD: case PCI_PRODUCT_VORTEX_GDT_6x18RD: case PCI_PRODUCT_VORTEX_GDT_6x28RD: case PCI_PRODUCT_VORTEX_GDT_6x38RD: case PCI_PRODUCT_VORTEX_GDT_6x58RD: case PCI_PRODUCT_VORTEX_GDT_6518RS: case PCI_PRODUCT_VORTEX_GDT_7x18RN: case PCI_PRODUCT_VORTEX_GDT_7x28RN: case PCI_PRODUCT_VORTEX_GDT_7x38RN: case PCI_PRODUCT_VORTEX_GDT_7x58RN: case PCI_PRODUCT_VORTEX_GDT_6x19RD: case PCI_PRODUCT_VORTEX_GDT_6x29RD: case PCI_PRODUCT_VORTEX_GDT_7x19RN: case PCI_PRODUCT_VORTEX_GDT_7x29RN: case PCI_PRODUCT_VORTEX_GDT_7x43RN: sc->sc_class = GDT_MPR; } /* If we don't recognize it, determine class heuristically. */ if (sc->sc_class == 0) sc->sc_class = prod < 0x100 ? GDT_PCINEW : GDT_MPR; if (prod >= GDT_PCI_PRODUCT_FC) sc->sc_class |= GDT_FC; } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) { sc->sc_class = GDT_MPR; } if (pci_mapreg_map(pa, GDT_CLASS(sc) == GDT_PCINEW ? GDT_PCINEW_DPMEM : GDT_PCI_DPMEM, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt, &dpmemh, &dpmembase, &dpmemsize, 0)) { if (pci_mapreg_map(pa, GDT_CLASS(sc) == GDT_PCINEW ? GDT_PCINEW_DPMEM : GDT_PCI_DPMEM, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0, &dpmemt,&dpmemh, &dpmembase, &dpmemsize, 0)) { printf("cannot map DPMEM\n"); goto bail_out; } } status |= DPMEM_MAPPED; sc->sc_dpmemt = dpmemt; sc->sc_dpmemh = dpmemh; sc->sc_dpmembase = dpmembase; sc->sc_dmat = pa->pa_dmat; /* * The GDT_PCINEW series also has two other regions to map. */ if (GDT_CLASS(sc) == GDT_PCINEW) { if (pci_mapreg_map(pa, GDT_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM, 0, &iomemt, &iomemh, &iomembase, &iomemsize, 0)) { printf("can't map memory mapped i/o ports\n"); goto bail_out; } status |= IOMEM_MAPPED; if (pci_mapreg_map(pa, GDT_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, &iobase, &iosize, 0)) { printf("can't map i/o space\n"); goto bail_out; } status |= IO_MAPPED; sc->sc_iot = iot; sc->sc_ioh = ioh; sc->sc_iobase = iobase; } switch (GDT_CLASS(sc)) { case GDT_PCI: bus_space_set_region_4(dpmemt, dpmemh, 0, 0, GDT_DPR_IF_SZ >> 2); if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { printf("can't write to DPMEM\n"); goto bail_out; } #if 0 /* disable board interrupts, deinit services */ gdth_writeb(0xff, &dp6_ptr->io.irqdel); gdth_writeb(0x00, &dp6_ptr->io.irqen); gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status); gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); gdth_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("initialization error (DEINIT failed)\n"); gdth_munmap(ha->brd); return 0; } gdth_delay(1); } prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]); gdth_writeb(0, &dp6_ptr->u.ic.S_Status); gdth_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("illegal protocol version\n"); gdth_munmap(ha->brd); return 0; } ha->type = GDT_PCI; ha->ic_all_size = sizeof(dp6_ptr->u); /* special command to controller BIOS */ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); gdth_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("initialization error\n"); gdth_munmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp6_ptr->u.ic.S_Status); gdth_writeb(0xff, &dp6_ptr->io.irqdel); #endif sc->sc_ic_all_size = GDT_DPRAM_SZ; sc->sc_copy_cmd = gdt_pci_copy_cmd; sc->sc_get_status = gdt_pci_get_status; sc->sc_intr = gdt_pci_intr; sc->sc_release_event = gdt_pci_release_event; sc->sc_set_sema0 = gdt_pci_set_sema0; sc->sc_test_busy = gdt_pci_test_busy; break; case GDT_PCINEW: bus_space_set_region_4(dpmemt, dpmemh, 0, 0, GDT_DPR_IF_SZ >> 2); if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { printf("cannot write to DPMEM\n"); goto bail_out; } #if 0 /* disable board interrupts, deinit services */ outb(0x00,PTR2USHORT(&ha->plx->control1)); outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status); gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; gdth_delay(20); while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("initialization error (DEINIT failed)\n"); gdth_munmap(ha->brd); return 0; } gdth_delay(1); } prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]); gdth_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("illegal protocol version\n"); gdth_munmap(ha->brd); return 0; } ha->type = GDT_PCINEW; ha->ic_all_size = sizeof(dp6c_ptr->u); /* special command to controller BIOS */ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; gdth_delay(20); while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("initialization error\n"); gdth_munmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); #endif sc->sc_ic_all_size = GDT_PCINEW_SZ; sc->sc_copy_cmd = gdt_pcinew_copy_cmd; sc->sc_get_status = gdt_pcinew_get_status; sc->sc_intr = gdt_pcinew_intr; sc->sc_release_event = gdt_pcinew_release_event; sc->sc_set_sema0 = gdt_pcinew_set_sema0; sc->sc_test_busy = gdt_pcinew_test_busy; break; case GDT_MPR: bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC, GDT_MPR_MAGIC); if (bus_space_read_4(dpmemt, dpmemh, GDT_MPR_IC) != GDT_MPR_MAGIC) { printf("cannot access DPMEM at 0x%lx (shadowed?)\n", dpmembase); goto bail_out; } /* * XXX Here the Linux driver has a weird remapping logic I * don't understand. My controller does not need it, and I * cannot see what purpose it serves, therefore I did not * do anything similar. */ bus_space_set_region_4(dpmemt, dpmemh, GDT_I960_SZ, 0, GDT_DPR_IF_SZ >> 2); /* Disable everything */ bus_space_write_1(dpmemt, dpmemh, GDT_EDOOR_EN, bus_space_read_1(dpmemt, dpmemh, GDT_EDOOR_EN) | 4); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_EDOOR, 0xff); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_CMD_INDEX, 0); bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO, dpmembase); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 0xff); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_space_read_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS) != 0xff) { if (--retries == 0) { printf("DEINIT failed (status 0x%x)\n", bus_space_read_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS)); goto bail_out; } DELAY(1); } protocol = (u_int8_t)bus_space_read_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); if (protocol != GDT_PROTOCOL_VERSION) { printf("unsupported protocol %d\n", protocol); goto bail_out; } /* special commnd to controller BIOS */ bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO, 0); bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), 0); bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), 1); bus_space_write_4(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), 0); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 0xfe); bus_space_write_1(dpmemt, dpmemh, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_space_read_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { if (--retries == 0) { printf("initialization error\n"); goto bail_out; } DELAY(1); } bus_space_write_1(dpmemt, dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); sc->sc_ic_all_size = GDT_MPR_SZ; sc->sc_copy_cmd = gdt_mpr_copy_cmd; sc->sc_get_status = gdt_mpr_get_status; sc->sc_intr = gdt_mpr_intr; sc->sc_release_event = gdt_mpr_release_event; sc->sc_set_sema0 = gdt_mpr_set_sema0; sc->sc_test_busy = gdt_mpr_test_busy; } if (pci_intr_map(pa, &ih)) { printf("couldn't map interrupt\n"); goto bail_out; } intrstr = pci_intr_string(pa->pa_pc, ih); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, gdt_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf("couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto bail_out; } status |= INTR_ESTABLISHED; if (intrstr != NULL) printf("%s ", intrstr); if (gdt_attach(sc)) goto bail_out; gdt_pci_enable_intr(sc); return; bail_out: if (status & DPMEM_MAPPED) bus_space_unmap(dpmemt, dpmemh, dpmemsize); if (status & IOMEM_MAPPED) bus_space_unmap(iomemt, iomemh, iomembase); if (status & IO_MAPPED) bus_space_unmap(iot, ioh, iosize); if (status & INTR_ESTABLISHED) pci_intr_disestablish(pa->pa_pc, sc->sc_ih); return; }
void icp_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; struct icp_softc *icp; bus_space_tag_t dpmemt, iomemt, iot; bus_space_handle_t dpmemh, iomemh, ioh; bus_addr_t dpmembase, iomembase, iobase; bus_size_t dpmemsize, iomemsize, iosize; u_int32_t status; #define DPMEM_MAPPED 1 #define IOMEM_MAPPED 2 #define IO_MAPPED 4 #define INTR_ESTABLISHED 8 int retries; u_int8_t protocol; pci_intr_handle_t ih; const char *intrstr; char intrbuf[PCI_INTRSTR_LEN]; pa = aux; status = 0; icp = device_private(self); icp->icp_dv = self; icp->icp_class = icp_pci_find_class(pa); aprint_naive(": RAID controller\n"); aprint_normal(": "); if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX && PCI_PRODUCT(pa->pa_id) >= ICP_PCI_PRODUCT_FC) icp->icp_class |= ICP_FC; if (pci_mapreg_map(pa, ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM : ICP_PCI_DPMEM, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt, &dpmemh, &dpmembase, &dpmemsize)) { if (pci_mapreg_map(pa, ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM : ICP_PCI_DPMEM, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0, &dpmemt, &dpmemh, &dpmembase, &dpmemsize)) { aprint_error("cannot map DPMEM\n"); goto bail_out; } } status |= DPMEM_MAPPED; icp->icp_dpmemt = dpmemt; icp->icp_dpmemh = dpmemh; icp->icp_dpmembase = dpmembase; icp->icp_dmat = pa->pa_dmat; /* * The ICP_PCINEW series also has two other regions to map. */ if (ICP_CLASS(icp) == ICP_PCINEW) { if (pci_mapreg_map(pa, ICP_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM, 0, &iomemt, &iomemh, &iomembase, &iomemsize)) { aprint_error("cannot map memory mapped I/O ports\n"); goto bail_out; } status |= IOMEM_MAPPED; if (pci_mapreg_map(pa, ICP_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, &iobase, &iosize)) { aprint_error("cannot map I/O ports\n"); goto bail_out; } status |= IO_MAPPED; icp->icp_iot = iot; icp->icp_ioh = ioh; icp->icp_iobase = iobase; } switch (ICP_CLASS(icp)) { case ICP_PCI: bus_space_set_region_4(dpmemt, dpmemh, 0, 0, ICP_DPR_IF_SZ >> 2); if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { aprint_error("cannot write to DPMEM\n"); goto bail_out; } #if 0 /* disable board interrupts, deinit services */ icph_writeb(0xff, &dp6_ptr->io.irqdel); icph_writeb(0x00, &dp6_ptr->io.irqen); icph_writeb(0x00, &dp6_ptr->u.ic.S_Status); icph_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); icph_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); icph_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); icph_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("initialization error (DEINIT failed)\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } prot_ver = (unchar)icph_readl(&dp6_ptr->u.ic.S_Info[0]); icph_writeb(0, &dp6_ptr->u.ic.S_Status); icph_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("illegal protocol version\n"); icph_munmap(ha->brd); return 0; } ha->type = ICP_PCI; ha->ic_all_size = sizeof(dp6_ptr->u); /* special command to controller BIOS */ icph_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); icph_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); icph_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); icph_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); icph_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); icph_writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("initialization error\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } icph_writeb(0, &dp6_ptr->u.ic.S_Status); icph_writeb(0xff, &dp6_ptr->io.irqdel); #endif icp->icp_ic_all_size = ICP_DPRAM_SZ; icp->icp_copy_cmd = icp_pci_copy_cmd; icp->icp_get_status = icp_pci_get_status; icp->icp_intr = icp_pci_intr; icp->icp_release_event = icp_pci_release_event; icp->icp_set_sema0 = icp_pci_set_sema0; icp->icp_test_busy = icp_pci_test_busy; break; case ICP_PCINEW: bus_space_set_region_4(dpmemt, dpmemh, 0, 0, ICP_DPR_IF_SZ >> 2); if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) { aprint_error("cannot write to DPMEM\n"); goto bail_out; } #if 0 /* disable board interrupts, deinit services */ outb(0x00,PTR2USHORT(&ha->plx->control1)); outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); icph_writeb(0x00, &dp6c_ptr->u.ic.S_Status); icph_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); icph_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); icph_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("initialization error (DEINIT failed)\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } prot_ver = (unchar)icph_readl(&dp6c_ptr->u.ic.S_Info[0]); icph_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("illegal protocol version\n"); icph_munmap(ha->brd); return 0; } ha->type = ICP_PCINEW; ha->ic_all_size = sizeof(dp6c_ptr->u); /* special command to controller BIOS */ icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); icph_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); icph_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; icph_delay(20); while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("initialization error\n"); icph_munmap(ha->brd); return 0; } icph_delay(1); } icph_writeb(0, &dp6c_ptr->u.ic.S_Status); #endif icp->icp_ic_all_size = ICP_PCINEW_SZ; icp->icp_copy_cmd = icp_pcinew_copy_cmd; icp->icp_get_status = icp_pcinew_get_status; icp->icp_intr = icp_pcinew_intr; icp->icp_release_event = icp_pcinew_release_event; icp->icp_set_sema0 = icp_pcinew_set_sema0; icp->icp_test_busy = icp_pcinew_test_busy; break; case ICP_MPR: bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC, ICP_MPR_MAGIC); if (bus_space_read_4(dpmemt, dpmemh, ICP_MPR_IC) != ICP_MPR_MAGIC) { aprint_error( "cannot access DPMEM at 0x%lx (shadowed?)\n", (u_long)dpmembase); goto bail_out; } /* * XXX Here the Linux driver has a weird remapping logic I * don't understand. My controller does not need it, and I * cannot see what purpose it serves, therefore I did not * do anything similar. */ bus_space_set_region_4(dpmemt, dpmemh, ICP_I960_SZ, 0, ICP_DPR_IF_SZ >> 2); /* Disable everything. */ bus_space_write_1(dpmemt, dpmemh, ICP_EDOOR_EN, bus_space_read_1(dpmemt, dpmemh, ICP_EDOOR_EN) | 4); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_EDOOR, 0xff); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS, 0); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_CMD_INDEX, 0); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO, htole32(dpmembase)); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX, 0xff); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1); DELAY(20); retries = 1000000; while (bus_space_read_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS) != 0xff) { if (--retries == 0) { aprint_error("DEINIT failed\n"); goto bail_out; } DELAY(1); } protocol = (u_int8_t)bus_space_read_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS, 0); if (protocol != ICP_PROTOCOL_VERSION) { aprint_error("unsupported protocol %d\n", protocol); goto bail_out; } /* special commnd to controller BIOS */ bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO, 0); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO + sizeof(u_int32_t), 0); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO + 2 * sizeof(u_int32_t), 1); bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO + 3 * sizeof(u_int32_t), 0); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX, 0xfe); bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1); DELAY(20); retries = 1000000; while (bus_space_read_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS) != 0xfe) { if (--retries == 0) { aprint_error("initialization error\n"); goto bail_out; } DELAY(1); } bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS, 0); icp->icp_copy_cmd = icp_mpr_copy_cmd; icp->icp_get_status = icp_mpr_get_status; icp->icp_intr = icp_mpr_intr; icp->icp_release_event = icp_mpr_release_event; icp->icp_set_sema0 = icp_mpr_set_sema0; icp->icp_test_busy = icp_mpr_test_busy; break; } if (pci_intr_map(pa, &ih)) { aprint_error("couldn't map interrupt\n"); goto bail_out; } intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); icp->icp_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, icp_intr, icp); if (icp->icp_ih == NULL) { aprint_error("couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); goto bail_out; } status |= INTR_ESTABLISHED; if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) aprint_normal("Intel Storage RAID controller\n"); else aprint_normal("ICP-Vortex RAID controller\n"); icp->icp_pci_bus = pa->pa_bus; icp->icp_pci_device = pa->pa_device; icp->icp_pci_device_id = PCI_PRODUCT(pa->pa_id); icp->icp_pci_subdevice_id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); if (icp_init(icp, intrstr)) goto bail_out; icp_pci_enable_intr(icp); return; bail_out: if ((status & DPMEM_MAPPED) != 0) bus_space_unmap(dpmemt, dpmemh, dpmemsize); if ((status & IOMEM_MAPPED) != 0) bus_space_unmap(iomemt, iomemh, iomembase); if ((status & IO_MAPPED) != 0) bus_space_unmap(iot, ioh, iosize); if ((status & INTR_ESTABLISHED) != 0) pci_intr_disestablish(pa->pa_pc, icp->icp_ih); }