Annotation of sys/dev/eisa/uha_eisa.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: uha_eisa.c,v 1.6 2007/04/10 17:47:55 miod Exp $ */
2: /* $NetBSD: uha_eisa.c,v 1.5 1996/10/21 22:31:07 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1994, 1996 Charles M. Hannum. 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 by Charles M. Hannum.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: #include <sys/types.h>
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/device.h>
37: #include <sys/kernel.h>
38: #include <sys/proc.h>
39: #include <sys/user.h>
40:
41: #include <machine/bus.h>
42: #include <machine/intr.h>
43:
44: #include <scsi/scsi_all.h>
45: #include <scsi/scsiconf.h>
46:
47: #include <dev/eisa/eisavar.h>
48: #include <dev/eisa/eisadevs.h>
49:
50: #include <dev/ic/uhareg.h>
51: #include <dev/ic/uhavar.h>
52:
53: #define UHA_EISA_SLOT_OFFSET 0xc80
54: #define UHA_EISA_IOSIZE 0x020
55:
56: #ifndef DDB
57: #define Debugger() panic("should call debugger here (uha_eisa.c)")
58: #endif
59:
60: int uha_eisa_match(struct device *, void *, void *);
61: void uha_eisa_attach(struct device *, struct device *, void *);
62:
63: struct cfattach uha_eisa_ca = {
64: sizeof(struct uha_softc), uha_eisa_match, uha_eisa_attach
65: };
66:
67: #define KVTOPHYS(x) vtophys((vaddr_t)(x))
68:
69: int u24_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
70: void u24_start_mbox(struct uha_softc *, struct uha_mscp *);
71: int u24_poll(struct uha_softc *, struct scsi_xfer *, int);
72: int u24_intr(void *);
73: void u24_init(struct uha_softc *);
74:
75: /*
76: * Check the slots looking for a board we recognise
77: * If we find one, note its address (slot) and call
78: * the actual probe routine to check it out.
79: */
80: int
81: uha_eisa_match(parent, match, aux)
82: struct device *parent;
83: void *match, *aux;
84: {
85: struct eisa_attach_args *ea = aux;
86: bus_space_tag_t iot = ea->ea_iot;
87: bus_space_handle_t ioh;
88: int rv;
89:
90: /* must match one of our known ID strings */
91: if (strncmp(ea->ea_idstring, "USC024", 6))
92: return (0);
93:
94: if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
95: UHA_EISA_SLOT_OFFSET, UHA_EISA_IOSIZE, 0, &ioh))
96: return (0);
97:
98: rv = u24_find(iot, ioh, NULL);
99:
100: bus_space_unmap(iot, ioh, UHA_EISA_IOSIZE);
101:
102: return (rv);
103: }
104:
105: /*
106: * Attach all the sub-devices we can find
107: */
108: void
109: uha_eisa_attach(parent, self, aux)
110: struct device *parent, *self;
111: void *aux;
112: {
113: struct eisa_attach_args *ea = aux;
114: struct uha_softc *sc = (void *)self;
115: bus_space_tag_t iot = ea->ea_iot;
116: bus_space_handle_t ioh;
117: eisa_chipset_tag_t ec = ea->ea_ec;
118: eisa_intr_handle_t ih;
119: const char *model, *intrstr;
120:
121: if (!strncmp(ea->ea_idstring, "USC024", 6))
122: model = EISA_PRODUCT_USC0240;
123: else
124: model = "unknown model!";
125: printf(": %s\n", model);
126:
127: if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
128: UHA_EISA_SLOT_OFFSET, UHA_EISA_IOSIZE, 0, &ioh))
129: panic("uha_attach: could not map I/O addresses");
130:
131: sc->sc_iot = iot;
132: sc->sc_ioh = ioh;
133: if (!u24_find(iot, ioh, sc))
134: panic("uha_attach: u24_find failed!");
135:
136: if (eisa_intr_map(ec, sc->sc_irq, &ih)) {
137: printf("%s: couldn't map interrupt (%d)\n",
138: sc->sc_dev.dv_xname, sc->sc_irq);
139: return;
140: }
141: intrstr = eisa_intr_string(ec, ih);
142: sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO,
143: u24_intr, sc, sc->sc_dev.dv_xname);
144: if (sc->sc_ih == NULL) {
145: printf("%s: couldn't establish interrupt",
146: sc->sc_dev.dv_xname);
147: if (intrstr != NULL)
148: printf(" at %s", intrstr);
149: printf("\n");
150: return;
151: }
152: printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
153:
154: /* Save function pointers for later use. */
155: sc->start_mbox = u24_start_mbox;
156: sc->poll = u24_poll;
157: sc->init = u24_init;
158:
159: uha_attach(sc);
160: }
161:
162: int
163: u24_find(iot, ioh, sc)
164: bus_space_tag_t iot;
165: bus_space_handle_t ioh;
166: struct uha_softc *sc;
167: {
168: u_int8_t config0, config1, config2;
169: int irq, drq;
170: int resetcount = 4000; /* 4 secs? */
171:
172: config0 = bus_space_read_1(iot, ioh, U24_CONFIG + 0);
173: config1 = bus_space_read_1(iot, ioh, U24_CONFIG + 1);
174: config2 = bus_space_read_1(iot, ioh, U24_CONFIG + 2);
175: if ((config0 & U24_MAGIC1) == 0 ||
176: (config1 & U24_MAGIC2) == 0)
177: return (0);
178:
179: drq = -1;
180:
181: switch (config0 & U24_IRQ_MASK) {
182: case U24_IRQ10:
183: irq = 10;
184: break;
185: case U24_IRQ11:
186: irq = 11;
187: break;
188: case U24_IRQ14:
189: irq = 14;
190: break;
191: case U24_IRQ15:
192: irq = 15;
193: break;
194: default:
195: printf("u24_find: illegal irq setting %x\n",
196: config0 & U24_IRQ_MASK);
197: return (0);
198: }
199:
200: bus_space_write_1(iot, ioh, U24_LINT, UHA_ASRST);
201:
202: while (--resetcount) {
203: if (bus_space_read_1(iot, ioh, U24_LINT))
204: break;
205: delay(1000); /* 1 mSec per loop */
206: }
207: if (!resetcount) {
208: printf("u24_find: board timed out during reset\n");
209: return (0);
210: }
211:
212: /* if we want to fill in softc, do so now */
213: if (sc != NULL) {
214: sc->sc_irq = irq;
215: sc->sc_drq = drq;
216: sc->sc_scsi_dev = config2 & U24_HOSTID_MASK;
217: }
218:
219: return (1);
220: }
221:
222: void
223: u24_start_mbox(sc, mscp)
224: struct uha_softc *sc;
225: struct uha_mscp *mscp;
226: {
227: bus_space_tag_t iot = sc->sc_iot;
228: bus_space_handle_t ioh = sc->sc_ioh;
229: int spincount = 100000; /* 1s should be enough */
230:
231: while (--spincount) {
232: if ((bus_space_read_1(iot, ioh, U24_LINT) & U24_LDIP) == 0)
233: break;
234: delay(100);
235: }
236: if (!spincount) {
237: printf("%s: uha_start_mbox, board not responding\n",
238: sc->sc_dev.dv_xname);
239: Debugger();
240: }
241:
242: bus_space_write_4(iot, ioh, U24_OGMPTR, KVTOPHYS(mscp));
243: if (mscp->flags & MSCP_ABORT)
244: bus_space_write_1(iot, ioh, U24_OGMCMD, 0x80);
245: else
246: bus_space_write_1(iot, ioh, U24_OGMCMD, 0x01);
247: bus_space_write_1(iot, ioh, U24_LINT, U24_OGMFULL);
248:
249: if ((mscp->xs->flags & SCSI_POLL) == 0)
250: timeout_add(&mscp->xs->stimeout, (mscp->timeout * hz) / 1000);
251: }
252:
253: int
254: u24_poll(sc, xs, count)
255: struct uha_softc *sc;
256: struct scsi_xfer *xs;
257: int count;
258: {
259: bus_space_tag_t iot = sc->sc_iot;
260: bus_space_handle_t ioh = sc->sc_ioh;
261:
262: while (count) {
263: /*
264: * If we had interrupts enabled, would we
265: * have got an interrupt?
266: */
267: if (bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP)
268: u24_intr(sc);
269: if (xs->flags & ITSDONE)
270: return (0);
271: delay(1000);
272: count--;
273: }
274: return (1);
275: }
276:
277: int
278: u24_intr(arg)
279: void *arg;
280: {
281: struct uha_softc *sc = arg;
282: bus_space_tag_t iot = sc->sc_iot;
283: bus_space_handle_t ioh = sc->sc_ioh;
284: struct uha_mscp *mscp;
285: u_char uhastat;
286: u_long mboxval;
287:
288: #ifdef UHADEBUG
289: printf("%s: uhaintr ", sc->sc_dev.dv_xname);
290: #endif /*UHADEBUG */
291:
292: if ((bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP) == 0)
293: return (0);
294:
295: for (;;) {
296: /*
297: * First get all the information and then
298: * acknowledge the interrupt
299: */
300: uhastat = bus_space_read_1(iot, ioh, U24_SINT);
301: mboxval = bus_space_read_4(iot, ioh, U24_ICMPTR);
302: bus_space_write_1(iot, ioh, U24_SINT, U24_ICM_ACK);
303: bus_space_write_1(iot, ioh, U24_ICMCMD, 0);
304:
305: #ifdef UHADEBUG
306: printf("status = 0x%x ", uhastat);
307: #endif /*UHADEBUG*/
308:
309: /*
310: * Process the completed operation
311: */
312: mscp = uha_mscp_phys_kv(sc, mboxval);
313: if (!mscp) {
314: printf("%s: BAD MSCP RETURNED!\n",
315: sc->sc_dev.dv_xname);
316: continue; /* whatever it was, it'll timeout */
317: }
318: timeout_del(&mscp->xs->stimeout);
319: uha_done(sc, mscp);
320:
321: if ((bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP) == 0)
322: return (1);
323: }
324: }
325:
326: void
327: u24_init(sc)
328: struct uha_softc *sc;
329: {
330: bus_space_tag_t iot = sc->sc_iot;
331: bus_space_handle_t ioh = sc->sc_ioh;
332:
333: /* free OGM and ICM */
334: bus_space_write_1(iot, ioh, U24_OGMCMD, 0);
335: bus_space_write_1(iot, ioh, U24_ICMCMD, 0);
336: /* make sure interrupts are enabled */
337: #ifdef UHADEBUG
338: printf("u24_init: lmask=%02x, smask=%02x\n",
339: bus_space_read_1(iot, ioh, U24_LMASK),
340: bus_space_read_1(iot, ioh, U24_SMASK));
341: #endif
342: bus_space_write_1(iot, ioh, U24_LMASK, 0xd2); /* XXX */
343: bus_space_write_1(iot, ioh, U24_SMASK, 0x92); /* XXX */
344: }
CVSweb