📄 ewrk3.c
字号:
ewrk3_dev_index(char *s)){ int i = 0, j = 0; for (; *s; s++) { if (isdigit(*s)) { j = 1; i = (i * 10) + (*s - '0'); } else if (j) break; } return i;}/* ** Read the EWRK3 EEPROM using this routine */static int Read_EEPROM(u_long iobase, u_char eaddr){ int i; outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ outb(EEPROM_RD, EWRK3_IOPR); /* issue read command */ for (i = 0; i < 5000; i++) inb(EWRK3_CSR); /* wait 1msec */ return inw(EWRK3_EPROM1); /* 16 bits data return */}/* ** Write the EWRK3 EEPROM using this routine */static int Write_EEPROM(short data, u_long iobase, u_char eaddr){ int i; outb(EEPROM_WR_EN, EWRK3_IOPR); /* issue write enable command */ for (i = 0; i < 5000; i++) inb(EWRK3_CSR); /* wait 1msec */ outw(data, EWRK3_EPROM1); /* write data to register */ outb((eaddr & 0x3f), EWRK3_PIR1); /* set up 6 bits of address info */ outb(EEPROM_WR, EWRK3_IOPR); /* issue write command */ for (i = 0; i < 75000; i++) inb(EWRK3_CSR); /* wait 15msec */ outb(EEPROM_WR_DIS, EWRK3_IOPR); /* issue write disable command */ for (i = 0; i < 5000; i++) inb(EWRK3_CSR); /* wait 1msec */ return 0;}/* ** Look for a particular board name in the on-board EEPROM. */__initfunc(static void EthwrkSignature(char *name, char *eeprom_image)){ u_long i, j, k; char *signatures[] = EWRK3_SIGNATURE; strcpy(name, ""); for (i = 0; *signatures[i] != '\0' && *name == '\0'; i++) { for (j = EEPROM_PNAME7, k = 0; j <= EEPROM_PNAME0 && k < strlen(signatures[i]); j++) { if (signatures[i][k] == eeprom_image[j]) { /* track signature */ k++; } else { /* lost signature; begin search again */ k = 0; } } if (k == strlen(signatures[i])) { for (k = 0; k < EWRK3_STRLEN; k++) { name[k] = eeprom_image[EEPROM_PNAME7 + k]; name[EWRK3_STRLEN] = '\0'; } } } return; /* return the device name string */}/* ** Look for a special sequence in the Ethernet station address PROM that ** is common across all EWRK3 products. ** ** Search the Ethernet address ROM for the signature. Since the ROM address ** counter can start at an arbitrary point, the search must include the entire ** probe sequence length plus the (length_of_the_signature - 1). ** Stop the search IMMEDIATELY after the signature is found so that the ** PROM address counter is correctly positioned at the start of the ** ethernet address for later read out. */__initfunc(static int DevicePresent(u_long iobase)){ union { struct { u32 a; u32 b; } llsig; char Sig[sizeof(u32) << 1]; } dev; short sigLength; char data; int i, j, status = 0; dev.llsig.a = ETH_PROM_SIG; dev.llsig.b = ETH_PROM_SIG; sigLength = sizeof(u32) << 1; for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) { data = inb(EWRK3_APROM); if (dev.Sig[j] == data) { /* track signature */ j++; } else { /* lost signature; begin search again */ if (data == dev.Sig[0]) { j = 1; } else { j = 0; } } } if (j != sigLength) { status = -ENODEV; /* search failed */ } return status;}__initfunc(static u_char get_hw_addr(struct device *dev, u_char * eeprom_image, char chipType)){ int i, j, k; u_short chksum; u_char crc, lfsr, sd, status = 0; u_long iobase = dev->base_addr; u16 tmp; if (chipType == LeMAC2) { for (crc = 0x6a, j = 0; j < ETH_ALEN; j++) { sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j]; outb(dev->dev_addr[j], EWRK3_PAR0 + j); for (k = 0; k < 8; k++, sd >>= 1) { lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; crc = (crc >> 1) + lfsr; } } if (crc != eeprom_image[EEPROM_PA_CRC]) status = -1; } else { for (i = 0, k = 0; i < ETH_ALEN;) { k <<= 1; if (k > 0xffff) k -= 0xffff; k += (u_char) (tmp = inb(EWRK3_APROM)); dev->dev_addr[i] = (u_char) tmp; outb(dev->dev_addr[i], EWRK3_PAR0 + i); i++; k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8); dev->dev_addr[i] = (u_char) tmp; outb(dev->dev_addr[i], EWRK3_PAR0 + i); i++; if (k > 0xffff) k -= 0xffff; } if (k == 0xffff) k = 0; chksum = inb(EWRK3_APROM); chksum |= (inb(EWRK3_APROM) << 8); if (k != chksum) status = -1; } return status;}/* ** Look for a particular board name in the EISA configuration space */__initfunc(static int EISA_signature(char *name, s32 eisa_id)){ u_long i; char *signatures[] = EWRK3_SIGNATURE; char ManCode[EWRK3_STRLEN]; union { s32 ID; char Id[4]; } Eisa; int status = 0; *name = '\0'; for (i = 0; i < 4; i++) { Eisa.Id[i] = inb(eisa_id + i); } ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); ManCode[5] = '\0'; for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { if (strstr(ManCode, signatures[i]) != NULL) { strcpy(name, ManCode); status = 1; } } return status; /* return the device name string */}/* ** Perform IOCTL call functions here. Some are privileged operations and the ** effective uid is checked in those cases. */static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd){ struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data; u_long iobase = dev->base_addr; int i, j, status = 0; u_char csr; union { u_char addr[HASH_TABLE_LEN * ETH_ALEN]; u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; } tmp; switch (ioc->cmd) { case EWRK3_GET_HWADDR: /* Get the hardware address */ for (i = 0; i < ETH_ALEN; i++) { tmp.addr[i] = dev->dev_addr[i]; } ioc->len = ETH_ALEN; if (!(status = verify_area(VERIFY_WRITE, (void *) ioc->data, ioc->len))) { copy_to_user(ioc->data, tmp.addr, ioc->len); } break; case EWRK3_SET_HWADDR: /* Set the hardware address */ if (capable(CAP_NET_ADMIN)) { if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) { csr = inb(EWRK3_CSR); csr |= (CSR_TXD | CSR_RXD); outb(csr, EWRK3_CSR); /* Disable the TX and RX */ copy_from_user(tmp.addr, ioc->data, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) { dev->dev_addr[i] = tmp.addr[i]; outb(tmp.addr[i], EWRK3_PAR0 + i); } csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */ outb(csr, EWRK3_CSR); } } else { status = -EPERM; } break; case EWRK3_SET_PROM: /* Set Promiscuous Mode */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr |= CSR_PME; csr &= ~CSR_MCE; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_CLR_PROM: /* Clear Promiscuous Mode */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr &= ~CSR_PME; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_SAY_BOO: /* Say "Boo!" to the kernel log file */ printk("%s: Boo!\n", dev->name); break; case EWRK3_GET_MCA: /* Get the multicast address table */ if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { while (test_and_set_bit(0, (void *) &lp->lock) != 0); /* Wait for lock to free */ if (lp->shmem_length == IO_ONLY) { outb(0, EWRK3_IOPR); outw(PAGE0_HTE, EWRK3_PIR1); for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { tmp.addr[i] = inb(EWRK3_DATA); } } else { outb(0, EWRK3_MPR); memcpy_fromio(tmp.addr, (char *) (lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3)); } ioc->len = (HASH_TABLE_LEN >> 3); copy_to_user(ioc->data, tmp.addr, ioc->len); } lp->lock = 0; /* Unlock the page register */ break; case EWRK3_SET_MCA: /* Set a multicast address */ if (capable(CAP_NET_ADMIN)) { if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) { copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len); set_multicast_list(dev); } } else { status = -EPERM; } break; case EWRK3_CLR_MCA: /* Clear all multicast addresses */ if (capable(CAP_NET_ADMIN)) { set_multicast_list(dev); } else { status = -EPERM; } break; case EWRK3_MCA_EN: /* Enable multicast addressing */ if (capable(CAP_NET_ADMIN)) { csr = inb(EWRK3_CSR); csr |= CSR_MCE; csr &= ~CSR_PME; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; case EWRK3_GET_STATS: /* Get the driver statistics */ cli(); ioc->len = sizeof(lp->pktStats); if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { copy_to_user(ioc->data, &lp->pktStats, ioc->len); } sti(); break; case EWRK3_CLR_STATS: /* Zero out the driver statistics */ if (capable(CAP_NET_ADMIN)) { cli(); memset(&lp->pktStats, 0, sizeof(lp->pktStats)); sti(); } else { status = -EPERM; } break; case EWRK3_GET_CSR: /* Get the CSR Register contents */ tmp.addr[0] = inb(EWRK3_CSR); ioc->len = 1; if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { copy_to_user(ioc->data, tmp.addr, ioc->len); } break; case EWRK3_SET_CSR: /* Set the CSR Register contents */ if (capable(CAP_NET_ADMIN)) { if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) { copy_from_user(tmp.addr, ioc->data, 1); outb(tmp.addr[0], EWRK3_CSR); } } else { status = -EPERM; } break; case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { for (i = 0; i < (EEPROM_MAX >> 1); i++) { tmp.val[i] = (short) Read_EEPROM(iobase, i); } i = EEPROM_MAX; tmp.addr[i++] = inb(EWRK3_CMR); /* Config/Management Reg. */ for (j = 0; j < ETH_ALEN; j++) { tmp.addr[i++] = inb(EWRK3_PAR0 + j); } ioc->len = EEPROM_MAX + 1 + ETH_ALEN; if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { copy_to_user(ioc->data, tmp.addr, ioc->len); } } else { status = -EPERM; } break; case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) { copy_from_user(tmp.addr, ioc->data, EEPROM_MAX); for (i = 0; i < (EEPROM_MAX >> 1); i++) { Write_EEPROM(tmp.val[i], iobase, i); } } } else { status = -EPERM; } break; case EWRK3_GET_CMR: /* Get the CMR Register contents */ tmp.addr[0] = inb(EWRK3_CMR); ioc->len = 1; if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { copy_to_user(ioc->data, tmp.addr, ioc->len); } break; case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ if (suser()) { lp->txc = 1; } else { status = -EPERM; } break; case EWRK3_CLR_TX_CUT_THRU: /* Clear TX cut through mode */ if (suser()) { lp->txc = 0; } else { status = -EPERM; } break; default: status = -EOPNOTSUPP; } return status;}#ifdef MODULEstatic char devicename[9] ={0,};static struct device thisEthwrk ={ devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0x300, 5, /* I/O address, IRQ */ 0, 0, 0, NULL, ewrk3_probe};static int io = 0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */static int irq = 5; /* or use the insmod io= irq= options */MODULE_PARM(io, "i");MODULE_PARM(irq, "i");int init_module(void){ thisEthwrk.base_addr = io; thisEthwrk.irq = irq; if (register_netdev(&thisEthwrk) != 0) return -EIO; return 0;}void cleanup_module(void){ unregister_netdev(&thisEthwrk); if (thisEthwrk.priv) { kfree(thisEthwrk.priv); thisEthwrk.priv = NULL; } thisEthwrk.irq = 0; release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);}#endif /* MODULE *//* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" * * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -