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

📄 cs8900a_char_core.c

📁 在s3c2410上把cs8900a网卡实现为一个字符设备,是新手学习字符设备的好思路
💻 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 + -