⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcm1480_pci_machdep.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 3 页
字号:
   done. */intpci_device_preset (pcitag_t tag){    pcireg_t id;    int skip;    skip = 0;    id = pci_conf_read(tag, PCI_ID_REG);    switch (PCI_VENDOR(id)) {	case PCI_VENDOR_SIBYTE:	    /* Check for a host bridge seen internally, in which case	       we don't want to allocate any address space for its	       BARs. */	    if (tag == BCM1400_PCI_BRIDGE || tag == BCM1400_LDT_BRIDGE)		skip = 1;	    break;	case PCI_VENDOR_AMD:	    if (PCI_PRODUCT(id) == PCI_PRODUCT_PLX_HT7520_APIC)		ht7520apic_preset (tag);	    break;	default:	    break;    }    return skip;}/* Called for each non-bridge (Type 0) function after assigning the BAR   and InterruptLine (XXX check this) resources.. */voidpci_device_setup (pcitag_t tag){    pcireg_t id = pci_conf_read(tag, PCI_ID_REG);    switch (PCI_VENDOR(id)) {	case PCI_VENDOR_AMD:	    if (PCI_PRODUCT(id) == PCI_PRODUCT_PLX_HT7520_APIC)		ht7520apic_setup (tag);	    break;	default:	    break;    }}/* Called for each bridge (Type 1) function after configuring the   secondary bus, to allow device-specific initialization. */voidpci_bridge_setup (pcitag_t tag, pci_flags_t flags){    pcireg_t id = pci_conf_read(tag, PCI_ID_REG);    switch (PCI_VENDOR(id)) {	case PCI_VENDOR_ALSC:	    switch (PCI_PRODUCT(id)) {		case PCI_PRODUCT_ALSC_SP1011:		    sp1011_setup (tag, flags);		    break;		case PCI_PRODUCT_ALSC_AS90L10208:		    as90l10208_setup (tag, flags);		    break;		default:		    break;	    }	    break;        case PCI_VENDOR_AMD:	    /* The PLX ht7520 requires configuration of the	       interrupt mapping, but it packages the IOAPIC as a	       separate function, registers of which will not yet have	       been initialized if the standard traversal order is	       followed.  See next.  */	    break;	default:	    break;    }}/* Machine dependent access primitives and utility functions */voidpci_flush (void){    /* note: this is a noop for the BCM1400. */}pcitag_tpci_make_tag (int port, int bus, int device, int function){    return BCM1400_PCI_MAKE_TAG(port, bus, device, function);}voidpci_break_tag (pcitag_t tag,	       int *portp, int *busp, int *devicep, int *functionp){    if (portp) *portp = (tag >> 24) & PCI_PORTMAX;    if (busp) *busp = (tag >> 16) & PCI_BUSMAX;    if (devicep) *devicep = (tag >> 11) & PCI_DEVMAX;    if (functionp) *functionp = (tag >> 8) & PCI_FUNCMAX;}intpci_canscan (pcitag_t tag){    int port, bus, device, function;    pci_break_tag (tag, &port, &bus, &device, &function);     if (bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX)	return 0;    switch (port) {	case 0:	    if (bus == 0 && bcm1400_in_device_mode)		return 0;	    break;	case 1:	    if (bus == 0 && bcm1400_ldt_slave_mode)		return 0;	    break;	default:	    return 0;    }    return 1;}intpci_probe_tag(pcitag_t tag){    physaddr_t addrp;    pcireg_t data;    if (!pci_canscan(tag))	return 0;    addrp = (physaddr_t) BCM1400_CFG_ADDR(tag, PCI_ID_REG, 4);    /* An earlier version of this code cleared the MasterAbort and       TargetAbort bits in the PCI host bridge, did the read, and       looked for those bits to be set.  For the BCM1400, that's       inappropriate because	 - it's the wrong host bridge for devices behind HT.	 - it loses status if testing the PCI host bridge itself.       We rely on getting 0xffff when reading the vendor ID.  Note       that this still has side effects on the host bridge registers.    */    data = phys_read32(addrp);  /* device + vendor ID */    mips_wbflush();    /* if it returned all vendor id bits set, it's not a device */    return (PCI_VENDOR(data) != 0xffff);}/* Read/write access to PCI configuration registers.  For most   applications, pci_conf_read<N> and pci_conf_write<N> are deprecated   unless N = 32. */static pcireg_tpci_conf_readn(pcitag_t tag, int reg, int width){    physaddr_t addrp;    pcireg_t data;#if (PCI_DEBUG != 0)    int port, bus, device, function;    if (reg & (width-1) || reg < 0 || reg >= PCI_REGMAX) {	if (_pciverbose >= 1)	    pci_tagprintf(tag, "pci_conf_readn: bad reg 0x%x\n", reg);	return 0;    }    pci_break_tag(tag, &port, &bus, &device, &function);     if (port > PCI_PORTMAX	|| bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX) {	if (_pciverbose >= 1)	    pci_tagprintf(tag, "pci_conf_readn: bad tag 0x%x\n", tag);	return 0;    }#endif /* PCI_DEBUG */    mips_wbflush();    addrp = (physaddr_t) BCM1400_CFG_ADDR(tag, reg, width);    switch (width) {    case 1:	data = (pcireg_t) phys_read8(addrp);	break;    case 2:	data = (pcireg_t) phys_read16(addrp);	break;    default:    case 4:	data = (pcireg_t) phys_read32(addrp);	break;    }    mips_wbflush();    return data;}pcireg_tpci_conf_read8(pcitag_t tag, int reg){    return pci_conf_readn(tag, reg, 1);}pcireg_tpci_conf_read(pcitag_t tag, int reg){    return pci_conf_readn(tag, reg, 4);}static voidpci_conf_writen(pcitag_t tag, int reg, pcireg_t data, int width){    physaddr_t addrp;#if (PCI_DEBUG != 0)    int port, bus, device, function;    if (reg & (width-1) || reg < 0 || reg > PCI_REGMAX) {	if (_pciverbose >= 1)	    pci_tagprintf(tag, "pci_conf_writen: bad reg 0x%x\n", reg);	return;    }    pci_break_tag(tag, &port, &bus, &device, &function);    if (port > PCI_PORTMAX	|| bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX) {	if (_pciverbose >= 1)	    pci_tagprintf(tag, "pci_conf_writen: bad tag 0x%x\n", tag);	return;    }#endif /* PCI_DEBUG */    mips_wbflush();    addrp = (physaddr_t) BCM1400_CFG_ADDR(tag, reg, width);    switch (width) {    case 1:	phys_write8(addrp, data);	break;    case 2:	phys_write16(addrp, data);	break;    default:    case 4:	phys_write32(addrp, data);	break;    }    mips_wbflush();}voidpci_conf_write8(pcitag_t tag, int reg, pcireg_t data){    pci_conf_writen(tag, reg, data, 1);}voidpci_conf_write(pcitag_t tag, int reg, pcireg_t data){    pci_conf_writen(tag, reg, data, 4);}/* Acked writes are intended primarily for updating the unitID field   during HT fabric initialization.  The write changes the address of   the target, so further accesses should be avoided until the write   completes or times out.   */intpci_conf_write_acked(pcitag_t tag, int reg, pcireg_t data){    int done;    int port, bus;    unsigned int count, prev_count;    int  i;    pci_break_tag(tag, &port, &bus, NULL, NULL);    /* The following code uses the target_done counters in each host       bridge.  It assumes that there is are no concurrent non-posted       transactions on the relevant bus. */    switch (port) {	case 0:    /* The write will use the PCI Host Bridge */	    prev_count = pci_conf_read(BCM1400_PCI_BRIDGE, R_BCM1480_PHB_TGTDONE);	    prev_count &= M_BCM1480_PHB_TGT_DONE_COUNTER;	    pci_conf_write(tag, reg, data);	    for (i = 0; i < 1000; i++) {		count = pci_conf_read(BCM1400_PCI_BRIDGE, R_BCM1480_PHB_TGTDONE);		count &= M_BCM1480_PHB_TGT_DONE_COUNTER;		if (count != prev_count)		    break;		}	    done = (count != prev_count);	    break;	case 1:    /* The write will use the HT Host Bridge */	    prev_count = pci_conf_read(BCM1400_LDT_BRIDGE, R_BCM1480_HTD_TGTDONE);	    prev_count &= M_BCM1480_HTD_TGT_DONE_COUNTER;	    pci_conf_write(tag, reg, data);	    for (i = 0; i < 1000; i++) {		count = pci_conf_read(BCM1400_LDT_BRIDGE, R_BCM1480_HTD_TGTDONE);		count &= M_BCM1480_HTD_TGT_DONE_COUNTER;		if (count != prev_count)		    break;		}	    done = (count != prev_count);	    break;	default:  /* Otherwise, just write and read back. */	    pci_conf_write(tag, reg, data);	    (void) pci_conf_read(tag, reg);	    done = 1;	}    return done;}intpci_map_io(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap){    pcireg_t address;    struct host_port *p;    phys_addr_t pa;        if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {	if (_pciverbose >= 1)	    pci_tagprintf(tag, "pci_map_io: bad request\n");	return -1;    }        address = pci_conf_read(tag, reg);        if ((address & PCI_MAPREG_TYPE_IO) == 0) {	if (_pciverbose >= 1)	    pci_tagprintf(tag,			  "pci_map_io: attempt to i/o map a memory region\n");	return -1;    }    p = &P[BCM1400_HOST_PORT(tag)];    pa = ((address & PCI_MAPREG_IO_ADDR_MASK) - p->pci_io_base) + p->io_space;    if (endian == PCI_MATCH_BITS)	pa |= p->io_bit_endian;          *pap = pa;    return 0;}intpci_map_mem(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap){    pcireg_t address;    struct host_port *p;    phys_addr_t pa;    if (reg == PCI_MAPREG_ROM) {	/* expansion ROM */	address = pci_conf_read(tag, reg);	if ((address & PCI_MAPREG_ROM_ENABLE) == 0) {	    pci_tagprintf(tag, "pci_map_mem: attempt to map missing rom\n");	    return -1;	}	pa = address & PCI_MAPREG_ROM_ADDR_MASK;    } else {	if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {	    if (_pciverbose >= 1)		pci_tagprintf(tag, "pci_map_mem: bad request\n");	    return -1;	}		address = pci_conf_read(tag, reg);		if ((address & PCI_MAPREG_TYPE_IO) != 0) {	    if (_pciverbose >= 1)		pci_tagprintf(tag,			      "pci_map_mem: attempt to memory map an I/O region\n");	    return -1;	}		pa = address & PCI_MAPREG_MEM_ADDR_MASK;	switch (address & PCI_MAPREG_MEM_TYPE_MASK) {	case PCI_MAPREG_MEM_TYPE_32BIT:	case PCI_MAPREG_MEM_TYPE_32BIT_1M:	    break;	case PCI_MAPREG_MEM_TYPE_64BIT:	    if (reg + 4 < PCI_MAPREG_END)	        pa |= ((phys_addr_t)pci_conf_read(tag, reg+4) << 32);	    else {	        if (_pciverbose >= 1)		    pci_tagprintf(tag, "pci_map_mem: bad 64-bit reguest\n");		return -1;	    }	    break;	default:	    if (_pciverbose >= 1)		pci_tagprintf(tag, "pci_map_mem: reserved mapping type\n");	    return -1;	}    }    p = &P[BCM1400_HOST_PORT(tag)];    pa = (pa - p->pci_mem_base) + p->mem_space;    if (endian == PCI_MATCH_BITS)	pa |= p->mem_bit_endian;          *pap = pa;    return 0;}/* XXX This is restricts ISA devices to port 0 XXX */#define ISAPORT_BASE(x)     (P[1].io_space + (x))uint8_tinb (unsigned int port){    return phys_read8(ISAPORT_BASE(port));}uint16_tinw (unsigned int port){    return phys_read16(ISAPORT_BASE(port));}uint32_tinl (unsigned int port){    return phys_read32(ISAPORT_BASE(port));}voidoutb (unsigned int port, uint8_t val){    phys_write8(ISAPORT_BASE(port), val);    mips_wbflush();}voidoutw (unsigned int port, uint16_t val){    phys_write16(ISAPORT_BASE(port), val);    mips_wbflush();}voidoutl (unsigned int port, uint32_t val){    phys_write32(ISAPORT_BASE(port), val);    mips_wbflush();}/* Map PCI interrupts A, B, C, D into a value for the IntLine   register.  For BCM1400, return the source number used by the   interrupt mapper, or 0xff if none. */uint8_tpci_int_line(uint8_t pci_int){    return (pci_int == 0) ? 0xff : (8 + (pci_int-1));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -