📄 cs8900a_char_core.c
字号:
#define IRQ_LAN IRQ_CS8900static int base_addr = 0xd0000300;static int irq = IRQ_LAN;static int curr_rx_cfg; /* a copy of PP_RxCFG */static int send_cmd;static int rx_ok = 0;spinlock_t cs_lock;/* buffering the data */unsigned char BUF[1600];unsigned char RBUF[1600];static int rlength=0;/* device name & major */#define DEVICE_NAME "mycs8900a"#define DEVICE_MAJOR 253inline int readreg(int portno) { outw(portno, base_addr + ADD_PORT); return inw(base_addr + DATA_PORT);}voidmy_msleep(int ms){ current->state = TASK_INTERRUPTIBLE; schedule_timeout(ms*HZ/1000);}static int __init cs89x0_probe(void) { unsigned rev_type = 0; int ret; unsigned char dev_addr[6]; BWSCON = (BWSCON & ~(BWSCON_ST2 | BWSCON_WS2 | BWSCON_DW2)) | (BWSCON_ST2 | BWSCON_WS2 | BWSCON_DW(2, BWSCON_DW_16)); BANKCON2= BANKCON_Tacs0 | BANKCON_Tcos4 | BANKCON_Tacc14 | BANKCON_Toch1 | BANKCON_Tcah4 | BANKCON_Tacp6 | BANKCON_PMC1; set_external_irq(IRQ_CS8900, EXT_RISING_EDGE, GPIO_PULLUP_DIS); /* get the chip type */ rev_type = readreg(PRODUCT_ID_ADD); rev_type = rev_type &~ REVISON_BITS; if (rev_type != CS8900) { printk(__FILE__ ": wrong device driver!\n"); ret = -ENODEV; return ret; } reset_chip(); dev_addr[0] = 0x00; dev_addr[1] = 0x00; dev_addr[2] = 0xc0; dev_addr[3] = 0x22; dev_addr[4] = 0x33; dev_addr[5] = 0x00; set_mac_address(dev_addr); send_cmd = TX_AFTER_ALL; ret = cs8900_initreg( ); if (ret) return ret; /* Fill in the fields of the device structure with ethernet values. */ set_multicast_list( ); printk("\n"); DPRINTK(1, "cs89x0_probe() successful\n"); return 0; }void __init reset_chip( ){ int reset_start_time; writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET); /* wait 30 ms */ my_msleep(30); /* Wait until the chip is reset */ reset_start_time = jiffies; while( (readreg(PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 4) ;}static int cs8900_initreg( void ){ int ret; /* Prevent the crystal chip from generating interrupts */ writereg(PP_BusCTL, readreg(PP_BusCTL) & ~ENABLE_IRQ); ret = request_irq(irq, &net_interrupt, SA_INTERRUPT, "cs8900", NULL); if (ret) { printk("%s: request_irq(%d) failed\n", "cs8900", irq); goto bad_out; } writereg(PP_CS8900_ISAINT, 0); /* while we're testing the interface, leave interrupts disabled */ writereg(PP_BusCTL, MEMORY_ON); /* Turn on both receive and transmit operations */ writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON); /* Receive only error free packets addressed to this card */ writereg( PP_RxCTL, DEF_RX_ACCEPT); curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL; writereg(PP_RxCFG, curr_rx_cfg); writereg( PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); writereg(PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL); /* now that we've got our act together, enable everything */ writereg(PP_BusCTL, readreg(PP_BusCTL) | ENABLE_IRQ); enable_irq(irq); DPRINTK(1, "cs89x0: net_open() succeeded\n"); return 0; bad_out: return ret;}static int net_send_packet(unsigned char *buf,int len){ writereg(PP_BusCTL, 0x0); writereg(PP_BusCTL, readreg(PP_BusCTL) | ENABLE_IRQ); /* keep the upload from being interrupted, since we ask the chip to start transmitting before the whole packet has been completely uploaded. */ spin_lock(&cs_lock); /* initiate a transmit sequence */ writeword(TX_CMD_PORT, send_cmd); writeword(TX_LEN_PORT, len); /* Test to see if the chip has allocated memory for the packet */ if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) { /* * Gasp! It hasn't. But that shouldn't happen since * we're waiting for TxOk, so return 1 and requeue this packet. */ spin_unlock_irq(&cs_lock); DPRINTK(1, "cs89x0: Tx buffer not free!\n"); return -1; } /* Write the contents of the packet */ writeblock(buf, len); spin_unlock(&cs_lock); return 0;}/* The typical workload of the driver: Handle the network interface interrupts. */ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs){ int status; while ((status = readword(ISQ_PORT))) { switch(status & ISQ_EVENT_MASK) { case ISQ_RECEIVER_EVENT: net_rx(); break; case ISQ_TRANSMITTER_EVENT: break; case ISQ_BUFFER_EVENT: break; case ISQ_RX_MISS_EVENT: break; case ISQ_TX_COL_EVENT: break; } }}/* We have a good packet(s), get it/them out of the buffers. */static void net_rx() { int status, length; status = inw(base_addr + RX_FRAME_PORT); if ((status & RX_OK) == 0) { return ; } length = inw(base_addr + RX_FRAME_PORT); readblock(RBUF, length); rlength = length; rx_ok = 1;}static void set_multicast_list( ){ unsigned long flags; spin_lock_irqsave(&cs_lock, flags); writereg( PP_RxCTL, DEF_RX_ACCEPT | RX_ALL_ACCEPT); /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */ writereg( PP_RxCFG,curr_rx_cfg | (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) ); spin_unlock_irqrestore(&cs_lock, flags);}static int set_mac_address(unsigned char *addr){ int i; /* set the Ethernet address */ for (i=0; i < 3; i++) writereg(PP_IA+i*2, addr[i*2] | (addr[i*2+1] << 8)); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -