|
|
1.1 root 1: /*
2: * massbus adapter subroutines
3: * this version for comet
4: */
5:
6: #include "sys/param.h"
7: #include "sys/nxaddr.h"
8: #include "sys/mbaddr.h"
9: #include "sys/mba.h"
10: #include "sys/pte.h"
11: #include "sys/buf.h"
12:
13: /*
14: * hardware things
15: */
16:
17: #define NMAP 256
18:
19: struct mbaregs {
20: long conf; /* configuration register; unused */
21: long cr; /* control register */
22: long sr; /* status register */
23: long va; /* address */
24: long bcr; /* count */
25: long _junk0[251]; /* pad up to 0x400 */
26: long devreg[MBAUNITS][32];
27: long map[NMAP];
28: };
29:
30: #define mbas devreg[0][4] /* attn summary reg; same in all devs */
31:
32: #define CRINIT 01 /* cr -- adapter init */
33: #define CRIE 04 /* cr -- interrupt enable */
34:
35: #define MRV 0x80000000 /* map register -- valid bit */
36: #define MPAGE 0x001fffff /* map register -- page number */
37: /* really only 15 bits on comet; others seem to read 0 */
38:
39: /*
40: * things from mkconf
41: */
42:
43: extern int mbacnt;
44: extern struct mba mba[];
45: extern struct nxaddr mbaaddr[];
46: extern int (*mbavec[][MBAUNITS])();
47: extern char mbaid[][MBAUNITS];
48:
49: #define BUSY 01 /* this mba already transferring */
50: #define INIT 02 /* did init */
51:
52: #define NOUNIT (-1) /* in mbq */
53:
54: caddr_t
55: mbaddr(ap)
56: register struct mbaddr *ap;
57: {
58: register struct mba *mp;
59:
60: if (ap->mbno < 0 || ap->mbno >= mbacnt)
61: return (0);
62: if (ap->unit < 0 || ap->unit >= MBAUNITS)
63: return (0);
64: mp = &mba[ap->mbno];
65: if ((mp->flags & INIT) == 0
66: && mbinit(ap->mbno) == 0)
67: return (0);
68: return ((caddr_t)mp->addr->devreg[ap->unit]);
69: }
70:
71: mbinit(dev)
72: int dev;
73: {
74: register struct mba *mp;
75:
76: mp = &mba[dev];
77: if ((mp->addr = (struct mbaregs *)nxaddr(&mbaaddr[dev])) == NULL
78: || badaddr(&mp->addr->conf, sizeof(long))) {
79: printf("mba%d absent\n");
80: return (0);
81: }
82: mp->addr->cr = CRINIT;
83: mp->addr->cr = CRIE;
84: mp->first = NOUNIT;
85: mp->flags |= INIT;
86: return (1);
87: }
88:
89: /*
90: * enqueue a transfer for this unit;
91: * if not busy, start
92: * if there's already a transfer for this unit, something is wrong
93: */
94: mbstart(ap, bp, go)
95: register struct mbaddr *ap;
96: register struct buf *bp;
97: int (*go)();
98: {
99: register struct mba *mp;
100: register int i;
101:
102: mp = &mba[ap->mbno];
103: i = ap->unit;
104: if (mp->mbuf[i])
105: panic("mbstart");
106: if (mp->first == NOUNIT)
107: mp->first = i;
108: else
109: mp->mbq[mp->last] = i;
110: mp->last = i;
111: mp->mbq[i] = NOUNIT;
112: mp->mbuf[i] = bp;
113: mp->xstart[i] = go;
114: if ((mp->flags & BUSY) == 0)
115: mbxfer(mp);
116: }
117:
118: /*
119: * really start a transfer
120: * mp->lastoff is saved only for mbadj
121: */
122:
123: mbxfer(mp)
124: register struct mba *mp;
125: {
126: register struct mbaregs *reg;
127: register struct pte *p;
128: register long *map;
129: register long size;
130: register struct buf *bp;
131:
132: if (mp->first == NOUNIT)
133: return;
134: reg = mp->addr;
135: bp = mp->mbuf[mp->first];
136: mp->lastoff = (long)bp->b_un.b_addr & PGOFSET;
137: size = btoc(bp->b_bcount);
138: if (mp->lastoff)
139: size++;
140: if (size >= NMAP)
141: size = NMAP-1; /* tough */
142: p = btopte(bp);
143: map = reg->map;
144: while (--size >= 0)
145: *map++ = p++->pg_pfnum | MRV;
146: *map = 0; /* safety */
147: reg->bcr = -bp->b_bcount;
148: reg->va = mp->lastoff;
149: mp->flags |= BUSY;
150: (*mp->xstart[mp->first])(bp);
151: }
152:
153: /*
154: * cheats needed for ECC correction
155: * must be called from interrupt code,
156: * before we've started another transfer
157: */
158:
159: long
160: mbcuraddr(ap)
161: struct mbaddr *ap;
162: {
163: return (mba[ap->mbno].addr->va);
164: }
165:
166: /*
167: * adjust registers to redo current transfer
168: * somewhere in the middle, but not where we were
169: * new buffer address is original+aoff;
170: * new count is as given
171: */
172:
173: mbadj(ap, aoff, count)
174: struct mbaddr *ap;
175: int aoff, count;
176: {
177: register struct mba *mp;
178: register struct mbaregs *reg;
179:
180: mp = &mba[ap->mbno];
181: reg = mp->addr;
182: reg->bcr = -count;
183: reg->va = aoff + mp->lastoff;
184: }
185:
186: /*
187: * xfer was restarted
188: * just mark adapter busy again, and delicately re-insert us in the queue
189: * -- we know we were at the head before
190: */
191:
192: mbcontin(ap)
193: register struct mbaddr *ap;
194: {
195: register struct mba *mp;
196:
197: mp = &mba[ap->mbno];
198: mp->flags |= BUSY;
199: mp->mbq[ap->unit] = mp->first;
200: mp->first = ap->unit;
201: }
202:
203: /*
204: * get, put a byte in MASSBUS space
205: */
206:
207: static long
208: mbphys(ap, addr)
209: struct mbaddr *ap;
210: long addr;
211: {
212: register long m;
213: register int pg;
214: register struct mba *mp;
215:
216: mp = &mba[ap->mbno];
217: if (mp->addr == 0)
218: panic("mbphys");
219: pg = addr / NBPG;
220: if (pg >= NMAP)
221: return (-1);
222: m = mp->addr->map[pg];
223: if ((m & MRV) == 0)
224: return (-1);
225: return ((m & MPAGE) * NBPG + addr % NBPG);
226: }
227:
228: mbgetc(ap, addr)
229: struct mbaddr *ap;
230: long addr;
231: {
232: register long phys;
233:
234: phys = mbphys(ap, addr);
235: if (phys < 0)
236: return (-1);
237: return (phgetc(phys));
238: }
239:
240: int
241: mbputc(ap, addr, c)
242: struct mbaddr *ap;
243: long addr;
244: char c;
245: {
246: register long phys;
247:
248: phys = mbphys(ap, addr);
249: if (phys < 0)
250: return (-1);
251: return (phputc(phys, c));
252: }
253:
254: /*
255: * massbus interrupt
256: * if a transfer in progress, call the driver
257: * if attn, call drivers for that too
258: * it is up to the driver to clear attn
259: * (but for convenience, we promise to tell them what bit to clear)
260: */
261:
262: mba0int(dev)
263: register int dev;
264: {
265: register struct mba *mp;
266: register struct mbaregs *reg;
267: register long sr;
268: register int as, i;
269:
270: if (dev < 0 || dev > mbacnt
271: || (mp = &mba[dev], (mp->flags & INIT)) == 0) {
272: mbshutup(dev);
273: return;
274: }
275: reg = mp->addr;
276: sr = reg->sr;
277: reg->sr = sr; /* clear attn and error latches */
278: as = reg->mbas&0377;
279: if (mp->flags & BUSY) {
280: i = mp->first;
281: mp->mbuf[i] = NULL;
282: mp->first = mp->mbq[i];
283: mp->flags &=~ BUSY;
284: (*mbavec[dev][i])(mbaid[dev][i], sr, (-reg->bcr)&0xffff, as & (1<<i));
285: as &=~ (1<<i);
286: }
287: for (i = 0; as; i++, as >>= 1)
288: if (as & 01)
289: (*mbavec[dev][i])(mbaid[dev][i], 0, 0, 1<<i);
290: if ((mp->flags & BUSY) == 0)
291: mbxfer(mp);
292: }
293:
294: /*
295: * mbavec for non-existent drives points here
296: */
297:
298: mbastray(dev)
299: int dev;
300: {
301: printf("mba%d drive %d stray attn\n", dev>>3, dev&07);
302: }
303:
304: /*
305: * here if didn't expect mba interrupt
306: * might just be a leftover ATTN from a previous boot;
307: * not necessarily cleared
308: */
309:
310: mbshutup(dev)
311: int dev;
312: {
313: register struct mbaregs *reg;
314:
315: if (dev < 0 || dev >= mbacnt
316: || (reg = (struct mbaregs *)nxaddr(&mbaaddr[dev])) == NULL
317: || badaddr(®->conf, sizeof(long))) {
318: printf("mb%d: unacceptable interrupt\n", dev);
319: return; /* and probably get stuck forever */
320: }
321: reg->cr = CRINIT; /* quiet, please */
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.