Annotation of sys/arch/mvme68k/stand/netboot/if_ie.c, Revision 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