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

📄 undi_nii.c

📁 网卡 BOOT ROM 的 64 住源程序。模块有:核心代码、H文件、网卡驱动程序、头代码文件。
💻 C
📖 第 1 页 / 共 3 页
字号:
	uint16_t media_header_len;	undi_frame_type type;	uint8_t reserved[7];} PACKED;struct fptr {	void *func;	void *gp;};extern char __gp[];/* Variables */static unsigned undi_ifnum;static void *undi_entry_point;static struct cdb cdb;static char buffer[1024*1024];/* SW UNDI callbacks */static void undi_udelay(uint64_t microseconds){#if 0	printf("undi_udelay(%lx)\n", microseconds);#endif	if (microseconds < 10) {		microseconds = 10;	}	if (microseconds > 1000) {		mdelay(microseconds/1000);		microseconds%=1000;	}	udelay(microseconds);}static struct fptr fptr_undi_udelay = {	.func = &undi_udelay,	.gp = &__gp,};static void undi_block(uint32_t enable __unused){#if 0	printf("undi_block(%x)\n",		enable);#endif	return;}static struct fptr fptr_undi_block = {	.func = &undi_block,	.gp = &__gp,};static void undi_virt2phys(uint64_t virtual, uint64_t *ptr){#if 0	printf("undi_virt2phys(%lx, %lx)\n",		virtual, ptr);#endif	*ptr = virt_to_phys((void *)virtual);}static struct fptr fptr_undi_virt2phys = {	.func = &undi_virt2phys,	.gp = &__gp,};#define UNDI_IO_READ	0#define UNDI_IO_WRITE	1#define UNDI_MEM_READ	2#define UNDI_MEM_WRITE	3static void undi_mem_io(uint8_t read_write, uint8_t len, uint64_t port, uint64_t buf_addr){	printf("undi_mem_io(%hhx, %hhx, %lx, %lx)\n",		read_write, len, port, buf_addr);#if 0	if ((read_write == UNDI_IO_READ) && (len == 1)) {		uint8_t *buf = (void *)buf_addr;		*buf = inb(port);	}	else if ((read_write == UNDI_IO_READ) && (len == 2)) {		uint16_t *buf = (void *)buf_addr;		*buf = inw(port);	}	else if ((read_write == UNDI_IO_READ) && (len == 4)) {		uint32_t *buf = (void *)buf_addr;		*buf = inl(port);	}	else if ((read_write == UNDI_IO_READ) && (len == 8)) {		uint64_t *buf = (void *)buf_addr;		*buf = inq(port);	}	else if ((read_write == UNDI_IO_WRITE) && (len == 1)) {		uint8_t *buf = (void *)buf_addr;		outb(*buf, port);	}	else if ((read_write == UNDI_IO_WRITE) && (len == 2)) {		uint16_t *buf = (void *)buf_addr;		outw(*buf, port);	}	else if ((read_write == UNDI_IO_WRITE) && (len == 4)) {		uint32_t *buf = (void *)buf_addr;		outl(*buf, port);	}	else if ((read_write == UNDI_IO_WRITE) && (len == 8)) {		uint64_t *buf = (void *)buf_addr;		outq(*buf, port);	}	else if ((read_write == UNDI_MEM_READ) && (len == 1)) {		uint8_t *buf = (void *)buf_addr;		*buf = readb(port);	}	else if ((read_write == UNDI_MEM_READ) && (len == 2)) {		uint16_t *buf = (void *)buf_addr;		*buf = readw(port);	}	else if ((read_write == UNDI_MEM_READ) && (len == 4)) {		uint32_t *buf = (void *)buf_addr;		*buf = readl(port);	}	else if ((read_write == UNDI_MEM_READ) && (len == 8)) {		uint64_t *buf = (void *)buf_addr;		*buf = readq(port);	}	else if ((read_write == UNDI_MEM_WRITE) && (len == 1)) {		uint8_t *buf = (void *)buf_addr;		writeb(*buf, port);	}	else if ((read_write == UNDI_MEM_WRITE) && (len == 2)) {		uint16_t *buf = (void *)buf_addr;		writew(*buf, port);	}	else if ((read_write == UNDI_MEM_WRITE) && (len == 4)) {		uint32_t *buf = (void *)buf_addr;		writel(*buf, port);	}	else if ((read_write == UNDI_MEM_WRITE) && (len == 8)) {		uint64_t *buf = (void *)buf_addr;		writeq(*buf, port);	}#endif}static struct fptr fptr_undi_mem_io = {	.func = &undi_mem_io,	.gp = &__gp,};/* static void undi_memio(this, width, address, count, buffer);??? *//* Wrappers to call the undi functions */static int undi_call(struct cdb *cdb){	int result = 1;	cdb->stat_code  = CDB_STATCODE_INITIALIZE;	cdb->stat_flags = CDB_STATFLAGS_INITIALIZE;	cdb->ifnum      = undi_ifnum;	cdb->control    = CDB_CONTROL_LAST_CDB_IN_LIST;	__call(undi_entry_point, cdb);	/* Wait until the command executes... */	while((cdb->stat_flags & CDB_STATFLAGS_STATUS_MASK) == 0)		;	if ((cdb->stat_flags & CDB_STATFLAGS_STATUS_MASK) != 		CDB_STATFLAGS_COMMAND_COMPLETE)		result = 0;	if (cdb->stat_code != CDB_STATCODE_SUCCESS)		result = 0;	return result;}static int get_state(struct cdb *cdb){	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_GET_STATE;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	return undi_call(cdb);}static int start(struct cdb *cdb){	static struct cpb_start cpb;	memset(&cpb, 0, sizeof(cpb));	cpb.delay     = &fptr_undi_udelay;	cpb.block     = &fptr_undi_block;	cpb.virt2phys = &fptr_undi_virt2phys;	cpb.mem_io    = &fptr_undi_mem_io;	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_START;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	cdb->cpb_size = sizeof(cpb);	cdb->cpb_addr = virt_to_phys(&cpb);		return undi_call(cdb);}static int stop(struct cdb *cdb){	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_STOP;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	return undi_call(cdb);}static int get_init_info(struct cdb *cdb, struct db_init_info *info){	memset(info, 0, sizeof(*info));	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_GET_INIT_INFO;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	cdb->db_size  = sizeof(*info);	cdb->db_addr  = virt_to_phys(info);	return undi_call(cdb);}#if 0/* get_config_info crashes broadcoms pxe driver */static int get_config_info(struct cdb *cdb, struct db_config_info *info){	memset(info, 0, sizeof(*info));	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_GET_CONFIG_INFO;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	cdb->db_size  = sizeof(*info);	cdb->db_addr  = virt_to_phys(info);	return undi_call(cdb);}#endifstatic int initialize(struct cdb *cdb, int media_detect,	struct cpb_initialize *cpb, struct db_initialize *db){	memset(db, 0, sizeof(*db));	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_INITIALIZE;	cdb->op_flags = media_detect?		CDB_OPFLAGS_INIT_DETECT_CABLE:CDB_OPFLAGS_INIT_DO_NOT_DETECT_CABLE;	cdb->cpb_size = sizeof(*cpb);	cdb->cpb_addr = virt_to_phys(cpb);	cdb->db_size  = sizeof(*db);	cdb->db_addr  = virt_to_phys(db);	return undi_call(cdb);}static int shutdown(struct cdb *cdb){	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_SHUTDOWN;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	return undi_call(cdb);}static int station_address_read(struct cdb *cdb, struct db_station_address *db){	memset(db, 0, sizeof(*db));	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_STATION_ADDRESS;	cdb->op_flags = CDB_OPFLAGS_STATION_ADDRESS_READ;	cdb->db_size  = sizeof(*db);	cdb->db_addr  = virt_to_phys(db);	return undi_call(cdb);}static int receive_filters(struct cdb *cdb, unsigned opflags){	/* I currently do not support setting	 * or returning the multicast filter list.	 * So do not even attempt to pass them.	 */	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_RECEIVE_FILTERS;	cdb->op_flags = opflags;	return undi_call(cdb);}static int get_transmitted_status(struct cdb *cdb, struct db_get_status *db){	memset(db, 0, sizeof(*db));	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_GET_STATUS;	cdb->op_flags = CDB_OPFLAGS_GET_TRANSMITTED_BUFFERS;	cdb->db_size  = sizeof(*db);	cdb->db_addr  = virt_to_phys(db);	return undi_call(cdb);}static int transmit(struct cdb *cdb, struct cpb_transmit *cpb){	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_TRANSMIT;	cdb->op_flags = CDB_OPFLAGS_TRANSMIT_WHOLE | CDB_OPFLAGS_TRANSMIT_DONT_BLOCK;	cdb->cpb_size = sizeof(*cpb);	cdb->cpb_addr = virt_to_phys(cpb);	return undi_call(cdb);}static int receive(struct cdb *cdb, 	struct cpb_receive *cpb, struct db_receive *db){	memset(db, 0, sizeof(*db));	memset(cdb, 0, sizeof(*cdb));	cdb->op_code  = CDB_OP_RECEIVE;	cdb->op_flags = CDB_OPFLAGS_NOT_USED;	cdb->cpb_size = sizeof(*cpb);	cdb->cpb_addr = virt_to_phys(cpb);	cdb->db_size  = sizeof(*db);	cdb->db_addr  = virt_to_phys(db);	return undi_call(cdb);}/* The work horse functions */static int nic_poll(struct nic *nic ){	int result;	struct cpb_receive cpb;	struct db_receive db;	memset(&cpb, 0, sizeof(cpb));	cpb.buffer_addr = virt_to_phys(nic->packet);	cpb.buffer_len = ETH_FRAME_LEN;	result = receive(&cdb, &cpb, &db);	if (result) {		nic->packetlen = db.frame_len;		return 1;	}	else if (cdb.stat_code != CDB_STATCODE_NO_DATA) {		printf("Receive failed: %lx\n", cdb.stat_code);			}	return 0;	/* initially as this is called to flush the input */}static void nic_transmit(struct nic *nic, const char *dest, unsigned int type, 	unsigned int size, const char *data){	int result;	static struct {		uint8_t  dst_addr[ETH_ALEN];		uint8_t  src_addr[ETH_ALEN];		uint16_t type;		uint8_t  data[ETH_MAX_MTU];	} packet;	struct cpb_transmit cpb;	struct db_get_status db;	int done;	/* Build the packet to transmit in my buffer */	memcpy(&packet.dst_addr, dest, ETH_ALEN);	memcpy(&packet.src_addr, nic->node_addr, ETH_ALEN);	packet.type = htons(type);	memcpy(&packet.data, data, size);		/* send the packet to destination */	cpb.frame_addr       = virt_to_phys(&packet);	cpb.data_len         = ETH_HLEN + size;	cpb.media_header_len = ETH_HLEN;	result = transmit(&cdb, &cpb);	if (!result) {		printf("transmit failed: %lx\n", cdb.stat_code);		return;	}	/* Wait until the packet is actually transmitted, 	 * indicating it is safe to reuse my trasmit buffer.	 */	done = 0;	while(!done) {		int i;		result = get_transmitted_status(&cdb, &db);		for(i = 0; i < UNDI_MAX_XMIT_BUFFERS; i++) {			if (db.tx_buffer[i] == virt_to_phys(&packet)) {				done = 1;			}		}	}}

⌨️ 快捷键说明

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