fxp.c

Go to the documentation of this file.
00001 /*
00002  * fxp.c
00003  *
00004  * This file contains an ethernet device driver for Intel 82557, 82558, 
00005  * 82559, 82550, and 82562 fast ethernet controllers.
00006  *
00007  * The valid messages and their parameters are:
00008  *
00009  *   m_type       DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
00010  * |------------+----------+---------+----------+---------+---------|
00011  * | HARDINT    |          |         |          |         |         |
00012  * |------------|----------|---------|----------|---------|---------|
00013  * | DL_WRITE   | port nr  | proc nr | count    | mode    | address |
00014  * |------------|----------|---------|----------|---------|---------|
00015  * | DL_WRITEV  | port nr  | proc nr | count    | mode    | address |
00016  * |------------|----------|---------|----------|---------|---------|
00017  * | DL_READ    | port nr  | proc nr | count    |         | address |
00018  * |------------|----------|---------|----------|---------|---------|
00019  * | DL_READV   | port nr  | proc nr | count    |         | address |
00020  * |------------|----------|---------|----------|---------|---------|
00021  * | DL_INIT    | port nr  | proc nr | mode     |         | address |
00022  * |------------|----------|---------|----------|---------|---------|
00023  * | DL_GETSTAT | port nr  | proc nr |          |         | address |
00024  * |------------|----------|---------|----------|---------|---------|
00025  * | DL_STOP    | port_nr  |         |          |         |         |
00026  * |------------|----------|---------|----------|---------|---------|
00027  *
00028  * The messages sent are:
00029  *
00030  *   m-type        DL_PORT    DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
00031  * |-------------+----------+---------+----------+---------+---------|
00032  * |DL_TASK_REPLY| port nr  | proc nr | rd-count | err|stat| clock   |
00033  * |-------------+----------+---------+----------+---------+---------|
00034  *
00035  *   m_type        m3_i1     m3_i2       m3_ca1
00036  * |-------------+---------+-----------+---------------|
00037  * |DL_INIT_REPLY| port nr | last port | ethernet addr |
00038  * |-------------+---------+-----------+---------------|
00039  *
00040  * Created:     Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
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 /* Number of receive buffers */
00066 #define N_RX_BUF        40
00067 
00068 /* Number of transmit buffers */
00069 #define N_TX_BUF        4
00070 
00071 /* I/O vectors are handled IOVEC_NR entries at a time. */
00072 #define IOVEC_NR        16
00073 
00074 /* Configuration */
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 },          /* Intel 82557, etc. */
00087         { 0x8086, 0x2449, 0 },          /* Intel 82801BA/BAM/CA/CAM */
00088 
00089         { 0x0000, 0x0000, 0 }
00090 };
00091 
00092 #define FXP_PORT_NR     1               /* Minix */
00093 
00094 typedef int irq_hook_t;
00095 
00096 /* Translate a pointer to a field in a structure to a pointer to the structure
00097  * itself.  So it translates '&struct_ptr->field' back to 'struct_ptr'.
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 /* ignore interrupt for the moment */
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;               /* Needed? */
00123         int fxp_irq;
00124         int fxp_type;                   /* What kind of hardware */
00125         int fxp_ee_addrlen;             /* #EEPROM address bits */
00126         int fxp_tx_alive;
00127         int fxp_need_reset;
00128 
00129         /* Rx */
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;              /* Re-configure after draining send
00138                                          * queue
00139                                          */
00140 
00141         /* Tx */
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         /* Link status */
00152         int fxp_report_link;
00153         int fxp_link_up;
00154         int fxp_mii_busy;
00155         u16_t fxp_mii_scr;
00156 
00157         /* PCI related */
00158         int fxp_seen;                   /* TRUE iff device available */
00159         u8_t fxp_pcibus;        
00160         u8_t fxp_pcidev;        
00161         u8_t fxp_pcifunc;       
00162 
00163         /* 'large' items */
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 /* fxp_mode */
00176 #define FM_DISABLED     0x0
00177 #define FM_ENABLED      0x1
00178 
00179 /* fxp_flags */
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 /* fxp_features */
00191 #define FFE_NONE        0x0
00192 
00193 /* fxp_type */
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  *                              main                                         *
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   /* What about memory allocation? */
00281         /* Claim buffer memory now under Minix, before MM takes it all. */
00282         for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)
00283                 fxp_init_buf(fp);
00284 #endif
00285 
00286         /* Try to notify inet that we are present (again) */
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  *                              fxp_init                                     *
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(); /* Configure PCI devices. */
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                 /* This is the default, try to (re)locate the device. */
00373                 fxp_conf_hw(fp);
00374                 if (fp->fxp_mode == FM_DISABLED)
00375                 {
00376                         /* Probe failed, or the device is configured off. */
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  *                              fxp_pci_conf                                 *
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  *                              fxp_probe                                    *
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                 /* Look for specific PCI device */
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";                  /* 0x01 */
00576                                 fp->fxp_type= FT_82557;
00577                                 break;
00578         case FXP_REV_82557B:    str= "82557B"; break;           /* 0x02 */
00579         case FXP_REV_82557C:    str= "82557C"; break;           /* 0x03 */
00580         case FXP_REV_82558A:    str= "82558A";                  /* 0x04 */
00581                                 fp->fxp_type= FT_82558A;
00582                                 break;
00583         case FXP_REV_82558B:    str= "82558B"; break;           /* 0x05 */
00584         case FXP_REV_82559A:    str= "82559A"; break;           /* 0x06 */
00585         case FXP_REV_82559B:    str= "82559B"; break;           /* 0x07 */
00586         case FXP_REV_82559C:    str= "82559C";                  /* 0x08 */
00587                                 fp->fxp_type= FT_82559;
00588                                 break;
00589         case FXP_REV_82559ERA:  str= "82559ER-A";               /* 0x09 */
00590                                 fp->fxp_type= FT_82559;
00591                                 break;
00592         case FXP_REV_82550_1:   str= "82550(1)";                /* 0x0C */
00593                                 fp->fxp_type= FT_82559;
00594                                 break;
00595         case FXP_REV_82550_2:   str= "82550(2)";                /* 0x0D */
00596                                 fp->fxp_type= FT_82559;
00597                                 break;
00598         case FXP_REV_82550_3:   str= "82550(3)";                /* 0x0E */
00599                                 fp->fxp_type= FT_82559;
00600                                 break;
00601         case FXP_REV_82551_1:   str= "82551(1)";                /* 0x0F */
00602                                 fp->fxp_type= FT_82559;
00603                                 break;
00604         case FXP_REV_82551_2:   str= "82551(2)";                /* 0x10 */
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  *                              fxp_conf_hw                                  *
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;      /* Superfluous */
00635 
00636         if (!fp->fxp_seen)
00637                 return;
00638 
00639         /* PCI device is present */
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;  /* Unknown */
00646         fp->fxp_need_reset= 0;
00647         fp->fxp_report_link= 0;
00648         fp->fxp_link_up= -1;    /* Unknown */
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         /* Try to come up with a sensible configuration for the current
00659          * device. Unfortunately every device is different, defaults are
00660          * not always zero, and some fields are re-used with a completely
00661          * different interpretation. We start out with a sensible default
00662          * for all devices and then add device specific changes.
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;         /* Do we want "Memory Write and Invalidate"? */
00695         ext_stat1= 0;   /* Do we want extended statistical counters? */
00696         ext_stat2= 0;   /* Do we want even more statistical counters? */
00697         lim_fifo= 0;    /* Limit number of frame in TX FIFO */
00698         i82503= 0;      /* Older 10 Mbps interface on the 82557 */
00699         fc= 0;          /* Flow control */
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                         /* From FreeBSD driver */
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  *                              fxp_init_hw                                  *
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         /* Set the interrupt handler and policy. Do not automatically 
00761          * reenable interrupts. Return the IRQ line number on interrupts.
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         /* Reset PHY? */
00775 
00776         fxp_do_conf(fp);
00777 
00778         /* Set pointer to statistical counters */
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 /* check idle */);
00784 
00785         /* Ack previous interrupts */
00786         isr= fxp_inb(port, SCB_INT_STAT);
00787         fxp_outb(port, SCB_INT_STAT, isr);
00788 
00789         /* Enable interrupts */
00790         fxp_outb(port, SCB_INT_MASK, 0);
00791 
00792         fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
00793                 TRUE /* check idle */);
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  *                              fxp_init_buf                                 *
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         /* What about memory allocation? */
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;      /* Just in case */
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  *                              fxp_reset_hw                                 *
00902  *===========================================================================*/
00903 static void fxp_reset_hw(fp)
00904 fxp_t *fp;
00905 {
00906 /* Inline the function in init? */
00907         port_t port;
00908 
00909         port= fp->fxp_base_port;
00910 
00911         /* Reset device */
00912         fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
00913         tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
00914 
00915         /* Disable interrupts */
00916         fxp_outb(port, SCB_INT_MASK, SIM_M);
00917 
00918         /* Set CU base to zero */
00919         fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
00920 
00921         /* Set RU base to zero */
00922         fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
00923 }
00924 
00925 /*===========================================================================*
00926  *                              fxp_confaddr                                 *
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         /* User defined ethernet address? */
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); /* It's all or nothing */
00958 #endif
00959 
00960         if (i == 0)
00961         {
00962                 /* Get ethernet address from EEPROM */
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         /* Tell NIC about ethernet address */
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 /* check idle */);
00983 
00984         getuptime(&t0);
00985         do {
00986                 /* Wait for CU command to complete */
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  *                              fxp_rec_mode                                 *
01009  *===========================================================================*/
01010 static void fxp_rec_mode(fp)
01011 fxp_t *fp;
01012 {
01013         fp->fxp_conf_bytes[0]= CC_BYTES_NR;     /* Just to be sure */
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         /* Queue request if not idle */
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  *                              fxp_writev                                   *
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; /* lint */
01075                 prev_txp= NULL; /* lint */
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                         /* Send queue is full */
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 /* check idle */);
01169         }
01170         else
01171         {
01172                 /* Link new request in transmit list */
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         /* If the interrupt handler called, don't send a reply. The reply
01182          * will be sent after all interrupts are handled. 
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  *                              fxp_readv                                    *
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                 /* Receive buffer is empty, suspend */
01237                 goto suspend;
01238         }
01239 
01240         if (!rfd_status & RFDS_OK)
01241         {
01242                 /* Not OK? What happened? */
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         /* Re-init the current buffer */
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                 /* Check the status of the RU */
01349                 scb_status= fxp_inb(port, SCB_STATUS);
01350                 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
01351                 {
01352                         /* Race condition? */
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                 /* No need to store any state */
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  *                              fxp_do_conf                                  *
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         /* Configure device */
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 /* check idle */);
01400 
01401         getuptime(&t0);
01402         do {
01403                 /* Wait for CU command to complete */
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  *                              fxp_cu_ptr_cmd                               *
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                 /* Consistency check. Make sure that CU is idle */
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         /* What is a reasonable time-out? There is nothing in the
01441          * documentation. 1 ms should be enough.
01442          */
01443         getuptime(&t0);
01444         do {
01445                 /* Wait for CU command to be accepted */
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  *                              fxp_ru_ptr_cmd                               *
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                 /* Consistency check, make sure that RU is idle */
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                 /* Wait for RU command to be accepted */
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  *                              fxp_restart_ru                               *
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         /* Make sure that RU is in the 'No resources' state */
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 /* do not check idle */);
01523 }
01524 
01525 /*===========================================================================*
01526  *                              fxp_getstat                                  *
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         /* The dump commmand doesn't take a pointer. Setting a pointer
01553          * doesn't hard though.
01554          */
01555         fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
01556 
01557         getuptime(&t0);
01558         do {
01559                 /* Wait for CU command to complete */
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  *                              fxp_getname                                  *
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  *                              fxp_handler                                  *
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         /* Ack interrupt */
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                 /* Assume that receive buffer is full of packets. fxp_readv
01662                  * will restart the RU.
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  *                              fxp_check_ints                               *
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                         ; /* Nothing */
01695                 else if (fp->fxp_rx_mess.m_type == DL_READV)
01696                 {
01697                         fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
01698                                 TRUE /* vectored */);
01699                 }
01700                 else
01701                 {
01702                         assert(fp->fxp_rx_mess.m_type == DL_READ);
01703                         fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
01704                                 FALSE /* !vectored */);
01705                 }
01706         }
01707         if (fp->fxp_tx_idle)
01708                 ;       /* Nothing to do */
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                         /* Check the status of the CU */
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                                 /* Nothing to do */
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                                 /* Check the status of the CU */
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                                         /* Nothing to do */
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 /* check idle */);
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 /* from int */,
01804                                                 TRUE /* vectored */);
01805                                 }
01806                                 else
01807                                 {
01808                                         assert(fp->fxp_tx_mess.m_type ==
01809                                                 DL_WRITE);
01810                                         fxp_writev(&fp->fxp_tx_mess,
01811                                                 TRUE /* from int */,
01812                                                 FALSE /* !vectored */);
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  *                              fxp_watchdog_f                               *
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                 /* Handle race condition, MII interface mgith be busy */
01843                 if(!fp->fxp_mii_busy)
01844                 {
01845                         /* Check the link status. */
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                         /* Assume that an idle system is alive */
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  *                              fxp_link_changed                             *
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  *                              fxp_report_link                              *
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         /* Assume an 82555 (compatible) PHY. The should be changed for
01904          * 82557 NICs with different PHYs
01905          */
01906         ms_regs= 0;     /* No master/slave registers. */
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); /* Read the status register twice, why? */
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         /* How do we know about the link status? */
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  *                              fxp_stop                                     *
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                 /* Reset device */
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  *                              reply                                        *
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  *                              mess_reply                                   *
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  *                              put_userdata                                 *
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  *                              eeprom_read                                  *
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);    /* Enable EEPROM */
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);        /* bit */
02259                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
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);        /* bit */
02270                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
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); /* Clock */
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);  /* Disable EEPROM */
02287         micro_delay(EECS_DELAY);
02288 
02289         return v;
02290 }
02291 
02292 /*===========================================================================*
02293  *                              eeprom_addrsize                              *
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         /* Try to find out the size of the EEPROM */
02305         fxp_outb(port, CSR_EEPROM, CE_EECS);    /* Enable EEPROM */
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);        /* bit */
02311                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
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);        /* bit */
02321                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
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         /* Discard 16 data bits */
02334         for (i= 0; i<16; i++)
02335         {
02336                 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
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);  /* Disable EEPROM */
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  *                              mii_read                                     *
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  *                              fxp_set_timer                                *
02389  *===========================================================================*/
02390 PRIVATE void fxp_set_timer(tp, delta, watchdog)
02391 timer_t *tp;                            /* timer to be set */
02392 clock_t delta;                          /* in how many ticks */
02393 tmr_func_t watchdog;                    /* watchdog function to be called */
02394 {
02395         clock_t now;                            /* current time */
02396         int r;
02397 
02398         /* Get the current time. */
02399         r= getuptime(&now);
02400         if (r != OK)
02401                 panic("FXP","unable to get uptime from clock", r);
02402 
02403         /* Add the timer to the local timer queue. */
02404         tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
02405 
02406         /* Possibly reschedule an alarm call. This happens when a new timer
02407          * is added in front. 
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  *                              fxp_expire_tmrs                              *
02425  *===========================================================================*/
02426 PRIVATE void fxp_expire_timers()
02427 {
02428 /* A synchronous alarm message was received. Check if there are any expired 
02429  * timers. Possibly reschedule the next alarm.  
02430  */
02431   clock_t now;                          /* current time */
02432   timer_t *tp;
02433   int r;
02434 
02435   /* Get the current time to compare the timers against. */
02436   r= getuptime(&now);
02437   if (r != OK)
02438         panic("FXP","Unable to get uptime from clock.", r);
02439 
02440   /* Scan the timers queue for expired timers. Dispatch the watchdog function
02441    * for each expired timers. Possibly a new alarm call must be scheduled.
02442    */
02443   tmrs_exptimers(&fxp_timers, now, NULL);
02444   if (fxp_timers == NULL)
02445         fxp_next_timeout= TMR_NEVER;
02446   else
02447   {                                       /* set new alarm */
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  * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $
02502  */
02503 

Generated on Fri Apr 14 22:57:16 2006 for minix by  doxygen 1.4.6