Main Page | Directories | File List | Globals

rtl_8029.c

Go to the documentation of this file.
00001 /*
00002  * kernel_drivers/adi_net/rtl_8029.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/08
00008  * Author:      Lukasz Dembinski
00009  * Info:        rtl_8029.c
00010  * Contact:     mailto: <dembol@nasa.com.pl>
00011  *
00012  */
00013 
00014 /*
00015  * TODO:
00016  * - support for multiple RTL-s
00017  */
00018 
00019 #include <agnix/agnix.h>
00020 #include <agnix/init.h>
00021 #include <agnix/adi/adi.h>
00022 #include <agnix/ioport.h>
00023 #include <agnix/console.h>
00024 #include <agnix/irq.h>
00025 #include <agnix/memory.h>
00026 #include <agnix/net/net.h>
00027 #include <agnix/counters.h>
00028 
00029 #define MOD_NAME        "NET_RTL_8029: "
00030 
00031 #define RTL_8029_MAX_RESET_TIME 10
00032 
00033 /*
00034  * RTL 8029 read registers PAGE0
00035  */
00036 #define RTL_8029_CR             0x00
00037 #define RTL_8029_CLDA0          0x01
00038 #define RTL_8029_CLDA1          0x02
00039 #define RTL_8029_BNRY           0x03
00040 #define RTL_8029_TSR            0x04
00041 #define RTL_8029_NCR            0x05
00042 #define RTL_8029_FIFO           0x06
00043 #define RTL_8029_ISR            0x07
00044 #define RTL_8029_CRDA0          0x08
00045 #define RTL_8029_CRDA1          0x09
00046 #define RTL_8029_RSR            0x0c
00047 #define RTL_8029_CNTR0          0x0d
00048 #define RTL_8029_CNTR1          0x0e
00049 #define RTL_8029_CNTR2          0x0f
00050 
00051 #define RTL_8029_DMADATA        0x10
00052 #define RTL_8029_RESET          0x1f
00053 
00054 /*
00055  * RTL 8029 write registers PAGE0
00056  */
00057 #define RTL_8029_PSTART         0x01
00058 #define RTL_8029_PSTOP          0x02
00059 #define RTL_8029_TPSR           0x04
00060 #define RTL_8029_TBCR0          0x05
00061 #define RTL_8029_TBCR1          0x06
00062 #define RTL_8029_RSAR0          0x08
00063 #define RTL_8029_RSAR1          0x09
00064 #define RTL_8029_RBCR0          0x0a
00065 #define RTL_8029_RBCR1          0x0b
00066 #define RTL_8029_RCR            0x0c
00067 #define RTL_8029_TCR            0x0d
00068 #define RTL_8029_DCR            0x0e
00069 #define RTL_8029_IMR            0x0f
00070 
00071 /*
00072  * RTL 8029 CR bits
00073  */
00074 #define CR_STP                  0x01
00075 #define CR_STA                  0x02
00076 #define CR_TXP                  0x04
00077 #define CR_READ_DMA             0x08
00078 #define CR_WRITE_DMA            0x10
00079 #define CR_ABORT_DMA            0x20
00080 #define CR_PAGE0                0x00
00081 #define CR_PAGE1                0x40
00082 #define CR_PAGE2                0x80
00083 
00084 /*
00085  * RTL 8029 ISR bits
00086  */
00087 #define ISR_PRX                 0x01
00088 #define ISR_PTX                 0x02
00089 #define ISR_PRXE                0x04
00090 #define ISR_PTXE                0x08
00091 #define ISR_OVW                 0x10
00092 #define ISR_CNT                 0x20
00093 #define ISR_RDC                 0x40
00094 #define ISR_RESET               0x80
00095 
00096 
00097 /*
00098  * RTL 8029 IMR bits
00099  */
00100 #define IMR_PRXE                0x01
00101 #define IMR_PTXE                0x02
00102 #define IMR_RXEE                0x04
00103 #define IMR_TXEE                0x08
00104 #define IMR_OVWE                0x10
00105 #define IMR_CNTE                0x20
00106 #define IMR_RDCE                0x40
00107 
00108 /*
00109  * RTL 8029 RCR bits
00110  */
00111 #define RCR_BROADCAST           0x04
00112 #define RCR_MULTICAST           0x08
00113 #define RCR_PROMISC             0x10
00114 
00115 
00116 /*
00117  * RTL 8029 read registers PAGE1
00118  */
00119 
00120 #define RTL_8029_CURR           0x07 
00121 
00122 /*
00123  * RTL 8029 read registers PAGE1
00124  */
00125 
00126 #define RTL_8029_CURR           0x07 
00127 
00128 /*
00129  * RTL_8029 transmit pages
00130  * 12 pages = 2 ethernet frames max
00131  * 6 pages  = 1 ethernet frame max
00132  */ 
00133 #define RTL_8029_TX_PAGES       12
00134 
00135 /*
00136  * some defines
00137  */
00138 #define NET_RECV_MODE_BROADCAST 0x01
00139 #define NET_RECV_MODE_MULTICAST 0x02
00140 #define NET_RECV_MODE_PROMISC   0x04
00141 #define RTL_8029_MIN_FRB_LEN    63
00142 #define RTL_8029_DEBUG          0
00143 
00144 extern int counter_jiffies_desc;
00145 
00146 u32 rtl_iobase;
00147 u8  rtl_eprom[32];
00148 
00149 struct adi_netdev_s rtl_8029_netdev;
00150 struct rtl_8029_param_s rtl_8029_netdev_param;
00151 
00152 struct adi_driver_id_s rtl_8029_driver_id[] = {
00153     { PCIBUS_VENDOR_REALTEK_ID, PCIBUS_DEVICE_RTL_8029_AS__ID },
00154     { 0 }    
00155 };
00156 
00157 int rtl_8029_reset(struct pcidev_s *pcidev)
00158 {
00159     u32 start_jiffies;
00160     u32 jiffies_latch[2];
00161     
00162     counter_read(counter_jiffies_desc, jiffies_latch);
00163     start_jiffies = jiffies_latch[0];
00164     
00165     outb(inb(rtl_iobase + RTL_8029_RESET), rtl_iobase + RTL_8029_RESET);
00166     
00167     while(!(inb(rtl_iobase + RTL_8029_ISR) & ISR_RESET)) {
00168         counter_read(counter_jiffies_desc, jiffies_latch);
00169         if (jiffies_latch[0] - start_jiffies >= RTL_8029_MAX_RESET_TIME) {
00170             printk(MOD_NAME "reset failure\n");
00171             return -1;
00172         }
00173     }
00174     
00175     outb(0xff, rtl_iobase + RTL_8029_ISR);
00176     
00177     return 0;
00178 }
00179 
00180 int rtl_8029_set_recv_mode(struct adi_netdev_s *netdev, int recv_mode)
00181 {
00182     u32 rtl_8029_rcr = 0;
00183 
00184     if (recv_mode & NET_RECV_MODE_BROADCAST) {
00185         rtl_8029_rcr |= RCR_BROADCAST;
00186     }
00187     
00188     if (recv_mode & NET_RECV_MODE_MULTICAST) {
00189         rtl_8029_rcr |= RCR_MULTICAST;
00190     }
00191     
00192     if (recv_mode & NET_RECV_MODE_PROMISC) {
00193         rtl_8029_rcr |= RCR_PROMISC;
00194     }
00195 
00196     outb(rtl_8029_rcr, rtl_iobase + RTL_8029_RCR);
00197 
00198     return 0;
00199 }
00200 
00201 int rtl_8029_open(void)
00202 {
00203     return 0;
00204 }
00205 
00206 int rtl_8029_send_frame(struct frb_s *frb)
00207 {
00208     u32 flags;
00209     u16 frame_len = frb->frb_len;    
00210     u8 *ptr;
00211     int i;
00212 
00213     if (frame_len < RTL_8029_MIN_FRB_LEN)
00214         frame_len = RTL_8029_MIN_FRB_LEN;
00215     
00216     if (rtl_8029_netdev_param.tx_busy[0])
00217         return -1;
00218         
00219     spin_lock_irqsave(&rtl_8029_netdev.if_lock, flags);
00220 
00221     rtl_8029_netdev_param.tx_busy[0] = 1;
00222 
00223     outb(0x00, rtl_iobase + RTL_8029_IMR);
00224 
00225     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00226     outb(0x42, rtl_iobase + RTL_8029_RBCR0);
00227     outb(0x00, rtl_iobase + RTL_8029_RBCR1);
00228     outb(0x42, rtl_iobase + RTL_8029_RSAR0);
00229     outb(0x00, rtl_iobase + RTL_8029_RSAR1);
00230     outb(CR_READ_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00231     outb(ISR_RDC, rtl_iobase + RTL_8029_ISR);
00232     
00233     outb(frame_len & 0xff, rtl_iobase + RTL_8029_RBCR0);
00234     outb(frame_len >> 8,   rtl_iobase + RTL_8029_RBCR1);
00235     outb(0, rtl_iobase + RTL_8029_RSAR0);
00236     outb(rtl_8029_netdev_param.tx_start_page, rtl_iobase + RTL_8029_RSAR1);
00237     outb(CR_WRITE_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00238 
00239     ptr = frb_data(frb);
00240     for (i = 0; i < (frame_len >> 2); i++) {
00241         outl(*(u32 *)ptr, rtl_iobase + RTL_8029_DMADATA);
00242         ptr += 4;
00243     }
00244     
00245     if ((frame_len & 3) == 2) {
00246         outw(*(u16 *)ptr, rtl_iobase + RTL_8029_DMADATA);
00247         ptr += 2;
00248     }
00249 
00250     if ((frame_len & 3) == 1)
00251         outb(*(u8 *)ptr, rtl_iobase + RTL_8029_DMADATA);
00252 
00253 //    wait max 40 ms for remote DMA complete
00254 //    while((inb(rtl_iobase + RTL_8029_ISR) & ISR_RDC) == 0) {
00255 //        counter_read(counter_jiffies_desc, jiffies_latch);
00256 //      if (jiffies_latch[0] - start_jiffies >= 200) {
00257 //          printk(MOD_NAME "Timeout on waiting for ISR_RDC\n");
00258 //          break;
00259 //      }
00260 //    }
00261     
00262     outb(ISR_RDC, rtl_iobase + RTL_8029_ISR);
00263 
00264     /* send transmit triggers */
00265     outb(CR_PAGE0 | CR_ABORT_DMA, rtl_iobase + RTL_8029_CR);
00266     outb(frame_len & 0xff, rtl_iobase + RTL_8029_TBCR0);
00267     outb(frame_len >> 8,   rtl_iobase + RTL_8029_TBCR1);
00268     outb(rtl_8029_netdev_param.tx_start_page, rtl_iobase + RTL_8029_TPSR);
00269     outb(CR_PAGE0 | CR_TXP | CR_STA, rtl_iobase + RTL_8029_CR);
00270     outb(IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE, rtl_iobase + RTL_8029_IMR);
00271 
00272     spin_unlock_irqrestore(&rtl_8029_netdev.if_lock, flags);
00273     
00274     return 0;
00275 }
00276 
00277 int rtl_8029_receive_frame(struct frb_s *frb)
00278 {
00279     struct rtl_8029_rx_desc_s rx_desc;
00280     u8 *ptr;
00281     u8 current_page;
00282     u8 boundary_page;
00283     u8 next_page;
00284     u16 frame_len;
00285     int i;
00286 
00287     outb(CR_PAGE1 | CR_ABORT_DMA | CR_STP, rtl_iobase + RTL_8029_CR);    
00288     current_page  = inb(rtl_iobase + 0x07);
00289     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STP, rtl_iobase + RTL_8029_CR);    
00290 
00291     boundary_page = inb(rtl_iobase + RTL_8029_BNRY) + 1;
00292 
00293 #if RTL_8029_DEBUG
00294     printk("boundary = %02x\n", boundary_page);
00295 #endif
00296 
00297     if (boundary_page >= 0x80)
00298         boundary_page = 0x40 + RTL_8029_TX_PAGES;
00299 
00300     if (boundary_page == current_page) {
00301         return -1;
00302     }
00303 
00304     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00305     outb(sizeof(rx_desc), rtl_iobase + RTL_8029_RBCR0); // lo
00306     outb(0x00, rtl_iobase + RTL_8029_RBCR1);            // hi
00307     outb(0x00, rtl_iobase + RTL_8029_RSAR0);
00308     outb(boundary_page, rtl_iobase + RTL_8029_RSAR1);
00309     outb(CR_PAGE0 | CR_READ_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00310 
00311     ptr = (u8 *)&rx_desc;
00312     *(u32 *)ptr = inl(rtl_iobase + RTL_8029_DMADATA);
00313 
00314     frame_len = rx_desc.count - sizeof(rx_desc);
00315     frb->frb_len = frame_len;
00316 
00317 #if RTL_8029_DEBUG
00318     printk("frame_len = %d\n", frame_len);
00319 #endif
00320 
00321     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00322     outb(frame_len & 0xff, rtl_iobase + RTL_8029_RBCR0);        // lo
00323     outb(frame_len >> 8,   rtl_iobase + RTL_8029_RBCR1);        // hi
00324     outb(sizeof(rx_desc), rtl_iobase + RTL_8029_RSAR0);
00325     outb(boundary_page, rtl_iobase + RTL_8029_RSAR1);
00326     outb(CR_PAGE0 | CR_READ_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00327 
00328     ptr = frb->frb_data;
00329 
00330     for (i = 0; i < (frame_len >> 2); i++) {
00331         *(u32 *)ptr = inl(rtl_iobase + RTL_8029_DMADATA);
00332         ptr += 4;
00333     }
00334 
00335     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00336 
00337     next_page = rx_desc.next;
00338 
00339 #if RTL_8029_DEBUG
00340     printk("next_page = %02x\n\n", next_page);
00341 #endif
00342 
00343     outb(next_page - 1, rtl_iobase + RTL_8029_BNRY);
00344     
00345     return 0;
00346 }
00347 
00348 int rtl_8029_receive_frames(struct adi_netdev_s *netdev)
00349 {
00350     struct frb_s frame_buf;
00351     int max_frames;
00352 
00353     for (max_frames = 0; max_frames < 16; max_frames++) {
00354         frame_buf.frb_offset = 0;
00355         frame_buf.frb_data = (u8 *)get_free_pages(0);
00356     
00357         if (rtl_8029_receive_frame(&frame_buf) < 0) {
00358             put_free_pages((u32)frame_buf.frb_data, 0);
00359             break;
00360         }
00361             
00362         frame_buf.frb_dev = netdev;
00363         net_layer_2_recv_pack(&frame_buf);
00364 
00365         put_free_pages((u32)frame_buf.frb_data, 0);
00366     }
00367 
00368     return 0;
00369 }
00370 
00371 void rtl_8029_irq(u32 data)
00372 {
00373     int max_irq_services;
00374     u8 irq_status;
00375 
00376     spin_lock(&rtl_8029_netdev.if_lock);
00377 
00378     max_irq_services = 0;
00379     outb(CR_PAGE0 | CR_ABORT_DMA, rtl_iobase + RTL_8029_CR);
00380     while((max_irq_services++ < 16) && (irq_status = inb(rtl_iobase + RTL_8029_ISR))) {
00381 
00382         if (irq_status & ISR_PRX) {
00383 #if RTL_8029_DEBUG
00384             printk(MOD_NAME "PRX irq\n");
00385 #endif
00386             outb(ISR_PRX, rtl_iobase + RTL_8029_ISR);
00387             rtl_8029_receive_frames(&rtl_8029_netdev);
00388         } 
00389         
00390         if (irq_status & ISR_PTX) {
00391 #if RTL_8029_DEBUG
00392             printk(MOD_NAME "PTX irq\n");
00393 #endif
00394             outb(ISR_PTX, rtl_iobase + RTL_8029_ISR);
00395             rtl_8029_netdev_param.tx_busy[0] = 0;
00396         }
00397         
00398         if (irq_status & ISR_PTXE) {
00399 #if RTL_8029_DEBUG
00400             printk(MOD_NAME "PTXE irq\n");
00401 #endif
00402             outb(ISR_PTXE, rtl_iobase + RTL_8029_ISR);
00403         }
00404 
00405         if (irq_status & ISR_PRXE) {
00406 #if RTL_8029_DEBUG
00407             printk(MOD_NAME "PRXE irq\n");
00408 #endif
00409             outb(ISR_PRXE, rtl_iobase + RTL_8029_ISR);
00410         }
00411         
00412         if (irq_status & (ISR_OVW | ISR_CNT | ISR_RDC | ISR_RESET)) {
00413             outb(ISR_OVW | ISR_CNT | ISR_RDC | ISR_RESET, rtl_iobase + RTL_8029_ISR);
00414         }
00415     }
00416 
00417     outb(CR_PAGE0 | CR_ABORT_DMA, rtl_iobase + RTL_8029_CR);
00418     outb(0xff, rtl_iobase + RTL_8029_ISR);
00419     
00420     spin_unlock(&rtl_8029_netdev.if_lock);
00421 }
00422 
00423 int rtl_8029_open_driver(struct adi_netdev_s *netdev)
00424 {
00425     return 0;
00426 }
00427 
00428 int rtl_8029_close_driver(struct adi_netdev_s *netdev)
00429 {
00430     return 0;
00431 }
00432 
00433 struct irq_routine_s rtl_8029_irq_routine = {
00434     .proc       = rtl_8029_irq,
00435     .flags      = IRQ_FLAG_RANDOM,
00436 };
00437 
00438 struct adi_netdev_ops_s rtl_8029_netdev_ops = {
00439     .driver_open        = rtl_8029_open_driver,
00440     .driver_close       = rtl_8029_close_driver,
00441     .set_recv_mode      = rtl_8029_set_recv_mode, 
00442     .transmit_frame     = rtl_8029_send_frame
00443 };
00444 
00445 struct adi_netdev_s rtl_8029_netdev = {
00446     .if_ops             = &rtl_8029_netdev_ops,
00447 };
00448 
00449 int rtl_8029_probe(struct pcidev_s *pcidev, struct adi_driver_id_s *adi_driver_id)
00450 {
00451     int i;
00452 
00453     adi_netdev_init(&rtl_8029_netdev);
00454 
00455     pcibus_enable_device(pcidev);
00456 
00457     if (pcidev->dev_resources[0].res_flags & ADI_RES_FLAG_IO)
00458         rtl_iobase = pcidev->dev_resources[0].res_start;
00459     else {
00460         printk(MOD_NAME "device resource 0 is not IO\n");
00461         return -1;
00462     }
00463 
00464     rtl_8029_netdev_param.start_page = 0x40;
00465     rtl_8029_netdev_param.end_page   = 0x80;
00466     rtl_8029_netdev_param.tx_start_page = 0x40;
00467     rtl_8029_netdev_param.rx_start_page = 0x40 + RTL_8029_TX_PAGES;
00468     rtl_8029_netdev_param.tx_busy[0] = 0;
00469     rtl_8029_netdev_param.tx_busy[1] = 0;
00470 
00471     printk(MOD_NAME "dev_irq=%d ", pcidev->dev_irq);
00472     install_irq(pcidev->dev_irq, &rtl_8029_irq_routine);
00473     printk("iobase=%04x ", rtl_iobase);
00474 
00475     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STP, rtl_iobase + RTL_8029_CR);
00476     rtl_8029_reset(pcidev);
00477 
00478     outb(0x40 | 0x08 | 0x01, rtl_iobase + RTL_8029_DCR);        /* word-wide 4 Words */
00479     outb(0x00, rtl_iobase + RTL_8029_IMR);
00480     outb(0xff, rtl_iobase + RTL_8029_ISR);
00481 //      outb(0x20, rtl_iobase + RTL_8029_RCR);    
00482     outb(0x00, rtl_iobase + RTL_8029_RCR);    
00483     outb(0x00, rtl_iobase + RTL_8029_TCR);    
00484 //        outb(0x02, rtl_iobase + RTL_8029_TCR);    
00485     outb(0x20, rtl_iobase + RTL_8029_RBCR0);
00486     outb(0x00, rtl_iobase + RTL_8029_RBCR1);
00487     outb(0x00, rtl_iobase + RTL_8029_RSAR0);
00488     outb(0x00, rtl_iobase + RTL_8029_RSAR1);
00489     outb(CR_READ_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00490     
00491     for (i = 0; i < 32; i++) {
00492         rtl_eprom[i] = inb(rtl_iobase + RTL_8029_DMADATA);
00493     }
00494 
00495     outb(0x40 | 0x08 | 0x01, rtl_iobase + RTL_8029_DCR);
00496 
00497     outb(CR_PAGE1 | CR_ABORT_DMA | CR_STP, rtl_iobase + RTL_8029_CR);
00498     
00499     /* setting mac address in PAR */
00500     for (i = 0; i < 6; i++) {
00501         rtl_8029_netdev.if_layer_2.if_addr[i] = rtl_eprom[i];
00502         outb(rtl_eprom[i], rtl_iobase + 0x01 + i);
00503     }
00504     rtl_8029_netdev.if_layer_2.if_addr_len = NET_LAYER_2_ETH_MAC_LEN;
00505 
00506     outb(rtl_8029_netdev_param.rx_start_page, rtl_iobase + RTL_8029_CURR);
00507 
00508     printk("%s hwaddr=%02x:%02x:%02x:%02x:%02x:%02x\n", rtl_8029_netdev.if_name,
00509             rtl_eprom[0], rtl_eprom[1], rtl_eprom[2], rtl_eprom[3], rtl_eprom[4], rtl_eprom[5]);
00510 
00511     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STP, rtl_iobase + RTL_8029_CR);
00512     outb(0x40 | 0x08 | 0x01, rtl_iobase + RTL_8029_DCR);        /* word-wide 4 Words */
00513     outb(0x00, rtl_iobase + RTL_8029_RBCR0);
00514     outb(0x00, rtl_iobase + RTL_8029_RBCR1);
00515 //      outb(0x20, rtl_iobase + RTL_8029_RCR);    
00516     outb(0x00, rtl_iobase + RTL_8029_RCR);    
00517 //      outb(0x02, rtl_iobase + RTL_8029_TCR);   
00518     outb(0x00, rtl_iobase + RTL_8029_TCR);   
00519     outb(rtl_8029_netdev_param.tx_start_page, rtl_iobase + RTL_8029_TPSR); 
00520     outb(rtl_8029_netdev_param.rx_start_page, rtl_iobase + RTL_8029_PSTART);
00521     outb(rtl_8029_netdev_param.end_page, rtl_iobase + RTL_8029_PSTOP);
00522     outb(rtl_8029_netdev_param.end_page - 1, rtl_iobase + RTL_8029_BNRY);
00523     outb(0xff, rtl_iobase + RTL_8029_ISR);
00524     outb(0x00, rtl_iobase + RTL_8029_IMR);
00525 
00526     /*
00527      * enable packet receive irq, packet transmitted irq
00528      * receive error irq, transmit error irq, overwrite irq, counter overflow irq
00529      */   
00530     outb(IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE, rtl_iobase + RTL_8029_IMR);
00531     outb(0xff, rtl_iobase + RTL_8029_ISR);
00532 
00533     outb(CR_PAGE0 | CR_ABORT_DMA | CR_STA, rtl_iobase + RTL_8029_CR);
00534 
00535     /*
00536      * normal transmit mode
00537      */
00538     outb(0x00, rtl_iobase + RTL_8029_TCR);
00539     
00540     /*
00541      * accept broadcasts
00542      */
00543     rtl_8029_set_recv_mode(&rtl_8029_netdev, NET_RECV_MODE_BROADCAST);
00544 
00545     adi_register_netdev(&rtl_8029_netdev);
00546 
00547     return 0;
00548 }
00549 
00550 int rtl_8029_remove(struct pcidev_s *pcidev)
00551 {
00552     return 0;
00553 }
00554 
00555 struct adi_driver_pci_s rtl_8029_driver_pci = {
00556     .adi_driver_probe   = rtl_8029_probe,
00557     .adi_driver_remove  = rtl_8029_remove
00558 };
00559 
00560 struct adi_driver_s rtl_8029_driver = {
00561     .adi_driver_name    = "rtl_8029 network card",
00562     .adi_driver_type    = ADI_DRIVER_TYPE_PCI,
00563     .adi_driver_id      = rtl_8029_driver_id,
00564     .adi_driver_union.adi_driver_pci = &rtl_8029_driver_pci
00565 };
00566 
00567 int adi_netdrv_rtl_8029_init(void)
00568 {
00569     adi_register_driver(&rtl_8029_driver);
00570 
00571     return 0;
00572 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix