/* * 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. */ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) { int status = 0; uint64_t flag; flag = pcibr_lock(pcibus_info); status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); if (status < 0) { /* Failed to allocate */ pcibr_unlock(pcibus_info, flag); return -1; } pcibr_unlock(pcibus_info, flag); return status; }
void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) { volatile uint64_t ate; int count; uint64_t flags; if (pcibr_invalidate_ate) { /* For debugging purposes, clear the valid bit in the ATE */ ate = *pcibr_ate_addr(pcibus_info, index); count = pcibus_info->pbi_int_ate_resource.ate[index]; ate_write(pcibus_info, index, count, (ate & ~PCI32_ATE_V)); } flags = pcibr_lock(pcibus_info); free_ate_resource(&pcibus_info->pbi_int_ate_resource, index); pcibr_unlock(pcibus_info, flags); }
void ate_thaw(pcibr_dmamap_t pcibr_dmamap, int ate_index, #if PCIBR_FREEZE_TIME bridge_ate_t ate, int ate_total, unsigned freeze_time_start, #endif unsigned *cmd_regs, unsigned s) { pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft; int dma_slot = pcibr_dmamap->bd_slot; int slot; bridge_t *bridge = pcibr_soft->bs_base; int ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM; unsigned cmd_reg; #if PCIBR_FREEZE_TIME unsigned freeze_time; static unsigned max_freeze_time = 0; static unsigned max_ate_total; #endif if (!ext_ates) return; /* restore cmd regs */ for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { if ((cmd_reg = cmd_regs[slot]) & PCI_CMD_BUS_MASTER) { if ( IS_PIC_SOFT(pcibr_soft) ) { pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg); } else { if (io_get_sh_swapper(NASID_GET(bridge))) { bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = __swab32(cmd_reg); } else { // BUG(); /* Does this really work if called when io_get_sh_swapper = 0? */ // bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg; pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg); } } } } pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY; atomic_inc(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active)); #if PCIBR_FREEZE_TIME freeze_time = get_timestamp() - freeze_time_start; if ((max_freeze_time < freeze_time) || (max_ate_total < ate_total)) { if (max_freeze_time < freeze_time) max_freeze_time = freeze_time; if (max_ate_total < ate_total) max_ate_total = ate_total; pcibr_unlock(pcibr_soft, s); printk( "%s: pci freeze time %d usec for %d ATEs\n" "\tfirst ate: %R\n", pcibr_soft->bs_name, freeze_time * 1000 / 1250, ate_total, ate, ate_bits); } else #endif pcibr_unlock(pcibr_soft, s); }