|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)mb.c 1.1 86/02/03 Copyr 1983 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * Mainbus support routines.
11: */
12:
13: #include "../h/param.h"
14: #include "../h/systm.h"
15: #include "../h/vmmac.h"
16: #include "../h/vmmeter.h"
17: #include "../h/vmparam.h"
18: #include "../h/map.h"
19: #include "../h/buf.h"
20: #include "../h/dir.h"
21: #include "../h/user.h"
22: #include "../h/proc.h"
23: #include "../h/conf.h"
24: /*#include "../h/kernel.h"*/
25:
26: #include "../machine/mmu.h"
27: #include "../machine/cpu.h"
28: #include "../machine/psl.h"
29: #include "../machine/pte.h"
30: #include "../machine/reg.h"
31:
32: #include "../sundev/mbvar.h"
33:
34: /*
35: * Do transfer on controller argument.
36: * We queue for resource wait in the Mainbus code if necessary.
37: * We return 1 if the transfer was started, 0 if it was not.
38: * If you call this routine with the head of the queue for a
39: * Mainbus, it will automatically remove the controller from the Mainbus
40: * queue before it returns. If some other controller is given
41: * as argument, it will be added to the request queue if the
42: * request cannot be started immediately. This means that
43: * passing a controller which is on the queue but not at the head
44: * of the request queue is likely to be a disaster.
45: */
46: mbgo(mc)
47: register struct mb_ctlr *mc;
48: {
49: register struct mb_hd *mh = mc->mc_mh;
50: register struct buf *bp = mc->mc_tab.b_actf->b_actf;
51: register int s;
52:
53: s = splx(pritospl(SPLMB));
54: if ((mc->mc_driver->mdr_flags & MDR_XCLU) &&
55: mh->mh_users > 0 || mh->mh_xclu)
56: goto rwait;
57: mc->mc_mbinfo = mbsetup(mh, bp, MB_CANTWAIT);
58: if (mc->mc_mbinfo == 0)
59: goto rwait;
60: mh->mh_users++;
61: if (mc->mc_driver->mdr_flags & MDR_XCLU)
62: mh->mh_xclu = 1;
63: (void) splx(s);
64: if (mh->mh_actf == mc)
65: mh->mh_actf = mc->mc_forw;
66: if ((mc->mc_driver->mdr_flags & MDR_SWAB) && (bp->b_flags&B_READ)==0)
67: swab(bp->b_un.b_addr, bp->b_un.b_addr, (int)bp->b_bcount);
68: (*mc->mc_driver->mdr_go)(mc);
69: return (1);
70: rwait:
71: if (mh->mh_actf != mc) {
72: mc->mc_forw = NULL;
73: if (mh->mh_actf == NULL)
74: mh->mh_actf = mc;
75: else
76: mh->mh_actl->mc_forw = mc;
77: mh->mh_actl = mc;
78: }
79: (void) splx(s);
80: return (0);
81: }
82:
83: mbdone(mc)
84: register struct mb_ctlr *mc;
85: {
86: register struct mb_hd *mh = mc->mc_mh;
87: register struct buf *bp = mc->mc_tab.b_actf->b_actf;
88:
89: if (mc->mc_driver->mdr_flags & MDR_XCLU)
90: mh->mh_xclu = 0;
91: mh->mh_users--;
92: mbrelse(mh, &mc->mc_mbinfo);
93: if (mc->mc_driver->mdr_flags & MDR_SWAB)
94: swab(bp->b_un.b_addr, bp->b_un.b_addr, (int)bp->b_bcount);
95: (*mc->mc_driver->mdr_done)(mc);
96: }
97:
98: /*
99: * Allocate and setup Mainbus map registers.
100: * Flags says whether the caller can't
101: * wait (e.g. if the caller is at interrupt level).
102: *
103: * We also allow DMA to memory already mapped at the Mainbus
104: * (e.g., for Sun Ethernet board memory) and denote this with
105: * a zero in the MBI_NMR field.
106: */
107: mbsetup(mh, bp, flags)
108: register struct mb_hd *mh;
109: struct buf *bp;
110: int flags;
111: {
112: int npf, reg;
113: register struct pte *pte;
114: register char *addr;
115: int s, o;
116: struct mbcookie mbcookie;
117: #ifdef sun2
118: int uc;
119: #endif
120:
121: o = (int)bp->b_un.b_addr & PGOFSET;
122: if ((bp->b_flags & B_PHYS) == 0)
123: pte = &Sysmap[btop((int)bp->b_un.b_addr - KERNELBASE)];
124: else {
125: if (bp->b_kmx == 0)
126: panic("mbsetup: zero kmx");
127: pte = &Usrptmap[bp->b_kmx];
128: }
129:
130: npf = btoc(bp->b_bcount + o);
131: if (buscheck(pte, npf)) {
132: mbcookie.mbi_mapreg = pte->pg_pfnum;
133: mbcookie.mbi_offset = o;
134: return (*(int *)&mbcookie);
135: }
136:
137: /* Defensively invalidate the page following the allocation */
138: npf++;
139: s = splx(pritospl(SPLMB));
140: while ((reg = (int)rmalloc(mh->mh_map, (long)npf)) == 0) {
141: if (flags & MB_CANTWAIT) {
142: (void) splx(s);
143: return (0);
144: }
145: mh->mh_mrwant++;
146: sleep((caddr_t)&mh->mh_mrwant, PSWP);
147: }
148: (void) splx(s);
149: mbcookie.mbi_mapreg = reg;
150: mbcookie.mbi_offset = o;
151: addr = &DVMA[ctob(reg)];
152: #ifdef sun2
153: uc = getusercontext();
154: setusercontext(KCONTEXT);
155: #endif
156: while (--npf > 0) {
157: register int pfnum;
158:
159: switch (*(int *)pte & PGT_MASK) {
160: default:
161: /* may not go from dvma back out to the bus */
162: panic("mbsetup: bad PGT");
163: case PGT_OBMEM:
164: case PGT_OBIO:
165: if ((pfnum = pte->pg_pfnum) == 0)
166: panic("mbsetup: zero pfnum");
167: setpgmap(addr, (long)(PG_V | PG_KW | pfnum));
168: addr += NBPG;
169: pte++;
170: }
171: }
172: setpgmap(addr, (long)0);
173: #ifdef sun2
174: setusercontext(uc);
175: #endif
176: return (*(int *)&mbcookie);
177: }
178:
179: /*
180: * Non buffer setup interface... set up a buffer and call mbsetup.
181: */
182: mballoc(mh, addr, bcnt, flags)
183: struct mb_hd *mh;
184: caddr_t addr;
185: int bcnt, flags;
186: {
187: struct buf mbbuf;
188:
189: mbbuf.b_un.b_addr = addr;
190: mbbuf.b_flags = B_BUSY;
191: mbbuf.b_bcount = bcnt;
192: /* that's all the fields mbsetup() needs */
193: return (mbsetup(mh, &mbbuf, flags));
194: }
195:
196: /*
197: * Release resources on Mainbus, and then unblock resource waiters.
198: * The map register parameter is by value since we need to block
199: * against Mainbus resets.
200: */
201: mbrelse(mh, amr)
202: register struct mb_hd *mh;
203: int *amr;
204: {
205: register int reg, s;
206: register char *addr;
207: int mr;
208: #ifdef sun2
209: int uc;
210: #endif
211:
212: /*
213: * Carefully see if we should release the space, since
214: * it may be released asynchronously at Mainbus reset time.
215: */
216: s = splx(pritospl(SPLMB));
217: mr = *amr;
218: if (mr == 0) {
219: printf("mbrelse: MR == 0!!!\n");
220: (void) splx(s);
221: return;
222: }
223: *amr = 0;
224: (void) splx(s); /* let interrupts in, we're safe for a while */
225:
226: if ((reg = MBI_MR(mr)) < dvmasize) { /* DVMA memory */
227: long getpgmap();
228: register int npf = 1; /* plus one for last entry */
229:
230: #ifdef sun2
231: uc = getusercontext();
232: setusercontext(KCONTEXT);
233: #endif
234: for (addr = &DVMA[ctob(reg)]; getpgmap(addr) != (long)0;
235: addr += NBPG, npf++)
236: setpgmap(addr, (long)0);
237: #ifdef sun2
238: setusercontext(uc);
239: #endif
240: /*
241: * Put back the registers in the resource map.
242: * The map code must not be reentered, so we do this
243: * at high spl.
244: */
245: s = splx(pritospl(SPLMB));
246: rmfree(mh->mh_map, (long)npf, (long)reg);
247: (void) splx(s);
248:
249: /*
250: * Wakeup sleepers for map registers,
251: * and also, if there are processes blocked in mbgo(),
252: * give them a chance at the Mainbus.
253: */
254: if (mh->mh_mrwant) {
255: mh->mh_mrwant = 0;
256: wakeup((caddr_t)&mh->mh_mrwant);
257: }
258: }
259: while (mh->mh_actf && mbgo(mh->mh_actf))
260: ;
261: }
262:
263: /*
264: * Swap bytes in 16-bit [half-]words
265: * for going between the 11 and the interdata
266: */
267: swab(pf, pt, n)
268: register caddr_t pf, pt;
269: register int n;
270: {
271: register char temp;
272:
273: n = (n+1)>>1;
274:
275: while (--n >= 0) {
276: temp = *pf++;
277: *pt++ = *pf++;
278: *pt++ = temp;
279: }
280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.