dp8390.c

Go to the documentation of this file.
00001 /*
00002  * dp8390.c
00003  *
00004  * This file contains a ethernet device driver for NS dp8390 based ethernet
00005  * cards.
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:     before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
00041  *
00042  * Modified Mar 10 1994 by Philip Homburg
00043  *      Become a generic dp8390 driver.
00044  *
00045  * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
00046  *      Added support for 3c503 boards.
00047  */
00048 
00049 #include "../drivers.h"
00050 
00051 #include <stdlib.h>
00052 #include <minix/com.h>
00053 #include <net/hton.h>
00054 #include <net/gen/ether.h>
00055 #include <net/gen/eth_io.h>
00056 #include "assert.h"
00057 
00058 #include "local.h"
00059 #include "dp8390.h"
00060 
00061 #define DE_PORT_NR      3
00062 
00063 static dpeth_t de_table[DE_PORT_NR];
00064 static u16_t eth_ign_proto;
00065 static char *progname;
00066 
00067 /* Configuration */
00068 typedef struct dp_conf
00069 {
00070         port_t dpc_port;
00071         int dpc_irq;
00072         phys_bytes dpc_mem;
00073         char *dpc_envvar;
00074 } dp_conf_t;
00075 
00076 dp_conf_t dp_conf[]=    /* Card addresses */
00077 {
00078         /* I/O port, IRQ,  Buffer address,  Env. var. */
00079         {  0x280,     3,    0xD0000,        "DPETH0"    },
00080         {  0x300,     5,    0xC8000,        "DPETH1"    },
00081         {  0x380,    10,    0xD8000,        "DPETH2"    },
00082 };
00083 
00084 /* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
00085  * the error: "array size is negative".
00086  */
00087 extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
00088 
00089 /* Card inits configured out? */
00090 #if !ENABLE_WDETH
00091 #define wdeth_probe(dep)        (0)
00092 #endif
00093 #if !ENABLE_NE2000
00094 #define ne_probe(dep)           (0)
00095 #endif
00096 #if !ENABLE_3C503
00097 #define el2_probe(dep)          (0)
00098 #endif
00099 
00100 /* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
00101  * on writes to the CR register. Additional CR_STAs do not appear to hurt
00102  * genuine dp8390s
00103  */
00104 #define CR_EXTRA        CR_STA
00105 
00106 #if ENABLE_PCI
00107 _PROTOTYPE( static void pci_conf, (void)                                );
00108 #endif
00109 _PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
00110                                                         int vectored)   );
00111 _PROTOTYPE( static void do_vread, (message *mp, int vectored)           );
00112 _PROTOTYPE( static void do_init, (message *mp)                          );
00113 _PROTOTYPE( static void do_int, (dpeth_t *dep)                          );
00114 _PROTOTYPE( static void do_getstat, (message *mp)                       );
00115 _PROTOTYPE( static void do_getname, (message *mp)                       );
00116 _PROTOTYPE( static void do_stop, (message *mp)                          );
00117 _PROTOTYPE( static void dp_init, (dpeth_t *dep)                         );
00118 _PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)                     );
00119 _PROTOTYPE( static void dp_reinit, (dpeth_t *dep)                       );
00120 _PROTOTYPE( static void dp_reset, (dpeth_t *dep)                        );
00121 _PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)                   );
00122 _PROTOTYPE( static void dp_recv, (dpeth_t *dep)                         );
00123 _PROTOTYPE( static void dp_send, (dpeth_t *dep)                         );
00124 _PROTOTYPE( static void dp8390_stop, (void)                             );
00125 _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
00126                                 size_t offset, size_t size, void *dst)  );
00127 _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
00128                                 size_t offset, size_t size, void *dst)  );
00129 _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
00130                                 size_t offset, size_t size, void *dst)  );
00131 _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
00132                                                         int length)     );
00133 _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, 
00134                 vir_bytes offset, int nic_addr, vir_bytes count)        );
00135 _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
00136                                 iovec_dat_t *iovp, vir_bytes offset,
00137                                 int nic_addr, vir_bytes count)          );
00138 _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
00139                                 iovec_dat_t *iovp, vir_bytes offset,
00140                                 int nic_addr, vir_bytes count)          );
00141 _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr, 
00142                 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
00143 _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, 
00144                 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
00145 _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, 
00146                 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
00147 _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)              );
00148 _PROTOTYPE( static void conf_hw, (dpeth_t *dep)                         );
00149 _PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)     );
00150 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)             );
00151 _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)   );
00152 _PROTOTYPE( static void mess_reply, (message *req, message *reply)      );
00153 _PROTOTYPE( static void get_userdata, (int user_proc,
00154                 vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
00155 _PROTOTYPE( static void put_userdata, (int user_proc,
00156                 vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
00157 _PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)                             );
00158 _PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)                             );
00159 _PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
00160                                         vir_bytes buf, size_t size)     );
00161 _PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
00162                                         vir_bytes buf, size_t size)     );
00163 _PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
00164                                         vir_bytes buf, size_t size)     );
00165 _PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
00166                                         vir_bytes buf, size_t size)     );
00167 
00168 /*===========================================================================*
00169  *                              dpeth_task                                   *
00170  *===========================================================================*/
00171 int main(int argc, char *argv[])
00172 {
00173         message m;
00174         int i, irq, r, tasknr;
00175         dpeth_t *dep;
00176         long v;
00177 
00178         if (argc < 1)
00179         {
00180                 panic("DP8390",
00181                         "A head which at this time has no name", NO_NUM);
00182         }
00183         (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
00184 
00185         env_setargs(argc, argv);
00186 
00187         for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
00188         {
00189                 strcpy(dep->de_name, "dp8390#0");
00190                 dep->de_name[7] += i;
00191         }
00192 
00193         v= 0;
00194         (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
00195         eth_ign_proto= htons((u16_t) v);
00196 
00197         /* Try to notify inet that we are present (again) */
00198         r = _pm_findproc("inet", &tasknr);
00199         if (r == OK)
00200                 notify(tasknr);
00201 
00202         while (TRUE)
00203         {
00204                 if ((r= receive(ANY, &m)) != OK)
00205                         panic("", "dp8390: receive failed", r);
00206 
00207                 switch (m.m_type)
00208                 {
00209                 case DEV_PING:  notify(m.m_source);             continue;
00210                 case DL_WRITE:  do_vwrite(&m, FALSE, FALSE);    break;
00211                 case DL_WRITEV: do_vwrite(&m, FALSE, TRUE);     break;
00212                 case DL_READ:   do_vread(&m, FALSE);            break;
00213                 case DL_READV:  do_vread(&m, TRUE);             break;
00214                 case DL_INIT:   do_init(&m);                    break;
00215                 case DL_GETSTAT: do_getstat(&m);                break;
00216                 case DL_GETNAME: do_getname(&m);                break;
00217                 case DL_STOP:   do_stop(&m);                    break;
00218                 case HARD_INT:
00219                         for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
00220                         {
00221                                 if (dep->de_mode != DEM_ENABLED)
00222                                         continue;
00223                                 assert(dep->de_flags & DEF_ENABLED);
00224                                 irq= dep->de_irq;
00225                                 assert(irq >= 0 && irq < NR_IRQ_VECTORS);
00226                                 if (dep->de_int_pending || 1)
00227                                 {
00228                                         dep->de_int_pending= 0;
00229                                         dp_check_ints(dep);
00230                                         do_int(dep);
00231                                         r= sys_irqenable(&dep->de_hook);
00232                                         if (r != OK)
00233                                         {
00234                                                 panic("DP8390", 
00235                                                 "unable enable interrupts", r);
00236                                         }
00237                                 }
00238                         }
00239                         break;
00240                 case SYS_SIG:   {
00241                         sigset_t sigset = m.NOTIFY_ARG;
00242                         if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();
00243                         break;
00244                 }
00245                 case SYN_ALARM:
00246                         printf("dp8390: strange, got SYN_ALARM\n");
00247                         break;
00248                 case PROC_EVENT:
00249                         break;
00250                 default:
00251                         panic("", "dp8390: illegal message", m.m_type);
00252                 }
00253         }
00254 }
00255 
00256 #if 0
00257 /*===========================================================================*
00258  *                              dp8390_dump                                  *
00259  *===========================================================================*/
00260 void dp8390_dump()
00261 {
00262         dpeth_t *dep;
00263         int i, isr;
00264 
00265         printf("\n");
00266         for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
00267         {
00268 #if XXX
00269                 if (dep->de_mode == DEM_DISABLED)
00270                         printf("dp8390 port %d is disabled\n", i);
00271                 else if (dep->de_mode == DEM_SINK)
00272                         printf("dp8390 port %d is in sink mode\n", i);
00273 #endif
00274 
00275                 if (dep->de_mode != DEM_ENABLED)
00276                         continue;
00277 
00278                 printf("dp8390 statistics of port %d:\n", i);
00279 
00280                 printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
00281                 printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
00282                 printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
00283 
00284                 printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
00285                 printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
00286                 printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
00287 
00288                 printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
00289                 printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
00290                 printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
00291 
00292                 printf("collision  :%8ld\t", dep->de_stat.ets_collision);
00293                 printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
00294                 printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
00295 
00296                 printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
00297                 printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
00298                 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
00299 
00300                 printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
00301 
00302                 isr= inb_reg0(dep, DP_ISR);
00303                 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
00304                                         inb_reg0(dep, DP_ISR), dep->de_flags);
00305         }
00306 }
00307 #endif
00308 
00309 /*===========================================================================*
00310  *                              dp8390_stop                                  *
00311  *===========================================================================*/
00312 static void dp8390_stop()
00313 {
00314         message mess;
00315         int i;
00316 
00317         for (i= 0; i<DE_PORT_NR; i++)
00318         {
00319                 if (de_table[i].de_mode != DEM_ENABLED)
00320                         continue;
00321                 mess.m_type= DL_STOP;
00322                 mess.DL_PORT= i;
00323                 do_stop(&mess);
00324         }
00325 }
00326 
00327 #if ENABLE_PCI
00328 /*===========================================================================*
00329  *                              pci_conf                                     *
00330  *===========================================================================*/
00331 static void pci_conf()
00332 {
00333         int i, h;
00334         char *envvar;
00335         struct dpeth *dep;
00336         static char envfmt[] = "*:d.d.d";
00337         long v;
00338         static int first_time= 1;
00339 
00340         if (!first_time)
00341                 return;
00342         first_time= 0;
00343 
00344         for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
00345         {
00346                 envvar= dp_conf[i].dpc_envvar;
00347                 if (!(dep->de_pci= env_prefix(envvar, "pci")))
00348                         continue;       /* no PCI config */
00349                 v= 0;
00350                 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
00351                 dep->de_pcibus= v;
00352                 v= 0;
00353                 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
00354                 dep->de_pcidev= v;
00355                 v= 0;
00356                 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
00357                 dep->de_pcifunc= v;
00358         }
00359 
00360         for (h= 1; h >= 0; h--) {
00361                 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
00362                 {
00363                         if (!dep->de_pci)
00364                                 continue;
00365                         if (((dep->de_pcibus | dep->de_pcidev |
00366                                 dep->de_pcifunc) != 0) != h)
00367                         {
00368                                 continue;
00369                         }
00370                         if (!rtl_probe(dep))
00371                                 dep->de_pci= -1;
00372                 }
00373         }
00374 }
00375 #endif /* ENABLE_PCI */
00376 
00377 /*===========================================================================*
00378  *                              do_vwrite                                    *
00379  *===========================================================================*/
00380 static void do_vwrite(mp, from_int, vectored)
00381 message *mp;
00382 int from_int;
00383 int vectored;
00384 {
00385         int port, count, size;
00386         int sendq_head;
00387         dpeth_t *dep;
00388 
00389         port = mp->DL_PORT;
00390         count = mp->DL_COUNT;
00391         if (port < 0 || port >= DE_PORT_NR)
00392                 panic("", "dp8390: illegal port", port);
00393         dep= &de_table[port];
00394         dep->de_client= mp->DL_PROC;
00395 
00396         if (dep->de_mode == DEM_SINK)
00397         {
00398                 assert(!from_int);
00399                 dep->de_flags |= DEF_PACK_SEND;
00400                 reply(dep, OK, FALSE);
00401                 return;
00402         }
00403         assert(dep->de_mode == DEM_ENABLED);
00404         assert(dep->de_flags & DEF_ENABLED);
00405         if (dep->de_flags & DEF_SEND_AVAIL)
00406                 panic("", "dp8390: send already in progress", NO_NUM);
00407 
00408         sendq_head= dep->de_sendq_head;
00409         if (dep->de_sendq[sendq_head].sq_filled)
00410         {
00411                 if (from_int)
00412                         panic("", "dp8390: should not be sending\n", NO_NUM);
00413                 dep->de_sendmsg= *mp;
00414                 dep->de_flags |= DEF_SEND_AVAIL;
00415                 reply(dep, OK, FALSE);
00416                 return;
00417         }
00418         assert(!(dep->de_flags & DEF_PACK_SEND));
00419 
00420         if (vectored)
00421         {
00422                 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00423                         (count > IOVEC_NR ? IOVEC_NR : count) *
00424                         sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
00425                 dep->de_write_iovec.iod_iovec_s = count;
00426                 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
00427                 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
00428 
00429                 dep->de_tmp_iovec = dep->de_write_iovec;
00430                 size = calc_iovec_size(&dep->de_tmp_iovec);
00431         }
00432         else
00433         {  
00434                 dep->de_write_iovec.iod_iovec[0].iov_addr =
00435                         (vir_bytes) mp->DL_ADDR;
00436                 dep->de_write_iovec.iod_iovec[0].iov_size =
00437                         mp->DL_COUNT;
00438                 dep->de_write_iovec.iod_iovec_s = 1;
00439                 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
00440                 dep->de_write_iovec.iod_iovec_addr = 0;
00441                 size= mp->DL_COUNT;
00442         }
00443         if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
00444         {
00445                 panic("", "dp8390: invalid packet size", size);
00446         }
00447         (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
00448                 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
00449                 size);
00450         dep->de_sendq[sendq_head].sq_filled= TRUE;
00451         if (dep->de_sendq_tail == sendq_head)
00452         {
00453                 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
00454                 outb_reg0(dep, DP_TBCR1, size >> 8);
00455                 outb_reg0(dep, DP_TBCR0, size & 0xff);
00456                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
00457         }
00458         else
00459                 dep->de_sendq[sendq_head].sq_size= size;
00460         
00461         if (++sendq_head == dep->de_sendq_nr)
00462                 sendq_head= 0;
00463         assert(sendq_head < SENDQ_NR);
00464         dep->de_sendq_head= sendq_head;
00465 
00466         dep->de_flags |= DEF_PACK_SEND;
00467 
00468         /* If the interrupt handler called, don't send a reply. The reply
00469          * will be sent after all interrupts are handled. 
00470          */
00471         if (from_int)
00472                 return;
00473         reply(dep, OK, FALSE);
00474 
00475         assert(dep->de_mode == DEM_ENABLED);
00476         assert(dep->de_flags & DEF_ENABLED);
00477 }
00478 
00479 /*===========================================================================*
00480  *                              do_vread                                     *
00481  *===========================================================================*/
00482 static void do_vread(mp, vectored)
00483 message *mp;
00484 int vectored;
00485 {
00486         int port, count;
00487         int size;
00488         dpeth_t *dep;
00489 
00490         port = mp->DL_PORT;
00491         count = mp->DL_COUNT;
00492         if (port < 0 || port >= DE_PORT_NR)
00493                 panic("", "dp8390: illegal port", port);
00494         dep= &de_table[port];
00495         dep->de_client= mp->DL_PROC;
00496         if (dep->de_mode == DEM_SINK)
00497         {
00498                 reply(dep, OK, FALSE);
00499                 return;
00500         }
00501         assert(dep->de_mode == DEM_ENABLED);
00502         assert(dep->de_flags & DEF_ENABLED);
00503 
00504         if(dep->de_flags & DEF_READING)
00505                 panic("", "dp8390: read already in progress", NO_NUM);
00506 
00507         if (vectored)
00508         {
00509                 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00510                         (count > IOVEC_NR ? IOVEC_NR : count) *
00511                         sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
00512                 dep->de_read_iovec.iod_iovec_s = count;
00513                 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
00514                 dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
00515 
00516                 dep->de_tmp_iovec = dep->de_read_iovec;
00517                 size= calc_iovec_size(&dep->de_tmp_iovec);
00518         }
00519         else
00520         {
00521                 dep->de_read_iovec.iod_iovec[0].iov_addr =
00522                         (vir_bytes) mp->DL_ADDR;
00523                 dep->de_read_iovec.iod_iovec[0].iov_size =
00524                         mp->DL_COUNT;
00525                 dep->de_read_iovec.iod_iovec_s = 1;
00526                 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
00527                 dep->de_read_iovec.iod_iovec_addr = 0;
00528                 size= count;
00529         }
00530         if (size < ETH_MAX_PACK_SIZE_TAGGED)
00531                 panic("", "dp8390: wrong packet size", size);
00532         dep->de_flags |= DEF_READING;
00533 
00534         dp_recv(dep);
00535 
00536         if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
00537                 (DEF_READING|DEF_STOPPED))
00538         {
00539                 /* The chip is stopped, and all arrived packets are 
00540                  * delivered.
00541                  */
00542                 dp_reset(dep);
00543         }
00544         reply(dep, OK, FALSE);
00545 }
00546 
00547 /*===========================================================================*
00548  *                              do_init                                      *
00549  *===========================================================================*/
00550 static void do_init(mp)
00551 message *mp;
00552 {
00553         int port;
00554         dpeth_t *dep;
00555         message reply_mess;
00556 
00557 #if ENABLE_PCI
00558         pci_conf(); /* Configure PCI devices. */
00559 #endif
00560 
00561         port = mp->DL_PORT;
00562         if (port < 0 || port >= DE_PORT_NR)
00563         {
00564                 reply_mess.m_type= DL_INIT_REPLY;
00565                 reply_mess.m3_i1= ENXIO;
00566                 mess_reply(mp, &reply_mess);
00567                 return;
00568         }
00569         dep= &de_table[port];
00570         if (dep->de_mode == DEM_DISABLED)
00571         {
00572                 /* This is the default, try to (re)locate the device. */
00573                 conf_hw(dep);
00574                 if (dep->de_mode == DEM_DISABLED)
00575                 {
00576                         /* Probe failed, or the device is configured off. */
00577                         reply_mess.m_type= DL_INIT_REPLY;
00578                         reply_mess.m3_i1= ENXIO;
00579                         mess_reply(mp, &reply_mess);
00580                         return;
00581                 }
00582                 if (dep->de_mode == DEM_ENABLED)
00583                         dp_init(dep);
00584         }
00585 
00586         if (dep->de_mode == DEM_SINK)
00587         {
00588                 strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
00589                 dep->de_address.ea_addr[5] = port;
00590                 dp_confaddr(dep);
00591                 reply_mess.m_type = DL_INIT_REPLY;
00592                 reply_mess.m3_i1 = mp->DL_PORT;
00593                 reply_mess.m3_i2 = DE_PORT_NR;
00594                 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
00595                 mess_reply(mp, &reply_mess);
00596                 return;
00597         }
00598         assert(dep->de_mode == DEM_ENABLED);
00599         assert(dep->de_flags & DEF_ENABLED);
00600 
00601         dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
00602 
00603         if (mp->DL_MODE & DL_PROMISC_REQ)
00604                 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
00605         if (mp->DL_MODE & DL_MULTI_REQ)
00606                 dep->de_flags |= DEF_MULTI;
00607         if (mp->DL_MODE & DL_BROAD_REQ)
00608                 dep->de_flags |= DEF_BROAD;
00609 
00610         dep->de_client = mp->m_source;
00611         dp_reinit(dep);
00612 
00613         reply_mess.m_type = DL_INIT_REPLY;
00614         reply_mess.m3_i1 = mp->DL_PORT;
00615         reply_mess.m3_i2 = DE_PORT_NR;
00616         *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
00617 
00618         mess_reply(mp, &reply_mess);
00619 }
00620 
00621 /*===========================================================================*
00622  *                              do_int                                       *
00623  *===========================================================================*/
00624 static void do_int(dep)
00625 dpeth_t *dep;
00626 {
00627         if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
00628                 reply(dep, OK, TRUE);
00629 }
00630 
00631 /*===========================================================================*
00632  *                              do_getstat                                   *
00633  *===========================================================================*/
00634 static void do_getstat(mp)
00635 message *mp;
00636 {
00637         int port;
00638         dpeth_t *dep;
00639 
00640         port = mp->DL_PORT;
00641         if (port < 0 || port >= DE_PORT_NR)
00642                 panic("", "dp8390: illegal port", port);
00643         dep= &de_table[port];
00644         dep->de_client= mp->DL_PROC;
00645         if (dep->de_mode == DEM_SINK)
00646         {
00647                 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00648                         (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
00649                 reply(dep, OK, FALSE);
00650                 return;
00651         }
00652         assert(dep->de_mode == DEM_ENABLED);
00653         assert(dep->de_flags & DEF_ENABLED);
00654 
00655         dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
00656         dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
00657         dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
00658 
00659         put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00660                 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
00661         reply(dep, OK, FALSE);
00662 }
00663 
00664 /*===========================================================================*
00665  *                              do_getname                                   *
00666  *===========================================================================*/
00667 static void do_getname(mp)
00668 message *mp;
00669 {
00670         int r;
00671 
00672         strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
00673         mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
00674         mp->m_type= DL_NAME_REPLY;
00675         r= send(mp->m_source, mp);
00676         if (r != OK)
00677                 panic("dp8390", "do_getname: send failed: %d\n", r);
00678 }
00679 
00680 /*===========================================================================*
00681  *                              do_stop                                      *
00682  *===========================================================================*/
00683 static void do_stop(mp)
00684 message *mp;
00685 {
00686         int port;
00687         dpeth_t *dep;
00688 
00689         port = mp->DL_PORT;
00690 
00691         if (port < 0 || port >= DE_PORT_NR)
00692                 panic("", "dp8390: illegal port", port);
00693         dep= &de_table[port];
00694         if (dep->de_mode == DEM_SINK)
00695                 return;
00696         assert(dep->de_mode == DEM_ENABLED);
00697 
00698         if (!(dep->de_flags & DEF_ENABLED))
00699                 return;
00700 
00701         outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
00702         (dep->de_stopf)(dep);
00703 
00704         dep->de_flags= DEF_EMPTY;
00705 }
00706 
00707 /*===========================================================================*
00708  *                              dp_init                                      *
00709  *===========================================================================*/
00710 static void dp_init(dep)
00711 dpeth_t *dep;
00712 {
00713         int dp_rcr_reg;
00714         int i, r;
00715 
00716         /* General initialization */
00717         dep->de_flags = DEF_EMPTY;
00718         (*dep->de_initf)(dep);
00719 
00720         dp_confaddr(dep);
00721 
00722         if (debug)
00723         {
00724                 printf("%s: Ethernet address ", dep->de_name);
00725                 for (i= 0; i < 6; i++)
00726                         printf("%x%c", dep->de_address.ea_addr[i],
00727                                                         i < 5 ? ':' : '\n');
00728         }
00729 
00730         /* Initialization of the dp8390 following the mandatory procedure
00731          * in reference manual ("DP8390D/NS32490D NIC Network Interface
00732          * Controller", National Semiconductor, July 1995, Page 29).
00733          */
00734         /* Step 1: */
00735         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
00736         /* Step 2: */
00737         if (dep->de_16bit)
00738                 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
00739         else
00740                 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
00741         /* Step 3: */
00742         outb_reg0(dep, DP_RBCR0, 0);
00743         outb_reg0(dep, DP_RBCR1, 0);
00744         /* Step 4: */
00745         dp_rcr_reg = 0;
00746         if (dep->de_flags & DEF_PROMISC)
00747                 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
00748         if (dep->de_flags & DEF_BROAD)
00749                 dp_rcr_reg |= RCR_AB;
00750         if (dep->de_flags & DEF_MULTI)
00751                 dp_rcr_reg |= RCR_AM;
00752         outb_reg0(dep, DP_RCR, dp_rcr_reg);
00753         /* Step 5: */
00754         outb_reg0(dep, DP_TCR, TCR_INTERNAL);
00755         /* Step 6: */
00756         outb_reg0(dep, DP_BNRY, dep->de_startpage);
00757         outb_reg0(dep, DP_PSTART, dep->de_startpage);
00758         outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
00759         /* Step 7: */
00760         outb_reg0(dep, DP_ISR, 0xFF);
00761         /* Step 8: */
00762         outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
00763                 IMR_OVWE | IMR_CNTE);
00764         /* Step 9: */
00765         outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
00766 
00767         outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
00768         outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
00769         outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
00770         outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
00771         outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
00772         outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
00773 
00774         outb_reg1(dep, DP_MAR0, 0xff);
00775         outb_reg1(dep, DP_MAR1, 0xff);
00776         outb_reg1(dep, DP_MAR2, 0xff);
00777         outb_reg1(dep, DP_MAR3, 0xff);
00778         outb_reg1(dep, DP_MAR4, 0xff);
00779         outb_reg1(dep, DP_MAR5, 0xff);
00780         outb_reg1(dep, DP_MAR6, 0xff);
00781         outb_reg1(dep, DP_MAR7, 0xff);
00782 
00783         outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
00784         /* Step 10: */
00785         outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
00786         /* Step 11: */
00787         outb_reg0(dep, DP_TCR, TCR_NORMAL);
00788 
00789         inb_reg0(dep, DP_CNTR0);                /* reset counters by reading */
00790         inb_reg0(dep, DP_CNTR1);
00791         inb_reg0(dep, DP_CNTR2);
00792 
00793         /* Finish the initialization. */
00794         dep->de_flags |= DEF_ENABLED;
00795         for (i= 0; i<dep->de_sendq_nr; i++)
00796                 dep->de_sendq[i].sq_filled= 0;
00797         dep->de_sendq_head= 0;
00798         dep->de_sendq_tail= 0;
00799         if (!dep->de_prog_IO)
00800         {
00801                 dep->de_user2nicf= dp_user2nic;
00802                 dep->de_nic2userf= dp_nic2user;
00803                 dep->de_getblockf= dp_getblock;
00804         }
00805         else if (dep->de_16bit)
00806         {
00807                 dep->de_user2nicf= dp_pio16_user2nic;
00808                 dep->de_nic2userf= dp_pio16_nic2user;
00809                 dep->de_getblockf= dp_pio16_getblock;
00810         }
00811         else
00812         {
00813                 dep->de_user2nicf= dp_pio8_user2nic;
00814                 dep->de_nic2userf= dp_pio8_nic2user;
00815                 dep->de_getblockf= dp_pio8_getblock;
00816         }
00817 
00818         /* Set the interrupt handler and policy. Do not automatically 
00819          * reenable interrupts. Return the IRQ line number on interrupts.
00820          */
00821         dep->de_hook = dep->de_irq;
00822         r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
00823         if (r != OK)
00824                 panic("DP8390", "sys_irqsetpolicy failed", r);
00825 
00826         r= sys_irqenable(&dep->de_hook);
00827         if (r != OK)
00828         {
00829                 panic("DP8390", "unable enable interrupts", r);
00830         }
00831 }
00832 
00833 /*===========================================================================*
00834  *                              dp_confaddr                                  *
00835  *===========================================================================*/
00836 static void dp_confaddr(dep)
00837 dpeth_t *dep;
00838 {
00839         int i;
00840         char eakey[16];
00841         static char eafmt[]= "x:x:x:x:x:x";
00842         long v;
00843 
00844         /* User defined ethernet address? */
00845         strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
00846         strcat(eakey, "_EA");
00847 
00848         for (i= 0; i < 6; i++)
00849         {
00850                 v= dep->de_address.ea_addr[i];
00851                 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
00852                 {
00853                         break;
00854                 }
00855                 dep->de_address.ea_addr[i]= v;
00856         }
00857 
00858         if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
00859 }
00860 
00861 /*===========================================================================*
00862  *                              dp_reinit                                    *
00863  *===========================================================================*/
00864 static void dp_reinit(dep)
00865 dpeth_t *dep;
00866 {
00867         int dp_rcr_reg;
00868 
00869         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
00870 
00871         dp_rcr_reg = 0;
00872         if (dep->de_flags & DEF_PROMISC)
00873                 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
00874         if (dep->de_flags & DEF_BROAD)
00875                 dp_rcr_reg |= RCR_AB;
00876         if (dep->de_flags & DEF_MULTI)
00877                 dp_rcr_reg |= RCR_AM;
00878         outb_reg0(dep, DP_RCR, dp_rcr_reg);
00879 }
00880 
00881 /*===========================================================================*
00882  *                              dp_reset                                     *
00883  *===========================================================================*/
00884 static void dp_reset(dep)
00885 dpeth_t *dep;
00886 {
00887         int i;
00888 
00889         /* Stop chip */
00890         outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
00891         outb_reg0(dep, DP_RBCR0, 0);
00892         outb_reg0(dep, DP_RBCR1, 0);
00893         for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
00894                 ; /* Do nothing */
00895         outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
00896         outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
00897         outb_reg0(dep, DP_TCR, TCR_NORMAL);
00898 
00899         /* Acknowledge the ISR_RDC (remote dma) interrupt. */
00900         for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
00901                 ; /* Do nothing */
00902         outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
00903 
00904         /* Reset the transmit ring. If we were transmitting a packet, we
00905          * pretend that the packet is processed. Higher layers will
00906          * retransmit if the packet wasn't actually sent.
00907          */
00908         dep->de_sendq_head= dep->de_sendq_tail= 0;
00909         for (i= 0; i<dep->de_sendq_nr; i++)
00910                 dep->de_sendq[i].sq_filled= 0;
00911         dp_send(dep);
00912         dep->de_flags &= ~DEF_STOPPED;
00913 }
00914 
00915 /*===========================================================================*
00916  *                              dp_check_ints                                *
00917  *===========================================================================*/
00918 static void dp_check_ints(dep)
00919 dpeth_t *dep;
00920 {
00921         int isr, tsr;
00922         int size, sendq_tail;
00923 
00924         if (!(dep->de_flags & DEF_ENABLED))
00925                 panic("", "dp8390: got premature interrupt", NO_NUM);
00926 
00927         for(;;)
00928         {
00929                 isr = inb_reg0(dep, DP_ISR);
00930                 if (!isr)
00931                         break;
00932                 outb_reg0(dep, DP_ISR, isr);
00933                 if (isr & (ISR_PTX|ISR_TXE))
00934                 {
00935                         if (isr & ISR_TXE)
00936                         {
00937 #if DEBUG
00938  { printf("%s: got send Error\n", dep->de_name); }
00939 #endif
00940                                 dep->de_stat.ets_sendErr++;
00941                         }
00942                         else
00943                         {
00944                                 tsr = inb_reg0(dep, DP_TSR);
00945 
00946                                 if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
00947 #if 0   /* Reserved in later manuals, should be ignored */
00948                                 if (!(tsr & TSR_DFR))
00949                                 {
00950                                         /* In most (all?) implementations of
00951                                          * the dp8390, this bit is set
00952                                          * when the packet is not deferred
00953                                          */
00954                                         dep->de_stat.ets_transDef++;
00955                                 }
00956 #endif
00957                                 if (tsr & TSR_COL) dep->de_stat.ets_collision++;
00958                                 if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
00959                                 if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
00960                                 if (tsr & TSR_FU
00961                                         && ++dep->de_stat.ets_fifoUnder <= 10)
00962                                 {
00963                                         printf("%s: fifo underrun\n",
00964                                                 dep->de_name);
00965                                 }
00966                                 if (tsr & TSR_CDH
00967                                         && ++dep->de_stat.ets_CDheartbeat <= 10)
00968                                 {
00969                                         printf("%s: CD heart beat failure\n",
00970                                                 dep->de_name);
00971                                 }
00972                                 if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
00973                         }
00974                         sendq_tail= dep->de_sendq_tail;
00975 
00976                         if (!(dep->de_sendq[sendq_tail].sq_filled))
00977                         {
00978                                 /* Software bug? */
00979                                 assert(!debug);
00980 
00981                                 /* Or hardware bug? */
00982                                 printf(
00983                                 "%s: transmit interrupt, but not sending\n",
00984                                         dep->de_name);
00985                                 continue;
00986                         }
00987                         dep->de_sendq[sendq_tail].sq_filled= 0;
00988                         if (++sendq_tail == dep->de_sendq_nr)
00989                                 sendq_tail= 0;
00990                         dep->de_sendq_tail= sendq_tail;
00991                         if (dep->de_sendq[sendq_tail].sq_filled)
00992                         {
00993                                 size= dep->de_sendq[sendq_tail].sq_size;
00994                                 outb_reg0(dep, DP_TPSR,
00995                                         dep->de_sendq[sendq_tail].sq_sendpage);
00996                                 outb_reg0(dep, DP_TBCR1, size >> 8);
00997                                 outb_reg0(dep, DP_TBCR0, size & 0xff);
00998                                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
00999                         }
01000                         if (dep->de_flags & DEF_SEND_AVAIL)
01001                                 dp_send(dep);
01002                 }
01003 
01004                 if (isr & ISR_PRX)
01005                 {
01006                         /* Only call dp_recv if there is a read request */
01007                         if (dep->de_flags & DEF_READING)
01008                                 dp_recv(dep);
01009                 }
01010                 
01011                 if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
01012                 if (isr & ISR_CNT)
01013                 {
01014                         dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
01015                         dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
01016                         dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
01017                 }
01018                 if (isr & ISR_OVW)
01019                 {
01020                         dep->de_stat.ets_OVW++;
01021 #if 0
01022                         { printW(); printf(
01023                                 "%s: got overwrite warning\n", dep->de_name); }
01024 #endif
01025                         if (dep->de_flags & DEF_READING)
01026                         {
01027                                 printf(
01028 "dp_check_ints: strange: overwrite warning and pending read request\n");
01029                                 dp_recv(dep);
01030                         }
01031                 }
01032                 if (isr & ISR_RDC)
01033                 {
01034                         /* Nothing to do */
01035                 }
01036                 if (isr & ISR_RST)
01037                 {
01038                         /* this means we got an interrupt but the ethernet 
01039                          * chip is shutdown. We set the flag DEF_STOPPED,
01040                          * and continue processing arrived packets. When the
01041                          * receive buffer is empty, we reset the dp8390.
01042                          */
01043 #if 0
01044                          { printW(); printf(
01045                                 "%s: NIC stopped\n", dep->de_name); }
01046 #endif
01047                         dep->de_flags |= DEF_STOPPED;
01048                         break;
01049                 }
01050         }
01051         if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == 
01052                                                 (DEF_READING|DEF_STOPPED))
01053         {
01054                 /* The chip is stopped, and all arrived packets are 
01055                  * delivered.
01056                  */
01057                 dp_reset(dep);
01058         }
01059 }
01060 
01061 /*===========================================================================*
01062  *                              dp_recv                                      *
01063  *===========================================================================*/
01064 static void dp_recv(dep)
01065 dpeth_t *dep;
01066 {
01067         dp_rcvhdr_t header;
01068         unsigned pageno, curr, next;
01069         vir_bytes length;
01070         int packet_processed, r;
01071         u16_t eth_type;
01072 
01073         packet_processed = FALSE;
01074         pageno = inb_reg0(dep, DP_BNRY) + 1;
01075         if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
01076 
01077         do
01078         {
01079                 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
01080                 curr = inb_reg1(dep, DP_CURR);
01081                 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
01082 
01083                 if (curr == pageno) break;
01084 
01085                 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
01086                         &header);
01087                 (dep->de_getblockf)(dep, pageno, sizeof(header) +
01088                         2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
01089 
01090                 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
01091                         sizeof(dp_rcvhdr_t);
01092                 next = header.dr_next;
01093                 if (length < ETH_MIN_PACK_SIZE ||
01094                         length > ETH_MAX_PACK_SIZE_TAGGED)
01095                 {
01096                         printf("%s: packet with strange length arrived: %d\n",
01097                                 dep->de_name, (int) length);
01098                         next= curr;
01099                 }
01100                 else if (next < dep->de_startpage || next >= dep->de_stoppage)
01101                 {
01102                         printf("%s: strange next page\n", dep->de_name);
01103                         next= curr;
01104                 }
01105                 else if (eth_type == eth_ign_proto)
01106                 {
01107                         /* Hack: ignore packets of a given protocol, useful
01108                          * if you share a net with 80 computers sending
01109                          * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
01110                          */
01111                         static int first= 1;
01112                         if (first)
01113                         {
01114                                 first= 0;
01115                                 printf("%s: dropping proto 0x%04x packets\n",
01116                                         dep->de_name,
01117                                         ntohs(eth_ign_proto));
01118                         }
01119                         dep->de_stat.ets_packetR++;
01120                 }
01121                 else if (header.dr_status & RSR_FO)
01122                 {
01123                         /* This is very serious, so we issue a warning and
01124                          * reset the buffers */
01125                         printf("%s: fifo overrun, resetting receive buffer\n",
01126                                 dep->de_name);
01127                         dep->de_stat.ets_fifoOver++;
01128                         next = curr;
01129                 }
01130                 else if ((header.dr_status & RSR_PRX) &&
01131                                            (dep->de_flags & DEF_ENABLED))
01132                 {
01133                         r = dp_pkt2user(dep, pageno, length);
01134                         if (r != OK)
01135                                 return;
01136 
01137                         packet_processed = TRUE;
01138                         dep->de_stat.ets_packetR++;
01139                 }
01140                 if (next == dep->de_startpage)
01141                         outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
01142                 else
01143                         outb_reg0(dep, DP_BNRY, next - 1);
01144 
01145                 pageno = next;
01146         }
01147         while (!packet_processed);
01148 }
01149 
01150 /*===========================================================================*
01151  *                              dp_send                                      *
01152  *===========================================================================*/
01153 static void dp_send(dep)
01154 dpeth_t *dep;
01155 {
01156         if (!(dep->de_flags & DEF_SEND_AVAIL))
01157                 return;
01158 
01159         dep->de_flags &= ~DEF_SEND_AVAIL;
01160         switch(dep->de_sendmsg.m_type)
01161         {
01162         case DL_WRITE:  do_vwrite(&dep->de_sendmsg, TRUE, FALSE);       break;
01163         case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE);        break;
01164         default:
01165                 panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);
01166                 break;
01167         }
01168 }
01169 
01170 /*===========================================================================*
01171  *                              dp_getblock                                  *
01172  *===========================================================================*/
01173 static void dp_getblock(dep, page, offset, size, dst)
01174 dpeth_t *dep;
01175 int page;
01176 size_t offset;
01177 size_t size;
01178 void *dst;
01179 {
01180         int r;
01181 
01182         offset = page * DP_PAGESIZE + offset;
01183 
01184         r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset,
01185                 SELF, D, (vir_bytes)dst, size);
01186 
01187         if (r != OK)
01188                 panic("DP8390", "dp_getblock: sys_vircopy failed", r);
01189 }
01190 
01191 /*===========================================================================*
01192  *                              dp_pio8_getblock                             *
01193  *===========================================================================*/
01194 static void dp_pio8_getblock(dep, page, offset, size, dst)
01195 dpeth_t *dep;
01196 int page;
01197 size_t offset;
01198 size_t size;
01199 void *dst;
01200 {
01201         offset = page * DP_PAGESIZE + offset;
01202         outb_reg0(dep, DP_RBCR0, size & 0xFF);
01203         outb_reg0(dep, DP_RBCR1, size >> 8);
01204         outb_reg0(dep, DP_RSAR0, offset & 0xFF);
01205         outb_reg0(dep, DP_RSAR1, offset >> 8);
01206         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01207 
01208         insb(dep->de_data_port, dst, size);
01209 }
01210 
01211 /*===========================================================================*
01212  *                              dp_pio16_getblock                            *
01213  *===========================================================================*/
01214 static void dp_pio16_getblock(dep, page, offset, size, dst)
01215 dpeth_t *dep;
01216 int page;
01217 size_t offset;
01218 size_t size;
01219 void *dst;
01220 {
01221         offset = page * DP_PAGESIZE + offset;
01222         outb_reg0(dep, DP_RBCR0, size & 0xFF);
01223         outb_reg0(dep, DP_RBCR1, size >> 8);
01224         outb_reg0(dep, DP_RSAR0, offset & 0xFF);
01225         outb_reg0(dep, DP_RSAR1, offset >> 8);
01226         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01227 
01228         assert (!(size & 1));
01229         insw(dep->de_data_port, dst, size);
01230 }
01231 
01232 /*===========================================================================*
01233  *                              dp_pkt2user                                  *
01234  *===========================================================================*/
01235 static int dp_pkt2user(dep, page, length)
01236 dpeth_t *dep;
01237 int page, length;
01238 {
01239         int last, count;
01240 
01241         if (!(dep->de_flags & DEF_READING))
01242                 return EGENERIC;
01243 
01244         last = page + (length - 1) / DP_PAGESIZE;
01245         if (last >= dep->de_stoppage)
01246         {
01247                 count = (dep->de_stoppage - page) * DP_PAGESIZE -
01248                         sizeof(dp_rcvhdr_t);
01249 
01250                 /* Save read_iovec since we need it twice. */
01251                 dep->de_tmp_iovec = dep->de_read_iovec;
01252                 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
01253                         sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
01254                 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE, 
01255                                 &dep->de_read_iovec, count, length - count);
01256         }
01257         else
01258         {
01259                 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
01260                         sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
01261         }
01262 
01263         dep->de_read_s = length;
01264         dep->de_flags |= DEF_PACK_RECV;
01265         dep->de_flags &= ~DEF_READING;
01266 
01267         return OK;
01268 }
01269 
01270 /*===========================================================================*
01271  *                              dp_user2nic                                  *
01272  *===========================================================================*/
01273 static void dp_user2nic(dep, iovp, offset, nic_addr, count)
01274 dpeth_t *dep;
01275 iovec_dat_t *iovp;
01276 vir_bytes offset;
01277 int nic_addr;
01278 vir_bytes count;
01279 {
01280         vir_bytes vir_hw, vir_user;
01281         int bytes, i, r;
01282 
01283         vir_hw = dep->de_linmem + nic_addr;
01284 
01285         i= 0;
01286         while (count > 0)
01287         {
01288                 if (i >= IOVEC_NR)
01289                 {
01290                         dp_next_iovec(iovp);
01291                         i= 0;
01292                         continue;
01293                 }
01294                 assert(i < iovp->iod_iovec_s);
01295                 if (offset >= iovp->iod_iovec[i].iov_size)
01296                 {
01297                         offset -= iovp->iod_iovec[i].iov_size;
01298                         i++;
01299                         continue;
01300                 }
01301                 bytes = iovp->iod_iovec[i].iov_size - offset;
01302                 if (bytes > count)
01303                         bytes = count;
01304 
01305                 r= sys_vircopy(iovp->iod_proc_nr, D,
01306                         iovp->iod_iovec[i].iov_addr + offset,
01307                         SELF, BIOS_SEG, vir_hw, bytes);
01308                 if (r != OK)
01309                         panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
01310 
01311                 count -= bytes;
01312                 vir_hw += bytes;
01313                 offset += bytes;
01314         }
01315         assert(count == 0);
01316 }
01317 
01318 /*===========================================================================*
01319  *                              dp_pio8_user2nic                             *
01320  *===========================================================================*/
01321 static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
01322 dpeth_t *dep;
01323 iovec_dat_t *iovp;
01324 vir_bytes offset;
01325 int nic_addr;
01326 vir_bytes count;
01327 {
01328         phys_bytes phys_user;
01329         int bytes, i;
01330 
01331         outb_reg0(dep, DP_ISR, ISR_RDC);
01332 
01333         outb_reg0(dep, DP_RBCR0, count & 0xFF);
01334         outb_reg0(dep, DP_RBCR1, count >> 8);
01335         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01336         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01337         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
01338 
01339         i= 0;
01340         while (count > 0)
01341         {
01342                 if (i >= IOVEC_NR)
01343                 {
01344                         dp_next_iovec(iovp);
01345                         i= 0;
01346                         continue;
01347                 }
01348                 assert(i < iovp->iod_iovec_s);
01349                 if (offset >= iovp->iod_iovec[i].iov_size)
01350                 {
01351                         offset -= iovp->iod_iovec[i].iov_size;
01352                         i++;
01353                         continue;
01354                 }
01355                 bytes = iovp->iod_iovec[i].iov_size - offset;
01356                 if (bytes > count)
01357                         bytes = count;
01358 
01359                 do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
01360                         iovp->iod_iovec[i].iov_addr + offset, bytes);
01361                 count -= bytes;
01362                 offset += bytes;
01363         }
01364         assert(count == 0);
01365 
01366         for (i= 0; i<100; i++)
01367         {
01368                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
01369                         break;
01370         }
01371         if (i == 100)
01372         {
01373                 panic("", "dp8390: remote dma failed to complete", NO_NUM);
01374         }
01375 }
01376 
01377 /*===========================================================================*
01378  *                              dp_pio16_user2nic                            *
01379  *===========================================================================*/
01380 static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
01381 dpeth_t *dep;
01382 iovec_dat_t *iovp;
01383 vir_bytes offset;
01384 int nic_addr;
01385 vir_bytes count;
01386 {
01387         vir_bytes vir_user;
01388         vir_bytes ecount;
01389         int i, r, bytes, user_proc;
01390         u8_t two_bytes[2];
01391         int odd_byte;
01392 
01393         ecount= (count+1) & ~1;
01394         odd_byte= 0;
01395 
01396         outb_reg0(dep, DP_ISR, ISR_RDC);
01397         outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
01398         outb_reg0(dep, DP_RBCR1, ecount >> 8);
01399         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01400         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01401         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
01402 
01403         i= 0;
01404         while (count > 0)
01405         {
01406                 if (i >= IOVEC_NR)
01407                 {
01408                         dp_next_iovec(iovp);
01409                         i= 0;
01410                         continue;
01411                 }
01412                 assert(i < iovp->iod_iovec_s);
01413                 if (offset >= iovp->iod_iovec[i].iov_size)
01414                 {
01415                         offset -= iovp->iod_iovec[i].iov_size;
01416                         i++;
01417                         continue;
01418                 }
01419                 bytes = iovp->iod_iovec[i].iov_size - offset;
01420                 if (bytes > count)
01421                         bytes = count;
01422 
01423                 user_proc= iovp->iod_proc_nr;
01424                 vir_user= iovp->iod_iovec[i].iov_addr + offset;
01425                 if (odd_byte)
01426                 {
01427                         r= sys_vircopy(user_proc, D, vir_user, 
01428                                 SELF, D, (vir_bytes)&two_bytes[1], 1);
01429                         if (r != OK)
01430                         {
01431                                 panic("DP8390",
01432                                         "dp_pio16_user2nic: sys_vircopy failed",
01433                                         r);
01434                         }
01435                         outw(dep->de_data_port, *(u16_t *)two_bytes);
01436                         count--;
01437                         offset++;
01438                         bytes--;
01439                         vir_user++;
01440                         odd_byte= 0;
01441                         if (!bytes)
01442                                 continue;
01443                 }
01444                 ecount= bytes & ~1;
01445                 if (ecount != 0)
01446                 {
01447                         do_vir_outsw(dep->de_data_port, user_proc, vir_user,
01448                                 ecount);
01449                         count -= ecount;
01450                         offset += ecount;
01451                         bytes -= ecount;
01452                         vir_user += ecount;
01453                 }
01454                 if (bytes)
01455                 {
01456                         assert(bytes == 1);
01457                         r= sys_vircopy(user_proc, D, vir_user, 
01458                                 SELF, D, (vir_bytes)&two_bytes[0], 1);
01459                         if (r != OK)
01460                         {
01461                                 panic("DP8390",
01462                                         "dp_pio16_user2nic: sys_vircopy failed",
01463                                         r);
01464                         }
01465                         count--;
01466                         offset++;
01467                         bytes--;
01468                         vir_user++;
01469                         odd_byte= 1;
01470                 }
01471         }
01472         assert(count == 0);
01473 
01474         if (odd_byte)
01475                 outw(dep->de_data_port, *(u16_t *)two_bytes);
01476 
01477         for (i= 0; i<100; i++)
01478         {
01479                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
01480                         break;
01481         }
01482         if (i == 100)
01483         {
01484                 panic("", "dp8390: remote dma failed to complete", NO_NUM);
01485         }
01486 }
01487 
01488 /*===========================================================================*
01489  *                              dp_nic2user                                  *
01490  *===========================================================================*/
01491 static void dp_nic2user(dep, nic_addr, iovp, offset, count)
01492 dpeth_t *dep;
01493 int nic_addr;
01494 iovec_dat_t *iovp;
01495 vir_bytes offset;
01496 vir_bytes count;
01497 {
01498         vir_bytes vir_hw, vir_user;
01499         int bytes, i, r;
01500 
01501         vir_hw = dep->de_linmem + nic_addr;
01502 
01503         i= 0;
01504         while (count > 0)
01505         {
01506                 if (i >= IOVEC_NR)
01507                 {
01508                         dp_next_iovec(iovp);
01509                         i= 0;
01510                         continue;
01511                 }
01512                 assert(i < iovp->iod_iovec_s);
01513                 if (offset >= iovp->iod_iovec[i].iov_size)
01514                 {
01515                         offset -= iovp->iod_iovec[i].iov_size;
01516                         i++;
01517                         continue;
01518                 }
01519                 bytes = iovp->iod_iovec[i].iov_size - offset;
01520                 if (bytes > count)
01521                         bytes = count;
01522 
01523                 r= sys_vircopy(SELF, BIOS_SEG, vir_hw,
01524                         iovp->iod_proc_nr, D,
01525                         iovp->iod_iovec[i].iov_addr + offset, bytes);
01526                 if (r != OK)
01527                         panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
01528 
01529                 count -= bytes;
01530                 vir_hw += bytes;
01531                 offset += bytes;
01532         }
01533         assert(count == 0);
01534 }
01535 
01536 /*===========================================================================*
01537  *                              dp_pio8_nic2user                             *
01538  *===========================================================================*/
01539 static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
01540 dpeth_t *dep;
01541 int nic_addr;
01542 iovec_dat_t *iovp;
01543 vir_bytes offset;
01544 vir_bytes count;
01545 {
01546         phys_bytes phys_user;
01547         int bytes, i;
01548 
01549         outb_reg0(dep, DP_RBCR0, count & 0xFF);
01550         outb_reg0(dep, DP_RBCR1, count >> 8);
01551         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01552         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01553         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01554 
01555         i= 0;
01556         while (count > 0)
01557         {
01558                 if (i >= IOVEC_NR)
01559                 {
01560                         dp_next_iovec(iovp);
01561                         i= 0;
01562                         continue;
01563                 }
01564                 assert(i < iovp->iod_iovec_s);
01565                 if (offset >= iovp->iod_iovec[i].iov_size)
01566                 {
01567                         offset -= iovp->iod_iovec[i].iov_size;
01568                         i++;
01569                         continue;
01570                 }
01571                 bytes = iovp->iod_iovec[i].iov_size - offset;
01572                 if (bytes > count)
01573                         bytes = count;
01574 
01575                 do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
01576                         iovp->iod_iovec[i].iov_addr + offset, bytes);
01577                 count -= bytes;
01578                 offset += bytes;
01579         }
01580         assert(count == 0);
01581 }
01582 
01583 /*===========================================================================*
01584  *                              dp_pio16_nic2user                            *
01585  *===========================================================================*/
01586 static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
01587 dpeth_t *dep;
01588 int nic_addr;
01589 iovec_dat_t *iovp;
01590 vir_bytes offset;
01591 vir_bytes count;
01592 {
01593         vir_bytes vir_user;
01594         vir_bytes ecount;
01595         int i, r, bytes, user_proc;
01596         u8_t two_bytes[2];
01597         int odd_byte;
01598 
01599         ecount= (count+1) & ~1;
01600         odd_byte= 0;
01601 
01602         outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
01603         outb_reg0(dep, DP_RBCR1, ecount >> 8);
01604         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01605         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01606         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01607 
01608         i= 0;
01609         while (count > 0)
01610         {
01611                 if (i >= IOVEC_NR)
01612                 {
01613                         dp_next_iovec(iovp);
01614                         i= 0;
01615                         continue;
01616                 }
01617                 assert(i < iovp->iod_iovec_s);
01618                 if (offset >= iovp->iod_iovec[i].iov_size)
01619                 {
01620                         offset -= iovp->iod_iovec[i].iov_size;
01621                         i++;
01622                         continue;
01623                 }
01624                 bytes = iovp->iod_iovec[i].iov_size - offset;
01625                 if (bytes > count)
01626                         bytes = count;
01627 
01628                 user_proc= iovp->iod_proc_nr;
01629                 vir_user= iovp->iod_iovec[i].iov_addr + offset;
01630                 if (odd_byte)
01631                 {
01632                         r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
01633                                 user_proc, D, vir_user,  1);
01634                         if (r != OK)
01635                         {
01636                                 panic("DP8390",
01637                                         "dp_pio16_nic2user: sys_vircopy failed",
01638                                         r);
01639                         }
01640                         count--;
01641                         offset++;
01642                         bytes--;
01643                         vir_user++;
01644                         odd_byte= 0;
01645                         if (!bytes)
01646                                 continue;
01647                 }
01648                 ecount= bytes & ~1;
01649                 if (ecount != 0)
01650                 {
01651                         do_vir_insw(dep->de_data_port, user_proc, vir_user,
01652                                 ecount);
01653                         count -= ecount;
01654                         offset += ecount;
01655                         bytes -= ecount;
01656                         vir_user += ecount;
01657                 }
01658                 if (bytes)
01659                 {
01660                         assert(bytes == 1);
01661                         *(u16_t *)two_bytes= inw(dep->de_data_port);
01662                         r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
01663                                 user_proc, D, vir_user,  1);
01664                         if (r != OK)
01665                         {
01666                                 panic("DP8390",
01667                                         "dp_pio16_nic2user: sys_vircopy failed",
01668                                         r);
01669                         }
01670                         count--;
01671                         offset++;
01672                         bytes--;
01673                         vir_user++;
01674                         odd_byte= 1;
01675                 }
01676         }
01677         assert(count == 0);
01678 }
01679 
01680 /*===========================================================================*
01681  *                              dp_next_iovec                                        *
01682  *===========================================================================*/
01683 static void dp_next_iovec(iovp)
01684 iovec_dat_t *iovp;
01685 {
01686         assert(iovp->iod_iovec_s > IOVEC_NR);
01687 
01688         iovp->iod_iovec_s -= IOVEC_NR;
01689 
01690         iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
01691 
01692         get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
01693                 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
01694                 sizeof(iovec_t), iovp->iod_iovec); 
01695 }
01696 
01697 /*===========================================================================*
01698  *                              conf_hw                                      *
01699  *===========================================================================*/
01700 static void conf_hw(dep)
01701 dpeth_t *dep;
01702 {
01703         static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };
01704 
01705         int ifnr;
01706         dp_conf_t *dcp;
01707 
01708         dep->de_mode= DEM_DISABLED;     /* Superfluous */
01709         ifnr= dep-de_table;
01710 
01711         dcp= &dp_conf[ifnr];
01712         update_conf(dep, dcp);
01713         if (dep->de_mode != DEM_ENABLED)
01714                 return;
01715         if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
01716         {
01717                 printf("%s: No ethernet card found at 0x%x\n", 
01718                         dep->de_name, dep->de_base_port);
01719                 dep->de_mode= DEM_DISABLED;
01720                 return;
01721         }
01722 
01723 /* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
01724 
01725         dep->de_flags = DEF_EMPTY;
01726         dep->de_stat = empty_stat;
01727 }
01728 
01729 /*===========================================================================*
01730  *                              update_conf                                  *
01731  *===========================================================================*/
01732 static void update_conf(dep, dcp)
01733 dpeth_t *dep;
01734 dp_conf_t *dcp;
01735 {
01736         long v;
01737         static char dpc_fmt[] = "x:d:x:x";
01738 
01739 #if ENABLE_PCI
01740         if (dep->de_pci)
01741         {
01742                 if (dep->de_pci == 1)
01743                 {
01744                         /* PCI device is present */
01745                         dep->de_mode= DEM_ENABLED;
01746                 }
01747                 return;         /* Already configured */
01748         }
01749 #endif
01750 
01751         /* Get the default settings and modify them from the environment. */
01752         dep->de_mode= DEM_SINK;
01753         v= dcp->dpc_port;
01754         switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
01755         case EP_OFF:
01756                 dep->de_mode= DEM_DISABLED;
01757                 break;
01758         case EP_ON:
01759         case EP_SET:
01760                 dep->de_mode= DEM_ENABLED;      /* Might become disabled if 
01761                                                  * all probes fail */
01762                 break;
01763         }
01764         dep->de_base_port= v;
01765 
01766         v= dcp->dpc_irq | DEI_DEFAULT;
01767         (void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
01768                                                 (long) NR_IRQ_VECTORS - 1);
01769         dep->de_irq= v;
01770 
01771         v= dcp->dpc_mem;
01772         (void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
01773         dep->de_linmem= v;
01774 
01775         v= 0;
01776         (void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
01777         dep->de_ramsize= v;
01778 }
01779 
01780 /*===========================================================================*
01781  *                              calc_iovec_size                              *
01782  *===========================================================================*/
01783 static int calc_iovec_size(iovp)
01784 iovec_dat_t *iovp;
01785 {
01786         /* Calculate the size of a request. Note that the iovec_dat
01787          * structure will be unusable after calc_iovec_size.
01788          */
01789         int size;
01790         int i;
01791 
01792         size= 0;
01793         i= 0;
01794         while (i < iovp->iod_iovec_s)
01795         {
01796                 if (i >= IOVEC_NR)
01797                 {
01798                         dp_next_iovec(iovp);
01799                         i= 0;
01800                         continue;
01801                 }
01802                 size += iovp->iod_iovec[i].iov_size;
01803                 i++;
01804         }
01805         return size;
01806 }
01807 
01808 /*===========================================================================*
01809  *                              reply                                        *
01810  *===========================================================================*/
01811 static void reply(dep, err, may_block)
01812 dpeth_t *dep;
01813 int err;
01814 int may_block;
01815 {
01816         message reply;
01817         int status;
01818         int r;
01819 
01820         status = 0;
01821         if (dep->de_flags & DEF_PACK_SEND)
01822                 status |= DL_PACK_SEND;
01823         if (dep->de_flags & DEF_PACK_RECV)
01824                 status |= DL_PACK_RECV;
01825 
01826         reply.m_type = DL_TASK_REPLY;
01827         reply.DL_PORT = dep - de_table;
01828         reply.DL_PROC = dep->de_client;
01829         reply.DL_STAT = status | ((u32_t) err << 16);
01830         reply.DL_COUNT = dep->de_read_s;
01831         reply.DL_CLCK = 0;      /* Don't know */
01832         r= send(dep->de_client, &reply);
01833 
01834         if (r == ELOCKED && may_block)
01835         {
01836 #if 0
01837                 printf("send locked\n");
01838 #endif
01839                 return;
01840         }
01841 
01842         if (r < 0)
01843                 panic("", "dp8390: send failed:", r);
01844         
01845         dep->de_read_s = 0;
01846         dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
01847 }
01848 
01849 /*===========================================================================*
01850  *                              mess_reply                                   *
01851  *===========================================================================*/
01852 static void mess_reply(req, reply_mess)
01853 message *req;
01854 message *reply_mess;
01855 {
01856         if (send(req->m_source, reply_mess) != OK)
01857                 panic("", "dp8390: unable to mess_reply", NO_NUM);
01858 }
01859 
01860 /*===========================================================================*
01861  *                              get_userdata                                 *
01862  *===========================================================================*/
01863 static void get_userdata(user_proc, user_addr, count, loc_addr)
01864 int user_proc;
01865 vir_bytes user_addr;
01866 vir_bytes count;
01867 void *loc_addr;
01868 {
01869         int r;
01870 
01871         r= sys_vircopy(user_proc, D, user_addr,
01872                 SELF, D, (vir_bytes)loc_addr, count);
01873         if (r != OK)
01874                 panic("DP8390", "get_userdata: sys_vircopy failed", r);
01875 }
01876 
01877 /*===========================================================================*
01878  *                              put_userdata                                 *
01879  *===========================================================================*/
01880 static void put_userdata(user_proc, user_addr, count, loc_addr)
01881 int user_proc;
01882 vir_bytes user_addr;
01883 vir_bytes count;
01884 void *loc_addr;
01885 {
01886         int r;
01887 
01888         r= sys_vircopy(SELF, D, (vir_bytes)loc_addr, 
01889                 user_proc, D, user_addr, count);
01890         if (r != OK)
01891                 panic("DP8390", "put_userdata: sys_vircopy failed", r);
01892 }
01893 
01894 u8_t inb(port_t port)
01895 {
01896         int r;
01897         u32_t value;
01898 
01899         r= sys_inb(port, &value);
01900         if (r != OK)
01901                 panic("DP8390","sys_inb failed", r);
01902         return value;
01903 }
01904 
01905 u16_t inw(port_t port)
01906 {
01907         int r;
01908         unsigned long value;
01909 
01910         r= sys_inw(port, &value);
01911         if (r != OK)
01912                 panic("DP8390", "sys_inw failed", r);
01913         return (u16_t) value;
01914 }
01915 
01916 void outb(port_t port, u8_t value)
01917 {
01918         int r;
01919 
01920         r= sys_outb(port, value);
01921         if (r != OK)
01922                 panic("DP8390", "sys_outb failed", r);
01923 }
01924 
01925 void outw(port_t port, u16_t value)
01926 {
01927         int r;
01928 
01929         r= sys_outw(port, value);
01930         if (r != OK)
01931                 panic("DP8390", "sys_outw failed", r);
01932 }
01933 
01934 static void insb(port_t port, void *buf, size_t size)
01935 {
01936         do_vir_insb(port, SELF, (vir_bytes)buf, size);
01937 }
01938 
01939 static void insw(port_t port, void *buf, size_t size)
01940 {
01941         do_vir_insw(port, SELF, (vir_bytes)buf, size);
01942 }
01943 
01944 static void do_vir_insb(port_t port, int proc, vir_bytes buf, size_t size)
01945 {
01946         int r;
01947 
01948         r= sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc, (void *)buf, size);
01949         if (r != OK)
01950                 panic("DP8390", "sys_sdevio failed", r);
01951 }
01952 
01953 static void do_vir_insw(port_t port, int proc, vir_bytes buf, size_t size)
01954 {
01955         int r;
01956 
01957         r= sys_sdevio(DIO_INPUT, port, DIO_WORD, proc, (void *)buf, size);
01958         if (r != OK)
01959                 panic("DP8390", "sys_sdevio failed", r);
01960 }
01961 
01962 static void do_vir_outsb(port_t port, int proc, vir_bytes buf, size_t size)
01963 {
01964         int r;
01965 
01966         r= sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc, (void *)buf, size);
01967         if (r != OK)
01968                 panic("DP8390", "sys_sdevio failed", r);
01969 }
01970 
01971 static void do_vir_outsw(port_t port, int proc, vir_bytes buf, size_t size)
01972 {
01973         int r;
01974 
01975         r= sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc, (void *)buf, size);
01976         if (r != OK)
01977                 panic("DP8390", "sys_sdevio failed", r);
01978 }
01979 
01980 /*
01981  * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
01982  */

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