00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
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
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
00110
00111 #define RCR_BROADCAST 0x04
00112 #define RCR_MULTICAST 0x08
00113 #define RCR_PROMISC 0x10
00114
00115
00116
00117
00118
00119
00120 #define RTL_8029_CURR 0x07
00121
00122
00123
00124
00125
00126 #define RTL_8029_CURR 0x07
00127
00128
00129
00130
00131
00132
00133 #define RTL_8029_TX_PAGES 12
00134
00135
00136
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
00254
00255
00256
00257
00258
00259
00260
00261
00262 outb(ISR_RDC, rtl_iobase + RTL_8029_ISR);
00263
00264
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);
00306 outb(0x00, rtl_iobase + RTL_8029_RBCR1);
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);
00323 outb(frame_len >> 8, rtl_iobase + RTL_8029_RBCR1);
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);
00479 outb(0x00, rtl_iobase + RTL_8029_IMR);
00480 outb(0xff, rtl_iobase + RTL_8029_ISR);
00481
00482 outb(0x00, rtl_iobase + RTL_8029_RCR);
00483 outb(0x00, rtl_iobase + RTL_8029_TCR);
00484
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
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);
00513 outb(0x00, rtl_iobase + RTL_8029_RBCR0);
00514 outb(0x00, rtl_iobase + RTL_8029_RBCR1);
00515
00516 outb(0x00, rtl_iobase + RTL_8029_RCR);
00517
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
00528
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
00537
00538 outb(0x00, rtl_iobase + RTL_8029_TCR);
00539
00540
00541
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 }