/* Enable interrupts */ void gdt_pci_enable_intr(struct gdt_softc *sc) { GDT_DPRINTF(GDT_D_INTR, ("gdt_pci_enable_intr(%p) ", sc)); switch(GDT_CLASS(sc)) { case GDT_PCI: bus_space_write_1(sc->sc_dpmemt, sc->sc_dpmemh, GDT_IRQDEL, 1); bus_space_write_1(sc->sc_dpmemt, sc->sc_dpmemh, GDT_CMD_INDEX, 0); bus_space_write_1(sc->sc_dpmemt, sc->sc_dpmemh, GDT_IRQEN, 1); break; case GDT_PCINEW: bus_space_write_1(sc->sc_iot, sc->sc_ioh, GDT_EDOOR_REG, 0xff); bus_space_write_1(sc->sc_iot, sc->sc_ioh, GDT_CONTROL1, 3); break; case GDT_MPR: bus_space_write_1(sc->sc_dpmemt, sc->sc_dpmemh, GDT_MPR_EDOOR, 0xff); bus_space_write_1(sc->sc_dpmemt, sc->sc_dpmemh, GDT_EDOOR_EN, bus_space_read_1(sc->sc_dpmemt, sc->sc_dpmemh, GDT_EDOOR_EN) & ~4); break; } }
/* Enable interrupts */ void gdt_pci_enable_intr(struct gdt_softc *gdt) { GDT_DPRINTF(GDT_D_INTR, ("gdt_pci_enable_intr(%p) ", gdt)); switch(GDT_CLASS(gdt)) { case GDT_MPR: bus_write_1(gdt->sc_dpmem, GDT_MPR_EDOOR, 0xff); bus_write_1(gdt->sc_dpmem, GDT_EDOOR_EN, bus_read_1(gdt->sc_dpmem, GDT_EDOOR_EN) & ~4); break; } }
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; }