📄 pic.c
字号:
pcibr_soft->bs_moduleid = iomoduleid_get(pcibr_soft->bs_nasid); if (pcibr_soft->bs_bricktype > 0) { switch (pcibr_soft->bs_bricktype) { case MODULE_PXBRICK: case MODULE_IXBRICK: case MODULE_OPUSBRICK: pcibr_soft->bs_first_slot = 0; pcibr_soft->bs_last_slot = 1; pcibr_soft->bs_last_reset = 1; /* Bus 1 of IXBrick has a IO9, so there are 4 devices, not 2 */ if ((pcibr_widget_to_bus(pcibr_vhdl) == 1) && isIO9(pcibr_soft->bs_nasid)) { pcibr_soft->bs_last_slot = 3; pcibr_soft->bs_last_reset = 3; } break; case MODULE_CGBRICK: pcibr_soft->bs_first_slot = 0; pcibr_soft->bs_last_slot = 0; pcibr_soft->bs_last_reset = 0; break; default: printk(KERN_WARNING "%s: Unknown bricktype: 0x%x\n", pcibr_soft->bs_name, pcibr_soft->bs_bricktype); break; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pic_attach2: bricktype=%d, brickbus=%d, " "slots %d-%d\n", pcibr_soft->bs_bricktype, pcibr_widget_to_bus(pcibr_vhdl), pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot)); } /* * Initialize bridge and bus locks */ spin_lock_init(&pcibr_soft->bs_lock); /* * If we have one, process the hints structure. */ if (pcibr_hints) { unsigned rrb_fixed; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, pcibr_vhdl, "pic_attach2: pcibr_hints=0x%lx\n", pcibr_hints)); rrb_fixed = pcibr_hints->ph_rrb_fixed; pcibr_soft->bs_rrb_fixed = rrb_fixed; if (pcibr_hints->ph_intr_bits) pcibr_soft->bs_intr_bits = pcibr_hints->ph_intr_bits; for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { int hslot = pcibr_hints->ph_host_slot[slot] - 1; if (hslot < 0) { pcibr_soft->bs_slot[slot].host_slot = slot; } else { pcibr_soft->bs_slot[slot].has_host = 1; pcibr_soft->bs_slot[slot].host_slot = hslot; } } } /* * Set-up initial values for state fields */ for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE; pcibr_soft->bs_slot[slot].bss_devio.bssd_ref_cnt = 0; pcibr_soft->bs_slot[slot].bss_d64_base = PCIBR_D64_BASE_UNSET; pcibr_soft->bs_slot[slot].bss_d32_base = PCIBR_D32_BASE_UNSET; pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] = -1; } for (ibit = 0; ibit < 8; ++ibit) { pcibr_soft->bs_intr[ibit].bsi_xtalk_intr = 0; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_soft = pcibr_soft; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_list = NULL; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_ibit = ibit; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_hdlrcnt = 0; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_shared = 0; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_connected = 0; } /* * connect up our error handler. PIC has 2 busses (thus resulting in 2 * pcibr_soft structs under 1 widget), so only register a xwidget error * handler for PIC's bus0. NOTE: for PIC pcibr_error_handler_wrapper() * is a wrapper routine we register that will call the real error handler * pcibr_error_handler() with the correct pcibr_soft struct. */ if (busnum == 0) { xwidget_error_register(xconn_vhdl, pcibr_error_handler_wrapper, pcibr_soft); } /* * Clear all pending interrupts. Assume all interrupts are from slot 3 * until otherise setup. */ pcireg_intr_reset_set(pcibr_soft, PIC_IRR_ALL_CLR); pcireg_intr_device_set(pcibr_soft, 0x006db6db); /* Setup the mapping register used for direct mapping */ pcibr_directmap_init(pcibr_soft); /* * Initialize the PICs control register. */ pic_ctrl_reg = pcireg_control_get(pcibr_soft); /* Bridges Requester ID: bus = busnum, dev = 0, func = 0 */ pic_ctrl_reg &= ~PIC_CTRL_BUS_NUM_MASK; pic_ctrl_reg |= PIC_CTRL_BUS_NUM(busnum); pic_ctrl_reg &= ~PIC_CTRL_DEV_NUM_MASK; pic_ctrl_reg &= ~PIC_CTRL_FUN_NUM_MASK; pic_ctrl_reg &= ~PIC_CTRL_NO_SNOOP; pic_ctrl_reg &= ~PIC_CTRL_RELAX_ORDER; /* enable parity checking on PICs internal RAM */ pic_ctrl_reg |= PIC_CTRL_PAR_EN_RESP; pic_ctrl_reg |= PIC_CTRL_PAR_EN_ATE; /* PIC BRINGUP WAR (PV# 862253): dont enable write request parity */ if (!PCIBR_WAR_ENABLED(PV862253, pcibr_soft)) { pic_ctrl_reg |= PIC_CTRL_PAR_EN_REQ; } pic_ctrl_reg |= PIC_CTRL_PAGE_SIZE; pcireg_control_set(pcibr_soft, pic_ctrl_reg); /* Initialize internal mapping entries (ie. the ATEs) */ for (entry = 0; entry < pcibr_soft->bs_int_ate_size; entry++) pcireg_int_ate_set(pcibr_soft, entry, 0); pcibr_soft->bs_int_ate_resource.start = 0; pcibr_soft->bs_int_ate_resource.end = pcibr_soft->bs_int_ate_size - 1; /* Setup the PICs error interrupt handler. */ xtalk_intr = xtalk_intr_alloc(xconn_vhdl, (device_desc_t)0, pcibr_vhdl); ASSERT(xtalk_intr != NULL); irq = ((hub_intr_t)xtalk_intr)->i_bit; cpu = ((hub_intr_t)xtalk_intr)->i_cpuid; intr_unreserve_level(cpu, irq); ((hub_intr_t)xtalk_intr)->i_bit = SGI_PCIBR_ERROR; xtalk_intr->xi_vector = SGI_PCIBR_ERROR; pcibr_soft->bsi_err_intr = xtalk_intr; /* * On IP35 with XBridge, we do some extra checks in pcibr_setwidint * in order to work around some addressing limitations. In order * for that fire wall to work properly, we need to make sure we * start from a known clean state. */ pcibr_clearwidint(pcibr_soft); xtalk_intr_connect(xtalk_intr, (intr_func_t) pcibr_error_intr_handler, (intr_arg_t) pcibr_soft, (xtalk_intr_setfunc_t) pcibr_setwidint, (void *) pcibr_soft); request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, SA_SHIRQ, "PCIBR error", (intr_arg_t) pcibr_soft); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_vhdl, "pcibr_setwidint: target_id=0x%lx, int_addr=0x%lx\n", pcireg_intr_dst_target_id_get(pcibr_soft), pcireg_intr_dst_addr_get(pcibr_soft))); /* now we can start handling error interrupts */ int_enable = pcireg_intr_enable_get(pcibr_soft); int_enable |= PIC_ISR_ERRORS; /* PIC BRINGUP WAR (PV# 856864 & 856865): allow the tnums that are * locked out to be freed up sooner (by timing out) so that the * read tnums are never completely used up. */ if (PCIBR_WAR_ENABLED(PV856864, pcibr_soft)) { int_enable &= ~PIC_ISR_PCIX_REQ_TOUT; int_enable &= ~PIC_ISR_XREAD_REQ_TIMEOUT; pcireg_req_timeout_set(pcibr_soft, 0x750); } pcireg_intr_enable_set(pcibr_soft, int_enable); pcireg_intr_mode_set(pcibr_soft, 0); /* dont send 'clear interrupt' pkts */ pcireg_tflush_get(pcibr_soft); /* wait until Bridge PIO complete */ /* * PIC BRINGUP WAR (PV# 856866, 859504, 861476, 861478): Don't use * RRB0, RRB8, RRB1, and RRB9. Assign them to DEVICE[2|3]--VCHAN3 * so they are not used. This works since there is currently no * API to penable VCHAN3. */ if (PCIBR_WAR_ENABLED(PV856866, pcibr_soft)) { pcireg_rrb_bit_set(pcibr_soft, 0, 0x000f000f); /* even rrb reg */ pcireg_rrb_bit_set(pcibr_soft, 1, 0x000f000f); /* odd rrb reg */ } /* PIC only supports 64-bit direct mapping in PCI-X mode. Since * all PCI-X devices that initiate memory transactions must be * capable of generating 64-bit addressed, we force 64-bit DMAs. */ pcibr_soft->bs_dma_flags = 0; if (IS_PCIX(pcibr_soft)) { pcibr_soft->bs_dma_flags |= PCIIO_DMA_A64; } { iopaddr_t prom_base_addr = pcibr_soft->bs_xid << 24; int prom_base_size = 0x1000000; int status; struct resource *res; /* Allocate resource maps based on bus page size; for I/O and memory * space, free all pages except those in the base area and in the * range set by the PROM. * * PROM creates BAR addresses in this format: 0x0ws00000 where w is * the widget number and s is the device register offset for the slot. */ /* Setup the Bus's PCI IO Root Resource. */ pcibr_soft->bs_io_win_root_resource.start = PCIBR_BUS_IO_BASE; pcibr_soft->bs_io_win_root_resource.end = 0xffffffff; res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL); if (!res) panic("PCIBR:Unable to allocate resource structure\n"); /* Block off the range used by PROM. */ res->start = prom_base_addr; res->end = prom_base_addr + (prom_base_size - 1); status = request_resource(&pcibr_soft->bs_io_win_root_resource, res); if (status) panic("PCIBR:Unable to request_resource()\n"); /* Setup the Small Window Root Resource */ pcibr_soft->bs_swin_root_resource.start = PAGE_SIZE; pcibr_soft->bs_swin_root_resource.end = 0x000FFFFF; /* Setup the Bus's PCI Memory Root Resource */ pcibr_soft->bs_mem_win_root_resource.start = 0x200000; pcibr_soft->bs_mem_win_root_resource.end = 0xffffffff; res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL); if (!res) panic("PCIBR:Unable to allocate resource structure\n"); /* Block off the range used by PROM. */ res->start = prom_base_addr; res->end = prom_base_addr + (prom_base_size - 1); status = request_resource(&pcibr_soft->bs_mem_win_root_resource, res); if (status) panic("PCIBR:Unable to request_resource()\n"); } /* build "no-slot" connection point */ pcibr_info = pcibr_device_info_new(pcibr_soft, PCIIO_SLOT_NONE, PCIIO_FUNC_NONE, PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE); noslot_conn = pciio_device_info_register(pcibr_vhdl, &pcibr_info->f_c); /* Store no slot connection point info for tearing it down during detach. */ pcibr_soft->bs_noslot_conn = noslot_conn; pcibr_soft->bs_noslot_info = pcibr_info; for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Find out what is out there */ (void)pcibr_slot_info_init(pcibr_vhdl, slot); } for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Set up the address space for this slot in the PCI land */ (void)pcibr_slot_addr_space_init(pcibr_vhdl, slot); } for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Setup the device register */ (void)pcibr_slot_device_init(pcibr_vhdl, slot); } if (IS_PCIX(pcibr_soft)) { pcibr_soft->bs_pcix_rbar_inuse = 0; pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR; pcibr_soft->bs_pcix_rbar_percent_allowed = pcibr_pcix_rbars_calc(pcibr_soft); for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Setup the PCI-X Read Buffer Attribute Registers (RBARs) */ (void)pcibr_slot_pcix_rbar_init(pcibr_soft, slot); } } for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Setup host/guest relations */ (void)pcibr_slot_guest_info_init(pcibr_vhdl, slot); } /* Handle initial RRB management */ pcibr_initial_rrb(pcibr_vhdl, pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot); /* Before any drivers get called that may want to re-allocate RRB's, * let's get some special cases pre-allocated. Drivers may override * these pre-allocations, but by doing pre-allocations now we're * assured not to step all over what the driver intended. */ if (pcibr_soft->bs_bricktype > 0) { switch (pcibr_soft->bs_bricktype) { case MODULE_PXBRICK: case MODULE_IXBRICK: case MODULE_OPUSBRICK: /* * If IO9 in bus 1, allocate RRBs to all the IO9 devices */ if ((pcibr_widget_to_bus(pcibr_vhdl) == 1) && (pcibr_soft->bs_slot[0].bss_vendor_id == 0x10A9) && (pcibr_soft->bs_slot[0].bss_device_id == 0x100A)) { pcibr_rrb_alloc_init(pcibr_soft, 0, VCHAN0, 4); pcibr_rrb_alloc_init(pcibr_soft, 1, VCHAN0, 4); pcibr_rrb_alloc_init(pcibr_soft, 2, VCHAN0, 4); pcibr_rrb_alloc_init(pcibr_soft, 3, VCHAN0, 4); } else { pcibr_rrb_alloc_init(pcibr_soft, 0, VCHAN0, 4); pcibr_rrb_alloc_init(pcibr_soft, 1, VCHAN0, 4); } break; case MODULE_CGBRICK: pcibr_rrb_alloc_init(pcibr_soft, 0, VCHAN0, 8); break; } /* switch */ } for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Call the device attach */ (void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0); } pciio_device_attach(noslot_conn, 0); return 0;}/* * pci provider functions * * mostly in pcibr.c but if any are needed here then * this might be a way to get them here. */pciio_provider_t pci_pic_provider ={ PCIIO_ASIC_TYPE_PIC, (pciio_piomap_alloc_f *) pcibr_piomap_alloc, (pciio_piomap_free_f *) pcibr_piomap_free, (pciio_piomap_addr_f *) pcibr_piomap_addr, (pciio_piomap_done_f *) pcibr_piomap_done, (pciio_piotrans_addr_f *) pcibr_piotrans_addr, (pciio_piospace_alloc_f *) pcibr_piospace_alloc, (pciio_piospace_free_f *) pcibr_piospace_free, (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc, (pciio_dmamap_free_f *) pcibr_dmamap_free, (pciio_dmamap_addr_f *) pcibr_dmamap_addr, (pciio_dmamap_done_f *) pcibr_dmamap_done, (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr, (pciio_dmamap_drain_f *) pcibr_dmamap_drain, (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain, (pciio_intr_alloc_f *) pcibr_intr_alloc, (pciio_intr_free_f *) pcibr_intr_free, (pciio_intr_connect_f *) pcibr_intr_connect, (pciio_intr_disconnect_f *) pcibr_intr_disconnect, (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get, (pciio_provider_startup_f *) pcibr_provider_startup, (pciio_provider_shutdown_f *) pcibr_provider_shutdown, (pciio_reset_f *) pcibr_reset, (pciio_endian_set_f *) pcibr_endian_set, (pciio_config_get_f *) pcibr_config_get, (pciio_config_set_f *) pcibr_config_set, (pciio_error_extract_f *) pcibr_error_extract, (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback, (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback, (pciio_device_unregister_f *) pcibr_device_unregister,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -