Annotation of sys/dev/isa/fdc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: fdc.c,v 1.17 2005/09/19 01:28:04 deraadt Exp $ */
2: /* $NetBSD: fd.c,v 1.90 1996/05/12 23:12:03 mycroft Exp $ */
3:
4: /*-
5: * Copyright (c) 1993, 1994, 1995 Charles Hannum.
6: * Copyright (c) 1990 The Regents of the University of California.
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * Don Ahn.
11: *
12: * Portions Copyright (c) 1993, 1994 by
13: * jc@irbs.UUCP (John Capo)
14: * vak@zebub.msk.su (Serge Vakulenko)
15: * ache@astral.msk.su (Andrew A. Chernov)
16: * joerg_wunsch@uriah.sax.de (Joerg Wunsch)
17: *
18: * Redistribution and use in source and binary forms, with or without
19: * modification, are permitted provided that the following conditions
20: * are met:
21: * 1. Redistributions of source code must retain the above copyright
22: * notice, this list of conditions and the following disclaimer.
23: * 2. Redistributions in binary form must reproduce the above copyright
24: * notice, this list of conditions and the following disclaimer in the
25: * documentation and/or other materials provided with the distribution.
26: * 3. Neither the name of the University nor the names of its contributors
27: * may be used to endorse or promote products derived from this software
28: * without specific prior written permission.
29: *
30: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40: * SUCH DAMAGE.
41: *
42: * @(#)fd.c 7.4 (Berkeley) 5/25/91
43: */
44:
45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/kernel.h>
48: #include <sys/file.h>
49: #include <sys/ioctl.h>
50: #include <sys/device.h>
51: #include <sys/disklabel.h>
52: #include <sys/dkstat.h>
53: #include <sys/disk.h>
54: #include <sys/buf.h>
55: #include <sys/malloc.h>
56: #include <sys/uio.h>
57: #include <sys/mtio.h>
58: #include <sys/syslog.h>
59: #include <sys/queue.h>
60: #include <sys/timeout.h>
61:
62: #include <machine/cpu.h>
63: #include <machine/bus.h>
64: #include <machine/conf.h>
65: #include <machine/intr.h>
66: #include <machine/ioctl_fd.h>
67:
68: #include <dev/isa/isavar.h>
69: #include <dev/isa/isadmavar.h>
70: #include <dev/isa/fdreg.h>
71:
72: #if defined(__i386__) || defined(__amd64__) /* XXX */
73: #include <dev/ic/mc146818reg.h> /* for NVRAM access */
74: #include <i386/isa/nvram.h>
75: #endif
76:
77: #include <dev/isa/fdlink.h>
78:
79: #include "fd.h"
80:
81: /* controller driver configuration */
82: int fdcprobe(struct device *, void *, void *);
83: void fdcattach(struct device *, struct device *, void *);
84:
85: struct cfattach fdc_ca = {
86: sizeof(struct fdc_softc), fdcprobe, fdcattach
87: };
88:
89: struct cfdriver fdc_cd = {
90: NULL, "fdc", DV_DULL
91: };
92:
93: int fddprint(void *, const char *);
94: int fdcintr(void *);
95:
96: int
97: fdcprobe(parent, match, aux)
98: struct device *parent;
99: void *match, *aux;
100: {
101: register struct isa_attach_args *ia = aux;
102: bus_space_tag_t iot;
103: bus_space_handle_t ioh;
104: bus_space_handle_t ioh_ctl;
105: int rv;
106:
107: iot = ia->ia_iot;
108: rv = 0;
109:
110: /* Map the i/o space. */
111: if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh))
112: return 0;
113: if (bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
114: FDCTL_NPORT, 0, &ioh_ctl))
115: return 0;
116:
117: /* reset */
118: bus_space_write_1(iot, ioh, fdout, 0);
119: delay(100);
120: bus_space_write_1(iot, ioh, fdout, FDO_FRST);
121:
122: /* see if it can handle a command */
123: if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
124: goto out;
125: out_fdc(iot, ioh, 0xdf);
126: out_fdc(iot, ioh, 2);
127:
128: rv = 1;
129: ia->ia_iosize = FDC_NPORT;
130: ia->ia_msize = 0;
131:
132: out:
133: bus_space_unmap(iot, ioh, FDC_NPORT);
134: bus_space_unmap(iot, ioh_ctl, FDCTL_NPORT);
135: return rv;
136: }
137:
138: void
139: fdcattach(parent, self, aux)
140: struct device *parent, *self;
141: void *aux;
142: {
143: struct fdc_softc *fdc = (void *)self;
144: bus_space_tag_t iot;
145: bus_space_handle_t ioh;
146: bus_space_handle_t ioh_ctl;
147: struct isa_attach_args *ia = aux;
148: struct fdc_attach_args fa;
149: int type;
150:
151: iot = ia->ia_iot;
152:
153: /* Re-map the I/O space. */
154: if (bus_space_map(iot, ia->ia_iobase, FDC_NPORT, 0, &ioh) ||
155: bus_space_map(iot, ia->ia_iobase + FDCTL_OFFSET,
156: FDCTL_NPORT, 0, &ioh_ctl))
157: panic("fdcattach: couldn't map I/O ports");
158:
159: fdc->sc_iot = iot;
160: fdc->sc_ioh = ioh;
161: fdc->sc_ioh_ctl = ioh_ctl;
162:
163: fdc->sc_drq = ia->ia_drq;
164: fdc->sc_state = DEVIDLE;
165: TAILQ_INIT(&fdc->sc_link.fdlink.sc_drives); /* XXX */
166:
167: printf("\n");
168:
169: fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
170: IPL_BIO, fdcintr, fdc, fdc->sc_dev.dv_xname);
171:
172: #if defined(__i386__) || defined(__amd64__)
173: /*
174: * The NVRAM info only tells us about the first two disks on the
175: * `primary' floppy controller.
176: */
177: if (fdc->sc_dev.dv_unit == 0)
178: type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
179: else
180: #endif
181: type = -1;
182:
183: timeout_set(&fdc->fdcpseudointr_to, fdcpseudointr, fdc);
184:
185: /* physical limit: four drives per controller. */
186: for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
187: fa.fa_flags = 0;
188: fa.fa_type = 0;
189: #if NFD > 0
190: if (type >= 0 && fa.fa_drive < 2)
191: fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
192: type, fa.fa_drive);
193: else
194: #endif
195: fa.fa_deftype = NULL; /* unknown */
196: (void)config_found(self, (void *)&fa, fddprint);
197: }
198: }
199:
200: /*
201: * Print the location of a disk/tape drive (called just before attaching the
202: * the drive). If `fdc' is not NULL, the drive was found but was not
203: * in the system config file; print the drive name as well.
204: * Return QUIET (config_find ignores this if the device was configured) to
205: * avoid printing `fdN not configured' messages.
206: */
207: int
208: fddprint(aux, fdc)
209: void *aux;
210: const char *fdc;
211: {
212: register struct fdc_attach_args *fa = aux;
213:
214: if (!fdc)
215: printf(" drive %d", fa->fa_drive);
216: return QUIET;
217: }
218:
219: int
220: fdcresult(fdc)
221: struct fdc_softc *fdc;
222: {
223: bus_space_tag_t iot = fdc->sc_iot;
224: bus_space_handle_t ioh = fdc->sc_ioh;
225: u_char i;
226: int j = 100000, n = 0;
227:
228: for (; j; j--) {
229: i = bus_space_read_1(iot, ioh, fdsts) &
230: (NE7_DIO | NE7_RQM | NE7_CB);
231: if (i == NE7_RQM)
232: return n;
233: if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
234: if (n >= sizeof(fdc->sc_status)) {
235: log(LOG_ERR, "fdcresult: overrun\n");
236: return -1;
237: }
238: fdc->sc_status[n++] =
239: bus_space_read_1(iot, ioh, fddata);
240: }
241: delay(10);
242: }
243: return -1;
244: }
245:
246: int
247: out_fdc(iot, ioh, x)
248: bus_space_tag_t iot;
249: bus_space_handle_t ioh;
250: u_char x;
251: {
252: int i = 100000;
253:
254: while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
255: if (i <= 0)
256: return -1;
257: while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
258: if (i <= 0)
259: return -1;
260: bus_space_write_1(iot, ioh, fddata, x);
261: return 0;
262: }
263:
264: void
265: fdcstart(fdc)
266: struct fdc_softc *fdc;
267: {
268:
269: #ifdef DIAGNOSTIC
270: /* only got here if controller's drive queue was inactive; should
271: be in idle state */
272: if (fdc->sc_state != DEVIDLE) {
273: printf("fdcstart: not idle\n");
274: return;
275: }
276: #endif
277: (void) fdcintr(fdc);
278: }
279:
280: void
281: fdcstatus(dv, n, s)
282: struct device *dv;
283: int n;
284: char *s;
285: {
286: struct fdc_softc *fdc = (void *)dv->dv_parent;
287:
288: if (n == 0) {
289: out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
290: (void) fdcresult(fdc);
291: n = 2;
292: }
293:
294: printf("%s: %s", dv->dv_xname, s);
295:
296: switch (n) {
297: case 0:
298: printf("\n");
299: break;
300: case 2:
301: printf(" (st0 %b cyl %d)\n",
302: fdc->sc_status[0], NE7_ST0BITS,
303: fdc->sc_status[1]);
304: break;
305: case 7:
306: printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
307: fdc->sc_status[0], NE7_ST0BITS,
308: fdc->sc_status[1], NE7_ST1BITS,
309: fdc->sc_status[2], NE7_ST2BITS,
310: fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
311: break;
312: #ifdef DIAGNOSTIC
313: default:
314: printf("\nfdcstatus: weird size");
315: break;
316: #endif
317: }
318: }
319:
320: void
321: fdcpseudointr(arg)
322: void *arg;
323: {
324: int s;
325:
326: /* Just ensure it has the right spl. */
327: s = splbio();
328: (void) fdcintr(arg);
329: splx(s);
330: }
331:
332: int
333: fdcintr(arg)
334: void *arg;
335: {
336: #if NFD > 0
337: struct fdc_softc *fdc = arg;
338: extern int fdintr(struct fdc_softc *);
339:
340: /* Will switch on device type, shortly. */
341: return (fdintr(fdc));
342: #else
343: printf("fdcintr: got interrupt, but no devices!\n");
344: return (1);
345: #endif
346: }
CVSweb