00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "../drivers.h"
00050
00051 #include <stdlib.h>
00052 #include <stdio.h>
00053 #include <string.h>
00054 #include <stddef.h>
00055 #include <minix/com.h>
00056 #include <minix/keymap.h>
00057 #include <minix/syslib.h>
00058 #include <minix/type.h>
00059 #include <minix/sysutil.h>
00060 #include <timers.h>
00061 #include <ibm/portio.h>
00062 #include <net/hton.h>
00063 #include <net/gen/ether.h>
00064 #include <net/gen/eth_io.h>
00065 #include <ibm/pci.h>
00066
00067 #include <sys/types.h>
00068 #include <fcntl.h>
00069 #include <assert.h>
00070 #include <unistd.h>
00071 #include <sys/ioc_memory.h>
00072 #include "../../kernel/const.h"
00073 #include "../../kernel/config.h"
00074 #include "../../kernel/type.h"
00075
00076 #define tmra_ut timer_t
00077 #define tmra_inittimer(tp) tmr_inittimer(tp)
00078 #define Proc_number(p) proc_number(p)
00079 #define debug 0
00080 #define printW() ((void)0)
00081 #define vm_1phys2bus(p) (p)
00082
00083 #define VERBOSE 1
00084
00085 #include "rtl8139.h"
00086
00087 #define RX_BUFSIZE RL_RCR_RBLEN_64K_SIZE
00088 #define RX_BUFBITS RL_RCR_RBLEN_64K
00089 #define N_TX_BUF RL_N_TX
00090
00091 #define RE_PORT_NR 1
00092
00093
00094 #define IOVEC_NR 16
00095
00096
00097 #define RL_ENVVAR "RTLETH"
00098
00099 PRIVATE struct pcitab
00100 {
00101 u16_t vid;
00102 u16_t did;
00103 int checkclass;
00104 } pcitab[]=
00105 {
00106 { 0x10ec, 0x8139, 0 },
00107 { 0x1186, 0x1300, 0 },
00108
00109 { 0x0000, 0x0000, 0 }
00110 };
00111
00112 typedef struct re
00113 {
00114 port_t re_base_port;
00115 int re_irq;
00116 int re_mode;
00117 int re_flags;
00118 int re_client;
00119 int re_link_up;
00120 int re_got_int;
00121 int re_send_int;
00122 int re_report_link;
00123 int re_clear_rx;
00124 int re_need_reset;
00125 int re_tx_alive;
00126 char *re_model;
00127
00128
00129 phys_bytes re_rx_buf;
00130 char *v_re_rx_buf;
00131 vir_bytes re_read_s;
00132
00133
00134 int re_tx_head;
00135 int re_tx_tail;
00136 struct
00137 {
00138 int ret_busy;
00139 phys_bytes ret_buf;
00140 char * v_ret_buf;
00141 } re_tx[N_TX_BUF];
00142 u32_t re_ertxth;
00143
00144
00145 int re_seen;
00146 u8_t re_pcibus;
00147 u8_t re_pcidev;
00148 u8_t re_pcifunc;
00149
00150
00151 int re_hook_id;
00152 eth_stat_t re_stat;
00153 ether_addr_t re_address;
00154 message re_rx_mess;
00155 message re_tx_mess;
00156 char re_name[sizeof("rtl8139#n")];
00157 iovec_t re_iovec[IOVEC_NR];
00158 }
00159 re_t;
00160
00161 #define REM_DISABLED 0x0
00162 #define REM_ENABLED 0x1
00163
00164 #define REF_PACK_SENT 0x001
00165 #define REF_PACK_RECV 0x002
00166 #define REF_SEND_AVAIL 0x004
00167 #define REF_READING 0x010
00168 #define REF_EMPTY 0x000
00169 #define REF_PROMISC 0x040
00170 #define REF_MULTI 0x080
00171 #define REF_BROAD 0x100
00172 #define REF_ENABLED 0x200
00173
00174 static re_t re_table[RE_PORT_NR];
00175
00176 static u16_t eth_ign_proto;
00177 static tmra_ut rl_watchdog;
00178
00179 FORWARD _PROTOTYPE( unsigned my_inb, (U16_t port) );
00180 FORWARD _PROTOTYPE( unsigned my_inw, (U16_t port) );
00181 FORWARD _PROTOTYPE( unsigned my_inl, (U16_t port) );
00182 static unsigned my_inb(U16_t port) {
00183 u32_t value;
00184 int s;
00185 if ((s=sys_inb(port, &value)) !=OK)
00186 printf("RTL8139: warning, sys_inb failed: %d\n", s);
00187 return value;
00188 }
00189 static unsigned my_inw(U16_t port) {
00190 u32_t value;
00191 int s;
00192 if ((s=sys_inw(port, &value)) !=OK)
00193 printf("RTL8139: warning, sys_inw failed: %d\n", s);
00194 return value;
00195 }
00196 static unsigned my_inl(U16_t port) {
00197 U32_t value;
00198 int s;
00199 if ((s=sys_inl(port, &value)) !=OK)
00200 printf("RTL8139: warning, sys_inl failed: %d\n", s);
00201 return value;
00202 }
00203 #define rl_inb(port, offset) (my_inb((port) + (offset)))
00204 #define rl_inw(port, offset) (my_inw((port) + (offset)))
00205 #define rl_inl(port, offset) (my_inl((port) + (offset)))
00206
00207 FORWARD _PROTOTYPE( void my_outb, (U16_t port, U8_t value) );
00208 FORWARD _PROTOTYPE( void my_outw, (U16_t port, U16_t value) );
00209 FORWARD _PROTOTYPE( void my_outl, (U16_t port, U32_t value) );
00210 static void my_outb(U16_t port, U8_t value) {
00211 int s;
00212 if ((s=sys_outb(port, value)) !=OK)
00213 printf("RTL8139: warning, sys_outb failed: %d\n", s);
00214 }
00215 static void my_outw(U16_t port, U16_t value) {
00216 int s;
00217 if ((s=sys_outw(port, value)) !=OK)
00218 printf("RTL8139: warning, sys_outw failed: %d\n", s);
00219 }
00220 static void my_outl(U16_t port, U32_t value) {
00221 int s;
00222 if ((s=sys_outl(port, value)) !=OK)
00223 printf("RTL8139: warning, sys_outl failed: %d\n", s);
00224 }
00225 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
00226 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
00227 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
00228
00229 _PROTOTYPE( static void sig_handler, (void) );
00230 _PROTOTYPE( static void rl_init, (message *mp) );
00231 _PROTOTYPE( static void rl_pci_conf, (void) );
00232 _PROTOTYPE( static int rl_probe, (re_t *rep) );
00233 _PROTOTYPE( static void rl_conf_hw, (re_t *rep) );
00234 _PROTOTYPE( static void rl_init_buf, (re_t *rep) );
00235 _PROTOTYPE( static void rl_init_hw, (re_t *rep) );
00236 _PROTOTYPE( static void rl_reset_hw, (re_t *rep) );
00237 _PROTOTYPE( static void rl_confaddr, (re_t *rep) );
00238 _PROTOTYPE( static void rl_rec_mode, (re_t *rep) );
00239 _PROTOTYPE( static void rl_readv, (message *mp, int from_int,
00240 int vectored) );
00241 _PROTOTYPE( static void rl_writev, (message *mp, int from_int,
00242 int vectored) );
00243 _PROTOTYPE( static void rl_check_ints, (re_t *rep) );
00244 _PROTOTYPE( static void rl_report_link, (re_t *rep) );
00245 _PROTOTYPE( static void mii_print_techab, (U16_t techab) );
00246 _PROTOTYPE( static void mii_print_stat_speed, (U16_t stat,
00247 U16_t extstat) );
00248 _PROTOTYPE( static void rl_clear_rx, (re_t *rep) );
00249 _PROTOTYPE( static void rl_do_reset, (re_t *rep) );
00250 _PROTOTYPE( static void rl_getstat, (message *mp) );
00251 _PROTOTYPE( static void rl_getname, (message *mp) );
00252 _PROTOTYPE( static void reply, (re_t *rep, int err, int may_block) );
00253 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
00254 _PROTOTYPE( static void put_userdata, (int user_proc,
00255 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
00256 _PROTOTYPE( static void rtl8139_stop, (void) );
00257 _PROTOTYPE( static void check_int_events, (void) );
00258 _PROTOTYPE( static int do_hard_int, (void) );
00259 _PROTOTYPE( static void rtl8139_dump, (message *m) );
00260 #if 0
00261 _PROTOTYPE( static void dump_phy, (re_t *rep) );
00262 #endif
00263 _PROTOTYPE( static int rl_handler, (re_t *rep) );
00264 _PROTOTYPE( static void rl_watchdog_f, (timer_t *tp) );
00265
00266
00267
00268
00269 PRIVATE message m;
00270 PRIVATE int int_event_check;
00271
00272 static char *progname;
00273 extern int errno;
00274
00275
00276
00277
00278 int main(int argc, char *argv[])
00279 {
00280 int fkeys, sfkeys;
00281 int inet_proc_nr;
00282 int i, r;
00283 re_t *rep;
00284 long v;
00285
00286 env_setargs(argc, argv);
00287
00288 v= 0;
00289 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
00290 eth_ign_proto= htons((u16_t) v);
00291
00292
00293 fkeys = sfkeys = 0; bit_set(sfkeys, 9);
00294 if ((r=fkey_map(&fkeys, &sfkeys)) != OK)
00295 printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r);
00296
00297
00298 for (rep= &re_table[0]; rep < re_table+RE_PORT_NR; rep++)
00299 rl_init_buf(rep);
00300
00301
00302
00303
00304
00305 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
00306 r = _pm_findproc("inet", &inet_proc_nr);
00307 if (r == OK) notify(inet_proc_nr);
00308
00309
00310 while (TRUE)
00311 {
00312 if ((r= receive(ANY, &m)) != OK)
00313 panic("rtl8139","receive failed", r);
00314
00315 switch (m.m_type)
00316 {
00317 case DEV_PING: notify(m.m_source); continue;
00318 case DL_WRITEV: rl_writev(&m, FALSE, TRUE); break;
00319 case DL_WRITE: rl_writev(&m, FALSE, FALSE); break;
00320 #if 0
00321 case DL_READ: do_vread(&m, FALSE); break;
00322 #endif
00323 case DL_READV: rl_readv(&m, FALSE, TRUE); break;
00324 case DL_INIT: rl_init(&m); break;
00325 case DL_GETSTAT: rl_getstat(&m); break;
00326 case DL_GETNAME: rl_getname(&m); break;
00327 #if 0
00328 case DL_STOP: do_stop(&m); break;
00329 #endif
00330 case SYN_ALARM:
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 rl_watchdog_f(NULL);
00341 break;
00342 case HARD_INT:
00343 do_hard_int();
00344 if (int_event_check)
00345 check_int_events();
00346 break ;
00347 case FKEY_PRESSED: rtl8139_dump(&m); break;
00348 case PROC_EVENT:
00349 sig_handler();
00350 break;
00351 default:
00352 panic("rtl8139","illegal message", m.m_type);
00353 }
00354 }
00355 }
00356
00357
00358
00359
00360 PRIVATE void sig_handler()
00361 {
00362 sigset_t sigset;
00363 int sig;
00364
00365
00366 if (getsigset(&sigset) != 0) return;
00367
00368
00369 if (sigismember(&sigset, SIGTERM)) {
00370 rtl8139_stop();
00371 }
00372 }
00373
00374
00375
00376
00377 static void check_int_events(void)
00378 {
00379 int i;
00380 re_t *rep;
00381 for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
00382 {
00383 if (rep->re_mode != REM_ENABLED)
00384 continue;
00385 if (!rep->re_got_int)
00386 continue;
00387 rep->re_got_int= 0;
00388 assert(rep->re_flags & REF_ENABLED);
00389 rl_check_ints(rep);
00390 }
00391 }
00392
00393
00394
00395
00396 static void rtl8139_stop()
00397 {
00398 int i;
00399 re_t *rep;
00400
00401 for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
00402 {
00403 if (rep->re_mode != REM_ENABLED)
00404 continue;
00405 rl_outb(rep->re_base_port, RL_CR, 0);
00406 }
00407 sys_exit(0);
00408 }
00409
00410
00411
00412
00413 static void rtl8139_dump(m)
00414 message *m;
00415 {
00416 re_t *rep;
00417 int i;
00418
00419 printf("\n");
00420 for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)
00421 {
00422 if (rep->re_mode == REM_DISABLED)
00423 printf("Realtek RTL 8139 port %d is disabled\n", i);
00424
00425 if (rep->re_mode != REM_ENABLED)
00426 continue;
00427
00428 printf("Realtek RTL 8139 statistics of port %d:\n", i);
00429
00430 printf("recvErr :%8ld\t", rep->re_stat.ets_recvErr);
00431 printf("sendErr :%8ld\t", rep->re_stat.ets_sendErr);
00432 printf("OVW :%8ld\n", rep->re_stat.ets_OVW);
00433
00434 printf("CRCerr :%8ld\t", rep->re_stat.ets_CRCerr);
00435 printf("frameAll :%8ld\t", rep->re_stat.ets_frameAll);
00436 printf("missedP :%8ld\n", rep->re_stat.ets_missedP);
00437
00438 printf("packetR :%8ld\t", rep->re_stat.ets_packetR);
00439 printf("packetT :%8ld\t", rep->re_stat.ets_packetT);
00440 printf("transDef :%8ld\n", rep->re_stat.ets_transDef);
00441
00442 printf("collision :%8ld\t", rep->re_stat.ets_collision);
00443 printf("transAb :%8ld\t", rep->re_stat.ets_transAb);
00444 printf("carrSense :%8ld\n", rep->re_stat.ets_carrSense);
00445
00446 printf("fifoUnder :%8ld\t", rep->re_stat.ets_fifoUnder);
00447 printf("fifoOver :%8ld\t", rep->re_stat.ets_fifoOver);
00448 printf("CDheartbeat:%8ld\n", rep->re_stat.ets_CDheartbeat);
00449
00450 printf("OWC :%8ld\t", rep->re_stat.ets_OWC);
00451
00452 printf("re_flags = 0x%x\n", rep->re_flags);
00453
00454 printf(
00455 "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
00456 rl_inw(rep->re_base_port, RL_TSAD),
00457 rl_inl(rep->re_base_port, RL_TSD0+0*4),
00458 rl_inl(rep->re_base_port, RL_TSD0+1*4),
00459 rl_inl(rep->re_base_port, RL_TSD0+2*4),
00460 rl_inl(rep->re_base_port, RL_TSD0+3*4));
00461 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
00462 rep->re_tx_head, rep->re_tx_tail,
00463 rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
00464 rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
00465 }
00466 }
00467
00468
00469
00470
00471 static void rl_init(mp)
00472 message *mp;
00473 {
00474 static int first_time= 1;
00475
00476 int port;
00477 re_t *rep;
00478 message reply_mess;
00479
00480 if (first_time)
00481 {
00482 first_time= 0;
00483 rl_pci_conf();
00484
00485 tmra_inittimer(&rl_watchdog);
00486
00487 sys_setalarm(HZ, 0);
00488 }
00489
00490 port = mp->DL_PORT;
00491 if (port < 0 || port >= RE_PORT_NR)
00492 {
00493 reply_mess.m_type= DL_INIT_REPLY;
00494 reply_mess.m3_i1= ENXIO;
00495 mess_reply(mp, &reply_mess);
00496 return;
00497 }
00498 rep= &re_table[port];
00499 if (rep->re_mode == REM_DISABLED)
00500 {
00501
00502 rl_conf_hw(rep);
00503 if (rep->re_mode == REM_DISABLED)
00504 {
00505
00506 reply_mess.m_type= DL_INIT_REPLY;
00507 reply_mess.m3_i1= ENXIO;
00508 mess_reply(mp, &reply_mess);
00509 return;
00510 }
00511 if (rep->re_mode == REM_ENABLED)
00512 rl_init_hw(rep);
00513 #if VERBOSE
00514 rl_report_link(rep);
00515 #endif
00516 }
00517
00518 assert(rep->re_mode == REM_ENABLED);
00519 assert(rep->re_flags & REF_ENABLED);
00520
00521 rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);
00522
00523 if (mp->DL_MODE & DL_PROMISC_REQ)
00524 rep->re_flags |= REF_PROMISC;
00525 if (mp->DL_MODE & DL_MULTI_REQ)
00526 rep->re_flags |= REF_MULTI;
00527 if (mp->DL_MODE & DL_BROAD_REQ)
00528 rep->re_flags |= REF_BROAD;
00529
00530 rep->re_client = mp->m_source;
00531 rl_rec_mode(rep);
00532
00533 reply_mess.m_type = DL_INIT_REPLY;
00534 reply_mess.m3_i1 = mp->DL_PORT;
00535 reply_mess.m3_i2 = RE_PORT_NR;
00536 *(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;
00537
00538 mess_reply(mp, &reply_mess);
00539 }
00540
00541
00542
00543
00544 static void rl_pci_conf()
00545 {
00546 int i, h;
00547 re_t *rep;
00548 static char envvar[] = RL_ENVVAR "#";
00549 static char envfmt[] = "*:d.d.d";
00550 static char val[128];
00551 long v;
00552
00553 for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)
00554 {
00555 strcpy(rep->re_name, "rtl8139#0");
00556 rep->re_name[8] += i;
00557 rep->re_seen= FALSE;
00558 envvar[sizeof(RL_ENVVAR)-1]= '0'+i;
00559 if (0 == env_get_param(envvar, val, sizeof(val)) &&
00560 ! env_prefix(envvar, "pci")) {
00561 env_panic(envvar);
00562 }
00563 v= 0;
00564 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
00565 rep->re_pcibus= v;
00566 v= 0;
00567 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
00568 rep->re_pcidev= v;
00569 v= 0;
00570 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
00571 rep->re_pcifunc= v;
00572 }
00573
00574 pci_init();
00575
00576 for (h= 1; h >= 0; h--) {
00577 for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)
00578 {
00579 if (((rep->re_pcibus | rep->re_pcidev |
00580 rep->re_pcifunc) != 0) != h)
00581 {
00582 continue;
00583 }
00584 if (rl_probe(rep))
00585 rep->re_seen= TRUE;
00586 }
00587 }
00588 }
00589
00590
00591
00592
00593 static int rl_probe(rep)
00594 re_t *rep;
00595 {
00596 int i, r, devind, just_one;
00597 u16_t vid, did;
00598 u32_t bar;
00599 u8_t ilr;
00600 char *dname;
00601
00602 if ((rep->re_pcibus | rep->re_pcidev | rep->re_pcifunc) != 0)
00603 {
00604
00605 r= pci_find_dev(rep->re_pcibus, rep->re_pcidev,
00606 rep->re_pcifunc, &devind);
00607 if (r == 0)
00608 {
00609 printf("%s: no PCI found at %d.%d.%d\n",
00610 rep->re_name, rep->re_pcibus,
00611 rep->re_pcidev, rep->re_pcifunc);
00612 return 0;
00613 }
00614 pci_ids(devind, &vid, &did);
00615 just_one= TRUE;
00616 }
00617 else
00618 {
00619 r= pci_first_dev(&devind, &vid, &did);
00620 if (r == 0)
00621 return 0;
00622 just_one= FALSE;
00623 }
00624
00625 for(;;)
00626 {
00627 for (i= 0; pcitab[i].vid != 0; i++)
00628 {
00629 if (pcitab[i].vid != vid)
00630 continue;
00631 if (pcitab[i].did != did)
00632 continue;
00633 if (pcitab[i].checkclass)
00634 {
00635 panic("rtl_probe",
00636 "class check not implemented", NO_NUM);
00637 }
00638 break;
00639 }
00640 if (pcitab[i].vid != 0)
00641 break;
00642
00643 if (just_one)
00644 {
00645 printf(
00646 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
00647 rep->re_name, vid, did,
00648 rep->re_pcibus,
00649 rep->re_pcidev, rep->re_pcifunc);
00650 return 0;
00651 }
00652
00653 r= pci_next_dev(&devind, &vid, &did);
00654 if (!r)
00655 return 0;
00656 }
00657
00658 #if VERBOSE
00659 dname= pci_dev_name(vid, did);
00660 if (!dname)
00661 dname= "unknown device";
00662 printf("%s: ", rep->re_name);
00663 printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
00664 #endif
00665 pci_reserve(devind);
00666
00667 bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
00668 if (bar < 0x400)
00669 {
00670 panic("rtl_probe",
00671 "base address is not properly configured", NO_NUM);
00672 }
00673 rep->re_base_port= bar;
00674
00675 ilr= pci_attr_r8(devind, PCI_ILR);
00676 rep->re_irq= ilr;
00677 if (debug)
00678 {
00679 printf("%s: using I/O address 0x%lx, IRQ %d\n",
00680 rep->re_name, (unsigned long)bar, ilr);
00681 }
00682
00683 return TRUE;
00684 }
00685
00686
00687
00688
00689 static void rl_conf_hw(rep)
00690 re_t *rep;
00691 {
00692 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 };
00693
00694 rep->re_mode= REM_DISABLED;
00695
00696 if (rep->re_seen)
00697 {
00698
00699 rep->re_mode= REM_ENABLED;
00700 }
00701 if (rep->re_mode != REM_ENABLED)
00702 return;
00703
00704 rep->re_flags= REF_EMPTY;
00705 rep->re_link_up= -1;
00706 rep->re_got_int= 0;
00707 rep->re_send_int= 0;
00708 rep->re_report_link= 0;
00709 rep->re_clear_rx= 0;
00710 rep->re_need_reset= 0;
00711 rep->re_tx_alive= 0;
00712 rep->re_read_s= 0;
00713 rep->re_tx_head= 0;
00714 rep->re_tx_tail= 0;
00715 rep->re_ertxth= RL_TSD_ERTXTH_8;
00716 rep->re_stat= empty_stat;
00717 }
00718
00719
00720
00721
00722 static void rl_init_buf(rep)
00723 re_t *rep;
00724 {
00725 size_t rx_bufsize, tx_bufsize, tot_bufsize;
00726 phys_bytes buf;
00727 char *mallocbuf;
00728 static struct memory chunk;
00729 int fd, s, i, off;
00730
00731
00732 tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;
00733 if (tx_bufsize % 4)
00734 tx_bufsize += 4-(tx_bufsize % 4);
00735 rx_bufsize= RX_BUFSIZE;
00736 tot_bufsize= N_TX_BUF*tx_bufsize + rx_bufsize;
00737
00738
00739 chunk.size = tot_bufsize;
00740
00741 #define BUF_ALIGNMENT (64*1024)
00742
00743 if(!(mallocbuf = malloc(BUF_ALIGNMENT + tot_bufsize))) {
00744 panic("RTL8139","Couldn't allocate kernel buffer",i);
00745 }
00746
00747 if(OK != (i = sys_umap(SELF, D, (vir_bytes) mallocbuf, tot_bufsize, &buf))) {
00748 panic("RTL8139","Couldn't re-map malloced buffer",i);
00749 }
00750
00751
00752
00753
00754 if((off = buf % BUF_ALIGNMENT)) {
00755 mallocbuf += BUF_ALIGNMENT - off;
00756 buf += BUF_ALIGNMENT - off;
00757 }
00758
00759 for (i= 0; i<N_TX_BUF; i++)
00760 {
00761 rep->re_tx[i].ret_buf= buf;
00762 rep->re_tx[i].v_ret_buf= mallocbuf;
00763 buf += tx_bufsize;
00764 mallocbuf += tx_bufsize;
00765 }
00766 rep->re_rx_buf= buf;
00767 rep->v_re_rx_buf= mallocbuf;
00768 }
00769
00770
00771
00772
00773 static void rl_init_hw(rep)
00774 re_t *rep;
00775 {
00776 int s, i;
00777
00778 rep->re_flags = REF_EMPTY;
00779 rep->re_flags |= REF_ENABLED;
00780
00781
00782
00783
00784
00785 rep->re_hook_id = rep->re_irq;
00786 if ((s=sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
00787 printf("RTL8139: error, couldn't set IRQ policy: %d\n", s);
00788
00789 rl_reset_hw(rep);
00790
00791 if ((s=sys_irqenable(&rep->re_hook_id)) != OK)
00792 printf("RTL8139: error, couldn't enable interrupts: %d\n", s);
00793
00794 #if VERBOSE
00795 if (rep->re_model) {
00796 printf("%s: model %s\n", rep->re_name, rep->re_model);
00797 } else
00798 {
00799 printf("%s: unknown model 0x%08x\n",
00800 rep->re_name,
00801 rl_inl(rep->re_base_port, RL_TCR) &
00802 (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
00803 }
00804 #endif
00805
00806 rl_confaddr(rep);
00807 if (debug)
00808 {
00809 printf("%s: Ethernet address ", rep->re_name);
00810 for (i= 0; i < 6; i++)
00811 {
00812 printf("%x%c", rep->re_address.ea_addr[i],
00813 i < 5 ? ':' : '\n');
00814 }
00815 }
00816 }
00817
00818
00819
00820
00821 static void rl_reset_hw(rep)
00822 re_t *rep;
00823 {
00824 port_t port;
00825 u32_t t;
00826 phys_bytes bus_buf;
00827 int i;
00828 clock_t t0,t1;
00829
00830 port= rep->re_base_port;
00831
00832 #if 0
00833
00834 rl_outb(port, RL_BMCR, MII_CTRL_RST);
00835 getuptime(&t0);
00836 do {
00837 if (!(rl_inb(port, RL_BMCR) & MII_CTRL_RST))
00838 break;
00839 } while (getuptime(&t1)==OK && (t1-t0) < HZ);
00840 if (rl_inb(port, RL_BMCR) & MII_CTRL_RST)
00841 panic("rtl8139","reset PHY failed to complete", NO_NUM);
00842 #endif
00843
00844
00845 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
00846 port, rl_inb(port, RL_CR));
00847 rl_outb(port, RL_CR, RL_CR_RST);
00848 getuptime(&t0);
00849 do {
00850 if (!(rl_inb(port, RL_CR) & RL_CR_RST))
00851 break;
00852 } while (getuptime(&t1)==OK && (t1-t0) < HZ);
00853 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
00854 port, rl_inb(port, RL_CR));
00855 if (rl_inb(port, RL_CR) & RL_CR_RST)
00856 printf("rtl8139: reset failed to complete");
00857
00858 t= rl_inl(port, RL_TCR);
00859 switch(t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM))
00860 {
00861 case RL_TCR_HWVER_RTL8139: rep->re_model= "RTL8139"; break;
00862 case RL_TCR_HWVER_RTL8139A: rep->re_model= "RTL8139A"; break;
00863 case RL_TCR_HWVER_RTL8139AG:
00864 rep->re_model= "RTL8139A-G / RTL8139C";
00865 break;
00866 case RL_TCR_HWVER_RTL8139B:
00867 rep->re_model= "RTL8139B / RTL8130";
00868 break;
00869 case RL_TCR_HWVER_RTL8100: rep->re_model= "RTL8100"; break;
00870 case RL_TCR_HWVER_RTL8100B:
00871 rep->re_model= "RTL8100B/RTL8139D";
00872 break;
00873 case RL_TCR_HWVER_RTL8139CP: rep->re_model= "RTL8139C+"; break;
00874 case RL_TCR_HWVER_RTL8101: rep->re_model= "RTL8101"; break;
00875 default:
00876 rep->re_model= NULL;
00877 break;
00878 }
00879
00880 #if 0
00881 printf("REVID: 0x%02x\n", rl_inb(port, RL_REVID));
00882 #endif
00883
00884
00885
00886
00887 #if 0
00888 08-0f R/W MAR[0-7] multicast
00889 #endif
00890 bus_buf= vm_1phys2bus(rep->re_rx_buf);
00891 rl_outl(port, RL_RBSTART, bus_buf);
00892
00893
00894 for (i= 0; i<N_TX_BUF; i++)
00895 {
00896 rep->re_tx[i].ret_busy= FALSE;
00897 bus_buf= vm_1phys2bus(rep->re_tx[i].ret_buf);
00898 rl_outl(port, RL_TSAD0+i*4, bus_buf);
00899 t= rl_inl(port, RL_TSD0+i*4);
00900 assert(t & RL_TSD_OWN);
00901 }
00902
00903 #if 0
00904 dump_phy(rep);
00905 #endif
00906
00907 t= rl_inw(port, RL_IMR);
00908 rl_outw(port, RL_IMR, t | (RL_IMR_SERR | RL_IMR_TIMEOUT |
00909 RL_IMR_LENCHG));
00910
00911 t= rl_inw(port, RL_IMR);
00912 rl_outw(port, RL_IMR, t | (RL_IMR_FOVW | RL_IMR_PUN |
00913 RL_IMR_RXOVW | RL_IMR_RER | RL_IMR_ROK));
00914
00915 t= rl_inw(port, RL_IMR);
00916 rl_outw(port, RL_IMR, t | (RL_IMR_TER | RL_IMR_TOK));
00917
00918 t= rl_inb(port, RL_CR);
00919 rl_outb(port, RL_CR, t | RL_CR_RE);
00920
00921 t= rl_inb(port, RL_CR);
00922 rl_outb(port, RL_CR, t | RL_CR_TE);
00923
00924 rl_outl(port, RL_RCR, RX_BUFBITS);
00925
00926 t= rl_inl(port, RL_TCR);
00927 rl_outl(port, RL_TCR, t | RL_TCR_IFG_STD);
00928 }
00929
00930
00931
00932
00933 static void rl_confaddr(rep)
00934 re_t *rep;
00935 {
00936 static char eakey[]= RL_ENVVAR "#_EA";
00937 static char eafmt[]= "x:x:x:x:x:x";
00938
00939 int i;
00940 port_t port;
00941 u32_t w;
00942 long v;
00943
00944
00945 eakey[sizeof(RL_ENVVAR)-1]= '0' + (rep-re_table);
00946
00947 port= rep->re_base_port;
00948
00949 for (i= 0; i < 6; i++)
00950 {
00951 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
00952 break;
00953 rep->re_address.ea_addr[i]= v;
00954 }
00955
00956 if (i != 0 && i != 6) env_panic(eakey);
00957
00958
00959 if (i == 6)
00960 {
00961 port= rep->re_base_port;
00962 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
00963 w= 0;
00964 for (i= 0; i<4; i++)
00965 w |= (rep->re_address.ea_addr[i] << (i*8));
00966 rl_outl(port, RL_IDR, w);
00967 w= 0;
00968 for (i= 4; i<6; i++)
00969 w |= (rep->re_address.ea_addr[i] << ((i-4)*8));
00970 rl_outl(port, RL_IDR+4, w);
00971 rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
00972 }
00973
00974
00975 for (i= 0; i<6; i++)
00976 rep->re_address.ea_addr[i]= rl_inb(port, RL_IDR+i);
00977 }
00978
00979
00980
00981
00982 static void rl_rec_mode(rep)
00983 re_t *rep;
00984 {
00985 port_t port;
00986 u32_t rcr;
00987
00988 port= rep->re_base_port;
00989 rcr= rl_inl(port, RL_RCR);
00990 rcr &= ~(RL_RCR_AB|RL_RCR_AM|RL_RCR_APM|RL_RCR_AAP);
00991 if (rep->re_flags & REF_PROMISC)
00992 rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
00993 if (rep->re_flags & REF_BROAD)
00994 rcr |= RL_RCR_AB;
00995 if (rep->re_flags & REF_MULTI)
00996 rcr |= RL_RCR_AM;
00997 rcr |= RL_RCR_APM;
00998
00999 rl_outl(port, RL_RCR, rcr);
01000 }
01001
01002
01003
01004
01005 static void rl_readv(mp, from_int, vectored)
01006 message *mp;
01007 int from_int;
01008 int vectored;
01009 {
01010 int i, j, n, o, s, s1, dl_port, re_client, count, size;
01011 port_t port;
01012 unsigned amount, totlen, packlen;
01013 phys_bytes src_phys, dst_phys, iov_src;
01014 u16_t d_start, d_end;
01015 u32_t l, rxstat = 0x12345678;
01016 re_t *rep;
01017 iovec_t *iovp;
01018 int cps;
01019
01020 dl_port = mp->DL_PORT;
01021 count = mp->DL_COUNT;
01022 if (dl_port < 0 || dl_port >= RE_PORT_NR)
01023 panic("rtl8139"," illegal port", dl_port);
01024 rep= &re_table[dl_port];
01025 re_client= mp->DL_PROC;
01026 rep->re_client= re_client;
01027
01028 if (rep->re_clear_rx)
01029 goto suspend;
01030
01031 assert(rep->re_mode == REM_ENABLED);
01032 assert(rep->re_flags & REF_ENABLED);
01033
01034 port= rep->re_base_port;
01035
01036
01037
01038 if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
01039 {
01040
01041 goto suspend;
01042 }
01043
01044 d_start= rl_inw(port, RL_CAPR) + RL_CAPR_DATA_OFF;
01045 d_end= rl_inw(port, RL_CBR) % RX_BUFSIZE;
01046
01047 if (d_start >= RX_BUFSIZE)
01048 {
01049 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
01050 rl_inw(port, RL_CAPR));
01051 d_start %= RX_BUFSIZE;
01052 }
01053
01054 if (d_end > d_start)
01055 amount= d_end-d_start;
01056 else
01057 amount= d_end+RX_BUFSIZE - d_start;
01058
01059 rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start);
01060
01061 #if DEAD_CODE
01062 src_phys= rep->re_rx_buf + d_start;
01063 cps = sys_physcopy(
01064 NONE, PHYS_SEG, src_phys,
01065 SELF, D, (vir_bytes) &rxstat, sizeof(rxstat));
01066 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01067 #endif
01068
01069 if (rep->re_clear_rx)
01070 {
01071 #if 0
01072 printf("rl_readv: late buffer overflow\n");
01073 #endif
01074 goto suspend;
01075 }
01076
01077
01078
01079 if (!(rxstat & RL_RXS_ROK))
01080 {
01081 printf("rxstat = 0x%08lx\n", rxstat);
01082 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
01083 d_start, d_end, rxstat);
01084 panic("rtl8139","received packet not OK", NO_NUM);
01085 }
01086 totlen= (rxstat >> RL_RXS_LEN_S);
01087 if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE)
01088 {
01089
01090 printf(
01091 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
01092 totlen, rxstat, d_start);
01093 printf(
01094 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
01095 d_start, d_end, totlen, rxstat);
01096 panic(NULL, NULL, NO_NUM);
01097 }
01098
01099 #if 0
01100 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
01101 d_start, d_end, totlen, rxstat);
01102 #endif
01103
01104 if (totlen+4 > amount)
01105 {
01106 printf("rl_readv: packet not yet ready\n");
01107 goto suspend;
01108 }
01109
01110
01111 packlen= totlen - ETH_CRC_SIZE;
01112
01113 if (vectored)
01114 {
01115 int iov_offset = 0;
01116 #if 0
01117 if ((cps = sys_umap(re_client, D, (vir_bytes) mp->DL_ADDR,
01118 count * sizeof(rep->re_iovec[0]), &iov_src)) != OK)
01119 printf("sys_umap failed: %d\n", cps);
01120 #endif
01121
01122 size= 0;
01123 o= d_start+4;
01124 src_phys= rep->re_rx_buf;
01125 for (i= 0; i<count; i += IOVEC_NR,
01126 iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
01127 iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
01128 {
01129 n= IOVEC_NR;
01130 if (i+n > count)
01131 n= count-i;
01132 #if 0
01133 cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec,
01134 n * sizeof(rep->re_iovec[0]));
01135 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01136 #else
01137 cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset,
01138 SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0]));
01139 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
01140 #endif
01141
01142 for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
01143 {
01144 s= iovp->iov_size;
01145 if (size + s > packlen)
01146 {
01147 assert(packlen > size);
01148 s= packlen-size;
01149 }
01150
01151 #if 0
01152 if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK)
01153 panic("rtl8139","umap_local failed\n", NO_NUM);
01154 #endif
01155
01156 if (o >= RX_BUFSIZE)
01157 {
01158 o -= RX_BUFSIZE;
01159 assert(o < RX_BUFSIZE);
01160 }
01161
01162 if (o+s > RX_BUFSIZE)
01163 {
01164 assert(o<RX_BUFSIZE);
01165 s1= RX_BUFSIZE-o;
01166
01167 #if 0
01168 cps = sys_abscopy(src_phys+o, dst_phys, s1);
01169 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01170 cps = sys_abscopy(src_phys, dst_phys+s1, s-s1);
01171 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01172 #else
01173 cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
01174 re_client, D, iovp->iov_addr, s1);
01175 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
01176 cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf,
01177 re_client, D, iovp->iov_addr+s1, s-s1);
01178 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
01179 #endif
01180 }
01181 else
01182 {
01183 #if 0
01184 cps = sys_abscopy(src_phys+o, dst_phys, s);
01185 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01186 #else
01187 cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
01188 re_client, D, iovp->iov_addr, s);
01189 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
01190 #endif
01191 }
01192
01193 size += s;
01194 if (size == packlen)
01195 break;
01196 o += s;
01197 }
01198 if (size == packlen)
01199 break;
01200 }
01201 if (size < packlen)
01202 {
01203 assert(0);
01204 }
01205 }
01206 else
01207 {
01208 assert(0);
01209 #if 0
01210 size= mp->DL_COUNT;
01211 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
01212 panic("rtl8139","invalid packet size", size);
01213 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
01214 panic("rtl8139","umap_local failed", NO_NUM);
01215
01216 p= rep->re_tx[tx_head].ret_buf;
01217 cps = sys_abscopy(phys_user, p, size);
01218 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01219 #endif
01220 }
01221
01222 if (rep->re_clear_rx)
01223 {
01224
01225
01226
01227 #if 0
01228 printf("rl_readv: later buffer overflow\n");
01229 #endif
01230 goto suspend;
01231 }
01232
01233 rep->re_stat.ets_packetR++;
01234 rep->re_read_s= packlen;
01235 rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
01236
01237
01238 l= d_start;
01239 l += totlen+4;
01240 l= (l+3) & ~3;
01241 if (l >= RX_BUFSIZE)
01242 {
01243 l -= RX_BUFSIZE;
01244 assert(l < RX_BUFSIZE);
01245 }
01246 rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
01247
01248 if (!from_int)
01249 reply(rep, OK, FALSE);
01250
01251 return;
01252
01253 suspend:
01254 if (from_int)
01255 {
01256 assert(rep->re_flags & REF_READING);
01257
01258
01259 return;
01260 }
01261
01262 rep->re_rx_mess= *mp;
01263 assert(!(rep->re_flags & REF_READING));
01264 rep->re_flags |= REF_READING;
01265
01266 reply(rep, OK, FALSE);
01267 }
01268
01269
01270
01271
01272 static void rl_writev(mp, from_int, vectored)
01273 message *mp;
01274 int from_int;
01275 int vectored;
01276 {
01277 phys_bytes p, iov_src, phys_user;
01278 int i, j, n, s, port, count, size;
01279 int tx_head, re_client;
01280 re_t *rep;
01281 iovec_t *iovp;
01282 char *ret;
01283 int cps;
01284
01285 port = mp->DL_PORT;
01286 count = mp->DL_COUNT;
01287 if (port < 0 || port >= RE_PORT_NR)
01288 panic("rtl8139","illegal port", port);
01289 rep= &re_table[port];
01290 re_client= mp->DL_PROC;
01291 rep->re_client= re_client;
01292
01293 assert(rep->re_mode == REM_ENABLED);
01294 assert(rep->re_flags & REF_ENABLED);
01295
01296 if (from_int)
01297 {
01298 assert(rep->re_flags & REF_SEND_AVAIL);
01299 rep->re_flags &= ~REF_SEND_AVAIL;
01300 rep->re_send_int= FALSE;
01301 rep->re_tx_alive= TRUE;
01302 }
01303
01304 tx_head= rep->re_tx_head;
01305 if (rep->re_tx[tx_head].ret_busy)
01306 {
01307 assert(!(rep->re_flags & REF_SEND_AVAIL));
01308 rep->re_flags |= REF_SEND_AVAIL;
01309 if (rep->re_tx[tx_head].ret_busy)
01310 goto suspend;
01311
01312
01313
01314
01315
01316 #if 0
01317 printf("rl_writev: race detected\n");
01318 #endif
01319 rep->re_flags &= ~REF_SEND_AVAIL;
01320 rep->re_send_int= FALSE;
01321 }
01322
01323 assert(!(rep->re_flags & REF_SEND_AVAIL));
01324 assert(!(rep->re_flags & REF_PACK_SENT));
01325
01326 if (vectored)
01327 {
01328 int iov_offset = 0;
01329
01330 #if 0
01331 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR,
01332 count * sizeof(rep->re_iovec[0]), &iov_src))
01333 panic("rtl8139","umap_local failed", NO_NUM);
01334 #endif
01335
01336 size= 0;
01337 #if 0
01338 p= rep->re_tx[tx_head].ret_buf;
01339 #else
01340 ret = rep->re_tx[tx_head].v_ret_buf;
01341 #endif
01342 for (i= 0; i<count; i += IOVEC_NR,
01343 iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
01344 iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
01345 {
01346 n= IOVEC_NR;
01347 if (i+n > count)
01348 n= count-i;
01349 #if 0
01350 cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec,
01351 n * sizeof(rep->re_iovec[0]));
01352 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01353 #else
01354 cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset,
01355 SELF, D, (vir_bytes) rep->re_iovec,
01356 n * sizeof(rep->re_iovec[0]));
01357 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
01358 #endif
01359
01360 for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
01361 {
01362 s= iovp->iov_size;
01363 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
01364 {
01365 panic("rtl8139","invalid packet size",
01366 NO_NUM);
01367 }
01368
01369 if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user))
01370 panic("rtl8139","umap_local failed\n", NO_NUM);
01371
01372 #if 0
01373 cps = sys_abscopy(phys_user, p, s);
01374 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01375 #else
01376 cps = sys_vircopy(re_client, D, iovp->iov_addr,
01377 SELF, D, (vir_bytes) ret, s);
01378 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
01379 #endif
01380 size += s;
01381 #if 0
01382 p += s;
01383 #endif
01384 ret += s;
01385 }
01386 }
01387 if (size < ETH_MIN_PACK_SIZE)
01388 panic("rtl8139","invalid packet size", size);
01389 }
01390 else
01391 {
01392 size= mp->DL_COUNT;
01393 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
01394 panic("rtl8139","invalid packet size", size);
01395 #if 0
01396 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
01397 panic("rtl8139","umap_local failed\n", NO_NUM);
01398
01399 p= rep->re_tx[tx_head].ret_buf;
01400 cps = sys_abscopy(phys_user, p, size);
01401 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01402 #else
01403 ret = rep->re_tx[tx_head].v_ret_buf;
01404 cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR,
01405 SELF, D, (vir_bytes) ret, size);
01406 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
01407 #endif
01408 }
01409
01410 rl_outl(rep->re_base_port, RL_TSD0+tx_head*4,
01411 rep->re_ertxth | size);
01412 rep->re_tx[tx_head].ret_busy= TRUE;
01413
01414 if (++tx_head == N_TX_BUF)
01415 tx_head= 0;
01416 assert(tx_head < RL_N_TX);
01417 rep->re_tx_head= tx_head;
01418
01419 rep->re_flags |= REF_PACK_SENT;
01420
01421
01422
01423
01424 if (from_int)
01425 return;
01426 reply(rep, OK, FALSE);
01427 return;
01428
01429 suspend:
01430 #if 0
01431 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
01432 tx_head, rep->re_tx_tail,
01433 rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
01434 rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
01435 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
01436 rl_inl(rep->re_base_port, RL_TSD0+0*4),
01437 rl_inl(rep->re_base_port, RL_TSD0+1*4),
01438 rl_inl(rep->re_base_port, RL_TSD0+2*4),
01439 rl_inl(rep->re_base_port, RL_TSD0+3*4));
01440 #endif
01441
01442 if (from_int)
01443 panic("rtl8139","should not be sending\n", NO_NUM);
01444
01445 rep->re_tx_mess= *mp;
01446 reply(rep, OK, FALSE);
01447 }
01448
01449
01450
01451
01452 static void rl_check_ints(rep)
01453 re_t *rep;
01454 {
01455 #if 0
01456 10-1f R/W TSD[0-3] Transmit Status of Descriptor [0-3]
01457 31 R CRS Carrier Sense Lost
01458 30 R TABT Transmit Abort
01459 29 R OWC Out of Window Collision
01460 27-24 R NCC[3-0] Number of Collision Count
01461 23-22 reserved
01462 21-16 R/W ERTXH[5-0] Early Tx Threshold
01463 15 R TOK Transmit OK
01464 14 R TUN Transmit FIFO Underrun
01465 13 R/W OWN OWN
01466 12-0 R/W SIZE Descriptor Size
01467 3e-3f R/W ISR Interrupt Status Register
01468 6 R/W FOVW Fx FIFO Overflow Interrupt
01469 5 R/W PUN/LinkChg Packet Underrun / Link Change Interrupt
01470 3 R/W TER Transmit Error Interrupt
01471 2 R/W TOK Transmit OK Interrupt
01472 3e-3f R/W ISR Interrupt Status Register
01473 15 R/W SERR System Error Interrupt
01474 14 R/W TimeOut Time Out Interrupt
01475 13 R/W LenChg Cable Length Change Interrupt
01476 3e-3f R/W ISR Interrupt Status Register
01477 4 R/W RXOVW Rx Buffer Overflow Interrupt
01478 1 R/W RER Receive Error Interrupt
01479 0 R/W ROK Receive OK Interrupt
01480 4c-4f R/W MPC Missed Packet Counter
01481 60-61 R TSAD Transmit Status of All Descriptors
01482 15-12 R TOK[3-0] TOK bit of Descriptor [3-0]
01483 11-8 R TUN[3-0] TUN bit of Descriptor [3-0]
01484 7-4 R TABT[3-0] TABT bit of Descriptor [3-0]
01485 3-0 R OWN[3-0] OWN bit of Descriptor [3-0]
01486 6c-6d R DIS Disconnect Counter
01487 15-0 R DCNT Disconnect Counter
01488 6e-6f R FCSC False Carrier Sense Counter
01489 15-0 R FCSCNT False Carrier event counter
01490 72-73 R REC RX_ER Counter
01491 15-0 R RXERCNT Received packet counter
01492 #endif
01493
01494 int re_flags;
01495
01496 re_flags= rep->re_flags;
01497
01498 if ((re_flags & REF_READING) &&
01499 !(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
01500 {
01501 if (rep->re_rx_mess.m_type == DL_READV)
01502 {
01503 rl_readv(&rep->re_rx_mess, TRUE ,
01504 TRUE );
01505 }
01506 else
01507 {
01508 assert(rep->re_rx_mess.m_type == DL_READ);
01509 rl_readv(&rep->re_rx_mess, TRUE ,
01510 FALSE );
01511 }
01512 }
01513 if (rep->re_clear_rx)
01514 rl_clear_rx(rep);
01515
01516 if (rep->re_need_reset)
01517 rl_do_reset(rep);
01518
01519 if (rep->re_send_int)
01520 {
01521 if (rep->re_tx_mess.m_type == DL_WRITEV)
01522 {
01523 rl_writev(&rep->re_tx_mess, TRUE ,
01524 TRUE );
01525 }
01526 else
01527 {
01528 assert(rep->re_tx_mess.m_type == DL_WRITE);
01529 rl_writev(&rep->re_tx_mess, TRUE ,
01530 FALSE );
01531 }
01532 }
01533
01534 if (rep->re_report_link)
01535 rl_report_link(rep);
01536
01537 if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
01538 reply(rep, OK, TRUE);
01539 }
01540
01541
01542
01543
01544 static void rl_report_link(rep)
01545 re_t *rep;
01546 {
01547 port_t port;
01548 u16_t mii_ctrl, mii_status, mii_ana, mii_anlpa, mii_ane, mii_extstat;
01549 u8_t msr;
01550 int f, link_up;
01551
01552 rep->re_report_link= FALSE;
01553 port= rep->re_base_port;
01554 msr= rl_inb(port, RL_MSR);
01555 link_up= !(msr & RL_MSR_LINKB);
01556 rep->re_link_up= link_up;
01557 if (!link_up)
01558 {
01559 printf("%s: link down\n", rep->re_name);
01560 return;
01561 }
01562
01563 mii_ctrl= rl_inw(port, RL_BMCR);
01564 mii_status= rl_inw(port, RL_BMSR);
01565 mii_ana= rl_inw(port, RL_ANAR);
01566 mii_anlpa= rl_inw(port, RL_ANLPAR);
01567 mii_ane= rl_inw(port, RL_ANER);
01568 mii_extstat= 0;
01569
01570 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
01571 {
01572 printf("%s: PHY: ", rep->re_name);
01573 f= 1;
01574 if (mii_ctrl & MII_CTRL_LB)
01575 {
01576 printf("loopback mode");
01577 f= 0;
01578 }
01579 if (mii_ctrl & MII_CTRL_PD)
01580 {
01581 if (!f) printf(", ");
01582 f= 0;
01583 printf("powered down");
01584 }
01585 if (mii_ctrl & MII_CTRL_ISO)
01586 {
01587 if (!f) printf(", ");
01588 f= 0;
01589 printf("isolated");
01590 }
01591 printf("\n");
01592 return;
01593 }
01594 if (!(mii_ctrl & MII_CTRL_ANE))
01595 {
01596 printf("%s: manual config: ", rep->re_name);
01597 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
01598 {
01599 case MII_CTRL_SP_10: printf("10 Mbps"); break;
01600 case MII_CTRL_SP_100: printf("100 Mbps"); break;
01601 case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
01602 case MII_CTRL_SP_RES: printf("reserved speed"); break;
01603 }
01604 if (mii_ctrl & MII_CTRL_DM)
01605 printf(", full duplex");
01606 else
01607 printf(", half duplex");
01608 printf("\n");
01609 return;
01610 }
01611
01612 if (!debug) goto resspeed;
01613
01614 printf("%s: ", rep->re_name);
01615 mii_print_stat_speed(mii_status, mii_extstat);
01616 printf("\n");
01617
01618 if (!(mii_status & MII_STATUS_ANC))
01619 printf("%s: auto-negotiation not complete\n", rep->re_name);
01620 if (mii_status & MII_STATUS_RF)
01621 printf("%s: remote fault detected\n", rep->re_name);
01622 if (!(mii_status & MII_STATUS_ANA))
01623 {
01624 printf("%s: local PHY has no auto-negotiation ability\n",
01625 rep->re_name);
01626 }
01627 if (!(mii_status & MII_STATUS_LS))
01628 printf("%s: link down\n", rep->re_name);
01629 if (mii_status & MII_STATUS_JD)
01630 printf("%s: jabber condition detected\n", rep->re_name);
01631 if (!(mii_status & MII_STATUS_EC))
01632 {
01633 printf("%s: no extended register set\n", rep->re_name);
01634 goto resspeed;
01635 }
01636 if (!(mii_status & MII_STATUS_ANC))
01637 goto resspeed;
01638
01639 printf("%s: local cap.: ", rep->re_name);
01640 mii_print_techab(mii_ana);
01641 printf("\n");
01642
01643 if (mii_ane & MII_ANE_PDF)
01644 printf("%s: parallel detection fault\n", rep->re_name);
01645 if (!(mii_ane & MII_ANE_LPANA))
01646 {
01647 printf("%s: link-partner does not support auto-negotiation\n",
01648 rep->re_name);
01649 goto resspeed;
01650 }
01651
01652 printf("%s: remote cap.: ", rep->re_name);
01653 mii_print_techab(mii_anlpa);
01654 printf("\n");
01655
01656 resspeed:
01657 printf("%s: ", rep->re_name);
01658 printf("link up at %d Mbps, ", (msr & RL_MSR_SPEED_10) ? 10 : 100);
01659 printf("%s duplex\n", ((mii_ctrl & MII_CTRL_DM) ? "full" : "half"));
01660
01661 }
01662
01663 static void mii_print_techab(techab)
01664 u16_t techab;
01665 {
01666 int fs, ft;
01667 if ((techab & MII_ANA_SEL_M) != MII_ANA_SEL_802_3)
01668 {
01669 printf("strange selector 0x%x, value 0x%x",
01670 techab & MII_ANA_SEL_M,
01671 (techab & MII_ANA_TAF_M) >> MII_ANA_TAF_S);
01672 return;
01673 }
01674 fs= 1;
01675 if (techab & (MII_ANA_100T4 | MII_ANA_100TXFD | MII_ANA_100TXHD))
01676 {
01677 printf("100 Mbps: ");
01678 fs= 0;
01679 ft= 1;
01680 if (techab & MII_ANA_100T4)
01681 {
01682 printf("T4");
01683 ft= 0;
01684 }
01685 if (techab & (MII_ANA_100TXFD | MII_ANA_100TXHD))
01686 {
01687 if (!ft)
01688 printf(", ");
01689 ft= 0;
01690 printf("TX-");
01691 switch(techab & (MII_ANA_100TXFD|MII_ANA_100TXHD))
01692 {
01693 case MII_ANA_100TXFD: printf("FD"); break;
01694 case MII_ANA_100TXHD: printf("HD"); break;
01695 default: printf("FD/HD"); break;
01696 }
01697 }
01698 }
01699 if (techab & (MII_ANA_10TFD | MII_ANA_10THD))
01700 {
01701 if (!fs)
01702 printf(", ");
01703 printf("10 Mbps: ");
01704 fs= 0;
01705 printf("T-");
01706 switch(techab & (MII_ANA_10TFD|MII_ANA_10THD))
01707 {
01708 case MII_ANA_10TFD: printf("FD"); break;
01709 case MII_ANA_10THD: printf("HD"); break;
01710 default: printf("FD/HD"); break;
01711 }
01712 }
01713 if (techab & MII_ANA_PAUSE_SYM)
01714 {
01715 if (!fs)
01716 printf(", ");
01717 fs= 0;
01718 printf("pause(SYM)");
01719 }
01720 if (techab & MII_ANA_PAUSE_ASYM)
01721 {
01722 if (!fs)
01723 printf(", ");
01724 fs= 0;
01725 printf("pause(ASYM)");
01726 }
01727 if (techab & MII_ANA_TAF_RES)
01728 {
01729 if (!fs)
01730 printf(", ");
01731 fs= 0;
01732 printf("0x%x", (techab & MII_ANA_TAF_RES) >> MII_ANA_TAF_S);
01733 }
01734 }
01735
01736 static void mii_print_stat_speed(stat, extstat)
01737 u16_t stat;
01738 u16_t extstat;
01739 {
01740 int fs, ft;
01741 fs= 1;
01742 if (stat & MII_STATUS_EXT_STAT)
01743 {
01744 if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD |
01745 MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
01746 {
01747 printf("1000 Mbps: ");
01748 fs= 0;
01749 ft= 1;
01750 if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD))
01751 {
01752 ft= 0;
01753 printf("X-");
01754 switch(extstat &
01755 (MII_ESTAT_1000XFD|MII_ESTAT_1000XHD))
01756 {
01757 case MII_ESTAT_1000XFD: printf("FD"); break;
01758 case MII_ESTAT_1000XHD: printf("HD"); break;
01759 default: printf("FD/HD"); break;
01760 }
01761 }
01762 if (extstat & (MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
01763 {
01764 if (!ft)
01765 printf(", ");
01766 ft= 0;
01767 printf("T-");
01768 switch(extstat &
01769 (MII_ESTAT_1000TFD|MII_ESTAT_1000THD))
01770 {
01771 case MII_ESTAT_1000TFD: printf("FD"); break;
01772 case MII_ESTAT_1000THD: printf("HD"); break;
01773 default: printf("FD/HD"); break;
01774 }
01775 }
01776 }
01777 }
01778 if (stat & (MII_STATUS_100T4 |
01779 MII_STATUS_100XFD | MII_STATUS_100XHD |
01780 MII_STATUS_100T2FD | MII_STATUS_100T2HD))
01781 {
01782 if (!fs)
01783 printf(", ");
01784 fs= 0;
01785 printf("100 Mbps: ");
01786 ft= 1;
01787 if (stat & MII_STATUS_100T4)
01788 {
01789 printf("T4");
01790 ft= 0;
01791 }
01792 if (stat & (MII_STATUS_100XFD | MII_STATUS_100XHD))
01793 {
01794 if (!ft)
01795 printf(", ");
01796 ft= 0;
01797 printf("TX-");
01798 switch(stat & (MII_STATUS_100XFD|MII_STATUS_100XHD))
01799 {
01800 case MII_STATUS_100XFD: printf("FD"); break;
01801 case MII_STATUS_100XHD: printf("HD"); break;
01802 default: printf("FD/HD"); break;
01803 }
01804 }
01805 if (stat & (MII_STATUS_100T2FD | MII_STATUS_100T2HD))
01806 {
01807 if (!ft)
01808 printf(", ");
01809 ft= 0;
01810 printf("T2-");
01811 switch(stat & (MII_STATUS_100T2FD|MII_STATUS_100T2HD))
01812 {
01813 case MII_STATUS_100T2FD: printf("FD"); break;
01814 case MII_STATUS_100T2HD: printf("HD"); break;
01815 default: printf("FD/HD"); break;
01816 }
01817 }
01818 }
01819 if (stat & (MII_STATUS_10FD | MII_STATUS_10HD))
01820 {
01821 if (!fs)
01822 printf(", ");
01823 printf("10 Mbps: ");
01824 fs= 0;
01825 printf("T-");
01826 switch(stat & (MII_STATUS_10FD|MII_STATUS_10HD))
01827 {
01828 case MII_STATUS_10FD: printf("FD"); break;
01829 case MII_STATUS_10HD: printf("HD"); break;
01830 default: printf("FD/HD"); break;
01831 }
01832 }
01833 }
01834
01835
01836
01837
01838 static void rl_clear_rx(rep)
01839 re_t *rep;
01840 {
01841 port_t port;
01842 u8_t cr;
01843 int i;
01844 clock_t t0,t1;
01845
01846 rep->re_clear_rx= FALSE;
01847 port= rep->re_base_port;
01848
01849
01850 cr= rl_inb(port, RL_CR);
01851 cr &= ~RL_CR_RE;
01852 rl_outb(port, RL_CR, cr);
01853 getuptime(&t0);
01854 do {
01855 if (!(rl_inb(port, RL_CR) & RL_CR_RE))
01856 break;
01857 } while (getuptime(&t1)==OK && (t1-t0) < HZ);
01858 if (rl_inb(port, RL_CR) & RL_CR_RE)
01859 panic("rtl8139","cannot disable receiver", NO_NUM);
01860
01861 #if 0
01862 printf("RBSTART = 0x%08x\n", rl_inl(port, RL_RBSTART));
01863 printf("CAPR = 0x%04x\n", rl_inw(port, RL_CAPR));
01864 printf("CBR = 0x%04x\n", rl_inw(port, RL_CBR));
01865 printf("RCR = 0x%08x\n", rl_inl(port, RL_RCR));
01866 #endif
01867
01868 rl_outb(port, RL_CR, cr | RL_CR_RE);
01869
01870 rl_outl(port, RL_RCR, RX_BUFBITS);
01871
01872 rl_rec_mode(rep);
01873
01874 rep->re_stat.ets_missedP++;
01875 }
01876
01877
01878
01879
01880 static void rl_do_reset(rep)
01881 re_t *rep;
01882 {
01883 rep->re_need_reset= FALSE;
01884 rl_reset_hw(rep);
01885 rl_rec_mode(rep);
01886
01887 rep->re_tx_head= 0;
01888 if (rep->re_flags & REF_SEND_AVAIL)
01889 {
01890 rep->re_tx[rep->re_tx_head].ret_busy= FALSE;
01891 rep->re_send_int= TRUE;
01892 }
01893 }
01894
01895
01896
01897
01898 static void rl_getstat(mp)
01899 message *mp;
01900 {
01901 int port;
01902 eth_stat_t stats;
01903 re_t *rep;
01904
01905 port = mp->DL_PORT;
01906 if (port < 0 || port >= RE_PORT_NR)
01907 panic("rtl8139","illegal port", port);
01908 rep= &re_table[port];
01909 rep->re_client= mp->DL_PROC;
01910
01911 assert(rep->re_mode == REM_ENABLED);
01912 assert(rep->re_flags & REF_ENABLED);
01913
01914 stats= rep->re_stat;
01915
01916 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
01917 (vir_bytes) sizeof(stats), &stats);
01918 reply(rep, OK, FALSE);
01919 }
01920
01921
01922
01923
01924
01925 static void rl_getname(mp)
01926 message *mp;
01927 {
01928 int r;
01929
01930 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
01931 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
01932 mp->m_type= DL_NAME_REPLY;
01933 r= send(mp->m_source, mp);
01934 if (r != OK)
01935 panic("RTL8139", "rl_getname: send failed: %d\n", r);
01936 }
01937
01938
01939
01940
01941
01942 static void reply(rep, err, may_block)
01943 re_t *rep;
01944 int err;
01945 int may_block;
01946 {
01947 message reply;
01948 int status;
01949 int r;
01950 clock_t now;
01951
01952 status = 0;
01953 if (rep->re_flags & REF_PACK_SENT)
01954 status |= DL_PACK_SEND;
01955 if (rep->re_flags & REF_PACK_RECV)
01956 status |= DL_PACK_RECV;
01957
01958 reply.m_type = DL_TASK_REPLY;
01959 reply.DL_PORT = rep - re_table;
01960 reply.DL_PROC = rep->re_client;
01961 reply.DL_STAT = status | ((u32_t) err << 16);
01962 reply.DL_COUNT = rep->re_read_s;
01963 if (OK != (r = getuptime(&now)))
01964 panic("rtl8139","getuptime() failed:", r);
01965 reply.DL_CLCK = now;
01966
01967 r= send(rep->re_client, &reply);
01968
01969 if (r == ELOCKED && may_block)
01970 {
01971 #if 0
01972 printW(); printf("send locked\n");
01973 #endif
01974 return;
01975 }
01976
01977 if (r < 0) {
01978 printf("RTL8139 tried sending to %d, type %d\n", rep->re_client, reply.m_type);
01979 panic("rtl8139","send failed:", r);
01980 }
01981
01982 rep->re_read_s = 0;
01983 rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
01984 }
01985
01986
01987
01988
01989 static void mess_reply(req, reply_mess)
01990 message *req;
01991 message *reply_mess;
01992 {
01993 if (send(req->m_source, reply_mess) != OK)
01994 panic("rtl8139","unable to mess_reply", NO_NUM);
01995 }
01996
01997
01998
01999
02000 static void put_userdata(user_proc, user_addr, count, loc_addr)
02001 int user_proc;
02002 vir_bytes user_addr;
02003 vir_bytes count;
02004 void *loc_addr;
02005 {
02006 int cps;
02007 cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
02008 if (cps != OK) printf("RTL8139: warning, scopy failed: %d\n", cps);
02009 }
02010
02011 #if 0
02012 static void dump_phy(rep)
02013 re_t *rep;
02014 {
02015 port_t port;
02016 u32_t t;
02017
02018 port= rep->re_base_port;
02019
02020 t= rl_inb(port, RL_MSR);
02021 printf("MSR: 0x%02lx\n", t);
02022 if (t & RL_MSR_SPEED_10)
02023 printf("\t10 Mbps\n");
02024 if (t & RL_MSR_LINKB)
02025 printf("\tLink failed\n");
02026
02027 t= rl_inb(port, RL_CONFIG1);
02028 printf("CONFIG1: 0x%02lx\n", t);
02029
02030 t= rl_inb(port, RL_CONFIG3);
02031 printf("CONFIG3: 0x%02lx\n", t);
02032
02033 t= rl_inb(port, RL_CONFIG4);
02034 printf("CONFIG4: 0x%02lx\n", t);
02035
02036 t= rl_inw(port, RL_BMCR);
02037 printf("BMCR (MII_CTRL): 0x%04lx\n", t);
02038
02039 t= rl_inw(port, RL_BMSR);
02040 printf("BMSR:");
02041 if (t & MII_STATUS_100T4)
02042 printf(" 100Base-T4");
02043 if (t & MII_STATUS_100XFD)
02044 printf(" 100Base-X-FD");
02045 if (t & MII_STATUS_100XHD)
02046 printf(" 100Base-X-HD");
02047 if (t & MII_STATUS_10FD)
02048 printf(" 10Mbps-FD");
02049 if (t & MII_STATUS_10HD)
02050 printf(" 10Mbps-HD");
02051 if (t & MII_STATUS_100T2FD)
02052 printf(" 100Base-T2-FD");
02053 if (t & MII_STATUS_100T2HD)
02054 printf(" 100Base-T2-HD");
02055 if (t & MII_STATUS_EXT_STAT)
02056 printf(" Ext-stat");
02057 if (t & MII_STATUS_RES)
02058 printf(" res-0x%lx", t & MII_STATUS_RES);
02059 if (t & MII_STATUS_MFPS)
02060 printf(" MFPS");
02061 if (t & MII_STATUS_ANC)
02062 printf(" ANC");
02063 if (t & MII_STATUS_RF)
02064 printf(" remote-fault");
02065 if (t & MII_STATUS_ANA)
02066 printf(" ANA");
02067 if (t & MII_STATUS_LS)
02068 printf(" Link");
02069 if (t & MII_STATUS_JD)
02070 printf(" Jabber");
02071 if (t & MII_STATUS_EC)
02072 printf(" Extended-capability");
02073 printf("\n");
02074
02075 t= rl_inw(port, RL_ANAR);
02076 printf("ANAR (MII_ANA): 0x%04lx\n", t);
02077
02078 t= rl_inw(port, RL_ANLPAR);
02079 printf("ANLPAR: 0x%04lx\n", t);
02080
02081 t= rl_inw(port, RL_ANER);
02082 printf("ANER (MII_ANE): ");
02083 if (t & MII_ANE_RES)
02084 printf(" res-0x%lx", t & MII_ANE_RES);
02085 if (t & MII_ANE_PDF)
02086 printf(" Par-Detect-Fault");
02087 if (t & MII_ANE_LPNPA)
02088 printf(" LP-Next-Page-Able");
02089 if (t & MII_ANE_NPA)
02090 printf(" Loc-Next-Page-Able");
02091 if (t & MII_ANE_PR)
02092 printf(" Page-Received");
02093 if (t & MII_ANE_LPANA)
02094 printf(" LP-Auto-Neg-Able");
02095 printf("\n");
02096
02097 t= rl_inw(port, RL_NWAYTR);
02098 printf("NWAYTR: 0x%04lx\n", t);
02099 t= rl_inw(port, RL_CSCR);
02100 printf("CSCR: 0x%04lx\n", t);
02101
02102 t= rl_inb(port, RL_CONFIG5);
02103 printf("CONFIG5: 0x%02lx\n", t);
02104 }
02105 #endif
02106
02107 static int do_hard_int(void)
02108 {
02109 int i,s;
02110
02111 for (i=0; i < RE_PORT_NR; i ++) {
02112
02113
02114 rl_handler( &re_table[i]);
02115
02116
02117 if ((s=sys_irqenable(&re_table[i].re_hook_id)) != OK)
02118 printf("RTL8139: error, couldn't enable interrupts: %d\n", s);
02119 }
02120 }
02121
02122
02123
02124
02125 static int rl_handler(rep)
02126 re_t *rep;
02127 {
02128 int i, port, tx_head, tx_tail, link_up;
02129 u16_t isr, tsad;
02130 u32_t tsd, tcr, ertxth;
02131 #if 0
02132 u8_t cr;
02133 #endif
02134 clock_t t0,t1;
02135 int_event_check = FALSE;
02136
02137 port= rep->re_base_port;
02138
02139
02140 isr= rl_inw(port, RL_ISR);
02141 rl_outw(port, RL_ISR, isr);
02142
02143 if (isr & RL_IMR_FOVW)
02144 {
02145 isr &= ~RL_IMR_FOVW;
02146
02147
02148 rep->re_stat.ets_fifoOver++;
02149 }
02150 if (isr & RL_IMR_PUN)
02151 {
02152 isr &= ~RL_IMR_PUN;
02153
02154
02155
02156
02157 link_up= !(rl_inb(port, RL_MSR) & RL_MSR_LINKB);
02158 if (link_up != rep->re_link_up)
02159 {
02160 rep->re_report_link= TRUE;
02161 rep->re_got_int= TRUE;
02162 int_event_check = TRUE;
02163 }
02164 }
02165 if (isr & RL_IMR_RXOVW)
02166 {
02167 isr &= ~RL_IMR_RXOVW;
02168
02169
02170 rep->re_clear_rx= TRUE;
02171 rep->re_got_int= TRUE;
02172 int_event_check = TRUE;
02173 }
02174
02175 if (isr & (RL_ISR_RER | RL_ISR_ROK))
02176 {
02177 isr &= ~(RL_ISR_RER | RL_ISR_ROK);
02178
02179 if (!rep->re_got_int && (rep->re_flags & REF_READING))
02180 {
02181 rep->re_got_int= TRUE;
02182 int_event_check = TRUE;
02183 }
02184 }
02185 #if 0
02186 if ((isr & (RL_ISR_TER | RL_ISR_TOK)) &&
02187 (rep->re_flags & REF_SEND_AVAIL) &&
02188 (rep->re_tx[0].ret_busy || rep->re_tx[1].ret_busy ||
02189 rep->re_tx[2].ret_busy || rep->re_tx[3].ret_busy))
02190
02191 {
02192 printf(
02193 "rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
02194 rep->re_tx_head, rep->re_tx_tail,
02195 rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
02196 rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
02197 printf(
02198 "rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
02199 rl_inw(port, RL_TSAD),
02200 rl_inl(port, RL_TSD0+0*4),
02201 rl_inl(port, RL_TSD0+1*4),
02202 rl_inl(port, RL_TSD0+2*4),
02203 rl_inl(port, RL_TSD0+3*4));
02204 }
02205 #endif
02206 if ((isr & (RL_ISR_TER | RL_ISR_TOK)) || 1)
02207 {
02208 isr &= ~(RL_ISR_TER | RL_ISR_TOK);
02209
02210 tsad= rl_inw(port, RL_TSAD);
02211 if (tsad & (RL_TSAD_TABT0|RL_TSAD_TABT1|
02212 RL_TSAD_TABT2|RL_TSAD_TABT3))
02213 {
02214 #if 0
02215
02216
02217 rep->re_need_reset= TRUE;
02218 rep->re_got_int= TRUE;
02219 int_event_check = TRUE;
02220 #elif 0
02221
02222 rep->re_stat.ets_transAb++;
02223
02224 cr= rl_inb(port, RL_CR);
02225 cr &= ~RL_CR_TE;
02226 rl_outb(port, RL_CR, cr);
02227 getuptime(&t0);
02228 do {
02229 if (!(rl_inb(port, RL_CR) & RL_CR_TE))
02230 break;
02231 } while (getuptime(&t1)==OK && (t1-t0) < HZ);
02232 if (rl_inb(port, RL_CR) & RL_CR_TE)
02233 {
02234 panic("rtl8139","cannot disable transmitter",
02235 NO_NUM);
02236 }
02237 rl_outb(port, RL_CR, cr | RL_CR_TE);
02238
02239 tcr= rl_inl(port, RL_TCR);
02240 rl_outl(port, RL_TCR, tcr | RL_TCR_IFG_STD);
02241
02242 printf("rl_handler: reset after abort\n");
02243
02244 if (rep->re_flags & REF_SEND_AVAIL)
02245 {
02246 printf("rl_handler: REF_SEND_AVAIL\n");
02247 rep->re_send_int= TRUE;
02248 rep->re_got_int= TRUE;
02249 int_event_check = TRUE;
02250 }
02251 for (i= 0; i< N_TX_BUF; i++)
02252 rep->re_tx[i].ret_busy= FALSE;
02253 rep->re_tx_head= 0;
02254 #else
02255 printf("rl_handler, TABT, tasd = 0x%04x\n",
02256 tsad);
02257
02258
02259 for (i= 0; i< N_TX_BUF; i++)
02260 {
02261 tsd= rl_inl(port, RL_TSD0+i*4);
02262 if (tsd & RL_TSD_TABT)
02263 break;
02264 }
02265 if (i >= N_TX_BUF)
02266 {
02267 printf(
02268 "rl_handler: can't find aborted TX req.\n");
02269 }
02270 else
02271 {
02272 printf("TSD%d = 0x%04lx\n", i, tsd);
02273
02274
02275 rep->re_tx_head= rep->re_tx_tail= i;
02276 }
02277
02278
02279
02280
02281 rep->re_stat.ets_transAb++;
02282 tcr= rl_inl(port, RL_TCR);
02283 rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
02284 #endif
02285 }
02286
02287
02288 tx_head= rep->re_tx_head;
02289 tx_tail= rep->re_tx_tail;
02290 for (i= 0; i< 2*N_TX_BUF; i++)
02291 {
02292 if (!rep->re_tx[tx_tail].ret_busy)
02293 {
02294
02295
02296
02297
02298
02299 if (tx_tail == tx_head)
02300 break;
02301 if (++tx_tail >= N_TX_BUF)
02302 tx_tail= 0;
02303 assert(tx_tail < RL_N_TX);
02304 rep->re_tx_tail= tx_tail;
02305 continue;
02306 }
02307 tsd= rl_inl(port, RL_TSD0+tx_tail*4);
02308 if (!(tsd & RL_TSD_OWN))
02309 {
02310
02311 break;
02312 }
02313
02314
02315 if (tsd & RL_TSD_CRS)
02316 rep->re_stat.ets_carrSense++;
02317 if (tsd & RL_TSD_TABT)
02318 {
02319 printf("rl_handler, TABT, TSD%d = 0x%04lx\n",
02320 tx_tail, tsd);
02321 assert(0);
02322
02323
02324 rep->re_stat.ets_transAb++;
02325 tcr= rl_inl(port, RL_TCR);
02326 rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
02327 }
02328 if (tsd & RL_TSD_OWC)
02329 rep->re_stat.ets_OWC++;
02330 if (tsd & RL_TSD_CDH)
02331 rep->re_stat.ets_CDheartbeat++;
02332
02333
02334 if (tsd & RL_TSD_TOK)
02335 rep->re_stat.ets_packetT++;
02336 else
02337 rep->re_stat.ets_sendErr++;
02338 if (tsd & RL_TSD_TUN)
02339 {
02340 rep->re_stat.ets_fifoUnder++;
02341
02342
02343 ertxth= tsd + (1 << RL_TSD_ERTXTH_S);
02344 ertxth &= RL_TSD_ERTXTH_M;
02345 if (debug && ertxth > rep->re_ertxth)
02346 {
02347 printf("%s: new ertxth: %ld bytes\n",
02348 rep->re_name,
02349 (ertxth >> RL_TSD_ERTXTH_S) *
02350 32);
02351 rep->re_ertxth= ertxth;
02352 }
02353 }
02354 rep->re_tx[tx_tail].ret_busy= FALSE;
02355
02356 #if 0
02357 if (rep->re_flags & REF_SEND_AVAIL)
02358 {
02359 printf("TSD%d: %08lx\n", tx_tail, tsd);
02360 printf(
02361 "rl_handler: head %d, tail %d, busy: %d %d %d %d\n",
02362 tx_head, tx_tail,
02363 rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
02364 rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
02365 }
02366 #endif
02367
02368 if (++tx_tail >= N_TX_BUF)
02369 tx_tail= 0;
02370 assert(tx_tail < RL_N_TX);
02371 rep->re_tx_tail= tx_tail;
02372
02373 if (rep->re_flags & REF_SEND_AVAIL)
02374 {
02375 #if 0
02376 printf("rl_handler: REF_SEND_AVAIL\n");
02377 #endif
02378 rep->re_send_int= TRUE;
02379 if (!rep->re_got_int)
02380 {
02381 rep->re_got_int= TRUE;
02382 int_event_check = TRUE;
02383 }
02384 }
02385 }
02386 assert(i < 2*N_TX_BUF);
02387 }
02388 if (isr)
02389 {
02390 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
02391 isr);
02392 }
02393
02394 return 1;
02395 }
02396
02397
02398
02399
02400 static void rl_watchdog_f(tp)
02401 timer_t *tp;
02402 {
02403 int i;
02404 re_t *rep;
02405
02406 sys_setalarm(HZ, 0);
02407
02408 for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)
02409 {
02410 if (rep->re_mode != REM_ENABLED)
02411 continue;
02412 if (!(rep->re_flags & REF_SEND_AVAIL))
02413 {
02414
02415 rep->re_tx_alive= TRUE;
02416 continue;
02417 }
02418 if (rep->re_tx_alive)
02419 {
02420 rep->re_tx_alive= FALSE;
02421 continue;
02422 }
02423 printf("rl_watchdog_f: resetting port %d\n", i);
02424 printf(
02425 "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
02426 rl_inw(rep->re_base_port, RL_TSAD),
02427 rl_inl(rep->re_base_port, RL_TSD0+0*4),
02428 rl_inl(rep->re_base_port, RL_TSD0+1*4),
02429 rl_inl(rep->re_base_port, RL_TSD0+2*4),
02430 rl_inl(rep->re_base_port, RL_TSD0+3*4));
02431 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
02432 rep->re_tx_head, rep->re_tx_tail,
02433 rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
02434 rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
02435 rep->re_need_reset= TRUE;
02436 rep->re_got_int= TRUE;
02437
02438 check_int_events();
02439 }
02440 }
02441
02442 #if 0
02443
02444 _PROTOTYPE( static void rtl_init, (struct dpeth *dep) );
02445 _PROTOTYPE( static u16_t get_ee_word, (dpeth_t *dep, int a) );
02446 _PROTOTYPE( static void ee_wen, (dpeth_t *dep) );
02447 _PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w) );
02448 _PROTOTYPE( static void ee_wds, (dpeth_t *dep) );
02449
02450 static void rtl_init(dep)
02451 dpeth_t *dep;
02452 {
02453 u8_t reg_a, reg_b, cr, config0, config2, config3;
02454 int i;
02455 char val[128];
02456
02457 printf("rtl_init called\n");
02458 ne_init(dep);
02459
02460
02461 outb_reg0(dep, DP_CR, CR_PS_P0);
02462 reg_a = inb_reg0(dep, DP_DUM1);
02463 reg_b = inb_reg0(dep, DP_DUM2);
02464
02465 printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);
02466
02467 outb_reg0(dep, DP_CR, CR_PS_P3);
02468 config0 = inb_reg3(dep, 3);
02469 config2 = inb_reg3(dep, 5);
02470 config3 = inb_reg3(dep, 6);
02471 outb_reg0(dep, DP_CR, CR_PS_P0);
02472
02473 printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
02474 config0, config2, config3);
02475
02476 if (0 == sys_getkenv("RTL8029FD",9+1, val, sizeof(val)))
02477 {
02478 printf("rtl_init: setting full-duplex mode\n");
02479 outb_reg0(dep, DP_CR, CR_PS_P3);
02480
02481 cr= inb_reg3(dep, 1);
02482 outb_reg3(dep, 1, cr | 0xc0);
02483
02484 outb_reg3(dep, 6, config3 | 0x40);
02485 config3 = inb_reg3(dep, 6);
02486
02487 config2= inb_reg3(dep, 5);
02488 outb_reg3(dep, 5, config2 | 0x20);
02489 config2= inb_reg3(dep, 5);
02490
02491 outb_reg3(dep, 1, cr);
02492
02493 outb_reg0(dep, DP_CR, CR_PS_P0);
02494
02495 printf("rtl_init: config 2 = %x\n", config2);
02496 printf("rtl_init: config 3 = %x\n", config3);
02497 }
02498
02499 for (i= 0; i<64; i++)
02500 printf("%x ", get_ee_word(dep, i));
02501 printf("\n");
02502
02503 if (0 == sys_getkenv("RTL8029MN",9+1, val, sizeof(val)))
02504 {
02505 ee_wen(dep);
02506
02507 set_ee_word(dep, 0x78/2, 0x10ec);
02508 set_ee_word(dep, 0x7A/2, 0x8029);
02509 set_ee_word(dep, 0x7C/2, 0x10ec);
02510 set_ee_word(dep, 0x7E/2, 0x8029);
02511
02512 ee_wds(dep);
02513
02514 assert(get_ee_word(dep, 0x78/2) == 0x10ec);
02515 assert(get_ee_word(dep, 0x7A/2) == 0x8029);
02516 assert(get_ee_word(dep, 0x7C/2) == 0x10ec);
02517 assert(get_ee_word(dep, 0x7E/2) == 0x8029);
02518 }
02519
02520 if (0 == sys_getkenv("RTL8029XXX",10+1, val, sizeof(val)))
02521 {
02522 ee_wen(dep);
02523
02524 set_ee_word(dep, 0x76/2, 0x8029);
02525
02526 ee_wds(dep);
02527
02528 assert(get_ee_word(dep, 0x76/2) == 0x8029);
02529 }
02530 }
02531
02532 static u16_t get_ee_word(dep, a)
02533 dpeth_t *dep;
02534 int a;
02535 {
02536 int b, i, cmd;
02537 u16_t w;
02538
02539 outb_reg0(dep, DP_CR, CR_PS_P3);
02540
02541
02542 outb_reg3(dep, 1, 0x80 | 0x8);
02543
02544 cmd= 0x180 | (a & 0x3f);
02545 for (i= 8; i >= 0; i--)
02546 {
02547 b= (cmd & (1 << i));
02548 b= (b ? 2 : 0);
02549
02550
02551 outb_reg3(dep, 1, 0x80 | 0x8 | b);
02552 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
02553 }
02554 outb_reg3(dep, 1, 0x80 | 0x8);
02555
02556 w= 0;
02557 for (i= 0; i<16; i++)
02558 {
02559 w <<= 1;
02560
02561
02562
02563
02564 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
02565 outb_reg3(dep, 1, 0x80 | 0x8 | b);
02566 b= inb_reg3(dep, 1);
02567 w |= (b & 1);
02568 }
02569
02570 outb_reg3(dep, 1, 0x80);
02571 outb_reg3(dep, 1, 0x00);
02572 outb_reg0(dep, DP_CR, CR_PS_P0);
02573
02574 return w;
02575 }
02576
02577 static void ee_wen(dep)
02578 dpeth_t *dep;
02579 {
02580 int b, i, cmd;
02581 u16_t w;
02582
02583 outb_reg0(dep, DP_CR, CR_PS_P3);
02584
02585
02586 outb_reg3(dep, 1, 0x80 | 0x8);
02587
02588 cmd= 0x130;
02589 for (i= 8; i >= 0; i--)
02590 {
02591 b= (cmd & (1 << i));
02592 b= (b ? 2 : 0);
02593
02594
02595 outb_reg3(dep, 1, 0x80 | 0x8 | b);
02596 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
02597 }
02598 outb_reg3(dep, 1, 0x80 | 0x8);
02599 outb_reg3(dep, 1, 0x80);
02600
02601 }
02602
02603 static void set_ee_word(dep, a, w)
02604 dpeth_t *dep;
02605 int a;
02606 u16_t w;
02607 {
02608 int b, i, cmd;
02609 clock_t t0, t1;
02610
02611 outb_reg3(dep, 1, 0x80 | 0x8);
02612
02613 cmd= 0x140 | (a & 0x3f);
02614 for (i= 8; i >= 0; i--)
02615 {
02616 b= (cmd & (1 << i));
02617 b= (b ? 2 : 0);
02618
02619
02620 outb_reg3(dep, 1, 0x80 | 0x8 | b);
02621 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
02622 }
02623 for (i= 15; i >= 0; i--)
02624 {
02625 b= (w & (1 << i));
02626 b= (b ? 2 : 0);
02627
02628
02629 outb_reg3(dep, 1, 0x80 | 0x8 | b);
02630 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
02631 }
02632 outb_reg3(dep, 1, 0x80 | 0x8);
02633 outb_reg3(dep, 1, 0x80);
02634
02635 outb_reg3(dep, 1, 0x80 | 0x8);
02636 getuptime(&t0);
02637 do {
02638 if (inb_reg3(dep, 1) & 1)
02639 break;
02640 } while (getuptime(&t1) == OK && (t1 == t0));
02641 if (!(inb_reg3(dep, 1) & 1))
02642 panic("set_ee_word","device remains busy", NO_NUM);
02643 }
02644
02645 static void ee_wds(dep)
02646 dpeth_t *dep;
02647 {
02648 int b, i, cmd;
02649 u16_t w;
02650
02651 outb_reg0(dep, DP_CR, CR_PS_P3);
02652
02653
02654 outb_reg3(dep, 1, 0x80 | 0x8);
02655
02656 cmd= 0x100;
02657 for (i= 8; i >= 0; i--)
02658 {
02659 b= (cmd & (1 << i));
02660 b= (b ? 2 : 0);
02661
02662
02663 outb_reg3(dep, 1, 0x80 | 0x8 | b);
02664 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
02665 }
02666 outb_reg3(dep, 1, 0x80 | 0x8);
02667 outb_reg3(dep, 1, 0x80);
02668 outb_reg3(dep, 1, 0x00);
02669 outb_reg0(dep, DP_CR, CR_PS_P0);
02670 }
02671 #endif
02672
02673
02674
02675