Annotation of sys/arch/mvme88k/stand/netboot/if_ie.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ie.c,v 1.8 2006/05/16 22:52:09 miod Exp $ */
2:
3: /*
4: * Copyright (c) 1995 Theo de Raadt
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: */
27:
28: #include <sys/param.h>
29: #include <sys/types.h>
30:
31: #include <netinet/in.h>
32: #include <netinet/in_systm.h>
33:
34: #define ETHER_MIN_LEN 64
35: #define ETHER_MAX_LEN 1518
36: #define ETHER_CRC_LEN 4
37:
38: #define NTXBUF 1
39: #define NRXBUF 16
40: #define IE_RBUF_SIZE ETHER_MAX_LEN
41:
42: #include <machine/prom.h>
43:
44: #include "stand.h"
45: #include "libsa.h"
46: #include "netif.h"
47: #include "config.h"
48: #include "net.h"
49:
50: #include "i82586.h"
51: #include "if_iereg.h"
52:
53: int ie_debug = 0;
54:
55: void ie_stop(struct netif *);
56: void ie_end(struct netif *);
57: void ie_error(struct netif *, char *, volatile struct iereg *);
58: int ie_get(struct iodesc *, void *, size_t, time_t);
59: void ie_init(struct iodesc *, void *);
60: int ie_match(struct netif *, void *);
61: int ie_poll(struct iodesc *, void *, int);
62: int ie_probe(struct netif *, void *);
63: int ie_put(struct iodesc *, void *, size_t);
64: void ie_reset(struct netif *, u_char *);
65: extern void machdep_common_ether(u_char *);
66:
67: struct netif_stats ie_stats;
68:
69: struct netif_dif ie0_dif = {
70: 0, /* unit */
71: 1, /* nsel */
72: &ie_stats,
73: 0,
74: 0,
75: };
76:
77: struct netif_driver ie_driver = {
78: "ie", /* netif_bname */
79: ie_match, /* match */
80: ie_probe, /* probe */
81: ie_init, /* init */
82: ie_get, /* get */
83: ie_put, /* put */
84: ie_end, /* end */
85: &ie0_dif, /* netif_ifs */
86: 1, /* netif_nifs */
87: };
88:
89: struct ie_configuration {
90: u_int phys_addr;
91: int used;
92: } ie_config[] = {
93: { INTEL_REG_ADDR, 0 }
94: };
95:
96: int nie_config = sizeof(ie_config) / (sizeof(ie_config[0]));
97:
98: struct {
99: struct iereg *sc_reg; /* IE registers */
100: struct iemem *sc_mem; /* RAM */
101: } ie_softc;
102:
103: int
104: ie_match(nif, machdep_hint)
105: struct netif *nif;
106: void *machdep_hint;
107: {
108: char *name;
109: int i, val = 0;
110:
111: name = machdep_hint;
112: if (name && !bcmp(ie_driver.netif_bname, name, 2))
113: val += 10;
114: for (i = 0; i < nie_config; i++) {
115: if (ie_config[i].used)
116: continue;
117: if (ie_debug)
118: printf("ie%d: ie_match --> %d\n", i, val + 1);
119: ie_config[i].used++;
120: return (val + 1);
121: }
122: if (ie_debug)
123: printf("ie%d: ie_match --> 0\n", i);
124: return (0);
125: }
126:
127: int
128: ie_probe(nif, machdep_hint)
129: struct netif *nif;
130: void *machdep_hint;
131: {
132:
133: /* the set unit is the current unit */
134: if (ie_debug)
135: printf("ie%d: ie_probe called\n", nif->nif_unit);
136: return (0);
137: /* return (1);*/
138: }
139:
140: void
141: ie_error(nif, str, ier)
142: struct netif *nif;
143: char *str;
144: volatile struct iereg *ier;
145: {
146: panic("ie%d: unknown error", nif->nif_unit);
147: }
148:
149: void
150: ieack(ier, iem)
151: volatile struct iereg *ier;
152: struct iemem *iem;
153: {
154: /* ack the `interrupt' */
155: iem->im_scb.ie_command = iem->im_scb.ie_status & IE_ST_WHENCE;
156: ier->ie_attention = 1; /* chan attention! */
157: while (iem->im_scb.ie_command)
158: ;
159: }
160:
161: void
162: ie_reset(nif, myea)
163: struct netif *nif;
164: u_char *myea;
165: {
166: volatile struct iereg *ier = ie_softc.sc_reg;
167: struct iemem *iem = ie_softc.sc_mem;
168: int timo = 10000, i;
169: volatile int t;
170: u_int a;
171:
172: if (ie_debug)
173: printf("ie%d: ie_reset called\n", nif->nif_unit);
174:
175: /*printf("ier %x iem %x\n", ier, iem);*/
176:
177: *(u_char *)0xfff4202a = 0x40;
178:
179: bzero(iem, sizeof(*iem));
180: iem->im_scp.scp_sysbus = 0;
181: iem->im_scp.scp_iscp_low = (int) &iem->im_iscp & 0xffff;
182: iem->im_scp.scp_iscp_high = (int) &iem->im_iscp >> 16;
183:
184: iem->im_iscp.iscp_scboffset = (int) &iem->im_scb - (int) iem;
185: iem->im_iscp.iscp_busy = 1;
186: iem->im_iscp.iscp_base_low = (int) iem & 0xffff;
187: iem->im_iscp.iscp_base_high = (int) iem >> 16;
188:
189: /*
190: * completely and utterly unlike what i expected, the
191: * "write" order is:
192: * 1st: d15-d0 -> high address
193: * 2nd: d31-d16 -> low address
194: */
195:
196: /* reset chip */
197: a = IE_PORT_RESET;
198: ier->ie_porthigh = a & 0xffff;
199: t = 0;
200: t = 1;
201: ier->ie_portlow = a >> 16;
202: for (t = timo; t--;)
203: ;
204:
205: /* set new SCP pointer */
206: a = (int) &iem->im_scp | IE_PORT_NEWSCP;
207: ier->ie_porthigh = a & 0xffff;
208: t = 0;
209: t = 1;
210: ier->ie_portlow = a >> 16;
211: for (t = timo; t--;)
212: ;
213:
214: ier->ie_attention = 1; /* chan attention! */
215: for (t = timo * 10; t--;)
216: ;
217:
218: /* send CONFIGURE command */
219: iem->im_scb.ie_command = IE_CU_START;
220: iem->im_scb.ie_command_list = (int) &iem->im_cc - (int) iem;
221: iem->im_cc.com.ie_cmd_status = 0;
222: iem->im_cc.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
223: iem->im_cc.com.ie_cmd_link = 0xffff;
224: iem->im_cc.ie_config_count = 0x0c;
225: iem->im_cc.ie_fifo = 8;
226: iem->im_cc.ie_save_bad = 0x40;
227: iem->im_cc.ie_addr_len = 0x2e;
228: iem->im_cc.ie_priority = 0;
229: iem->im_cc.ie_ifs = 0x60;
230: iem->im_cc.ie_slot_low = 0;
231: iem->im_cc.ie_slot_high = 0xf2;
232: iem->im_cc.ie_promisc = 0;
233: iem->im_cc.ie_crs_cdt = 0;
234: iem->im_cc.ie_min_len = 64;
235: iem->im_cc.ie_junk = 0xff;
236:
237: ier->ie_attention = 1; /* chan attention! */
238: for (t = timo * 10; t--;)
239: ;
240:
241: ieack(ier, iem);
242:
243: /*printf("ic %x\n", &iem->im_ic);*/
244: /* send IASETUP command */
245: iem->im_scb.ie_command = IE_CU_START;
246: iem->im_scb.ie_command_list = (int) &iem->im_ic - (int) iem;
247: iem->im_ic.com.ie_cmd_status = 0;
248: iem->im_ic.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
249: iem->im_ic.com.ie_cmd_link = 0xffff;
250: bcopy(myea, (void *)&iem->im_ic.ie_address, sizeof iem->im_ic.ie_address);
251:
252: ier->ie_attention = 1; /* chan attention! */
253: for (t = timo * 10; t--;)
254: ;
255:
256: ieack(ier, iem);
257:
258: /* setup buffers */
259:
260: for (i = 0; i < NRXBUF; i++) {
261: iem->im_rfd[i].ie_fd_next = (int) &iem->im_rfd[(i+1) % NRXBUF] -
262: (int) iem;
263: iem->im_rbd[i].ie_rbd_next = (int) &iem->im_rbd[(i+1) % NRXBUF] -
264: (int) iem;
265: a = (int) &iem->im_rxbuf[i * IE_RBUF_SIZE];
266: iem->im_rbd[i].ie_rbd_buffer_low = a & 0xffff;
267: iem->im_rbd[i].ie_rbd_buffer_high = a >> 16;
268: iem->im_rbd[i].ie_rbd_length = IE_RBUF_SIZE;
269: }
270: iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
271: iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
272: iem->im_rfd[0].ie_fd_buf_desc = (int) &iem->im_rbd[0] - (int) iem;
273:
274: /*printf("rfd[0] %x rbd[0] %x buf[0] %x\n", &iem->im_rfd, &iem->im_rbd,
275: &iem->im_rxbuf);*/
276:
277: /* send receiver start command */
278: iem->im_scb.ie_command = IE_RU_START;
279: iem->im_scb.ie_command_list = 0;
280: iem->im_scb.ie_recv_list = (int) &iem->im_rfd[0] - (int) iem;
281: ier->ie_attention = 1; /* chan attention! */
282: while (iem->im_scb.ie_command)
283: ;
284:
285: ieack(ier, iem);
286: }
287:
288: int
289: ie_poll(desc, pkt, len)
290: struct iodesc *desc;
291: void *pkt;
292: int len;
293: {
294: volatile struct iereg *ier = ie_softc.sc_reg;
295: struct iemem *iem = ie_softc.sc_mem;
296: static int slot;
297: int length = 0;
298: u_short status;
299:
300: asm(".word 0xf518\n");
301: status = iem->im_rfd[slot].ie_fd_status;
302: if (status & IE_FD_BUSY)
303: return (0);
304:
305: /* printf("slot %d: %x\n", slot, status); */
306: if ((status & (IE_FD_COMPLETE | IE_FD_OK)) == (IE_FD_COMPLETE | IE_FD_OK)) {
307: if (status & IE_FD_OK) {
308: length = iem->im_rbd[slot].ie_rbd_actual & 0x3fff;
309: if (length > len)
310: length = len;
311: bcopy((void *)&iem->im_rxbuf[slot * IE_RBUF_SIZE],
312: pkt, length);
313:
314: iem->im_rfd[slot].ie_fd_status = 0;
315: iem->im_rfd[slot].ie_fd_last |= IE_FD_LAST;
316: iem->im_rfd[(slot+NRXBUF-1)%NRXBUF].ie_fd_last &=
317: ~IE_FD_LAST;
318: iem->im_rbd[slot].ie_rbd_actual = 0;
319: iem->im_rbd[slot].ie_rbd_length |= IE_RBD_LAST;
320: iem->im_rbd[(slot+NRXBUF-1)%NRXBUF].ie_rbd_length &=
321: ~IE_RBD_LAST;
322: /*printf("S%d\n", slot);*/
323:
324: } else {
325: printf("shit\n");
326: }
327: slot++;
328: /* should move descriptor onto end of queue... */
329: }
330: if ((iem->im_scb.ie_status & IE_RU_READY) == 0) {
331: printf("RR\n");
332:
333: for (slot = 0; slot < NRXBUF; slot++) {
334: iem->im_rbd[slot].ie_rbd_length &= ~IE_RBD_LAST;
335: iem->im_rfd[slot].ie_fd_last &= ~IE_FD_LAST;
336: }
337: iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
338: iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
339:
340: iem->im_rfd[0].ie_fd_buf_desc = (int)&iem->im_rbd[0] - (int)iem;
341:
342: iem->im_scb.ie_command = IE_RU_START;
343: iem->im_scb.ie_command_list = 0;
344: iem->im_scb.ie_recv_list = (int)&iem->im_rfd[0] - (int)iem;
345: ier->ie_attention = 1; /* chan attention! */
346: while (iem->im_scb.ie_command)
347: ;
348: slot = 0;
349: }
350: slot = slot % NRXBUF;
351: return (length);
352: }
353:
354: int
355: ie_put(desc, pkt, len)
356: struct iodesc *desc;
357: void *pkt;
358: size_t len;
359: {
360: volatile struct iereg *ier = ie_softc.sc_reg;
361: struct iemem *iem = ie_softc.sc_mem;
362: u_char *p = pkt;
363: u_int a;
364: int xx = 0;
365:
366: /* send transmit command */
367:
368: while (iem->im_scb.ie_command)
369: ;
370:
371: /* copy data */
372: bcopy(p, (void *)&iem->im_txbuf[xx], len);
373:
374: if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
375: bzero((char *)&iem->im_txbuf[xx] + len,
376: ETHER_MIN_LEN - ETHER_CRC_LEN - len);
377: len = ETHER_MIN_LEN - ETHER_CRC_LEN;
378: }
379:
380: /* build transmit descriptor */
381: iem->im_xd[xx].ie_xmit_flags = len | IE_XMIT_LAST;
382: iem->im_xd[xx].ie_xmit_next = 0xffff;
383: a = (int) &iem->im_txbuf[xx];
384: iem->im_xd[xx].ie_xmit_buf_low = a & 0xffff;
385: iem->im_xd[xx].ie_xmit_buf_high = a >> 16;
386:
387: /* transmit command */
388: iem->im_xc[xx].com.ie_cmd_status = 0;
389: iem->im_xc[xx].com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_LAST;
390: iem->im_xc[xx].com.ie_cmd_link = 0xffff;
391: iem->im_xc[xx].ie_xmit_desc = (int) &iem->im_xd[xx] - (int) iem;
392: iem->im_xc[xx].ie_xmit_length = len;
393: bcopy(p, (void *)&iem->im_xc[xx].ie_xmit_addr,
394: sizeof iem->im_xc[xx].ie_xmit_addr);
395:
396: iem->im_scb.ie_command = IE_CU_START;
397: iem->im_scb.ie_command_list = (int) &iem->im_xc[xx] - (int) iem;
398:
399: ier->ie_attention = 1; /* chan attention! */
400:
401: if (ie_debug) {
402: printf("ie%d: send %ld to %x:%x:%x:%x:%x:%x\n",
403: desc->io_netif->nif_unit, len,
404: p[0], p[1], p[2], p[3], p[4], p[5]);
405: }
406: return (len);
407: }
408:
409: int
410: ie_get(desc, pkt, len, timeout)
411: struct iodesc *desc;
412: void *pkt;
413: size_t len;
414: time_t timeout;
415: {
416: time_t t;
417: int cc;
418:
419: t = getsecs();
420: cc = 0;
421: while (((getsecs() - t) < timeout) && !cc) {
422: cc = ie_poll(desc, pkt, len);
423: }
424: return (cc);
425: }
426: /*
427: * init ie device. return 0 on failure, 1 if ok.
428: */
429: void
430: ie_init(desc, machdep_hint)
431: struct iodesc *desc;
432: void *machdep_hint;
433: {
434: struct netif *nif = desc->io_netif;
435:
436: if (ie_debug)
437: printf("ie%d: ie_init called\n", desc->io_netif->nif_unit);
438: machdep_common_ether(desc->myea);
439: bzero(&ie_softc, sizeof(ie_softc));
440: ie_softc.sc_reg =
441: (struct iereg *) ie_config[desc->io_netif->nif_unit].phys_addr;
442: ie_softc.sc_mem = (struct iemem *) 0xae0000;
443: ie_reset(desc->io_netif, desc->myea);
444: printf("device: %s%d attached to %s\n", nif->nif_driver->netif_bname,
445: nif->nif_unit, ether_sprintf(desc->myea));
446: }
447:
448: void
449: ie_stop(nif)
450: struct netif *nif;
451: {
452: volatile struct iereg *ier = ie_softc.sc_reg;
453: struct iemem *iem = ie_softc.sc_mem;
454: int timo = 10000;
455: volatile int t;
456: u_int a;
457:
458: iem->im_iscp.iscp_busy = 1;
459: /* reset chip */
460: a = IE_PORT_RESET;
461: ier->ie_porthigh = a & 0xffff;
462: t = 0;
463: t = 1;
464: ier->ie_portlow = a >> 16;
465: for (t = timo; t--;)
466: ;
467:
468: /* reset chip again */
469: a = IE_PORT_RESET;
470: ier->ie_porthigh = a & 0xffff;
471: t = 0;
472: t = 1;
473: ier->ie_portlow = a >> 16;
474: for (t = timo; t--;)
475: ;
476:
477: /*printf("status %x busy %x\n", iem->im_scb.ie_status,
478: iem->im_iscp.iscp_busy);*/
479: }
480:
481: void
482: ie_end(nif)
483: struct netif *nif;
484: {
485: if (ie_debug)
486: printf("ie%d: ie_end called\n", nif->nif_unit);
487:
488: ie_stop(nif);
489:
490: /* *(u_char *) 0xfff42002 = 0; */
491: }
CVSweb