|
|
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.