Annotation of sys/arch/vax/vax/ctu.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ctu.c,v 1.10 2007/06/06 17:15:13 deraadt Exp $ */
2: /* $NetBSD: ctu.c,v 1.10 2000/03/23 06:46:44 thorpej Exp $ */
3: /*
4: * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed at Ludd, University of
18: * Lule}, Sweden and its contributors.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Device driver for 11/750 Console TU58.
36: *
37: * Error checking is almost nonexistent, the driver should be
38: * fixed to at least calculate checksum on incoming packets.
39: * Writing of tapes does not work, by some unknown reason so far.
40: * It is almost useless to try to use this driver when running
41: * multiuser, because the serial device don't have any buffers
42: * so we will lose interrupts.
43: */
44:
45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/callout.h>
48: #include <sys/kernel.h>
49: #include <sys/buf.h>
50: #include <sys/fcntl.h>
51: #include <sys/malloc.h>
52: #include <sys/ioctl.h>
53: #include <sys/device.h>
54: #include <sys/proc.h>
55: #include <sys/disklabel.h> /* For disklabel prototype */
56:
57: #include <machine/mtpr.h>
58: #include <machine/rsp.h>
59: #include <machine/scb.h>
60: #include <machine/trap.h>
61:
62: enum tu_state {
63: SC_UNUSED,
64: SC_INIT,
65: SC_READY,
66: SC_SEND_CMD,
67: SC_GET_RESP,
68: SC_GET_WCONT,
69: SC_GET_END,
70: SC_RESTART,
71: };
72:
73: struct tu_softc {
74: enum tu_state sc_state;
75: int sc_error;
76: char sc_rsp[15]; /* Should be struct rsb; but don't work */
77: u_char *sc_xfptr; /* Current char to xfer */
78: u_char *sc_blk; /* Base of current 128b block */
79: int sc_tpblk; /* Start block number */
80: int sc_nbytes; /* Number of bytes to xfer */
81: int sc_xbytes; /* Number of xfer'd bytes */
82: int sc_bbytes; /* Number of xfer'd bytes this block */
83: int sc_op; /* Read/write */
84: int sc_xmtok; /* set if OK to xmit */
85: struct buf_queue sc_q; /* pending I/O requests */
86: } tu_sc;
87:
88: struct ivec_dsp tu_recv, tu_xmit;
89:
90: void ctutintr(void *);
91: void cturintr(void *);
92: void ctuattach(void);
93: void ctustart(struct buf *);
94: void ctuwatch(void *);
95: short ctu_cksum(unsigned short *, int);
96:
97: int ctuopen(dev_t, int, int, struct proc *);
98: int ctuclose(dev_t, int, int, struct proc *);
99: void ctustrategy(struct buf *);
100: int ctuioctl(dev_t, u_long, caddr_t, int, struct proc *);
101: int ctudump(dev_t, daddr64_t, caddr_t, size_t);
102:
103: static struct callout ctu_watch_ch = CALLOUT_INITIALIZER;
104:
105: void
106: ctuattach()
107: {
108: BUFQ_INIT(&tu_sc.sc_q);
109:
110: tu_recv = idsptch;
111: tu_recv.hoppaddr = cturintr;
112: scb->scb_csrint = (void *)&tu_recv;
113:
114: tu_xmit = idsptch;
115: tu_xmit.hoppaddr = ctutintr;
116: scb->scb_cstint = (void *)&tu_xmit;
117: }
118:
119: int
120: ctuopen(dev, oflags, devtype, p)
121: dev_t dev;
122: int oflags, devtype;
123: struct proc *p;
124: {
125: int unit, error;
126:
127: unit = minor(dev);
128:
129: if (unit)
130: return ENXIO;
131:
132: if (tu_sc.sc_state != SC_UNUSED)
133: return EBUSY;
134:
135: tu_sc.sc_error = 0;
136: mtpr(0100, PR_CSRS); /* Enable receive interrupt */
137: callout_reset(&ctu_watch_ch, hz, ctuwatch, NULL);
138:
139: tu_sc.sc_state = SC_INIT;
140:
141: mtpr(RSP_TYP_INIT, PR_CSTD);
142:
143: if ((error = tsleep((caddr_t)&tu_sc, (PZERO + 10)|PCATCH,
144: "ctuopen", 0)))
145: return (error);
146:
147: if (tu_sc.sc_error)
148: return tu_sc.sc_error;
149:
150: tu_sc.sc_state = SC_READY;
151: tu_sc.sc_xmtok = 1;
152:
153: mtpr(0100, PR_CSTS);
154: return 0;
155:
156: }
157:
158: int
159: ctuclose(dev, oflags, devtype, p)
160: dev_t dev;
161: int oflags, devtype;
162: struct proc *p;
163: {
164: mtpr(0, PR_CSRS);
165: mtpr(0, PR_CSTS);
166: tu_sc.sc_state = SC_UNUSED;
167: callout_stop(&ctu_watch_ch);
168: return 0;
169: }
170:
171: void
172: ctustrategy(bp)
173: struct buf *bp;
174: {
175: int s;
176:
177: #ifdef TUDEBUG
178: printf("addr %x, block %x, nblock %x, read %x\n",
179: bp->b_data, bp->b_blkno, bp->b_bcount,
180: bp->b_flags & B_READ);
181: #endif
182:
183: if (bp->b_blkno >= 512) {
184: s = splbio();
185: biodone(bp);
186: splx(s);
187: return;
188: }
189: bp->b_rawblkno = bp->b_blkno;
190: s = splbio();
191: disksort_blkno(&tu_sc.sc_q, bp); /* Why not use disksort? */
192: if (tu_sc.sc_state == SC_READY)
193: ctustart(bp);
194: splx(s);
195: }
196:
197: void
198: ctustart(bp)
199: struct buf *bp;
200: {
201: struct rsp *rsp = (struct rsp *)tu_sc.sc_rsp;
202:
203:
204: tu_sc.sc_xfptr = tu_sc.sc_blk = bp->b_data;
205: tu_sc.sc_tpblk = bp->b_blkno;
206: tu_sc.sc_nbytes = bp->b_bcount;
207: tu_sc.sc_xbytes = tu_sc.sc_bbytes = 0;
208: tu_sc.sc_op = bp->b_flags & B_READ ? RSP_OP_READ : RSP_OP_WRITE;
209:
210: rsp->rsp_typ = RSP_TYP_COMMAND;
211: rsp->rsp_sz = 012;
212: rsp->rsp_op = tu_sc.sc_op;
213: rsp->rsp_mod = 0;
214: rsp->rsp_drv = 0;
215: rsp->rsp_sw = rsp->rsp_xx1 = rsp->rsp_xx2 = 0;
216: rsp->rsp_cnt = tu_sc.sc_nbytes;
217: rsp->rsp_blk = tu_sc.sc_tpblk;
218: rsp->rsp_sum = ctu_cksum((unsigned short *)rsp, 6);
219: tu_sc.sc_state = SC_SEND_CMD;
220: if (tu_sc.sc_xmtok) {
221: tu_sc.sc_xmtok = 0;
222: ctutintr(NULL);
223: }
224: }
225:
226: int
227: ctuioctl(dev, cmd, data, fflag, p)
228: dev_t dev;
229: u_long cmd;
230: caddr_t data;
231: int fflag;
232: struct proc *p;
233: {
234: return 0;
235: }
236:
237: /*
238: * Not bloody likely...
239: */
240: int
241: ctudump(dev, blkno, va, size)
242: dev_t dev;
243: daddr64_t blkno;
244: caddr_t va;
245: size_t size;
246: {
247: return 0;
248: }
249:
250: void
251: cturintr(arg)
252: void *arg;
253: {
254: int status = mfpr(PR_CSRD);
255: struct buf *bp;
256:
257: bp = BUFQ_FIRST(&tu_sc.sc_q);
258: switch (tu_sc.sc_state) {
259:
260: case SC_UNUSED:
261: printf("stray console storage interrupt, got %o\n", status);
262: break;
263:
264: case SC_INIT:
265: if (status != RSP_TYP_CONTINUE)
266: tu_sc.sc_error = EIO;
267: wakeup((void *)&tu_sc);
268: break;
269: case SC_GET_RESP:
270: tu_sc.sc_tpblk++;
271: if (tu_sc.sc_xbytes == tu_sc.sc_nbytes) {
272: tu_sc.sc_bbytes++;
273: if (tu_sc.sc_bbytes == 146) { /* We're finished! */
274: #ifdef TUDEBUG
275: printf("Xfer ok\n");
276: #endif
277: BUFQ_REMOVE(&tu_sc.sc_q, bp);
278: biodone(bp);
279: tu_sc.sc_xmtok = 1;
280: tu_sc.sc_state = SC_READY;
281: if (BUFQ_FIRST(&tu_sc.sc_q) != NULL)
282: ctustart(BUFQ_FIRST(&tu_sc.sc_q));
283: }
284: break;
285: }
286: tu_sc.sc_bbytes++;
287: if (tu_sc.sc_bbytes < 3) /* Data header */
288: break;
289: if (tu_sc.sc_bbytes == 132) { /* Finished */
290: tu_sc.sc_bbytes = 0;
291: break;
292: }
293: if (tu_sc.sc_bbytes == 131) /* First checksum */
294: break;
295: tu_sc.sc_xfptr[tu_sc.sc_xbytes++] = status;
296: break;
297:
298: case SC_GET_WCONT:
299: if (status != 020)
300: printf("SC_GET_WCONT: status %o\n", status);
301: else
302: ctutintr(NULL);
303: tu_sc.sc_xmtok = 0;
304: break;
305:
306: case SC_RESTART:
307: ctustart(BUFQ_FIRST(&tu_sc.sc_q));
308: break;
309:
310: default:
311: if (status == 4) { /* Protocol error, or something */
312: tu_sc.sc_state = SC_RESTART;
313: mtpr(RSP_TYP_INIT, PR_CSTD);
314: return;
315: }
316: printf("Unknown receive ctuintr state %d, pack %o\n",
317: tu_sc.sc_state, status);
318: }
319:
320: }
321:
322: void
323: ctutintr(arg)
324: void *arg;
325: {
326: int c;
327:
328: if (tu_sc.sc_xmtok)
329: return;
330:
331: switch (tu_sc.sc_state) {
332: case SC_SEND_CMD:
333: c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff;
334: mtpr(c, PR_CSTD);
335: if (tu_sc.sc_xbytes > 13) {
336: tu_sc.sc_state = (tu_sc.sc_op == RSP_OP_READ ?
337: SC_GET_RESP : SC_GET_WCONT);
338: tu_sc.sc_xbytes = 0;
339: tu_sc.sc_xmtok++;
340: }
341: break;
342:
343: case SC_GET_WCONT:
344: switch (tu_sc.sc_bbytes) {
345: case 0:
346: mtpr(1, PR_CSTD); /* This is a data packet */
347: break;
348:
349: case 1:
350: mtpr(128, PR_CSTD); /* # of bytes to send */
351: break;
352:
353: case 130:
354: mtpr(0, PR_CSTD); /* First checksum */
355: break;
356:
357: case 131:
358: mtpr(0, PR_CSTD); /* Second checksum */
359: break;
360:
361: case 132: /* Nothing to send... */
362: tu_sc.sc_bbytes = -1;
363: if (tu_sc.sc_xbytes == tu_sc.sc_nbytes + 1)
364: tu_sc.sc_op = SC_GET_END;
365: break;
366: default:
367: c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff;
368: mtpr(c, PR_CSTD);
369: break;
370: }
371: tu_sc.sc_bbytes++;
372: break;
373:
374: default:
375: printf("Unknown xmit ctuintr state %d\n",tu_sc.sc_state);
376: }
377: }
378:
379: short
380: ctu_cksum(buf, words)
381: unsigned short *buf;
382: int words;
383: {
384: int i, cksum;
385:
386: for (i = cksum = 0; i < words; i++)
387: cksum += buf[i];
388:
389: hej: if (cksum > 65535) {
390: cksum = (cksum & 65535) + (cksum >> 16);
391: goto hej;
392: }
393: return cksum;
394: }
395:
396: int oldtp;
397:
398: /*
399: * Watch so that we don't get blocked unnecessary due to lost int's.
400: */
401: void
402: ctuwatch(arg)
403: void *arg;
404: {
405:
406: callout_reset(&ctu_watch_ch, hz, ctuwatch, NULL);
407:
408: if (tu_sc.sc_state == SC_GET_RESP && tu_sc.sc_tpblk != 0 &&
409: tu_sc.sc_tpblk == oldtp && (tu_sc.sc_tpblk % 128 != 0)) {
410: printf("tu0: lost recv interrupt\n");
411: ctustart(BUFQ_FIRST(&tu_sc.sc_q));
412: return;
413: }
414: if (tu_sc.sc_state == SC_RESTART)
415: mtpr(RSP_TYP_INIT, PR_CSTS);
416: oldtp = tu_sc.sc_tpblk;
417: }
CVSweb