📄 undi_nii.c
字号:
static void nic_disable(struct dev *dev){ struct nic *nic = (struct nic *)dev; int result; result = shutdown(&cdb); if (!result) { printf("UNDI nic does not want to shutdown: %x\n", cdb.stat_code); } result = stop(&cdb); if (!result) { printf("UNDI nic does not want to stop: %x\n", cdb.stat_code); } undi_ifnum = 0; undi_entry_point = 0;}static uint8_t undi_checksum(struct sw_undi *undi){ uint8_t undi_sum, *ptr; int i; ptr = (uint8_t *)undi; undi_sum = 0; for(i = 0; i < undi->len; i++) { undi_sum += ((char *)undi)[i]; } return undi_sum;}#if 0/* Debug functions */void print_nii(EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE *nii){ printf("NII Revision: %lx\n", nii->Revision); printf("NII ID: %lx\n", nii->ID); printf("NII ImageAddr: %lx\n", nii->ImageAddr); printf("NII ImageSize: %x\n", nii->ImageSize); printf("NII StringID: %c%c%c%c\n", nii->StringId[0], nii->StringId[1], nii->StringId[2], nii->StringId[3]); printf("NII Type: %hhx\n", nii->Type); printf("NII Version: %d.%d\n", nii->MajorVer, nii->MinorVer); printf("NII IfNum: %hhx\n", nii->IfNum); printf("\n");}void print_sw_undi(struct sw_undi *undi){ int i; printf("UNDI signature: %c%c%c%c\n", undi->signature[0], undi->signature[1], undi->signature[2], undi->signature[3]); printf("UNDI len: %hhx\n", undi->len); printf("UNDI fudge: %hhx\n", undi->fudge); printf("UNDI rev: %hhx\n", undi->rev); printf("UNDI ifcnt: %hhx\n", undi->ifcnt); printf("UNDI version: %d.%d\n", undi->major, undi->minor); printf("UNDI implementation: %x\n", undi->implementation); printf("UNDI entry point: %lx\n", undi->entry_point); printf("UNDI bus type cnt: %d\n", undi->bus_type_cnt); for(i = 0; i < undi->bus_type_cnt; i++) { printf("UNDI bus type: %c%c%c%c\n", ((undi->bus_type[i]) >> 0) & 0xff, ((undi->bus_type[i]) >> 8) & 0xff, ((undi->bus_type[i]) >> 16) & 0xff, ((undi->bus_type[i]) >> 24) & 0xff); } printf("UNDI sum: %hhx\n", undi_checksum(undi)); printf("\n");}void print_init_info(struct db_init_info *info){ printf("init_info.memory_required: %d\n", info->memory_required); printf("init_info.frame_data_len: %d\n", info->frame_data_len); printf("init_info.link_speeds: %d %d %d %d\n", info->link_speeds[0], info->link_speeds[1], info->link_speeds[2], info->link_speeds[3]); printf("init_info.media_header_len: %d\n", info->media_header_len); printf("init_info.hw_addr_len: %d\n", info->hw_addr_len); printf("init_info.mcast_filter_cnt: %d\n", info->mcast_filter_cnt); printf("init_info.tx_buf_cnt: %d\n", info->tx_buf_cnt); printf("init_info.tx_buf_size: %d\n", info->tx_buf_size); printf("init_info.rx_buf_cnt: %d\n", info->rx_buf_cnt); printf("init_info.rx_buf_size: %d\n", info->rx_buf_size); printf("init_info.if_type: %hhx\n", info->if_type); printf("init_info.duplex: %hhx\n", info->duplex); printf("init_info.loopback: %hhx\n", info->loopback); printf("\n");}void print_config_info(struct db_config_info *info){ int i; printf("config_info.bus_type: %c%c%c%c\n", ((info->pci.bus_type) >> 0) & 0xff, ((info->pci.bus_type) >> 8) & 0xff, ((info->pci.bus_type) >> 16) & 0xff, ((info->pci.bus_type) >> 24) & 0xff); if (info->pci.bus_type != UNDI_BUS_TYPE_PCI) { return; } printf("config_info.bus: %hx\n", info->pci.bus); printf("config_info.device: %hhx\n", info->pci.device); printf("config_info.function: %hhx\n", info->pci.function); printf("config_info.config:\n"); for(i = 0; i < 256; i++) { if ((i & 0xf) == 0) { printf("[%hhx]", i); } printf(" %hhx", info->pci.config[i]); if ((i & 0xf) == 0xf) { printf("\n"); } } printf("\n"); }void print_cdb(struct cdb *cdb){ printf("\n"); printf("cdb.op_code: %hx\n", cdb->op_code); printf("cdb.op_flags: %hx\n", cdb->op_flags); printf("cdb.cpb_size: %d\n", cdb->cpb_size); printf("cdb.db_size: %d\n", cdb->db_size); printf("cdb.cpb_addr: %lx\n", cdb->cpb_addr); printf("cdb.db_addr: %lx\n", cdb->db_addr); printf("cdb.stat_code: %lx\n", cdb->stat_code); printf("cdb.stat_flags: %lx\n", cdb->stat_flags); printf("cdb.ifnum %d\n", cdb->ifnum); printf("cdb.control: %hx\n", cdb->control); printf("\n");}#endif #define ARPHRD_ETHER 1static int nic_setup(struct dev *dev, EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE *nii){ struct nic *nic = (struct nic *)dev; int result; struct sw_undi *undi; struct db_init_info init_info; struct cpb_initialize cpb_initialize; struct db_initialize db_initialize; struct db_station_address db_station_address; int media_detect; unsigned filter, no_filter; int i; /* Fail if I I'm not passed a valid nii */ if (!nii) return 0; /* Fail if this nit a SW UNDI interface */ if (nii->ID == 0) return 0; undi = phys_to_virt(nii->ID); /* Verify the undi structure */ /* It must have a pxe signature */ if (memcmp(undi->signature, "!PXE", 4) != 0) return 0; /* It must have a valid checksum */ if (undi_checksum(undi) != 0) return 0; /* It must be software undi */ if (undi->implementation & UNDI_IMP_HW_UNDI) return 0; /* Setup to do undi calls */ undi_ifnum = nii->IfNum; undi_entry_point = (void *)undi->entry_point; /* Find the UNDI state... */ result = get_state(&cdb); if (!result) return 0; /* See if the device is already initialized */ if ((cdb.stat_flags & CDB_STATFLAGS_GET_STATE_MASK) != CDB_STATFLAGS_GET_STATE_STOPPED) { /* If so attempt to stop it */ if ((cdb.stat_flags & CDB_STATFLAGS_GET_STATE_MASK) == CDB_STATFLAGS_GET_STATE_INITIALIZED) { result = shutdown(&cdb); result = stop(&cdb); } else if ((cdb.stat_flags & CDB_STATFLAGS_GET_STATE_MASK) == CDB_STATFLAGS_GET_STATE_STARTED) { result = stop(&cdb); } /* See if it did stop */ result = get_state(&cdb); if (!result) return 0; /* If it didn't stop give up */ if ((cdb.stat_flags & CDB_STATFLAGS_GET_STATE_MASK) != CDB_STATFLAGS_GET_STATE_STOPPED) return 0; } result = start(&cdb); if (!result) { printf("Device would not start: %x\n", cdb.stat_code); return 0; } result = get_init_info(&cdb, &init_info); if (!result) { printf("Device wount not give init info: %x\n", cdb.stat_code); stop(&cdb); return 0; } /* See if the NIC can detect the presence of a cable */ media_detect = (cdb.stat_flags & CDB_STATFLAGS_CABLE_DETECT_MASK) == CDB_STATFLAGS_CABLE_DETECT_SUPPORTED; if ((init_info.if_type != ARPHRD_ETHER) || (init_info.hw_addr_len != ETH_ALEN)) { printf("Not ethernet\n"); stop(&cdb); return 0; } if (init_info.memory_required > sizeof(buffer)) { printf("NIC wants %d bytes I only have %ld bytes\n", init_info.memory_required, sizeof(buffer)); stop(&cdb); return 0; } /* Initialize the device */ memset(buffer, 0, sizeof(buffer)); memset(&cpb_initialize, 0, sizeof(cpb_initialize)); cpb_initialize.memory_addr = virt_to_phys(&buffer); cpb_initialize.memory_length = init_info.memory_required; cpb_initialize.link_speed = 0; /* auto detect */ /* UNDI nics will not take suggestions :( * So let them figure out an appropriate buffer stragety on their own. */ cpb_initialize.tx_buf_cnt = 0; cpb_initialize.tx_buf_size = 0; cpb_initialize.rx_buf_cnt = 0; cpb_initialize.rx_buf_size = 0; cpb_initialize.duplex = 0; cpb_initialize.loopback = 0; result = initialize(&cdb, media_detect, &cpb_initialize, &db_initialize); if (!result) { printf("Device would not initialize: %x\n", cdb.stat_code); stop(&cdb); return 0; }#if 0 /* It appears the memory_used parameter is never set correctly, ignore it */ if (db_initialize.memory_used > sizeof(buffer)) { printf("NIC is using %d bytes I only have %ld bytes\n", db_initialize.memory_used, sizeof(buffer)); printf("tx_buf_cnt: %d\n", db_initialize.tx_buf_cnt); printf("tx_buf_size: %d\n", db_initialize.tx_buf_size); printf("rx_buf_cnt: %d\n", db_initialize.rx_buf_cnt); printf("rx_buf_size: %d\n", db_initialize.rx_buf_size); nic_disable(dev); return 0; } printf("NIC is using %d bytes\n", db_initialize.memory_used);#endif if (media_detect && ( (cdb.stat_flags & ~CDB_STATFLAGS_STATUS_MASK) == CDB_STATFLAGS_INITIALIZED_NO_MEDIA)) { printf("No media present\n"); nic_disable(dev); return 0; } /* Get the mac address */ result = station_address_read(&cdb, &db_station_address); if (!result) { printf("Could not read station address: %x\n", cdb.stat_code); nic_disable(dev); return 0; } for(i = 0; i < ETH_ALEN; i++) { nic->node_addr[i] = db_station_address.station_address[i]; } printf("Ethernet addr: %!\n", nic->node_addr); filter = CDB_OPFLAGS_RECEIVE_FILTER_ENABLE | CDB_OPFLAGS_RECEIVE_FILTER_UNICAST | CDB_OPFLAGS_RECEIVE_FILTER_BROADCAST; no_filter = CDB_OPFLAGS_RECEIVE_FILTER_DISABLE | CDB_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST | CDB_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; if (undi->implementation & UNDI_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) { filter |= CDB_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; no_filter |= CDB_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS; } else if (undi->implementation & UNDI_IMP_PROMISCUOUS_RX_SUPPORTED) { filter |= CDB_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS; } result = receive_filters(&cdb, no_filter); if (!result) { printf("Could not clear receive filters: %x\n", cdb.stat_code); nic_disable(dev); return 0; } result = receive_filters(&cdb, filter); if (!result) { printf("Could not set receive filters: %x\n", cdb.stat_code); nic_disable(dev); return 0; } /* It would be nice to call get_config_info so I could pass * the type of nic, but that crashes some efi drivers. */ /* Everything worked! */ dev->disable = nic_disable; nic->poll = nic_poll; nic->transmit = nic_transmit; return 1;}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/static int nic_probe(struct dev *dev, unsigned short *dummy __unused){ EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE *nii; int index; int result; index = dev->index+ 1; if (dev->how_probe == PROBE_AWAKE) { index--; } for(result = 0; !result && (nii = lookup_efi_nic(index)); index++) { result = nic_setup(dev, nii); if (result) { break; } } dev->index = result ? index : -1; return result;}static struct isa_driver nic_driver __isa_driver = { .type = NIC_DRIVER, .name = "undi_nii", .probe = nic_probe, .ioaddrs = 0,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -