Annotation of sys/arch/mvme68k/stand/netboot/if_ie.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ie.c,v 1.12 2003/08/20 00:26:00 deraadt 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:
49: #include "i82586.h"
50: #include "if_iereg.h"
51:
52: int ie_debug = 0;
53:
54: void ie_stop(struct netif *);
55: void ie_end(struct netif *);
56: void ie_error(struct netif *, char *, volatile struct iereg *);
57: int ie_get(struct iodesc *, void *, size_t, time_t);
58: void ie_init(struct iodesc *, void *);
59: int ie_match(struct netif *, void *);
60: int ie_poll(struct iodesc *, void *, int);
61: int ie_probe(struct netif *, void *);
62: int ie_put(struct iodesc *, void *, size_t);
63: void ie_reset(struct netif *, u_char *);
64:
65: struct netif_stats ie_stats;
66:
67: struct netif_dif ie0_dif = {
68: 0, /* unit */
69: 1, /* nsel */
70: &ie_stats,
71: 0,
72: 0,
73: };
74:
75: struct netif_driver ie_driver = {
76: "ie", /* netif_bname */
77: ie_match, /* match */
78: ie_probe, /* probe */
79: ie_init, /* init */
80: ie_get, /* get */
81: ie_put, /* put */
82: ie_end, /* end */
83: &ie0_dif, /* netif_ifs */
84: 1, /* netif_nifs */
85: };
86:
87: struct ie_configuration {
88: u_int phys_addr;
89: int used;
90: } ie_config[] = {
91: { INTEL_REG_ADDR, 0 }
92: };
93:
94: int nie_config = sizeof(ie_config) / (sizeof(ie_config[0]));
95:
96: struct {
97: struct iereg *sc_reg; /* IE registers */
98: struct iemem *sc_mem; /* RAM */
99: } ie_softc;
100:
101: int
102: ie_match(struct netif *nif, void *machdep_hint)
103: {
104: char *name;
105: int i, val = 0;
106:
107: if (bugargs.cputyp == CPU_147)
108: return (0);
109: name = machdep_hint;
110: if (name && !bcmp(ie_driver.netif_bname, name, 2))
111: val += 10;
112: for (i = 0; i < nie_config; i++) {
113: if (ie_config[i].used)
114: continue;
115: if (ie_debug)
116: printf("ie%d: ie_match --> %d\n", i, val + 1);
117: ie_config[i].used++;
118: return (val + 1);
119: }
120: if (ie_debug)
121: printf("ie%d: ie_match --> 0\n", i);
122: return (0);
123: }
124:
125: int
126: ie_probe(struct netif *nif, void *machdep_hint)
127: {
128:
129: /* the set unit is the current unit */
130: if (ie_debug)
131: printf("ie%d: ie_probe called\n", nif->nif_unit);
132:
133: if (bugargs.cputyp != CPU_147)
134: return (0);
135: return (1);
136: }
137:
138: void
139: ie_error(struct netif *nif, char *str, volatile struct iereg *ier)
140: {
141: panic("ie%d: unknown error", nif->nif_unit);
142: }
143:
144: static void
145: ieack(volatile struct iereg *ier, struct iemem *iem)
146: {
147: /* ack the `interrupt' */
148: iem->im_scb.ie_command = iem->im_scb.ie_status & IE_ST_WHENCE;
149: ier->ie_attention = 1; /* chan attention! */
150: while (iem->im_scb.ie_command)
151: ;
152: }
153:
154: void
155: ie_reset(struct netif *nif, u_char *myea)
156: {
157: volatile struct iereg *ier = ie_softc.sc_reg;
158: struct iemem *iem = ie_softc.sc_mem;
159: int timo = 10000, stat, i;
160: volatile int t;
161: u_int a;
162:
163: if (ie_debug)
164: printf("ie%d: ie_reset called\n", nif->nif_unit);
165:
166: /*printf("ier %x iem %x\n", ier, iem);*/
167:
168: *(u_char *)0xfff4202a = 0x40;
169:
170: bzero(iem, sizeof(*iem));
171: iem->im_scp.scp_sysbus = 0;
172: iem->im_scp.scp_iscp_low = (int) &iem->im_iscp & 0xffff;
173: iem->im_scp.scp_iscp_high = (int) &iem->im_iscp >> 16;
174:
175: iem->im_iscp.iscp_scboffset = (int) &iem->im_scb - (int) iem;
176: iem->im_iscp.iscp_busy = 1;
177: iem->im_iscp.iscp_base_low = (int) iem & 0xffff;
178: iem->im_iscp.iscp_base_high = (int) iem >> 16;
179:
180: /*
181: * completely and utterly unlike what i expected, the
182: * "write" order is:
183: * 1st: d15-d0 -> high address
184: * 2nd: d31-d16 -> low address
185: */
186:
187: /* reset chip */
188: a = IE_PORT_RESET;
189: ier->ie_porthigh = a & 0xffff;
190: t = 0;
191: t = 1;
192: ier->ie_portlow = a >> 16;
193: for (t = timo; t--;)
194: ;
195:
196: /* set new SCP pointer */
197: a = (int) &iem->im_scp | IE_PORT_NEWSCP;
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: ier->ie_attention = 1; /* chan attention! */
206: for (t = timo * 10; t--;)
207: ;
208:
209: /* send CONFIGURE command */
210: iem->im_scb.ie_command = IE_CU_START;
211: iem->im_scb.ie_command_list = (int) &iem->im_cc - (int) iem;
212: iem->im_cc.com.ie_cmd_status = 0;
213: iem->im_cc.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
214: iem->im_cc.com.ie_cmd_link = 0xffff;
215: iem->im_cc.ie_config_count = 0x0c;
216: iem->im_cc.ie_fifo = 8;
217: iem->im_cc.ie_save_bad = 0x40;
218: iem->im_cc.ie_addr_len = 0x2e;
219: iem->im_cc.ie_priority = 0;
220: iem->im_cc.ie_ifs = 0x60;
221: iem->im_cc.ie_slot_low = 0;
222: iem->im_cc.ie_slot_high = 0xf2;
223: iem->im_cc.ie_promisc = 0;
224: iem->im_cc.ie_crs_cdt = 0;
225: iem->im_cc.ie_min_len = 64;
226: iem->im_cc.ie_junk = 0xff;
227:
228: ier->ie_attention = 1; /* chan attention! */
229: for (t = timo * 10; t--;)
230: ;
231:
232: ieack(ier, iem);
233:
234: /*printf("ic %x\n", &iem->im_ic);*/
235: /* send IASETUP command */
236: iem->im_scb.ie_command = IE_CU_START;
237: iem->im_scb.ie_command_list = (int) &iem->im_ic - (int) iem;
238: iem->im_ic.com.ie_cmd_status = 0;
239: iem->im_ic.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
240: iem->im_ic.com.ie_cmd_link = 0xffff;
241: bcopy(myea, (void *)&iem->im_ic.ie_address, sizeof iem->im_ic.ie_address);
242:
243: ier->ie_attention = 1; /* chan attention! */
244: for (t = timo * 10; t--;)
245: ;
246:
247: ieack(ier, iem);
248:
249: /* setup buffers */
250:
251: for (i = 0; i < NRXBUF; i++) {
252: iem->im_rfd[i].ie_fd_next = (int) &iem->im_rfd[(i+1) % NRXBUF] -
253: (int) iem;
254: iem->im_rbd[i].ie_rbd_next = (int) &iem->im_rbd[(i+1) % NRXBUF] -
255: (int) iem;
256: a = (int) &iem->im_rxbuf[i * IE_RBUF_SIZE];
257: iem->im_rbd[i].ie_rbd_buffer_low = a & 0xffff;
258: iem->im_rbd[i].ie_rbd_buffer_high = a >> 16;
259: iem->im_rbd[i].ie_rbd_length = IE_RBUF_SIZE;
260: }
261: iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
262: iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
263: iem->im_rfd[0].ie_fd_buf_desc = (int) &iem->im_rbd[0] - (int) iem;
264:
265: /*printf("rfd[0] %x rbd[0] %x buf[0] %x\n", &iem->im_rfd, &iem->im_rbd,
266: &iem->im_rxbuf);*/
267:
268: /* send receiver start command */
269: iem->im_scb.ie_command = IE_RU_START;
270: iem->im_scb.ie_command_list = 0;
271: iem->im_scb.ie_recv_list = (int) &iem->im_rfd[0] - (int) iem;
272: ier->ie_attention = 1; /* chan attention! */
273: while (iem->im_scb.ie_command)
274: ;
275:
276: ieack(ier, iem);
277: }
278:
279: int
280: ie_poll(struct iodesc *desc, void *pkt, int len)
281: {
282: volatile struct iereg *ier = ie_softc.sc_reg;
283: struct iemem *iem = ie_softc.sc_mem;
284: u_char *p = pkt;
285: static int slot;
286: int length = 0;
287: u_int a;
288: u_short status;
289:
290: asm(".word 0xf518\n");
291: status = iem->im_rfd[slot].ie_fd_status;
292: if (status & IE_FD_BUSY)
293: return (0);
294:
295: /* printf("slot %d: %x\n", slot, status); */
296: if ((status & (IE_FD_COMPLETE | IE_FD_OK)) == (IE_FD_COMPLETE | IE_FD_OK)) {
297: if (status & IE_FD_OK) {
298: length = iem->im_rbd[slot].ie_rbd_actual & 0x3fff;
299: if (length > len)
300: length = len;
301: bcopy((void *)&iem->im_rxbuf[slot * IE_RBUF_SIZE],
302: pkt, length);
303:
304: iem->im_rfd[slot].ie_fd_status = 0;
305: iem->im_rfd[slot].ie_fd_last |= IE_FD_LAST;
306: iem->im_rfd[(slot+NRXBUF-1)%NRXBUF].ie_fd_last &=
307: ~IE_FD_LAST;
308: iem->im_rbd[slot].ie_rbd_actual = 0;
309: iem->im_rbd[slot].ie_rbd_length |= IE_RBD_LAST;
310: iem->im_rbd[(slot+NRXBUF-1)%NRXBUF].ie_rbd_length &=
311: ~IE_RBD_LAST;
312: /*printf("S%d\n", slot);*/
313:
314: } else {
315: printf("shit\n");
316: }
317: slot++;
318: /* should move descriptor onto end of queue... */
319: }
320: if ((iem->im_scb.ie_status & IE_RU_READY) == 0) {
321: printf("RR\n");
322:
323: for (slot = 0; slot < NRXBUF; slot++) {
324: iem->im_rbd[slot].ie_rbd_length &= ~IE_RBD_LAST;
325: iem->im_rfd[slot].ie_fd_last &= ~IE_FD_LAST;
326: }
327: iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
328: iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
329:
330: iem->im_rfd[0].ie_fd_buf_desc = (int)&iem->im_rbd[0] - (int)iem;
331:
332: iem->im_scb.ie_command = IE_RU_START;
333: iem->im_scb.ie_command_list = 0;
334: iem->im_scb.ie_recv_list = (int)&iem->im_rfd[0] - (int)iem;
335: ier->ie_attention = 1; /* chan attention! */
336: while (iem->im_scb.ie_command)
337: ;
338: slot = 0;
339: }
340: slot = slot % NRXBUF;
341: return (length);
342: }
343:
344: int
345: ie_put(struct iodesc *desc, void *pkt, size_t len)
346: {
347: volatile struct iereg *ier = ie_softc.sc_reg;
348: struct iemem *iem = ie_softc.sc_mem;
349: u_char *p = pkt;
350: int timo = 10000, stat, i;
351: volatile int t;
352: u_int a;
353: int xx = 0;
354:
355: /* send transmit command */
356:
357: while (iem->im_scb.ie_command)
358: ;
359:
360: /* copy data */
361: bcopy(p, (void *)&iem->im_txbuf[xx], len);
362:
363: if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
364: bzero((char *)&iem->im_txbuf[xx] + len,
365: ETHER_MIN_LEN - ETHER_CRC_LEN - len);
366: len = ETHER_MIN_LEN - ETHER_CRC_LEN;
367: }
368:
369: /* build transmit descriptor */
370: iem->im_xd[xx].ie_xmit_flags = len | IE_XMIT_LAST;
371: iem->im_xd[xx].ie_xmit_next = 0xffff;
372: a = (int) &iem->im_txbuf[xx];
373: iem->im_xd[xx].ie_xmit_buf_low = a & 0xffff;
374: iem->im_xd[xx].ie_xmit_buf_high = a >> 16;
375:
376: /* transmit command */
377: iem->im_xc[xx].com.ie_cmd_status = 0;
378: iem->im_xc[xx].com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_LAST;
379: iem->im_xc[xx].com.ie_cmd_link = 0xffff;
380: iem->im_xc[xx].ie_xmit_desc = (int) &iem->im_xd[xx] - (int) iem;
381: iem->im_xc[xx].ie_xmit_length = len;
382: bcopy(p, (void *)&iem->im_xc[xx].ie_xmit_addr,
383: sizeof iem->im_xc[xx].ie_xmit_addr);
384:
385: iem->im_scb.ie_command = IE_CU_START;
386: iem->im_scb.ie_command_list = (int) &iem->im_xc[xx] - (int) iem;
387:
388: ier->ie_attention = 1; /* chan attention! */
389:
390: if (ie_debug) {
391: printf("ie%d: send %d to %x:%x:%x:%x:%x:%x\n",
392: desc->io_netif->nif_unit, len,
393: p[0], p[1], p[2], p[3], p[4], p[5]);
394: }
395: return (len);
396: }
397:
398: int
399: ie_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
400: {
401: time_t t;
402: int cc;
403:
404: t = getsecs();
405: cc = 0;
406: while (((getsecs() - t) < timeout) && !cc) {
407: cc = ie_poll(desc, pkt, len);
408: }
409: return (cc);
410: }
411: /*
412: * init ie device. return 0 on failure, 1 if ok.
413: */
414: void
415: ie_init(struct iodesc *desc, void *machdep_hint)
416: {
417: struct netif *nif = desc->io_netif;
418:
419: if (ie_debug)
420: printf("ie%d: ie_init called\n", desc->io_netif->nif_unit);
421: machdep_common_ether(desc->myea);
422: bzero(&ie_softc, sizeof(ie_softc));
423: ie_softc.sc_reg =
424: (struct iereg *) ie_config[desc->io_netif->nif_unit].phys_addr;
425: /* printf("buffer @0x%x\n", RELOC - 0x20000);*/
426: ie_softc.sc_mem = (struct iemem *) 0x3e0000;
427: ie_reset(desc->io_netif, desc->myea);
428: printf("device: %s%d attached to %s\n", nif->nif_driver->netif_bname,
429: nif->nif_unit, ether_sprintf(desc->myea));
430: }
431:
432: void
433: ie_stop(struct netif *nif)
434: {
435: volatile struct iereg *ier = ie_softc.sc_reg;
436: struct iemem *iem = ie_softc.sc_mem;
437: int timo = 10000;
438: volatile int t;
439: u_int a;
440:
441: iem->im_iscp.iscp_busy = 1;
442: /* reset chip */
443: a = IE_PORT_RESET;
444: ier->ie_porthigh = a & 0xffff;
445: t = 0;
446: t = 1;
447: ier->ie_portlow = a >> 16;
448: for (t = timo; t--;)
449: ;
450:
451: /* reset chip again */
452: a = IE_PORT_RESET;
453: ier->ie_porthigh = a & 0xffff;
454: t = 0;
455: t = 1;
456: ier->ie_portlow = a >> 16;
457: for (t = timo; t--;)
458: ;
459:
460: /*printf("status %x busy %x\n", iem->im_scb.ie_status,
461: iem->im_iscp.iscp_busy);*/
462: }
463:
464: void
465: ie_end(struct netif *nif)
466: {
467: if (ie_debug)
468: printf("ie%d: ie_end called\n", nif->nif_unit);
469:
470: ie_stop(nif);
471:
472: /* *(u_char *) 0xfff42002 = 0; */
473: }
CVSweb