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 #include "../drivers.h"
00044
00045 #include <stdlib.h>
00046 #include <net/hton.h>
00047 #include <net/gen/ether.h>
00048 #include <net/gen/eth_io.h>
00049 #include <ibm/pci.h>
00050
00051 #include <timers.h>
00052
00053 #define tmra_ut timer_t
00054 #define tmra_inittimer(tp) tmr_inittimer(tp)
00055 #define Proc_number(p) proc_number(p)
00056 #define debug 0
00057 #define RAND_UPDATE
00058 #define printW() ((void)0)
00059 #define vm_1phys2bus(p) (p)
00060
00061 #include "assert.h"
00062 #include "fxp.h"
00063 #include "mii.h"
00064
00065
00066 #define N_RX_BUF 40
00067
00068
00069 #define N_TX_BUF 4
00070
00071
00072 #define IOVEC_NR 16
00073
00074
00075 #define FXP_ENVVAR "FXPETH"
00076
00077 struct pcitab
00078 {
00079 u16_t vid;
00080 u16_t did;
00081 int checkclass;
00082 };
00083
00084 PRIVATE struct pcitab pcitab_fxp[]=
00085 {
00086 { 0x8086, 0x1229, 0 },
00087 { 0x8086, 0x2449, 0 },
00088
00089 { 0x0000, 0x0000, 0 }
00090 };
00091
00092 #define FXP_PORT_NR 1
00093
00094 typedef int irq_hook_t;
00095
00096
00097
00098
00099 #define structof(type, field, ptr) \
00100 ((type *) (((char *) (ptr)) - offsetof(type, field)))
00101
00102 #define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
00103
00104 static timer_t *fxp_timers= NULL;
00105 static clock_t fxp_next_timeout= 0;
00106
00107 static void micro_delay(unsigned long usecs);
00108
00109
00110 #define interrupt(x) 0
00111
00112 char buffer[70*1024];
00113
00114 typedef struct fxp
00115 {
00116 port_t fxp_base_port;
00117 int fxp_mode;
00118 int fxp_got_int;
00119 int fxp_send_int;
00120 int fxp_flags;
00121 int fxp_client;
00122 int fxp_features;
00123 int fxp_irq;
00124 int fxp_type;
00125 int fxp_ee_addrlen;
00126 int fxp_tx_alive;
00127 int fxp_need_reset;
00128
00129
00130 vir_bytes fxp_read_s;
00131 int fxp_rx_nbuf;
00132 int fxp_rx_bufsize;
00133 struct rfd *fxp_rx_buf;
00134 phys_bytes fxp_rx_busaddr;
00135 int fxp_rx_head;
00136 int fxp_rx_need_restart;
00137 int fxp_need_conf;
00138
00139
00140
00141
00142 int fxp_tx_nbuf;
00143 int fxp_tx_bufsize;
00144 struct tx *fxp_tx_buf;
00145 phys_bytes fxp_tx_busaddr;
00146 int fxp_tx_idle;
00147 int fxp_tx_head;
00148 int fxp_tx_tail;
00149 int fxp_tx_threshold;
00150
00151
00152 int fxp_report_link;
00153 int fxp_link_up;
00154 int fxp_mii_busy;
00155 u16_t fxp_mii_scr;
00156
00157
00158 int fxp_seen;
00159 u8_t fxp_pcibus;
00160 u8_t fxp_pcidev;
00161 u8_t fxp_pcifunc;
00162
00163
00164 irq_hook_t fxp_hook;
00165 ether_addr_t fxp_address;
00166 message fxp_rx_mess;
00167 message fxp_tx_mess;
00168 struct sc fxp_stat;
00169 u8_t fxp_conf_bytes[CC_BYTES_NR];
00170 char fxp_name[sizeof("fxp#n")];
00171 iovec_t fxp_iovec[IOVEC_NR];
00172 }
00173 fxp_t;
00174
00175
00176 #define FM_DISABLED 0x0
00177 #define FM_ENABLED 0x1
00178
00179
00180 #define FF_EMPTY 0x000
00181 #define FF_PACK_SENT 0x001
00182 #define FF_PACK_RECV 0x002
00183 #define FF_SEND_AVAIL 0x004
00184 #define FF_READING 0x010
00185 #define FF_PROMISC 0x040
00186 #define FF_MULTI 0x080
00187 #define FF_BROAD 0x100
00188 #define FF_ENABLED 0x200
00189
00190
00191 #define FFE_NONE 0x0
00192
00193
00194 #define FT_UNKNOWN 0x0
00195 #define FT_82557 0x1
00196 #define FT_82558A 0x2
00197 #define FT_82559 0x4
00198
00199 static fxp_t fxp_table[FXP_PORT_NR];
00200
00201 static int fxp_tasknr= ANY;
00202 static u16_t eth_ign_proto;
00203 static tmra_ut fxp_watchdog;
00204 static char *progname;
00205
00206 extern int errno;
00207
00208 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
00209 #define fxp_inw(port, offset) (do_inw((port) + (offset)))
00210 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
00211 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
00212 #define fxp_outw(port, offset, value) (do_outw((port) + (offset), (value)))
00213 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
00214
00215 _PROTOTYPE( static void fxp_init, (message *mp) );
00216 _PROTOTYPE( static void fxp_pci_conf, (void) );
00217 _PROTOTYPE( static int fxp_probe, (fxp_t *fp) );
00218 _PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp) );
00219 _PROTOTYPE( static void fxp_init_hw, (fxp_t *fp) );
00220 _PROTOTYPE( static void fxp_init_buf, (fxp_t *fp) );
00221 _PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp) );
00222 _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) );
00223 _PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) );
00224 _PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
00225 int vectored) );
00226 _PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
00227 int vectored) );
00228 _PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) );
00229 _PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
00230 phys_bytes bus_addr, int check_idle) );
00231 _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
00232 phys_bytes bus_addr, int check_idle) );
00233 _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
00234 _PROTOTYPE( static void fxp_getstat, (message *mp) );
00235 _PROTOTYPE( static void fxp_getname, (message *mp) );
00236 _PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
00237 _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) );
00238 _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp) );
00239 _PROTOTYPE( static int fxp_link_changed, (fxp_t *fp) );
00240 _PROTOTYPE( static void fxp_report_link, (fxp_t *fp) );
00241 _PROTOTYPE( static void fxp_stop, (void));
00242 _PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
00243 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
00244 _PROTOTYPE( static void put_userdata, (int user_proc,
00245 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
00246 _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) );
00247 _PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
00248 _PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
00249 _PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
00250 tmr_func_t watchdog) );
00251 _PROTOTYPE( static void fxp_expire_timers,(void) );
00252 _PROTOTYPE( static u8_t do_inb, (port_t port) );
00253 _PROTOTYPE( static u32_t do_inl, (port_t port) );
00254 _PROTOTYPE( static void do_outb, (port_t port, u8_t v) );
00255 _PROTOTYPE( static void do_outl, (port_t port, u32_t v) );
00256
00257
00258
00259
00260 int main(int argc, char *argv[])
00261 {
00262 message m;
00263 int i, r, tasknr;
00264 fxp_t *fp;
00265 long v;
00266
00267 if ((fxp_tasknr= getprocnr())<0)
00268 panic("FXP", "couldn't get proc nr", errno);
00269
00270 if (argc < 1)
00271 panic("FXP", "A head which at this time has no name", NO_NUM);
00272 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
00273
00274 v= 0;
00275 #if 0
00276 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
00277 #endif
00278 eth_ign_proto= htons((u16_t) v);
00279
00280 #if 0
00281
00282 for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)
00283 fxp_init_buf(fp);
00284 #endif
00285
00286
00287 r = _pm_findproc("inet", &tasknr);
00288 if (r == OK)
00289 notify(tasknr);
00290
00291 while (TRUE)
00292 {
00293 if ((r= receive(ANY, &m)) != OK)
00294 panic("FXP","receive failed", r);
00295
00296 switch (m.m_type)
00297 {
00298 case DEV_PING: notify(m.m_source); continue;
00299 case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
00300 case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
00301 #if 0
00302 case DL_READ: fxp_vread(&m, FALSE); break;
00303 #endif
00304 case DL_READV: fxp_readv(&m, FALSE, TRUE); break;
00305 case DL_INIT: fxp_init(&m); break;
00306 case DL_GETSTAT: fxp_getstat(&m); break;
00307 case DL_GETNAME: fxp_getname(&m); break;
00308 case HARD_INT:
00309 for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
00310 {
00311 if (fp->fxp_mode != FM_ENABLED)
00312 continue;
00313 fxp_handler(fp);
00314
00315 r= sys_irqenable(&fp->fxp_hook);
00316 if (r != OK)
00317 panic("FXP","unable enable interrupts", r);
00318
00319 if (!fp->fxp_got_int)
00320 continue;
00321 fp->fxp_got_int= 0;
00322 assert(fp->fxp_flags & FF_ENABLED);
00323 fxp_check_ints(fp);
00324 }
00325 break;
00326 case SYS_SIG: {
00327 sigset_t sigset = m.NOTIFY_ARG;
00328 if (sigismember(&sigset, SIGKSTOP)) fxp_stop();
00329 break;
00330 }
00331 case PROC_EVENT: break;
00332 case SYN_ALARM: fxp_expire_timers(); break;
00333 default:
00334 panic("FXP"," illegal message", m.m_type);
00335 }
00336 }
00337 }
00338
00339
00340
00341
00342 static void fxp_init(mp)
00343 message *mp;
00344 {
00345 static int first_time= 1;
00346
00347 int port;
00348 fxp_t *fp;
00349 message reply_mess;
00350
00351 if (first_time)
00352 {
00353 first_time= 0;
00354 fxp_pci_conf();
00355
00356 tmra_inittimer(&fxp_watchdog);
00357 tmr_arg(&fxp_watchdog)->ta_int= 0;
00358 fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
00359 }
00360
00361 port = mp->DL_PORT;
00362 if (port < 0 || port >= FXP_PORT_NR)
00363 {
00364 reply_mess.m_type= DL_INIT_REPLY;
00365 reply_mess.m3_i1= ENXIO;
00366 mess_reply(mp, &reply_mess);
00367 return;
00368 }
00369 fp= &fxp_table[port];
00370 if (fp->fxp_mode == FM_DISABLED)
00371 {
00372
00373 fxp_conf_hw(fp);
00374 if (fp->fxp_mode == FM_DISABLED)
00375 {
00376
00377 reply_mess.m_type= DL_INIT_REPLY;
00378 reply_mess.m3_i1= ENXIO;
00379 mess_reply(mp, &reply_mess);
00380 return;
00381 }
00382 if (fp->fxp_mode == FM_ENABLED)
00383 fxp_init_hw(fp);
00384 fxp_report_link(fp);
00385 }
00386
00387 assert(fp->fxp_mode == FM_ENABLED);
00388 assert(fp->fxp_flags & FF_ENABLED);
00389
00390 fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
00391
00392 if (mp->DL_MODE & DL_PROMISC_REQ)
00393 fp->fxp_flags |= FF_PROMISC;
00394 if (mp->DL_MODE & DL_MULTI_REQ)
00395 fp->fxp_flags |= FF_MULTI;
00396 if (mp->DL_MODE & DL_BROAD_REQ)
00397 fp->fxp_flags |= FF_BROAD;
00398
00399 fp->fxp_client = mp->m_source;
00400 fxp_rec_mode(fp);
00401
00402 reply_mess.m_type = DL_INIT_REPLY;
00403 reply_mess.m3_i1 = mp->DL_PORT;
00404 reply_mess.m3_i2 = FXP_PORT_NR;
00405 *(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
00406
00407 mess_reply(mp, &reply_mess);
00408 }
00409
00410
00411
00412
00413 static void fxp_pci_conf()
00414 {
00415 static char envvar[] = FXP_ENVVAR "#";
00416 static char envfmt[] = "*:d.d.d";
00417
00418 int i, h;
00419 fxp_t *fp;
00420 long v;
00421
00422 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
00423 {
00424 strcpy(fp->fxp_name, "fxp#0");
00425 fp->fxp_name[4] += i;
00426 fp->fxp_seen= FALSE;
00427 fp->fxp_features= FFE_NONE;
00428 envvar[sizeof(FXP_ENVVAR)-1]= '0'+i;
00429 #if 0
00430 if (getenv(envvar) != NULL)
00431 {
00432 if (strcmp(getenv(envvar), "off") == 0)
00433 {
00434 fp->fxp_pcibus= 255;
00435 continue;
00436 }
00437 if (!env_prefix(envvar, "pci"))
00438 env_panic(envvar);
00439 }
00440 #endif
00441
00442 v= 0;
00443 #if 0
00444 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
00445 #endif
00446 fp->fxp_pcibus= v;
00447 v= 0;
00448 #if 0
00449 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
00450 #endif
00451 fp->fxp_pcidev= v;
00452 v= 0;
00453 #if 0
00454 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
00455 #endif
00456 fp->fxp_pcifunc= v;
00457 }
00458
00459 pci_init();
00460
00461 for (h= 1; h >= 0; h--) {
00462 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
00463 {
00464 if (fp->fxp_pcibus == 255)
00465 continue;
00466 if (((fp->fxp_pcibus | fp->fxp_pcidev |
00467 fp->fxp_pcifunc) != 0) != h)
00468 {
00469 continue;
00470 }
00471 if (fxp_probe(fp))
00472 fp->fxp_seen= TRUE;
00473 }
00474 }
00475 }
00476
00477
00478
00479
00480 static int fxp_probe(fp)
00481 fxp_t *fp;
00482 {
00483 int i, r, devind, just_one;
00484 u16_t vid, did;
00485 u32_t bar;
00486 u8_t ilr, rev;
00487 char *dname, *str;
00488
00489 if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
00490 {
00491
00492 r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
00493 fp->fxp_pcifunc, &devind);
00494 if (r == 0)
00495 {
00496 printf("%s: no PCI device found at %d.%d.%d\n",
00497 fp->fxp_name, fp->fxp_pcibus,
00498 fp->fxp_pcidev, fp->fxp_pcifunc);
00499 return FALSE;
00500 }
00501 pci_ids(devind, &vid, &did);
00502 just_one= TRUE;
00503 }
00504 else
00505 {
00506 r= pci_first_dev(&devind, &vid, &did);
00507 if (r == 0)
00508 return FALSE;
00509 just_one= FALSE;
00510 }
00511
00512 for(;;)
00513 {
00514 for (i= 0; pcitab_fxp[i].vid != 0; i++)
00515 {
00516 if (pcitab_fxp[i].vid != vid)
00517 continue;
00518 if (pcitab_fxp[i].did != did)
00519 continue;
00520 if (pcitab_fxp[i].checkclass)
00521 {
00522 panic("FXP","fxp_probe: class check not implemented",
00523 NO_NUM);
00524 }
00525 break;
00526 }
00527 if (pcitab_fxp[i].vid != 0)
00528 break;
00529
00530 if (just_one)
00531 {
00532 printf(
00533 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
00534 fp->fxp_name, vid, did,
00535 fp->fxp_pcibus,
00536 fp->fxp_pcidev, fp->fxp_pcifunc);
00537 return FALSE;
00538 }
00539
00540 r= pci_next_dev(&devind, &vid, &did);
00541 if (!r)
00542 return FALSE;
00543 }
00544
00545 dname= pci_dev_name(vid, did);
00546 #if VERBOSE
00547 if (!dname)
00548 dname= "unknown device";
00549 printf("%s: %s (%04x/%04x) at %s\n",
00550 fp->fxp_name, dname, vid, did, pci_slot_name(devind));
00551 #endif
00552 pci_reserve(devind);
00553
00554 bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
00555 if (bar < 0x400)
00556 {
00557 panic("FXP","fxp_probe: base address is not properly configured",
00558 NO_NUM);
00559 }
00560 fp->fxp_base_port= bar;
00561
00562 ilr= pci_attr_r8(devind, PCI_ILR);
00563 fp->fxp_irq= ilr;
00564 if (debug)
00565 {
00566 printf("%s: using I/O address 0x%lx, IRQ %d\n",
00567 fp->fxp_name, (unsigned long)bar, ilr);
00568 }
00569
00570 rev= pci_attr_r8(devind, PCI_REV);
00571 str= NULL;
00572 fp->fxp_type= FT_UNKNOWN;
00573 switch(rev)
00574 {
00575 case FXP_REV_82557A: str= "82557A";
00576 fp->fxp_type= FT_82557;
00577 break;
00578 case FXP_REV_82557B: str= "82557B"; break;
00579 case FXP_REV_82557C: str= "82557C"; break;
00580 case FXP_REV_82558A: str= "82558A";
00581 fp->fxp_type= FT_82558A;
00582 break;
00583 case FXP_REV_82558B: str= "82558B"; break;
00584 case FXP_REV_82559A: str= "82559A"; break;
00585 case FXP_REV_82559B: str= "82559B"; break;
00586 case FXP_REV_82559C: str= "82559C";
00587 fp->fxp_type= FT_82559;
00588 break;
00589 case FXP_REV_82559ERA: str= "82559ER-A";
00590 fp->fxp_type= FT_82559;
00591 break;
00592 case FXP_REV_82550_1: str= "82550(1)";
00593 fp->fxp_type= FT_82559;
00594 break;
00595 case FXP_REV_82550_2: str= "82550(2)";
00596 fp->fxp_type= FT_82559;
00597 break;
00598 case FXP_REV_82550_3: str= "82550(3)";
00599 fp->fxp_type= FT_82559;
00600 break;
00601 case FXP_REV_82551_1: str= "82551(1)";
00602 fp->fxp_type= FT_82559;
00603 break;
00604 case FXP_REV_82551_2: str= "82551(2)";
00605 fp->fxp_type= FT_82559;
00606 break;
00607 }
00608
00609 #if VERBOSE
00610 if (str)
00611 printf("%s: device revision: %s\n", fp->fxp_name, str);
00612 else
00613 printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
00614 #endif
00615
00616 if (fp->fxp_type == FT_UNKNOWN)
00617 {
00618 printf("fxp_probe: device is not supported by this driver\n");
00619 return FALSE;
00620 }
00621
00622 return TRUE;
00623 }
00624
00625
00626
00627
00628 static void fxp_conf_hw(fp)
00629 fxp_t *fp;
00630 {
00631 int i;
00632 int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
00633
00634 fp->fxp_mode= FM_DISABLED;
00635
00636 if (!fp->fxp_seen)
00637 return;
00638
00639
00640 fp->fxp_mode= FM_ENABLED;
00641
00642 fp->fxp_flags= FF_EMPTY;
00643 fp->fxp_got_int= 0;
00644 fp->fxp_send_int= 0;
00645 fp->fxp_ee_addrlen= 0;
00646 fp->fxp_need_reset= 0;
00647 fp->fxp_report_link= 0;
00648 fp->fxp_link_up= -1;
00649 fp->fxp_mii_busy= 0;
00650 fp->fxp_read_s= 0;
00651 fp->fxp_rx_need_restart= 0;
00652 fp->fxp_need_conf= 0;
00653 fp->fxp_tx_head= 0;
00654 fp->fxp_tx_tail= 0;
00655 fp->fxp_tx_alive= 0;
00656 fp->fxp_tx_threshold= TXTT_MIN;
00657
00658
00659
00660
00661
00662
00663
00664 fp->fxp_conf_bytes[0]= CC_BYTES_NR;
00665 fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
00666 fp->fxp_conf_bytes[2]= CAI_DEFAULT;
00667 fp->fxp_conf_bytes[3]= 0;
00668 fp->fxp_conf_bytes[4]= 0;
00669 fp->fxp_conf_bytes[5]= 0;
00670 fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
00671 fp->fxp_conf_bytes[7]= CUR_1;
00672 fp->fxp_conf_bytes[8]= CCB8_503_MII;
00673 fp->fxp_conf_bytes[9]= 0;
00674 fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
00675 CCB10_RES1;
00676 fp->fxp_conf_bytes[11]= 0;
00677 fp->fxp_conf_bytes[12]= CIS_DEFAULT;
00678 fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
00679 fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
00680 fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
00681 fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
00682 fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
00683 fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
00684 fp->fxp_conf_bytes[19]= CCB19_FDPE;
00685 fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
00686 fp->fxp_conf_bytes[21]= CCB21_RES21;
00687
00688 #if VERBOSE
00689 for (i= 0; i<CC_BYTES_NR; i++)
00690 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
00691 printf("\n");
00692 #endif
00693
00694 mwi= 0;
00695 ext_stat1= 0;
00696 ext_stat2= 0;
00697 lim_fifo= 0;
00698 i82503= 0;
00699 fc= 0;
00700
00701 switch(fp->fxp_type)
00702 {
00703 case FT_82557:
00704 if (i82503)
00705 {
00706 fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
00707 fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
00708 }
00709 break;
00710 case FT_82558A:
00711 case FT_82559:
00712 if (mwi)
00713 fp->fxp_conf_bytes[3] |= CCB3_MWIE;
00714 if (ext_stat1)
00715 fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
00716 if (ext_stat2)
00717 fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
00718 if (lim_fifo)
00719 fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
00720 if (fc)
00721 {
00722
00723 fp->fxp_conf_bytes[16]= 0x1f;
00724 fp->fxp_conf_bytes[17]= 0x01;
00725
00726 fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
00727 CCB19_FDRSTOFC;
00728 }
00729
00730 fp->fxp_conf_bytes[18] |= CCB18_LROK;
00731 break;
00732 default:
00733 panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);
00734 }
00735
00736 #if VERBOSE
00737 for (i= 0; i<CC_BYTES_NR; i++)
00738 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
00739 printf("\n");
00740 #endif
00741 }
00742
00743
00744
00745
00746 static void fxp_init_hw(fp)
00747 fxp_t *fp;
00748 {
00749 int i, r, isr;
00750 port_t port;
00751 u32_t bus_addr;
00752
00753 port= fp->fxp_base_port;
00754
00755 fxp_init_buf(fp);
00756
00757 fp->fxp_flags = FF_EMPTY;
00758 fp->fxp_flags |= FF_ENABLED;
00759
00760
00761
00762
00763 fp->fxp_hook = fp->fxp_irq;
00764 r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
00765 if (r != OK)
00766 panic("FXP","sys_irqsetpolicy failed", r);
00767
00768 fxp_reset_hw(fp);
00769
00770 r= sys_irqenable(&fp->fxp_hook);
00771 if (r != OK)
00772 panic("FXP","sys_irqenable failed", r);
00773
00774
00775
00776 fxp_do_conf(fp);
00777
00778
00779 r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
00780 &bus_addr);
00781 if (r != OK)
00782 panic("FXP","sys_umap failed", r);
00783 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE );
00784
00785
00786 isr= fxp_inb(port, SCB_INT_STAT);
00787 fxp_outb(port, SCB_INT_STAT, isr);
00788
00789
00790 fxp_outb(port, SCB_INT_MASK, 0);
00791
00792 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
00793 TRUE );
00794
00795 fxp_confaddr(fp);
00796 if (debug)
00797 {
00798 printf("%s: Ethernet address ", fp->fxp_name);
00799 for (i= 0; i < 6; i++)
00800 {
00801 printf("%x%c", fp->fxp_address.ea_addr[i],
00802 i < 5 ? ':' : '\n');
00803 }
00804 }
00805 }
00806
00807
00808
00809
00810 static void fxp_init_buf(fp)
00811 fxp_t *fp;
00812 {
00813 size_t rx_totbufsize, tx_totbufsize, tot_bufsize;
00814 phys_bytes buf;
00815 int i, r;
00816 struct rfd *rfdp;
00817 struct tx *txp;
00818
00819 fp->fxp_rx_nbuf= N_RX_BUF;
00820 rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
00821 fp->fxp_rx_bufsize= rx_totbufsize;
00822
00823 fp->fxp_tx_nbuf= N_TX_BUF;
00824 tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
00825 fp->fxp_tx_bufsize= tx_totbufsize;
00826
00827 tot_bufsize= tx_totbufsize + rx_totbufsize;
00828
00829
00830 {
00831 static int first_time= 1;
00832
00833 assert(first_time);
00834 first_time= 0;
00835
00836 #define BUFALIGN 4096
00837 assert(tot_bufsize <= sizeof(buffer)-BUFALIGN);
00838 buf= (phys_bytes)buffer;
00839 buf += BUFALIGN - (buf % BUFALIGN);
00840 }
00841
00842 fp->fxp_rx_buf= (struct rfd *)buf;
00843 r= sys_umap(SELF, D, (vir_bytes)buf, rx_totbufsize,
00844 &fp->fxp_rx_busaddr);
00845 if (r != OK)
00846 panic("FXP","sys_umap failed", r);
00847 for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
00848 {
00849 rfdp->rfd_status= 0;
00850 rfdp->rfd_command= 0;
00851 if (i != fp->fxp_rx_nbuf-1)
00852 {
00853 r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],
00854 sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
00855 if (r != OK)
00856 panic("FXP","sys_umap failed", r);
00857 }
00858 else
00859 {
00860 rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
00861 rfdp->rfd_command |= RFDC_EL;
00862 }
00863 rfdp->rfd_reserved= 0;
00864 rfdp->rfd_res= 0;
00865 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
00866
00867 }
00868 fp->fxp_rx_head= 0;
00869
00870 fp->fxp_tx_buf= (struct tx *)(buf+rx_totbufsize);
00871 r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,
00872 (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
00873 if (r != OK)
00874 panic("FXP","sys_umap failed", r);
00875
00876 for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
00877 {
00878 txp->tx_status= 0;
00879 txp->tx_command= TXC_EL | CBL_NOP;
00880 if (i != fp->fxp_tx_nbuf-1)
00881 {
00882 r= sys_umap(SELF, D, (vir_bytes)&txp[1],
00883 (phys_bytes)sizeof(txp[1]),
00884 &txp->tx_linkaddr);
00885 if (r != OK)
00886 panic("FXP","sys_umap failed", r);
00887 }
00888 else
00889 {
00890 txp->tx_linkaddr= fp->fxp_tx_busaddr;
00891 }
00892 txp->tx_tbda= TX_TBDA_NIL;
00893 txp->tx_size= 0;
00894 txp->tx_tthresh= fp->fxp_tx_threshold;
00895 txp->tx_ntbd= 0;
00896 }
00897 fp->fxp_tx_idle= 1;
00898 }
00899
00900
00901
00902
00903 static void fxp_reset_hw(fp)
00904 fxp_t *fp;
00905 {
00906
00907 port_t port;
00908
00909 port= fp->fxp_base_port;
00910
00911
00912 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
00913 tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
00914
00915
00916 fxp_outb(port, SCB_INT_MASK, SIM_M);
00917
00918
00919 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE );
00920
00921
00922 fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE );
00923 }
00924
00925
00926
00927
00928 static void fxp_confaddr(fp)
00929 fxp_t *fp;
00930 {
00931 static char eakey[]= FXP_ENVVAR "#_EA";
00932 static char eafmt[]= "x:x:x:x:x:x";
00933 clock_t t0,t1;
00934 int i, r;
00935 port_t port;
00936 u32_t bus_addr;
00937 long v;
00938 struct ias ias;
00939
00940 port= fp->fxp_base_port;
00941
00942
00943 eakey[sizeof(FXP_ENVVAR)-1]= '0' + (fp-fxp_table);
00944
00945 #if 0
00946 for (i= 0; i < 6; i++)
00947 {
00948 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
00949 break;
00950 fp->fxp_address.ea_addr[i]= v;
00951 }
00952 #else
00953 i= 0;
00954 #endif
00955
00956 #if 0
00957 if (i != 0 && i != 6) env_panic(eakey);
00958 #endif
00959
00960 if (i == 0)
00961 {
00962
00963 for (i= 0; i<3; i++)
00964 {
00965 v= eeprom_read(fp, i);
00966 fp->fxp_address.ea_addr[i*2]= (v & 0xff);
00967 fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
00968 }
00969 }
00970
00971
00972 ias.ias_status= 0;
00973 ias.ias_command= CBL_C_EL | CBL_AIS;
00974 ias.ias_linkaddr= 0;
00975 memcpy(ias.ias_ethaddr, fp->fxp_address.ea_addr,
00976 sizeof(ias.ias_ethaddr));
00977 r= sys_umap(SELF, D, (vir_bytes)&ias, (phys_bytes)sizeof(ias),
00978 &bus_addr);
00979 if (r != OK)
00980 panic("FXP","sys_umap failed", r);
00981
00982 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE );
00983
00984 getuptime(&t0);
00985 do {
00986
00987 if (ias.ias_status & CBL_F_C)
00988 break;
00989 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
00990
00991 if (!(ias.ias_status & CBL_F_C))
00992 panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
00993 if (!(ias.ias_status & CBL_F_OK))
00994 panic("FXP","fxp_confaddr: CU command failed", NO_NUM);
00995
00996 #if VERBOSE
00997 printf("%s: hardware ethernet address: ", fp->fxp_name);
00998 for (i= 0; i<6; i++)
00999 {
01000 printf("%02x%s", fp->fxp_address.ea_addr[i],
01001 i < 5 ? ":" : "");
01002 }
01003 printf("\n");
01004 #endif
01005 }
01006
01007
01008
01009
01010 static void fxp_rec_mode(fp)
01011 fxp_t *fp;
01012 {
01013 fp->fxp_conf_bytes[0]= CC_BYTES_NR;
01014 fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
01015 fp->fxp_conf_bytes[21] &= ~CCB21_MA;
01016
01017 if (fp->fxp_flags & FF_PROMISC)
01018 fp->fxp_conf_bytes[15] |= CCB15_PM;
01019 if (fp->fxp_flags & FF_MULTI)
01020 fp->fxp_conf_bytes[21] |= CCB21_MA;
01021
01022 if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
01023 fp->fxp_conf_bytes[15] |= CCB15_BD;
01024
01025
01026 if (fp->fxp_tx_idle)
01027 {
01028 fxp_do_conf(fp);
01029 }
01030 else
01031 {
01032 printf("fxp_rec_mode: setting fxp_need_conf\n");
01033 fp->fxp_need_conf= TRUE;
01034 }
01035 }
01036
01037
01038
01039
01040 static void fxp_writev(mp, from_int, vectored)
01041 message *mp;
01042 int from_int;
01043 int vectored;
01044 {
01045 vir_bytes iov_src;
01046 int i, j, n, o, r, s, dl_port, count, size, prev_head;
01047 int fxp_client, fxp_tx_nbuf, fxp_tx_head;
01048 u16_t tx_command;
01049 fxp_t *fp;
01050 iovec_t *iovp;
01051 struct tx *txp, *prev_txp;
01052
01053 dl_port = mp->DL_PORT;
01054 count = mp->DL_COUNT;
01055 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
01056 panic("FXP","fxp_writev: illegal port", dl_port);
01057 fp= &fxp_table[dl_port];
01058 fxp_client= mp->DL_PROC;
01059 fp->fxp_client= fxp_client;
01060
01061 assert(fp->fxp_mode == FM_ENABLED);
01062 assert(fp->fxp_flags & FF_ENABLED);
01063
01064 if (from_int)
01065 {
01066 assert(fp->fxp_flags & FF_SEND_AVAIL);
01067 fp->fxp_flags &= ~FF_SEND_AVAIL;
01068 fp->fxp_tx_alive= TRUE;
01069 }
01070
01071 if (fp->fxp_tx_idle)
01072 {
01073 txp= fp->fxp_tx_buf;
01074 fxp_tx_head= 0;
01075 prev_txp= NULL;
01076 }
01077 else
01078 {
01079 fxp_tx_nbuf= fp->fxp_tx_nbuf;
01080 prev_head= fp->fxp_tx_head;
01081 fxp_tx_head= prev_head+1;
01082 if (fxp_tx_head == fxp_tx_nbuf)
01083 fxp_tx_head= 0;
01084 assert(fxp_tx_head < fxp_tx_nbuf);
01085
01086 if (fxp_tx_head == fp->fxp_tx_tail)
01087 {
01088
01089 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
01090 fp->fxp_flags |= FF_SEND_AVAIL;
01091 goto suspend;
01092 }
01093
01094 prev_txp= &fp->fxp_tx_buf[prev_head];
01095 txp= &fp->fxp_tx_buf[fxp_tx_head];
01096 }
01097
01098 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
01099 assert(!(fp->fxp_flags & FF_PACK_SENT));
01100
01101 if (vectored)
01102 {
01103
01104 iov_src = (vir_bytes)mp->DL_ADDR;
01105
01106 size= 0;
01107 o= 0;
01108 for (i= 0; i<count; i += IOVEC_NR,
01109 iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
01110 {
01111 n= IOVEC_NR;
01112 if (i+n > count)
01113 n= count-i;
01114 r= sys_vircopy(fxp_client, D, iov_src,
01115 SELF, D, (vir_bytes)fp->fxp_iovec,
01116 n * sizeof(fp->fxp_iovec[0]));
01117 if (r != OK)
01118 panic("FXP","fxp_writev: sys_vircopy failed", r);
01119
01120 for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
01121 {
01122 s= iovp->iov_size;
01123 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
01124 {
01125 panic("FXP","fxp_writev: invalid packet size",
01126 NO_NUM);
01127 }
01128
01129 r= sys_vircopy(fxp_client, D, iovp->iov_addr,
01130 SELF, D, (vir_bytes)(txp->tx_buf+o),
01131 s);
01132 if (r != OK)
01133 {
01134 panic("FXP","fxp_writev: sys_vircopy failed",
01135 r);
01136 }
01137 size += s;
01138 o += s;
01139 }
01140 }
01141 if (size < ETH_MIN_PACK_SIZE)
01142 panic("FXP","fxp_writev: invalid packet size", size);
01143 }
01144 else
01145 {
01146 size= mp->DL_COUNT;
01147 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
01148 panic("FXP","fxp_writev: invalid packet size", size);
01149
01150 r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR,
01151 SELF, D, (vir_bytes)txp->tx_buf, size);
01152 if (r != OK)
01153 panic("FXP","fxp_writev: sys_vircopy failed", r);
01154 }
01155
01156 txp->tx_status= 0;
01157 txp->tx_command= TXC_EL | CBL_XMIT;
01158 txp->tx_tbda= TX_TBDA_NIL;
01159 txp->tx_size= TXSZ_EOF | size;
01160 txp->tx_tthresh= fp->fxp_tx_threshold;
01161 txp->tx_ntbd= 0;
01162 if (fp->fxp_tx_idle)
01163 {
01164 fp->fxp_tx_idle= 0;
01165 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
01166
01167 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
01168 TRUE );
01169 }
01170 else
01171 {
01172
01173 tx_command= prev_txp->tx_command;
01174 assert(tx_command == (TXC_EL | CBL_XMIT));
01175 prev_txp->tx_command= CBL_XMIT;
01176 fp->fxp_tx_head= fxp_tx_head;
01177 }
01178
01179 fp->fxp_flags |= FF_PACK_SENT;
01180
01181
01182
01183
01184 if (from_int)
01185 return;
01186 reply(fp, OK, FALSE);
01187 return;
01188
01189 suspend:
01190 if (from_int)
01191 panic("FXP","fxp: should not be sending\n", NO_NUM);
01192
01193 fp->fxp_tx_mess= *mp;
01194 reply(fp, OK, FALSE);
01195 }
01196
01197
01198
01199
01200 static void fxp_readv(mp, from_int, vectored)
01201 message *mp;
01202 int from_int;
01203 int vectored;
01204 {
01205 int i, j, n, o, r, s, dl_port, fxp_client, count, size,
01206 fxp_rx_head, fxp_rx_nbuf;
01207 port_t port;
01208 unsigned packlen;
01209 vir_bytes iov_src;
01210 u16_t rfd_status;
01211 u16_t rfd_res;
01212 u8_t scb_status;
01213 fxp_t *fp;
01214 iovec_t *iovp;
01215 struct rfd *rfdp, *prev_rfdp;
01216
01217 dl_port = mp->DL_PORT;
01218 count = mp->DL_COUNT;
01219 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
01220 panic("FXP","fxp_readv: illegal port", dl_port);
01221 fp= &fxp_table[dl_port];
01222 fxp_client= mp->DL_PROC;
01223 fp->fxp_client= fxp_client;
01224
01225 assert(fp->fxp_mode == FM_ENABLED);
01226 assert(fp->fxp_flags & FF_ENABLED);
01227
01228 port= fp->fxp_base_port;
01229
01230 fxp_rx_head= fp->fxp_rx_head;
01231 rfdp= &fp->fxp_rx_buf[fxp_rx_head];
01232
01233 rfd_status= rfdp->rfd_status;
01234 if (!(rfd_status & RFDS_C))
01235 {
01236
01237 goto suspend;
01238 }
01239
01240 if (!rfd_status & RFDS_OK)
01241 {
01242
01243 assert(0);
01244 }
01245 else
01246 {
01247 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
01248 RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
01249 RFDS_RXERR)));
01250 }
01251 rfd_res= rfdp->rfd_res;
01252 assert(rfd_res & RFDR_EOF);
01253 assert(rfd_res & RFDR_F);
01254
01255 packlen= rfd_res & RFDSZ_SIZE;
01256
01257 if (vectored)
01258 {
01259 iov_src = (vir_bytes)mp->DL_ADDR;
01260
01261 size= 0;
01262 o= 0;
01263 for (i= 0; i<count; i += IOVEC_NR,
01264 iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
01265 {
01266 n= IOVEC_NR;
01267 if (i+n > count)
01268 n= count-i;
01269 r= sys_vircopy(fxp_client, D, iov_src,
01270 SELF, D, (vir_bytes)fp->fxp_iovec,
01271 n * sizeof(fp->fxp_iovec[0]));
01272 if (r != OK)
01273 panic("FXP","fxp_readv: sys_vircopy failed", r);
01274
01275 for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
01276 {
01277 s= iovp->iov_size;
01278 if (size + s > packlen)
01279 {
01280 assert(packlen > size);
01281 s= packlen-size;
01282 }
01283
01284 r= sys_vircopy(SELF, D,
01285 (vir_bytes)(rfdp->rfd_buf+o),
01286 fxp_client, D, iovp->iov_addr, s);
01287 if (r != OK)
01288 {
01289 panic("FXP","fxp_readv: sys_vircopy failed",
01290 r);
01291 }
01292
01293 size += s;
01294 if (size == packlen)
01295 break;
01296 o += s;
01297 }
01298 if (size == packlen)
01299 break;
01300 }
01301 if (size < packlen)
01302 {
01303 assert(0);
01304 }
01305 }
01306 else
01307 {
01308 assert(0);
01309 }
01310
01311 fp->fxp_read_s= packlen;
01312 fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
01313
01314
01315 rfdp->rfd_status= 0;
01316 rfdp->rfd_command= RFDC_EL;
01317 rfdp->rfd_reserved= 0;
01318 rfdp->rfd_res= 0;
01319 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
01320
01321 fxp_rx_nbuf= fp->fxp_rx_nbuf;
01322 if (fxp_rx_head == 0)
01323 {
01324 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
01325 }
01326 else
01327 prev_rfdp= &rfdp[-1];
01328
01329 assert(prev_rfdp->rfd_command & RFDC_EL);
01330 prev_rfdp->rfd_command &= ~RFDC_EL;
01331
01332 fxp_rx_head++;
01333 if (fxp_rx_head == fxp_rx_nbuf)
01334 fxp_rx_head= 0;
01335 assert(fxp_rx_head < fxp_rx_nbuf);
01336 fp->fxp_rx_head= fxp_rx_head;
01337
01338 if (!from_int)
01339 reply(fp, OK, FALSE);
01340
01341 return;
01342
01343 suspend:
01344 if (fp->fxp_rx_need_restart)
01345 {
01346 fp->fxp_rx_need_restart= 0;
01347
01348
01349 scb_status= fxp_inb(port, SCB_STATUS);
01350 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
01351 {
01352
01353 printf("fxp_readv: restart race: 0x%x\n",
01354 scb_status);
01355 assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
01356 }
01357 else
01358 {
01359 fxp_restart_ru(fp);
01360 }
01361 }
01362 if (from_int)
01363 {
01364 assert(fp->fxp_flags & FF_READING);
01365
01366
01367 return;
01368 }
01369
01370 fp->fxp_rx_mess= *mp;
01371 assert(!(fp->fxp_flags & FF_READING));
01372 fp->fxp_flags |= FF_READING;
01373
01374 reply(fp, OK, FALSE);
01375 }
01376
01377
01378
01379
01380 static void fxp_do_conf(fp)
01381 fxp_t *fp;
01382 {
01383 int r;
01384 u32_t bus_addr;
01385 struct cbl_conf cc;
01386 clock_t t0,t1;
01387
01388
01389 cc.cc_status= 0;
01390 cc.cc_command= CBL_C_EL | CBL_CONF;
01391 cc.cc_linkaddr= 0;
01392 memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes));
01393
01394 r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc),
01395 &bus_addr);
01396 if (r != OK)
01397 panic("FXP","sys_umap failed", r);
01398
01399 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE );
01400
01401 getuptime(&t0);
01402 do {
01403
01404 if (cc.cc_status & CBL_F_C)
01405 break;
01406 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
01407
01408 if (!(cc.cc_status & CBL_F_C))
01409 panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
01410 if (!(cc.cc_status & CBL_F_OK))
01411 panic("FXP","fxp_do_conf: CU command failed", NO_NUM);
01412
01413 }
01414
01415
01416
01417
01418 static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
01419 fxp_t *fp;
01420 int cmd;
01421 phys_bytes bus_addr;
01422 int check_idle;
01423 {
01424 clock_t t0,t1;
01425 port_t port;
01426 u8_t scb_cmd;
01427
01428 port= fp->fxp_base_port;
01429
01430 if (check_idle)
01431 {
01432
01433 if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
01434 panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);
01435 }
01436
01437 fxp_outl(port, SCB_POINTER, bus_addr);
01438 fxp_outb(port, SCB_CMD, cmd);
01439
01440
01441
01442
01443 getuptime(&t0);
01444 do {
01445
01446 scb_cmd= fxp_inb(port, SCB_CMD);
01447 if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
01448 break;
01449 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
01450
01451 if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
01452 panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
01453 }
01454
01455
01456
01457
01458 static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
01459 fxp_t *fp;
01460 int cmd;
01461 phys_bytes bus_addr;
01462 int check_idle;
01463 {
01464 clock_t t0,t1;
01465 port_t port;
01466 u8_t scb_cmd;
01467
01468 port= fp->fxp_base_port;
01469
01470 if (check_idle)
01471 {
01472
01473 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
01474 panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);
01475 }
01476
01477 fxp_outl(port, SCB_POINTER, bus_addr);
01478 fxp_outb(port, SCB_CMD, cmd);
01479
01480 getuptime(&t0);
01481 do {
01482
01483 scb_cmd= fxp_inb(port, SCB_CMD);
01484 if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
01485 break;
01486 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
01487
01488 if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
01489 panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
01490 }
01491
01492
01493
01494
01495 static void fxp_restart_ru(fp)
01496 fxp_t *fp;
01497 {
01498 int i, fxp_rx_nbuf;
01499 port_t port;
01500 struct rfd *rfdp;
01501
01502 port= fp->fxp_base_port;
01503
01504 fxp_rx_nbuf= fp->fxp_rx_nbuf;
01505 for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
01506 {
01507 rfdp->rfd_status= 0;
01508 rfdp->rfd_command= 0;
01509 if (i == fp->fxp_rx_nbuf-1)
01510 rfdp->rfd_command= RFDC_EL;
01511 rfdp->rfd_reserved= 0;
01512 rfdp->rfd_res= 0;
01513 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
01514 }
01515 fp->fxp_rx_head= 0;
01516
01517
01518 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
01519 panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);
01520
01521 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
01522 FALSE );
01523 }
01524
01525
01526
01527
01528 static void fxp_getstat(mp)
01529 message *mp;
01530 {
01531 clock_t t0,t1;
01532 int dl_port;
01533 port_t port;
01534 fxp_t *fp;
01535 u32_t *p;
01536 eth_stat_t stats;
01537
01538 dl_port = mp->DL_PORT;
01539 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
01540 panic("FXP","fxp_getstat: illegal port", dl_port);
01541 fp= &fxp_table[dl_port];
01542 fp->fxp_client= mp->DL_PROC;
01543
01544 assert(fp->fxp_mode == FM_ENABLED);
01545 assert(fp->fxp_flags & FF_ENABLED);
01546
01547 port= fp->fxp_base_port;
01548
01549 p= &fp->fxp_stat.sc_tx_fcp;
01550 *p= 0;
01551
01552
01553
01554
01555 fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE );
01556
01557 getuptime(&t0);
01558 do {
01559
01560 if (*p != 0)
01561 break;
01562 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
01563
01564 if (*p == 0)
01565 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
01566 if (*p != SCM_DSC)
01567 panic("FXP","fxp_getstat: bad magic", NO_NUM);
01568
01569 stats.ets_recvErr=
01570 fp->fxp_stat.sc_rx_crc +
01571 fp->fxp_stat.sc_rx_align +
01572 fp->fxp_stat.sc_rx_resource +
01573 fp->fxp_stat.sc_rx_overrun +
01574 fp->fxp_stat.sc_rx_cd +
01575 fp->fxp_stat.sc_rx_short;
01576 stats.ets_sendErr=
01577 fp->fxp_stat.sc_tx_maxcol +
01578 fp->fxp_stat.sc_tx_latecol +
01579 fp->fxp_stat.sc_tx_crs;
01580 stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
01581 stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
01582 stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
01583 stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
01584 stats.ets_packetR= fp->fxp_stat.sc_rx_good;
01585 stats.ets_packetT= fp->fxp_stat.sc_tx_good;
01586 stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
01587 stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
01588 stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
01589 stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
01590 stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
01591 stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
01592 stats.ets_CDheartbeat= 0;
01593 stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
01594
01595 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
01596 (vir_bytes) sizeof(stats), &stats);
01597 reply(fp, OK, FALSE);
01598 }
01599
01600
01601
01602
01603
01604 static void fxp_getname(mp)
01605 message *mp;
01606 {
01607 int r;
01608
01609 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
01610 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
01611 mp->m_type= DL_NAME_REPLY;
01612 r= send(mp->m_source, mp);
01613 if (r != OK)
01614 panic("FXP", "fxp_getname: send failed", r);
01615 }
01616
01617
01618
01619
01620 static int fxp_handler(fp)
01621 fxp_t *fp;
01622 {
01623 int port;
01624 u16_t isr;
01625
01626 RAND_UPDATE
01627
01628 port= fp->fxp_base_port;
01629
01630
01631 isr= fxp_inb(port, SCB_INT_STAT);
01632 fxp_outb(port, SCB_INT_STAT, isr);
01633
01634 if (isr & SIS_FR)
01635 {
01636 isr &= ~SIS_FR;
01637
01638 if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
01639 {
01640 fp->fxp_got_int= TRUE;
01641 interrupt(fxp_tasknr);
01642 }
01643 }
01644 if (isr & SIS_CNA)
01645 {
01646 isr &= ~SIS_CNA;
01647 if (!fp->fxp_tx_idle)
01648 {
01649 fp->fxp_send_int= TRUE;
01650 if (!fp->fxp_got_int)
01651 {
01652 fp->fxp_got_int= TRUE;
01653 interrupt(fxp_tasknr);
01654 }
01655 }
01656 }
01657 if (isr & SIS_RNR)
01658 {
01659 isr &= ~SIS_RNR;
01660
01661
01662
01663
01664 fp->fxp_rx_need_restart= 1;
01665 }
01666 if (isr)
01667 {
01668 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
01669 isr);
01670 }
01671
01672 return 1;
01673 }
01674
01675
01676
01677
01678 static void fxp_check_ints(fp)
01679 fxp_t *fp;
01680 {
01681 int n, fxp_flags, prev_tail;
01682 int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
01683 port_t port;
01684 u32_t busaddr;
01685 u16_t tx_status;
01686 u8_t scb_status;
01687 struct tx *txp;
01688
01689 fxp_flags= fp->fxp_flags;
01690
01691 if (fxp_flags & FF_READING)
01692 {
01693 if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
01694 ;
01695 else if (fp->fxp_rx_mess.m_type == DL_READV)
01696 {
01697 fxp_readv(&fp->fxp_rx_mess, TRUE ,
01698 TRUE );
01699 }
01700 else
01701 {
01702 assert(fp->fxp_rx_mess.m_type == DL_READ);
01703 fxp_readv(&fp->fxp_rx_mess, TRUE ,
01704 FALSE );
01705 }
01706 }
01707 if (fp->fxp_tx_idle)
01708 ;
01709 else if (fp->fxp_send_int)
01710 {
01711 fp->fxp_send_int= FALSE;
01712 fxp_tx_tail= fp->fxp_tx_tail;
01713 fxp_tx_nbuf= fp->fxp_tx_nbuf;
01714 n= 0;
01715 for (;;)
01716 {
01717 txp= &fp->fxp_tx_buf[fxp_tx_tail];
01718 tx_status= txp->tx_status;
01719 if (!(tx_status & TXS_C))
01720 break;
01721
01722 n++;
01723
01724 assert(tx_status & TXS_OK);
01725 if (tx_status & TXS_U)
01726 {
01727 fxp_tx_threshold= fp->fxp_tx_threshold;
01728 if (fxp_tx_threshold < TXTT_MAX)
01729 {
01730 fxp_tx_threshold++;
01731 fp->fxp_tx_threshold= fxp_tx_threshold;
01732 }
01733 printf(
01734 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
01735 fxp_tx_threshold);
01736 }
01737
01738 if (txp->tx_command & TXC_EL)
01739 {
01740 fp->fxp_tx_idle= 1;
01741 break;
01742 }
01743
01744 fxp_tx_tail++;
01745 if (fxp_tx_tail == fxp_tx_nbuf)
01746 fxp_tx_tail= 0;
01747 assert(fxp_tx_tail < fxp_tx_nbuf);
01748 }
01749
01750 if (fp->fxp_need_conf)
01751 {
01752
01753 port= fp->fxp_base_port;
01754 scb_status= fxp_inb(port, SCB_STATUS);
01755 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
01756 {
01757
01758 printf("scb_status = 0x%x\n", scb_status);
01759 }
01760 else
01761 {
01762 printf("fxp_check_ints: fxp_need_conf\n");
01763 fp->fxp_need_conf= FALSE;
01764 fxp_do_conf(fp);
01765 }
01766 }
01767
01768 if (n)
01769 {
01770 if (!fp->fxp_tx_idle)
01771 {
01772 fp->fxp_tx_tail= fxp_tx_tail;
01773
01774
01775 port= fp->fxp_base_port;
01776 scb_status= fxp_inb(port, SCB_STATUS);
01777 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
01778 {
01779
01780 printf("scb_status = 0x%x\n",
01781 scb_status);
01782
01783 }
01784 else
01785 {
01786 if (fxp_tx_tail == 0)
01787 prev_tail= fxp_tx_nbuf-1;
01788 else
01789 prev_tail= fxp_tx_tail-1;
01790 busaddr= fp->fxp_tx_buf[prev_tail].
01791 tx_linkaddr;
01792
01793 fxp_cu_ptr_cmd(fp, SC_CU_START,
01794 busaddr, 1 );
01795 }
01796 }
01797
01798 if (fp->fxp_flags & FF_SEND_AVAIL)
01799 {
01800 if (fp->fxp_tx_mess.m_type == DL_WRITEV)
01801 {
01802 fxp_writev(&fp->fxp_tx_mess,
01803 TRUE ,
01804 TRUE );
01805 }
01806 else
01807 {
01808 assert(fp->fxp_tx_mess.m_type ==
01809 DL_WRITE);
01810 fxp_writev(&fp->fxp_tx_mess,
01811 TRUE ,
01812 FALSE );
01813 }
01814 }
01815 }
01816
01817 }
01818 if (fp->fxp_report_link)
01819 fxp_report_link(fp);
01820
01821 if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
01822 reply(fp, OK, TRUE);
01823 }
01824
01825
01826
01827
01828 static void fxp_watchdog_f(tp)
01829 timer_t *tp;
01830 {
01831 int i;
01832 fxp_t *fp;
01833
01834 tmr_arg(&fxp_watchdog)->ta_int= 0;
01835 fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
01836
01837 for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
01838 {
01839 if (fp->fxp_mode != FM_ENABLED)
01840 continue;
01841
01842
01843 if(!fp->fxp_mii_busy)
01844 {
01845
01846 if (fxp_link_changed(fp))
01847 {
01848 #if VERBOSE
01849 printf("fxp_watchdog_f: link changed\n");
01850 #endif
01851 fp->fxp_report_link= TRUE;
01852 fp->fxp_got_int= TRUE;
01853 interrupt(fxp_tasknr);
01854 }
01855 }
01856
01857 if (!(fp->fxp_flags & FF_SEND_AVAIL))
01858 {
01859
01860 fp->fxp_tx_alive= TRUE;
01861 continue;
01862 }
01863 if (fp->fxp_tx_alive)
01864 {
01865 fp->fxp_tx_alive= FALSE;
01866 continue;
01867 }
01868
01869 fp->fxp_need_reset= TRUE;
01870 fp->fxp_got_int= TRUE;
01871 interrupt(fxp_tasknr);
01872 }
01873 }
01874
01875
01876
01877
01878 static int fxp_link_changed(fp)
01879 fxp_t *fp;
01880 {
01881 u16_t scr;
01882
01883 scr= mii_read(fp, MII_SCR);
01884 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
01885
01886 return (fp->fxp_mii_scr != scr);
01887 }
01888
01889
01890
01891
01892 static void fxp_report_link(fp)
01893 fxp_t *fp;
01894 {
01895 port_t port;
01896 u16_t mii_ctrl, mii_status, mii_id1, mii_id2,
01897 mii_ana, mii_anlpa, mii_ane, mii_extstat,
01898 mii_ms_ctrl, mii_ms_status, scr;
01899 u32_t oui;
01900 int model, rev;
01901 int f, link_up, ms_regs;
01902
01903
01904
01905
01906 ms_regs= 0;
01907
01908 fp->fxp_report_link= FALSE;
01909 port= fp->fxp_base_port;
01910
01911 scr= mii_read(fp, MII_SCR);
01912 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
01913 fp->fxp_mii_scr= scr;
01914
01915 mii_ctrl= mii_read(fp, MII_CTRL);
01916 mii_read(fp, MII_STATUS);
01917 mii_status= mii_read(fp, MII_STATUS);
01918 mii_id1= mii_read(fp, MII_PHYID_H);
01919 mii_id2= mii_read(fp, MII_PHYID_L);
01920 mii_ana= mii_read(fp, MII_ANA);
01921 mii_anlpa= mii_read(fp, MII_ANLPA);
01922 mii_ane= mii_read(fp, MII_ANE);
01923 if (mii_status & MII_STATUS_EXT_STAT)
01924 mii_extstat= mii_read(fp, MII_EXT_STATUS);
01925 else
01926 mii_extstat= 0;
01927 if (ms_regs)
01928 {
01929 mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
01930 mii_ms_status= mii_read(fp, MII_MS_STATUS);
01931 }
01932 else
01933 {
01934 mii_ms_ctrl= 0;
01935 mii_ms_status= 0;
01936 }
01937
01938
01939 link_up= !!(mii_status & MII_STATUS_LS);
01940
01941 fp->fxp_link_up= link_up;
01942 if (!link_up)
01943 {
01944 #if VERBOSE
01945 printf("%s: link down\n", fp->fxp_name);
01946 #endif
01947 return;
01948 }
01949
01950 oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) |
01951 ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
01952 model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
01953 rev= (mii_id2 & MII_PL_REV_MASK);
01954
01955 #if VERBOSE
01956 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
01957 #endif
01958
01959 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
01960 {
01961 printf("%s: PHY: ", fp->fxp_name);
01962 f= 1;
01963 if (mii_ctrl & MII_CTRL_LB)
01964 {
01965 printf("loopback mode");
01966 f= 0;
01967 }
01968 if (mii_ctrl & MII_CTRL_PD)
01969 {
01970 if (!f) printf(", ");
01971 f= 0;
01972 printf("powered down");
01973 }
01974 if (mii_ctrl & MII_CTRL_ISO)
01975 {
01976 if (!f) printf(", ");
01977 f= 0;
01978 printf("isolated");
01979 }
01980 printf("\n");
01981 return;
01982 }
01983 if (!(mii_ctrl & MII_CTRL_ANE))
01984 {
01985 printf("%s: manual config: ", fp->fxp_name);
01986 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
01987 {
01988 case MII_CTRL_SP_10: printf("10 Mbps"); break;
01989 case MII_CTRL_SP_100: printf("100 Mbps"); break;
01990 case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
01991 case MII_CTRL_SP_RES: printf("reserved speed"); break;
01992 }
01993 if (mii_ctrl & MII_CTRL_DM)
01994 printf(", full duplex");
01995 else
01996 printf(", half duplex");
01997 printf("\n");
01998 return;
01999 }
02000
02001 if (!debug) goto resspeed;
02002
02003 printf("%s: ", fp->fxp_name);
02004 mii_print_stat_speed(mii_status, mii_extstat);
02005 printf("\n");
02006
02007 if (!(mii_status & MII_STATUS_ANC))
02008 printf("%s: auto-negotiation not complete\n", fp->fxp_name);
02009 if (mii_status & MII_STATUS_RF)
02010 printf("%s: remote fault detected\n", fp->fxp_name);
02011 if (!(mii_status & MII_STATUS_ANA))
02012 {
02013 printf("%s: local PHY has no auto-negotiation ability\n",
02014 fp->fxp_name);
02015 }
02016 if (!(mii_status & MII_STATUS_LS))
02017 printf("%s: link down\n", fp->fxp_name);
02018 if (mii_status & MII_STATUS_JD)
02019 printf("%s: jabber condition detected\n", fp->fxp_name);
02020 if (!(mii_status & MII_STATUS_EC))
02021 {
02022 printf("%s: no extended register set\n", fp->fxp_name);
02023 goto resspeed;
02024 }
02025 if (!(mii_status & MII_STATUS_ANC))
02026 goto resspeed;
02027
02028 printf("%s: local cap.: ", fp->fxp_name);
02029 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
02030 {
02031 printf("1000 Mbps: T-");
02032 switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
02033 {
02034 case MII_MSC_1000T_FD: printf("FD"); break;
02035 case MII_MSC_1000T_HD: printf("HD"); break;
02036 default: printf("FD/HD"); break;
02037 }
02038 if (mii_ana)
02039 printf(", ");
02040 }
02041 mii_print_techab(mii_ana);
02042 printf("\n");
02043
02044 if (mii_ane & MII_ANE_PDF)
02045 printf("%s: parallel detection fault\n", fp->fxp_name);
02046 if (!(mii_ane & MII_ANE_LPANA))
02047 {
02048 printf("%s: link-partner does not support auto-negotiation\n",
02049 fp->fxp_name);
02050 goto resspeed;
02051 }
02052
02053 printf("%s: remote cap.: ", fp->fxp_name);
02054 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
02055 if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
02056 {
02057 printf("1000 Mbps: T-");
02058 switch(mii_ms_status &
02059 (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
02060 {
02061 case MII_MSS_LP1000T_FD: printf("FD"); break;
02062 case MII_MSS_LP1000T_HD: printf("HD"); break;
02063 default: printf("FD/HD"); break;
02064 }
02065 if (mii_anlpa)
02066 printf(", ");
02067 }
02068 mii_print_techab(mii_anlpa);
02069 printf("\n");
02070
02071 if (ms_regs)
02072 {
02073 printf("%s: ", fp->fxp_name);
02074 if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
02075 {
02076 printf("manual %s",
02077 (mii_ms_ctrl & MII_MSC_MS_VAL) ?
02078 "MASTER" : "SLAVE");
02079 }
02080 else
02081 {
02082 printf("%s device",
02083 (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
02084 "multiport" : "single-port");
02085 }
02086 if (mii_ms_ctrl & MII_MSC_RES)
02087 printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
02088 printf(": ");
02089 if (mii_ms_status & MII_MSS_FAULT)
02090 printf("M/S config fault");
02091 else if (mii_ms_status & MII_MSS_MASTER)
02092 printf("MASTER");
02093 else
02094 printf("SLAVE");
02095 printf("\n");
02096 }
02097
02098 if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
02099 {
02100 if (!(mii_ms_status & MII_MSS_LOCREC))
02101 {
02102 printf("%s: local receiver not OK\n",
02103 fp->fxp_name);
02104 }
02105 if (!(mii_ms_status & MII_MSS_REMREC))
02106 {
02107 printf("%s: remote receiver not OK\n",
02108 fp->fxp_name);
02109 }
02110 }
02111 if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
02112 {
02113 printf("%s", fp->fxp_name);
02114 if (mii_ms_status & MII_MSS_RES)
02115 printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
02116 if (mii_ms_status & MII_MSS_IDLE_ERR)
02117 {
02118 printf(" idle error %d",
02119 mii_ms_status & MII_MSS_IDLE_ERR);
02120 }
02121 printf("\n");
02122 }
02123
02124 resspeed:
02125 #if VERBOSE
02126 printf("%s: link up, %d Mbps, %s duplex\n",
02127 fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
02128 (scr & MII_SCR_FD) ? "full" : "half");
02129 #endif
02130 ;
02131 }
02132
02133
02134
02135
02136 static void fxp_stop()
02137 {
02138 int i;
02139 port_t port;
02140 fxp_t *fp;
02141
02142 for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
02143 {
02144 if (fp->fxp_mode != FM_ENABLED)
02145 continue;
02146 if (!(fp->fxp_flags & FF_ENABLED))
02147 continue;
02148 port= fp->fxp_base_port;
02149
02150
02151 if (debug)
02152 printf("%s: resetting device\n", fp->fxp_name);
02153 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
02154 }
02155 sys_exit(0);
02156 }
02157
02158
02159
02160
02161 static void reply(fp, err, may_block)
02162 fxp_t *fp;
02163 int err;
02164 int may_block;
02165 {
02166 message reply;
02167 int status;
02168 int r;
02169
02170 status = 0;
02171 if (fp->fxp_flags & FF_PACK_SENT)
02172 status |= DL_PACK_SEND;
02173 if (fp->fxp_flags & FF_PACK_RECV)
02174 status |= DL_PACK_RECV;
02175
02176 reply.m_type = DL_TASK_REPLY;
02177 reply.DL_PORT = fp - fxp_table;
02178 reply.DL_PROC = fp->fxp_client;
02179 reply.DL_STAT = status | ((u32_t) err << 16);
02180 reply.DL_COUNT = fp->fxp_read_s;
02181 #if 0
02182 reply.DL_CLCK = get_uptime();
02183 #else
02184 reply.DL_CLCK = 0;
02185 #endif
02186
02187 r= send(fp->fxp_client, &reply);
02188
02189 if (r == ELOCKED && may_block)
02190 {
02191 #if 0
02192 printW(); printf("send locked\n");
02193 #endif
02194 return;
02195 }
02196
02197 if (r < 0)
02198 panic("FXP","fxp: send failed:", r);
02199
02200 fp->fxp_read_s = 0;
02201 fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
02202 }
02203
02204
02205
02206
02207 static void mess_reply(req, reply_mess)
02208 message *req;
02209 message *reply_mess;
02210 {
02211 if (send(req->m_source, reply_mess) != OK)
02212 panic("FXP","fxp: unable to mess_reply", NO_NUM);
02213 }
02214
02215
02216
02217
02218 static void put_userdata(user_proc, user_addr, count, loc_addr)
02219 int user_proc;
02220 vir_bytes user_addr;
02221 vir_bytes count;
02222 void *loc_addr;
02223 {
02224 int r;
02225
02226 r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
02227 user_proc, D, user_addr, count);
02228 if (r != OK)
02229 panic("FXP","put_userdata: sys_vircopy failed", r);
02230 }
02231
02232
02233
02234
02235 PRIVATE u16_t eeprom_read(fp, reg)
02236 fxp_t *fp;
02237 int reg;
02238 {
02239 port_t port;
02240 u16_t v;
02241 int b, i, alen;
02242
02243 alen= fp->fxp_ee_addrlen;
02244 if (!alen)
02245 {
02246 eeprom_addrsize(fp);
02247 alen= fp->fxp_ee_addrlen;
02248 assert(alen == 6 || alen == 8);
02249 }
02250
02251 port= fp->fxp_base_port;
02252
02253 fxp_outb(port, CSR_EEPROM, CE_EECS);
02254 v= EEPROM_READ_PREFIX;
02255 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
02256 {
02257 b= ((v & (1 << i)) ? CE_EEDI : 0);
02258 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02259 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK);
02260 micro_delay(EESK_PERIOD/2+1);
02261 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02262 micro_delay(EESK_PERIOD/2+1);
02263 }
02264
02265 v= reg;
02266 for (i= alen-1; i >= 0; i--)
02267 {
02268 b= ((v & (1 << i)) ? CE_EEDI : 0);
02269 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02270 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK);
02271 micro_delay(EESK_PERIOD/2+1);
02272 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02273 micro_delay(EESK_PERIOD/2+1);
02274 }
02275
02276 v= 0;
02277 for (i= 0; i<16; i++)
02278 {
02279 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK);
02280 micro_delay(EESK_PERIOD/2+1);
02281 b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
02282 v= (v << 1) | b;
02283 fxp_outb(port, CSR_EEPROM, CE_EECS );
02284 micro_delay(EESK_PERIOD/2+1);
02285 }
02286 fxp_outb(port, CSR_EEPROM, 0);
02287 micro_delay(EECS_DELAY);
02288
02289 return v;
02290 }
02291
02292
02293
02294
02295 PRIVATE void eeprom_addrsize(fp)
02296 fxp_t *fp;
02297 {
02298 port_t port;
02299 u16_t v;
02300 int b, i;
02301
02302 port= fp->fxp_base_port;
02303
02304
02305 fxp_outb(port, CSR_EEPROM, CE_EECS);
02306 v= EEPROM_READ_PREFIX;
02307 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
02308 {
02309 b= ((v & (1 << i)) ? CE_EEDI : 0);
02310 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02311 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK);
02312 micro_delay(EESK_PERIOD/2+1);
02313 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02314 micro_delay(EESK_PERIOD/2+1);
02315 }
02316
02317 for (i= 0; i<32; i++)
02318 {
02319 b= 0;
02320 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02321 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK);
02322 micro_delay(EESK_PERIOD/2+1);
02323 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
02324 micro_delay(EESK_PERIOD/2+1);
02325 v= fxp_inb(port, CSR_EEPROM);
02326 if (!(v & CE_EEDO))
02327 break;
02328 }
02329 if (i >= 32)
02330 panic("FXP","eeprom_addrsize: failed", NO_NUM);
02331 fp->fxp_ee_addrlen= i+1;
02332
02333
02334 for (i= 0; i<16; i++)
02335 {
02336 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK);
02337 micro_delay(EESK_PERIOD/2+1);
02338 fxp_outb(port, CSR_EEPROM, CE_EECS );
02339 micro_delay(EESK_PERIOD/2+1);
02340 }
02341 fxp_outb(port, CSR_EEPROM, 0);
02342 micro_delay(EECS_DELAY);
02343
02344 #if VERBOSE
02345 printf("%s EEPROM address length: %d\n",
02346 fp->fxp_name, fp->fxp_ee_addrlen);
02347 #endif
02348 }
02349
02350
02351
02352
02353 PRIVATE u16_t mii_read(fp, reg)
02354 fxp_t *fp;
02355 int reg;
02356 {
02357 clock_t t0,t1;
02358 port_t port;
02359 u32_t v;
02360
02361 port= fp->fxp_base_port;
02362
02363 assert(!fp->fxp_mii_busy);
02364 fp->fxp_mii_busy++;
02365
02366 if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
02367 panic("FXP","mii_read: MDI not ready", NO_NUM);
02368 fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
02369 (reg << CM_REG_SHIFT));
02370
02371 getuptime(&t0);
02372 do {
02373 v= fxp_inl(port, CSR_MDI_CTL);
02374 if (v & CM_READY)
02375 break;
02376 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
02377
02378 if (!(v & CM_READY))
02379 panic("FXP","mii_read: MDI not ready after command", NO_NUM);
02380
02381 fp->fxp_mii_busy--;
02382 assert(!fp->fxp_mii_busy);
02383
02384 return v & CM_DATA_MASK;
02385 }
02386
02387
02388
02389
02390 PRIVATE void fxp_set_timer(tp, delta, watchdog)
02391 timer_t *tp;
02392 clock_t delta;
02393 tmr_func_t watchdog;
02394 {
02395 clock_t now;
02396 int r;
02397
02398
02399 r= getuptime(&now);
02400 if (r != OK)
02401 panic("FXP","unable to get uptime from clock", r);
02402
02403
02404 tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
02405
02406
02407
02408
02409 if (fxp_next_timeout == 0 ||
02410 fxp_timers->tmr_exp_time < fxp_next_timeout)
02411 {
02412 fxp_next_timeout= fxp_timers->tmr_exp_time;
02413 #if VERBOSE
02414 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
02415 fxp_next_timeout, fxp_next_timeout-now);
02416 #endif
02417 r= sys_setalarm(fxp_next_timeout, 1);
02418 if (r != OK)
02419 panic("FXP","unable to set synchronous alarm", r);
02420 }
02421 }
02422
02423
02424
02425
02426 PRIVATE void fxp_expire_timers()
02427 {
02428
02429
02430
02431 clock_t now;
02432 timer_t *tp;
02433 int r;
02434
02435
02436 r= getuptime(&now);
02437 if (r != OK)
02438 panic("FXP","Unable to get uptime from clock.", r);
02439
02440
02441
02442
02443 tmrs_exptimers(&fxp_timers, now, NULL);
02444 if (fxp_timers == NULL)
02445 fxp_next_timeout= TMR_NEVER;
02446 else
02447 {
02448 fxp_next_timeout = fxp_timers->tmr_exp_time;
02449 r= sys_setalarm(fxp_next_timeout, 1);
02450 if (r != OK)
02451 panic("FXP","Unable to set synchronous alarm.", r);
02452 }
02453 }
02454
02455 static void micro_delay(unsigned long usecs)
02456 {
02457 tickdelay(MICROS_TO_TICKS(usecs));
02458 }
02459
02460 static u8_t do_inb(port_t port)
02461 {
02462 int r;
02463 u32_t value;
02464
02465 r= sys_inb(port, &value);
02466 if (r != OK)
02467 panic("FXP","sys_inb failed", r);
02468 return value;
02469 }
02470
02471 static u32_t do_inl(port_t port)
02472 {
02473 int r;
02474 u32_t value;
02475
02476 r= sys_inl(port, &value);
02477 if (r != OK)
02478 panic("FXP","sys_inl failed", r);
02479 return value;
02480 }
02481
02482 static void do_outb(port_t port, u8_t value)
02483 {
02484 int r;
02485
02486 r= sys_outb(port, value);
02487 if (r != OK)
02488 panic("FXP","sys_outb failed", r);
02489 }
02490
02491 static void do_outl(port_t port, u32_t value)
02492 {
02493 int r;
02494
02495 r= sys_outl(port, value);
02496 if (r != OK)
02497 panic("FXP","sys_outl failed", r);
02498 }
02499
02500
02501
02502
02503