|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * Parallel port network driver v1.1 ! 28: * All rights reserved. ! 29: */ ! 30: ! 31: /* ! 32: Subject: parallel network interface ! 33: ! 34: The printer network driver has the following hardware requirements for the ! 35: interconnection cable: ! 36: ! 37: Connections: ! 38: Side1 Side2 Function Side1 / Side2 ! 39: Pin 5 Pin 10 Interrupt strobe: send status (w)/send status (r) ! 40: Pin 2 Pin 15 Data bits : write / read ! 41: Pin 3 Pin 13 Data bits : write / read ! 42: Pin 4 Pin 12 Data bits : write / read ! 43: Pin 6 Pin 11 Data bits : write / read ! 44: Pin 10 Pin 5 ! 45: Pin 11 Pin 6 ! 46: Pin 12 Pin 4 ! 47: Pin 13 Pin 3 ! 48: Pin 15 Pin 2 ! 49: Pins 18-25 Pins 18-25 (ground interconnections) ! 50: ! 51: The cable is "symmetric" in that either side can be plugged into either of the ! 52: computers. ! 53: ! 54: The hardware requirements are as follows: ! 55: Port 0x378 must be writable with the following specifications: ! 56: Bit 4 -> pin 6 ! 57: Bit 3 -> pin 5 ! 58: Bit 2 -> pin 4 ! 59: Bit 1 -> pin 3 ! 60: Bit 0 -> pin 2 ! 61: Port 0x379 must be readable with the following specifications: ! 62: Bit 7 <- pin 11 ! 63: Bit 6 <- pin 10 ! 64: Bit 5 <- pin 12 ! 65: Bit 4 <- pin 13 ! 66: Bit 3 <- pin 15 ! 67: Port 0x37a must be readable and writable with the following specifications: ! 68: Bit 4 -> interrupt enable ! 69: So Port 0x378 connects to Port 0x379 as ! 70: Bit 3 -> pin 5 : pin 10 -> Bit 6 0x08 -> 0x40 ! 71: ! 72: Bit 4 -> pin 6 : pin 11 -> Bit 7 0x08<<1 -> ~ 0x80 ! 73: Bit 2 -> pin 4 : pin 12 -> Bit 5 0x07 -> 0x38 ! 74: Bit 1 -> pin 3 : pin 13 -> Bit 4 0x07 -> 0x38 ! 75: Bit 0 -> pin 2 : pin 15 -> Bit 3 0x07 -> 0x38 ! 76: [note: bit 0 is considered the least significant bit, pins on the connector ! 77: are numbered starting with 1, -> represents sending data out on the bus, <- ! 78: represents reading data from the bus] ! 79: ! 80: Pins 1,7,8,9, and 16 are currently unused, and may be allowed to "float". ! 81: ! 82: The data is sent in 4 bit "nybbles", with the highest 4 bits being sent first. ! 83: ! 84: To bring up the interface, all that should be required is ! 85: ifconfig par0 <your ip address> <connected machine's ip address> up ! 86: and to bring down the interface ! 87: ifconfig par0 down ! 88: You may get a warning message (such as printer out of paper) once you down ! 89: the interface, as the port is monitored for both printer and network activity ! 90: depending on whether par0 is up or down, and when you down the interface the ! 91: printer driver will then read whatever is on the port (which will be the last ! 92: message from the other computer). ! 93: */ ! 94: ! 95: #include <par.h> ! 96: #if NPAR > 0 ! 97: ! 98: #include <kern/time_out.h> ! 99: #include <device/device_types.h> ! 100: #include <device/errno.h> ! 101: #include <device/io_req.h> ! 102: #include <device/if_hdr.h> ! 103: #include <device/if_ether.h> ! 104: #include <device/net_status.h> ! 105: #include <device/net_io.h> ! 106: ! 107: #include <i386/ipl.h> ! 108: #include <i386/pio.h> ! 109: #include <chips/busses.h> ! 110: #include <i386at/if_par.h> ! 111: ! 112: ! 113: int parintr(); ! 114: int parioctl(); ! 115: int parattach(); ! 116: int paroutput(); ! 117: ! 118: int (*oldvect)(); ! 119: int oldunit; ! 120: ! 121: extern struct bus_device *lprinfo[]; ! 122: ! 123: int par_watch = 0; ! 124: ! 125: struct par_softc { ! 126: struct ifnet ds_if; ! 127: u_char ds_addr[6]; /* Ethernet hardware address */ ! 128: u_char address[6]; ! 129: char sc_buf[PARMTU+sizeof(struct ifnet *)]; ! 130: } par_softc[NPAR]; ! 131: ! 132: void parintoff(unit) ! 133: int unit; ! 134: { ! 135: struct bus_device *lpdev = lprinfo[unit]; ! 136: ! 137: outb(INTR(lpdev->address), 0x07); ! 138: par_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; ! 139: ivect[lpdev->sysdep1] = oldvect; ! 140: iunit[lpdev->sysdep1] = oldunit; ! 141: } ! 142: ! 143: void parinit(unit) ! 144: int unit; ! 145: { ! 146: struct bus_device *lpdev = lprinfo[unit]; ! 147: ! 148: if (ivect[lpdev->sysdep1] != parintr) { ! 149: oldvect = ivect[lpdev->sysdep1]; ! 150: oldunit = iunit[lpdev->sysdep1]; ! 151: ivect[lpdev->sysdep1] = parintr; ! 152: iunit[lpdev->sysdep1] = unit; ! 153: } ! 154: outb(INTR(lpdev->address),0x11); ! 155: par_softc[unit].ds_if.if_flags |= IFF_RUNNING; ! 156: *(struct ifnet **)par_softc[unit].sc_buf = &par_softc[unit].ds_if; ! 157: } ! 158: ! 159: struct ether_header par_eh; ! 160: ! 161: int parattach(dev) ! 162: struct bus_device *dev; ! 163: { ! 164: u_char unit = (u_char)dev->unit; ! 165: struct ifnet *ifp; ! 166: struct par_softc*sp; ! 167: ! 168: if ((unit < 0) || (unit >= NPAR)) ! 169: return(0); ! 170: printf("\n par%d: at lpr%d, port = %x, spl = %d, pic = %d. ", ! 171: unit, unit, dev->address, dev->sysdep, dev->sysdep1); ! 172: ! 173: sp = &par_softc[unit]; ! 174: ifp = &(sp->ds_if); ! 175: ! 176: *(sp->ds_addr) = *(sp->address) = 0x11; ! 177: *(sp->ds_addr + 1) = *(sp->address + 1) = 0x22; ! 178: *(sp->ds_addr + 2) = *(sp->address + 2) = 0x33; ! 179: *(sp->ds_addr + 3) = *(sp->address + 3) = 0x44; ! 180: *(sp->ds_addr + 4) = *(sp->address + 4) = 0x55; ! 181: *(sp->ds_addr + 5) = *(sp->address + 5) = 0x66; ! 182: ! 183: par_eh.ether_dhost[5] = par_eh.ether_shost[0] = 0x11; ! 184: par_eh.ether_dhost[4] = par_eh.ether_shost[1] = 0x22; ! 185: par_eh.ether_dhost[3] = par_eh.ether_shost[2] = 0x33; ! 186: par_eh.ether_dhost[2] = par_eh.ether_shost[3] = 0x44; ! 187: par_eh.ether_dhost[1] = par_eh.ether_shost[4] = 0x55; ! 188: par_eh.ether_dhost[0] = par_eh.ether_shost[5] = 0x66; ! 189: par_eh.ether_type = htons(0x0800); ! 190: ! 191: printf("ethernet id [%x:%x:%x:%x:%x:%x]", ! 192: sp->address[0],sp->address[1],sp->address[2], ! 193: sp->address[3],sp->address[4],sp->address[5]); ! 194: ! 195: ifp->if_unit = unit; ! 196: ifp->if_mtu = ETHERMTU; ! 197: ifp->if_flags = IFF_POINTOPOINT; ! 198: ifp->if_header_size = sizeof(struct ether_header); ! 199: ifp->if_header_format = HDR_ETHERNET; ! 200: ifp->if_address_size = 6; ! 201: ifp->if_address = (char *)&par_softc[unit].address[0]; ! 202: if_init_queues(ifp); ! 203: return(0); ! 204: } ! 205: ! 206: int parstart(); /* forward */ ! 207: ! 208: /*ARGSUSED*/ ! 209: paropen(dev, flag) ! 210: dev_t dev; ! 211: int flag; ! 212: { ! 213: register int unit = minor(dev); ! 214: ! 215: if (unit < 0 || unit >= NPAR) ! 216: return (ENXIO); ! 217: ! 218: par_softc[unit].ds_if.if_flags |= IFF_UP; ! 219: parinit(unit); ! 220: return(0); ! 221: } ! 222: ! 223: paroutput(dev, ior) ! 224: dev_t dev; ! 225: io_req_t ior; ! 226: { ! 227: register int unit = minor(dev); ! 228: ! 229: if (unit < 0 || unit >= NPAR) ! 230: return (ENXIO); ! 231: return (net_write(&par_softc[unit].ds_if, parstart, ior)); ! 232: } ! 233: ! 234: parsetinput(dev, receive_port, priority, filter, filter_count) ! 235: dev_t dev; ! 236: mach_port_t receive_port; ! 237: int priority; ! 238: filter_t filter[]; ! 239: unsigned int filter_count; ! 240: { ! 241: register int unit = minor(dev); ! 242: ! 243: if (unit < 0 || unit >= NPAR) ! 244: return (ENXIO); ! 245: ! 246: return (net_set_filter(&par_softc[unit].ds_if, ! 247: receive_port, priority, ! 248: filter, filter_count)); ! 249: } ! 250: ! 251: int parstart(unit) ! 252: { ! 253: struct ifnet *ifp = &(par_softc[unit].ds_if); ! 254: u_short addr = lprinfo[unit]->address; ! 255: struct sockaddr *dst; ! 256: int len, i; ! 257: spl_t s; ! 258: u_char *mcp, c; ! 259: io_req_t m; ! 260: ! 261: if (!(ifp->if_flags & IFF_RUNNING)) { ! 262: #ifdef WHY ! 263: m_free(m); ! 264: parintoff(unit); ! 265: return(ENETDOWN); ! 266: #else WHY ! 267: parintoff(unit); ! 268: return(-1); ! 269: #endif WHY ! 270: } ! 271: s = SPLNET(); ! 272: ! 273: IF_DEQUEUE(&ifp->if_snd, m); ! 274: if (m == 0) { ! 275: splx(s); ! 276: return 0; ! 277: } ! 278: len = m->io_count; ! 279: if (par_watch) ! 280: printf("O%d\n",len); ! 281: len -= 14 /* XXX */; ! 282: mcp = (u_char *)m->io_data + 14 /* XXX */; ! 283: while (len--) { ! 284: c=*mcp++; ! 285: outb(OUTPUT(addr),((c&0x80)>>3) | ((c&0x70)>>4) | 0x08); ! 286: i=MAXSPIN; ! 287: while (!(inb(INPUT(addr))&0x40) && --i); ! 288: outb(OUTPUT(addr),((c&0x08)<<1) | (c&0x07)); ! 289: i=MAXSPIN; ! 290: while ((inb(INPUT(addr))&0x40) && --i); ! 291: } ! 292: outb(OUTPUT(addr),(((c&0x08)<<1) | (c&0x07))^0x17); ! 293: iodone(m); ! 294: splx(s); ! 295: return (0); ! 296: } ! 297: ! 298: /*ARGSUSED*/ ! 299: pargetstat(dev, flavor, status, count) ! 300: dev_t dev; ! 301: int flavor; ! 302: dev_status_t status; /* pointer to OUT array */ ! 303: unsigned int *count; /* out */ ! 304: { ! 305: register int unit = minor(dev); ! 306: ! 307: if (unit < 0 || unit >= NPAR) ! 308: return (ENXIO); ! 309: ! 310: ! 311: switch (flavor) { ! 312: case NET_DSTADDR: ! 313: return (D_SUCCESS); ! 314: break; ! 315: } ! 316: ! 317: return (net_getstat(&par_softc[unit].ds_if, ! 318: flavor, ! 319: status, ! 320: count)); ! 321: } ! 322: ! 323: parsetstat(dev, flavor, status, count) ! 324: dev_t dev; ! 325: int flavor; ! 326: dev_status_t status; ! 327: unsigned int count; ! 328: { ! 329: register int unit = minor(dev); ! 330: register struct par_softc *sp; ! 331: ! 332: if (unit < 0 || unit >= NPAR) ! 333: return (ENXIO); ! 334: ! 335: sp = &par_softc[unit]; ! 336: ! 337: switch (flavor) { ! 338: case NET_STATUS: ! 339: { ! 340: /* ! 341: * All we can change are flags, and not many of those. ! 342: */ ! 343: register struct net_status *ns = (struct net_status *)status; ! 344: int mode = 0; ! 345: ! 346: if (count < NET_STATUS_COUNT) ! 347: return (D_INVALID_SIZE); ! 348: ! 349: #if 0 ! 350: /* ha ha ha */ ! 351: if (ns->flags & IFF_ALLMULTI) ! 352: mode |= MOD_ENAL; ! 353: if (ns->flags & IFF_PROMISC) ! 354: mode |= MOD_PROM; ! 355: /* ! 356: * Force a complete reset if the receive mode changes ! 357: * so that these take effect immediately. ! 358: */ ! 359: if (sp->mode != mode) { ! 360: sp->mode = mode; ! 361: if (sp->flags & DSF_RUNNING) { ! 362: sp->flags &= ~(DSF_LOCK | DSF_RUNNING); ! 363: parinit(unit); ! 364: } ! 365: } ! 366: #endif ! 367: break; ! 368: } ! 369: case NET_ADDRESS: ! 370: { ! 371: register union ether_cvt { ! 372: char addr[6]; ! 373: int lwd[2]; ! 374: } *ec = (union ether_cvt *)status; ! 375: ! 376: if (count < sizeof(*ec)/sizeof(int)) ! 377: return (D_INVALID_SIZE); ! 378: ! 379: ec->lwd[0] = ntohl(ec->lwd[0]); ! 380: ec->lwd[1] = ntohl(ec->lwd[1]); ! 381: /* at3c501seteh(sp->base, ec->addr);*/ ! 382: break; ! 383: } ! 384: ! 385: default: ! 386: return (D_INVALID_OPERATION); ! 387: } ! 388: return (D_SUCCESS); ! 389: } ! 390: ! 391: int parintr(unit) ! 392: int unit; ! 393: { ! 394: register struct par_softc *sp = &par_softc[unit]; ! 395: u_short addr = lprinfo[unit]->address; ! 396: char *trav = sp->sc_buf; ! 397: short len = 0; ! 398: u_char c, c2; ! 399: int i; ! 400: ipc_kmsg_t new_kmsg; ! 401: struct ether_header *ehp; ! 402: struct packet_header *pkt; ! 403: struct ifnet *ifp = &(sp->ds_if); ! 404: ! 405: do { ! 406: c2=inb(INPUT(addr)); ! 407: outb(OUTPUT(addr),0x08); ! 408: i=MAXSPIN; ! 409: while(((c=inb(INPUT(addr)))&0x40) && --i); ! 410: ! 411: c = inb(INPUT(addr)); ! 412: outb(OUTPUT(addr),0x00); ! 413: if (!i) ! 414: break; ! 415: ! 416: if (++len > ETHERMTU) { ! 417: trav = sp->sc_buf; ! 418: len = 0; ! 419: continue; ! 420: } ! 421: *trav++ = ((~c2)&0x80) | ((c2&0x38)<<1) | (((~c)&0x80)>>4) | ((c&0x38)>>3); ! 422: i=MAXSPIN; ! 423: while (!((c2=inb(INPUT(addr)))&0x40) && --i) ! 424: if (((c2^0xb8)&0xf8) == (c&0xf8)) ! 425: goto end; ! 426: } while (i); ! 427: end: ! 428: if (len < 20) /* line noise ? */ ! 429: return; ! 430: if (par_watch) ! 431: printf("I%d\n",len); ! 432: ! 433: new_kmsg = net_kmsg_get(); ! 434: if (new_kmsg == IKM_NULL) { ! 435: /* ! 436: * Drop the packet. ! 437: */ ! 438: sp->ds_if.if_rcvdrops++; ! 439: return; ! 440: } ! 441: ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]); ! 442: pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]); ! 443: *ehp = par_eh; ! 444: ! 445: bcopy (sp->sc_buf, (char *) (pkt + 1), len); ! 446: ! 447: pkt->type = ehp->ether_type; ! 448: pkt->length = len + sizeof(struct packet_header); ! 449: /* ! 450: * Hand the packet to the network module. ! 451: */ ! 452: net_packet(ifp, new_kmsg, pkt->length, ! 453: ethernet_priority(new_kmsg)); ! 454: return(0); ! 455: } ! 456: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.