📄 ewrk3.c
字号:
dev->init = init; /* initialisation routine */ } return dev;}static intewrk3_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.*/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.*/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;}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*/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))) { memcpy_tofs(ioc->data, tmp.addr, ioc->len); } break; case EWRK3_SET_HWADDR: /* Set the hardware address */ if (suser()) { 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 */ memcpy_fromfs(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 (suser()) { 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 (suser()) { 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 (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); memcpy_tofs(ioc->data, tmp.addr, ioc->len); } lp->lock = 0; /* Unlock the page register */ break; case EWRK3_SET_MCA: /* Set a multicast address */ if (suser()) { if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) { memcpy_fromfs(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 (suser()) { set_multicast_list(dev); } else { status = -EPERM; } break; case EWRK3_MCA_EN: /* Enable multicast addressing */ if (suser()) { 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))) { memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); } sti(); break; case EWRK3_CLR_STATS: /* Zero out the driver statistics */ if (suser()) { 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))) { memcpy_tofs(ioc->data, tmp.addr, ioc->len); } break; case EWRK3_SET_CSR: /* Set the CSR Register contents */ if (suser()) { if (!(status=verify_area(VERIFY_READ, ioc->data, 1))) { memcpy_fromfs(tmp.addr, ioc->data, 1); outb(tmp.addr[0], EWRK3_CSR); } } else { status = -EPERM; } break; case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ if (suser()) { 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))) { memcpy_tofs(ioc->data, tmp.addr, ioc->len); } } else { status = -EPERM; } break; case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ if (suser()) { if (!(status=verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) { memcpy_fromfs(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))) { memcpy_tofs(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 */intinit_module(void){ thisEthwrk.base_addr=io; thisEthwrk.irq=irq; if (register_netdev(&thisEthwrk) != 0) return -EIO; return 0;}voidcleanup_module(void){ if (thisEthwrk.priv) { kfree(thisEthwrk.priv); thisEthwrk.priv = NULL; } thisEthwrk.irq = 0; unregister_netdev(&thisEthwrk); 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 + -