📄 lance.c
字号:
if (offset >= iovp->iod_iovec[i].iov_size) { offset -= iovp->iod_iovec[i].iov_size; i++; continue; } bytes = iovp->iod_iovec[i].iov_size - offset; if (bytes > count) bytes = count; /* phys_user = numap_local(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes); phys_copy(phys_hw, phys_user, (phys_bytes) bytes); */ if ( (r=sys_datacopy( SELF, nic_addr, iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes )) != OK ) panic( "lance", "sys_datacopy failed: ", r ); count -= bytes; nic_addr += bytes; offset += bytes; }}/*===========================================================================* * calc_iovec_size * *===========================================================================*/static int calc_iovec_size(iovp)iovec_dat_t *iovp;{ int size,i; size = i = 0; while (i < iovp->iod_iovec_s) { if (i >= IOVEC_NR) { ec_next_iovec(iovp); i= 0; continue; } size += iovp->iod_iovec[i].iov_size; i++; } return size;}/*===========================================================================* * ec_next_iovec * *===========================================================================*/static void ec_next_iovec(iovp)iovec_dat_t *iovp;{ iovp->iod_iovec_s -= IOVEC_NR; iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t); get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_t), iovp->iod_iovec); }/*===========================================================================* * do_getstat * *===========================================================================*/static void do_getstat(mp)message *mp;{ int port; ether_card_t *ec; port = mp->DL_PORT; if (port < 0 || port >= EC_PORT_NR_MAX) panic( "lance", "illegal port", port); ec= &ec_table[port]; ec->client= mp->DL_PROC; put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR, (vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat); reply(ec, OK, FALSE);}/*===========================================================================* * put_userdata * *===========================================================================*/static void put_userdata(user_proc, user_addr, count, loc_addr)int user_proc;vir_bytes user_addr;vir_bytes count;void *loc_addr;{ /*phys_bytes dst; dst = numap_local(user_proc, user_addr, count); if (!dst) panic( "lance", "umap failed", NO_NUM); phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count); */ int cps; cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count); if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);}/*===========================================================================* * do_stop * *===========================================================================*/static void do_stop(mp)message *mp;{ int port; ether_card_t *ec; unsigned short ioaddr; port = mp->DL_PORT; if (port < 0 || port >= EC_PORT_NR_MAX) panic( "lance", "illegal port", port); ec = &ec_table[port]; if (!(ec->flags & ECF_ENABLED)) return; ioaddr = ec->ec_port; out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* reset */ ec->flags = ECF_EMPTY;}static void getAddressing(devind, ec)int devind;ether_card_t *ec;{ unsigned int membase, ioaddr; int reg, irq; for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { ioaddr = pci_attr_r32(devind, reg); if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0) continue; /* Strip the I/O address out of the returned value */ ioaddr &= PCI_BASE_ADDRESS_IO_MASK; /* Get the memory base address */ membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1); /* KK: Get the IRQ number */ irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN); if (irq) irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE); /* Get the ROM base address */ /*pci_attr_r32(devind, PCI_ROM_ADDRESS, &romaddr); romaddr >>= 10;*/ /* Take the first one or the one that matches in boot ROM address */ /*if (pci_ioaddr == 0 || romaddr == ((unsigned long) rom.rom_segment << 4)) {*/ ec->ec_linmem = membase; ec->ec_port = ioaddr; ec->ec_irq = irq; /*}*/ }}/*===========================================================================* * lance_probe * *===========================================================================*/static int lance_probe(ec)ether_card_t *ec;{ unsigned short pci_cmd, attached = 0; unsigned short ioaddr; int lance_version, chip_version; int devind, just_one, i, r; u16_t vid, did; u32_t bar; u8_t ilr; char *dname; if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0) { /* Look for specific PCI device */ r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev, ec->ec_pcifunc, &devind); if (r == 0) { printf("%s: no PCI found at %d.%d.%d\n", ec->port_name, ec->ec_pcibus, ec->ec_pcidev, ec->ec_pcifunc); return 0; } pci_ids(devind, &vid, &did); just_one= TRUE; } else { r= pci_first_dev(&devind, &vid, &did); if (r == 0) return 0; just_one= FALSE; } for(;;) { for (i= 0; pcitab[i].vid != 0; i++) { if (pcitab[i].vid != vid) continue; if (pcitab[i].did != did) continue; if (pcitab[i].checkclass) { panic("lance", "class check not implemented", NO_NUM); } break; } if (pcitab[i].vid != 0) break; if (just_one) { printf( "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n", ec->port_name, vid, did, ec->ec_pcibus, ec->ec_pcidev, ec->ec_pcifunc); return 0; } r= pci_next_dev(&devind, &vid, &did); if (!r) return 0; } dname= pci_dev_name(vid, did); if (!dname) dname= "unknown device"; /* printf("%s: ", ec->port_name); printf("%s ", dname); printf("(%x/", vid); printf("%x) ", did); printf("at %s\n", pci_slot_name(devind)); */ pci_reserve(devind); /* for (i = 0; pci_dev_list[i].vendor != 0; i++) { if (pci_dev_list[i].suffix == 1) { ec->ec_port = pci_dev_list[i].ioaddr; ec->ec_irq = pci_dev_list[i].irq; ec->ec_linmem = pci_dev_list[i].membase; ec->ec_bus = pci_dev_list[i].bus; ec->ec_dev = pci_dev_list[i].devfn; ec->ec_fnc = pci_dev_list[i].suffix = -1; attached = 1; break; } } if (attached == 0) return 0; */ getAddressing(devind, ec); /* ===== Bus Master ? ===== */ /*pcibios_read_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, &pci_cmd);*/ pci_cmd = pci_attr_r32(devind, PCI_CR); if (!(pci_cmd & PCI_COMMAND_MASTER)) { pci_cmd |= PCI_COMMAND_MASTER; /*pcibios_write_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, pci_cmd);*/ pci_attr_w32(devind, PCI_CR, pci_cmd); } /* ===== Probe Details ===== */ ioaddr = ec->ec_port; out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* Reset */ out_word(ioaddr+LANCE_ADDR, 0x0); /* Sw to win 0 */ if (in_word(ioaddr+LANCE_DATA) != 0x4) { ec->mode=EC_DISABLED; } /* Probe Chip Version */ out_word(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */ if (in_word(ioaddr+LANCE_ADDR) != 88) lance_version = 0; else { chip_version = in_word(ioaddr+LANCE_DATA); out_word(ioaddr+LANCE_ADDR, 89); chip_version |= in_word(ioaddr+LANCE_DATA) << 16; if ((chip_version & 0xfff) != 0x3) { ec->mode=EC_DISABLED; } chip_version = (chip_version >> 12) & 0xffff; for (lance_version = 1; chip_table[lance_version].id_number != 0; ++lance_version) if (chip_table[lance_version].id_number == chip_version) break; }#if 0 printf("%s: %s at %X:%d\n", ec->port_name, chip_table[lance_version].name, ec->ec_port, ec->ec_irq);#endif return lance_version;}/*===========================================================================* * do_getname * *===========================================================================*/static void do_getname(mp)message *mp;{ int r; strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME)); mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; mp->m_type= DL_NAME_REPLY; r= send(mp->m_source, mp); if (r != OK) panic("LANCE", "do_getname: send failed", r);}/*===========================================================================* * lance_init_card * *===========================================================================*/static void lance_init_card(ec)ether_card_t *ec;{ int i; Address l; unsigned short ioaddr = ec->ec_port; /* ============= setup init_block(cf. lance_probe1) ================ */ /* make sure data structure is 8-byte aligned */ l = ((Address)lance + 7) & ~7; lp = (struct lance_interface *)l; lp->init_block.mode = 0x3; /* disable Rx and Tx */ lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0; /* using multiple Rx/Tx buffer */ lp->init_block.rx_ring = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; lp->init_block.tx_ring = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS; l = virt_to_bus(&lp->init_block); out_word(ioaddr+LANCE_ADDR, 0x1); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, (unsigned short)l); out_word(ioaddr+LANCE_ADDR, 0x2); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, (unsigned short)(l >> 16)); out_word(ioaddr+LANCE_ADDR, 0x4); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x915); out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); /* ============= Get MAC address (cf. lance_probe1) ================ */ for (i = 0; i < 6; ++i) ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i); /* ============ (re)start init_block(cf. lance_reset) =============== */ /* Reset the LANCE */ (void)in_word(ioaddr+LANCE_RESET); /* ----- Re-initialize the LANCE ----- */ /* Set station address */ for (i = 0; i < 6; ++i) lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i]; /* Preset the receive ring headers */ for (i=0; i<RX_RING_SIZE; i++) { lp->rx_ring[i].buf_length = -ETH_FRAME_LEN; /* OWN */ lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff; /* we set the top byte as the very last thing */ lp->rx_ring[i].u.addr[3] = 0x80; } /* Preset the transmitting ring headers */ for (i=0; i<TX_RING_SIZE; i++) { lp->tx_ring[i].u.base = 0; isstored[i] = 0; } lp->init_block.mode = 0x0; /* enable Rx and Tx */ l = (Address)virt_to_bus(&lp->init_block); out_word(ioaddr+LANCE_ADDR, 0x1); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, (short)l); out_word(ioaddr+LANCE_ADDR, 0x2); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, (short)(l >> 16)); out_word(ioaddr+LANCE_ADDR, 0x4); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x915); out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); /* ----- start when init done. ----- */ out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ out_word(ioaddr+LANCE_DATA, 0x1); /* init */ for (i = 10000; i > 0; --i) if (in_word(ioaddr+LANCE_DATA) & 0x100) break; /* Set 'Multicast Table' */ for (i=0;i<4;++i) { out_word(ioaddr+LANCE_ADDR, 0x8 + i); out_word(ioaddr+LANCE_DATA, 0xffff); } /* Set 'Receive Mode' */ if (ec->flags & ECF_PROMISC) { out_word(ioaddr+LANCE_ADDR, 0xf); out_word(ioaddr+LANCE_DATA, 0x8000); } else { if (ec->flags & (ECF_BROAD | ECF_MULTI)) { out_word(ioaddr+LANCE_ADDR, 0xf); out_word(ioaddr+LANCE_DATA, 0x0000); } else { out_word(ioaddr+LANCE_ADDR, 0xf); out_word(ioaddr+LANCE_DATA, 0x4000); } } out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */ return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -