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