int iq80321_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct i80321_softc *sc = pa->pa_pc->pc_intr_v; int b, d, f; uint32_t busno; /* * The IQ80321's interrupts are routed like so: * * XINT0 i82544 Gig-E * * XINT1 UART * * XINT2 INTA# from S-PCI-X slot * * XINT3 INTB# from S-PCI-X slot */ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f); /* No mappings for devices not on our bus. */ if (b != busno) goto no_mapping; switch (d) { case 4: /* i82544 Gig-E */ if (pa->pa_intrpin == 1) { *ihp = ICU_INT_XINT(0); return (0); } goto no_mapping; case 6: /* S-PCI-X slot */ if (pa->pa_intrpin == 1) { *ihp = ICU_INT_XINT(2); return (0); } if (pa->pa_intrpin == 2) { *ihp = ICU_INT_XINT(3); return (0); } goto no_mapping; default: no_mapping: printf("iq80321_pci_intr_map: no mapping for %d/%d/%d\n", pa->pa_bus, pa->pa_device, pa->pa_function); return (1); } return (0); }
extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin) { int bus; int device; int func; uint32_t busno; struct i80321_pci_softc *sc = device_get_softc(pcib); bus = pci_get_bus(dev); device = pci_get_slot(dev); func = pci_get_function(dev); busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; if (bus != busno) goto no_mapping; switch (device) { /* IQ31244 PCI */ case 1: /* PCIX-PCIX bridge */ /* * The S-ATA chips are behind the bridge, and all of * the S-ATA interrupts are wired together. */ return (ICU_INT_XINT(2)); case 2: /* PCI slot */ /* All pins are wired together. */ return (ICU_INT_XINT(3)); case 3: /* i82546 dual Gig-E */ if (pin == 1 || pin == 2) return (ICU_INT_XINT(0)); goto no_mapping; /* IQ80321 PCI */ case 4: /* i82544 Gig-E */ case 8: /* * Apparently you can set the device for the ethernet adapter * to 8 with a jumper, so handle that as well */ if (pin == 1) return (ICU_INT_XINT(0)); goto no_mapping; case 6: /* S-PCI-X slot */ if (pin == 1) return (ICU_INT_XINT(2)); if (pin == 2) return (ICU_INT_XINT(3)); goto no_mapping; default: no_mapping: printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin); } return (0); }
void i80321_pci_init(pci_chipset_tag_t pc, void *cookie) { #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) struct i80321_softc *sc = cookie; struct extent *ioext, *memext; uint32_t busno; #endif pc->pc_conf_v = cookie; pc->pc_attach_hook = i80321_pci_attach_hook; pc->pc_bus_maxdevs = i80321_pci_bus_maxdevs; pc->pc_make_tag = i80321_pci_make_tag; pc->pc_decompose_tag = i80321_pci_decompose_tag; pc->pc_conf_read = i80321_pci_conf_read; pc->pc_conf_write = i80321_pci_conf_write; #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE) /* * Configure the PCI bus. * * XXX We need to revisit this. We only configure the Secondary * bus (and its children). The bus configure code needs changes * to support how the busses are arranged on this chip. We also * need to only configure devices in the private device space on * the Secondary bus. */ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; ioext = extent_create("pciio", sc->sc_ioout_xlate + sc->sc_ioout_xlate_offset, sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE - 1, M_DEVBUF, NULL, 0, EX_NOWAIT); #ifdef I80321_USE_DIRECT_WIN memext = extent_create("pcimem", VERDE_OUT_DIRECT_WIN_BASE + VERDE_OUT_DIRECT_WIN_SKIP, VERDE_OUT_DIRECT_WIN_BASE + VERDE_OUT_DIRECT_WIN_SIZE- 1, M_DEVBUF, NULL, 0, EX_NOWAIT); #else memext = extent_create("pcimem", sc->sc_owin[0].owin_xlate_lo, sc->sc_owin[0].owin_xlate_lo + VERDE_OUT_XLATE_MEM_WIN_SIZE - 1, M_DEVBUF, NULL, 0, EX_NOWAIT); #endif aprint_normal("%s: configuring PCI bus\n", sc->sc_dev.dv_xname); pci_configure_bus(pc, ioext, memext, NULL, busno, arm_dcache_align); extent_destroy(ioext); extent_destroy(memext); #endif }
int iq80321_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct i80321_softc *sc = pa->pa_pc->pc_intr_v; int b, d, f; uint32_t busno; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f); /* No mappings for devices not on our bus. */ if (b != busno) goto no_mapping; switch (d) { case 0: /* i82546EB Dual GigE */ /* * This is a dual-function chip which uses INTA and INTB, * connected to XINT0 and XINT1 respectively. */ if (f != 0 && f != 1) goto no_mapping; *ihp = ICU_INT_XINT(f); return (0); case 1: /* i31244 S-ATA Interface */ *ihp = ICU_INT_XINT(2); return (0); case 2: /* Symbios Logic 53c1010 SCSI Controllers */ case 3: /* * Both controllers share a single pin */ *ihp = ICU_INT_XINT(3); return (0); default: no_mapping: printf("iq80321_pci_intr_map: no mapping for %d/%d/%d/%c\n", pa->pa_bus, pa->pa_device, pa->pa_function, '@' + pa->pa_intrpin); return (1); } return (0); }
int iq80321_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct i80321_softc *sc = pa->pa_pc->pc_intr_v; int b, d, f; uint32_t busno; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f); /* No mappings for devices not on our bus. */ if (b != busno) goto no_mapping; switch (d) { case 1: /* PCIX-PCIX bridge */ /* * The S-ATA chips are behind the bridge, and all of * the S-ATA interrupts are wired together. */ *ihp = ICU_INT_XINT(2); return (0); case 2: /* PCI slot */ /* All pins are wired together. */ *ihp = ICU_INT_XINT(3); return (0); case 3: /* i82546 dual Gig-E */ if (pa->pa_intrpin == 1 || pa->pa_intrpin == 2) { *ihp = ICU_INT_XINT(0); return (0); } goto no_mapping; default: no_mapping: printf("iq80321_pci_intr_map: no mapping for %d/%d/%d/%c\n", pa->pa_bus, pa->pa_device, pa->pa_function, '@' + pa->pa_intrpin); return (1); } return (0); }
int iyonix_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct i80321_softc *sc = pa->pa_pc->pc_intr_v; int b, d, f; uint32_t busno; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f); /* No mappings for devices not on our bus. */ if (b != busno) goto no_mapping; /* * XXX We currently deal only with the southbridge and with * regular PCI. IOC devices may need further attention. */ /* Devices on the southbridge are all routed through xint 1 */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI) { switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_ALI_M1543: /* Southbridge */ case PCI_PRODUCT_ALI_M5229: /* ATA */ case PCI_PRODUCT_ALI_M5237: /* ohci */ case PCI_PRODUCT_ALI_M5257: /* Modem */ case PCI_PRODUCT_ALI_M5451: /* AC97 */ case PCI_PRODUCT_ALI_M7101: /* PMC */ *ihp = ICU_INT_XINT(1); return (0); } } /* Route other interrupts with default swizzling rule */ *ihp = ICU_INT_XINT((d + pa->pa_intrpin - 1) % 4); return 0; no_mapping: printf("iyonix_pci_intr_map: no mapping for %d/%d/%d\n", pa->pa_bus, pa->pa_device, pa->pa_function); return (1); }
static int i80321_pci_attach(device_t dev) { uint32_t busno; struct i80321_pci_softc *sc = device_get_softc(dev); sc->sc_st = i80321_softc->sc_st; sc->sc_atu_sh = i80321_softc->sc_atu_sh; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; sc->sc_dev = dev; sc->sc_busno = busno; sc->sc_pciio = &i80321_softc->sc_pci_iot; sc->sc_pcimem = &i80321_softc->sc_pci_memt; sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo + VERDE_OUT_XLATE_MEM_WIN_SIZE; sc->sc_io = i80321_softc->sc_iow_vaddr; /* Initialize memory and i/o rmans. */ sc->sc_io_rman.rm_type = RMAN_ARRAY; sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports"; if (rman_init(&sc->sc_io_rman) != 0 || rman_manage_region(&sc->sc_io_rman, sc->sc_io, sc->sc_io + VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) { panic("i80321_pci_probe: failed to set up I/O rman"); } sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "I80321 PCI Memory"; if (rman_init(&sc->sc_mem_rman) != 0 || rman_manage_region(&sc->sc_mem_rman, 0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) { panic("i80321_pci_probe: failed to set up memory rman"); } sc->sc_irq_rman.rm_type = RMAN_ARRAY; sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs"; if (rman_init(&sc->sc_irq_rman) != 0 || rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0) panic("i80321_pci_probe: failed to set up IRQ rman"); device_add_child(dev, "pci",busno); return (bus_generic_attach(dev)); }
int iq80321_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct i80321_softc *sc = pa->pa_pc->pc_intr_v; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_intrtag; int i; int b, d, f; uint32_t busno; uint32_t intr; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; pci_decompose_tag(pc, tag, &b, &d, &f); /* No mappings for devices not on our bus. */ if (b != busno) goto no_mapping; for (i = 0; iq80321_irq_map[i].irq != 255; i++) { if (d == iq80321_irq_map[i].dev && pa->pa_intrpin == iq80321_irq_map[i].intrpin) { *ihp = iq80321_irq_map[i].irq; intr = pci_conf_read(pa->pa_pc, pa->pa_intrtag, PCI_INTERRUPT_REG); intr = (intr & ~0xff) | iq80321_irq_map[i].irq; pci_conf_write(pa->pa_pc, pa->pa_intrtag, PCI_INTERRUPT_REG, intr); return (0); } } no_mapping: intr = pci_conf_read(pa->pa_pc, pa->pa_intrtag, PCI_INTERRUPT_REG); printf("iq80321_pci_intr_map: no mapping for %d/%d/%d (%d, %d, %d)\n", pa->pa_bus, pa->pa_device, pa->pa_function, d, pa->pa_intrpin, intr); return (1); }
extern int machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin) { int bus; int device; int func; uint32_t busno; struct i80321_pci_softc *sc = device_get_softc(pcib); bus = pci_get_bus(dev); device = pci_get_slot(dev); func = pci_get_function(dev); busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; if (bus != busno) goto no_mapping; switch (device) { /* EP80219 PCI */ case 1: /* Ethernet i82555 10/100 */ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(0)); return (ICU_INT_XINT(0)); case 2: /* UART */ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(1)); return (ICU_INT_XINT(1)); case 3: /* * The S-ATA chips are behind the bridge, and all of * the S-ATA interrupts are wired together. */ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(2)); return (ICU_INT_XINT(2)); case 4: /* MINI-PIC_INT */ printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(3)); return( ICU_INT_XINT(3)); default: no_mapping: printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin); } return (0); }
static int i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func, int reg, uint32_t *addr) { uint32_t busno; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; /* * If the bus # is the same as our own, then use Type 0 cycles, * else use Type 1. * * XXX We should filter out all non-private devices here! * XXX How does private space interact with PCI-PCI bridges? */ if (bus == busno) { if (slot > (31 - 16)) return (1); /* * NOTE: PCI-X requires that that devices updated their * PCIXSR on every config write with the device number * specified in AD[15:11]. If we don't set this field, * each device could end of thinking it is at device 0, * which can cause a number of problems. Doing this * unconditionally should be OK when only PCI devices * are present. */ bus &= 0xff; slot &= 0x1f; func &= 0x07; *addr = (1U << (slot + 16)) | (slot << 11) | (func << 8) | reg; } else { *addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1; } return (0); }
static int i80321_pci_conf_setup(struct i80321_softc *sc, pcitag_t tag, int offset, struct pciconf_state *ps) { uint32_t busno; i80321_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f); busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; /* * If the bus # is the same as our own, then use Type 0 cycles, * else use Type 1. * * XXX We should filter out all non-private devices here! * XXX How does private space interact with PCI-PCI bridges? */ if (ps->ps_b == busno) { if (ps->ps_d > (31 - 16)) return (1); /* * NOTE: PCI-X requires that devices update their * PCIXSR on every config write with the device number * specified in AD[15:11]. If we don't set this field, * each device could end of thinking it is at device 0, * which can cause a number of problems. Doing this * unconditionally should be OK when only PCI devices * are present. */ ps->ps_addr_val = (1U << (ps->ps_d + 16)) | (ps->ps_d << 11) | (ps->ps_f << 8) | offset; } else { /* The tag is already in the correct format. */ ps->ps_addr_val = tag | offset | 1; } return (0); }
int iq80321_attach(device_t dev) { struct i80321_softc *sc = device_get_softc(dev); int b0u, b0l, b1u, b1l; vm_paddr_t memstart = 0; vm_size_t memsize = 0; int busno; /* * Fill in the space tag for the i80321's own devices, * and hand-craft the space handle for it (the device * was mapped during early bootstrap). */ i80321_bs_init(&i80321_bs_tag, sc); sc->sc_st = &i80321_bs_tag; sc->sc_sh = IQ80321_80321_VBASE; sc->dev = dev; sc->sc_is_host = 1; /* * Slice off a subregion for the Memory Controller -- we need it * here in order read the memory size. */ if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE, VERDE_MCU_SIZE, &sc->sc_mcu_sh)) panic("%s: unable to subregion MCU registers", device_get_name(dev)); if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE, VERDE_ATU_SIZE, &sc->sc_atu_sh)) panic("%s: unable to subregion ATU registers", device_get_name(dev)); /* * We have mapped the PCI I/O windows in the early * bootstrap phase. */ sc->sc_iow_vaddr = IQ80321_IOW_VBASE; /* * Check the configuration of the ATU to see if another BIOS * has configured us. If a PC BIOS didn't configure us, then: * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c. * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c. * If a BIOS has configured us, at least one of those should be * different. This is pretty fragile, but it's not clear what * would work better. */ b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0); b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4); b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8); b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc); #ifdef VERBOSE_INIT_ARM printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", b0l,b0u, b1l, b1u ); #endif #define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 b0l &= PCI_MAPREG_MEM_ADDR_MASK; b0u &= PCI_MAPREG_MEM_ADDR_MASK; b1l &= PCI_MAPREG_MEM_ADDR_MASK; b1u &= PCI_MAPREG_MEM_ADDR_MASK; #ifdef VERBOSE_INIT_ARM printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", b0l,b0u, b1l, b1u ); #endif if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0)) sc->sc_is_host = 0; else sc->sc_is_host = 1; /* FIXME: i force it's */ #ifdef CPU_XSCALE_80219 sc->sc_is_host = 1; #endif i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize); /* * We set up the Inbound Windows as follows: * * 0 Access to i80321 PMMRs * * 1 Reserve space for private devices * * 2 RAM access * * 3 Unused. * * This chunk needs to be customized for each IOP321 application. */ #if 0 sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE; sc->sc_iwin[0].iwin_base_hi = 0; sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE; sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE; #endif if (sc->sc_is_host) { /* Map PCI:Local 1:1. */ sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE | PCI_MAPREG_MEM_PREFETCHABLE_MASK | PCI_MAPREG_MEM_TYPE_64BIT; sc->sc_iwin[1].iwin_base_hi = 0; } else { sc->sc_iwin[1].iwin_base_lo = 0; sc->sc_iwin[1].iwin_base_hi = 0; } sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE; sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE; if (sc->sc_is_host) { sc->sc_iwin[2].iwin_base_lo = memstart | PCI_MAPREG_MEM_PREFETCHABLE_MASK | PCI_MAPREG_MEM_TYPE_64BIT; sc->sc_iwin[2].iwin_base_hi = 0; } else { sc->sc_iwin[2].iwin_base_lo = 0; sc->sc_iwin[2].iwin_base_hi = 0; } sc->sc_iwin[2].iwin_xlate = memstart; sc->sc_iwin[2].iwin_size = memsize; if (sc->sc_is_host) { sc->sc_iwin[3].iwin_base_lo = 0 | PCI_MAPREG_MEM_PREFETCHABLE_MASK | PCI_MAPREG_MEM_TYPE_64BIT; } else { sc->sc_iwin[3].iwin_base_lo = 0; } sc->sc_iwin[3].iwin_base_hi = 0; sc->sc_iwin[3].iwin_xlate = 0; sc->sc_iwin[3].iwin_size = 0; #ifdef VERBOSE_INIT_ARM printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", sc->sc_iwin[1].iwin_base_hi, sc->sc_iwin[1].iwin_base_lo, sc->sc_iwin[1].iwin_xlate, sc->sc_iwin[1].iwin_size ); printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", sc->sc_iwin[2].iwin_base_hi, sc->sc_iwin[2].iwin_base_lo, sc->sc_iwin[2].iwin_xlate, sc->sc_iwin[2].iwin_size ); #endif /* * We set up the Outbound Windows as follows: * * 0 Access to private PCI space. * * 1 Unused. */ #define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) sc->sc_owin[0].owin_xlate_lo = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; /* * Set the Secondary Outbound I/O window to map * to PCI address 0 for all 64K of the I/O space. */ sc->sc_ioout_xlate = 0; i80321_attach(sc); i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate; i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); i80321_dr.dr_len = sc->sc_iwin[2].iwin_size; dma_range_init = 1; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; sc->sc_irq_rman.rm_type = RMAN_ARRAY; sc->sc_irq_rman.rm_descr = "i80321 IRQs"; if (rman_init(&sc->sc_irq_rman) != 0 || rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0) panic("i80321_attach: failed to set up IRQ rman"); device_add_child(dev, "obio", 0); device_add_child(dev, "itimer", 0); device_add_child(dev, "iopwdog", 0); #ifndef CPU_XSCALE_80219 device_add_child(dev, "iqseg", 0); #endif device_add_child(dev, "pcib", busno); device_add_child(dev, "i80321_dma", 0); device_add_child(dev, "i80321_dma", 1); #ifndef CPU_XSCALE_80219 device_add_child(dev, "i80321_aau", 0); #endif bus_generic_probe(dev); bus_generic_attach(dev); return (0); }
/* * i80321_attach: * * Board-independent attach routine for the i80321. */ void i80321_attach(struct i80321_softc *sc) { struct pcibus_attach_args pba; pcireg_t preg; i80321_softc = sc; /* * Slice off some useful subregion handles. */ if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE, VERDE_ATU_SIZE, &sc->sc_atu_sh)) panic("%s: unable to subregion ATU registers\n", sc->sc_dev.dv_xname); /* We expect the Memory Controller to be already sliced off. */ /* * Program the Inbound windows. */ if (sc->sc_is_host) { bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START, sc->sc_iwin[0].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x04, sc->sc_iwin[0].iwin_base_hi); } bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, sc->sc_iwin[0].iwin_xlate); if (sc->sc_is_host) { bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x08, sc->sc_iwin[1].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x0c, sc->sc_iwin[1].iwin_base_hi); } bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); /* no xlate for window 1 */ if (sc->sc_is_host) { bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x10, sc->sc_iwin[2].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x14, sc->sc_iwin[2].iwin_base_hi); } bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, sc->sc_iwin[2].iwin_xlate); if (sc->sc_is_host) { bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); } bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, sc->sc_iwin[3].iwin_xlate); /* * Mask (disable) the ATU interrupt sources. * XXX May want to revisit this if we encounter * XXX an application that wants it. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUIMR, ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| ATUIMR_PTAT|ATUIMR_PMPE); /* * Program the outbound windows. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOWTVR, sc->sc_ioout_xlate); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); /* * Set up the ATU configuration register. All we do * right now is enable Outbound Windows. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, ATUCR_OUT_EN); /* * Enable bus mastering, memory access, SERR, and parity * checking on the ATU. */ if (sc->sc_is_host) { preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_COMMAND_STATUS_REG); preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_COMMAND_STATUS_REG, preg); } /* * Initialize the bus space and DMA tags and the PCI chipset tag. */ i80321_io_bs_init(&sc->sc_pci_iot, sc); i80321_mem_bs_init(&sc->sc_pci_memt, sc); i80321_pci_dma_init(&sc->sc_pci_dmat, sc); i80321_pci_init(&sc->sc_pci_chipset, sc); /* * Attach the PCI bus. */ preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); preg = PCIXSR_BUSNO(preg); if (preg == 0xff) preg = 0; pba.pba_busname = "pci"; pba.pba_iot = &sc->sc_pci_iot; pba.pba_memt = &sc->sc_pci_memt; pba.pba_dmat = &sc->sc_pci_dmat; pba.pba_pc = &sc->sc_pci_chipset; pba.pba_bus = preg; pba.pba_bridgetag = NULL; pba.pba_intrswiz = 0; /* XXX what if busno != 0? */ pba.pba_intrtag = 0; pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; (void) config_found(&sc->sc_dev, &pba, i80321_pcibus_print); }
int hdlg_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct i80321_softc *sc = pa->pa_pc->pc_intr_v; uint32_t busno; int b, d, f; /* * GigaLANDISK's interrupts are routed like so: * * XINT0 Intel i82541PI Gig-E * * XINT1 ACARD ATP875-A * * XINT2 NEC echi/ochi * * XINT3 UART */ busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f); /* No mappings for devices not on our bus. */ if (b != busno) goto no_mapping; switch (d) { case 1: /* i82541PI Gig-E */ if (pa->pa_intrpin == 1) { *ihp = ICU_INT_XINT(0); return 0; } goto no_mapping; case 2: /* ATP875-A */ if (pa->pa_intrpin == 1) { *ihp = ICU_INT_XINT(1); return 0; } goto no_mapping; case 3: /* echi/ochi */ switch (pa->pa_intrpin) { case 1: /* ohci */ case 2: /* ohci */ case 3: /* ehci */ *ihp = ICU_INT_XINT(2); return 0; } goto no_mapping; default: no_mapping: printf("hdlg_pci_intr_map: no mapping for %d/%d/%d\n", pa->pa_bus, pa->pa_device, pa->pa_function); return 1; } return 0; }
/* * i80321_attach: * * Board-independent attach routine for the i80321. */ void i80321_attach(struct i80321_softc *sc) { struct pcibus_attach_args pba; const struct iopxs_device *id; struct iopxs_attach_args ia; pcireg_t preg; i80321_softc = sc; /* * Program the Inbound windows. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, sc->sc_iwin[0].iwin_xlate); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START, sc->sc_iwin[0].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x04, sc->sc_iwin[0].iwin_base_hi); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); /* no xlate for window 1 */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x08, sc->sc_iwin[1].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x0c, sc->sc_iwin[1].iwin_base_hi); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, sc->sc_iwin[2].iwin_xlate); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x10, sc->sc_iwin[2].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START + 0x14, sc->sc_iwin[2].iwin_base_hi); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, sc->sc_iwin[3].iwin_xlate); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); /* * Mask (disable) the ATU interrupt sources. * XXX May want to revisit this if we encounter * XXX an application that wants it. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUIMR, ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| ATUIMR_PTAT|ATUIMR_PMPE); /* * Program the outbound windows. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OIOWTVR, sc->sc_ioout_xlate); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); /* * Set up the ATU configuration register. All we do * right now is enable Outbound Windows. */ bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, ATUCR_OUT_EN); /* * Enable bus mastering, memory access, SERR, and parity * checking on the ATU. */ preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_COMMAND_STATUS_REG); preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; bus_space_write_4(sc->sc_st, sc->sc_atu_sh, PCI_COMMAND_STATUS_REG, preg); /* Initialize the bus space tags. */ i80321_io_bs_init(&sc->sc_pci_iot, sc); i80321_mem_bs_init(&sc->sc_pci_memt, sc); /* Initialize the DMA tags. */ i80321_pci_dma_init(sc); i80321_local_dma_init(sc); /* * Attach all the IOP built-ins. */ for (id = iopxs_devices; id->id_name != NULL; id++) { ia.ia_name = id->id_name; ia.ia_st = sc->sc_st; ia.ia_sh = sc->sc_sh; ia.ia_dmat = &sc->sc_local_dmat; ia.ia_offset = id->id_offset; ia.ia_size = id->id_size; config_found(&sc->sc_dev, &ia, i80321_iopxs_print); } /* * Attach the PCI bus. */ preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); preg = PCIXSR_BUSNO(preg); if (preg == 0xff) preg = 0; pba.pba_busname = "pci"; pba.pba_iot = &sc->sc_pci_iot; pba.pba_memt = &sc->sc_pci_memt; pba.pba_dmat = &sc->sc_pci_dmat; pba.pba_pc = &sc->sc_pci_chipset; pba.pba_domain = pci_ndomains++; pba.pba_bus = preg; pba.pba_bridgetag = NULL; pba.pba_intrswiz = 0; /* XXX what if busno != 0? */ pba.pba_intrtag = 0; config_found((struct device *)sc, &pba, i80321_iopxs_print); }