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

📄 rtl_rtl8139_drv.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
  	u32 pio_start, pio_end, pio_flags, pio_len;    	unsigned long mmio_start, mmio_end, mmio_flags;  	unsigned int mmio_len;  	u8 tmp8;  	int rc=0, i, option, addr_len;  	static int board_idx=0;  	u32 tmp;  	void *ioaddr = NULL;  	char *print_name;   	print_name = dev ? dev->slot_name : "rtl8139";  	pio_start = rt_pci_resource_start (dev, 0);  	pio_end = rt_pci_resource_end (dev, 0);  	pio_flags = rt_pci_resource_flags (dev, 0);  	pio_len = rt_pci_resource_len (dev, 0);   	mmio_start = rt_pci_resource_start (dev, 1);  	mmio_end = rt_pci_resource_end (dev, 1);  	mmio_flags = rt_pci_resource_flags (dev, 1);  	mmio_len = rt_pci_resource_len (dev, 1);  	rtl_8139_tp.mmio_len = mmio_len;  	/* set this immediately, we need to know before  	* we talk to the chip directly */  	if (pio_len == RTL8139B_IO_SIZE) {  		rtl_8139_tp.chipset = CH_8139B;  	}   	/* make sure PCI base addr 0 is PIO */  	if (!(pio_flags & IORESOURCE_IO)) {  		rtl_printf ("region #0 not a PIO resource, aborting\n");  	}   	/* make sure PCI base addr 1 is MMIO */  	if (!(mmio_flags & IORESOURCE_MEM)) {  		rtl_printf ( "region #1 not an MMIO resource, aborting\n");  	}   	/* check for weird/broken PCI region reporting */  	if ((pio_len < RTL_MIN_IO_SIZE) || (mmio_len < RTL_MIN_IO_SIZE)) {  		rtl_printf ( "Invalid PCI region size(s), aborting\n");  	}    	print_name = dev ? dev->slot_name : "rtl8139";  	rc = pci_request_regions (dev, dev->name);     	if (rc)  		goto err_out;  	pci_set_master (dev);   	/* ioremap MMIO region */  	ioaddr = ioremap (mmio_start, mmio_len);  	if (ioaddr == NULL) {  		rtl_printf ("cannot remap MMIO, aborting\n");  		rc = -EIO;  		goto err_out;  	}  	/* Soft reset the chip. */  	RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);   	/* Check that the chip has finished the reset. */  	for (i = 1000; i > 0; i--)  		if ((RTL_R8 (ChipCmd) & CmdReset) == 0)  			break;  		else  			udelay (10);   	/* Bring the chip out of low-power mode. */  	if (rtl_8139_tp.chipset == CH_8139B) {  		RTL_W8 (Config1, RTL_R8 (Config1) & ~(1<<4));  		RTL_W8 (Config4, RTL_R8 (Config4) & ~(1<<2));  	} else {  		/* handle RTL8139A and RTL8139 cases */  		/* XXX from becker driver. is this right?? */  		RTL_W8 (Config1, 0);  	}  	/* make sure chip thinks PIO and MMIO are enabled */  	tmp8 = RTL_R8 (Config1);  	if ((tmp8 & Cfg1_PIO) == 0) {  		rtl_printf ("PIO not enabled, Cfg1=%02X, aborting\n", tmp8);        	rc = -EIO;        	goto err_out;  	}  	if ((tmp8 & Cfg1_MMIO) == 0) {  		rtl_printf ("MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);        	rc = -EIO;        	goto err_out;  	}  	/* identify chip attached to board */	/*      tmp = RTL_R8 (ChipVersion);   */  	tmp = RTL_R32 (TxConfig);  	tmp = ( (tmp&0x7c000000) + ( (tmp&0x00800000)<<2 ) )>>24;  	rtl_8139_tp.drv_flags = board_info[0].hw_flags;  	rtl_8139_tp.pci_dev = dev;  	rtl_8139_tp.mmio_addr = ioaddr;   	for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--)  		if (tmp == rtl_chip_info[i].version) {        		rtl_8139_tp.chipset = i;        	}  	if(rtl_8139_tp.chipset > (ARRAY_SIZE (rtl_chip_info) - 2))  		rtl_8139_tp.chipset = ARRAY_SIZE (rtl_chip_info) - 2;   	/* Find the connected MII xcvrs.  	Doing this in open() would allow detecting external xcvrs later, but takes too much time. */  	if (rtl_8139_tp.drv_flags & HAS_MII_XCVR) {  		int phy, phy_idx = 0;        	for (phy = 0; phy < 32 && phy_idx < sizeof(rtl_8139_tp.phys); phy++) {        		int mii_status = rt_rtl8139_mdio_read(dev, phy, 1);                	if (mii_status != 0xffff  &&  mii_status != 0x0000) {                       		rtl_8139_tp.phys[phy_idx++] = phy;                       		rtl_8139_tp.advertising = rt_rtl8139_mdio_read(dev, phy, 4);                       		rtl_printf( "%s: MII transceiver %d status 0x%4.4x "                              		"advertising %4.4x.\n",                              		dev->name, phy, mii_status, rtl_8139_tp.advertising);                	}        	}        	if (phy_idx == 0) {                	rtl_printf( "%s: No MII transceivers found!  Assuming SYM "                       		"transceiver.\n",                       		dev->name);                       	rtl_8139_tp.phys[0] = 32;        	}  	} else        	rtl_8139_tp.phys[0] = 32;   	/* Put the chip into low-power mode. */  	RTL_W8_F (Cfg9346, Cfg9346_Unlock);   	tmp = RTL_R8 (Config1) & Config1Clear;  	tmp |= (rtl_8139_tp.chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */  	RTL_W8_F (Config1, tmp);   	RTL_W8_F (HltClk, 'H'); /* 'R' would leave the clock running. */   	/* The lower four bits are the media type. */  	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];  	rtl_8139_tp.AutoNegoAbility = option&0xF;   	if (option > 0) {        	rtl_8139_tp.full_duplex = (option & 0x210) ? 1 : 0;        	rtl_8139_tp.default_port = option & 0xFF;        	if (rtl_8139_tp.default_port)              		rtl_8139_tp.medialock = 1;  	}  	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)        	rtl_8139_tp.full_duplex = full_duplex[board_idx];  	if (rtl_8139_tp.full_duplex) {        	rtl_printf( "%s: Media type forced to Full Duplex.\n", dev->name);        	/* Changing the MII-advertised media because might prevent  re-connection. */        	rtl_8139_tp.duplex_lock = 1;  	}   	if (rtl_8139_tp.default_port) {       		rtl_printf( "%s: Forcing %dMbs %s-duplex operation.\n", dev->name,             		(option & 0x0C ? 100 : 10),             		(option & 0x0A ? "full" : "half"));       			rt_rtl8139_mdio_write(dev, rtl_8139_tp.phys[0], 0,             		((option & 0x20) ? 0x2000 : 0) |     /* 100mbps? */             		((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */  	}  	addr_len = rt_rtl8139_read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;  	for (i = 0; i < 3; i++)     		((u16 *) (rtl_8139_tp.dev_addr))[i] =  le16_to_cpu (rt_rtl8139_read_eeprom (ioaddr, i + 7, addr_len));  	rtl_printf( "%s: %s at 0x%lx, "                "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "                "IRQ %d\n",                dev->name,                board_info[0].name,                rtl_8139_tp.mmio_addr,                rtl_8139_tp.dev_addr[0], rtl_8139_tp.dev_addr[1],                rtl_8139_tp.dev_addr[2], rtl_8139_tp.dev_addr[3],                rtl_8139_tp.dev_addr[4], rtl_8139_tp.dev_addr[5],                dev->irq);  	dev_rtl8139_open(dev);  	return 0;err_out:  		rtl_printf ("EXIT, returning %d\n", rc);  		return rc;}static void rt_rtl8139_tx_clear (struct rtl8139_private rtl_8139_tp){        int i;         rtl_8139_tp.cur_tx = 0;        rtl_8139_tp.dirty_tx = 0;         /* Dump the unsent Tx packets. */        for (i = 0; i < NUM_TX_DESC; i++) {                struct ring_info *rp = &rtl_8139_tp.tx_info[i];                if (rp->mapping != 0) {                        pci_unmap_single (rtl_8139_tp.pci_dev, rp->mapping,                                          rp->skb->len, PCI_DMA_TODEVICE);                        rp->mapping = 0;                }                if (rp->skb) {                        dev_kfree_skb (rp->skb);                        rp->skb = NULL;                        rtl_8139_tp.stats.tx_dropped++;                }        }}static int rt_rtl8139_close (struct pci_dev *dev){        void *ioaddr = rtl_8139_tp.mmio_addr;         rtl_printf ("%s: Shutting down ethercard, status was 0x%4.4x.\n", dev->name, RTL_R16 (IntrStatus));         /* Stop the chip's Tx and Rx DMA processes. */        RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear));         /* Disable interrupts by clearing the interrupt mask. */        RTL_W16 (IntrMask, 0x0000);         /* Update the error counts. */        rtl_8139_tp.stats.rx_missed_errors += RTL_R32 (RxMissed);        RTL_W32 (RxMissed, 0); 	if(rtl_8139_tp.must_free_irq) {        	    rtl_free_irq (dev->irq);	    rtl_8139_tp.must_free_irq = 0;	}         rt_rtl8139_tx_clear(rtl_8139_tp);        pci_free_consistent(rtl_8139_tp.pci_dev, RX_BUF_TOT_LEN,rtl_8139_tp.rx_ring, rtl_8139_tp.rx_ring_dma);        pci_free_consistent(rtl_8139_tp.pci_dev, TX_BUF_TOT_LEN,rtl_8139_tp.tx_bufs, rtl_8139_tp.tx_bufs_dma);        rtl_8139_tp.rx_ring = NULL;        rtl_8139_tp.tx_bufs = NULL;         /* Green! Put the chip in low-power mode. */        RTL_W8 (Cfg9346, Cfg9346_Unlock);        RTL_W8 (Config1, 0x03);        RTL_W8 (HltClk, 'H');   /* 'R' would leave the clock running. */         return 0;}static void  rt_rtl8139_remove_one (struct pci_dev *pdev){	long io_addr; 	io_addr = (long)rtl_8139_tp.mmio_addr;         iounmap (rtl_8139_tp.mmio_addr);        pci_release_regions (pdev);  }/***************************************************************************************/static ssize_t rt_rtl8139_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos){  sem_wait(&rtl8139_sem);  return  rt_rtl8139_policy.extract_frame_of_buffer(&rt_rtl8139_rx_buffer,buf); }/***************************************************************************************/static int rt_rtl8139_ioctl(struct rtl_file * filp, unsigned int request, unsigned long other){  	switch(request) {  	case 1:           /* set_ip_filter */    		rt_rtl8139_set_ip_filter(other);    		break;  	case 2:           /* obtain_mac_address */    		rt_rtl8139_obtain_mac_address((unsigned char *)other);    		break;  	}  	return 0;}/***************************************************************************************/static int rt_rtl8139_release (struct rtl_file *filp){	rtl_irqstate_t state;	rtl_no_interrupts(state);		rtl_printf("rtl8139_close\n");  	rt_rtl8139_close(rtl8139dev);	rtl_printf("rtl8139_remove_one\n");	rt_rtl8139_remove_one (rtl8139dev);    	if(rt_rtl8139_opened == 0x01){	  sem_destroy(&rtl8139_sem);	  rtl_printf("Deallocating rx_buffer\n");	  rt_rtl8139_policy.dealloc_rx_buffer(&rt_rtl8139_rx_buffer);    	}	rtl_printf("After deallocating rx_buffer\n");	rt_rtl8139_opened = 0x00;	rtl_restore_interrupts(state);    	return 0;}/***************************************************************************************/static ssize_t rt_rtl8139_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos){  	ssize_t tmp;  	rtl_irqstate_t state;   	rtl_no_interrupts(state);  	tmp=rt_rtl8139_send_packet(buf,count);  	rtl_restore_interrupts(state);   	return tmp; }/***************************************************************************************/static int rt_rtl8139_open (struct rtl_file *filp){  	if(rt_rtl8139_opened == 0x00){    		if((rtl8139dev = init_rtl8139_device())!=NULL){		  sem_init(&rtl8139_sem, 0, 0);		  start_up_rtl8139_device(rtl8139dev);		  rt_rtl8139_opened = 0x01;		  rtl_printf("Successfully Opened\n");		  return RTL8139_MAJOR;    		}else{      			rtl_printf("ERROR: Couldn't initialize device\n");      			return -1;    		}  	}else{    		rtl_printf("Device is already opened\n");    		return -1;  	}}/***************************************************************************************/struct pci_dev *init_rtl8139_device(void){  	struct pci_dev *dev;   	/* First of all, we must get a pointer to the pci_dev structure */  	if((dev = rt_pci_find_device(RTL8139_VENDOR_ID, RTL8139_DEVICE_ID, NULL))== NULL)    	return NULL;   	rt_rtl8139_policy.initialize_rx_buffer(&rt_rtl8139_rx_buffer);   	/* Let's enable the device */  	if (rt_pci_enable_device(dev)){    		rtl_printf("PCI ERROR: Can't enable device\n");    		return NULL;  	}   	return dev;}/***************************************************************************************/int init_module(void){  	printk("\n\n\nRT-Linux driver for the Ethernet Card rtl8139 being loaded\n\n\n");   	if (rtl_register_rtldev (RTL8139_MAJOR, RTL8139_NAME, &rt_rtl8139_fops)) {    		printk ("RTLinux /dev/%s: unable to get RTLinux major %d\n", RTL8139_NAME, RTL8139_MAJOR);    		return -EIO;  	}else{    		printk("Registered device /dev/%s major number %d\n",RTL8139_NAME, RTL8139_MAJOR);    		rt_rtl8139_registered = 0x01;    		return 0;  	}}/***************************************************************************************/void cleanup_module(void){  	int inside = 1;  	rtl_irqstate_t state; 	if((rt_rtl8139_opened == 0x01) || rt_rtl8139_inside_the_interrupt_handler){	  rt_rtl8139_trying_to_close = 1; 	  /* Since inside the interrupt handler there's a call to the scheduler, there may  */	  /* be an execution of the interrupt handler that hasn't been completely executed. */	  /* The card cannot be released in that case, so we must be sure that there is no  */	  /* interrupt handler execution pending. Otherwise, that may crash the system.     */	  while(inside){	    rtl_no_interrupts(state); 	    if(rt_rtl8139_inside_the_interrupt_handler){	      rtl_restore_interrupts(state);	      usleep(10);	    }else{	      rtl_hard_disable_irq(rtl_8139_tp.pci_dev->irq);	      rtl_restore_interrupts(state);	      inside = 0;	    }	  }	}  	if(rt_rtl8139_registered == 0x01){    		printk("Unregistering device /dev/%s\n",RTL8139_NAME);    		rtl_unregister_rtldev(RTL8139_MAJOR,RTL8139_NAME);  	}  	printk("\n\n\nRT-Linux driver for the Ethernet Card rtl8139 being removed\n\n\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -