|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/biaddr.h"
3: #include "sys/conf.h"
4: #include "sys/user.h"
5: #include "sys/buf.h"
6: #include "sys/pte.h"
7:
8: extern caddr_t bitest[];
9: extern struct biaddr bitstaddr[];
10: extern int bitstcnt;
11:
12: static bitstopen();
13: static bitstread(), bitstwrite();
14: struct cdevsw bitstcdev = cdinit(bitstopen, nulldev, bitstread, bitstwrite, nodev);
15:
16: char biscratch[4096];
17:
18: /*
19: * BVP data structures
20: */
21:
22: typedef struct quadque {
23: struct quadque *head, *tail;
24: } quadque;
25:
26: struct pqb {
27: quadque p_cmdq[4]; /* command queues */
28: quadque p_rspq; /* response queue */
29: short p_vector; /* interrupt vector, BR */
30: short p_nodmsk; /* interrupt node mask */
31: long p_nfreeq; /* number of free queues */
32: struct fqb *p_fqb; /* fqp virtual address */
33: char pp_junk0[156];
34: long p_bvplvl; /* BVP protocol version */
35: struct pqb *p_pqb; /* pqb virtual self-pointer */
36: struct bdt *p_bdt; /* bdt virtual address */
37: long p_bdtlen; /* and size */
38: struct pte *p_spt; /* system page table phys addr */
39: long p_sptlen; /* and size */
40: struct pte *p_gpt; /* global page pable phys addr */
41: long p_gptlen; /* and size */
42: long p_funcmask; /* ?? */
43: char pp_junk1[24];
44: /* stuff filled in by port after init */
45: short p_maxdg; /* max datagram size */
46: short p_maxmsg; /* max message size */
47: long p_ucodetype;
48: long p_ucodevers;
49: long p_hwtype;
50: long p_vers[3];
51: char p_qelogo[216]; /* `queue entry logout area' */
52: };
53:
54: /*
55: * free queue block
56: */
57: struct fqb {
58: long f_size; /* max size of things in this queue */
59: long f_junk; /* reserved, apparently */
60: quadque f_q; /* the free queue itself */
61: };
62:
63: #define NFREEQ 1
64:
65: /*
66: * buffer descriptor
67: */
68: struct bdt {
69: short b_flags;
70: short b_key;
71: long b_len; /* length of buffer */
72: struct pte *b_pte; /* relevant page table */
73: long b_sw; /* reserved for software */
74: };
75:
76: #define NBDT 1
77:
78: /*
79: * bundle of data for one port
80: * the pqb must be page-aligned;
81: * stick this in a buffer,
82: * which means it must all fit in one
83: */
84: struct bvpdata {
85: struct pqb p;
86: struct fqb f[NFREEQ];
87: struct bdt b[NBDT];
88: };
89:
90: /*
91: * port registers
92: */
93: struct regs {
94: long ctrl;
95: long stat;
96: long err;
97: long data;
98: };
99:
100: /*
101: * control bits
102: */
103: #define PCOWN 0x80 /* port own -- here is a command */
104: #define PCINIT 1
105: #define PCENAB 2
106: #define PCCMDQ 6 /* command queue not empty */
107: #define PCFREQ 7 /* free queue not empty */
108:
109: /*
110: * status bits
111: */
112: #define PSOWN 0x80000000 /* port own -- status valid */
113: #define PSSTD 0x20000000 /* self test done */
114: #define PSACC 0x10000000 /* adapter can communicate */
115: #define PSSTAT 0x70000 /* port state: */
116: #define SUNDEF 0x10000 /* undefined */
117: #define SINIT 0x20000 /* initialized */
118: #define SENAB 0x40000 /* enabled */
119: #define PSERR 0x40 /* error summary */
120:
121: /*
122: * to a header later
123: */
124: struct bvp {
125: struct bvpdata *d;
126: struct regs *r;
127: struct buf *dbuf;
128: };
129:
130: char *bitsnd, *bitrcv; /* places to put packets */
131:
132: struct bvp bvp;
133:
134: static
135: bitstopen(dev, flag)
136: int dev, flag;
137: {
138:
139: if (minor(dev)) {
140: u.u_error = ENXIO;
141: return;
142: }
143: if (bitest[0] == 0) { /* wrong */
144: if ((bitest[0] = biaddr(&bitstaddr[0])) == 0
145: || badaddr(bitest[0], sizeof(long))) {
146: printf("bitest absent\n");
147: u.u_error = ENXIO;
148: return;
149: }
150: bvp.r = (struct regs *)(bitest[0] + 0x204); /* cheat */
151: bitsnd = biscratch+7;
152: bitrcv = bitsnd + 2048;
153: bitsnd -= (long)bitsnd & 07; /* quad align */
154: bitrcv -= (long)bitrcv & 07;
155: }
156: if (bvpinit(&bvp) == 0) {
157: u.u_error = ENXIO;
158: return;
159: }
160: }
161:
162: /*
163: * read routine:
164: * nab a packet
165: */
166: static
167: bitstread(dev)
168: {
169: register struct bvpdata *b;
170:
171: b = bvp.d;
172: b->f[0].f_size = 2048;
173: if (insqti(bitrcv, &b->p.p_fqb[0].f_q))
174: bvpcomm(bvp.r, PCOWN|PCFREQ);
175: /* let someone else wait for now */
176: }
177:
178: /*
179: * write routine:
180: * send a packet
181: */
182: static
183: bitstwrite(dev)
184: {
185: register struct bvpdata *b;
186:
187: b = bvp.d;
188: if (insqti(bitsnd, &b->p.p_cmdq[0]))
189: bvpcomm(bvp.r, PCOWN|PCCMDQ);
190: }
191:
192: bvpinit(bv)
193: register struct bvp *bv;
194: {
195: register struct bvpdata *b;
196: register struct regs *r;
197:
198: if (bv->dbuf == NULL) {
199: bv->dbuf = geteblk();
200: if (bv->dbuf->b_bcount < sizeof(struct bvpdata)) {
201: printf("bcount too small\n");
202: brelse(bv->dbuf);
203: return (0);
204: }
205: clrbuf(bv->dbuf);
206: bv->d = (struct bvpdata *)bv->dbuf->b_un.b_addr;
207: }
208: r = bv->r;
209: if ((r->stat & PSSTAT) == SUNDEF) {
210: bvpdatinit(bv->d);
211: bvpcomm(r, physadr(&bv->d->p)|PCOWN|PCINIT);
212: bvpstat(r);
213: }
214: if ((r->stat & PSSTAT) == SINIT) {
215: bvpcomm(r, PCOWN|PCENAB);
216: bvpstat(r);
217: }
218: if ((r->stat & PSSTAT) != SENAB) {
219: printf("ps %x pe %x pd %x\n", r->stat, r->err, r->data);
220: return (0);
221: }
222: return (1);
223: }
224:
225: bvpdatinit(b)
226: register struct bvpdata *b;
227: {
228: /*
229: * just enough to make hardware happy
230: */
231: b->p.p_nfreeq = NFREEQ;
232: b->p.p_fqb = b->f;
233: b->p.p_bvplvl = 1;
234: b->p.p_pqb = &b->p;
235: b->p.p_bdt = b->b;
236: b->p.p_bdtlen = NBDT;
237: b->p.p_spt = (struct pte *)physadr(Sysmap);
238: b->p.p_sptlen = 0x100000; /* huge */
239: b->p.p_gpt = b->p.p_spt;
240: b->p.p_gptlen = b->p.p_sptlen;
241: }
242:
243: /*
244: * send a port command
245: * need a timeout
246: */
247: bvpcomm(r, c)
248: register struct regs *r;
249: long c;
250: {
251: while (r->ctrl & PCOWN)
252: ;
253: r->stat &=~ PSOWN;
254: r->ctrl = c;
255: }
256:
257: /*
258: * wait for status in init
259: * needs timeout
260: */
261:
262: long
263: bvpstat(r)
264: register struct regs *r;
265: {
266: while ((r->stat & PSOWN) == 0)
267: ;
268: return (r->stat);
269: }
270:
271: /*
272: * VAX queue primitives
273: */
274:
275: /*
276: * make an empty queue
277: */
278: initvq(q)
279: register quadque *q;
280: {
281: q->head = q->tail = 0;
282: }
283:
284: /*
285: * remove entry from head;
286: * return entry, or 0 if none
287: */
288: caddr_t
289: remqhi(q)
290: quadque *q;
291: {
292: asm("clrl r0");
293: asm("0: remqhi *4(ap),r0");
294: asm("bcs 0b"); /* couldn't interlock; try again */
295: }
296:
297: /*
298: * insert entry to tail
299: * return 1 if this was the first entry
300: */
301: insqti(e, q)
302: caddr_t e;
303: quadque *q;
304: {
305: asm("clrl r0");
306: asm("0: insqti *4(ap),*8(ap)");
307: asm("bcs 0b");
308: asm("bneq 1f");
309: asm("incl r0");
310: asm("1:");
311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.