4 * This file contains a ethernet device driver for AMD LANCE based ethernet
7 * The valid messages and their parameters are:
9 * m_type DL_ENDPT DL_COUNT DL_MODE DL_GRANT
10 * |--------------+---------+----------+---------+---------|
11 * | DL_WRITEV_S | endpt | count | | grant |
12 * |--------------|---------|----------|---------|---------|
13 * | DL_READV_S | endpt | count | | grant |
14 * |--------------|---------|----------|---------|---------|
15 * | DL_CONF | | | mode | |
16 * |--------------|---------|----------|---------|---------|
17 * | DL_GETSTAT_S | endpt | | | grant |
18 * |--------------|---------|----------|---------|---------|
19 * | hardware int | | | | |
20 * |--------------|---------|----------|---------|---------|
22 * The messages sent are:
24 * m_type DL_COUNT DL_FLAGS
25 * |---------------+----------+---------|
26 * | DL_TASK_REPLY | rd-count | flags |
27 * |---------------|----------|---------|
34 * m_type DL_STAT DL_ADDR
35 * |---------------+---------+---------------|
36 * | DL_CONF_REPLY | code | ethernet addr |
37 * |---------------|---------|---------------|
39 * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
40 * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
43 #define VERBOSE 0 /* Verbose debugging output */
44 #define LANCE_FKEY 0 /* Use function key to dump Lance stats */
46 #include <minix/drivers.h>
47 #include <minix/netdriver.h>
50 #include <net/gen/ether.h>
51 #include <net/gen/eth_io.h>
54 #include <minix/syslib.h>
55 #include <minix/endpoint.h>
56 #include <machine/pci.h>
61 static ether_card_t ec_state
;
62 static int ec_instance
;
65 typedef struct ec_conf
72 /* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */
74 ec_conf_t ec_conf
[EC_CONF_NR
]= /* Card addresses */
76 /* I/O port, IRQ, Buffer address. */
77 { 0x1000, 9, 0x00000, },
78 { 0xD000, 15, 0x00000, },
79 { 0x0000, 0, 0x00000, },
82 /* Actually, we use PCI-BIOS info. */
90 { PCI_VENDOR_ID_AMD
, PCI_DEVICE_ID_AMD_LANCE
, 0 }, /* AMD LANCE */
96 _PROTOTYPE( static void do_init
, (message
*mp
) );
97 _PROTOTYPE( static void ec_init
, (ether_card_t
*ec
) );
98 _PROTOTYPE( static void ec_confaddr
, (ether_card_t
*ec
) );
99 _PROTOTYPE( static void ec_reinit
, (ether_card_t
*ec
) );
100 _PROTOTYPE( static void ec_check_ints
, (ether_card_t
*ec
) );
101 _PROTOTYPE( static void conf_hw
, (ether_card_t
*ec
) );
102 _PROTOTYPE( static void update_conf
, (ether_card_t
*ec
, ec_conf_t
*ecp
) );
103 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
104 _PROTOTYPE( static void do_int
, (ether_card_t
*ec
) );
105 _PROTOTYPE( static void reply
, (ether_card_t
*ec
) );
106 _PROTOTYPE( static void ec_reset
, (ether_card_t
*ec
) );
107 _PROTOTYPE( static void ec_send
, (ether_card_t
*ec
) );
108 _PROTOTYPE( static void ec_recv
, (ether_card_t
*ec
) );
109 _PROTOTYPE( static void do_vwrite_s
, (message
*mp
, int from_int
) );
110 _PROTOTYPE( static void do_vread_s
, (const message
*mp
) );
111 _PROTOTYPE( static void ec_user2nic
,
112 (ether_card_t
*dep
, iovec_dat_t
*iovp
,
113 vir_bytes offset
, int nic_addr
,
115 _PROTOTYPE( static void ec_nic2user
,
116 (ether_card_t
*ec
, int nic_addr
,
117 iovec_dat_t
*iovp
, vir_bytes offset
,
119 _PROTOTYPE( static int calc_iovec_size
, (iovec_dat_t
*iovp
) );
120 _PROTOTYPE( static void ec_next_iovec
, (iovec_dat_t
*iovp
) );
121 _PROTOTYPE( static void do_getstat_s
, (message
*mp
) );
122 _PROTOTYPE( static void lance_stop
, (ether_card_t
*ec
) );
124 _PROTOTYPE( static void lance_dump
, (void) );
125 _PROTOTYPE( static void getAddressing
, (int devind
, ether_card_t
*ec
) );
127 /* probe+init LANCE cards */
128 _PROTOTYPE( static int lance_probe
, (ether_card_t
*ec
, int skip
) );
129 _PROTOTYPE( static void lance_init_card
, (ether_card_t
*ec
) );
131 /* Accesses Lance Control and Status Registers */
132 _PROTOTYPE( static u8_t in_byte
, (port_t port
) );
133 _PROTOTYPE( static u16_t in_word
, (port_t port
) );
134 _PROTOTYPE( static void out_word
, (port_t port
, u16_t value
) );
135 _PROTOTYPE( static u16_t read_csr
, (port_t ioaddr
, u16_t csrno
) );
136 _PROTOTYPE( static void write_csr
, (port_t ioaddr
, u16_t csrno
, u16_t value
));
140 typedef unsigned long Address
;
142 #define virt_to_bus(x) (vir2phys((unsigned long)x))
143 unsigned long vir2phys( unsigned long x
)
148 if ( (r
=sys_umap( SELF
, VM_D
, x
, 4, &value
)) != OK
) {
149 printf("lance: umap of 0x%lx failed\n",x
);
150 panic("sys_umap failed: %d", r
);
156 /* DMA limitations */
157 #define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */
159 #define CORRECT_DMA_MEM() ( (virt_to_bus(lance_buf + sizeof(struct lance_interface)) & ~DMA_ADDR_MASK) == 0 )
161 #define ETH_FRAME_LEN 1518
163 #define LANCE_MUST_PAD 0x00000001
164 #define LANCE_ENABLE_AUTOSELECT 0x00000002
165 #define LANCE_SELECT_PHONELINE 0x00000004
166 #define LANCE_MUST_UNRESET 0x00000008
168 static const struct lance_chip_type
174 {0x0000, "LANCE 7990", /* Ancient lance chip. */
175 LANCE_MUST_PAD
+ LANCE_MUST_UNRESET
},
176 {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */
177 LANCE_ENABLE_AUTOSELECT
},
178 {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
179 LANCE_ENABLE_AUTOSELECT
},
180 {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
181 LANCE_ENABLE_AUTOSELECT
},
182 {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
183 LANCE_ENABLE_AUTOSELECT
},
184 {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
185 LANCE_ENABLE_AUTOSELECT
},
186 {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
187 LANCE_ENABLE_AUTOSELECT
},
188 {0x2626, "PCnet/HomePNA 79C978",
189 LANCE_ENABLE_AUTOSELECT
|LANCE_SELECT_PHONELINE
},
190 {0x0, "PCnet (unknown)",
191 LANCE_ENABLE_AUTOSELECT
},
194 /* ############## for LANCE device ############## */
195 #define LANCE_ETH_ADDR 0x0
196 #define LANCE_DATA 0x10
197 #define LANCE_ADDR 0x12
198 #define LANCE_RESET 0x14
199 #define LANCE_BUS_IF 0x16
200 #define LANCE_TOTAL_SIZE 0x18
202 /* Use 2^4=16 {Rx,Tx} buffers */
203 #define LANCE_LOG_RX_BUFFERS 4
204 #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
205 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
206 #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
208 #define LANCE_LOG_TX_BUFFERS 4
209 #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
210 #define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
211 #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
213 /* for lance_interface */
214 struct lance_init_block
217 unsigned char phys_addr
[6];
218 unsigned long filter
[2];
227 unsigned char addr
[4];
229 short buf_length
; /* 2s complement */
237 unsigned char addr
[4];
239 short buf_length
; /* 2s complement */
243 struct lance_interface
245 struct lance_init_block init_block
;
246 struct lance_rx_head rx_ring
[RX_RING_SIZE
];
247 struct lance_tx_head tx_ring
[TX_RING_SIZE
];
248 unsigned char rbuf
[RX_RING_SIZE
][ETH_FRAME_LEN
];
249 unsigned char tbuf
[TX_RING_SIZE
][ETH_FRAME_LEN
];
252 /* =============== global variables =============== */
253 /* AKA the stuff that really should have been in ether_card_t */
254 static struct lance_interface
*lp
;
255 #define LANCE_BUF_SIZE (sizeof(struct lance_interface))
256 static char *lance_buf
= NULL
;
257 static int rx_slot_nr
= 0; /* Rx-slot number */
258 static int tx_slot_nr
= 0; /* Tx-slot number */
259 static int cur_tx_slot_nr
= 0; /* Tx-slot number */
260 static char isstored
[TX_RING_SIZE
]; /* Tx-slot in-use */
262 phys_bytes lance_buf_phys
;
264 /* SEF functions and variables. */
265 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
266 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
267 FORWARD
_PROTOTYPE( void sef_cb_signal_handler
, (int signo
) );
268 EXTERN
char **env_argv
;
270 /*===========================================================================*
272 *===========================================================================*/
273 int main( int argc
, char **argv
)
280 /* SEF local startup. */
281 env_setargs(argc
, argv
);
289 sys_irqenable(&ec
->ec_hook
);
291 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
292 panic("netdriver_receive failed: %d", r
);
295 sys_irqdisable(&ec
->ec_hook
);
297 if (is_ipc_notify(ipc_status
)) {
298 switch(_ENDPOINT_P(m
.m_source
)) {
303 if (ec
->mode
== EC_ENABLED
)
305 ec
->ec_int_pending
= 0;
311 panic("illegal notify source: %d", m
.m_source
);
314 /* get next message */
321 do_vwrite_s(&m
, FALSE
);
333 panic("illegal message: %d", m
.m_type
);
340 /*===========================================================================*
341 * sef_local_startup *
342 *===========================================================================*/
343 PRIVATE
void sef_local_startup()
345 /* Register init callbacks. */
346 sef_setcb_init_fresh(sef_cb_init_fresh
);
347 sef_setcb_init_lu(sef_cb_init_fresh
);
348 sef_setcb_init_restart(sef_cb_init_fresh
);
350 /* Register live update callbacks. */
351 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready
);
352 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree
);
354 /* Register signal callbacks. */
355 sef_setcb_signal_handler(sef_cb_signal_handler
);
357 /* Let SEF perform startup. */
361 /*===========================================================================*
362 * sef_cb_init_fresh *
363 *===========================================================================*/
364 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*UNUSED(info
))
366 /* Initialize the lance driver. */
369 int r
, fkeys
, sfkeys
;
374 bit_set( sfkeys
, 7 );
375 if ( (r
= fkey_map(&fkeys
, &sfkeys
)) != OK
)
376 printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r
);
380 (void) env_parse("instance", "d", 0, &v
, 0, 255);
381 ec_instance
= (int) v
;
383 /* Announce we are up! */
384 netdriver_announce();
389 /*===========================================================================*
390 * sef_cb_signal_handler *
391 *===========================================================================*/
392 PRIVATE
void sef_cb_signal_handler(int signo
)
395 /* Only check for termination signal, ignore anything else. */
396 if (signo
!= SIGTERM
) return;
398 if (ec_state
.mode
== EC_ENABLED
)
399 lance_stop(&ec_state
);
402 printf("LANCE driver stopped.\n");
408 /*===========================================================================*
410 *===========================================================================*/
411 static void lance_dump()
415 unsigned short ioaddr
;
419 if (ec
->mode
== EC_DISABLED
)
420 printf("lance instance %d is disabled\n", ec_instance
);
421 else if (ec
->mode
== EC_SINK
)
422 printf("lance instance %d is in sink mode\n", ec_instance
);
424 if (ec
->mode
!= EC_ENABLED
)
427 printf("lance statistics of instance %d:\n", ec_instance
);
429 printf("recvErr :%8ld\t", ec
->eth_stat
.ets_recvErr
);
430 printf("sendErr :%8ld\t", ec
->eth_stat
.ets_sendErr
);
431 printf("OVW :%8ld\n", ec
->eth_stat
.ets_OVW
);
433 printf("CRCerr :%8ld\t", ec
->eth_stat
.ets_CRCerr
);
434 printf("frameAll :%8ld\t", ec
->eth_stat
.ets_frameAll
);
435 printf("missedP :%8ld\n", ec
->eth_stat
.ets_missedP
);
437 printf("packetR :%8ld\t", ec
->eth_stat
.ets_packetR
);
438 printf("packetT :%8ld\t", ec
->eth_stat
.ets_packetT
);
439 printf("transDef :%8ld\n", ec
->eth_stat
.ets_transDef
);
441 printf("collision :%8ld\t", ec
->eth_stat
.ets_collision
);
442 printf("transAb :%8ld\t", ec
->eth_stat
.ets_transAb
);
443 printf("carrSense :%8ld\n", ec
->eth_stat
.ets_carrSense
);
445 printf("fifoUnder :%8ld\t", ec
->eth_stat
.ets_fifoUnder
);
446 printf("fifoOver :%8ld\t", ec
->eth_stat
.ets_fifoOver
);
447 printf("CDheartbeat:%8ld\n", ec
->eth_stat
.ets_CDheartbeat
);
449 printf("OWC :%8ld\t", ec
->eth_stat
.ets_OWC
);
451 ioaddr
= ec
->ec_port
;
452 isr
= read_csr(ioaddr
, LANCE_CSR0
);
453 printf("isr = 0x%x, flags = 0x%x\n", isr
,
456 printf("irq = %d\tioadr = 0x%x\n", ec
->ec_irq
, ec
->ec_port
);
458 csr
= read_csr(ioaddr
, LANCE_CSR0
);
459 printf("CSR0: 0x%x\n", csr
);
460 csr
= read_csr(ioaddr
, LANCE_CSR3
);
461 printf("CSR3: 0x%x\n", csr
);
462 csr
= read_csr(ioaddr
, LANCE_CSR4
);
463 printf("CSR4: 0x%x\n", csr
);
464 csr
= read_csr(ioaddr
, LANCE_CSR5
);
465 printf("CSR5: 0x%x\n", csr
);
466 csr
= read_csr(ioaddr
, LANCE_CSR15
);
467 printf("CSR15: 0x%x\n", csr
);
470 /*===========================================================================*
472 *===========================================================================*/
473 static void do_init(mp
)
481 if(!lance_buf
&& !(lance_buf
= alloc_contig(LANCE_BUF_SIZE
, AC_ALIGN4K
|AC_LOWER16M
, &lance_buf_phys
))) {
482 panic("alloc_contig failed: %d", LANCE_BUF_SIZE
);
486 strcpy(ec
->port_name
, "lance#0");
487 ec
->port_name
[6] += ec_instance
;
489 if (ec
->mode
== EC_DISABLED
)
491 /* This is the default, try to (re)locate the device. */
492 /* only try to enable if memory is correct for DMA */
493 if ( CORRECT_DMA_MEM() )
499 printf("LANCE: DMA denied because address out of range\n" );
502 if (ec
->mode
== EC_DISABLED
)
504 /* Probe failed, or the device is configured off. */
505 reply_mess
.m_type
= DL_CONF_REPLY
;
506 reply_mess
.DL_STAT
= ENXIO
;
507 mess_reply(mp
, &reply_mess
);
510 if (ec
->mode
== EC_ENABLED
)
514 if (ec
->mode
== EC_SINK
)
516 ec
->mac_address
.ea_addr
[0] =
517 ec
->mac_address
.ea_addr
[1] =
518 ec
->mac_address
.ea_addr
[2] =
519 ec
->mac_address
.ea_addr
[3] =
520 ec
->mac_address
.ea_addr
[4] =
521 ec
->mac_address
.ea_addr
[5] = 0;
523 reply_mess
.m_type
= DL_CONF_REPLY
;
524 reply_mess
.DL_STAT
= OK
;
525 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= ec
->mac_address
;
526 mess_reply(mp
, &reply_mess
);
529 assert(ec
->mode
== EC_ENABLED
);
530 assert(ec
->flags
& ECF_ENABLED
);
532 ec
->flags
&= ~(ECF_PROMISC
| ECF_MULTI
| ECF_BROAD
);
534 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
535 ec
->flags
|= ECF_PROMISC
| ECF_MULTI
| ECF_BROAD
;
536 if (mp
->DL_MODE
& DL_MULTI_REQ
)
537 ec
->flags
|= ECF_MULTI
;
538 if (mp
->DL_MODE
& DL_BROAD_REQ
)
539 ec
->flags
|= ECF_BROAD
;
543 reply_mess
.m_type
= DL_CONF_REPLY
;
544 reply_mess
.DL_STAT
= OK
;
545 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= ec
->mac_address
;
547 mess_reply(mp
, &reply_mess
);
551 /*===========================================================================*
553 *===========================================================================*/
554 static void do_int(ec
)
557 if (ec
->flags
& (ECF_PACK_SEND
| ECF_PACK_RECV
))
562 /*===========================================================================*
564 *===========================================================================*/
565 static void conf_hw(ec
)
568 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
573 ec
->mode
= EC_DISABLED
; /* Superfluous */
575 /* Pick a default configuration. This hardly matters anymore. */
576 confnr
= MIN(ec_instance
, EC_CONF_NR
-1);
578 ecp
= &ec_conf
[confnr
];
579 update_conf(ec
, ecp
);
580 if (ec
->mode
!= EC_ENABLED
)
583 if (!lance_probe(ec
, ec_instance
))
585 printf("%s: No ethernet card found on PCI-BIOS info.\n",
587 ec
->mode
= EC_DISABLED
;
591 /* XXX */ if (ec
->ec_linmem
== 0) ec
->ec_linmem
= 0xFFFF0000;
593 ec
->flags
= ECF_EMPTY
;
594 ec
->eth_stat
= empty_stat
;
598 /*===========================================================================*
600 *===========================================================================*/
601 static void update_conf(ec
, ecp
)
607 static char ec_fmt
[] = "x:d:x:x";
609 /* Get the default settings and modify them from the environment. */
610 strcpy(eckey
, "LANCE0");
611 eckey
[5] += ec_instance
;
614 switch (env_parse(eckey
, ec_fmt
, 0, &v
, 0x0000L
, 0xFFFFL
))
617 ec
->mode
= EC_DISABLED
;
622 ec
->mode
= EC_ENABLED
; /* Might become disabled if
629 v
= ecp
->ec_irq
| DEI_DEFAULT
;
630 (void) env_parse(eckey
, ec_fmt
, 1, &v
, 0L, (long) NR_IRQ_VECTORS
- 1);
634 (void) env_parse(eckey
, ec_fmt
, 2, &v
, 0L, 0xFFFFFL
);
638 (void) env_parse(eckey
, ec_fmt
, 3, &v
, 0x2000L
, 0x8000L
);
643 /*===========================================================================*
645 *===========================================================================*/
646 static void ec_init(ec
)
651 /* General initialization */
652 ec
->flags
= ECF_EMPTY
;
653 lance_init_card(ec
); /* Get mac_address, etc ...*/
658 printf("%s: Ethernet address ", ec
->port_name
);
659 for (i
= 0; i
< 6; i
++)
660 printf("%x%c", ec
->mac_address
.ea_addr
[i
],
664 /* Finish the initialization */
665 ec
->flags
|= ECF_ENABLED
;
667 /* Set the interrupt handler */
668 ec
->ec_hook
= ec
->ec_irq
;
669 if ((r
=sys_irqsetpolicy(ec
->ec_irq
, 0, &ec
->ec_hook
)) != OK
)
670 printf("lance: error, couldn't set IRQ policy: %d\n", r
);
676 /*===========================================================================*
678 *===========================================================================*/
679 static void reply(ec
)
686 if (ec
->flags
& ECF_PACK_SEND
)
687 flags
|= DL_PACK_SEND
;
688 if (ec
->flags
& ECF_PACK_RECV
)
689 flags
|= DL_PACK_RECV
;
691 reply
.m_type
= DL_TASK_REPLY
;
692 reply
.DL_FLAGS
= flags
;
693 reply
.DL_COUNT
= ec
->read_s
;
695 r
= send(ec
->client
, &reply
);
697 panic("send failed: %d", r
);
700 ec
->flags
&= ~(ECF_PACK_SEND
| ECF_PACK_RECV
);
704 /*===========================================================================*
706 *===========================================================================*/
707 static void mess_reply(req
, reply_mess
)
711 if (send(req
->m_source
, reply_mess
) != OK
)
712 panic("unable to mess_reply");
716 /*===========================================================================*
718 *===========================================================================*/
719 static void ec_confaddr(ec
)
724 static char eafmt
[]= "x:x:x:x:x:x";
727 /* User defined ethernet address? */
728 strcpy(eakey
, "LANCE0_EA");
729 eakey
[5] += ec_instance
;
731 for (i
= 0; i
< 6; i
++)
733 v
= ec
->mac_address
.ea_addr
[i
];
734 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
736 ec
->mac_address
.ea_addr
[i
]= v
;
739 if (i
!= 0 && i
!= 6)
741 /* It's all or nothing; force a panic. */
742 (void) env_parse(eakey
, "?", 0, &v
, 0L, 0L);
747 /*===========================================================================*
749 *===========================================================================*/
750 static void ec_reinit(ec
)
754 unsigned short ioaddr
= ec
->ec_port
;
757 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
760 tx_slot_nr
= cur_tx_slot_nr
= 0;
761 for (i
=0; i
<TX_RING_SIZE
; i
++)
763 lp
->tx_ring
[i
].u
.base
= 0;
767 /* re-init Rx-ring */
769 for (i
=0; i
<RX_RING_SIZE
; i
++)
771 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
772 lp
->rx_ring
[i
].u
.addr
[3] |= 0x80;
775 /* Set 'Receive Mode' */
776 if (ec
->flags
& ECF_PROMISC
)
778 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_PROM
);
782 if (ec
->flags
& (ECF_BROAD
| ECF_MULTI
))
784 write_csr(ioaddr
, LANCE_CSR15
, 0x0000);
788 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_DRCVBC
);
792 /* start && enable interrupt */
793 write_csr(ioaddr
, LANCE_CSR0
,
794 LANCE_CSR0_IDON
|LANCE_CSR0_IENA
|LANCE_CSR0_STRT
);
799 /*===========================================================================*
801 *===========================================================================*/
802 static void ec_check_ints(ec
)
805 int must_restart
= 0;
808 unsigned short ioaddr
= ec
->ec_port
;
810 if (!(ec
->flags
& ECF_ENABLED
))
811 panic("got premature interrupt");
816 printf("ETH: Reading ISR...");
818 isr
= read_csr(ioaddr
, LANCE_CSR0
);
819 if (isr
& (LANCE_CSR0_ERR
|LANCE_CSR0_RINT
|LANCE_CSR0_TINT
)) {
820 write_csr(ioaddr
, LANCE_CSR0
,
821 isr
& ~(LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
|LANCE_CSR0_STOP
822 |LANCE_CSR0_STRT
|LANCE_CSR0_INIT
) );
824 write_csr(ioaddr
, LANCE_CSR0
,
825 LANCE_CSR0_BABL
|LANCE_CSR0_CERR
|LANCE_CSR0_MISS
|LANCE_CSR0_MERR
826 |LANCE_CSR0_IDON
|LANCE_CSR0_IENA
);
828 #define ISR_RST 0x0000
830 if ((isr
& (LANCE_CSR0_TINT
|LANCE_CSR0_RINT
|LANCE_CSR0_MISS
831 |LANCE_CSR0_BABL
|LANCE_CSR0_ERR
)) == 0x0000)
839 if (isr
& LANCE_CSR0_MISS
)
842 printf("RX Missed Frame\n");
844 ec
->eth_stat
.ets_recvErr
++;
846 if ((isr
& LANCE_CSR0_BABL
) || (isr
& LANCE_CSR0_TINT
))
848 if (isr
& LANCE_CSR0_BABL
)
851 printf("TX Timeout\n");
853 ec
->eth_stat
.ets_sendErr
++;
855 if (isr
& LANCE_CSR0_TINT
)
860 /* status check: restart if needed. */
861 status
= lp
->tx_ring
[cur_tx_slot_nr
].u
.base
;
864 if (status
& 0x40000000)
866 status
= lp
->tx_ring
[cur_tx_slot_nr
].misc
;
867 ec
->eth_stat
.ets_sendErr
++;
869 ec
->eth_stat
.ets_transAb
++;
871 ec
->eth_stat
.ets_carrSense
++;
873 ec
->eth_stat
.ets_OWC
++;
876 ec
->eth_stat
.ets_fifoUnder
++;
882 if (status
& 0x18000000)
883 ec
->eth_stat
.ets_collision
++;
884 ec
->eth_stat
.ets_packetT
++;
887 /* transmit a packet on the next slot if it exists. */
889 if (isstored
[cur_tx_slot_nr
]==1)
891 /* free the tx-slot just transmitted */
892 isstored
[cur_tx_slot_nr
]=0;
893 cur_tx_slot_nr
= (++cur_tx_slot_nr
) & TX_RING_MOD_MASK
;
895 /* next tx-slot is ready? */
896 if (isstored
[cur_tx_slot_nr
]==1)
903 panic("got premature TX INT..");
907 lp
->tx_ring
[cur_tx_slot_nr
].u
.addr
[3] = 0x83;
908 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
);
913 /* we set a buffered message in the slot if it exists. */
914 /* and transmit it, if needed. */
915 if (ec
->flags
& ECF_SEND_AVAIL
)
918 if (isr
& LANCE_CSR0_RINT
)
928 ec
->flags
= ECF_STOPPED
;
935 /* ??? cf. lance driver on linux */
936 if (must_restart
== 1)
939 printf("ETH: restarting...\n");
942 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
944 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STRT
);
948 if ((ec
->flags
& (ECF_READING
|ECF_STOPPED
)) == (ECF_READING
|ECF_STOPPED
))
951 printf("ETH: resetting...\n");
957 /*===========================================================================*
959 *===========================================================================*/
960 static void ec_reset(ec
)
963 /* Stop/start the chip, and clear all RX,TX-slots */
964 unsigned short ioaddr
= ec
->ec_port
;
968 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
970 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STRT
);
973 tx_slot_nr
= cur_tx_slot_nr
= 0;
974 for (i
=0; i
<TX_RING_SIZE
; i
++)
976 lp
->tx_ring
[i
].u
.base
= 0;
980 /* re-init Rx-ring */
982 for (i
=0; i
<RX_RING_SIZE
; i
++)
984 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
985 lp
->rx_ring
[i
].u
.addr
[3] |= 0x80;
988 /* store a buffered message on the slot if exists */
990 ec
->flags
&= ~ECF_STOPPED
;
993 /*===========================================================================*
995 *===========================================================================*/
996 static void ec_send(ec
)
999 /* from ec_check_ints() or ec_reset(). */
1000 /* this function proccesses the buffered message. (slot/transmit) */
1001 if (!(ec
->flags
& ECF_SEND_AVAIL
))
1004 ec
->flags
&= ~ECF_SEND_AVAIL
;
1005 switch(ec
->sendmsg
.m_type
)
1007 case DL_WRITEV_S
: do_vwrite_s(&ec
->sendmsg
, TRUE
); break;
1009 panic("wrong type: %d", ec
->sendmsg
.m_type
);
1014 /*===========================================================================*
1016 *===========================================================================*/
1017 static void do_vread_s(const message
*mp
)
1024 ec
->client
= mp
->m_source
;
1025 count
= mp
->DL_COUNT
;
1027 r
= sys_safecopyfrom(mp
->DL_ENDPT
, mp
->DL_GRANT
, 0,
1028 (vir_bytes
)ec
->read_iovec
.iod_iovec
,
1029 (count
> IOVEC_NR
? IOVEC_NR
: count
) *
1030 sizeof(iovec_s_t
), D
);
1032 panic("do_vread_s: sys_safecopyfrom failed: %d", r
);
1033 ec
->read_iovec
.iod_iovec_s
= count
;
1034 ec
->read_iovec
.iod_proc_nr
= mp
->DL_ENDPT
;
1035 ec
->read_iovec
.iod_grant
= (cp_grant_id_t
) mp
->DL_GRANT
;
1036 ec
->read_iovec
.iod_iovec_offset
= 0;
1038 ec
->tmp_iovec
= ec
->read_iovec
;
1040 ec
->flags
|= ECF_READING
;
1044 if ((ec
->flags
& (ECF_READING
|ECF_STOPPED
)) == (ECF_READING
|ECF_STOPPED
))
1049 /*===========================================================================*
1051 *===========================================================================*/
1052 static void ec_recv(ec
)
1056 int packet_processed
;
1058 unsigned short ioaddr
= ec
->ec_port
;
1060 if ((ec
->flags
& ECF_READING
)==0)
1062 if (!(ec
->flags
& ECF_ENABLED
))
1065 /* we check all the received slots until find a properly received packet */
1066 packet_processed
= FALSE
;
1067 while (!packet_processed
)
1069 status
= lp
->rx_ring
[rx_slot_nr
].u
.base
>> 24;
1070 if ( (status
& 0x80) == 0x00 )
1072 status
= lp
->rx_ring
[rx_slot_nr
].u
.base
>> 24;
1078 ec
->eth_stat
.ets_recvErr
++;
1080 ec
->eth_stat
.ets_fifoOver
++;
1082 ec
->eth_stat
.ets_CRCerr
++;
1084 ec
->eth_stat
.ets_OVW
++;
1086 ec
->eth_stat
.ets_frameAll
++;
1091 ec
->eth_stat
.ets_packetR
++;
1092 length
= lp
->rx_ring
[rx_slot_nr
].msg_length
;
1096 ec_nic2user(ec
, (int)(lp
->rbuf
[rx_slot_nr
]),
1097 &ec
->read_iovec
, 0, length
);
1099 ec
->read_s
= length
;
1100 ec
->flags
|= ECF_PACK_RECV
;
1101 ec
->flags
&= ~ECF_READING
;
1102 packet_processed
= TRUE
;
1104 /* set up this slot again, and we move to the next slot */
1105 lp
->rx_ring
[rx_slot_nr
].buf_length
= -ETH_FRAME_LEN
;
1106 lp
->rx_ring
[rx_slot_nr
].u
.addr
[3] |= 0x80;
1108 write_csr(ioaddr
, LANCE_CSR0
,
1109 LANCE_CSR0_BABL
|LANCE_CSR0_CERR
|LANCE_CSR0_MISS
1110 |LANCE_CSR0_MERR
|LANCE_CSR0_IDON
|LANCE_CSR0_IENA
);
1112 rx_slot_nr
= (++rx_slot_nr
) & RX_RING_MOD_MASK
;
1119 /*===========================================================================*
1121 *===========================================================================*/
1122 static void do_vwrite_s(mp
, from_int
)
1126 int count
, check
, r
;
1128 unsigned short ioaddr
;
1132 ec
->client
= mp
->m_source
;
1133 count
= mp
->DL_COUNT
;
1135 if (isstored
[tx_slot_nr
]==1)
1137 /* all slots are used, so this message is buffered */
1139 ec
->flags
|= ECF_SEND_AVAIL
;
1144 /* convert the message to write_iovec */
1145 r
= sys_safecopyfrom(mp
->DL_ENDPT
, mp
->DL_GRANT
, 0,
1146 (vir_bytes
)ec
->write_iovec
.iod_iovec
,
1147 (count
> IOVEC_NR
? IOVEC_NR
: count
) *
1148 sizeof(iovec_s_t
), D
);
1150 panic("do_vwrite_s: sys_safecopyfrom failed: %d", r
);
1151 ec
->write_iovec
.iod_iovec_s
= count
;
1152 ec
->write_iovec
.iod_proc_nr
= mp
->DL_ENDPT
;
1153 ec
->write_iovec
.iod_grant
= mp
->DL_GRANT
;
1154 ec
->write_iovec
.iod_iovec_offset
= 0;
1156 ec
->tmp_iovec
= ec
->write_iovec
;
1157 ec
->write_s
= calc_iovec_size(&ec
->tmp_iovec
);
1159 /* copy write_iovec to the slot on DMA address */
1160 ec_user2nic(ec
, &ec
->write_iovec
, 0,
1161 (int)(lp
->tbuf
[tx_slot_nr
]), ec
->write_s
);
1162 /* set-up for transmitting, and transmit it if needed. */
1163 lp
->tx_ring
[tx_slot_nr
].buf_length
= -ec
->write_s
;
1164 lp
->tx_ring
[tx_slot_nr
].misc
= 0x0;
1165 lp
->tx_ring
[tx_slot_nr
].u
.base
1166 = virt_to_bus(lp
->tbuf
[tx_slot_nr
]) & 0xffffff;
1167 isstored
[tx_slot_nr
]=1;
1168 if (cur_tx_slot_nr
== tx_slot_nr
)
1172 tx_slot_nr
= (++tx_slot_nr
) & TX_RING_MOD_MASK
;
1176 ioaddr
= ec
->ec_port
;
1177 lp
->tx_ring
[cur_tx_slot_nr
].u
.addr
[3] = 0x83;
1178 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
);
1181 ec
->flags
|= ECF_PACK_SEND
;
1183 /* reply by calling do_int() if this function is called from interrupt. */
1190 /*===========================================================================*
1192 *===========================================================================*/
1193 static void ec_user2nic(ec
, iovp
, offset
, nic_addr
, count
)
1207 ec_next_iovec(iovp
);
1211 if (offset
>= iovp
->iod_iovec
[i
].iov_size
)
1213 offset
-= iovp
->iod_iovec
[i
].iov_size
;
1217 bytes
= iovp
->iod_iovec
[i
].iov_size
- offset
;
1221 if ( (r
=sys_safecopyfrom(iovp
->iod_proc_nr
,
1222 iovp
->iod_iovec
[i
].iov_grant
, offset
,
1223 nic_addr
, bytes
, D
)) != OK
)
1224 panic("ec_user2nic: sys_safecopyfrom failed: %d", r
);
1232 /*===========================================================================*
1234 *===========================================================================*/
1235 static void ec_nic2user(ec
, nic_addr
, iovp
, offset
, count
)
1249 ec_next_iovec(iovp
);
1253 if (offset
>= iovp
->iod_iovec
[i
].iov_size
)
1255 offset
-= iovp
->iod_iovec
[i
].iov_size
;
1259 bytes
= iovp
->iod_iovec
[i
].iov_size
- offset
;
1262 if ( (r
=sys_safecopyto( iovp
->iod_proc_nr
, iovp
->iod_iovec
[i
].iov_grant
,
1263 offset
, nic_addr
, bytes
, D
)) != OK
)
1264 panic("ec_nic2user: sys_safecopyto failed: %d", r
);
1273 /*===========================================================================*
1275 *===========================================================================*/
1276 static int calc_iovec_size(iovec_dat_t
*iovp
)
1282 while (i
< iovp
->iod_iovec_s
)
1286 ec_next_iovec(iovp
);
1290 size
+= iovp
->iod_iovec
[i
].iov_size
;
1297 /*===========================================================================*
1299 *===========================================================================*/
1300 static void ec_next_iovec(iovp
)
1305 iovp
->iod_iovec_s
-= IOVEC_NR
;
1306 iovp
->iod_iovec_offset
+= IOVEC_NR
* sizeof(iovec_s_t
);
1308 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_grant
,
1309 iovp
->iod_iovec_offset
,
1310 (vir_bytes
)iovp
->iod_iovec
,
1311 (iovp
->iod_iovec_s
> IOVEC_NR
?
1312 IOVEC_NR
: iovp
->iod_iovec_s
) *
1313 sizeof(iovec_s_t
), D
);
1315 panic("ec_next_iovec: sys_safecopyfrom failed: %d", r
);
1319 /*===========================================================================*
1321 *===========================================================================*/
1322 static void do_getstat_s(mp
)
1330 r
= sys_safecopyto(mp
->DL_ENDPT
, mp
->DL_GRANT
, 0,
1331 (vir_bytes
)&ec
->eth_stat
, sizeof(ec
->eth_stat
), D
);
1334 panic("do_getstat_s: sys_safecopyto failed: %d", r
);
1336 mp
->m_type
= DL_STAT_REPLY
;
1337 r
= send(mp
->m_source
, mp
);
1339 panic("do_getstat_s: send failed: %d", r
);
1342 /*===========================================================================*
1344 *===========================================================================*/
1345 static void lance_stop(ec
)
1348 unsigned short ioaddr
;
1350 if (!(ec
->flags
& ECF_ENABLED
))
1353 ioaddr
= ec
->ec_port
;
1356 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
1359 in_word(ioaddr
+LANCE_RESET
);
1361 ec
->flags
= ECF_EMPTY
;
1364 /*===========================================================================*
1366 *===========================================================================*/
1367 static void getAddressing(devind
, ec
)
1371 unsigned int membase
, ioaddr
;
1374 for (reg
= PCI_BASE_ADDRESS_0
; reg
<= PCI_BASE_ADDRESS_5
; reg
+= 4)
1376 ioaddr
= pci_attr_r32(devind
, reg
);
1378 if ((ioaddr
& PCI_BASE_ADDRESS_IO_MASK
) == 0
1379 || (ioaddr
& PCI_BASE_ADDRESS_SPACE_IO
) == 0)
1381 /* Strip the I/O address out of the returned value */
1382 ioaddr
&= PCI_BASE_ADDRESS_IO_MASK
;
1383 /* Get the memory base address */
1384 membase
= pci_attr_r32(devind
, PCI_BASE_ADDRESS_1
);
1385 /* KK: Get the IRQ number */
1386 irq
= pci_attr_r8(devind
, PCI_INTERRUPT_PIN
);
1388 irq
= pci_attr_r8(devind
, PCI_INTERRUPT_LINE
);
1390 ec
->ec_linmem
= membase
;
1391 ec
->ec_port
= ioaddr
;
1396 /*===========================================================================*
1398 *===========================================================================*/
1399 static int lance_probe(ec
, skip
)
1403 unsigned short pci_cmd
;
1404 unsigned short ioaddr
;
1405 int lance_version
, chip_version
;
1406 int devind
, just_one
, i
, r
;
1410 if ((ec
->ec_pcibus
| ec
->ec_pcidev
| ec
->ec_pcifunc
) != 0)
1412 /* Look for specific PCI device */
1413 r
= pci_find_dev(ec
->ec_pcibus
, ec
->ec_pcidev
,
1414 ec
->ec_pcifunc
, &devind
);
1417 printf("%s: no PCI found at %d.%d.%d\n",
1418 ec
->port_name
, ec
->ec_pcibus
,
1419 ec
->ec_pcidev
, ec
->ec_pcifunc
);
1422 pci_ids(devind
, &vid
, &did
);
1427 r
= pci_first_dev(&devind
, &vid
, &did
);
1435 for (i
= 0; pcitab
[i
].vid
!= 0; i
++)
1437 if (pcitab
[i
].vid
!= vid
)
1439 if (pcitab
[i
].did
!= did
)
1441 if (pcitab
[i
].checkclass
) {
1442 panic("class check not implemented");
1446 if (pcitab
[i
].vid
!= 0)
1448 if (just_one
|| !skip
)
1456 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
1457 ec
->port_name
, vid
, did
,
1459 ec
->ec_pcidev
, ec
->ec_pcifunc
);
1463 r
= pci_next_dev(&devind
, &vid
, &did
);
1468 pci_reserve(devind
);
1470 getAddressing(devind
, ec
);
1473 /* ===== Bus Master ? ===== */
1474 pci_cmd
= pci_attr_r32(devind
, PCI_CR
);
1475 if (!(pci_cmd
& PCI_COMMAND_MASTER
)) {
1476 pci_cmd
|= PCI_COMMAND_MASTER
;
1477 pci_attr_w32(devind
, PCI_CR
, pci_cmd
);
1480 /* ===== Probe Details ===== */
1481 ioaddr
= ec
->ec_port
;
1484 in_word(ioaddr
+LANCE_RESET
);
1486 if (read_csr(ioaddr
, LANCE_CSR0
) != LANCE_CSR0_STOP
)
1488 ec
->mode
=EC_DISABLED
;
1491 /* Probe Chip Version */
1492 out_word(ioaddr
+LANCE_ADDR
, 88); /* Get the version of the chip */
1493 if (in_word(ioaddr
+LANCE_ADDR
) != 88)
1497 chip_version
= read_csr(ioaddr
, LANCE_CSR88
);
1498 chip_version
|= read_csr(ioaddr
, LANCE_CSR89
) << 16;
1500 if ((chip_version
& 0xfff) != 0x3)
1502 ec
->mode
=EC_DISABLED
;
1504 chip_version
= (chip_version
>> 12) & 0xffff;
1505 for (lance_version
= 1; chip_table
[lance_version
].id_number
!= 0;
1507 if (chip_table
[lance_version
].id_number
== chip_version
)
1512 printf("%s: %s at %X:%d\n",
1513 ec
->port_name
, chip_table
[lance_version
].name
,
1514 ec
->ec_port
, ec
->ec_irq
);
1517 return lance_version
;
1520 /*===========================================================================*
1522 *===========================================================================*/
1523 static void lance_init_card(ec
)
1527 Address l
= (vir_bytes
)lance_buf
;
1528 unsigned short ioaddr
= ec
->ec_port
;
1530 /* ============= setup init_block(cf. lance_probe1) ================ */
1531 /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */
1533 lp
= (struct lance_interface
*)l
;
1535 /* disable Tx and Rx */
1536 lp
->init_block
.mode
= LANCE_CSR15_DTX
|LANCE_CSR15_DRX
;
1537 lp
->init_block
.filter
[0] = lp
->init_block
.filter
[1] = 0x0;
1538 /* using multiple Rx/Tx buffer */
1539 lp
->init_block
.rx_ring
1540 = (virt_to_bus(&lp
->rx_ring
) & 0xffffff) | RX_RING_LEN_BITS
;
1541 lp
->init_block
.tx_ring
1542 = (virt_to_bus(&lp
->tx_ring
) & 0xffffff) | TX_RING_LEN_BITS
;
1544 l
= virt_to_bus(&lp
->init_block
);
1545 write_csr(ioaddr
, LANCE_CSR1
, (unsigned short)l
);
1546 write_csr(ioaddr
, LANCE_CSR2
, (unsigned short)(l
>> 16));
1547 write_csr(ioaddr
, LANCE_CSR4
,
1548 LANCE_CSR4_APAD_XMT
|LANCE_CSR4_MFCOM
|LANCE_CSR4_RCVCCOM
1549 |LANCE_CSR4_TXSTRTM
|LANCE_CSR4_JABM
);
1551 /* ============= Get MAC address (cf. lance_probe1) ================ */
1552 for (i
= 0; i
< 6; ++i
)
1553 ec
->mac_address
.ea_addr
[i
]=in_byte(ioaddr
+LANCE_ETH_ADDR
+i
);
1555 /* ============ (re)start init_block(cf. lance_reset) =============== */
1556 /* Reset the LANCE */
1557 (void)in_word(ioaddr
+LANCE_RESET
);
1559 /* ----- Re-initialize the LANCE ----- */
1560 /* Set station address */
1561 for (i
= 0; i
< 6; ++i
)
1562 lp
->init_block
.phys_addr
[i
] = ec
->mac_address
.ea_addr
[i
];
1563 /* Preset the receive ring headers */
1564 for (i
=0; i
<RX_RING_SIZE
; i
++)
1566 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
1568 lp
->rx_ring
[i
].u
.base
= virt_to_bus(lp
->rbuf
[i
]) & 0xffffff;
1569 /* we set the top byte as the very last thing */
1570 lp
->rx_ring
[i
].u
.addr
[3] = 0x80;
1572 /* Preset the transmitting ring headers */
1573 for (i
=0; i
<TX_RING_SIZE
; i
++)
1575 lp
->tx_ring
[i
].u
.base
= 0;
1578 /* enable Rx and Tx */
1579 lp
->init_block
.mode
= 0x0;
1581 l
= (Address
)virt_to_bus(&lp
->init_block
);
1582 write_csr(ioaddr
, LANCE_CSR1
, (short)l
);
1583 write_csr(ioaddr
, LANCE_CSR2
, (short)(l
>> 16));
1584 write_csr(ioaddr
, LANCE_CSR4
,
1585 LANCE_CSR4_APAD_XMT
|LANCE_CSR4_MFCOM
|LANCE_CSR4_RCVCCOM
1586 |LANCE_CSR4_TXSTRTM
|LANCE_CSR4_JABM
);
1588 /* ----- start when init done. ----- */
1590 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
1592 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_INIT
);
1594 for (i
= 10000; i
> 0; --i
)
1595 if (read_csr(ioaddr
, LANCE_CSR0
) & LANCE_CSR0_IDON
)
1598 /* Set 'Multicast Table' */
1601 write_csr(ioaddr
, LANCE_CSR8
+ i
, 0xffff);
1604 /* Set 'Receive Mode' */
1605 if (ec
->flags
& ECF_PROMISC
)
1607 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_PROM
);
1611 if (ec
->flags
& (ECF_BROAD
| ECF_MULTI
))
1613 write_csr(ioaddr
, LANCE_CSR15
, 0x0000);
1617 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_DRCVBC
);
1621 /* start && enable interrupt */
1622 write_csr(ioaddr
, LANCE_CSR0
,
1623 LANCE_CSR0_IDON
|LANCE_CSR0_IENA
|LANCE_CSR0_STRT
);
1628 /*===========================================================================*
1630 *===========================================================================*/
1631 static u8_t
in_byte(port_t port
)
1636 r
= sys_inb(port
, &value
);
1638 panic("sys_inb failed: %d", r
);
1642 /*===========================================================================*
1644 *===========================================================================*/
1645 static u16_t
in_word(port_t port
)
1650 r
= sys_inw(port
, &value
);
1652 panic("sys_inw failed: %d", r
);
1657 /*===========================================================================*
1659 *===========================================================================*/
1660 static void out_word(port_t port
, u16_t value
)
1664 r
= sys_outw(port
, value
);
1666 panic("sys_outw failed: %d", r
);
1669 /*===========================================================================*
1671 *===========================================================================*/
1672 static u16_t
read_csr(port_t ioaddr
, u16_t csrno
)
1674 out_word(ioaddr
+LANCE_ADDR
, csrno
);
1675 return in_word(ioaddr
+LANCE_DATA
);
1678 /*===========================================================================*
1680 *===========================================================================*/
1681 static void write_csr(port_t ioaddr
, u16_t csrno
, u16_t value
)
1683 out_word(ioaddr
+LANCE_ADDR
, csrno
);
1684 out_word(ioaddr
+LANCE_DATA
, value
);