📄 pcibr.c
字号:
break; } if (COPYIN(arg, &req, sizeof(req))) { error = EFAULT; break; } error = pcibr_slot_query(pcibr_vhdl, &req); break; }#endif /* LATER */ default: break; } return error;}voidpcibr_freeblock_sub(iopaddr_t *free_basep, iopaddr_t *free_lastp, iopaddr_t base, size_t size){ iopaddr_t free_base = *free_basep; iopaddr_t free_last = *free_lastp; iopaddr_t last = base + size - 1; if ((last < free_base) || (base > free_last)); /* free block outside arena */ else if ((base <= free_base) && (last >= free_last)) /* free block contains entire arena */ *free_basep = *free_lastp = 0; else if (base <= free_base) /* free block is head of arena */ *free_basep = last + 1; else if (last >= free_last) /* free block is tail of arena */ *free_lastp = base - 1; /* * We are left with two regions: the free area * in the arena "below" the block, and the free * area in the arena "above" the block. Keep * the one that is bigger. */ else if ((base - free_base) > (free_last - last)) *free_lastp = base - 1; /* keep lower chunk */ else *free_basep = last + 1; /* keep upper chunk */}/* Convert from ssram_bits in control register to number of SSRAM entries */#define ATE_NUM_ENTRIES(n) _ate_info[n]/* Possible choices for number of ATE entries in Bridge's SSRAM */LOCAL int _ate_info[] ={ 0, /* 0 entries */ 8 * 1024, /* 8K entries */ 16 * 1024, /* 16K entries */ 64 * 1024 /* 64K entries */};#define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int))#define ATE_PROBE_VALUE 0x0123456789abcdefULL/* * Determine the size of this bridge's external mapping SSRAM, and set * the control register appropriately to reflect this size, and initialize * the external SSRAM. */LOCAL intpcibr_init_ext_ate_ram(bridge_t *bridge){ int largest_working_size = 0; int num_entries, entry; int i, j; bridgereg_t old_enable, new_enable; int s; /* Probe SSRAM to determine its size. */ old_enable = bridge->b_int_enable; new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; bridge->b_int_enable = new_enable; for (i = 1; i < ATE_NUM_SIZES; i++) { /* Try writing a value */ bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE; /* Guard against wrap */ for (j = 1; j < i; j++) bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(j) - 1] = 0; /* See if value was written */ if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE) largest_working_size = i; } bridge->b_int_enable = old_enable; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ /* * ensure that we write and read without any interruption. * The read following the write is required for the Bridge war */ s = splhi(); bridge->b_wid_control = (bridge->b_wid_control & ~BRIDGE_CTRL_SSRAM_SIZE_MASK) | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size); bridge->b_wid_control; /* inval addr bug war */ splx(s); num_entries = ATE_NUM_ENTRIES(largest_working_size);#if PCIBR_ATE_DEBUG if (num_entries) printk("bridge at 0x%x: clearing %d external ATEs\n", bridge, num_entries); else printk("bridge at 0x%x: no externa9422l ATE RAM found\n", bridge);#endif /* Initialize external mapping entries */ for (entry = 0; entry < num_entries; entry++) bridge->b_ext_ate_ram[entry] = 0; return (num_entries);}/* * Allocate "count" contiguous Bridge Address Translation Entries * on the specified bridge to be used for PCI to XTALK mappings. * Indices in rm map range from 1..num_entries. Indicies returned * to caller range from 0..num_entries-1. * * Return the start index on success, -1 on failure. */LOCAL intpcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count){ int index = 0; index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count);/* printk("Colin: pcibr_ate_alloc - index %d count %d \n", index, count); */ if (!index && pcibr_soft->bs_ext_ate_map) index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count); /* rmalloc manages resources in the 1..n * range, with 0 being failure. * pcibr_ate_alloc manages resources * in the 0..n-1 range, with -1 being failure. */ return index - 1;}LOCAL voidpcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count)/* Who says there's no such thing as a free meal? :-) */{ /* note the "+1" since rmalloc handles 1..n but * we start counting ATEs at zero. *//* printk("Colin: pcibr_ate_free - index %d count %d\n", index, count); */ rmfree((index < pcibr_soft->bs_int_ate_size) ? pcibr_soft->bs_int_ate_map : pcibr_soft->bs_ext_ate_map, count, index + 1);}LOCAL pcibr_info_tpcibr_info_get(devfs_handle_t vhdl){ return (pcibr_info_t) pciio_info_get(vhdl);}pcibr_info_tpcibr_device_info_new( pcibr_soft_t pcibr_soft, pciio_slot_t slot, pciio_function_t rfunc, pciio_vendor_id_t vendor, pciio_device_id_t device){ pcibr_info_t pcibr_info; pciio_function_t func; int ibit; func = (rfunc == PCIIO_FUNC_NONE) ? 0 : rfunc; NEW(pcibr_info); pciio_device_info_new(&pcibr_info->f_c, pcibr_soft->bs_vhdl, slot, rfunc, vendor, device); if (slot != PCIIO_SLOT_NONE) { /* * Currently favored mapping from PCI * slot number and INTA/B/C/D to Bridge * PCI Interrupt Bit Number: * * SLOT A B C D * 0 0 4 0 4 * 1 1 5 1 5 * 2 2 6 2 6 * 3 3 7 3 7 * 4 4 0 4 0 * 5 5 1 5 1 * 6 6 2 6 2 * 7 7 3 7 3 * * XXX- allow pcibr_hints to override default * XXX- allow ADMIN to override pcibr_hints */ for (ibit = 0; ibit < 4; ++ibit) pcibr_info->f_ibit[ibit] = (slot + 4 * ibit) & 7; /* * Record the info in the sparse func info space. */ if (func < pcibr_soft->bs_slot[slot].bss_ninfo) pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info; } return pcibr_info;}voidpcibr_device_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); pcibr_info_t pcibr_info; pciio_function_t func; pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[slot]; int nfunc = slotp->bss_ninfo; for (func = 0; func < nfunc; func++) { pcibr_info = slotp->bss_infos[func]; if (!pcibr_info) continue; slotp->bss_infos[func] = 0; pciio_device_info_unregister(pcibr_vhdl, &pcibr_info->f_c); pciio_device_info_free(&pcibr_info->f_c); DEL(pcibr_info); } /* Clear the DEVIO(x) for this slot */ slotp->bss_devio.bssd_space = PCIIO_SPACE_NONE; slotp->bss_devio.bssd_base = PCIBR_D32_BASE_UNSET; slotp->bss_device = 0; /* Reset the mapping usage counters */ slotp->bss_pmu_uctr = 0; slotp->bss_d32_uctr = 0; slotp->bss_d64_uctr = 0; /* Clear the Direct translation info */ slotp->bss_d64_base = PCIBR_D64_BASE_UNSET; slotp->bss_d64_flags = 0; slotp->bss_d32_base = PCIBR_D32_BASE_UNSET; slotp->bss_d32_flags = 0; /* Clear out shadow info necessary for the external SSRAM workaround */ slotp->bss_ext_ates_active = ATOMIC_INIT(0); slotp->bss_cmd_pointer = 0; slotp->bss_cmd_shadow = 0;}/* * PCI_ADDR_SPACE_LIMITS_LOAD * Gets the current values of * pci io base, * pci io last, * pci low memory base, * pci low memory last, * pci high memory base, * pci high memory last */#define PCI_ADDR_SPACE_LIMITS_LOAD() \ pci_io_fb = pcibr_soft->bs_spinfo.pci_io_base; \ pci_io_fl = pcibr_soft->bs_spinfo.pci_io_last; \ pci_lo_fb = pcibr_soft->bs_spinfo.pci_swin_base; \ pci_lo_fl = pcibr_soft->bs_spinfo.pci_swin_last; \ pci_hi_fb = pcibr_soft->bs_spinfo.pci_mem_base; \ pci_hi_fl = pcibr_soft->bs_spinfo.pci_mem_last;/* * PCI_ADDR_SPACE_LIMITS_STORE * Sets the current values of * pci io base, * pci io last, * pci low memory base, * pci low memory last, * pci high memory base, * pci high memory last */#define PCI_ADDR_SPACE_LIMITS_STORE() \ pcibr_soft->bs_spinfo.pci_io_base = pci_io_fb; \ pcibr_soft->bs_spinfo.pci_io_last = pci_io_fl; \ pcibr_soft->bs_spinfo.pci_swin_base = pci_lo_fb; \ pcibr_soft->bs_spinfo.pci_swin_last = pci_lo_fl; \ pcibr_soft->bs_spinfo.pci_mem_base = pci_hi_fb; \ pcibr_soft->bs_spinfo.pci_mem_last = pci_hi_fl;#define PCI_ADDR_SPACE_LIMITS_PRINT() \ printf("+++++++++++++++++++++++\n" \ "IO base 0x%x last 0x%x\n" \ "SWIN base 0x%x last 0x%x\n" \ "MEM base 0x%x last 0x%x\n" \ "+++++++++++++++++++++++\n", \ pcibr_soft->bs_spinfo.pci_io_base, \ pcibr_soft->bs_spinfo.pci_io_last, \ pcibr_soft->bs_spinfo.pci_swin_base, \ pcibr_soft->bs_spinfo.pci_swin_last, \ pcibr_soft->bs_spinfo.pci_mem_base, \ pcibr_soft->bs_spinfo.pci_mem_last);/* * pcibr_slot_info_init * Probe for this slot and see if it is populated. * If it is populated initialize the generic PCI infrastructural * information associated with this particular PCI device. */intpcibr_slot_info_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; bridge_t *bridge; cfg_p cfgw; unsigned idword; unsigned pfail; unsigned idwords[8]; pciio_vendor_id_t vendor; pciio_device_id_t device; unsigned htype; cfg_p wptr; int win; pciio_space_t space; iopaddr_t pci_io_fb, pci_io_fl; iopaddr_t pci_lo_fb, pci_lo_fl; iopaddr_t pci_hi_fb, pci_hi_fl; int nfunc; pciio_function_t rfunc; int func; devfs_handle_t conn_vhdl; pcibr_soft_slot_t slotp; /* Get the basic software information required to proceed */ pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) return(EINVAL); bridge = pcibr_soft->bs_base; if (!PCIBR_VALID_SLOT(slot)) return(EINVAL); /* If we have a host slot (eg:- IOC3 has 2 PCI slots and the initialization * is done by the host slot then we are done. */ if (pcibr_soft->bs_slot[slot].has_host) { return(0); } /* Check for a slot with any system critical functions */ if (pcibr_is_slot_sys_critical(pcibr_vhdl, slot)) return(EPERM); /* Load the current values of allocated PCI address spaces */ PCI_ADDR_SPACE_LIMITS_LOAD(); /* Try to read the device-id/vendor-id from the config space */ cfgw = bridge->b_type0_cfg_dev[slot].l; if (pcibr_probe_slot(bridge, cfgw, &idword)) return(ENODEV); slotp = &pcibr_soft->bs_slot[slot]; slotp->slot_status |= SLOT_POWER_UP; vendor = 0xFFFF & idword; /* If the vendor id is not valid then the slot is not populated * and we are done. */ if (vendor == 0xFFFF) return(ENODEV); device = 0xFFFF & (idword >> 16); htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1); nfunc = 1; rfunc = PCIIO_FUNC_NONE; pfail = 0; /* NOTE: if a card claims to be multifunction * but only responds to config space 0, treat * it as a unifunction card. */ if (htype & 0x80) { /* MULTIFUNCTION */ for (func = 1; func < 8; ++func) { cfgw = bridge->b_type0_cfg_dev[slot].f[func].l; if (pcibr_probe_slot(bridge, cfgw, &idwords[func])) { pfail |= 1 << func; continue; } vendor = 0xFFFF & idwords[func]; if (vendor == 0xFFFF) { pfail |= 1 << func; continue; } nfunc = func + 1; rfunc = 0; } cfgw = bridge->b_type0_cfg_dev[slot]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -