Annotation of sys/arch/vax/mba/mba.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mba.c,v 1.10 2006/01/20 23:27:25 miod Exp $ */
2: /* $NetBSD: mba.c,v 1.18 2000/01/24 02:40:36 matt Exp $ */
3: /*
4: * Copyright (c) 1994, 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: * Simple massbus drive routine.
36: * TODO:
37: * Autoconfig new devices 'on the fly'.
38: * More intelligent way to handle different interrupts.
39: */
40:
41: #include <sys/param.h>
42: #include <sys/systm.h>
43: #include <sys/device.h>
44: #include <sys/queue.h>
45: #include <sys/buf.h>
46: #include <sys/proc.h>
47:
48: #include <uvm/uvm_extern.h>
49:
50: #include <machine/trap.h>
51: #include <machine/scb.h>
52: #include <machine/nexus.h>
53: #include <machine/pte.h>
54: #include <machine/pcb.h>
55: #include <machine/sid.h>
56: #include <machine/cpu.h>
57:
58: #include <vax/mba/mbareg.h>
59: #include <vax/mba/mbavar.h>
60:
61: struct mbaunit mbaunit[] = {
62: {MBADT_RP04, "rp04", MB_RP},
63: {MBADT_RP05, "rp05", MB_RP},
64: {MBADT_RP06, "rp06", MB_RP},
65: {MBADT_RP07, "rp07", MB_RP},
66: {MBADT_RM02, "rm02", MB_RP},
67: {MBADT_RM03, "rm03", MB_RP},
68: {MBADT_RM05, "rm05", MB_RP},
69: {MBADT_RM80, "rm80", MB_RP},
70: {0, 0, 0}
71: };
72:
73: int mbamatch(struct device *, struct cfdata *, void *);
74: void mbaattach(struct device *, struct device *, void *);
75: void mbaintr(void *);
76: int mbaprint(void *, const char *);
77: void mbaqueue(struct mba_device *);
78: void mbastart(struct mba_softc *);
79: void mbamapregs(struct mba_softc *);
80:
81: struct cfattach mba_cmi_ca = {
82: sizeof(struct mba_softc), mbamatch, mbaattach
83: };
84:
85: struct cfattach mba_sbi_ca = {
86: sizeof(struct mba_softc), mbamatch, mbaattach
87: };
88:
89: extern struct cfdriver mba_cd;
90:
91: /*
92: * Look if this is a massbuss adapter.
93: */
94: int
95: mbamatch(parent, cf, aux)
96: struct device *parent;
97: struct cfdata *cf;
98: void *aux;
99: {
100: struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
101:
102: if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
103: return 0;
104:
105: if (sa->type == NEX_MBA)
106: return 1;
107:
108: return 0;
109: }
110:
111: /*
112: * Attach the found massbuss adapter. Setup its interrupt vectors,
113: * reset it and go searching for drives on it.
114: */
115: void
116: mbaattach(parent, self, aux)
117: struct device *parent, *self;
118: void *aux;
119: {
120: struct mba_softc *sc = (void *)self;
121: struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
122: volatile struct mba_regs *mbar = (struct mba_regs *)sa->nexaddr;
123: struct mba_attach_args ma;
124: int i, j;
125:
126: printf("\n");
127: /*
128: * Set up interrupt vectors for this MBA.
129: */
130: sc->sc_dsp = idsptch;
131: sc->sc_dsp.pushlarg = sc;
132: sc->sc_dsp.hoppaddr = mbaintr;
133: scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] =
134: scb->scb_nexvec[2][sa->nexnum] = scb->scb_nexvec[3][sa->nexnum] =
135: &sc->sc_dsp;
136:
137: sc->sc_physnr = sa->nexnum - 8; /* MBA's have TR between 8 - 11... */
138: #if VAX750
139: if (vax_cputype == VAX_750)
140: sc->sc_physnr += 4; /* ...but not on 11/750 */
141: #endif
142: sc->sc_first = 0;
143: sc->sc_last = (void *)&sc->sc_first;
144: sc->sc_mbareg = (struct mba_regs *)mbar;
145: mbar->mba_cr = MBACR_INIT; /* Reset adapter */
146: mbar->mba_cr = MBACR_IE; /* Enable interrupts */
147:
148: for (i = 0; i < MAXMBADEV; i++) {
149: sc->sc_state = SC_AUTOCONF;
150: if ((mbar->mba_md[i].md_ds & MBADS_DPR) == 0)
151: continue;
152: /* We have a drive, ok. */
153: ma.unit = i;
154: ma.type = mbar->mba_md[i].md_dt & 0777;
155: j = 0;
156: while (mbaunit[j++].nr)
157: if (mbaunit[j].nr == ma.type)
158: break;
159: ma.devtyp = mbaunit[j].devtyp;
160: ma.name = mbaunit[j].name;
161: config_found(&sc->sc_dev, (void *)&ma, mbaprint);
162: }
163: }
164:
165: /*
166: * We got an interrupt. Check type of interrupt and call the specific
167: * device interrupt handling routine.
168: */
169: void
170: mbaintr(mba)
171: void *mba;
172: {
173: struct mba_softc *sc = mba;
174: volatile struct mba_regs *mr = sc->sc_mbareg;
175: struct mba_device *md;
176: struct buf *bp;
177: int itype, attn, anr;
178:
179: itype = mr->mba_sr;
180: mr->mba_sr = itype; /* Write back to clear bits */
181:
182: attn = mr->mba_md[0].md_as & 0xff;
183: mr->mba_md[0].md_as = attn;
184:
185: if (sc->sc_state == SC_AUTOCONF)
186: return; /* During autoconfig */
187:
188: md = sc->sc_first;
189: bp = BUFQ_FIRST(&md->md_q);
190: /*
191: * A data-transfer interrupt. Current operation is finished,
192: * call that device's finish routine to see what to do next.
193: */
194: if (sc->sc_state == SC_ACTIVE) {
195:
196: sc->sc_state = SC_IDLE;
197: switch ((*md->md_finish)(md, itype, &attn)) {
198:
199: case XFER_FINISH:
200: /*
201: * Transfer is finished. Take buffer of drive
202: * queue, and take drive of adapter queue.
203: * If more to transfer, start the adapter again
204: * by calling mbastart().
205: */
206: BUFQ_REMOVE(&md->md_q, bp);
207: sc->sc_first = md->md_back;
208: md->md_back = 0;
209: if (sc->sc_first == 0)
210: sc->sc_last = (void *)&sc->sc_first;
211:
212: if (BUFQ_FIRST(&md->md_q) != NULL) {
213: sc->sc_last->md_back = md;
214: sc->sc_last = md;
215: }
216:
217: bp->b_resid = 0;
218: biodone(bp);
219: if (sc->sc_first)
220: mbastart(sc);
221: break;
222:
223: case XFER_RESTART:
224: /*
225: * Something went wrong with the transfer. Try again.
226: */
227: mbastart(sc);
228: break;
229: }
230: }
231:
232: while (attn) {
233: anr = ffs(attn) - 1;
234: attn &= ~(1 << anr);
235: if (sc->sc_md[anr]->md_attn == 0)
236: panic("Should check for new MBA device %d", anr);
237: (*sc->sc_md[anr]->md_attn)(sc->sc_md[anr]);
238: }
239: }
240:
241: int
242: mbaprint(aux, mbaname)
243: void *aux;
244: const char *mbaname;
245: {
246: struct mba_attach_args *ma = aux;
247:
248: if (mbaname) {
249: if (ma->name)
250: printf("%s", ma->name);
251: else
252: printf("device type %o", ma->type);
253: printf(" at %s", mbaname);
254: }
255: printf(" drive %d", ma->unit);
256: return (ma->name ? UNCONF : UNSUPP);
257: }
258:
259: /*
260: * A device calls mbaqueue() when it wants to get on the adapter queue.
261: * Called at splbio(). If the adapter is inactive, start it.
262: */
263: void
264: mbaqueue(md)
265: struct mba_device *md;
266: {
267: struct mba_softc *sc = md->md_mba;
268: int i = (int)sc->sc_first;
269:
270: sc->sc_last->md_back = md;
271: sc->sc_last = md;
272:
273: if (i == 0)
274: mbastart(sc);
275: }
276:
277: /*
278: * Start activity on (idling) adapter. Calls mbamapregs() to setup
279: * for dma transfer, then the unit-specific start routine.
280: */
281: void
282: mbastart(sc)
283: struct mba_softc *sc;
284: {
285: struct mba_device *md = sc->sc_first;
286: volatile struct mba_regs *mr = sc->sc_mbareg;
287: struct buf *bp = BUFQ_FIRST(&md->md_q);
288:
289: disk_reallymapin(BUFQ_FIRST(&md->md_q), sc->sc_mbareg->mba_map,
290: 0, PG_V);
291:
292: sc->sc_state = SC_ACTIVE;
293: mr->mba_var = ((u_int)bp->b_data & VAX_PGOFSET);
294: mr->mba_bc = (~bp->b_bcount) + 1;
295: (*md->md_start)(md); /* machine-dependent start */
296: }
CVSweb