📄 pcibr_dvr.c
字号:
| BRIDGE_DEV_BARRIER; /* barrier on */ } /* Generic detail flags */ if (flags & PCIIO_WRITE_GATHER) new |= BRIDGE_DEV_WRGA_BITS; if (flags & PCIIO_NOWRITE_GATHER) new &= ~BRIDGE_DEV_WRGA_BITS; if (flags & PCIIO_PREFETCH) new |= BRIDGE_DEV_PREF; if (flags & PCIIO_NOPREFETCH) new &= ~BRIDGE_DEV_PREF; if (flags & PCIBR_WRITE_GATHER) new |= BRIDGE_DEV_WRGA_BITS; if (flags & PCIBR_NOWRITE_GATHER) new &= ~BRIDGE_DEV_WRGA_BITS; if (flags & PCIIO_BYTE_STREAM) new |= (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) ? BRIDGE_DEV_SWAP_DIR : BRIDGE_DEV_SWAP_BITS; if (flags & PCIIO_WORD_VALUES) new &= (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) ? ~BRIDGE_DEV_SWAP_DIR : ~BRIDGE_DEV_SWAP_BITS; /* Provider-specific flags */ if (flags & PCIBR_PREFETCH) new |= BRIDGE_DEV_PREF; if (flags & PCIBR_NOPREFETCH) new &= ~BRIDGE_DEV_PREF; if (flags & PCIBR_PRECISE) new |= BRIDGE_DEV_PRECISE; if (flags & PCIBR_NOPRECISE) new &= ~BRIDGE_DEV_PRECISE; if (flags & PCIBR_BARRIER) new |= BRIDGE_DEV_BARRIER; if (flags & PCIBR_NOBARRIER) new &= ~BRIDGE_DEV_BARRIER; if (flags & PCIBR_64BIT) new |= BRIDGE_DEV_DEV_SIZE; if (flags & PCIBR_NO64BIT) new &= ~BRIDGE_DEV_DEV_SIZE; /* * PIC BRINGUP WAR (PV# 855271): * Allow setting BRIDGE_DEV_VIRTUAL_EN on PIC iff we're a 64-bit * device. The bit is only intended for 64-bit devices and, on * PIC, can cause problems for 32-bit devices. */ if (IS_PIC_SOFT(pcibr_soft) && mask == BRIDGE_DEV_D64_BITS && PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) { if (flags & PCIBR_VCHAN1) { new |= BRIDGE_DEV_VIRTUAL_EN; xmask |= BRIDGE_DEV_VIRTUAL_EN; } } chg = old ^ new; /* what are we changing, */ chg &= xmask; /* of the interesting bits */ if (chg) { badd32 = slotp->bss_d32_uctr ? (BRIDGE_DEV_D32_BITS & chg) : 0; if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0; badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0; } else { badpmu = slotp->bss_pmu_uctr ? (BRIDGE_DEV_PMU_BITS & chg) : 0; badd64 = slotp->bss_d64_uctr ? (BRIDGE_DEV_D64_BITS & chg) : 0; } bad = badpmu | badd32 | badd64; if (bad) { /* some conflicts can be resolved by * forcing the bit on. this may cause * some performance degredation in * the stream(s) that want the bit off, * but the alternative is not allowing * the new stream at all. */ if ( (fix = bad & (BRIDGE_DEV_PRECISE | BRIDGE_DEV_BARRIER)) ) { bad &= ~fix; /* don't change these bits if * they are already set in "old" */ chg &= ~(fix & old); } /* some conflicts can be resolved by * forcing the bit off. this may cause * some performance degredation in * the stream(s) that want the bit on, * but the alternative is not allowing * the new stream at all. */ if ( (fix = bad & (BRIDGE_DEV_WRGA_BITS | BRIDGE_DEV_PREF)) ) { bad &= ~fix; /* don't change these bits if * we wanted to turn them on. */ chg &= ~(fix & new); } /* conflicts in other bits mean * we can not establish this DMA * channel while the other(s) are * still present. */ if (bad) { pcibr_unlock(pcibr_soft, s);#ifdef PIC_LATER PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl, "pcibr_try_set_device: mod blocked by %x\n", bad, device_bits));#endif return bad; } } } if (mask == BRIDGE_DEV_PMU_BITS) slotp->bss_pmu_uctr++; if (mask == BRIDGE_DEV_D32_BITS) slotp->bss_d32_uctr++; if (mask == BRIDGE_DEV_D64_BITS) slotp->bss_d64_uctr++; /* the value we want to write is the * original value, with the bits for * our selected changes flipped, and * with any disabled features turned off. */ new = old ^ chg; /* only change what we want to change */ if (slotp->bss_device == new) { pcibr_unlock(pcibr_soft, s); return 0; } if ( IS_PIC_SOFT(pcibr_soft) ) { bridge->b_device[slot].reg = new; slotp->bss_device = new; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } else { if (io_get_sh_swapper(NASID_GET(bridge))) { BRIDGE_REG_SET32((&bridge->b_device[slot].reg)) = __swab32(new); slotp->bss_device = new; BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */ } else { bridge->b_device[slot].reg = new; slotp->bss_device = new; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } } pcibr_unlock(pcibr_soft, s);#ifdef PIC_LATER PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl, "pcibr_try_set_device: Device(%d): %x\n", slot, new, device_bits));#else printk("pcibr_try_set_device: Device(%d): %x\n", slot, new);#endif return 0;}voidpcibr_release_device(pcibr_soft_t pcibr_soft, pciio_slot_t slot, bridgereg_t mask){ pcibr_soft_slot_t slotp; unsigned long s; slotp = &pcibr_soft->bs_slot[slot]; s = pcibr_lock(pcibr_soft); if (mask == BRIDGE_DEV_PMU_BITS) slotp->bss_pmu_uctr--; if (mask == BRIDGE_DEV_D32_BITS) slotp->bss_d32_uctr--; if (mask == BRIDGE_DEV_D64_BITS) slotp->bss_d64_uctr--; pcibr_unlock(pcibr_soft, s);}/* * flush write gather buffer for slot */static voidpcibr_device_write_gather_flush(pcibr_soft_t pcibr_soft, pciio_slot_t slot){ bridge_t *bridge; unsigned long s; volatile uint32_t wrf; s = pcibr_lock(pcibr_soft); bridge = pcibr_soft->bs_base; if ( IS_PIC_SOFT(pcibr_soft) ) { wrf = bridge->b_wr_req_buf[slot].reg; } else { if (io_get_sh_swapper(NASID_GET(bridge))) { wrf = BRIDGE_REG_GET32((&bridge->b_wr_req_buf[slot].reg)); } else { wrf = bridge->b_wr_req_buf[slot].reg; } } pcibr_unlock(pcibr_soft, s);}/* ===================================================================== * Bridge (pcibr) "Device Driver" entry points *//* * pcibr_init: called once during system startup or * when a loadable driver is loaded. * * The driver_register function should normally * be in _reg, not _init. But the pcibr driver is * required by devinit before the _reg routines * are called, so this is an exception. */voidpcibr_init(void){ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pcibr_init()\n")); xwidget_driver_register(XBRIDGE_WIDGET_PART_NUM, XBRIDGE_WIDGET_MFGR_NUM, "pcibr_", 0); xwidget_driver_register(BRIDGE_WIDGET_PART_NUM, BRIDGE_WIDGET_MFGR_NUM, "pcibr_", 0);}/* * open/close mmap/munmap interface would be used by processes * that plan to map the PCI bridge, and muck around with the * registers. This is dangerous to do, and will be allowed * to a select brand of programs. Typically these are * diagnostics programs, or some user level commands we may * write to do some weird things. * To start with expect them to have root priveleges. * We will ask for more later. *//* ARGSUSED */intpcibr_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp){ return 0;}/*ARGSUSED */intpcibr_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp){ return 0;}/*ARGSUSED */intpcibr_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot){ int error; devfs_handle_t vhdl = dev_to_vhdl(dev); devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get(vhdl); pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); bridge_t *bridge = pcibr_soft->bs_base; hwgraph_vertex_unref(pcibr_vhdl); ASSERT(pcibr_soft); len = ctob(btoc(len)); /* Make len page aligned */ error = v_mapphys(vt, (void *) ((__psunsigned_t) bridge + off), len); /* * If the offset being mapped corresponds to the flash prom * base, and if the mapping succeeds, and if the user * has requested the protections to be WRITE, enable the * flash prom to be written. * * XXX- deprecate this in favor of using the * real flash driver ... */ if (IS_BRIDGE_SOFT(pcibr_soft) && !error && ((off == BRIDGE_EXTERNAL_FLASH) || (len > BRIDGE_EXTERNAL_FLASH))) { int s; /* * ensure that we write and read without any interruption. * The read following the write is required for the Bridge war */ s = splhi(); if (io_get_sh_swapper(NASID_GET(bridge))) { BRIDGE_REG_SET32((&bridge->b_wid_control)) |= __swab32(BRIDGE_CTRL_FLASH_WR_EN); BRIDGE_REG_GET32((&bridge->b_wid_control)); /* inval addr bug war */ } else { bridge->b_wid_control |= BRIDGE_CTRL_FLASH_WR_EN; bridge->b_wid_control; /* inval addr bug war */ } splx(s); } return error;}/*ARGSUSED */intpcibr_unmap(devfs_handle_t dev, vhandl_t *vt){ devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t) dev); pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); bridge_t *bridge = pcibr_soft->bs_base; hwgraph_vertex_unref(pcibr_vhdl); if ( IS_PIC_SOFT(pcibr_soft) ) { /* * If flashprom write was enabled, disable it, as * this is the last unmap. */ if (IS_BRIDGE_SOFT(pcibr_soft) && (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN)) { int s; /* * 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_CTRL_FLASH_WR_EN; bridge->b_wid_control; /* inval addr bug war */ splx(s); } } else { if (io_get_sh_swapper(NASID_GET(bridge))) { if (BRIDGE_REG_GET32((&bridge->b_wid_control)) & BRIDGE_CTRL_FLASH_WR_EN) { int s; /* * ensure that we write and read without any interruption. * The read following the write is required for the Bridge war */ s = splhi(); BRIDGE_REG_SET32((&bridge->b_wid_control)) &= __swab32((unsigned int)~BRIDGE_CTRL_FLASH_WR_EN); BRIDGE_REG_GET32((&bridge->b_wid_control)); /* inval addr bug war */ splx(s); } else { if (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN) { int s; /* * 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_CTRL_FLASH_WR_EN; bridge->b_wid_control; /* inval addr bug war */ splx(s); } } } } return 0;}/* This is special case code used by grio. There are plans to make * this a bit more general in the future, but till then this should * be sufficient. */pciio_slot_tpcibr_device_slot_get(devfs_handle_t dev_vhdl){ char devname[MAXDEVNAME]; devfs_handle_t tdev; pciio_info_t pciio_info; pciio_slot_t slot = PCIIO_SLOT_NONE; vertex_to_name(dev_vhdl, devname, MAXDEVNAME); /* run back along the canonical path * until we find a PCI connection point. */ tdev = hwgraph_connectpt_get(dev_vhdl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -