📄 linux_2_6_14_cs8900.diff
字号:
+ if ((status & TxBidErr)) {+ spin_unlock_irq(&priv->lock);+ printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);+ priv->stats.tx_errors++;+ priv->stats.tx_aborted_errors++;+ priv->txlen = 0;+ return (1);+ }++ if (!(status & Rdy4TxNOW)) {+ spin_unlock_irq(&priv->lock);+ printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);+ priv->stats.tx_errors++;+ priv->txlen = 0;+ /* FIXME: store skb and send it in interrupt handler */+ return (1);+ }++ cs8900_frame_write (dev,skb);+ spin_unlock_irq(&priv->lock);++#ifdef DEBUG+ dump_packet (dev,skb,"send");+#endif /* #ifdef DEBUG */++ dev->trans_start = jiffies;++ dev_kfree_skb (skb);++ priv->txlen = skb->len;++ return (0);+}++static irqreturn_t cs8900_interrupt (int irq,void *id,struct pt_regs *regs)+{+ struct net_device *dev = (struct net_device *) id;+ cs8900_t *priv;+ volatile u16 status;+ irqreturn_t handled = 0;+ + if (dev->priv == NULL) {+ printk (KERN_WARNING "%s: irq %d for unknown device.\n",dev->name,irq);+ return 0;+ }++ priv = (cs8900_t *) dev->priv;+ + while ((status = cs8900_read (dev, PP_ISQ))) {+ handled = 1;++ switch (RegNum (status)) {+ case RxEvent:+ cs8900_receive (dev);+ break;++ case TxEvent:+ priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));+ if (!(RegContent (status) & TxOK)) {+ priv->stats.tx_errors++;+ if ((RegContent (status) & Out_of_window)) priv->stats.tx_window_errors++;+ if ((RegContent (status) & Jabber)) priv->stats.tx_aborted_errors++;+ break;+ } else if (priv->txlen) {+ priv->stats.tx_packets++;+ priv->stats.tx_bytes += priv->txlen;+ }+ priv->txlen = 0;+ netif_wake_queue (dev);+ break;++ case BufEvent:+ if ((RegContent (status) & RxMiss)) {+ u16 missed = MissCount (cs8900_read (dev,PP_RxMISS));+ priv->stats.rx_errors += missed;+ priv->stats.rx_missed_errors += missed;+ }+ if ((RegContent (status) & TxUnderrun)) {+ priv->stats.tx_errors++;+ priv->stats.tx_fifo_errors++;++ priv->txlen = 0;+ netif_wake_queue (dev);+ }+ /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */+ break;++ case TxCOL:+ priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));+ break;++ case RxMISS:+ status = MissCount (cs8900_read (dev,PP_RxMISS));+ priv->stats.rx_errors += status;+ priv->stats.rx_missed_errors += status;+ break;+ }+ }+ return IRQ_RETVAL(handled);+}++static void cs8900_transmit_timeout (struct net_device *dev)+{+ cs8900_t *priv = (cs8900_t *) dev->priv;+ priv->stats.tx_errors++;+ priv->stats.tx_heartbeat_errors++;+ priv->txlen = 0;+ netif_wake_queue (dev);+}++static int cs8900_start (struct net_device *dev)+{+ int result;++#if defined(CONFIG_ARCH_SMDK2410)+ set_irq_type(dev->irq, IRQT_RISING);++ /* enable the ethernet controller */+ cs8900_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE);+ cs8900_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA);+ cs8900_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE);+ cs8900_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE);+ cs8900_set (dev,PP_LineCTL,SerRxON | SerTxON);+ cs8900_set (dev,PP_BusCTL,EnableRQ);++#ifdef FULL_DUPLEX+ cs8900_set (dev,PP_TestCTL,FDX);+#endif /* #ifdef FULL_DUPLEX */+ udelay(200); + /* install interrupt handler */+ if ((result = request_irq (dev->irq, &cs8900_interrupt, 0, dev->name, dev)) < 0) {+ printk ("%s: could not register interrupt %d\n",dev->name, dev->irq);+ return (result);+ }+#else+ + /* install interrupt handler */+ if ((result = request_irq (dev->irq, &cs8900_interrupt, 0, dev->name, dev)) < 0) {+ printk ("%s: could not register interrupt %d\n",dev->name, dev->irq);+ return (result);+ }++ set_irq_type(dev->irq, IRQT_RISING);++ /* enable the ethernet controller */+ cs8900_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE);+ cs8900_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA);+ cs8900_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE);+ cs8900_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE);+ cs8900_set (dev,PP_LineCTL,SerRxON | SerTxON);+ cs8900_set (dev,PP_BusCTL,EnableRQ);++#ifdef FULL_DUPLEX+ cs8900_set (dev,PP_TestCTL,FDX);+#endif /* #ifdef FULL_DUPLEX */+ +#endif /* #if defined(CONFIG_ARCH_SMDK2410) */++ /* start the queue */+ netif_start_queue (dev);++ return (0);+}++static int cs8900_stop (struct net_device *dev)+{+ /* disable ethernet controller */+ cs8900_write (dev,PP_BusCTL,0);+ cs8900_write (dev,PP_TestCTL,0);+ cs8900_write (dev,PP_SelfCTL,0);+ cs8900_write (dev,PP_LineCTL,0);+ cs8900_write (dev,PP_BufCFG,0);+ cs8900_write (dev,PP_TxCFG,0);+ cs8900_write (dev,PP_RxCTL,0);+ cs8900_write (dev,PP_RxCFG,0);++ /* uninstall interrupt handler */+ free_irq (dev->irq,dev);++ /* stop the queue */+ netif_stop_queue (dev);++ return (0);+}++static struct net_device_stats *cs8900_get_stats (struct net_device *dev)+{+ cs8900_t *priv = (cs8900_t *) dev->priv;+ return (&priv->stats);+}++static void cs8900_set_receive_mode (struct net_device *dev)+{+ if ((dev->flags & IFF_PROMISC))+ cs8900_set (dev,PP_RxCTL,PromiscuousA);+ else+ cs8900_clear (dev,PP_RxCTL,PromiscuousA);++ if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)+ cs8900_set (dev,PP_RxCTL,MulticastA);+ else+ cs8900_clear (dev,PP_RxCTL,MulticastA);+}++static int cs8900_eeprom (struct net_device *dev)+{+ cs8900_t *priv = (cs8900_t *) dev->priv;+ int i;++ /* SMDK2410 CS8900A without EEPROM at all */+#if defined(CONFIG_ARCH_SMDK2410)+ return (-ENODEV);+#endif ++#ifdef DEBUG+ eepromdump (dev);+#endif++ if( (cs8900_read( dev, PP_SelfST) & EEPROMpresent) == 0)+ {+ /* no eeprom */+ return (-ENODEV);+ }++ /* add character device for easy eeprom programming */+ if( (priv->char_devnum=register_chrdev(0,"cs8900_eeprom",&cs8900_eeprom_fops)) != 0)+ printk (KERN_INFO "%s: Registered cs8900_eeprom char device (major #%d)\n",+ dev->name, priv->char_devnum);+ else+ printk (KERN_WARNING "%s: Failed to register char device cs8900_eeprom\n",dev->name);++ if( (cs8900_read( dev, PP_SelfST) & EEPROMOK) == 0) + {+ /* bad checksum, invalid config block */+ return (-EFAULT);+ }++ /* If we get here, the chip will have initialized the registers+ * that were specified in the eeprom configuration block+ * We assume this is at least the mac address.+ */+ for (i = 0; i < ETH_ALEN; i += 2)+ {+ u16 mac = cs8900_read (dev,PP_IA + i);+ dev->dev_addr[i] = mac & 0xff;+ dev->dev_addr[i+1] = (mac>>8) & 0xff;+ }++ return (0);+}++/*+ * EEPROM Charater device+ */++static int cs8900_eeprom_fopen(struct inode *inode, struct file *file)+{+ u16 i;+ for( i=0; i<MAX_EEPROM_SIZE/2; i++)+ {+ cs8900_eeprom_read( &cs8900_dev, &cs8900_eeprom_cache[i],i);+ }++ return 0;+}++static int cs8900_eeprom_frelease(struct inode *inode, struct file *file)+{+ return 0;+}++static loff_t cs8900_eeprom_fllseek(struct file * file,loff_t offset, int whence)+{+ long newpos;++ switch(whence)+ {+ case 0: /* SEEK_SET */+ newpos = offset;+ break;+ case 1: /* SEEK_CUR */+ newpos = file->f_pos + offset;+ break;+ case 2: /* SEEK_END */+ newpos = (MAX_EEPROM_SIZE-1) - offset;+ break;+ default: /* can't happen */+ return -EINVAL;++ }++ if( (newpos<0) || (newpos>=MAX_EEPROM_SIZE)) return -EINVAL;++ file->f_pos = newpos;+ return newpos;+}++static ssize_t cs8900_eeprom_fread(struct file *file, char *buf, size_t count, loff_t *f_pos)+{+ unsigned char *temp = (unsigned char *)cs8900_eeprom_cache;++ if (*f_pos >= MAX_EEPROM_SIZE)+ return 0;++ if (*f_pos + count > MAX_EEPROM_SIZE)+ count = MAX_EEPROM_SIZE - *f_pos;++ if (count<1)+ return 0;++ if (copy_to_user(buf, &temp[*f_pos], count)){+ return -EFAULT;+ }+ *f_pos += count;+ return count;+}++static ssize_t cs8900_eeprom_fwrite(struct file *file, const char *buf, size_t count, loff_t *f_pos)+{+ u16 i;+ unsigned char *temp = (unsigned char *)cs8900_eeprom_cache;++ if (*f_pos >= MAX_EEPROM_SIZE)+ return 0;++ if (*f_pos + count > MAX_EEPROM_SIZE)+ count = MAX_EEPROM_SIZE - *f_pos;++ if (count<1)+ return 0;++ /* FIXME: lock critical section */++ /* update the cache */+ if (copy_from_user(&temp[*f_pos], buf, count)){+ return -EFAULT;+ }++ /* not concerned about performance, so write the entire thing */+ for( i=0; i<MAX_EEPROM_SIZE/2; i++)+ {+ cs8900_eeprom_write( &cs8900_dev, &cs8900_eeprom_cache[i],i);+ }++ *f_pos += count;+ return count;+}++/*+ * Architecture dependant code+ */++#ifdef CONFIG_SA1100_FRODO+static void frodo_reset (struct net_device *dev)+{+ int i;+ volatile u16 value;++ /* reset ethernet controller */+ FRODO_CPLD_ETHERNET |= FRODO_ETH_RESET;+ mdelay (50);+ FRODO_CPLD_ETHERNET &= ~FRODO_ETH_RESET;+ mdelay (50);++ /* we tied SBHE to CHIPSEL, so each memory access ensure the chip is in 16-bit mode */+ for (i = 0; i < 3; i++) value = cs8900_read (dev,0);++ /* FIXME: poll status bit */+}+#endif /* #ifdef CONFIG_SA1100_FRODO */++/*+ * Driver initialization routines+ */++int __init cs8900_probe (struct net_device *dev)+{+ static cs8900_t priv;+ int i,result;+ u16 value;++ printk (VERSION_STRING"\n");++ memset (&priv,0,sizeof (cs8900_t));++ ether_setup (dev);++ dev->open = cs8900_start;+ dev->stop = cs8900_stop;+ dev->hard_start_xmit = cs8900_send_start;+ dev->get_stats = cs8900_get_stats;+ dev->set_multicast_list = cs8900_set_receive_mode;+ dev->tx_timeout = cs8900_transmit_timeout;+ dev->watchdog_timeo = HZ;++#if defined(CONFIG_ARCH_SMDK2410)+ dev->dev_addr[0] = 0x08;+ dev->dev_addr[1] = 0x00;+ dev->dev_addr[2] = 0x3e;+ dev->dev_addr[3] = 0x26;+ dev->dev_addr[4] = 0x0a;+ dev->dev_addr[5] = 0x5b;+#else+ dev->dev_addr[0] = 0x00;+ dev->dev_addr[1] = 0x12;+ dev->dev_addr[2] = 0x34;+ dev->dev_addr[3] = 0x56;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -