

Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.
0108000 /*
0108001 * dp8390.c
0108002 *
0108003 * This file contains a ethernet device driver for NS dp8390 based ethernet
0108004 * cards.
0108005 *
0108006 * The valid messages and their parameters are:
0108007 *
0108008 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
0108009 * |------------+----------+---------+----------+---------+---------|
0108010 * | HARDINT | | | | | |
0108011 * |------------|----------|---------|----------|---------|---------|
0108012 * | DL_WRITE | port nr | proc nr | count | mode | address |
0108013 * |------------|----------|---------|----------|---------|---------|
0108014 * | DL_WRITEV | port nr | proc nr | count | mode | address |
0108015 * |------------|----------|---------|----------|---------|---------|
0108016 * | DL_READ | port nr | proc nr | count | | address |
0108017 * |------------|----------|---------|----------|---------|---------|
0108018 * | DL_READV | port nr | proc nr | count | | address |
0108019 * |------------|----------|---------|----------|---------|---------|
0108020 * | DL_INIT | port nr | proc nr | mode | | address |
0108021 * |------------|----------|---------|----------|---------|---------|
0108022 * | DL_GETSTAT | port nr | proc nr | | | address |
0108023 * |------------|----------|---------|----------|---------|---------|
0108024 * | DL_STOP | port_nr | | | | |
0108025 * |------------|----------|---------|----------|---------|---------|
0108026 *
0108027 * The messages sent are:
0108028 *
0108029 * m-type DL_POR T DL_PROC DL_COUNT DL_STAT DL_CLCK
0108030 * |------------|----------|---------|----------|---------|---------|
0108031 * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock |
0108032 * |------------|----------|---------|----------|---------|---------|
0108033 *
0108034 * m_type m3_i1 m3_i2 m3_ca1
0108035 * |------------+---------+-----------+---------------|
0108036 * |DL_INIT_REPL| port nr | last port | ethernet addr |
0108037 * |------------|---------|-----------|---------------|
0108038 *
0108039 * Created: before Dec 28, 1992 by Philip Homburg <philip@cs.vu.nl>
0108040 *
0108041 * Modified Mar 10 1994 by Philip Homburg
0108042 * Become a generic dp8390 driver.
0108043 *
0108044 * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
0108045 * Added support for 3c503 boards.
0108046 */
0108047
0108048 #include "kernel.h"
0108049 #include <stdlib.h>
0108050 #include <minix/com.h>
0108051 #include <net/hton.h>
0108052 #include <net/gen/ether.h>
0108053 #include <net/gen/eth_io.h>
0108054 #include "assert.h"
0108055 INIT_ASSERT
0108056 #if __minix_vmd
0108057 #include "i386/protect.h"
0108058 #else
0108059 #include "protect.h"
0108060 #endif
0108061 #include "dp8390.h"
0108062 #include "proc.h"
0108063 #if __minix_vmd
0108064 #include "config.h"
0108065 #endif
0108066
0108067 #if ENABLE_DP8390 || __minix_vmd
0108068
0108069 #define DE_PORT_NR 2
0108070
0108071 static dpeth_t de_table[DE_PORT_NR];
0108072 static int int_pending[NR_IRQ_VECTORS];
0108073 static int dpeth_tasknr= ANY;
0108074 static u16_t eth_ign_proto;
0108075
0108076 /* Configuration */
0108077 typedef struct dp_conf
0108078 {
0108079 port_t dpc_port;
0108080 int dpc_irq;
0108081 phys_bytes dpc_mem;
0108082 char *dpc_envvar;
0108083 } dp_conf_t;
0108084
0108085 dp_conf_t dp_conf[]= /* Card addresses */
0108086 {
0108087 /* I/O port, IRQ, Buffer address, Env. var. */
0108088 { 0x280, 3, 0xD0000, "DPETH0" },
0108089 { 0x300, 5, 0xC8000, "DPETH1" },
0108090 };
0108091
0108092 /* Test if dp_conf has exactly DE_PORT_NR entries. If not then you will see
0108093 * the error: "array size is negative".
0108094 */
0108095 extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
0108096
0108097
0108098 /* Card inits configured out? */
0108099 #if !ENABLE_WDETH
0108100 #define wdeth_probe(dep) (0)
0108101 #endif
0108102 #if !ENABLE_NE2000
0108103 #define ne_probe(dep) (0)
0108104 #endif
0108105 #if !ENABLE_3C503
0108106 #define el2_probe(dep) (0)
0108107 #endif
0108108
0108109
0108110 _PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
0108111 int vectored) );
0108112 _PROTOTYPE( static void do_vread, (message *mp, int vectored) );
0108113 _PROTOTYPE( static void do_init, (message *mp) );
0108114 _PROTOTYPE( static void do_int, (dpeth_t *dep) );
0108115 _PROTOTYPE( static void do_getstat, (message *mp) );
0108116 _PROTOTYPE( static void do_stop, (message *mp) );
0108117 _PROTOTYPE( static void dp_init, (dpeth_t *dep) );
0108118 _PROTOTYPE( static void dp_confaddr, (dpeth_t *dep) );
0108119 _PROTOTYPE( static void dp_reinit, (dpeth_t *dep) );
0108120 _PROTOTYPE( static void dp_reset, (dpeth_t *dep) );
0108121 _PROTOTYPE( static void dp_check_ints, (dpeth_t *dep) );
0108122 _PROTOTYPE( static void dp_recv, (dpeth_t *dep) );
0108123 _PROTOTYPE( static void dp_send, (dpeth_t *dep) );
0108124 _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
0108125 size_t offset, size_t size, void *dst) );
0108126 _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
0108127 size_t offset, size_t size, void *dst) );
0108128 _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
0108129 size_t offset, size_t size, void *dst) );
0108130 _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
0108131 int length) );
0108132 _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
0108133 vir_bytes offset, int nic_addr, vir_bytes count) );
0108134 _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
0108135 iovec_dat_t *iovp, vir_bytes offset,
0108136 int nic_addr, vir_bytes count) );
0108137 _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
0108138 iovec_dat_t *iovp, vir_bytes offset,
0108139 int nic_addr, vir_bytes count) );
0108140 _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
0108141 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
0108142 _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
0108143 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
0108144 _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
0108145 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
0108146 _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp) );
0108147 _PROTOTYPE( static int dp_handler, (int irq) );
0108148 _PROTOTYPE( static void conf_hw, (dpeth_t *dep) );
0108149 _PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp) );
0108150 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
0108151 _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block) );
0108152 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
0108153 _PROTOTYPE( static void get_userdata, (int user_proc,
0108154 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
0108155 _PROTOTYPE( static void put_userdata, (int user_proc,
0108156 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
0108157
0108158 /*===========================================================================*
0108159 * dpeth_task *
0108160 *===========================================================================*/
0108161 void dp8390_task()
0108162 {
0108163 message m;
0108164 int i, irq, r;
0108165 dpeth_t *dep;
0108166 long v;
0108167
0108168 dpeth_tasknr= proc_number(proc_ptr);
0108169
0108170 v= 0;
0108171 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
0108172 eth_ign_proto= htons((u16_t) v);
0108173
0108174 while (TRUE)
0108175 {
0108176 if ((r= receive(ANY, &m)) != OK)
0108177 panic("dp8390: receive failed", r);
0108178
0108179 switch (m.m_type)
0108180 {
0108181 case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
0108182 case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
0108183 case DL_READ: do_vread(&m, FALSE); break;
0108184 case DL_READV: do_vread(&m, TRUE); break;
0108185 case DL_INIT: do_init(&m); break;
0108186 case DL_GETSTAT: do_getstat(&m); break;
0108187 case DL_STOP: do_stop(&m); break;
0108188 case HARD_INT:
0108189 for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
0108190 {
0108191 if (dep->de_mode != DEM_ENABLED)
0108192 continue;
0108193 assert(dep->de_flags & DEF_ENABLED);
0108194 irq= dep->de_irq;
0108195 assert(irq >= 0 && irq < NR_IRQ_VECTORS);
0108196 if (int_pending[irq])
0108197 {
0108198 int_pending[irq]= 0;
0108199 dp_check_ints(dep);
0108200 do_int(dep);
0108201 enable_irq(irq);
0108202 }
0108203 }
0108204 break;
0108205 default:
0108206 panic("dp8390: illegal message", m.m_type);
0108207 }
0108208 }
0108209 }
0108210
0108211
0108212 /*===========================================================================*
0108213 * dp_dump *
0108214 *===========================================================================*/
0108215 void dp_dump()
0108216 {
0108217 dpeth_t *dep;
0108218 int i, isr;
0108219
0108220 printf("\n");
0108221 for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
0108222 {
0108223 if (dep->de_mode == DEM_DISABLED)
0108224 printf("dp8390 port %d is disabled\n", i);
0108225 else if (dep->de_mode == DEM_SINK)
0108226 printf("dp8390 port %d is in sink mode\n", i);
0108227
0108228 if (dep->de_mode != DEM_ENABLED)
0108229 continue;
0108230
0108231 printf("dp8390 statistics of port %d:\n", i);
0108232
0108233 printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
0108234 printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
0108235 printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
0108236
0108237 printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
0108238 printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
0108239 printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
0108240
0108241 printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
0108242 printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
0108243 printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
0108244
0108245 printf("collision :%8ld\t", dep->de_stat.ets_collision);
0108246 printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
0108247 printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
0108248
0108249 printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
0108250 printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
0108251 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
0108252
0108253 printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
0108254
0108255 isr= inb_reg0(dep, DP_ISR);
0108256 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
0108257 inb_reg0(dep, DP_ISR), dep->de_flags);
0108258
0108259 if (debug)
0108260 {
0108261 int_pending[dep->de_irq]= 1;
0108262 interrupt(dpeth_tasknr);
0108263 }
0108264 }
0108265 }
0108266
0108267
0108268 /*===========================================================================*
0108269 * dp8390_stop *
0108270 *===========================================================================*/
0108271 void dp8390_stop()
0108272 {
0108273 message mess;
0108274 int i;
0108275
0108276 for (i= 0; i<DE_PORT_NR; i++)
0108277 {
0108278 if (de_table[i].de_mode != DEM_ENABLED)
0108279 continue;
0108280 mess.m_type= DL_STOP;
0108281 mess.DL_PORT= i;
0108282 do_stop(&mess);
0108283 }
0108284 }
0108285
0108286
0108287 /*===========================================================================*
0108288 * do_vwrite *
0108289 *===========================================================================*/
0108290 static void do_vwrite(mp, from_int, vectored)
0108291 message *mp;
0108292 int from_int;
0108293 int vectored;
0108294 {
0108295 int port, count, size;
0108296 int sendq_head;
0108297 dpeth_t *dep;
0108298
0108299 port = mp->DL_PORT;
0108300 count = mp->DL_COUNT;
0108301 if (port < 0 || port >= DE_PORT_NR)
0108302 panic("dp8390: illegal port", port);
0108303 dep= &de_table[port];
0108304 dep->de_client= mp->DL_PROC;
0108305
0108306 if (dep->de_mode == DEM_SINK)
0108307 {
0108308 assert(!from_int);
0108309 dep->de_flags |= DEF_PACK_SEND;
0108310 reply(dep, OK, FALSE);
0108311 return;
0108312 }
0108313 assert(dep->de_mode == DEM_ENABLED);
0108314 assert(dep->de_flags & DEF_ENABLED);
0108315 if (dep->de_flags & DEF_SEND_AVAIL)
0108316 panic("dp8390: send already in progress", NO_NUM);
0108317
0108318 sendq_head= dep->de_sendq_head;
0108319 if (dep->de_sendq[sendq_head].sq_filled)
0108320 {
0108321 if (from_int)
0108322 panic("dp8390: should not be sending\n", NO_NUM);
0108323 dep->de_sendmsg= *mp;
0108324 dep->de_flags |= DEF_SEND_AVAIL;
0108325 reply(dep, OK, FALSE);
0108326 return;
0108327 }
0108328 assert(!(dep->de_flags & DEF_PACK_SEND));
0108329
0108330 if (vectored)
0108331 {
0108332 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108333 (count > IOVEC_NR ? IOVEC_NR : count) *
0108334 sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
0108335 dep->de_write_iovec.iod_iovec_s = count;
0108336 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
0108337 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
0108338
0108339 dep->de_tmp_iovec = dep->de_write_iovec;
0108340 size = calc_iovec_size(&dep->de_tmp_iovec);
0108341 }
0108342 else
0108343 {
0108344 dep->de_write_iovec.iod_iovec[0].iov_addr =
0108345 (vir_bytes) mp->DL_ADDR;
0108346 dep->de_write_iovec.iod_iovec[0].iov_size =
0108347 mp->DL_COUNT;
0108348 dep->de_write_iovec.iod_iovec_s = 1;
0108349 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
0108350 dep->de_write_iovec.iod_iovec_addr = 0;
0108351 size= mp->DL_COUNT;
0108352 }
0108353 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
0108354 {
0108355 panic("dp8390: invalid packet size", size);
0108356 }
0108357 (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
0108358 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
0108359 size);
0108360 dep->de_sendq[sendq_head].sq_filled= TRUE;
0108361 if (dep->de_sendq_tail == sendq_head)
0108362 {
0108363 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
0108364 outb_reg0(dep, DP_TBCR1, size >> 8);
0108365 outb_reg0(dep, DP_TBCR0, size & 0xff);
0108366 outb_reg0(dep, DP_CR, CR_TXP); /* there it goes.. */
0108367 }
0108368 else
0108369 dep->de_sendq[sendq_head].sq_size= size;
0108370
0108371 if (++sendq_head == dep->de_sendq_nr)
0108372 sendq_head= 0;
0108373 assert(sendq_head < SENDQ_NR);
0108374 dep->de_sendq_head= sendq_head;
0108375
0108376 dep->de_flags |= DEF_PACK_SEND;
0108377
0108378 /* If the interrupt handler called, don't send a reply. The reply
0108379 * will be sent after all interrupts are handled.
0108380 */
0108381 if (from_int)
0108382 return;
0108383 reply(dep, OK, FALSE);
0108384
0108385 assert(dep->de_mode == DEM_ENABLED);
0108386 assert(dep->de_flags & DEF_ENABLED);
0108387 }
0108388
0108389
0108390 /*===========================================================================*
0108391 * do_vread *
0108392 *===========================================================================*/
0108393 static void do_vread(mp, vectored)
0108394 message *mp;
0108395 int vectored;
0108396 {
0108397 int port, count;
0108398 int size;
0108399 dpeth_t *dep;
0108400
0108401 port = mp->DL_PORT;
0108402 count = mp->DL_COUNT;
0108403 if (port < 0 || port >= DE_PORT_NR)
0108404 panic("dp8390: illegal port", port);
0108405 dep= &de_table[port];
0108406 dep->de_client= mp->DL_PROC;
0108407 if (dep->de_mode == DEM_SINK)
0108408 {
0108409 reply(dep, OK, FALSE);
0108410 return;
0108411 }
0108412 assert(dep->de_mode == DEM_ENABLED);
0108413 assert(dep->de_flags & DEF_ENABLED);
0108414
0108415 if(dep->de_flags & DEF_READING)
0108416 panic("dp8390: read already in progress", NO_NUM);
0108417
0108418 if (vectored)
0108419 {
0108420 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108421 (count > IOVEC_NR ? IOVEC_NR : count) *
0108422 sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
0108423 dep->de_read_iovec.iod_iovec_s = count;
0108424 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
0108425 dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
0108426
0108427 dep->de_tmp_iovec = dep->de_read_iovec;
0108428 size= calc_iovec_size(&dep->de_tmp_iovec);
0108429 }
0108430 else
0108431 {
0108432 dep->de_read_iovec.iod_iovec[0].iov_addr =
0108433 (vir_bytes) mp->DL_ADDR;
0108434 dep->de_read_iovec.iod_iovec[0].iov_size =
0108435 mp->DL_COUNT;
0108436 dep->de_read_iovec.iod_iovec_s = 1;
0108437 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
0108438 dep->de_read_iovec.iod_iovec_addr = 0;
0108439 size= count;
0108440 }
0108441 if (size < ETH_MAX_PACK_SIZE)
0108442 panic("dp8390: wrong packet size", size);
0108443 dep->de_flags |= DEF_READING;
0108444
0108445 dp_recv(dep);
0108446
0108447 if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
0108448 (DEF_READING|DEF_STOPPED))
0108449 {
0108450 /* The chip is stopped, and all arrived packets are
0108451 * delivered.
0108452 */
0108453 dp_reset(dep);
0108454 }
0108455 reply(dep, OK, FALSE);
0108456 }
0108457
0108458
0108459 /*===========================================================================*
0108460 * do_init *
0108461 *===========================================================================*/
0108462 static void do_init(mp)
0108463 message *mp;
0108464 {
0108465 int port;
0108466 dpeth_t *dep;
0108467 message reply_mess;
0108468
0108469 port = mp->DL_PORT;
0108470 if (port < 0 || port >= DE_PORT_NR)
0108471 {
0108472 reply_mess.m_type= DL_INIT_REPLY;
0108473 reply_mess.m3_i1= ENXIO;
0108474 mess_reply(mp, &reply_mess);
0108475 return;
0108476 }
0108477 dep= &de_table[port];
0108478 strcpy(dep->de_name, "dp8390#0");
0108479 dep->de_name[7] += port;
0108480 if (dep->de_mode == DEM_DISABLED)
0108481 {
0108482 /* This is the default, try to (re)locate the device. */
0108483 conf_hw(dep);
0108484 if (dep->de_mode == DEM_DISABLED)
0108485 {
0108486 /* Probe failed, or the device is configured off. */
0108487 reply_mess.m_type= DL_INIT_REPLY;
0108488 reply_mess.m3_i1= ENXIO;
0108489 mess_reply(mp, &reply_mess);
0108490 return;
0108491 }
0108492 if (dep->de_mode == DEM_ENABLED)
0108493 dp_init(dep);
0108494 }
0108495
0108496 if (dep->de_mode == DEM_SINK)
0108497 {
0108498 strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
0108499 dep->de_address.ea_addr[5] = port;
0108500 dp_confaddr(dep);
0108501 reply_mess.m_type = DL_INIT_REPLY;
0108502 reply_mess.m3_i1 = mp->DL_PORT;
0108503 reply_mess.m3_i2 = DE_PORT_NR;
0108504 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
0108505 mess_reply(mp, &reply_mess);
0108506 return;
0108507 }
0108508 assert(dep->de_mode == DEM_ENABLED);
0108509 assert(dep->de_flags & DEF_ENABLED);
0108510
0108511 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
0108512
0108513 if (mp->DL_MODE & DL_PROMISC_REQ)
0108514 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
0108515 if (mp->DL_MODE & DL_MULTI_REQ)
0108516 dep->de_flags |= DEF_MULTI;
0108517 if (mp->DL_MODE & DL_BROAD_REQ)
0108518 dep->de_flags |= DEF_BROAD;
0108519
0108520 dep->de_client = mp->m_source;
0108521 dp_reinit(dep);
0108522
0108523 reply_mess.m_type = DL_INIT_REPLY;
0108524 reply_mess.m3_i1 = mp->DL_PORT;
0108525 reply_mess.m3_i2 = DE_PORT_NR;
0108526 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
0108527
0108528 mess_reply(mp, &reply_mess);
0108529 }
0108530
0108531 /*===========================================================================*
0108532 * do_int *
0108533 *===========================================================================*/
0108534 static void do_int(dep)
0108535 dpeth_t *dep;
0108536 {
0108537 if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
0108538 reply(dep, OK, TRUE);
0108539 }
0108540
0108541
0108542 /*===========================================================================*
0108543 * do_getstat *
0108544 *===========================================================================*/
0108545 static void do_getstat(mp)
0108546 message *mp;
0108547 {
0108548 int port;
0108549 dpeth_t *dep;
0108550
0108551 port = mp->DL_PORT;
0108552 if (port < 0 || port >= DE_PORT_NR)
0108553 panic("dp8390: illegal port", port);
0108554 dep= &de_table[port];
0108555 dep->de_client= mp->DL_PROC;
0108556 if (dep->de_mode == DEM_SINK)
0108557 {
0108558 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108559 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
0108560 reply(dep, OK, FALSE);
0108561 return;
0108562 }
0108563 assert(dep->de_mode == DEM_ENABLED);
0108564 assert(dep->de_flags & DEF_ENABLED);
0108565
0108566 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
0108567 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
0108568 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
0108569
0108570 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108571 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
0108572 reply(dep, OK, FALSE);
0108573 }
0108574
0108575
0108576 /*===========================================================================*
0108577 * do_stop *
0108578 *===========================================================================*/
0108579 static void do_stop(mp)
0108580 message *mp;
0108581 {
0108582 int port;
0108583 dpeth_t *dep;
0108584
0108585 port = mp->DL_PORT;
0108586
0108587 if (port < 0 || port >= DE_PORT_NR)
0108588 panic("dp8390: illegal port", port);
0108589 dep= &de_table[port];
0108590 if (dep->de_mode == DEM_SINK)
0108591 return;
0108592 assert(dep->de_mode == DEM_ENABLED);
0108593
0108594 if (!(dep->de_flags & DEF_ENABLED))
0108595 return;
0108596
0108597 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
0108598 (dep->de_stopf)(dep);
0108599
0108600 dep->de_flags= DEF_EMPTY;
0108601 }
0108602
0108603
0108604 /*===========================================================================*
0108605 * dp_init *
0108606 *===========================================================================*/
0108607 static void dp_init(dep)
0108608 dpeth_t *dep;
0108609 {
0108610 int dp_rcr_reg;
0108611 int i;
0108612
0108613 /* General initialization */
0108614 dep->de_flags = DEF_EMPTY;
0108615 (*dep->de_initf)(dep);
0108616
0108617 dp_confaddr(dep);
0108618
0108619 if (debug)
0108620 {
0108621 printf("%s: Ethernet address ", dep->de_name);
0108622 for (i= 0; i < 6; i++)
0108623 printf("%x%c", dep->de_address.ea_addr[i],
0108624 i < 5 ? ':' : '\n');
0108625 }
0108626
0108627 /* Initialization of the dp8390 */
0108628 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
0108629 outb_reg0(dep, DP_IMR, 0);
0108630 outb_reg0(dep, DP_PSTART, dep->de_startpage);
0108631 outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
0108632 outb_reg0(dep, DP_BNRY, dep->de_startpage);
0108633 outb_reg0(dep, DP_RCR, RCR_MON);
0108634 outb_reg0(dep, DP_TCR, TCR_NORMAL);
0108635 if (dep->de_16bit)
0108636 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
0108637 else
0108638 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
0108639 outb_reg0(dep, DP_RBCR0, 0);
0108640 outb_reg0(dep, DP_RBCR1, 0);
0108641 outb_reg0(dep, DP_ISR, 0xFF);
0108642 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT);
0108643
0108644 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
0108645 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
0108646 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
0108647 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
0108648 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
0108649 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
0108650
0108651 outb_reg1(dep, DP_MAR0, 0xff);
0108652 outb_reg1(dep, DP_MAR1, 0xff);
0108653 outb_reg1(dep, DP_MAR2, 0xff);
0108654 outb_reg1(dep, DP_MAR3, 0xff);
0108655 outb_reg1(dep, DP_MAR4, 0xff);
0108656 outb_reg1(dep, DP_MAR5, 0xff);
0108657 outb_reg1(dep, DP_MAR6, 0xff);
0108658 outb_reg1(dep, DP_MAR7, 0xff);
0108659
0108660 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
0108661 outb_reg1(dep, DP_CR, CR_PS_P0 | CR_DM_ABORT);
0108662
0108663 dp_rcr_reg = 0;
0108664 if (dep->de_flags & DEF_PROMISC)
0108665 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
0108666 if (dep->de_flags & DEF_BROAD)
0108667 dp_rcr_reg |= RCR_AB;
0108668 if (dep->de_flags & DEF_MULTI)
0108669 dp_rcr_reg |= RCR_AM;
0108670 outb_reg0(dep, DP_RCR, dp_rcr_reg);
0108671 inb_reg0(dep, DP_CNTR0); /* reset counters by reading */
0108672 inb_reg0(dep, DP_CNTR1);
0108673 inb_reg0(dep, DP_CNTR2);
0108674
0108675 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
0108676 IMR_OVWE | IMR_CNTE);
0108677 outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
0108678
0108679 /* Finish the initialization. */
0108680 dep->de_flags |= DEF_ENABLED;
0108681 for (i= 0; i<dep->de_sendq_nr; i++)
0108682 dep->de_sendq[i].sq_filled= 0;
0108683 dep->de_sendq_head= 0;
0108684 dep->de_sendq_tail= 0;
0108685 if (!dep->de_prog_IO)
0108686 {
0108687 dep->de_user2nicf= dp_user2nic;
0108688 dep->de_nic2userf= dp_nic2user;
0108689 dep->de_getblockf= dp_getblock;
0108690 }
0108691 else if (dep->de_16bit)
0108692 {
0108693 dep->de_user2nicf= dp_pio16_user2nic;
0108694 dep->de_nic2userf= dp_pio16_nic2user;
0108695 dep->de_getblockf= dp_pio16_getblock;
0108696 }
0108697 else
0108698 {
0108699 dep->de_user2nicf= dp_pio8_user2nic;
0108700 dep->de_nic2userf= dp_pio8_nic2user;
0108701 dep->de_getblockf= dp_pio8_getblock;
0108702 }
0108703
0108704 /* set the interrupt handler */
0108705 put_irq_handler(dep->de_irq, dp_handler);
0108706 enable_irq(dep->de_irq);
0108707 }
0108708
0108709
0108710 /*===========================================================================*
0108711 * dp_confaddr *
0108712 *===========================================================================*/
0108713 static void dp_confaddr(dep)
0108714 dpeth_t *dep;
0108715 {
0108716 int i;
0108717 char eakey[16];
0108718 static char eafmt[]= "x:x:x:x:x:x";
0108719 long v;
0108720
0108721 /* User defined ethernet address? */
0108722 strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
0108723 strcat(eakey, "_EA");
0108724
0108725 for (i= 0; i < 6; i++)
0108726 {
0108727 v= dep->de_address.ea_addr[i];
0108728 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
0108729 break;
0108730 dep->de_address.ea_addr[i]= v;
0108731 }
0108732
0108733 if (i != 0 && i != 6)
0108734 {
0108735 /* It's all or nothing; force a panic. */
0108736 (void) env_parse(eakey, "?", 0, &v, 0L, 0L);
0108737 }
0108738 }
0108739
0108740
0108741 /*===========================================================================*
0108742 * dp_reinit *
0108743 *===========================================================================*/
0108744 static void dp_reinit(dep)
0108745 dpeth_t *dep;
0108746 {
0108747 int dp_rcr_reg;
0108748
0108749 outb_reg0(dep, DP_CR, CR_PS_P0);
0108750
0108751 dp_rcr_reg = 0;
0108752 if (dep->de_flags & DEF_PROMISC)
0108753 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
0108754 if (dep->de_flags & DEF_BROAD)
0108755 dp_rcr_reg |= RCR_AB;
0108756 if (dep->de_flags & DEF_MULTI)
0108757 dp_rcr_reg |= RCR_AM;
0108758 outb_reg0(dep, DP_RCR, dp_rcr_reg);
0108759 }
0108760
0108761
0108762 /*===========================================================================*
0108763 * dp_reset *
0108764 *===========================================================================*/
0108765 static void dp_reset(dep)
0108766 dpeth_t *dep;
0108767 {
0108768 int i;
0108769
0108770 /* Stop chip */
0108771 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
0108772 outb_reg0(dep, DP_RBCR0, 0);
0108773 outb_reg0(dep, DP_RBCR1, 0);
0108774 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
0108775 ; /* Do nothing */
0108776 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
0108777 outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
0108778 outb_reg0(dep, DP_TCR, TCR_NORMAL|TCR_OFST);
0108779
0108780 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
0108781 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
0108782 ; /* Do nothing */
0108783 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
0108784
0108785 /* Reset the transmit ring. If we were transmitting a packet, we
0108786 * pretend that the packet is processed. Higher layers will
0108787 * retransmit if the packet wasn't actually sent.
0108788 */
0108789 dep->de_sendq_head= dep->de_sendq_tail= 0;
0108790 for (i= 0; i<dep->de_sendq_nr; i++)
0108791 dep->de_sendq[i].sq_filled= 0;
0108792 dp_send(dep);
0108793 dep->de_flags &= ~DEF_STOPPED;
0108794 }
0108795
0108796
0108797 /*===========================================================================*
0108798 * dp_check_ints *
0108799 *===========================================================================*/
0108800 static void dp_check_ints(dep)
0108801 dpeth_t *dep;
0108802 {
0108803 int isr, tsr;
0108804 int size, sendq_tail;
0108805
0108806 if (!(dep->de_flags & DEF_ENABLED))
0108807 panic("dp8390: got premature interrupt", NO_NUM);
0108808
0108809 for(;;)
0108810 {
0108811 isr = inb_reg0(dep, DP_ISR);
0108812 if (!isr)
0108813 break;
0108814 outb_reg0(dep, DP_ISR, isr);
0108815 if (isr & (ISR_PTX|ISR_TXE))
0108816 {
0108817 if (isr & ISR_TXE)
0108818 {
0108819 #if DEBUG
0108820 { printf("%s: got send Error\n", dep->de_name); }
0108821 #endif
0108822 dep->de_stat.ets_sendErr++;
0108823 }
0108824 else
0108825 {
0108826 tsr = inb_reg0(dep, DP_TSR);
0108827
0108828 if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
0108829 if (!(tsr & TSR_DFR))
0108830 {
0108831 /* In most (all?) implementations of
0108832 * the dp8390, this bit is set
0108833 * when the packet is not deferred
0108834 */
0108835 dep->de_stat.ets_transDef++;
0108836 }
0108837 if (tsr & TSR_COL) dep->de_stat.ets_collision++;
0108838 if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
0108839 if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
0108840 if (tsr & TSR_FU
0108841 && ++dep->de_stat.ets_fifoUnder <= 10)
0108842 {
0108843 printf("%s: fifo underrun\n",
0108844 dep->de_name);
0108845 }
0108846 if (tsr & TSR_CDH
0108847 && ++dep->de_stat.ets_CDheartbeat <= 10)
0108848 {
0108849 printf("%s: CD heart beat failure\n",
0108850 dep->de_name);
0108851 }
0108852 if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
0108853 }
0108854 sendq_tail= dep->de_sendq_tail;
0108855
0108856 if (!(dep->de_sendq[sendq_tail].sq_filled))
0108857 {
0108858 /* Software bug? */
0108859 assert(!debug);
0108860
0108861 /* Or hardware bug? */
0108862 printf(
0108863 "%s: transmit interrupt, but not sending\n",
0108864 dep->de_name);
0108865 continue;
0108866 }
0108867 dep->de_sendq[sendq_tail].sq_filled= 0;
0108868 if (++sendq_tail == dep->de_sendq_nr)
0108869 sendq_tail= 0;
0108870 dep->de_sendq_tail= sendq_tail;
0108871 if (dep->de_sendq[sendq_tail].sq_filled)
0108872 {
0108873 size= dep->de_sendq[sendq_tail].sq_size;
0108874 outb_reg0(dep, DP_TPSR,
0108875 dep->de_sendq[sendq_tail].sq_sendpage);
0108876 outb_reg0(dep, DP_TBCR1, size >> 8);
0108877 outb_reg0(dep, DP_TBCR0, size & 0xff);
0108878 outb_reg0(dep, DP_CR, CR_TXP); /* there is goes.. */
0108879 }
0108880 if (dep->de_flags & DEF_SEND_AVAIL)
0108881 dp_send(dep);
0108882 }
0108883
0108884 if (isr & ISR_PRX)
0108885 {
0108886 /* Only call dp_recv if there is a read request */
0108887 if (dep->de_flags & DEF_READING)
0108888 dp_recv(dep);
0108889 }
0108890
0108891 if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
0108892 if (isr & ISR_CNT)
0108893 {
0108894 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
0108895 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
0108896 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
0108897 }
0108898 if (isr & ISR_OVW)
0108899 {
0108900 dep->de_stat.ets_OVW++;
0108901 #if DEBUG
0108902 { printW(); printf("%s: got overwrite warning\n", dep->de_name); }
0108903 #endif
0108904 if (dep->de_flags & DEF_READING)
0108905 {
0108906 printf(
0108907 "dp_check_ints: strange: overwrite warning and pending read request\n");
0108908 dp_recv(dep);
0108909 }
0108910 }
0108911 if (isr & ISR_RDC)
0108912 {
0108913 /* Nothing to do */
0108914 }
0108915 if (isr & ISR_RST)
0108916 {
0108917 /* this means we got an interrupt but the ethernet
0108918 * chip is shutdown. We set the flag DEF_STOPPED,
0108919 * and continue processing arrived packets. When the
0108920 * receive buffer is empty, we reset the dp8390.
0108921 */
0108922 #if DEBUG
0108923 { printW(); printf("%s: NIC stopped\n", dep->de_name); }
0108924 #endif
0108925 dep->de_flags |= DEF_STOPPED;
0108926 break;
0108927 }
0108928 }
0108929 if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
0108930 (DEF_READING|DEF_STOPPED))
0108931 {
0108932 /* The chip is stopped, and all arrived packets are
0108933 * delivered.
0108934 */
0108935 dp_reset(dep);
0108936 }
0108937 }
0108938
0108939
0108940 /*===========================================================================*
0108941 * dp_recv *
0108942 *===========================================================================*/
0108943 static void dp_recv(dep)
0108944 dpeth_t *dep;
0108945 {
0108946 dp_rcvhdr_t header;
0108947 unsigned pageno, curr, next;
0108948 vir_bytes length;
0108949 int packet_processed, r;
0108950 u16_t eth_type;
0108951
0108952 packet_processed = FALSE;
0108953 pageno = inb_reg0(dep, DP_BNRY) + 1;
0108954 if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
0108955
0108956 do
0108957 {
0108958 outb_reg0(dep, DP_CR, CR_PS_P1);
0108959 curr = inb_reg1(dep, DP_CURR);
0108960 outb_reg0(dep, DP_CR, CR_PS_P0);
0108961
0108962 if (curr == pageno) break;
0108963
0108964 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
0108965 &header);
0108966 (dep->de_getblockf)(dep, pageno, sizeof(header) +
0108967 2*sizeof(ether_addr_t), sizeof(eth_type), ð_type);
0108968
0108969 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
0108970 sizeof(dp_rcvhdr_t);
0108971 next = header.dr_next;
0108972 if (length < ETH_MIN_PACK_SIZE || length > ETH_MAX_PACK_SIZE)
0108973 {
0108974 printf("%s: packet with strange length arrived: %d\n",
0108975 dep->de_name, (int) length);
0108976 next= curr;
0108977 }
0108978 else if (next < dep->de_startpage || next >= dep->de_stoppage)
0108979 {
0108980 printf("%s: strange next page\n", dep->de_name);
0108981 next= curr;
0108982 }
0108983 else if (eth_type == eth_ign_proto)
0108984 {
0108985 /* Hack: ignore packets of a given protocol, useful
0108986 * if you share a net with 80 computers sending
0108987 * Amoeba FLIP broadcasts. (Protocol 0x8146.)
0108988 */
0108989 static int first= 1;
0108990 if (first)
0108991 {
0108992 first= 0;
0108993 printf("%s: dropping proto 0x%04x packets\n",
0108994 dep->de_name,
0108995 ntohs(eth_ign_proto));
0108996 }
0108997 dep->de_stat.ets_packetR++;
0108998 }
0108999 else if (header.dr_status & RSR_FO)
0109000 {
0109001 /* This is very serious, so we issue a warning and
0109002 * reset the buffers */
0109003 printf("%s: fifo overrun, resetting receive buffer\n",
0109004 dep->de_name);
0109005 dep->de_stat.ets_fifoOver++;
0109006 next = curr;
0109007 }
0109008 else if ((header.dr_status & RSR_PRX) &&
0109009 (dep->de_flags & DEF_ENABLED))
0109010 {
0109011 r = dp_pkt2user(dep, pageno, length);
0109012 if (r != OK)
0109013 return;
0109014
0109015 packet_processed = TRUE;
0109016 dep->de_stat.ets_packetR++;
0109017 }
0109018 if (next == dep->de_startpage)
0109019 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
0109020 else
0109021 outb_reg0(dep, DP_BNRY, next - 1);
0109022
0109023 pageno = next;
0109024 }
0109025 while (!packet_processed);
0109026 }
0109027
0109028
0109029 /*===========================================================================*
0109030 * dp_send *
0109031 *===========================================================================*/
0109032 static void dp_send(dep)
0109033 dpeth_t *dep;
0109034 {
0109035 if (!(dep->de_flags & DEF_SEND_AVAIL))
0109036 return;
0109037
0109038 dep->de_flags &= ~DEF_SEND_AVAIL;
0109039 switch(dep->de_sendmsg.m_type)
0109040 {
0109041 case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break;
0109042 case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break;
0109043 default:
0109044 panic("dp8390: wrong type:", dep->de_sendmsg.m_type);
0109045 break;
0109046 }
0109047 }
0109048
0109049
0109050 /*===========================================================================*
0109051 * dp_getblock *
0109052 *===========================================================================*/
0109053 static void dp_getblock(dep, page, offset, size, dst)
0109054 dpeth_t *dep;
0109055 int page;
0109056 size_t offset;
0109057 size_t size;
0109058 void *dst;
0109059 {
0109060 u16_t *ha;
0109061 int i;
0109062
0109063 ha = (u16_t *) dst;
0109064 offset = page * DP_PAGESIZE + offset;
0109065 assert(!(size & 1));
0109066 for (i= 0; i<size; i+=2)
0109067 {
0109068 *ha = mem_rdw(dep->de_memseg, dep->de_memoff + (offset+i));
0109069 ha++;
0109070 }
0109071 }
0109072
0109073
0109074 /*===========================================================================*
0109075 * dp_pio8_getblock *
0109076 *===========================================================================*/
0109077 static void dp_pio8_getblock(dep, page, offset, size, dst)
0109078 dpeth_t *dep;
0109079 int page;
0109080 size_t offset;
0109081 size_t size;
0109082 void *dst;
0109083 {
0109084 u8_t *ha;
0109085 int i;
0109086
0109087 ha = (u8_t *) dst;
0109088 offset = page * DP_PAGESIZE + offset;
0109089 outb_reg0(dep, DP_RBCR0, size & 0xFF);
0109090 outb_reg0(dep, DP_RBCR1, size >> 8);
0109091 outb_reg0(dep, DP_RSAR0, offset & 0xFF);
0109092 outb_reg0(dep, DP_RSAR1, offset >> 8);
0109093 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109094
0109095 for (i= 0; i<size; i++)
0109096 ha[i]= in_byte(dep->de_data_port);
0109097 }
0109098
0109099
0109100 /*===========================================================================*
0109101 * dp_pio16_getblock *
0109102 *===========================================================================*/
0109103 static void dp_pio16_getblock(dep, page, offset, size, dst)
0109104 dpeth_t *dep;
0109105 int page;
0109106 size_t offset;
0109107 size_t size;
0109108 void *dst;
0109109 {
0109110 u16_t *ha;
0109111 int i;
0109112
0109113 ha = (u16_t *) dst;
0109114 offset = page * DP_PAGESIZE + offset;
0109115 outb_reg0(dep, DP_RBCR0, size & 0xFF);
0109116 outb_reg0(dep, DP_RBCR1, size >> 8);
0109117 outb_reg0(dep, DP_RSAR0, offset & 0xFF);
0109118 outb_reg0(dep, DP_RSAR1, offset >> 8);
0109119 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109120
0109121 assert (!(size & 1));
0109122 size /= 2;
0109123 for (i= 0; i<size; i++)
0109124 ha[i]= in_word(dep->de_data_port);
0109125 }
0109126
0109127
0109128 /*===========================================================================*
0109129 * dp_pkt2user *
0109130 *===========================================================================*/
0109131 static int dp_pkt2user(dep, page, length)
0109132 dpeth_t *dep;
0109133 int page, length;
0109134 {
0109135 int last, count;
0109136
0109137 if (!(dep->de_flags & DEF_READING))
0109138 return EGENERIC;
0109139
0109140 last = page + (length - 1) / DP_PAGESIZE;
0109141 if (last >= dep->de_stoppage)
0109142 {
0109143 count = (dep->de_stoppage - page) * DP_PAGESIZE -
0109144 sizeof(dp_rcvhdr_t);
0109145
0109146 /* Save read_iovec since we need it twice. */
0109147 dep->de_tmp_iovec = dep->de_read_iovec;
0109148 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
0109149 sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
0109150 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
0109151 &dep->de_read_iovec, count, length - count);
0109152 }
0109153 else
0109154 {
0109155 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
0109156 sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
0109157 }
0109158
0109159 dep->de_read_s = length;
0109160 dep->de_flags |= DEF_PACK_RECV;
0109161 dep->de_flags &= ~DEF_READING;
0109162
0109163 return OK;
0109164 }
0109165
0109166
0109167 /*===========================================================================*
0109168 * dp_user2nic *
0109169 *===========================================================================*/
0109170 static void dp_user2nic(dep, iovp, offset, nic_addr, count)
0109171 dpeth_t *dep;
0109172 iovec_dat_t *iovp;
0109173 vir_bytes offset;
0109174 int nic_addr;
0109175 vir_bytes count;
0109176 {
0109177 phys_bytes phys_hw, phys_user;
0109178 int bytes, i;
0109179
0109180 phys_hw = dep->de_linmem + nic_addr;
0109181
0109182 i= 0;
0109183 while (count > 0)
0109184 {
0109185 if (i >= IOVEC_NR)
0109186 {
0109187 dp_next_iovec(iovp);
0109188 i= 0;
0109189 continue;
0109190 }
0109191 assert(i < iovp->iod_iovec_s);
0109192 if (offset >= iovp->iod_iovec[i].iov_size)
0109193 {
0109194 offset -= iovp->iod_iovec[i].iov_size;
0109195 i++;
0109196 continue;
0109197 }
0109198 bytes = iovp->iod_iovec[i].iov_size - offset;
0109199 if (bytes > count)
0109200 bytes = count;
0109201
0109202 phys_user = numap(iovp->iod_proc_nr,
0109203 iovp->iod_iovec[i].iov_addr + offset, bytes);
0109204 if (!phys_user)
0109205 panic("dp8390: umap failed\n", NO_NUM);
0109206 phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
0109207 count -= bytes;
0109208 phys_hw += bytes;
0109209 offset += bytes;
0109210 }
0109211 assert(count == 0);
0109212 }
0109213
0109214
0109215 /*===========================================================================*
0109216 * dp_pio8_user2nic *
0109217 *===========================================================================*/
0109218 static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
0109219 dpeth_t *dep;
0109220 iovec_dat_t *iovp;
0109221 vir_bytes offset;
0109222 int nic_addr;
0109223 vir_bytes count;
0109224 {
0109225 phys_bytes phys_user;
0109226 int bytes, i;
0109227
0109228 outb_reg0(dep, DP_ISR, ISR_RDC);
0109229
0109230 outb_reg0(dep, DP_RBCR0, count & 0xFF);
0109231 outb_reg0(dep, DP_RBCR1, count >> 8);
0109232 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109233 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109234 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
0109235
0109236 i= 0;
0109237 while (count > 0)
0109238 {
0109239 if (i >= IOVEC_NR)
0109240 {
0109241 dp_next_iovec(iovp);
0109242 i= 0;
0109243 continue;
0109244 }
0109245 assert(i < iovp->iod_iovec_s);
0109246 if (offset >= iovp->iod_iovec[i].iov_size)
0109247 {
0109248 offset -= iovp->iod_iovec[i].iov_size;
0109249 i++;
0109250 continue;
0109251 }
0109252 bytes = iovp->iod_iovec[i].iov_size - offset;
0109253 if (bytes > count)
0109254 bytes = count;
0109255
0109256 phys_user = numap(iovp->iod_proc_nr,
0109257 iovp->iod_iovec[i].iov_addr + offset, bytes);
0109258 if (!phys_user)
0109259 panic("dp8390: umap failed\n", NO_NUM);
0109260 port_write_byte(dep->de_data_port, phys_user, bytes);
0109261 count -= bytes;
0109262 offset += bytes;
0109263 }
0109264 assert(count == 0);
0109265
0109266 for (i= 0; i<100; i++)
0109267 {
0109268 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
0109269 break;
0109270 }
0109271 if (i == 100)
0109272 {
0109273 panic("dp8390: remote dma failed to complete", NO_NUM);
0109274 }
0109275 }
0109276
0109277
0109278 /*===========================================================================*
0109279 * dp_pio16_user2nic *
0109280 *===========================================================================*/
0109281 static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
0109282 dpeth_t *dep;
0109283 iovec_dat_t *iovp;
0109284 vir_bytes offset;
0109285 int nic_addr;
0109286 vir_bytes count;
0109287 {
0109288 phys_bytes phys_user;
0109289 vir_bytes ecount;
0109290 int bytes, i;
0109291 u8_t two_bytes[2];
0109292 phys_bytes phys_2bytes;
0109293 int odd_byte;
0109294
0109295 ecount= (count+1) & ~1;
0109296 phys_2bytes = vir2phys(two_bytes);
0109297 odd_byte= 0;
0109298
0109299 outb_reg0(dep, DP_ISR, ISR_RDC);
0109300 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
0109301 outb_reg0(dep, DP_RBCR1, ecount >> 8);
0109302 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109303 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109304 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
0109305
0109306 i= 0;
0109307 while (count > 0)
0109308 {
0109309 if (i >= IOVEC_NR)
0109310 {
0109311 dp_next_iovec(iovp);
0109312 i= 0;
0109313 continue;
0109314 }
0109315 assert(i < iovp->iod_iovec_s);
0109316 if (offset >= iovp->iod_iovec[i].iov_size)
0109317 {
0109318 offset -= iovp->iod_iovec[i].iov_size;
0109319 i++;
0109320 continue;
0109321 }
0109322 bytes = iovp->iod_iovec[i].iov_size - offset;
0109323 if (bytes > count)
0109324 bytes = count;
0109325
0109326 phys_user = numap(iovp->iod_proc_nr,
0109327 iovp->iod_iovec[i].iov_addr + offset, bytes);
0109328 if (!phys_user)
0109329 panic("dp8390: umap failed\n", NO_NUM);
0109330 if (odd_byte)
0109331 {
0109332 phys_copy(phys_user, phys_2bytes+1,
0109333 (phys_bytes) 1);
0109334 out_word(dep->de_data_port, *(u16_t *)two_bytes);
0109335 count--;
0109336 offset++;
0109337 bytes--;
0109338 phys_user++;
0109339 odd_byte= 0;
0109340 if (!bytes)
0109341 continue;
0109342 }
0109343 ecount= bytes & ~1;
0109344 if (ecount != 0)
0109345 {
0109346 port_write(dep->de_data_port, phys_user, ecount);
0109347 count -= ecount;
0109348 offset += ecount;
0109349 bytes -= ecount;
0109350 phys_user += ecount;
0109351 }
0109352 if (bytes)
0109353 {
0109354 assert(bytes == 1);
0109355 phys_copy(phys_user, phys_2bytes, (phys_bytes) 1);
0109356 count--;
0109357 offset++;
0109358 bytes--;
0109359 phys_user++;
0109360 odd_byte= 1;
0109361 }
0109362 }
0109363 assert(count == 0);
0109364
0109365 if (odd_byte)
0109366 out_word(dep->de_data_port, *(u16_t *)two_bytes);
0109367
0109368 for (i= 0; i<100; i++)
0109369 {
0109370 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
0109371 break;
0109372 }
0109373 if (i == 100)
0109374 {
0109375 panic("dp8390: remote dma failed to complete", NO_NUM);
0109376 }
0109377 }
0109378
0109379
0109380 /*===========================================================================*
0109381 * dp_nic2user *
0109382 *===========================================================================*/
0109383 static void dp_nic2user(dep, nic_addr, iovp, offset, count)
0109384 dpeth_t *dep;
0109385 int nic_addr;
0109386 iovec_dat_t *iovp;
0109387 vir_bytes offset;
0109388 vir_bytes count;
0109389 {
0109390 phys_bytes phys_hw, phys_user;
0109391 int bytes, i;
0109392
0109393 phys_hw = dep->de_linmem + nic_addr;
0109394
0109395 i= 0;
0109396 while (count > 0)
0109397 {
0109398 if (i >= IOVEC_NR)
0109399 {
0109400 dp_next_iovec(iovp);
0109401 i= 0;
0109402 continue;
0109403 }
0109404 assert(i < iovp->iod_iovec_s);
0109405 if (offset >= iovp->iod_iovec[i].iov_size)
0109406 {
0109407 offset -= iovp->iod_iovec[i].iov_size;
0109408 i++;
0109409 continue;
0109410 }
0109411 bytes = iovp->iod_iovec[i].iov_size - offset;
0109412 if (bytes > count)
0109413 bytes = count;
0109414
0109415 phys_user = numap(iovp->iod_proc_nr,
0109416 iovp->iod_iovec[i].iov_addr + offset, bytes);
0109417 if (!phys_user)
0109418 panic("dp8390: umap failed\n", NO_NUM);
0109419 phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
0109420 count -= bytes;
0109421 phys_hw += bytes;
0109422 offset += bytes;
0109423 }
0109424 assert(count == 0);
0109425 }
0109426
0109427
0109428 /*===========================================================================*
0109429 * dp_pio8_nic2user *
0109430 *===========================================================================*/
0109431 static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
0109432 dpeth_t *dep;
0109433 int nic_addr;
0109434 iovec_dat_t *iovp;
0109435 vir_bytes offset;
0109436 vir_bytes count;
0109437 {
0109438 phys_bytes phys_user;
0109439 int bytes, i;
0109440
0109441 outb_reg0(dep, DP_RBCR0, count & 0xFF);
0109442 outb_reg0(dep, DP_RBCR1, count >> 8);
0109443 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109444 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109445 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109446
0109447 i= 0;
0109448 while (count > 0)
0109449 {
0109450 if (i >= IOVEC_NR)
0109451 {
0109452 dp_next_iovec(iovp);
0109453 i= 0;
0109454 continue;
0109455 }
0109456 assert(i < iovp->iod_iovec_s);
0109457 if (offset >= iovp->iod_iovec[i].iov_size)
0109458 {
0109459 offset -= iovp->iod_iovec[i].iov_size;
0109460 i++;
0109461 continue;
0109462 }
0109463 bytes = iovp->iod_iovec[i].iov_size - offset;
0109464 if (bytes > count)
0109465 bytes = count;
0109466
0109467 phys_user = numap(iovp->iod_proc_nr,
0109468 iovp->iod_iovec[i].iov_addr + offset, bytes);
0109469 if (!phys_user)
0109470 panic("dp8390: umap failed\n", NO_NUM);
0109471 port_read_byte(dep->de_data_port, phys_user, bytes);
0109472 count -= bytes;
0109473 offset += bytes;
0109474 }
0109475 assert(count == 0);
0109476 }
0109477
0109478
0109479 /*===========================================================================*
0109480 * dp_pio16_nic2user *
0109481 *===========================================================================*/
0109482 static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
0109483 dpeth_t *dep;
0109484 int nic_addr;
0109485 iovec_dat_t *iovp;
0109486 vir_bytes offset;
0109487 vir_bytes count;
0109488 {
0109489 phys_bytes phys_user;
0109490 vir_bytes ecount;
0109491 int bytes, i;
0109492 u8_t two_bytes[2];
0109493 phys_bytes phys_2bytes;
0109494 int odd_byte;
0109495
0109496 ecount= (count+1) & ~1;
0109497 phys_2bytes = vir2phys(two_bytes);
0109498 odd_byte= 0;
0109499
0109500 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
0109501 outb_reg0(dep, DP_RBCR1, ecount >> 8);
0109502 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109503 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109504 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109505
0109506 i= 0;
0109507 while (count > 0)
0109508 {
0109509 if (i >= IOVEC_NR)
0109510 {
0109511 dp_next_iovec(iovp);
0109512 i= 0;
0109513 continue;
0109514 }
0109515 assert(i < iovp->iod_iovec_s);
0109516 if (offset >= iovp->iod_iovec[i].iov_size)
0109517 {
0109518 offset -= iovp->iod_iovec[i].iov_size;
0109519 i++;
0109520 continue;
0109521 }
0109522 bytes = iovp->iod_iovec[i].iov_size - offset;
0109523 if (bytes > count)
0109524 bytes = count;
0109525
0109526 phys_user = numap(iovp->iod_proc_nr,
0109527 iovp->iod_iovec[i].iov_addr + offset, bytes);
0109528 if (!phys_user)
0109529 panic("dp8390: umap failed\n", NO_NUM);
0109530 if (odd_byte)
0109531 {
0109532 phys_copy(phys_2bytes+1, phys_user, (phys_bytes) 1);
0109533 count--;
0109534 offset++;
0109535 bytes--;
0109536 phys_user++;
0109537 odd_byte= 0;
0109538 if (!bytes)
0109539 continue;
0109540 }
0109541 ecount= bytes & ~1;
0109542 if (ecount != 0)
0109543 {
0109544 port_read(dep->de_data_port, phys_user, ecount);
0109545 count -= ecount;
0109546 offset += ecount;
0109547 bytes -= ecount;
0109548 phys_user += ecount;
0109549 }
0109550 if (bytes)
0109551 {
0109552 assert(bytes == 1);
0109553 *(u16_t *)two_bytes= in_word(dep->de_data_port);
0109554 phys_copy(phys_2bytes, phys_user, (phys_bytes) 1);
0109555 count--;
0109556 offset++;
0109557 bytes--;
0109558 phys_user++;
0109559 odd_byte= 1;
0109560 }
0109561 }
0109562 assert(count == 0);
0109563 }
0109564
0109565
0109566 /*===========================================================================*
0109567 * dp_next_iovec *
0109568 *===========================================================================*/
0109569 static void dp_next_iovec(iovp)
0109570 iovec_dat_t *iovp;
0109571 {
0109572 assert(iovp->iod_iovec_s > IOVEC_NR);
0109573
0109574 iovp->iod_iovec_s -= IOVEC_NR;
0109575
0109576 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
0109577
0109578 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
0109579 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
0109580 sizeof(iovec_t), iovp->iod_iovec);
0109581 }
0109582
0109583
0109584 /*===========================================================================*
0109585 * dp_handler *
0109586 *===========================================================================*/
0109587 static int dp_handler(irq)
0109588 int irq;
0109589 {
0109590 /* DP8390 interrupt, send message and keep interrupts disabled. */
0109591
0109592 assert(irq >= 0 && irq < NR_IRQ_VECTORS);
0109593 int_pending[irq]= 1;
0109594 interrupt(dpeth_tasknr);
0109595
0109596 return 0;
0109597 }
0109598
0109599 /*===========================================================================*
0109600 * conf_hw *
0109601 *===========================================================================*/
0109602 static void conf_hw(dep)
0109603 dpeth_t *dep;
0109604 {
0109605 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
0109606
0109607 int ifnr;
0109608 dp_conf_t *dcp;
0109609
0109610 dep->de_mode= DEM_DISABLED; /* Superfluous */
0109611 ifnr= dep-de_table;
0109612
0109613 dcp= &dp_conf[ifnr];
0109614 update_conf(dep, dcp);
0109615 if (dep->de_mode != DEM_ENABLED)
0109616 return;
0109617 if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
0109618 {
0109619 printf("%s: No ethernet card found at 0x%x\n",
0109620 dep->de_name, dep->de_base_port);
0109621 dep->de_mode= DEM_DISABLED;
0109622 return;
0109623 }
0109624
0109625 /* Find a memory segment, programmed I/O should set the
0109626 * memory segment (linmem) to zero.
0109627 */
0109628 if (dep->de_linmem != 0)
0109629 {
0109630 phys2seg(&dep->de_memseg, &dep->de_memoff, dep->de_linmem);
0109631 }
0109632
0109633 /* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
0109634
0109635 dep->de_flags = DEF_EMPTY;
0109636 dep->de_stat = empty_stat;
0109637 }
0109638
0109639
0109640 /*===========================================================================*
0109641 * update_conf *
0109642 *===========================================================================*/
0109643 static void update_conf(dep, dcp)
0109644 dpeth_t *dep;
0109645 dp_conf_t *dcp;
0109646 {
0109647 long v;
0109648 static char dpc_fmt[] = "x:d:x:x";
0109649
0109650 /* Get the default settings and modify them from the environment. */
0109651 dep->de_mode= DEM_SINK;
0109652 v= dcp->dpc_port;
0109653 switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
0109654 case EP_OFF:
0109655 dep->de_mode= DEM_DISABLED;
0109656 break;
0109657 case EP_ON:
0109658 case EP_SET:
0109659 dep->de_mode= DEM_ENABLED; /* Might become disabled if
0109660 * all probes fail */
0109661 break;
0109662 }
0109663 dep->de_base_port= v;
0109664
0109665 v= dcp->dpc_irq | DEI_DEFAULT;
0109666 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
0109667 (long) NR_IRQ_VECTORS - 1);
0109668 dep->de_irq= v;
0109669
0109670 v= dcp->dpc_mem;
0109671 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
0109672 dep->de_linmem= v;
0109673
0109674 v= 0;
0109675 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
0109676 dep->de_ramsize= v;
0109677 }
0109678
0109679
0109680 /*===========================================================================*
0109681 * calc_iovec_size *
0109682 *===========================================================================*/
0109683 static int calc_iovec_size(iovp)
0109684 iovec_dat_t *iovp;
0109685 {
0109686 /* Calculate the size of a request. Note that the iovec_dat
0109687 * structure will be unusable after calc_iovec_size.
0109688 */
0109689 int size;
0109690 int i;
0109691
0109692 size= 0;
0109693 i= 0;
0109694 while (i < iovp->iod_iovec_s)
0109695 {
0109696 if (i >= IOVEC_NR)
0109697 {
0109698 dp_next_iovec(iovp);
0109699 i= 0;
0109700 continue;
0109701 }
0109702 size += iovp->iod_iovec[i].iov_size;
0109703 i++;
0109704 }
0109705 return size;
0109706 }
0109707
0109708
0109709 /*===========================================================================*
0109710 * reply *
0109711 *===========================================================================*/
0109712 static void reply(dep, err, may_block)
0109713 dpeth_t *dep;
0109714 int err;
0109715 int may_block;
0109716 {
0109717 message reply;
0109718 int status;
0109719 int r;
0109720
0109721 status = 0;
0109722 if (dep->de_flags & DEF_PACK_SEND)
0109723 status |= DL_PACK_SEND;
0109724 if (dep->de_flags & DEF_PACK_RECV)
0109725 status |= DL_PACK_RECV;
0109726
0109727 reply.m_type = DL_TASK_REPLY;
0109728 reply.DL_PORT = dep - de_table;
0109729 reply.DL_PROC = dep->de_client;
0109730 reply.DL_STAT = status | ((u32_t) err << 16);
0109731 reply.DL_COUNT = dep->de_read_s;
0109732 reply.DL_CLCK = get_uptime();
0109733 r= send(dep->de_client, &reply);
0109734
0109735 if (r == ELOCKED && may_block)
0109736 {
0109737 #if DEBUG
0109738 printW(); printf("send locked\n");
0109739 #endif
0109740 return;
0109741 }
0109742
0109743 if (r < 0)
0109744 panic("dp8390: send failed:", r);
0109745
0109746 dep->de_read_s = 0;
0109747 dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
0109748 }
0109749
0109750
0109751 /*===========================================================================*
0109752 * mess_reply *
0109753 *===========================================================================*/
0109754 static void mess_reply(req, reply_mess)
0109755 message *req;
0109756 message *reply_mess;
0109757 {
0109758 if (send(req->m_source, reply_mess) != OK)
0109759 panic("dp8390: unable to mess_reply", NO_NUM);
0109760 }
0109761
0109762
0109763 /*===========================================================================*
0109764 * get_userdata *
0109765 *===========================================================================*/
0109766 static void get_userdata(user_proc, user_addr, count, loc_addr)
0109767 int user_proc;
0109768 vir_bytes user_addr;
0109769 vir_bytes count;
0109770 void *loc_addr;
0109771 {
0109772 phys_bytes src;
0109773
0109774 src = numap(user_proc, user_addr, count);
0109775 if (!src)
0109776 panic("dp8390: umap failed", NO_NUM);
0109777
0109778 phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);
0109779 }
0109780
0109781
0109782 /*===========================================================================*
0109783 * put_userdata *
0109784 *===========================================================================*/
0109785 static void put_userdata(user_proc, user_addr, count, loc_addr)
0109786 int user_proc;
0109787 vir_bytes user_addr;
0109788 vir_bytes count;
0109789 void *loc_addr;
0109790 {
0109791 phys_bytes dst;
0109792
0109793 dst = numap(user_proc, user_addr, count);
0109794 if (!dst)
0109795 panic("dp8390: umap failed", NO_NUM);
0109796
0109797 phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);
0109798 }
0109799
0109800 #endif /* ENABLE_DP8390 */
0109801
0109802 /*
0109803 * $PchId: dp8390.c,v 1.5 1996/01/19 22:56:35 philip Exp $
0109804 */