1 | /*
|
---|
2 | * fxp.c
|
---|
3 | *
|
---|
4 | * This file contains an ethernet device driver for Intel 82557, 82558,
|
---|
5 | * 82559, 82550, and 82562 fast ethernet controllers.
|
---|
6 | *
|
---|
7 | * The valid messages and their parameters are:
|
---|
8 | *
|
---|
9 | * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
|
---|
10 | * |------------+----------+---------+----------+---------+---------|
|
---|
11 | * | HARDINT | | | | | |
|
---|
12 | * |------------|----------|---------|----------|---------|---------|
|
---|
13 | * | DL_WRITE | port nr | proc nr | count | mode | address |
|
---|
14 | * |------------|----------|---------|----------|---------|---------|
|
---|
15 | * | DL_WRITEV | port nr | proc nr | count | mode | address |
|
---|
16 | * |------------|----------|---------|----------|---------|---------|
|
---|
17 | * | DL_READ | port nr | proc nr | count | | address |
|
---|
18 | * |------------|----------|---------|----------|---------|---------|
|
---|
19 | * | DL_READV | port nr | proc nr | count | | address |
|
---|
20 | * |------------|----------|---------|----------|---------|---------|
|
---|
21 | * | DL_INIT | port nr | proc nr | mode | | address |
|
---|
22 | * |------------|----------|---------|----------|---------|---------|
|
---|
23 | * | DL_GETSTAT | port nr | proc nr | | | address |
|
---|
24 | * |------------|----------|---------|----------|---------|---------|
|
---|
25 | * | DL_STOP | port_nr | | | | |
|
---|
26 | * |------------|----------|---------|----------|---------|---------|
|
---|
27 | *
|
---|
28 | * The messages sent are:
|
---|
29 | *
|
---|
30 | * m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
|
---|
31 | * |-------------+----------+---------+----------+---------+---------|
|
---|
32 | * |DL_TASK_REPLY| port nr | proc nr | rd-count | err|stat| clock |
|
---|
33 | * |-------------+----------+---------+----------+---------+---------|
|
---|
34 | *
|
---|
35 | * m_type m3_i1 m3_i2 m3_ca1
|
---|
36 | * |-------------+---------+-----------+---------------|
|
---|
37 | * |DL_INIT_REPLY| port nr | last port | ethernet addr |
|
---|
38 | * |-------------+---------+-----------+---------------|
|
---|
39 | *
|
---|
40 | * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
|
---|
41 | */
|
---|
42 |
|
---|
43 | #include "../drivers.h"
|
---|
44 |
|
---|
45 | #include <stdlib.h>
|
---|
46 | #include <net/hton.h>
|
---|
47 | #include <net/gen/ether.h>
|
---|
48 | #include <net/gen/eth_io.h>
|
---|
49 | #include <ibm/pci.h>
|
---|
50 |
|
---|
51 | #include <timers.h>
|
---|
52 |
|
---|
53 | #define tmra_ut timer_t
|
---|
54 | #define tmra_inittimer(tp) tmr_inittimer(tp)
|
---|
55 | #define Proc_number(p) proc_number(p)
|
---|
56 | #define debug 0
|
---|
57 | #define RAND_UPDATE /**/
|
---|
58 | #define printW() ((void)0)
|
---|
59 | #define vm_1phys2bus(p) (p)
|
---|
60 |
|
---|
61 | #include "assert.h"
|
---|
62 | #include "fxp.h"
|
---|
63 | #include "mii.h"
|
---|
64 |
|
---|
65 | /* Number of receive buffers */
|
---|
66 | #define N_RX_BUF 40
|
---|
67 |
|
---|
68 | /* Number of transmit buffers */
|
---|
69 | #define N_TX_BUF 4
|
---|
70 |
|
---|
71 | /* I/O vectors are handled IOVEC_NR entries at a time. */
|
---|
72 | #define IOVEC_NR 16
|
---|
73 |
|
---|
74 | /* Configuration */
|
---|
75 | #define FXP_ENVVAR "FXPETH"
|
---|
76 |
|
---|
77 | struct pcitab
|
---|
78 | {
|
---|
79 | u16_t vid;
|
---|
80 | u16_t did;
|
---|
81 | int checkclass;
|
---|
82 | };
|
---|
83 |
|
---|
84 | PRIVATE struct pcitab pcitab_fxp[]=
|
---|
85 | {
|
---|
86 | { 0x8086, 0x1229, 0 }, /* Intel 82557, etc. */
|
---|
87 | { 0x8086, 0x2449, 0 }, /* Intel 82801BA/BAM/CA/CAM */
|
---|
88 |
|
---|
89 | { 0x0000, 0x0000, 0 }
|
---|
90 | };
|
---|
91 |
|
---|
92 | #define FXP_PORT_NR 1 /* Minix */
|
---|
93 |
|
---|
94 | typedef int irq_hook_t;
|
---|
95 |
|
---|
96 | /* Translate a pointer to a field in a structure to a pointer to the structure
|
---|
97 | * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
|
---|
98 | */
|
---|
99 | #define structof(type, field, ptr) \
|
---|
100 | ((type *) (((char *) (ptr)) - offsetof(type, field)))
|
---|
101 |
|
---|
102 | #define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
---|
103 |
|
---|
104 | static timer_t *fxp_timers= NULL;
|
---|
105 | static clock_t fxp_next_timeout= 0;
|
---|
106 |
|
---|
107 | static void micro_delay(unsigned long usecs);
|
---|
108 |
|
---|
109 | /* ignore interrupt for the moment */
|
---|
110 | #define interrupt(x) 0
|
---|
111 |
|
---|
112 | char buffer[70*1024];
|
---|
113 |
|
---|
114 | typedef struct fxp
|
---|
115 | {
|
---|
116 | port_t fxp_base_port;
|
---|
117 | int fxp_mode;
|
---|
118 | int fxp_got_int;
|
---|
119 | int fxp_send_int;
|
---|
120 | int fxp_flags;
|
---|
121 | int fxp_client;
|
---|
122 | int fxp_features; /* Needed? */
|
---|
123 | int fxp_irq;
|
---|
124 | int fxp_type; /* What kind of hardware */
|
---|
125 | int fxp_ee_addrlen; /* #EEPROM address bits */
|
---|
126 | int fxp_tx_alive;
|
---|
127 | int fxp_need_reset;
|
---|
128 |
|
---|
129 | /* Rx */
|
---|
130 | vir_bytes fxp_read_s;
|
---|
131 | int fxp_rx_nbuf;
|
---|
132 | int fxp_rx_bufsize;
|
---|
133 | struct rfd *fxp_rx_buf;
|
---|
134 | phys_bytes fxp_rx_busaddr;
|
---|
135 | int fxp_rx_head;
|
---|
136 | int fxp_rx_need_restart;
|
---|
137 | int fxp_need_conf; /* Re-configure after draining send
|
---|
138 | * queue
|
---|
139 | */
|
---|
140 |
|
---|
141 | /* Tx */
|
---|
142 | int fxp_tx_nbuf;
|
---|
143 | int fxp_tx_bufsize;
|
---|
144 | struct tx *fxp_tx_buf;
|
---|
145 | phys_bytes fxp_tx_busaddr;
|
---|
146 | int fxp_tx_idle;
|
---|
147 | int fxp_tx_head;
|
---|
148 | int fxp_tx_tail;
|
---|
149 | int fxp_tx_threshold;
|
---|
150 |
|
---|
151 | /* Link status */
|
---|
152 | int fxp_report_link;
|
---|
153 | int fxp_link_up;
|
---|
154 | int fxp_mii_busy;
|
---|
155 | u16_t fxp_mii_scr;
|
---|
156 |
|
---|
157 | /* PCI related */
|
---|
158 | int fxp_seen; /* TRUE iff device available */
|
---|
159 | u8_t fxp_pcibus;
|
---|
160 | u8_t fxp_pcidev;
|
---|
161 | u8_t fxp_pcifunc;
|
---|
162 |
|
---|
163 | /* 'large' items */
|
---|
164 | irq_hook_t fxp_hook;
|
---|
165 | ether_addr_t fxp_address;
|
---|
166 | message fxp_rx_mess;
|
---|
167 | message fxp_tx_mess;
|
---|
168 | struct sc fxp_stat;
|
---|
169 | u8_t fxp_conf_bytes[CC_BYTES_NR];
|
---|
170 | char fxp_name[sizeof("fxp#n")];
|
---|
171 | iovec_t fxp_iovec[IOVEC_NR];
|
---|
172 | }
|
---|
173 | fxp_t;
|
---|
174 |
|
---|
175 | /* fxp_mode */
|
---|
176 | #define FM_DISABLED 0x0
|
---|
177 | #define FM_ENABLED 0x1
|
---|
178 |
|
---|
179 | /* fxp_flags */
|
---|
180 | #define FF_EMPTY 0x000
|
---|
181 | #define FF_PACK_SENT 0x001
|
---|
182 | #define FF_PACK_RECV 0x002
|
---|
183 | #define FF_SEND_AVAIL 0x004
|
---|
184 | #define FF_READING 0x010
|
---|
185 | #define FF_PROMISC 0x040
|
---|
186 | #define FF_MULTI 0x080
|
---|
187 | #define FF_BROAD 0x100
|
---|
188 | #define FF_ENABLED 0x200
|
---|
189 |
|
---|
190 | /* fxp_features */
|
---|
191 | #define FFE_NONE 0x0
|
---|
192 |
|
---|
193 | /* fxp_type */
|
---|
194 | #define FT_UNKNOWN 0x0
|
---|
195 | #define FT_82557 0x1
|
---|
196 | #define FT_82558A 0x2
|
---|
197 | #define FT_82559 0x4
|
---|
198 |
|
---|
199 | static fxp_t fxp_table[FXP_PORT_NR];
|
---|
200 |
|
---|
201 | static int fxp_tasknr= ANY;
|
---|
202 | static u16_t eth_ign_proto;
|
---|
203 | static tmra_ut fxp_watchdog;
|
---|
204 | static char *progname;
|
---|
205 |
|
---|
206 | extern int errno;
|
---|
207 |
|
---|
208 | #define fxp_inb(port, offset) (do_inb((port) + (offset)))
|
---|
209 | #define fxp_inw(port, offset) (do_inw((port) + (offset)))
|
---|
210 | #define fxp_inl(port, offset) (do_inl((port) + (offset)))
|
---|
211 | #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
|
---|
212 | #define fxp_outw(port, offset, value) (do_outw((port) + (offset), (value)))
|
---|
213 | #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
|
---|
214 |
|
---|
215 | _PROTOTYPE( static void fxp_init, (message *mp) );
|
---|
216 | _PROTOTYPE( static void fxp_pci_conf, (void) );
|
---|
217 | _PROTOTYPE( static int fxp_probe, (fxp_t *fp) );
|
---|
218 | _PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp) );
|
---|
219 | _PROTOTYPE( static void fxp_init_hw, (fxp_t *fp) );
|
---|
220 | _PROTOTYPE( static void fxp_init_buf, (fxp_t *fp) );
|
---|
221 | _PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp) );
|
---|
222 | _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) );
|
---|
223 | _PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) );
|
---|
224 | _PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
|
---|
225 | int vectored) );
|
---|
226 | _PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
|
---|
227 | int vectored) );
|
---|
228 | _PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) );
|
---|
229 | _PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
|
---|
230 | phys_bytes bus_addr, int check_idle) );
|
---|
231 | _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
|
---|
232 | phys_bytes bus_addr, int check_idle) );
|
---|
233 | _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
|
---|
234 | _PROTOTYPE( static void fxp_getstat, (message *mp) );
|
---|
235 | _PROTOTYPE( static void fxp_getname, (message *mp) );
|
---|
236 | _PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
|
---|
237 | _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) );
|
---|
238 | _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp) );
|
---|
239 | _PROTOTYPE( static int fxp_link_changed, (fxp_t *fp) );
|
---|
240 | _PROTOTYPE( static void fxp_report_link, (fxp_t *fp) );
|
---|
241 | _PROTOTYPE( static void fxp_stop, (void));
|
---|
242 | _PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
|
---|
243 | _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
|
---|
244 | _PROTOTYPE( static void put_userdata, (int user_proc,
|
---|
245 | vir_bytes user_addr, vir_bytes count, void *loc_addr) );
|
---|
246 | _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) );
|
---|
247 | _PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
|
---|
248 | _PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
|
---|
249 | _PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
|
---|
250 | tmr_func_t watchdog) );
|
---|
251 | _PROTOTYPE( static void fxp_expire_timers,(void) );
|
---|
252 | _PROTOTYPE( static u8_t do_inb, (port_t port) );
|
---|
253 | _PROTOTYPE( static u32_t do_inl, (port_t port) );
|
---|
254 | _PROTOTYPE( static void do_outb, (port_t port, u8_t v) );
|
---|
255 | _PROTOTYPE( static void do_outl, (port_t port, u32_t v) );
|
---|
256 |
|
---|
257 | /*===========================================================================*
|
---|
258 | * main *
|
---|
259 | *===========================================================================*/
|
---|
260 | int main(int argc, char *argv[])
|
---|
261 | {
|
---|
262 | message m;
|
---|
263 | int i, r, tasknr;
|
---|
264 | fxp_t *fp;
|
---|
265 | long v;
|
---|
266 |
|
---|
267 | if ((fxp_tasknr= getprocnr())<0)
|
---|
268 | panic("FXP", "couldn't get proc nr", errno);
|
---|
269 |
|
---|
270 | if (argc < 1)
|
---|
271 | panic("FXP", "A head which at this time has no name", NO_NUM);
|
---|
272 | (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
|
---|
273 |
|
---|
274 | v= 0;
|
---|
275 | #if 0
|
---|
276 | (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
|
---|
277 | #endif
|
---|
278 | eth_ign_proto= htons((u16_t) v);
|
---|
279 |
|
---|
280 | #if 0 /* What about memory allocation? */
|
---|
281 | /* Claim buffer memory now under Minix, before MM takes it all. */
|
---|
282 | for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)
|
---|
283 | fxp_init_buf(fp);
|
---|
284 | #endif
|
---|
285 |
|
---|
286 | /* Try to notify inet that we are present (again) */
|
---|
287 | r = _pm_findproc("inet", &tasknr);
|
---|
288 | if (r == OK)
|
---|
289 | notify(tasknr);
|
---|
290 |
|
---|
291 | while (TRUE)
|
---|
292 | {
|
---|
293 | if ((r= receive(ANY, &m)) != OK)
|
---|
294 | panic("FXP","receive failed", r);
|
---|
295 |
|
---|
296 | switch (m.m_type)
|
---|
297 | {
|
---|
298 | case DEV_PING: notify(m.m_source); continue;
|
---|
299 | case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
|
---|
300 | case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
|
---|
301 | #if 0
|
---|
302 | case DL_READ: fxp_vread(&m, FALSE); break;
|
---|
303 | #endif
|
---|
304 | case DL_READV: fxp_readv(&m, FALSE, TRUE); break;
|
---|
305 | case DL_INIT: fxp_init(&m); break;
|
---|
306 | case DL_GETSTAT: fxp_getstat(&m); break;
|
---|
307 | case DL_GETNAME: fxp_getname(&m); break;
|
---|
308 | case HARD_INT:
|
---|
309 | for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
|
---|
310 | {
|
---|
311 | if (fp->fxp_mode != FM_ENABLED)
|
---|
312 | continue;
|
---|
313 | fxp_handler(fp);
|
---|
314 |
|
---|
315 | r= sys_irqenable(&fp->fxp_hook);
|
---|
316 | if (r != OK)
|
---|
317 | panic("FXP","unable enable interrupts", r);
|
---|
318 |
|
---|
319 | if (!fp->fxp_got_int)
|
---|
320 | continue;
|
---|
321 | fp->fxp_got_int= 0;
|
---|
322 | assert(fp->fxp_flags & FF_ENABLED);
|
---|
323 | fxp_check_ints(fp);
|
---|
324 | }
|
---|
325 | break;
|
---|
326 | case SYS_SIG: {
|
---|
327 | sigset_t sigset = m.NOTIFY_ARG;
|
---|
328 | if (sigismember(&sigset, SIGKSTOP)) fxp_stop();
|
---|
329 | break;
|
---|
330 | }
|
---|
331 | case PROC_EVENT: break;
|
---|
332 | case SYN_ALARM: fxp_expire_timers(); break;
|
---|
333 | default:
|
---|
334 | panic("FXP"," illegal message", m.m_type);
|
---|
335 | }
|
---|
336 | }
|
---|
337 | }
|
---|
338 |
|
---|
339 | /*===========================================================================*
|
---|
340 | * fxp_init *
|
---|
341 | *===========================================================================*/
|
---|
342 | static void fxp_init(mp)
|
---|
343 | message *mp;
|
---|
344 | {
|
---|
345 | static int first_time= 1;
|
---|
346 |
|
---|
347 | int port;
|
---|
348 | fxp_t *fp;
|
---|
349 | message reply_mess;
|
---|
350 |
|
---|
351 | if (first_time)
|
---|
352 | {
|
---|
353 | first_time= 0;
|
---|
354 | fxp_pci_conf(); /* Configure PCI devices. */
|
---|
355 |
|
---|
356 | tmra_inittimer(&fxp_watchdog);
|
---|
357 | tmr_arg(&fxp_watchdog)->ta_int= 0;
|
---|
358 | fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
|
---|
359 | }
|
---|
360 |
|
---|
361 | port = mp->DL_PORT;
|
---|
362 | if (port < 0 || port >= FXP_PORT_NR)
|
---|
363 | {
|
---|
364 | reply_mess.m_type= DL_INIT_REPLY;
|
---|
365 | reply_mess.m3_i1= ENXIO;
|
---|
366 | mess_reply(mp, &reply_mess);
|
---|
367 | return;
|
---|
368 | }
|
---|
369 | fp= &fxp_table[port];
|
---|
370 | if (fp->fxp_mode == FM_DISABLED)
|
---|
371 | {
|
---|
372 | /* This is the default, try to (re)locate the device. */
|
---|
373 | fxp_conf_hw(fp);
|
---|
374 | if (fp->fxp_mode == FM_DISABLED)
|
---|
375 | {
|
---|
376 | /* Probe failed, or the device is configured off. */
|
---|
377 | reply_mess.m_type= DL_INIT_REPLY;
|
---|
378 | reply_mess.m3_i1= ENXIO;
|
---|
379 | mess_reply(mp, &reply_mess);
|
---|
380 | return;
|
---|
381 | }
|
---|
382 | if (fp->fxp_mode == FM_ENABLED)
|
---|
383 | fxp_init_hw(fp);
|
---|
384 | fxp_report_link(fp);
|
---|
385 | }
|
---|
386 |
|
---|
387 | assert(fp->fxp_mode == FM_ENABLED);
|
---|
388 | assert(fp->fxp_flags & FF_ENABLED);
|
---|
389 |
|
---|
390 | fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
|
---|
391 |
|
---|
392 | if (mp->DL_MODE & DL_PROMISC_REQ)
|
---|
393 | fp->fxp_flags |= FF_PROMISC;
|
---|
394 | if (mp->DL_MODE & DL_MULTI_REQ)
|
---|
395 | fp->fxp_flags |= FF_MULTI;
|
---|
396 | if (mp->DL_MODE & DL_BROAD_REQ)
|
---|
397 | fp->fxp_flags |= FF_BROAD;
|
---|
398 |
|
---|
399 | fp->fxp_client = mp->m_source;
|
---|
400 | fxp_rec_mode(fp);
|
---|
401 |
|
---|
402 | reply_mess.m_type = DL_INIT_REPLY;
|
---|
403 | reply_mess.m3_i1 = mp->DL_PORT;
|
---|
404 | reply_mess.m3_i2 = FXP_PORT_NR;
|
---|
405 | *(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
|
---|
406 |
|
---|
407 | mess_reply(mp, &reply_mess);
|
---|
408 | }
|
---|
409 |
|
---|
410 | /*===========================================================================*
|
---|
411 | * fxp_pci_conf *
|
---|
412 | *===========================================================================*/
|
---|
413 | static void fxp_pci_conf()
|
---|
414 | {
|
---|
415 | static char envvar[] = FXP_ENVVAR "#";
|
---|
416 | static char envfmt[] = "*:d.d.d";
|
---|
417 |
|
---|
418 | int i, h;
|
---|
419 | fxp_t *fp;
|
---|
420 | long v;
|
---|
421 |
|
---|
422 | for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
|
---|
423 | {
|
---|
424 | strcpy(fp->fxp_name, "fxp#0");
|
---|
425 | fp->fxp_name[4] += i;
|
---|
426 | fp->fxp_seen= FALSE;
|
---|
427 | fp->fxp_features= FFE_NONE;
|
---|
428 | envvar[sizeof(FXP_ENVVAR)-1]= '0'+i;
|
---|
429 | #if 0
|
---|
430 | if (getenv(envvar) != NULL)
|
---|
431 | {
|
---|
432 | if (strcmp(getenv(envvar), "off") == 0)
|
---|
433 | {
|
---|
434 | fp->fxp_pcibus= 255;
|
---|
435 | continue;
|
---|
436 | }
|
---|
437 | if (!env_prefix(envvar, "pci"))
|
---|
438 | env_panic(envvar);
|
---|
439 | }
|
---|
440 | #endif
|
---|
441 |
|
---|
442 | v= 0;
|
---|
443 | #if 0
|
---|
444 | (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
|
---|
445 | #endif
|
---|
446 | fp->fxp_pcibus= v;
|
---|
447 | v= 0;
|
---|
448 | #if 0
|
---|
449 | (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
|
---|
450 | #endif
|
---|
451 | fp->fxp_pcidev= v;
|
---|
452 | v= 0;
|
---|
453 | #if 0
|
---|
454 | (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
|
---|
455 | #endif
|
---|
456 | fp->fxp_pcifunc= v;
|
---|
457 | }
|
---|
458 |
|
---|
459 | pci_init();
|
---|
460 |
|
---|
461 | for (h= 1; h >= 0; h--) {
|
---|
462 | for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
|
---|
463 | {
|
---|
464 | if (fp->fxp_pcibus == 255)
|
---|
465 | continue;
|
---|
466 | if (((fp->fxp_pcibus | fp->fxp_pcidev |
|
---|
467 | fp->fxp_pcifunc) != 0) != h)
|
---|
468 | {
|
---|
469 | continue;
|
---|
470 | }
|
---|
471 | if (fxp_probe(fp))
|
---|
472 | fp->fxp_seen= TRUE;
|
---|
473 | }
|
---|
474 | }
|
---|
475 | }
|
---|
476 |
|
---|
477 | /*===========================================================================*
|
---|
478 | * fxp_probe *
|
---|
479 | *===========================================================================*/
|
---|
480 | static int fxp_probe(fp)
|
---|
481 | fxp_t *fp;
|
---|
482 | {
|
---|
483 | int i, r, devind, just_one;
|
---|
484 | u16_t vid, did;
|
---|
485 | u32_t bar;
|
---|
486 | u8_t ilr, rev;
|
---|
487 | char *dname, *str;
|
---|
488 |
|
---|
489 | if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
|
---|
490 | {
|
---|
491 | /* Look for specific PCI device */
|
---|
492 | r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
|
---|
493 | fp->fxp_pcifunc, &devind);
|
---|
494 | if (r == 0)
|
---|
495 | {
|
---|
496 | printf("%s: no PCI device found at %d.%d.%d\n",
|
---|
497 | fp->fxp_name, fp->fxp_pcibus,
|
---|
498 | fp->fxp_pcidev, fp->fxp_pcifunc);
|
---|
499 | return FALSE;
|
---|
500 | }
|
---|
501 | pci_ids(devind, &vid, &did);
|
---|
502 | just_one= TRUE;
|
---|
503 | }
|
---|
504 | else
|
---|
505 | {
|
---|
506 | r= pci_first_dev(&devind, &vid, &did);
|
---|
507 | if (r == 0)
|
---|
508 | return FALSE;
|
---|
509 | just_one= FALSE;
|
---|
510 | }
|
---|
511 |
|
---|
512 | for(;;)
|
---|
513 | {
|
---|
514 | for (i= 0; pcitab_fxp[i].vid != 0; i++)
|
---|
515 | {
|
---|
516 | if (pcitab_fxp[i].vid != vid)
|
---|
517 | continue;
|
---|
518 | if (pcitab_fxp[i].did != did)
|
---|
519 | continue;
|
---|
520 | if (pcitab_fxp[i].checkclass)
|
---|
521 | {
|
---|
522 | panic("FXP","fxp_probe: class check not implemented",
|
---|
523 | NO_NUM);
|
---|
524 | }
|
---|
525 | break;
|
---|
526 | }
|
---|
527 | if (pcitab_fxp[i].vid != 0)
|
---|
528 | break;
|
---|
529 |
|
---|
530 | if (just_one)
|
---|
531 | {
|
---|
532 | printf(
|
---|
533 | "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
|
---|
534 | fp->fxp_name, vid, did,
|
---|
535 | fp->fxp_pcibus,
|
---|
536 | fp->fxp_pcidev, fp->fxp_pcifunc);
|
---|
537 | return FALSE;
|
---|
538 | }
|
---|
539 |
|
---|
540 | r= pci_next_dev(&devind, &vid, &did);
|
---|
541 | if (!r)
|
---|
542 | return FALSE;
|
---|
543 | }
|
---|
544 |
|
---|
545 | dname= pci_dev_name(vid, did);
|
---|
546 | #if VERBOSE
|
---|
547 | if (!dname)
|
---|
548 | dname= "unknown device";
|
---|
549 | printf("%s: %s (%04x/%04x) at %s\n",
|
---|
550 | fp->fxp_name, dname, vid, did, pci_slot_name(devind));
|
---|
551 | #endif
|
---|
552 | pci_reserve(devind);
|
---|
553 |
|
---|
554 | bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
|
---|
555 | if (bar < 0x400)
|
---|
556 | {
|
---|
557 | panic("FXP","fxp_probe: base address is not properly configured",
|
---|
558 | NO_NUM);
|
---|
559 | }
|
---|
560 | fp->fxp_base_port= bar;
|
---|
561 |
|
---|
562 | ilr= pci_attr_r8(devind, PCI_ILR);
|
---|
563 | fp->fxp_irq= ilr;
|
---|
564 | if (debug)
|
---|
565 | {
|
---|
566 | printf("%s: using I/O address 0x%lx, IRQ %d\n",
|
---|
567 | fp->fxp_name, (unsigned long)bar, ilr);
|
---|
568 | }
|
---|
569 |
|
---|
570 | rev= pci_attr_r8(devind, PCI_REV);
|
---|
571 | str= NULL;
|
---|
572 | fp->fxp_type= FT_UNKNOWN;
|
---|
573 | switch(rev)
|
---|
574 | {
|
---|
575 | case FXP_REV_82557A: str= "82557A"; /* 0x01 */
|
---|
576 | fp->fxp_type= FT_82557;
|
---|
577 | break;
|
---|
578 | case FXP_REV_82557B: str= "82557B"; break; /* 0x02 */
|
---|
579 | case FXP_REV_82557C: str= "82557C"; break; /* 0x03 */
|
---|
580 | case FXP_REV_82558A: str= "82558A"; /* 0x04 */
|
---|
581 | fp->fxp_type= FT_82558A;
|
---|
582 | break;
|
---|
583 | case FXP_REV_82558B: str= "82558B"; break; /* 0x05 */
|
---|
584 | case FXP_REV_82559A: str= "82559A"; break; /* 0x06 */
|
---|
585 | case FXP_REV_82559B: str= "82559B"; break; /* 0x07 */
|
---|
586 | case FXP_REV_82559C: str= "82559C"; /* 0x08 */
|
---|
587 | fp->fxp_type= FT_82559;
|
---|
588 | break;
|
---|
589 | case FXP_REV_82559ERA: str= "82559ER-A"; /* 0x09 */
|
---|
590 | fp->fxp_type= FT_82559;
|
---|
591 | break;
|
---|
592 | case FXP_REV_82550_1: str= "82550(1)"; /* 0x0C */
|
---|
593 | fp->fxp_type= FT_82559;
|
---|
594 | break;
|
---|
595 | case FXP_REV_82550_2: str= "82550(2)"; /* 0x0D */
|
---|
596 | fp->fxp_type= FT_82559;
|
---|
597 | break;
|
---|
598 | case FXP_REV_82550_3: str= "82550(3)"; /* 0x0E */
|
---|
599 | fp->fxp_type= FT_82559;
|
---|
600 | break;
|
---|
601 | case FXP_REV_82551_1: str= "82551(1)"; /* 0x0F */
|
---|
602 | fp->fxp_type= FT_82559;
|
---|
603 | break;
|
---|
604 | case FXP_REV_82551_2: str= "82551(2)"; /* 0x10 */
|
---|
605 | fp->fxp_type= FT_82559;
|
---|
606 | break;
|
---|
607 | }
|
---|
608 |
|
---|
609 | #if VERBOSE
|
---|
610 | if (str)
|
---|
611 | printf("%s: device revision: %s\n", fp->fxp_name, str);
|
---|
612 | else
|
---|
613 | printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
|
---|
614 | #endif
|
---|
615 |
|
---|
616 | if (fp->fxp_type == FT_UNKNOWN)
|
---|
617 | {
|
---|
618 | printf("fxp_probe: device is not supported by this driver\n");
|
---|
619 | return FALSE;
|
---|
620 | }
|
---|
621 |
|
---|
622 | return TRUE;
|
---|
623 | }
|
---|
624 |
|
---|
625 | /*===========================================================================*
|
---|
626 | * fxp_conf_hw *
|
---|
627 | *===========================================================================*/
|
---|
628 | static void fxp_conf_hw(fp)
|
---|
629 | fxp_t *fp;
|
---|
630 | {
|
---|
631 | int i;
|
---|
632 | int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
|
---|
633 |
|
---|
634 | fp->fxp_mode= FM_DISABLED; /* Superfluous */
|
---|
635 |
|
---|
636 | if (!fp->fxp_seen)
|
---|
637 | return;
|
---|
638 |
|
---|
639 | /* PCI device is present */
|
---|
640 | fp->fxp_mode= FM_ENABLED;
|
---|
641 |
|
---|
642 | fp->fxp_flags= FF_EMPTY;
|
---|
643 | fp->fxp_got_int= 0;
|
---|
644 | fp->fxp_send_int= 0;
|
---|
645 | fp->fxp_ee_addrlen= 0; /* Unknown */
|
---|
646 | fp->fxp_need_reset= 0;
|
---|
647 | fp->fxp_report_link= 0;
|
---|
648 | fp->fxp_link_up= -1; /* Unknown */
|
---|
649 | fp->fxp_mii_busy= 0;
|
---|
650 | fp->fxp_read_s= 0;
|
---|
651 | fp->fxp_rx_need_restart= 0;
|
---|
652 | fp->fxp_need_conf= 0;
|
---|
653 | fp->fxp_tx_head= 0;
|
---|
654 | fp->fxp_tx_tail= 0;
|
---|
655 | fp->fxp_tx_alive= 0;
|
---|
656 | fp->fxp_tx_threshold= TXTT_MIN;
|
---|
657 |
|
---|
658 | /* Try to come up with a sensible configuration for the current
|
---|
659 | * device. Unfortunately every device is different, defaults are
|
---|
660 | * not always zero, and some fields are re-used with a completely
|
---|
661 | * different interpretation. We start out with a sensible default
|
---|
662 | * for all devices and then add device specific changes.
|
---|
663 | */
|
---|
664 | fp->fxp_conf_bytes[0]= CC_BYTES_NR;
|
---|
665 | fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
|
---|
666 | fp->fxp_conf_bytes[2]= CAI_DEFAULT;
|
---|
667 | fp->fxp_conf_bytes[3]= 0;
|
---|
668 | fp->fxp_conf_bytes[4]= 0;
|
---|
669 | fp->fxp_conf_bytes[5]= 0;
|
---|
670 | fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
|
---|
671 | fp->fxp_conf_bytes[7]= CUR_1;
|
---|
672 | fp->fxp_conf_bytes[8]= CCB8_503_MII;
|
---|
673 | fp->fxp_conf_bytes[9]= 0;
|
---|
674 | fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
|
---|
675 | CCB10_RES1;
|
---|
676 | fp->fxp_conf_bytes[11]= 0;
|
---|
677 | fp->fxp_conf_bytes[12]= CIS_DEFAULT;
|
---|
678 | fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
|
---|
679 | fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
|
---|
680 | fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
|
---|
681 | fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
|
---|
682 | fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
|
---|
683 | fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
|
---|
684 | fp->fxp_conf_bytes[19]= CCB19_FDPE;
|
---|
685 | fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
|
---|
686 | fp->fxp_conf_bytes[21]= CCB21_RES21;
|
---|
687 |
|
---|
688 | #if VERBOSE
|
---|
689 | for (i= 0; i<CC_BYTES_NR; i++)
|
---|
690 | printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
|
---|
691 | printf("\n");
|
---|
692 | #endif
|
---|
693 |
|
---|
694 | mwi= 0; /* Do we want "Memory Write and Invalidate"? */
|
---|
695 | ext_stat1= 0; /* Do we want extended statistical counters? */
|
---|
696 | ext_stat2= 0; /* Do we want even more statistical counters? */
|
---|
697 | lim_fifo= 0; /* Limit number of frame in TX FIFO */
|
---|
698 | i82503= 0; /* Older 10 Mbps interface on the 82557 */
|
---|
699 | fc= 0; /* Flow control */
|
---|
700 |
|
---|
701 | switch(fp->fxp_type)
|
---|
702 | {
|
---|
703 | case FT_82557:
|
---|
704 | if (i82503)
|
---|
705 | {
|
---|
706 | fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
|
---|
707 | fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
|
---|
708 | }
|
---|
709 | break;
|
---|
710 | case FT_82558A:
|
---|
711 | case FT_82559:
|
---|
712 | if (mwi)
|
---|
713 | fp->fxp_conf_bytes[3] |= CCB3_MWIE;
|
---|
714 | if (ext_stat1)
|
---|
715 | fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
|
---|
716 | if (ext_stat2)
|
---|
717 | fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
|
---|
718 | if (lim_fifo)
|
---|
719 | fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
|
---|
720 | if (fc)
|
---|
721 | {
|
---|
722 | /* From FreeBSD driver */
|
---|
723 | fp->fxp_conf_bytes[16]= 0x1f;
|
---|
724 | fp->fxp_conf_bytes[17]= 0x01;
|
---|
725 |
|
---|
726 | fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
|
---|
727 | CCB19_FDRSTOFC;
|
---|
728 | }
|
---|
729 |
|
---|
730 | fp->fxp_conf_bytes[18] |= CCB18_LROK;
|
---|
731 | break;
|
---|
732 | default:
|
---|
733 | panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);
|
---|
734 | }
|
---|
735 |
|
---|
736 | #if VERBOSE
|
---|
737 | for (i= 0; i<CC_BYTES_NR; i++)
|
---|
738 | printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
|
---|
739 | printf("\n");
|
---|
740 | #endif
|
---|
741 | }
|
---|
742 |
|
---|
743 | /*===========================================================================*
|
---|
744 | * fxp_init_hw *
|
---|
745 | *===========================================================================*/
|
---|
746 | static void fxp_init_hw(fp)
|
---|
747 | fxp_t *fp;
|
---|
748 | {
|
---|
749 | int i, r, isr;
|
---|
750 | port_t port;
|
---|
751 | u32_t bus_addr;
|
---|
752 |
|
---|
753 | port= fp->fxp_base_port;
|
---|
754 |
|
---|
755 | fxp_init_buf(fp);
|
---|
756 |
|
---|
757 | fp->fxp_flags = FF_EMPTY;
|
---|
758 | fp->fxp_flags |= FF_ENABLED;
|
---|
759 |
|
---|
760 | /* Set the interrupt handler and policy. Do not automatically
|
---|
761 | * reenable interrupts. Return the IRQ line number on interrupts.
|
---|
762 | */
|
---|
763 | fp->fxp_hook = fp->fxp_irq;
|
---|
764 | r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
|
---|
765 | if (r != OK)
|
---|
766 | panic("FXP","sys_irqsetpolicy failed", r);
|
---|
767 |
|
---|
768 | fxp_reset_hw(fp);
|
---|
769 |
|
---|
770 | r= sys_irqenable(&fp->fxp_hook);
|
---|
771 | if (r != OK)
|
---|
772 | panic("FXP","sys_irqenable failed", r);
|
---|
773 |
|
---|
774 | /* Reset PHY? */
|
---|
775 |
|
---|
776 | fxp_do_conf(fp);
|
---|
777 |
|
---|
778 | /* Set pointer to statistical counters */
|
---|
779 | r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
|
---|
780 | &bus_addr);
|
---|
781 | if (r != OK)
|
---|
782 | panic("FXP","sys_umap failed", r);
|
---|
783 | fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
|
---|
784 |
|
---|
785 | /* Ack previous interrupts */
|
---|
786 | isr= fxp_inb(port, SCB_INT_STAT);
|
---|
787 | fxp_outb(port, SCB_INT_STAT, isr);
|
---|
788 |
|
---|
789 | /* Enable interrupts */
|
---|
790 | fxp_outb(port, SCB_INT_MASK, 0);
|
---|
791 |
|
---|
792 | fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
|
---|
793 | TRUE /* check idle */);
|
---|
794 |
|
---|
795 | fxp_confaddr(fp);
|
---|
796 | if (debug)
|
---|
797 | {
|
---|
798 | printf("%s: Ethernet address ", fp->fxp_name);
|
---|
799 | for (i= 0; i < 6; i++)
|
---|
800 | {
|
---|
801 | printf("%x%c", fp->fxp_address.ea_addr[i],
|
---|
802 | i < 5 ? ':' : '\n');
|
---|
803 | }
|
---|
804 | }
|
---|
805 | }
|
---|
806 |
|
---|
807 | /*===========================================================================*
|
---|
808 | * fxp_init_buf *
|
---|
809 | *===========================================================================*/
|
---|
810 | static void fxp_init_buf(fp)
|
---|
811 | fxp_t *fp;
|
---|
812 | {
|
---|
813 | size_t rx_totbufsize, tx_totbufsize, tot_bufsize;
|
---|
814 | phys_bytes buf;
|
---|
815 | int i, r;
|
---|
816 | struct rfd *rfdp;
|
---|
817 | struct tx *txp;
|
---|
818 |
|
---|
819 | fp->fxp_rx_nbuf= N_RX_BUF;
|
---|
820 | rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
|
---|
821 | fp->fxp_rx_bufsize= rx_totbufsize;
|
---|
822 |
|
---|
823 | fp->fxp_tx_nbuf= N_TX_BUF;
|
---|
824 | tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
|
---|
825 | fp->fxp_tx_bufsize= tx_totbufsize;
|
---|
826 |
|
---|
827 | tot_bufsize= tx_totbufsize + rx_totbufsize;
|
---|
828 |
|
---|
829 | /* What about memory allocation? */
|
---|
830 | {
|
---|
831 | static int first_time= 1;
|
---|
832 |
|
---|
833 | assert(first_time);
|
---|
834 | first_time= 0;
|
---|
835 |
|
---|
836 | #define BUFALIGN 4096
|
---|
837 | assert(tot_bufsize <= sizeof(buffer)-BUFALIGN);
|
---|
838 | buf= (phys_bytes)buffer;
|
---|
839 | buf += BUFALIGN - (buf % BUFALIGN);
|
---|
840 | }
|
---|
841 |
|
---|
842 | fp->fxp_rx_buf= (struct rfd *)buf;
|
---|
843 | r= sys_umap(SELF, D, (vir_bytes)buf, rx_totbufsize,
|
---|
844 | &fp->fxp_rx_busaddr);
|
---|
845 | if (r != OK)
|
---|
846 | panic("FXP","sys_umap failed", r);
|
---|
847 | for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
|
---|
848 | {
|
---|
849 | rfdp->rfd_status= 0;
|
---|
850 | rfdp->rfd_command= 0;
|
---|
851 | if (i != fp->fxp_rx_nbuf-1)
|
---|
852 | {
|
---|
853 | r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],
|
---|
854 | sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
|
---|
855 | if (r != OK)
|
---|
856 | panic("FXP","sys_umap failed", r);
|
---|
857 | }
|
---|
858 | else
|
---|
859 | {
|
---|
860 | rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
|
---|
861 | rfdp->rfd_command |= RFDC_EL;
|
---|
862 | }
|
---|
863 | rfdp->rfd_reserved= 0;
|
---|
864 | rfdp->rfd_res= 0;
|
---|
865 | rfdp->rfd_size= sizeof(rfdp->rfd_buf);
|
---|
866 |
|
---|
867 | }
|
---|
868 | fp->fxp_rx_head= 0;
|
---|
869 |
|
---|
870 | fp->fxp_tx_buf= (struct tx *)(buf+rx_totbufsize);
|
---|
871 | r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,
|
---|
872 | (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
|
---|
873 | if (r != OK)
|
---|
874 | panic("FXP","sys_umap failed", r);
|
---|
875 |
|
---|
876 | for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
|
---|
877 | {
|
---|
878 | txp->tx_status= 0;
|
---|
879 | txp->tx_command= TXC_EL | CBL_NOP; /* Just in case */
|
---|
880 | if (i != fp->fxp_tx_nbuf-1)
|
---|
881 | {
|
---|
882 | r= sys_umap(SELF, D, (vir_bytes)&txp[1],
|
---|
883 | (phys_bytes)sizeof(txp[1]),
|
---|
884 | &txp->tx_linkaddr);
|
---|
885 | if (r != OK)
|
---|
886 | panic("FXP","sys_umap failed", r);
|
---|
887 | }
|
---|
888 | else
|
---|
889 | {
|
---|
890 | txp->tx_linkaddr= fp->fxp_tx_busaddr;
|
---|
891 | }
|
---|
892 | txp->tx_tbda= TX_TBDA_NIL;
|
---|
893 | txp->tx_size= 0;
|
---|
894 | txp->tx_tthresh= fp->fxp_tx_threshold;
|
---|
895 | txp->tx_ntbd= 0;
|
---|
896 | }
|
---|
897 | fp->fxp_tx_idle= 1;
|
---|
898 | }
|
---|
899 |
|
---|
900 | /*===========================================================================*
|
---|
901 | * fxp_reset_hw *
|
---|
902 | *===========================================================================*/
|
---|
903 | static void fxp_reset_hw(fp)
|
---|
904 | fxp_t *fp;
|
---|
905 | {
|
---|
906 | /* Inline the function in init? */
|
---|
907 | port_t port;
|
---|
908 |
|
---|
909 | port= fp->fxp_base_port;
|
---|
910 |
|
---|
911 | /* Reset device */
|
---|
912 | fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
|
---|
913 | tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
|
---|
914 |
|
---|
915 | /* Disable interrupts */
|
---|
916 | fxp_outb(port, SCB_INT_MASK, SIM_M);
|
---|
917 |
|
---|
918 | /* Set CU base to zero */
|
---|
919 | fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
|
---|
920 |
|
---|
921 | /* Set RU base to zero */
|
---|
922 | fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
|
---|
923 | }
|
---|
924 |
|
---|
925 | /*===========================================================================*
|
---|
926 | * fxp_confaddr *
|
---|
927 | *===========================================================================*/
|
---|
928 | static void fxp_confaddr(fp)
|
---|
929 | fxp_t *fp;
|
---|
930 | {
|
---|
931 | static char eakey[]= FXP_ENVVAR "#_EA";
|
---|
932 | static char eafmt[]= "x:x:x:x:x:x";
|
---|
933 | clock_t t0,t1;
|
---|
934 | int i, r;
|
---|
935 | port_t port;
|
---|
936 | u32_t bus_addr;
|
---|
937 | long v;
|
---|
938 | struct ias ias;
|
---|
939 |
|
---|
940 | port= fp->fxp_base_port;
|
---|
941 |
|
---|
942 | /* User defined ethernet address? */
|
---|
943 | eakey[sizeof(FXP_ENVVAR)-1]= '0' + (fp-fxp_table);
|
---|
944 |
|
---|
945 | #if 0
|
---|
946 | for (i= 0; i < 6; i++)
|
---|
947 | {
|
---|
948 | if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
|
---|
949 | break;
|
---|
950 | fp->fxp_address.ea_addr[i]= v;
|
---|
951 | }
|
---|
952 | #else
|
---|
953 | i= 0;
|
---|
954 | #endif
|
---|
955 |
|
---|
956 | #if 0
|
---|
957 | if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
|
---|
958 | #endif
|
---|
959 |
|
---|
960 | if (i == 0)
|
---|
961 | {
|
---|
962 | /* Get ethernet address from EEPROM */
|
---|
963 | for (i= 0; i<3; i++)
|
---|
964 | {
|
---|
965 | v= eeprom_read(fp, i);
|
---|
966 | fp->fxp_address.ea_addr[i*2]= (v & 0xff);
|
---|
967 | fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
|
---|
968 | }
|
---|
969 | }
|
---|
970 |
|
---|
971 | /* Tell NIC about ethernet address */
|
---|
972 | ias.ias_status= 0;
|
---|
973 | ias.ias_command= CBL_C_EL | CBL_AIS;
|
---|
974 | ias.ias_linkaddr= 0;
|
---|
975 | memcpy(ias.ias_ethaddr, fp->fxp_address.ea_addr,
|
---|
976 | sizeof(ias.ias_ethaddr));
|
---|
977 | r= sys_umap(SELF, D, (vir_bytes)&ias, (phys_bytes)sizeof(ias),
|
---|
978 | &bus_addr);
|
---|
979 | if (r != OK)
|
---|
980 | panic("FXP","sys_umap failed", r);
|
---|
981 |
|
---|
982 | fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
|
---|
983 |
|
---|
984 | getuptime(&t0);
|
---|
985 | do {
|
---|
986 | /* Wait for CU command to complete */
|
---|
987 | if (ias.ias_status & CBL_F_C)
|
---|
988 | break;
|
---|
989 | } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
|
---|
990 |
|
---|
991 | if (!(ias.ias_status & CBL_F_C))
|
---|
992 | panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
|
---|
993 | if (!(ias.ias_status & CBL_F_OK))
|
---|
994 | panic("FXP","fxp_confaddr: CU command failed", NO_NUM);
|
---|
995 |
|
---|
996 | #if VERBOSE
|
---|
997 | printf("%s: hardware ethernet address: ", fp->fxp_name);
|
---|
998 | for (i= 0; i<6; i++)
|
---|
999 | {
|
---|
1000 | printf("%02x%s", fp->fxp_address.ea_addr[i],
|
---|
1001 | i < 5 ? ":" : "");
|
---|
1002 | }
|
---|
1003 | printf("\n");
|
---|
1004 | #endif
|
---|
1005 | }
|
---|
1006 |
|
---|
1007 | /*===========================================================================*
|
---|
1008 | * fxp_rec_mode *
|
---|
1009 | *===========================================================================*/
|
---|
1010 | static void fxp_rec_mode(fp)
|
---|
1011 | fxp_t *fp;
|
---|
1012 | {
|
---|
1013 | fp->fxp_conf_bytes[0]= CC_BYTES_NR; /* Just to be sure */
|
---|
1014 | fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
|
---|
1015 | fp->fxp_conf_bytes[21] &= ~CCB21_MA;
|
---|
1016 |
|
---|
1017 | if (fp->fxp_flags & FF_PROMISC)
|
---|
1018 | fp->fxp_conf_bytes[15] |= CCB15_PM;
|
---|
1019 | if (fp->fxp_flags & FF_MULTI)
|
---|
1020 | fp->fxp_conf_bytes[21] |= CCB21_MA;
|
---|
1021 |
|
---|
1022 | if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
|
---|
1023 | fp->fxp_conf_bytes[15] |= CCB15_BD;
|
---|
1024 |
|
---|
1025 | /* Queue request if not idle */
|
---|
1026 | if (fp->fxp_tx_idle)
|
---|
1027 | {
|
---|
1028 | fxp_do_conf(fp);
|
---|
1029 | }
|
---|
1030 | else
|
---|
1031 | {
|
---|
1032 | printf("fxp_rec_mode: setting fxp_need_conf\n");
|
---|
1033 | fp->fxp_need_conf= TRUE;
|
---|
1034 | }
|
---|
1035 | }
|
---|
1036 |
|
---|
1037 | /*===========================================================================*
|
---|
1038 | * fxp_writev *
|
---|
1039 | *===========================================================================*/
|
---|
1040 | static void fxp_writev(mp, from_int, vectored)
|
---|
1041 | message *mp;
|
---|
1042 | int from_int;
|
---|
1043 | int vectored;
|
---|
1044 | {
|
---|
1045 | vir_bytes iov_src;
|
---|
1046 | int i, j, n, o, r, s, dl_port, count, size, prev_head;
|
---|
1047 | int fxp_client, fxp_tx_nbuf, fxp_tx_head;
|
---|
1048 | u16_t tx_command;
|
---|
1049 | fxp_t *fp;
|
---|
1050 | iovec_t *iovp;
|
---|
1051 | struct tx *txp, *prev_txp;
|
---|
1052 |
|
---|
1053 | dl_port = mp->DL_PORT;
|
---|
1054 | count = mp->DL_COUNT;
|
---|
1055 | if (dl_port < 0 || dl_port >= FXP_PORT_NR)
|
---|
1056 | panic("FXP","fxp_writev: illegal port", dl_port);
|
---|
1057 | fp= &fxp_table[dl_port];
|
---|
1058 | fxp_client= mp->DL_PROC;
|
---|
1059 | fp->fxp_client= fxp_client;
|
---|
1060 |
|
---|
1061 | assert(fp->fxp_mode == FM_ENABLED);
|
---|
1062 | assert(fp->fxp_flags & FF_ENABLED);
|
---|
1063 |
|
---|
1064 | if (from_int)
|
---|
1065 | {
|
---|
1066 | assert(fp->fxp_flags & FF_SEND_AVAIL);
|
---|
1067 | fp->fxp_flags &= ~FF_SEND_AVAIL;
|
---|
1068 | fp->fxp_tx_alive= TRUE;
|
---|
1069 | }
|
---|
1070 |
|
---|
1071 | if (fp->fxp_tx_idle)
|
---|
1072 | {
|
---|
1073 | txp= fp->fxp_tx_buf;
|
---|
1074 | fxp_tx_head= 0; /* lint */
|
---|
1075 | prev_txp= NULL; /* lint */
|
---|
1076 | }
|
---|
1077 | else
|
---|
1078 | {
|
---|
1079 | fxp_tx_nbuf= fp->fxp_tx_nbuf;
|
---|
1080 | prev_head= fp->fxp_tx_head;
|
---|
1081 | fxp_tx_head= prev_head+1;
|
---|
1082 | if (fxp_tx_head == fxp_tx_nbuf)
|
---|
1083 | fxp_tx_head= 0;
|
---|
1084 | assert(fxp_tx_head < fxp_tx_nbuf);
|
---|
1085 |
|
---|
1086 | if (fxp_tx_head == fp->fxp_tx_tail)
|
---|
1087 | {
|
---|
1088 | /* Send queue is full */
|
---|
1089 | assert(!(fp->fxp_flags & FF_SEND_AVAIL));
|
---|
1090 | fp->fxp_flags |= FF_SEND_AVAIL;
|
---|
1091 | goto suspend;
|
---|
1092 | }
|
---|
1093 |
|
---|
1094 | prev_txp= &fp->fxp_tx_buf[prev_head];
|
---|
1095 | txp= &fp->fxp_tx_buf[fxp_tx_head];
|
---|
1096 | }
|
---|
1097 |
|
---|
1098 | assert(!(fp->fxp_flags & FF_SEND_AVAIL));
|
---|
1099 | assert(!(fp->fxp_flags & FF_PACK_SENT));
|
---|
1100 |
|
---|
1101 | if (vectored)
|
---|
1102 | {
|
---|
1103 |
|
---|
1104 | iov_src = (vir_bytes)mp->DL_ADDR;
|
---|
1105 |
|
---|
1106 | size= 0;
|
---|
1107 | o= 0;
|
---|
1108 | for (i= 0; i<count; i += IOVEC_NR,
|
---|
1109 | iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
|
---|
1110 | {
|
---|
1111 | n= IOVEC_NR;
|
---|
1112 | if (i+n > count)
|
---|
1113 | n= count-i;
|
---|
1114 | r= sys_vircopy(fxp_client, D, iov_src,
|
---|
1115 | SELF, D, (vir_bytes)fp->fxp_iovec,
|
---|
1116 | n * sizeof(fp->fxp_iovec[0]));
|
---|
1117 | if (r != OK)
|
---|
1118 | panic("FXP","fxp_writev: sys_vircopy failed", r);
|
---|
1119 |
|
---|
1120 | for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
|
---|
1121 | {
|
---|
1122 | s= iovp->iov_size;
|
---|
1123 | if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
|
---|
1124 | {
|
---|
1125 | panic("FXP","fxp_writev: invalid packet size",
|
---|
1126 | NO_NUM);
|
---|
1127 | }
|
---|
1128 |
|
---|
1129 | r= sys_vircopy(fxp_client, D, iovp->iov_addr,
|
---|
1130 | SELF, D, (vir_bytes)(txp->tx_buf+o),
|
---|
1131 | s);
|
---|
1132 | if (r != OK)
|
---|
1133 | {
|
---|
1134 | panic("FXP","fxp_writev: sys_vircopy failed",
|
---|
1135 | r);
|
---|
1136 | }
|
---|
1137 | size += s;
|
---|
1138 | o += s;
|
---|
1139 | }
|
---|
1140 | }
|
---|
1141 | if (size < ETH_MIN_PACK_SIZE)
|
---|
1142 | panic("FXP","fxp_writev: invalid packet size", size);
|
---|
1143 | }
|
---|
1144 | else
|
---|
1145 | {
|
---|
1146 | size= mp->DL_COUNT;
|
---|
1147 | if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
|
---|
1148 | panic("FXP","fxp_writev: invalid packet size", size);
|
---|
1149 |
|
---|
1150 | r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR,
|
---|
1151 | SELF, D, (vir_bytes)txp->tx_buf, size);
|
---|
1152 | if (r != OK)
|
---|
1153 | panic("FXP","fxp_writev: sys_vircopy failed", r);
|
---|
1154 | }
|
---|
1155 |
|
---|
1156 | txp->tx_status= 0;
|
---|
1157 | txp->tx_command= TXC_EL | CBL_XMIT;
|
---|
1158 | txp->tx_tbda= TX_TBDA_NIL;
|
---|
1159 | txp->tx_size= TXSZ_EOF | size;
|
---|
1160 | txp->tx_tthresh= fp->fxp_tx_threshold;
|
---|
1161 | txp->tx_ntbd= 0;
|
---|
1162 | if (fp->fxp_tx_idle)
|
---|
1163 | {
|
---|
1164 | fp->fxp_tx_idle= 0;
|
---|
1165 | fp->fxp_tx_head= fp->fxp_tx_tail= 0;
|
---|
1166 |
|
---|
1167 | fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
|
---|
1168 | TRUE /* check idle */);
|
---|
1169 | }
|
---|
1170 | else
|
---|
1171 | {
|
---|
1172 | /* Link new request in transmit list */
|
---|
1173 | tx_command= prev_txp->tx_command;
|
---|
1174 | assert(tx_command == (TXC_EL | CBL_XMIT));
|
---|
1175 | prev_txp->tx_command= CBL_XMIT;
|
---|
1176 | fp->fxp_tx_head= fxp_tx_head;
|
---|
1177 | }
|
---|
1178 |
|
---|
1179 | fp->fxp_flags |= FF_PACK_SENT;
|
---|
1180 |
|
---|
1181 | /* If the interrupt handler called, don't send a reply. The reply
|
---|
1182 | * will be sent after all interrupts are handled.
|
---|
1183 | */
|
---|
1184 | if (from_int)
|
---|
1185 | return;
|
---|
1186 | reply(fp, OK, FALSE);
|
---|
1187 | return;
|
---|
1188 |
|
---|
1189 | suspend:
|
---|
1190 | if (from_int)
|
---|
1191 | panic("FXP","fxp: should not be sending\n", NO_NUM);
|
---|
1192 |
|
---|
1193 | fp->fxp_tx_mess= *mp;
|
---|
1194 | reply(fp, OK, FALSE);
|
---|
1195 | }
|
---|
1196 |
|
---|
1197 | /*===========================================================================*
|
---|
1198 | * fxp_readv *
|
---|
1199 | *===========================================================================*/
|
---|
1200 | static void fxp_readv(mp, from_int, vectored)
|
---|
1201 | message *mp;
|
---|
1202 | int from_int;
|
---|
1203 | int vectored;
|
---|
1204 | {
|
---|
1205 | int i, j, n, o, r, s, dl_port, fxp_client, count, size,
|
---|
1206 | fxp_rx_head, fxp_rx_nbuf;
|
---|
1207 | port_t port;
|
---|
1208 | unsigned packlen;
|
---|
1209 | vir_bytes iov_src;
|
---|
1210 | u16_t rfd_status;
|
---|
1211 | u16_t rfd_res;
|
---|
1212 | u8_t scb_status;
|
---|
1213 | fxp_t *fp;
|
---|
1214 | iovec_t *iovp;
|
---|
1215 | struct rfd *rfdp, *prev_rfdp;
|
---|
1216 |
|
---|
1217 | dl_port = mp->DL_PORT;
|
---|
1218 | count = mp->DL_COUNT;
|
---|
1219 | if (dl_port < 0 || dl_port >= FXP_PORT_NR)
|
---|
1220 | panic("FXP","fxp_readv: illegal port", dl_port);
|
---|
1221 | fp= &fxp_table[dl_port];
|
---|
1222 | fxp_client= mp->DL_PROC;
|
---|
1223 | fp->fxp_client= fxp_client;
|
---|
1224 |
|
---|
1225 | assert(fp->fxp_mode == FM_ENABLED);
|
---|
1226 | assert(fp->fxp_flags & FF_ENABLED);
|
---|
1227 |
|
---|
1228 | port= fp->fxp_base_port;
|
---|
1229 |
|
---|
1230 | fxp_rx_head= fp->fxp_rx_head;
|
---|
1231 | rfdp= &fp->fxp_rx_buf[fxp_rx_head];
|
---|
1232 |
|
---|
1233 | rfd_status= rfdp->rfd_status;
|
---|
1234 | if (!(rfd_status & RFDS_C))
|
---|
1235 | {
|
---|
1236 | /* Receive buffer is empty, suspend */
|
---|
1237 | goto suspend;
|
---|
1238 | }
|
---|
1239 |
|
---|
1240 | if (!rfd_status & RFDS_OK)
|
---|
1241 | {
|
---|
1242 | /* Not OK? What happened? */
|
---|
1243 | assert(0);
|
---|
1244 | }
|
---|
1245 | else
|
---|
1246 | {
|
---|
1247 | assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
|
---|
1248 | RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
|
---|
1249 | RFDS_RXERR)));
|
---|
1250 | }
|
---|
1251 | rfd_res= rfdp->rfd_res;
|
---|
1252 | assert(rfd_res & RFDR_EOF);
|
---|
1253 | assert(rfd_res & RFDR_F);
|
---|
1254 |
|
---|
1255 | packlen= rfd_res & RFDSZ_SIZE;
|
---|
1256 |
|
---|
1257 | if (vectored)
|
---|
1258 | {
|
---|
1259 | iov_src = (vir_bytes)mp->DL_ADDR;
|
---|
1260 |
|
---|
1261 | size= 0;
|
---|
1262 | o= 0;
|
---|
1263 | for (i= 0; i<count; i += IOVEC_NR,
|
---|
1264 | iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
|
---|
1265 | {
|
---|
1266 | n= IOVEC_NR;
|
---|
1267 | if (i+n > count)
|
---|
1268 | n= count-i;
|
---|
1269 | r= sys_vircopy(fxp_client, D, iov_src,
|
---|
1270 | SELF, D, (vir_bytes)fp->fxp_iovec,
|
---|
1271 | n * sizeof(fp->fxp_iovec[0]));
|
---|
1272 | if (r != OK)
|
---|
1273 | panic("FXP","fxp_readv: sys_vircopy failed", r);
|
---|
1274 |
|
---|
1275 | for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
|
---|
1276 | {
|
---|
1277 | s= iovp->iov_size;
|
---|
1278 | if (size + s > packlen)
|
---|
1279 | {
|
---|
1280 | assert(packlen > size);
|
---|
1281 | s= packlen-size;
|
---|
1282 | }
|
---|
1283 |
|
---|
1284 | r= sys_vircopy(SELF, D,
|
---|
1285 | (vir_bytes)(rfdp->rfd_buf+o),
|
---|
1286 | fxp_client, D, iovp->iov_addr, s);
|
---|
1287 | if (r != OK)
|
---|
1288 | {
|
---|
1289 | panic("FXP","fxp_readv: sys_vircopy failed",
|
---|
1290 | r);
|
---|
1291 | }
|
---|
1292 |
|
---|
1293 | size += s;
|
---|
1294 | if (size == packlen)
|
---|
1295 | break;
|
---|
1296 | o += s;
|
---|
1297 | }
|
---|
1298 | if (size == packlen)
|
---|
1299 | break;
|
---|
1300 | }
|
---|
1301 | if (size < packlen)
|
---|
1302 | {
|
---|
1303 | assert(0);
|
---|
1304 | }
|
---|
1305 | }
|
---|
1306 | else
|
---|
1307 | {
|
---|
1308 | assert(0);
|
---|
1309 | }
|
---|
1310 |
|
---|
1311 | fp->fxp_read_s= packlen;
|
---|
1312 | fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
|
---|
1313 |
|
---|
1314 | /* Re-init the current buffer */
|
---|
1315 | rfdp->rfd_status= 0;
|
---|
1316 | rfdp->rfd_command= RFDC_EL;
|
---|
1317 | rfdp->rfd_reserved= 0;
|
---|
1318 | rfdp->rfd_res= 0;
|
---|
1319 | rfdp->rfd_size= sizeof(rfdp->rfd_buf);
|
---|
1320 |
|
---|
1321 | fxp_rx_nbuf= fp->fxp_rx_nbuf;
|
---|
1322 | if (fxp_rx_head == 0)
|
---|
1323 | {
|
---|
1324 | prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
|
---|
1325 | }
|
---|
1326 | else
|
---|
1327 | prev_rfdp= &rfdp[-1];
|
---|
1328 |
|
---|
1329 | assert(prev_rfdp->rfd_command & RFDC_EL);
|
---|
1330 | prev_rfdp->rfd_command &= ~RFDC_EL;
|
---|
1331 |
|
---|
1332 | fxp_rx_head++;
|
---|
1333 | if (fxp_rx_head == fxp_rx_nbuf)
|
---|
1334 | fxp_rx_head= 0;
|
---|
1335 | assert(fxp_rx_head < fxp_rx_nbuf);
|
---|
1336 | fp->fxp_rx_head= fxp_rx_head;
|
---|
1337 |
|
---|
1338 | if (!from_int)
|
---|
1339 | reply(fp, OK, FALSE);
|
---|
1340 |
|
---|
1341 | return;
|
---|
1342 |
|
---|
1343 | suspend:
|
---|
1344 | if (fp->fxp_rx_need_restart)
|
---|
1345 | {
|
---|
1346 | fp->fxp_rx_need_restart= 0;
|
---|
1347 |
|
---|
1348 | /* Check the status of the RU */
|
---|
1349 | scb_status= fxp_inb(port, SCB_STATUS);
|
---|
1350 | if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
|
---|
1351 | {
|
---|
1352 | /* Race condition? */
|
---|
1353 | printf("fxp_readv: restart race: 0x%x\n",
|
---|
1354 | scb_status);
|
---|
1355 | assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
|
---|
1356 | }
|
---|
1357 | else
|
---|
1358 | {
|
---|
1359 | fxp_restart_ru(fp);
|
---|
1360 | }
|
---|
1361 | }
|
---|
1362 | if (from_int)
|
---|
1363 | {
|
---|
1364 | assert(fp->fxp_flags & FF_READING);
|
---|
1365 |
|
---|
1366 | /* No need to store any state */
|
---|
1367 | return;
|
---|
1368 | }
|
---|
1369 |
|
---|
1370 | fp->fxp_rx_mess= *mp;
|
---|
1371 | assert(!(fp->fxp_flags & FF_READING));
|
---|
1372 | fp->fxp_flags |= FF_READING;
|
---|
1373 |
|
---|
1374 | reply(fp, OK, FALSE);
|
---|
1375 | }
|
---|
1376 |
|
---|
1377 | /*===========================================================================*
|
---|
1378 | * fxp_do_conf *
|
---|
1379 | *===========================================================================*/
|
---|
1380 | static void fxp_do_conf(fp)
|
---|
1381 | fxp_t *fp;
|
---|
1382 | {
|
---|
1383 | int r;
|
---|
1384 | u32_t bus_addr;
|
---|
1385 | struct cbl_conf cc;
|
---|
1386 | clock_t t0,t1;
|
---|
1387 |
|
---|
1388 | /* Configure device */
|
---|
1389 | cc.cc_status= 0;
|
---|
1390 | cc.cc_command= CBL_C_EL | CBL_CONF;
|
---|
1391 | cc.cc_linkaddr= 0;
|
---|
1392 | memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes));
|
---|
1393 |
|
---|
1394 | r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc),
|
---|
1395 | &bus_addr);
|
---|
1396 | if (r != OK)
|
---|
1397 | panic("FXP","sys_umap failed", r);
|
---|
1398 |
|
---|
1399 | fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
|
---|
1400 |
|
---|
1401 | getuptime(&t0);
|
---|
1402 | do {
|
---|
1403 | /* Wait for CU command to complete */
|
---|
1404 | if (cc.cc_status & CBL_F_C)
|
---|
1405 | break;
|
---|
1406 | } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
|
---|
1407 |
|
---|
1408 | if (!(cc.cc_status & CBL_F_C))
|
---|
1409 | panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
|
---|
1410 | if (!(cc.cc_status & CBL_F_OK))
|
---|
1411 | panic("FXP","fxp_do_conf: CU command failed", NO_NUM);
|
---|
1412 |
|
---|
1413 | }
|
---|
1414 |
|
---|
1415 | /*===========================================================================*
|
---|
1416 | * fxp_cu_ptr_cmd *
|
---|
1417 | *===========================================================================*/
|
---|
1418 | static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
|
---|
1419 | fxp_t *fp;
|
---|
1420 | int cmd;
|
---|
1421 | phys_bytes bus_addr;
|
---|
1422 | int check_idle;
|
---|
1423 | {
|
---|
1424 | clock_t t0,t1;
|
---|
1425 | port_t port;
|
---|
1426 | u8_t scb_cmd;
|
---|
1427 |
|
---|
1428 | port= fp->fxp_base_port;
|
---|
1429 |
|
---|
1430 | if (check_idle)
|
---|
1431 | {
|
---|
1432 | /* Consistency check. Make sure that CU is idle */
|
---|
1433 | if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
|
---|
1434 | panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 | fxp_outl(port, SCB_POINTER, bus_addr);
|
---|
1438 | fxp_outb(port, SCB_CMD, cmd);
|
---|
1439 |
|
---|
1440 | /* What is a reasonable time-out? There is nothing in the
|
---|
1441 | * documentation. 1 ms should be enough.
|
---|
1442 | */
|
---|
1443 | getuptime(&t0);
|
---|
1444 | do {
|
---|
1445 | /* Wait for CU command to be accepted */
|
---|
1446 | scb_cmd= fxp_inb(port, SCB_CMD);
|
---|
1447 | if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
|
---|
1448 | break;
|
---|
1449 | } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
|
---|
1450 |
|
---|
1451 | if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
|
---|
1452 | panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
|
---|
1453 | }
|
---|
1454 |
|
---|
1455 | /*===========================================================================*
|
---|
1456 | * fxp_ru_ptr_cmd *
|
---|
1457 | *===========================================================================*/
|
---|
1458 | static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
|
---|
1459 | fxp_t *fp;
|
---|
1460 | int cmd;
|
---|
1461 | phys_bytes bus_addr;
|
---|
1462 | int check_idle;
|
---|
1463 | {
|
---|
1464 | clock_t t0,t1;
|
---|
1465 | port_t port;
|
---|
1466 | u8_t scb_cmd;
|
---|
1467 |
|
---|
1468 | port= fp->fxp_base_port;
|
---|
1469 |
|
---|
1470 | if (check_idle)
|
---|
1471 | {
|
---|
1472 | /* Consistency check, make sure that RU is idle */
|
---|
1473 | if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
|
---|
1474 | panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);
|
---|
1475 | }
|
---|
1476 |
|
---|
1477 | fxp_outl(port, SCB_POINTER, bus_addr);
|
---|
1478 | fxp_outb(port, SCB_CMD, cmd);
|
---|
1479 |
|
---|
1480 | getuptime(&t0);
|
---|
1481 | do {
|
---|
1482 | /* Wait for RU command to be accepted */
|
---|
1483 | scb_cmd= fxp_inb(port, SCB_CMD);
|
---|
1484 | if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
|
---|
1485 | break;
|
---|
1486 | } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
|
---|
1487 |
|
---|
1488 | if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
|
---|
1489 | panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
|
---|
1490 | }
|
---|
1491 |
|
---|
1492 | /*===========================================================================*
|
---|
1493 | * fxp_restart_ru *
|
---|
1494 | *===========================================================================*/
|
---|
1495 | static void fxp_restart_ru(fp)
|
---|
1496 | fxp_t *fp;
|
---|
1497 | {
|
---|
1498 | int i, fxp_rx_nbuf;
|
---|
1499 | port_t port;
|
---|
1500 | struct rfd *rfdp;
|
---|
1501 |
|
---|
1502 | port= fp->fxp_base_port;
|
---|
1503 |
|
---|
1504 | fxp_rx_nbuf= fp->fxp_rx_nbuf;
|
---|
1505 | for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
|
---|
1506 | {
|
---|
1507 | rfdp->rfd_status= 0;
|
---|
1508 | rfdp->rfd_command= 0;
|
---|
1509 | if (i == fp->fxp_rx_nbuf-1)
|
---|
1510 | rfdp->rfd_command= RFDC_EL;
|
---|
1511 | rfdp->rfd_reserved= 0;
|
---|
1512 | rfdp->rfd_res= 0;
|
---|
1513 | rfdp->rfd_size= sizeof(rfdp->rfd_buf);
|
---|
1514 | }
|
---|
1515 | fp->fxp_rx_head= 0;
|
---|
1516 |
|
---|
1517 | /* Make sure that RU is in the 'No resources' state */
|
---|
1518 | if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
|
---|
1519 | panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);
|
---|
1520 |
|
---|
1521 | fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
|
---|
1522 | FALSE /* do not check idle */);
|
---|
1523 | }
|
---|
1524 |
|
---|
1525 | /*===========================================================================*
|
---|
1526 | * fxp_getstat *
|
---|
1527 | *===========================================================================*/
|
---|
1528 | static void fxp_getstat(mp)
|
---|
1529 | message *mp;
|
---|
1530 | {
|
---|
1531 | clock_t t0,t1;
|
---|
1532 | int dl_port;
|
---|
1533 | port_t port;
|
---|
1534 | fxp_t *fp;
|
---|
1535 | u32_t *p;
|
---|
1536 | eth_stat_t stats;
|
---|
1537 |
|
---|
1538 | dl_port = mp->DL_PORT;
|
---|
1539 | if (dl_port < 0 || dl_port >= FXP_PORT_NR)
|
---|
1540 | panic("FXP","fxp_getstat: illegal port", dl_port);
|
---|
1541 | fp= &fxp_table[dl_port];
|
---|
1542 | fp->fxp_client= mp->DL_PROC;
|
---|
1543 |
|
---|
1544 | assert(fp->fxp_mode == FM_ENABLED);
|
---|
1545 | assert(fp->fxp_flags & FF_ENABLED);
|
---|
1546 |
|
---|
1547 | port= fp->fxp_base_port;
|
---|
1548 |
|
---|
1549 | p= &fp->fxp_stat.sc_tx_fcp;
|
---|
1550 | *p= 0;
|
---|
1551 |
|
---|
1552 | /* The dump commmand doesn't take a pointer. Setting a pointer
|
---|
1553 | * doesn't hard though.
|
---|
1554 | */
|
---|
1555 | fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
|
---|
1556 |
|
---|
1557 | getuptime(&t0);
|
---|
1558 | do {
|
---|
1559 | /* Wait for CU command to complete */
|
---|
1560 | if (*p != 0)
|
---|
1561 | break;
|
---|
1562 | } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
|
---|
1563 |
|
---|
1564 | if (*p == 0)
|
---|
1565 | panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
|
---|
1566 | if (*p != SCM_DSC)
|
---|
1567 | panic("FXP","fxp_getstat: bad magic", NO_NUM);
|
---|
1568 |
|
---|
1569 | stats.ets_recvErr=
|
---|
1570 | fp->fxp_stat.sc_rx_crc +
|
---|
1571 | fp->fxp_stat.sc_rx_align +
|
---|
1572 | fp->fxp_stat.sc_rx_resource +
|
---|
1573 | fp->fxp_stat.sc_rx_overrun +
|
---|
1574 | fp->fxp_stat.sc_rx_cd +
|
---|
1575 | fp->fxp_stat.sc_rx_short;
|
---|
1576 | stats.ets_sendErr=
|
---|
1577 | fp->fxp_stat.sc_tx_maxcol +
|
---|
1578 | fp->fxp_stat.sc_tx_latecol +
|
---|
1579 | fp->fxp_stat.sc_tx_crs;
|
---|
1580 | stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
|
---|
1581 | stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
|
---|
1582 | stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
|
---|
1583 | stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
|
---|
1584 | stats.ets_packetR= fp->fxp_stat.sc_rx_good;
|
---|
1585 | stats.ets_packetT= fp->fxp_stat.sc_tx_good;
|
---|
1586 | stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
|
---|
1587 | stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
|
---|
1588 | stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
|
---|
1589 | stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
|
---|
1590 | stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
|
---|
1591 | stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
|
---|
1592 | stats.ets_CDheartbeat= 0;
|
---|
1593 | stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
|
---|
1594 |
|
---|
1595 | put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
|
---|
1596 | (vir_bytes) sizeof(stats), &stats);
|
---|
1597 | reply(fp, OK, FALSE);
|
---|
1598 | }
|
---|
1599 |
|
---|
1600 |
|
---|
1601 | /*===========================================================================*
|
---|
1602 | * fxp_getname *
|
---|
1603 | *===========================================================================*/
|
---|
1604 | static void fxp_getname(mp)
|
---|
1605 | message *mp;
|
---|
1606 | {
|
---|
1607 | int r;
|
---|
1608 |
|
---|
1609 | strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
|
---|
1610 | mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
|
---|
1611 | mp->m_type= DL_NAME_REPLY;
|
---|
1612 | r= send(mp->m_source, mp);
|
---|
1613 | if (r != OK)
|
---|
1614 | panic("FXP", "fxp_getname: send failed", r);
|
---|
1615 | }
|
---|
1616 |
|
---|
1617 | /*===========================================================================*
|
---|
1618 | * fxp_handler *
|
---|
1619 | *===========================================================================*/
|
---|
1620 | static int fxp_handler(fp)
|
---|
1621 | fxp_t *fp;
|
---|
1622 | {
|
---|
1623 | int port;
|
---|
1624 | u16_t isr;
|
---|
1625 |
|
---|
1626 | RAND_UPDATE
|
---|
1627 |
|
---|
1628 | port= fp->fxp_base_port;
|
---|
1629 |
|
---|
1630 | /* Ack interrupt */
|
---|
1631 | isr= fxp_inb(port, SCB_INT_STAT);
|
---|
1632 | fxp_outb(port, SCB_INT_STAT, isr);
|
---|
1633 |
|
---|
1634 | if (isr & SIS_FR)
|
---|
1635 | {
|
---|
1636 | isr &= ~SIS_FR;
|
---|
1637 |
|
---|
1638 | if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
|
---|
1639 | {
|
---|
1640 | fp->fxp_got_int= TRUE;
|
---|
1641 | interrupt(fxp_tasknr);
|
---|
1642 | }
|
---|
1643 | }
|
---|
1644 | if (isr & SIS_CNA)
|
---|
1645 | {
|
---|
1646 | isr &= ~SIS_CNA;
|
---|
1647 | if (!fp->fxp_tx_idle)
|
---|
1648 | {
|
---|
1649 | fp->fxp_send_int= TRUE;
|
---|
1650 | if (!fp->fxp_got_int)
|
---|
1651 | {
|
---|
1652 | fp->fxp_got_int= TRUE;
|
---|
1653 | interrupt(fxp_tasknr);
|
---|
1654 | }
|
---|
1655 | }
|
---|
1656 | }
|
---|
1657 | if (isr & SIS_RNR)
|
---|
1658 | {
|
---|
1659 | isr &= ~SIS_RNR;
|
---|
1660 |
|
---|
1661 | /* Assume that receive buffer is full of packets. fxp_readv
|
---|
1662 | * will restart the RU.
|
---|
1663 | */
|
---|
1664 | fp->fxp_rx_need_restart= 1;
|
---|
1665 | }
|
---|
1666 | if (isr)
|
---|
1667 | {
|
---|
1668 | printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
|
---|
1669 | isr);
|
---|
1670 | }
|
---|
1671 |
|
---|
1672 | return 1;
|
---|
1673 | }
|
---|
1674 |
|
---|
1675 | /*===========================================================================*
|
---|
1676 | * fxp_check_ints *
|
---|
1677 | *===========================================================================*/
|
---|
1678 | static void fxp_check_ints(fp)
|
---|
1679 | fxp_t *fp;
|
---|
1680 | {
|
---|
1681 | int n, fxp_flags, prev_tail;
|
---|
1682 | int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
|
---|
1683 | port_t port;
|
---|
1684 | u32_t busaddr;
|
---|
1685 | u16_t tx_status;
|
---|
1686 | u8_t scb_status;
|
---|
1687 | struct tx *txp;
|
---|
1688 |
|
---|
1689 | fxp_flags= fp->fxp_flags;
|
---|
1690 |
|
---|
1691 | if (fxp_flags & FF_READING)
|
---|
1692 | {
|
---|
1693 | if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
|
---|
1694 | ; /* Nothing */
|
---|
1695 | else if (fp->fxp_rx_mess.m_type == DL_READV)
|
---|
1696 | {
|
---|
1697 | fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
|
---|
1698 | TRUE /* vectored */);
|
---|
1699 | }
|
---|
1700 | else
|
---|
1701 | {
|
---|
1702 | assert(fp->fxp_rx_mess.m_type == DL_READ);
|
---|
1703 | fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
|
---|
1704 | FALSE /* !vectored */);
|
---|
1705 | }
|
---|
1706 | }
|
---|
1707 | if (fp->fxp_tx_idle)
|
---|
1708 | ; /* Nothing to do */
|
---|
1709 | else if (fp->fxp_send_int)
|
---|
1710 | {
|
---|
1711 | fp->fxp_send_int= FALSE;
|
---|
1712 | fxp_tx_tail= fp->fxp_tx_tail;
|
---|
1713 | fxp_tx_nbuf= fp->fxp_tx_nbuf;
|
---|
1714 | n= 0;
|
---|
1715 | for (;;)
|
---|
1716 | {
|
---|
1717 | txp= &fp->fxp_tx_buf[fxp_tx_tail];
|
---|
1718 | tx_status= txp->tx_status;
|
---|
1719 | if (!(tx_status & TXS_C))
|
---|
1720 | break;
|
---|
1721 |
|
---|
1722 | n++;
|
---|
1723 |
|
---|
1724 | assert(tx_status & TXS_OK);
|
---|
1725 | if (tx_status & TXS_U)
|
---|
1726 | {
|
---|
1727 | fxp_tx_threshold= fp->fxp_tx_threshold;
|
---|
1728 | if (fxp_tx_threshold < TXTT_MAX)
|
---|
1729 | {
|
---|
1730 | fxp_tx_threshold++;
|
---|
1731 | fp->fxp_tx_threshold= fxp_tx_threshold;
|
---|
1732 | }
|
---|
1733 | printf(
|
---|
1734 | "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
|
---|
1735 | fxp_tx_threshold);
|
---|
1736 | }
|
---|
1737 |
|
---|
1738 | if (txp->tx_command & TXC_EL)
|
---|
1739 | {
|
---|
1740 | fp->fxp_tx_idle= 1;
|
---|
1741 | break;
|
---|
1742 | }
|
---|
1743 |
|
---|
1744 | fxp_tx_tail++;
|
---|
1745 | if (fxp_tx_tail == fxp_tx_nbuf)
|
---|
1746 | fxp_tx_tail= 0;
|
---|
1747 | assert(fxp_tx_tail < fxp_tx_nbuf);
|
---|
1748 | }
|
---|
1749 |
|
---|
1750 | if (fp->fxp_need_conf)
|
---|
1751 | {
|
---|
1752 | /* Check the status of the CU */
|
---|
1753 | port= fp->fxp_base_port;
|
---|
1754 | scb_status= fxp_inb(port, SCB_STATUS);
|
---|
1755 | if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
|
---|
1756 | {
|
---|
1757 | /* Nothing to do */
|
---|
1758 | printf("scb_status = 0x%x\n", scb_status);
|
---|
1759 | }
|
---|
1760 | else
|
---|
1761 | {
|
---|
1762 | printf("fxp_check_ints: fxp_need_conf\n");
|
---|
1763 | fp->fxp_need_conf= FALSE;
|
---|
1764 | fxp_do_conf(fp);
|
---|
1765 | }
|
---|
1766 | }
|
---|
1767 |
|
---|
1768 | if (n)
|
---|
1769 | {
|
---|
1770 | if (!fp->fxp_tx_idle)
|
---|
1771 | {
|
---|
1772 | fp->fxp_tx_tail= fxp_tx_tail;
|
---|
1773 |
|
---|
1774 | /* Check the status of the CU */
|
---|
1775 | port= fp->fxp_base_port;
|
---|
1776 | scb_status= fxp_inb(port, SCB_STATUS);
|
---|
1777 | if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
|
---|
1778 | {
|
---|
1779 | /* Nothing to do */
|
---|
1780 | printf("scb_status = 0x%x\n",
|
---|
1781 | scb_status);
|
---|
1782 |
|
---|
1783 | }
|
---|
1784 | else
|
---|
1785 | {
|
---|
1786 | if (fxp_tx_tail == 0)
|
---|
1787 | prev_tail= fxp_tx_nbuf-1;
|
---|
1788 | else
|
---|
1789 | prev_tail= fxp_tx_tail-1;
|
---|
1790 | busaddr= fp->fxp_tx_buf[prev_tail].
|
---|
1791 | tx_linkaddr;
|
---|
1792 |
|
---|
1793 | fxp_cu_ptr_cmd(fp, SC_CU_START,
|
---|
1794 | busaddr, 1 /* check idle */);
|
---|
1795 | }
|
---|
1796 | }
|
---|
1797 |
|
---|
1798 | if (fp->fxp_flags & FF_SEND_AVAIL)
|
---|
1799 | {
|
---|
1800 | if (fp->fxp_tx_mess.m_type == DL_WRITEV)
|
---|
1801 | {
|
---|
1802 | fxp_writev(&fp->fxp_tx_mess,
|
---|
1803 | TRUE /* from int */,
|
---|
1804 | TRUE /* vectored */);
|
---|
1805 | }
|
---|
1806 | else
|
---|
1807 | {
|
---|
1808 | assert(fp->fxp_tx_mess.m_type ==
|
---|
1809 | DL_WRITE);
|
---|
1810 | fxp_writev(&fp->fxp_tx_mess,
|
---|
1811 | TRUE /* from int */,
|
---|
1812 | FALSE /* !vectored */);
|
---|
1813 | }
|
---|
1814 | }
|
---|
1815 | }
|
---|
1816 |
|
---|
1817 | }
|
---|
1818 | if (fp->fxp_report_link)
|
---|
1819 | fxp_report_link(fp);
|
---|
1820 |
|
---|
1821 | if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
|
---|
1822 | reply(fp, OK, TRUE);
|
---|
1823 | }
|
---|
1824 |
|
---|
1825 | /*===========================================================================*
|
---|
1826 | * fxp_watchdog_f *
|
---|
1827 | *===========================================================================*/
|
---|
1828 | static void fxp_watchdog_f(tp)
|
---|
1829 | timer_t *tp;
|
---|
1830 | {
|
---|
1831 | int i;
|
---|
1832 | fxp_t *fp;
|
---|
1833 |
|
---|
1834 | tmr_arg(&fxp_watchdog)->ta_int= 0;
|
---|
1835 | fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
|
---|
1836 |
|
---|
1837 | for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
|
---|
1838 | {
|
---|
1839 | if (fp->fxp_mode != FM_ENABLED)
|
---|
1840 | continue;
|
---|
1841 |
|
---|
1842 | /* Handle race condition, MII interface mgith be busy */
|
---|
1843 | if(!fp->fxp_mii_busy)
|
---|
1844 | {
|
---|
1845 | /* Check the link status. */
|
---|
1846 | if (fxp_link_changed(fp))
|
---|
1847 | {
|
---|
1848 | #if VERBOSE
|
---|
1849 | printf("fxp_watchdog_f: link changed\n");
|
---|
1850 | #endif
|
---|
1851 | fp->fxp_report_link= TRUE;
|
---|
1852 | fp->fxp_got_int= TRUE;
|
---|
1853 | interrupt(fxp_tasknr);
|
---|
1854 | }
|
---|
1855 | }
|
---|
1856 |
|
---|
1857 | if (!(fp->fxp_flags & FF_SEND_AVAIL))
|
---|
1858 | {
|
---|
1859 | /* Assume that an idle system is alive */
|
---|
1860 | fp->fxp_tx_alive= TRUE;
|
---|
1861 | continue;
|
---|
1862 | }
|
---|
1863 | if (fp->fxp_tx_alive)
|
---|
1864 | {
|
---|
1865 | fp->fxp_tx_alive= FALSE;
|
---|
1866 | continue;
|
---|
1867 | }
|
---|
1868 |
|
---|
1869 | fp->fxp_need_reset= TRUE;
|
---|
1870 | fp->fxp_got_int= TRUE;
|
---|
1871 | interrupt(fxp_tasknr);
|
---|
1872 | }
|
---|
1873 | }
|
---|
1874 |
|
---|
1875 | /*===========================================================================*
|
---|
1876 | * fxp_link_changed *
|
---|
1877 | *===========================================================================*/
|
---|
1878 | static int fxp_link_changed(fp)
|
---|
1879 | fxp_t *fp;
|
---|
1880 | {
|
---|
1881 | u16_t scr;
|
---|
1882 |
|
---|
1883 | scr= mii_read(fp, MII_SCR);
|
---|
1884 | scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
|
---|
1885 |
|
---|
1886 | return (fp->fxp_mii_scr != scr);
|
---|
1887 | }
|
---|
1888 |
|
---|
1889 | /*===========================================================================*
|
---|
1890 | * fxp_report_link *
|
---|
1891 | *===========================================================================*/
|
---|
1892 | static void fxp_report_link(fp)
|
---|
1893 | fxp_t *fp;
|
---|
1894 | {
|
---|
1895 | port_t port;
|
---|
1896 | u16_t mii_ctrl, mii_status, mii_id1, mii_id2,
|
---|
1897 | mii_ana, mii_anlpa, mii_ane, mii_extstat,
|
---|
1898 | mii_ms_ctrl, mii_ms_status, scr;
|
---|
1899 | u32_t oui;
|
---|
1900 | int model, rev;
|
---|
1901 | int f, link_up, ms_regs;
|
---|
1902 |
|
---|
1903 | /* Assume an 82555 (compatible) PHY. The should be changed for
|
---|
1904 | * 82557 NICs with different PHYs
|
---|
1905 | */
|
---|
1906 | ms_regs= 0; /* No master/slave registers. */
|
---|
1907 |
|
---|
1908 | fp->fxp_report_link= FALSE;
|
---|
1909 | port= fp->fxp_base_port;
|
---|
1910 |
|
---|
1911 | scr= mii_read(fp, MII_SCR);
|
---|
1912 | scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
|
---|
1913 | fp->fxp_mii_scr= scr;
|
---|
1914 |
|
---|
1915 | mii_ctrl= mii_read(fp, MII_CTRL);
|
---|
1916 | mii_read(fp, MII_STATUS); /* Read the status register twice, why? */
|
---|
1917 | mii_status= mii_read(fp, MII_STATUS);
|
---|
1918 | mii_id1= mii_read(fp, MII_PHYID_H);
|
---|
1919 | mii_id2= mii_read(fp, MII_PHYID_L);
|
---|
1920 | mii_ana= mii_read(fp, MII_ANA);
|
---|
1921 | mii_anlpa= mii_read(fp, MII_ANLPA);
|
---|
1922 | mii_ane= mii_read(fp, MII_ANE);
|
---|
1923 | if (mii_status & MII_STATUS_EXT_STAT)
|
---|
1924 | mii_extstat= mii_read(fp, MII_EXT_STATUS);
|
---|
1925 | else
|
---|
1926 | mii_extstat= 0;
|
---|
1927 | if (ms_regs)
|
---|
1928 | {
|
---|
1929 | mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
|
---|
1930 | mii_ms_status= mii_read(fp, MII_MS_STATUS);
|
---|
1931 | }
|
---|
1932 | else
|
---|
1933 | {
|
---|
1934 | mii_ms_ctrl= 0;
|
---|
1935 | mii_ms_status= 0;
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | /* How do we know about the link status? */
|
---|
1939 | link_up= !!(mii_status & MII_STATUS_LS);
|
---|
1940 |
|
---|
1941 | fp->fxp_link_up= link_up;
|
---|
1942 | if (!link_up)
|
---|
1943 | {
|
---|
1944 | #if VERBOSE
|
---|
1945 | printf("%s: link down\n", fp->fxp_name);
|
---|
1946 | #endif
|
---|
1947 | return;
|
---|
1948 | }
|
---|
1949 |
|
---|
1950 | oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) |
|
---|
1951 | ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
|
---|
1952 | model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
|
---|
1953 | rev= (mii_id2 & MII_PL_REV_MASK);
|
---|
1954 |
|
---|
1955 | #if VERBOSE
|
---|
1956 | printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
|
---|
1957 | #endif
|
---|
1958 |
|
---|
1959 | if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
|
---|
1960 | {
|
---|
1961 | printf("%s: PHY: ", fp->fxp_name);
|
---|
1962 | f= 1;
|
---|
1963 | if (mii_ctrl & MII_CTRL_LB)
|
---|
1964 | {
|
---|
1965 | printf("loopback mode");
|
---|
1966 | f= 0;
|
---|
1967 | }
|
---|
1968 | if (mii_ctrl & MII_CTRL_PD)
|
---|
1969 | {
|
---|
1970 | if (!f) printf(", ");
|
---|
1971 | f= 0;
|
---|
1972 | printf("powered down");
|
---|
1973 | }
|
---|
1974 | if (mii_ctrl & MII_CTRL_ISO)
|
---|
1975 | {
|
---|
1976 | if (!f) printf(", ");
|
---|
1977 | f= 0;
|
---|
1978 | printf("isolated");
|
---|
1979 | }
|
---|
1980 | printf("\n");
|
---|
1981 | return;
|
---|
1982 | }
|
---|
1983 | if (!(mii_ctrl & MII_CTRL_ANE))
|
---|
1984 | {
|
---|
1985 | printf("%s: manual config: ", fp->fxp_name);
|
---|
1986 | switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
|
---|
1987 | {
|
---|
1988 | case MII_CTRL_SP_10: printf("10 Mbps"); break;
|
---|
1989 | case MII_CTRL_SP_100: printf("100 Mbps"); break;
|
---|
1990 | case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
|
---|
1991 | case MII_CTRL_SP_RES: printf("reserved speed"); break;
|
---|
1992 | }
|
---|
1993 | if (mii_ctrl & MII_CTRL_DM)
|
---|
1994 | printf(", full duplex");
|
---|
1995 | else
|
---|
1996 | printf(", half duplex");
|
---|
1997 | printf("\n");
|
---|
1998 | return;
|
---|
1999 | }
|
---|
2000 |
|
---|
2001 | if (!debug) goto resspeed;
|
---|
2002 |
|
---|
2003 | printf("%s: ", fp->fxp_name);
|
---|
2004 | mii_print_stat_speed(mii_status, mii_extstat);
|
---|
2005 | printf("\n");
|
---|
2006 |
|
---|
2007 | if (!(mii_status & MII_STATUS_ANC))
|
---|
2008 | printf("%s: auto-negotiation not complete\n", fp->fxp_name);
|
---|
2009 | if (mii_status & MII_STATUS_RF)
|
---|
2010 | printf("%s: remote fault detected\n", fp->fxp_name);
|
---|
2011 | if (!(mii_status & MII_STATUS_ANA))
|
---|
2012 | {
|
---|
2013 | printf("%s: local PHY has no auto-negotiation ability\n",
|
---|
2014 | fp->fxp_name);
|
---|
2015 | }
|
---|
2016 | if (!(mii_status & MII_STATUS_LS))
|
---|
2017 | printf("%s: link down\n", fp->fxp_name);
|
---|
2018 | if (mii_status & MII_STATUS_JD)
|
---|
2019 | printf("%s: jabber condition detected\n", fp->fxp_name);
|
---|
2020 | if (!(mii_status & MII_STATUS_EC))
|
---|
2021 | {
|
---|
2022 | printf("%s: no extended register set\n", fp->fxp_name);
|
---|
2023 | goto resspeed;
|
---|
2024 | }
|
---|
2025 | if (!(mii_status & MII_STATUS_ANC))
|
---|
2026 | goto resspeed;
|
---|
2027 |
|
---|
2028 | printf("%s: local cap.: ", fp->fxp_name);
|
---|
2029 | if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
|
---|
2030 | {
|
---|
2031 | printf("1000 Mbps: T-");
|
---|
2032 | switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
|
---|
2033 | {
|
---|
2034 | case MII_MSC_1000T_FD: printf("FD"); break;
|
---|
2035 | case MII_MSC_1000T_HD: printf("HD"); break;
|
---|
2036 | default: printf("FD/HD"); break;
|
---|
2037 | }
|
---|
2038 | if (mii_ana)
|
---|
2039 | printf(", ");
|
---|
2040 | }
|
---|
2041 | mii_print_techab(mii_ana);
|
---|
2042 | printf("\n");
|
---|
2043 |
|
---|
2044 | if (mii_ane & MII_ANE_PDF)
|
---|
2045 | printf("%s: parallel detection fault\n", fp->fxp_name);
|
---|
2046 | if (!(mii_ane & MII_ANE_LPANA))
|
---|
2047 | {
|
---|
2048 | printf("%s: link-partner does not support auto-negotiation\n",
|
---|
2049 | fp->fxp_name);
|
---|
2050 | goto resspeed;
|
---|
2051 | }
|
---|
2052 |
|
---|
2053 | printf("%s: remote cap.: ", fp->fxp_name);
|
---|
2054 | if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
|
---|
2055 | if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
|
---|
2056 | {
|
---|
2057 | printf("1000 Mbps: T-");
|
---|
2058 | switch(mii_ms_status &
|
---|
2059 | (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
|
---|
2060 | {
|
---|
2061 | case MII_MSS_LP1000T_FD: printf("FD"); break;
|
---|
2062 | case MII_MSS_LP1000T_HD: printf("HD"); break;
|
---|
2063 | default: printf("FD/HD"); break;
|
---|
2064 | }
|
---|
2065 | if (mii_anlpa)
|
---|
2066 | printf(", ");
|
---|
2067 | }
|
---|
2068 | mii_print_techab(mii_anlpa);
|
---|
2069 | printf("\n");
|
---|
2070 |
|
---|
2071 | if (ms_regs)
|
---|
2072 | {
|
---|
2073 | printf("%s: ", fp->fxp_name);
|
---|
2074 | if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
|
---|
2075 | {
|
---|
2076 | printf("manual %s",
|
---|
2077 | (mii_ms_ctrl & MII_MSC_MS_VAL) ?
|
---|
2078 | "MASTER" : "SLAVE");
|
---|
2079 | }
|
---|
2080 | else
|
---|
2081 | {
|
---|
2082 | printf("%s device",
|
---|
2083 | (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
|
---|
2084 | "multiport" : "single-port");
|
---|
2085 | }
|
---|
2086 | if (mii_ms_ctrl & MII_MSC_RES)
|
---|
2087 | printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
|
---|
2088 | printf(": ");
|
---|
2089 | if (mii_ms_status & MII_MSS_FAULT)
|
---|
2090 | printf("M/S config fault");
|
---|
2091 | else if (mii_ms_status & MII_MSS_MASTER)
|
---|
2092 | printf("MASTER");
|
---|
2093 | else
|
---|
2094 | printf("SLAVE");
|
---|
2095 | printf("\n");
|
---|
2096 | }
|
---|
2097 |
|
---|
2098 | if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
|
---|
2099 | {
|
---|
2100 | if (!(mii_ms_status & MII_MSS_LOCREC))
|
---|
2101 | {
|
---|
2102 | printf("%s: local receiver not OK\n",
|
---|
2103 | fp->fxp_name);
|
---|
2104 | }
|
---|
2105 | if (!(mii_ms_status & MII_MSS_REMREC))
|
---|
2106 | {
|
---|
2107 | printf("%s: remote receiver not OK\n",
|
---|
2108 | fp->fxp_name);
|
---|
2109 | }
|
---|
2110 | }
|
---|
2111 | if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
|
---|
2112 | {
|
---|
2113 | printf("%s", fp->fxp_name);
|
---|
2114 | if (mii_ms_status & MII_MSS_RES)
|
---|
2115 | printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
|
---|
2116 | if (mii_ms_status & MII_MSS_IDLE_ERR)
|
---|
2117 | {
|
---|
2118 | printf(" idle error %d",
|
---|
2119 | mii_ms_status & MII_MSS_IDLE_ERR);
|
---|
2120 | }
|
---|
2121 | printf("\n");
|
---|
2122 | }
|
---|
2123 |
|
---|
2124 | resspeed:
|
---|
2125 | #if VERBOSE
|
---|
2126 | printf("%s: link up, %d Mbps, %s duplex\n",
|
---|
2127 | fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
|
---|
2128 | (scr & MII_SCR_FD) ? "full" : "half");
|
---|
2129 | #endif
|
---|
2130 | ;
|
---|
2131 | }
|
---|
2132 |
|
---|
2133 | /*===========================================================================*
|
---|
2134 | * fxp_stop *
|
---|
2135 | *===========================================================================*/
|
---|
2136 | static void fxp_stop()
|
---|
2137 | {
|
---|
2138 | int i;
|
---|
2139 | port_t port;
|
---|
2140 | fxp_t *fp;
|
---|
2141 |
|
---|
2142 | for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
|
---|
2143 | {
|
---|
2144 | if (fp->fxp_mode != FM_ENABLED)
|
---|
2145 | continue;
|
---|
2146 | if (!(fp->fxp_flags & FF_ENABLED))
|
---|
2147 | continue;
|
---|
2148 | port= fp->fxp_base_port;
|
---|
2149 |
|
---|
2150 | /* Reset device */
|
---|
2151 | if (debug)
|
---|
2152 | printf("%s: resetting device\n", fp->fxp_name);
|
---|
2153 | fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
|
---|
2154 | }
|
---|
2155 | sys_exit(0);
|
---|
2156 | }
|
---|
2157 |
|
---|
2158 | /*===========================================================================*
|
---|
2159 | * reply *
|
---|
2160 | *===========================================================================*/
|
---|
2161 | static void reply(fp, err, may_block)
|
---|
2162 | fxp_t *fp;
|
---|
2163 | int err;
|
---|
2164 | int may_block;
|
---|
2165 | {
|
---|
2166 | message reply;
|
---|
2167 | int status;
|
---|
2168 | int r;
|
---|
2169 |
|
---|
2170 | status = 0;
|
---|
2171 | if (fp->fxp_flags & FF_PACK_SENT)
|
---|
2172 | status |= DL_PACK_SEND;
|
---|
2173 | if (fp->fxp_flags & FF_PACK_RECV)
|
---|
2174 | status |= DL_PACK_RECV;
|
---|
2175 |
|
---|
2176 | reply.m_type = DL_TASK_REPLY;
|
---|
2177 | reply.DL_PORT = fp - fxp_table;
|
---|
2178 | reply.DL_PROC = fp->fxp_client;
|
---|
2179 | reply.DL_STAT = status | ((u32_t) err << 16);
|
---|
2180 | reply.DL_COUNT = fp->fxp_read_s;
|
---|
2181 | #if 0
|
---|
2182 | reply.DL_CLCK = get_uptime();
|
---|
2183 | #else
|
---|
2184 | reply.DL_CLCK = 0;
|
---|
2185 | #endif
|
---|
2186 |
|
---|
2187 | r= send(fp->fxp_client, &reply);
|
---|
2188 |
|
---|
2189 | if (r == ELOCKED && may_block)
|
---|
2190 | {
|
---|
2191 | #if 0
|
---|
2192 | printW(); printf("send locked\n");
|
---|
2193 | #endif
|
---|
2194 | return;
|
---|
2195 | }
|
---|
2196 |
|
---|
2197 | if (r < 0)
|
---|
2198 | panic("FXP","fxp: send failed:", r);
|
---|
2199 |
|
---|
2200 | fp->fxp_read_s = 0;
|
---|
2201 | fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
|
---|
2202 | }
|
---|
2203 |
|
---|
2204 | /*===========================================================================*
|
---|
2205 | * mess_reply *
|
---|
2206 | *===========================================================================*/
|
---|
2207 | static void mess_reply(req, reply_mess)
|
---|
2208 | message *req;
|
---|
2209 | message *reply_mess;
|
---|
2210 | {
|
---|
2211 | if (send(req->m_source, reply_mess) != OK)
|
---|
2212 | panic("FXP","fxp: unable to mess_reply", NO_NUM);
|
---|
2213 | }
|
---|
2214 |
|
---|
2215 | /*===========================================================================*
|
---|
2216 | * put_userdata *
|
---|
2217 | *===========================================================================*/
|
---|
2218 | static void put_userdata(user_proc, user_addr, count, loc_addr)
|
---|
2219 | int user_proc;
|
---|
2220 | vir_bytes user_addr;
|
---|
2221 | vir_bytes count;
|
---|
2222 | void *loc_addr;
|
---|
2223 | {
|
---|
2224 | int r;
|
---|
2225 |
|
---|
2226 | r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
|
---|
2227 | user_proc, D, user_addr, count);
|
---|
2228 | if (r != OK)
|
---|
2229 | panic("FXP","put_userdata: sys_vircopy failed", r);
|
---|
2230 | }
|
---|
2231 |
|
---|
2232 | /*===========================================================================*
|
---|
2233 | * eeprom_read *
|
---|
2234 | *===========================================================================*/
|
---|
2235 | PRIVATE u16_t eeprom_read(fp, reg)
|
---|
2236 | fxp_t *fp;
|
---|
2237 | int reg;
|
---|
2238 | {
|
---|
2239 | port_t port;
|
---|
2240 | u16_t v;
|
---|
2241 | int b, i, alen;
|
---|
2242 |
|
---|
2243 | alen= fp->fxp_ee_addrlen;
|
---|
2244 | if (!alen)
|
---|
2245 | {
|
---|
2246 | eeprom_addrsize(fp);
|
---|
2247 | alen= fp->fxp_ee_addrlen;
|
---|
2248 | assert(alen == 6 || alen == 8);
|
---|
2249 | }
|
---|
2250 |
|
---|
2251 | port= fp->fxp_base_port;
|
---|
2252 |
|
---|
2253 | fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
|
---|
2254 | v= EEPROM_READ_PREFIX;
|
---|
2255 | for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
|
---|
2256 | {
|
---|
2257 | b= ((v & (1 << i)) ? CE_EEDI : 0);
|
---|
2258 | fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
|
---|
2259 | fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
|
---|
2260 | micro_delay(EESK_PERIOD/2+1);
|
---|
2261 | fxp_outb(port, CSR_EEPROM, CE_EECS | b);
|
---|
2262 | micro_delay(EESK_PERIOD/2+1);
|
---|
2263 | }
|
---|
2264 |
|
---|
2265 | v= reg;
|
---|
2266 | for (i= alen-1; i >= 0; i--)
|
---|
2267 | {
|
---|
2268 | b= ((v & (1 << i)) ? CE_EEDI : 0);
|
---|
2269 | fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
|
---|
2270 | fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
|
---|
2271 | micro_delay(EESK_PERIOD/2+1);
|
---|
2272 | fxp_outb(port, CSR_EEPROM, CE_EECS | b);
|
---|
2273 | micro_delay(EESK_PERIOD/2+1);
|
---|
2274 | }
|
---|
2275 |
|
---|
2276 | v= 0;
|
---|
2277 | for (i= 0; i<16; i++)
|
---|
2278 | {
|
---|
2279 | fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
|
---|
2280 | micro_delay(EESK_PERIOD/2+1);
|
---|
2281 | b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
|
---|
2282 | v= (v << 1) | b;
|
---|
2283 | fxp_outb(port, CSR_EEPROM, CE_EECS );
|
---|
2284 | micro_delay(EESK_PERIOD/2+1);
|
---|
2285 | }
|
---|
2286 | fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
|
---|
2287 | micro_delay(EECS_DELAY);
|
---|
2288 |
|
---|
2289 | return v;
|
---|
2290 | }
|
---|
2291 |
|
---|
2292 | /*===========================================================================*
|
---|
2293 | * eeprom_addrsize *
|
---|
2294 | *===========================================================================*/
|
---|
2295 | PRIVATE void eeprom_addrsize(fp)
|
---|
2296 | fxp_t *fp;
|
---|
2297 | {
|
---|
2298 | port_t port;
|
---|
2299 | u16_t v;
|
---|
2300 | int b, i;
|
---|
2301 |
|
---|
2302 | port= fp->fxp_base_port;
|
---|
2303 |
|
---|
2304 | /* Try to find out the size of the EEPROM */
|
---|
2305 | fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
|
---|
2306 | v= EEPROM_READ_PREFIX;
|
---|
2307 | for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
|
---|
2308 | {
|
---|
2309 | b= ((v & (1 << i)) ? CE_EEDI : 0);
|
---|
2310 | fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
|
---|
2311 | fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
|
---|
2312 | micro_delay(EESK_PERIOD/2+1);
|
---|
2313 | fxp_outb(port, CSR_EEPROM, CE_EECS | b);
|
---|
2314 | micro_delay(EESK_PERIOD/2+1);
|
---|
2315 | }
|
---|
2316 |
|
---|
2317 | for (i= 0; i<32; i++)
|
---|
2318 | {
|
---|
2319 | b= 0;
|
---|
2320 | fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
|
---|
2321 | fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
|
---|
2322 | micro_delay(EESK_PERIOD/2+1);
|
---|
2323 | fxp_outb(port, CSR_EEPROM, CE_EECS | b);
|
---|
2324 | micro_delay(EESK_PERIOD/2+1);
|
---|
2325 | v= fxp_inb(port, CSR_EEPROM);
|
---|
2326 | if (!(v & CE_EEDO))
|
---|
2327 | break;
|
---|
2328 | }
|
---|
2329 | if (i >= 32)
|
---|
2330 | panic("FXP","eeprom_addrsize: failed", NO_NUM);
|
---|
2331 | fp->fxp_ee_addrlen= i+1;
|
---|
2332 |
|
---|
2333 | /* Discard 16 data bits */
|
---|
2334 | for (i= 0; i<16; i++)
|
---|
2335 | {
|
---|
2336 | fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
|
---|
2337 | micro_delay(EESK_PERIOD/2+1);
|
---|
2338 | fxp_outb(port, CSR_EEPROM, CE_EECS );
|
---|
2339 | micro_delay(EESK_PERIOD/2+1);
|
---|
2340 | }
|
---|
2341 | fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
|
---|
2342 | micro_delay(EECS_DELAY);
|
---|
2343 |
|
---|
2344 | #if VERBOSE
|
---|
2345 | printf("%s EEPROM address length: %d\n",
|
---|
2346 | fp->fxp_name, fp->fxp_ee_addrlen);
|
---|
2347 | #endif
|
---|
2348 | }
|
---|
2349 |
|
---|
2350 | /*===========================================================================*
|
---|
2351 | * mii_read *
|
---|
2352 | *===========================================================================*/
|
---|
2353 | PRIVATE u16_t mii_read(fp, reg)
|
---|
2354 | fxp_t *fp;
|
---|
2355 | int reg;
|
---|
2356 | {
|
---|
2357 | clock_t t0,t1;
|
---|
2358 | port_t port;
|
---|
2359 | u32_t v;
|
---|
2360 |
|
---|
2361 | port= fp->fxp_base_port;
|
---|
2362 |
|
---|
2363 | assert(!fp->fxp_mii_busy);
|
---|
2364 | fp->fxp_mii_busy++;
|
---|
2365 |
|
---|
2366 | if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
|
---|
2367 | panic("FXP","mii_read: MDI not ready", NO_NUM);
|
---|
2368 | fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
|
---|
2369 | (reg << CM_REG_SHIFT));
|
---|
2370 |
|
---|
2371 | getuptime(&t0);
|
---|
2372 | do {
|
---|
2373 | v= fxp_inl(port, CSR_MDI_CTL);
|
---|
2374 | if (v & CM_READY)
|
---|
2375 | break;
|
---|
2376 | } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
|
---|
2377 |
|
---|
2378 | if (!(v & CM_READY))
|
---|
2379 | panic("FXP","mii_read: MDI not ready after command", NO_NUM);
|
---|
2380 |
|
---|
2381 | fp->fxp_mii_busy--;
|
---|
2382 | assert(!fp->fxp_mii_busy);
|
---|
2383 |
|
---|
2384 | return v & CM_DATA_MASK;
|
---|
2385 | }
|
---|
2386 |
|
---|
2387 | /*===========================================================================*
|
---|
2388 | * fxp_set_timer *
|
---|
2389 | *===========================================================================*/
|
---|
2390 | PRIVATE void fxp_set_timer(tp, delta, watchdog)
|
---|
2391 | timer_t *tp; /* timer to be set */
|
---|
2392 | clock_t delta; /* in how many ticks */
|
---|
2393 | tmr_func_t watchdog; /* watchdog function to be called */
|
---|
2394 | {
|
---|
2395 | clock_t now; /* current time */
|
---|
2396 | int r;
|
---|
2397 |
|
---|
2398 | /* Get the current time. */
|
---|
2399 | r= getuptime(&now);
|
---|
2400 | if (r != OK)
|
---|
2401 | panic("FXP","unable to get uptime from clock", r);
|
---|
2402 |
|
---|
2403 | /* Add the timer to the local timer queue. */
|
---|
2404 | tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
|
---|
2405 |
|
---|
2406 | /* Possibly reschedule an alarm call. This happens when a new timer
|
---|
2407 | * is added in front.
|
---|
2408 | */
|
---|
2409 | if (fxp_next_timeout == 0 ||
|
---|
2410 | fxp_timers->tmr_exp_time < fxp_next_timeout)
|
---|
2411 | {
|
---|
2412 | fxp_next_timeout= fxp_timers->tmr_exp_time;
|
---|
2413 | #if VERBOSE
|
---|
2414 | printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
|
---|
2415 | fxp_next_timeout, fxp_next_timeout-now);
|
---|
2416 | #endif
|
---|
2417 | r= sys_setalarm(fxp_next_timeout, 1);
|
---|
2418 | if (r != OK)
|
---|
2419 | panic("FXP","unable to set synchronous alarm", r);
|
---|
2420 | }
|
---|
2421 | }
|
---|
2422 |
|
---|
2423 | /*===========================================================================*
|
---|
2424 | * fxp_expire_tmrs *
|
---|
2425 | *===========================================================================*/
|
---|
2426 | PRIVATE void fxp_expire_timers()
|
---|
2427 | {
|
---|
2428 | /* A synchronous alarm message was received. Check if there are any expired
|
---|
2429 | * timers. Possibly reschedule the next alarm.
|
---|
2430 | */
|
---|
2431 | clock_t now; /* current time */
|
---|
2432 | timer_t *tp;
|
---|
2433 | int r;
|
---|
2434 |
|
---|
2435 | /* Get the current time to compare the timers against. */
|
---|
2436 | r= getuptime(&now);
|
---|
2437 | if (r != OK)
|
---|
2438 | panic("FXP","Unable to get uptime from clock.", r);
|
---|
2439 |
|
---|
2440 | /* Scan the timers queue for expired timers. Dispatch the watchdog function
|
---|
2441 | * for each expired timers. Possibly a new alarm call must be scheduled.
|
---|
2442 | */
|
---|
2443 | tmrs_exptimers(&fxp_timers, now, NULL);
|
---|
2444 | if (fxp_timers == NULL)
|
---|
2445 | fxp_next_timeout= TMR_NEVER;
|
---|
2446 | else
|
---|
2447 | { /* set new alarm */
|
---|
2448 | fxp_next_timeout = fxp_timers->tmr_exp_time;
|
---|
2449 | r= sys_setalarm(fxp_next_timeout, 1);
|
---|
2450 | if (r != OK)
|
---|
2451 | panic("FXP","Unable to set synchronous alarm.", r);
|
---|
2452 | }
|
---|
2453 | }
|
---|
2454 |
|
---|
2455 | static void micro_delay(unsigned long usecs)
|
---|
2456 | {
|
---|
2457 | tickdelay(MICROS_TO_TICKS(usecs));
|
---|
2458 | }
|
---|
2459 |
|
---|
2460 | static u8_t do_inb(port_t port)
|
---|
2461 | {
|
---|
2462 | int r;
|
---|
2463 | u32_t value;
|
---|
2464 |
|
---|
2465 | r= sys_inb(port, &value);
|
---|
2466 | if (r != OK)
|
---|
2467 | panic("FXP","sys_inb failed", r);
|
---|
2468 | return value;
|
---|
2469 | }
|
---|
2470 |
|
---|
2471 | static u32_t do_inl(port_t port)
|
---|
2472 | {
|
---|
2473 | int r;
|
---|
2474 | u32_t value;
|
---|
2475 |
|
---|
2476 | r= sys_inl(port, &value);
|
---|
2477 | if (r != OK)
|
---|
2478 | panic("FXP","sys_inl failed", r);
|
---|
2479 | return value;
|
---|
2480 | }
|
---|
2481 |
|
---|
2482 | static void do_outb(port_t port, u8_t value)
|
---|
2483 | {
|
---|
2484 | int r;
|
---|
2485 |
|
---|
2486 | r= sys_outb(port, value);
|
---|
2487 | if (r != OK)
|
---|
2488 | panic("FXP","sys_outb failed", r);
|
---|
2489 | }
|
---|
2490 |
|
---|
2491 | static void do_outl(port_t port, u32_t value)
|
---|
2492 | {
|
---|
2493 | int r;
|
---|
2494 |
|
---|
2495 | r= sys_outl(port, value);
|
---|
2496 | if (r != OK)
|
---|
2497 | panic("FXP","sys_outl failed", r);
|
---|
2498 | }
|
---|
2499 |
|
---|
2500 | /*
|
---|
2501 | * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $
|
---|
2502 | */
|
---|
2503 |
|
---|