|
|
1.1 root 1: #include "../chunix/chsys.h"
2: #include "../chunix/chconf.h"
3: #include "../chaos/chaos.h"
4: /*
5: * Chaos device driver for the ch11 (CHAOS-11) broadcast network
6: * interface.
7: */
8: struct chxcvr ch11xcvr[NCHCH];
9: #define xc_chrtries xc_info.xc_ch11.ch_rtries
10: int chchstart(), chchreset();
11:
12: #ifdef VMUNIX
13: #include "../h/buf.h"
14: #include "../h/ubavar.h"
15: int chchndev;
16: /*
17: * Autoconfiguration support for VMUNIX
18: */
19: int chchprobe(), chchattach(), chchintr();
20: struct uba_device *chchdinfo[NCHCH];
21: unsigned short chchstd[] = { 0164140, 0165140, 0166140 };
22: struct uba_driver chchdriver =
23: { chchprobe, 0, chchattach, 0, chchstd, "chch", chchdinfo };
24:
25: chchprobe(reg)
26: caddr_t reg;
27: {
28: register int br, cvec;
29:
30: #ifdef lint
31: br = 0; cvec = br; br = cvec;
32: #endif
33: ((struct ch11 *)reg)->ch_csr = CHTCLR;
34: ((struct ch11 *)reg)->ch_csr = CHTIEN;
35: DELAY(10000);
36: ((struct ch11 *)reg)->ch_csr = 0;
37: return (1);
38: }
39:
40: /*ARGSUSED*/
41: chchattach(ui)
42: register struct uba_device *ui;
43: {
44:
45: if (++chchndev > NCHCH)
46: panic("too many ch11's");
47: chchsetup(&ch11xcvr[chchndev - 1], (struct ch11 *)ui->ui_addr);
48: }
49: #else VMUNIX
50: int chchndev = NCHCH;
51: int chchaddr[NCHCH] = { CHCH_ADDR };
52: #endif VMUNIX
53: /*
54: * Do the run-time initialization of the given transceiver.
55: */
56: chchsetup(xp, cp)
57: register struct chxcvr *xp;
58: register struct ch11 *cp;
59: {
60: xp->xc_devaddr = (unsigned *)cp;
61: xp->xc_addr = cp->ch_myaddr;
62: xp->xc_start = chchstart;
63: xp->xc_reset = chchreset;
64: printf("CHAOS cable: subnet: %o, host: %o, (%o)\n",
65: xp->xc_subnet, xp->xc_host, xp->xc_addr);
66: if (xp->xc_subnet >= CHNSUBNET)
67: panic("bad ch11 address");
68: }
69:
70: /*
71: * chaos11 initialization. Also does initialization to the static xcvr
72: * structure since initialized unions don't work anyway.
73: */
74: chchinit()
75: {
76: register struct chxcvr *xp;
77: register int i;
78:
79: for (i = 0, xp = &ch11xcvr[0]; xp < &ch11xcvr[chchndev]; xp++, i++) {
80: #ifndef VMUNIX
81: chchsetup(xp, (struct ch11 *)chchaddr[i]);
82: #endif not VMUNIX
83: chchreset(xp);
84: }
85: }
86: /*
87: * Reset things from an unknown state
88: */
89: chchreset(xp)
90: register struct chxcvr *xp;
91: {
92: register struct ch11 *cp = (struct ch11 *)xp->xc_devaddr;
93: register struct chroute *r;
94:
95: if (cp == 0)
96: return;
97: r = &Chroutetab[xp->xc_subnet];
98: r->rt_type = CHDIRECT;
99: r->rt_cost = CHHCOST/2;
100: r->rt_xcvr = xp;
101: cp->ch_csr = CHRST | CHRIEN | CHREN | CHTIEN;
102: }
103:
104: /*
105: * Start output on an idle line
106: */
107: chchstart(xp)
108: register struct chxcvr *xp;
109: {
110: if (xp->xc_tpkt != NOPKT)
111: panic("chchstart: already busy");
112: chchtint(xp);
113: }
114:
115: /*
116: * Receiver interrupt
117: */
118: chchrint(xcvr)
119: struct chxcvr *xcvr;
120: {
121: register nshorts;
122: register struct ch11 *cp;
123: register short *p;
124: register struct chxcvr *xp = xcvr; /* needed so xp is last reg */
125:
126: cp = (struct ch11 *)xp->xc_devaddr;
127: nshorts = (((cp->ch_rbc & 07777) + 1) >> 4) - 3;
128: if ((cp->ch_rbc & 017) != 017 || nshorts < 8)
129: xp->xc_leng++; /* bit count not multiple of 16 */
130: else if (cp->ch_csr & CHCRC)
131: xp->xc_crcr++; /* crc error during reception */
132: else if ((xp->xc_rpkt = hpkalloc(nshorts)) == NOPKT)
133: xp->xc_rej++; /* can't allocate a packet */
134: else {
135: p = (short *)&xp->xc_rpkt->pk_phead;
136: do {
137: *p++ = cp->ch_rbf;
138: } while (--nshorts);
139: nshorts = cp->ch_rbf;
140: nshorts = cp->ch_rbf;
141: nshorts = cp->ch_rbf;
142: if (cp->ch_csr & CHCRC) {
143: xp->xc_crci++; /* crc error during readout */
144: ch_free((char *)xp->xc_rpkt);
145: } else {
146: register struct chroute *r;
147:
148: LOCK;
149: r = &Chroutetab[xp->xc_subnet];
150: r->rt_type = CHDIRECT;
151: r->rt_cost = CHCCOST;
152: r->rt_xcvr = xp;
153: xp->xc_rcvd++;
154: rcvpkt((struct packet *)xp->xc_rpkt);
155: }
156: }
157: xp->xc_lost += (cp->ch_csr >> CHLCPOS) & CHLCMASK;
158: cp->ch_csr |= CHREN | CHRIEN; /* CHRIEN is "not really needed" */
159: }
160: /*
161: * Transmit interrupt
162: */
163: chchtint(xcvr)
164: struct chxcvr *xcvr;
165: {
166: register struct ch11 *cp;
167: register struct packet *pkt; /* shouldn't be reg on pdp11 */
168:
169: {
170: register struct chxcvr *xp = xcvr;
171:
172: LOCK;
173: cp = (struct ch11 *)xp->xc_devaddr;
174: cp->ch_csr &= ~CHTIEN;
175: if ((pkt = xp->xc_tpkt) != NOPKT) { /* if a real interrupt */
176: if (cp->ch_csr & CHABRT) { /* should retry here first */
177: xp->xc_abrt++;
178: if (++xp->xc_chrtries < 5)
179: goto retry;
180: } else
181: xp->xc_xmtd++;
182: xmitdone(pkt);
183: xp->xc_chrtries = 0;
184: }
185: if ((pkt = xmitnext(xp)) == NOPKT)
186: return;
187: retry: ;
188: }{
189: register int nshorts;
190: register short *p;
191:
192: nshorts = (sizeof(struct pkt_header) + pkt->pk_len + sizeof(short)-1)
193: /* / sizeof(short) */ >> 1;
194: debug(DTRANS,printf("Trans size=%d, %x\n", nshorts, pkt));
195: cp->ch_csr |= CHTCLR;
196: p = (short *)&pkt->pk_phead;
197: do {
198: cp->ch_wbf = *p++;
199: } while (--nshorts);
200: }{
201: register struct chroute *r;
202:
203: r = &Chroutetab[pkt->pk_dsubnet];
204: if (r->rt_type != CHDIRECT)
205: cp->ch_wbf = r->rt_addr;
206: else
207: cp->ch_wbf = pkt->pk_daddr; /* where to send it */
208: r = (struct chroute *)cp->ch_xmt; /* start transmission */
209: cp->ch_csr |= CHTIEN;
210: }
211: }
212: /*
213: * CHAOS-11 interrupt
214: * call chchrint and/or chchtint
215: */
216: chchintr(dev)
217: {
218: register struct chxcvr *xp = &ch11xcvr[dev];
219: register struct ch11 *cp = (struct ch11 *)xp->xc_devaddr;
220:
221: if (cp->ch_csr & (CHTDN | CHRDN)) {
222: if (cp->ch_csr & CHRDN)
223: if (cp->ch_csr & CHRIEN)
224: chchrint(xp);
225: if (cp->ch_csr & CHTDN)
226: if (cp->ch_csr & CHTIEN)
227: chchtint(xp);
228: } else
229: debug(DTRANS, printf("spurious CHAOS11 interrupt\n"));
230: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.