This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sys / i386 / stand / fd.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Don Ahn.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
e73885af
RG
36 * from: @(#)fd.c 7.3 (Berkeley) 5/25/91
37 * $Id$
15637ed4
RG
38 */
39
40/****************************************************************************/
41/* standalone fd driver */
42/****************************************************************************/
43#include "param.h"
44#include "disklabel.h"
45#include "i386/isa/fdreg.h"
46#include "i386/isa/isa.h"
47#include "saio.h"
48
49#define NUMRETRY 10
50/*#define FDDEBUG*/
51
52#define NFD 2
53#define FDBLK 512
54
55extern struct disklabel disklabel;
56
57struct fd_type {
58 int sectrac; /* sectors per track */
59 int secsize; /* size code for sectors */
60 int datalen; /* data len when secsize = 0 */
61 int gap; /* gap len between sectors */
62 int tracks; /* total num of tracks */
63 int size; /* size of disk in sectors */
64 int steptrac; /* steps per cylinder */
65 int trans; /* transfer speed code */
66};
67
68struct fd_type fd_types[] = {
69 { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy */
70 { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy */
71 /* need 720K 3.5in here as well */
72#ifdef noway
73 { 9,2,0xFF,0x23,40,720,2,1 }, /* 360k floppy in 1.2meg drive */
74 { 9,2,0xFF,0x2A,40,720,1,1 }, /* 360k floppy in DD drive */
75#endif
76};
77
78
79/* state needed for current transfer */
80static int probetype;
81static int fd_type;
82static int fd_motor;
83static int fd_retry;
84static int fd_drive;
85static int fd_status[7];
86
87static int fdc = IO_FD1; /* floppy disk base */
88
89/* Make sure DMA buffer doesn't cross 64k boundary */
90char bounce[FDBLK];
91
92
93/****************************************************************************/
94/* fdstrategy */
95/****************************************************************************/
96int
97fdstrategy(io,func)
98register struct iob *io;
99int func;
100{
101 char *address;
102 long nblocks,blknum;
103 int unit, iosize;
104
105#ifdef FDDEBUG
106printf("fdstrat ");
107#endif
108 unit = io->i_unit;
109 /*fd_type = io->i_part;*/
110
111 /*
112 * Set up block calculations.
113 */
114 iosize = io->i_cc / FDBLK;
115 blknum = (unsigned long) io->i_bn * DEV_BSIZE / FDBLK;
116 nblocks = fd_types[fd_type].size /* disklabel.d_secperunit */;
117 if ((blknum + iosize > nblocks) || blknum < 0) {
118#ifdef nope
119 printf("bn = %d; sectors = %d; type = %d; fssize = %d ",
120 blknum, iosize, fd_type, nblocks);
121 printf("fdstrategy - I/O out of filesystem boundaries\n");
122#endif
123 return(-1);
124 }
125
126 address = io->i_ma;
127 while (iosize > 0) {
128/*printf("iosize %d ", iosize);*/
129 if (fdio(func, unit, blknum, address))
130 return(-1);
131 iosize--;
132 blknum++;
133 address += FDBLK;
134 }
135 return(io->i_cc);
136}
137
138int ccyl = -1;
139
140int
141fdio(func, unit, blknum, address)
142int func,unit,blknum;
143char *address;
144{
145 int i,j, cyl, sectrac,sec,head,numretry;
146 struct fd_type *ft;
147
148/*printf("fdio ");*/
149 ft = &fd_types[fd_type];
150
151 sectrac = ft->sectrac;
152 cyl = blknum / (sectrac*2);
153 numretry = NUMRETRY;
154
155 if (func == F_WRITE)
156 bcopy(address,bounce,FDBLK);
157
158retry:
159 if (ccyl != cyl) {
160 out_fdc(15); /* Seek function */
161 out_fdc(unit); /* Drive number */
162 out_fdc(cyl);
163
164 waitio();
165 }
166
167 out_fdc(0x8);
168 i = in_fdc(); j = in_fdc();
169 if (!(i&0x20) || (cyl != j)) {
170 numretry--;
171 ccyl = j;
172 if (numretry) goto retry;
173
174 printf("Seek error %d, req = %d, at = %d\n",i,cyl,j);
175 printf("unit %d, type %d, sectrac %d, blknum %d\n",
176 unit,fd_type,sectrac,blknum);
177
178 return -1;
179 }
180 ccyl = cyl;
181
182 /* set up transfer */
183 fd_dma(func == F_READ, bounce, FDBLK);
184 sec = blknum % (sectrac * 2) /*disklabel.d_secpercyl*/;
185 head = sec / sectrac;
186 sec = sec % sectrac + 1;
187#ifdef FDDEBUG
188 printf("sec %d hd %d cyl %d ", sec, head, cyl);
189#endif
190
191 if (func == F_READ) out_fdc(0xE6);/* READ */
192 else out_fdc(0xC5); /* WRITE */
193 out_fdc(head << 2 | fd_drive); /* head & unit */
194 out_fdc(cyl); /* track */
195 out_fdc(head);
196 out_fdc(sec); /* sector */
197 out_fdc(ft->secsize); /* sector size */
198 out_fdc(sectrac); /* sectors/track */
199 out_fdc(ft->gap); /* gap size */
200 out_fdc(ft->datalen); /* data length */
201
202 waitio();
203
204 for(i=0;i<7;i++) {
205 fd_status[i] = in_fdc();
206 }
207 if (fd_status[0]&0xF8) {
208 numretry--;
209
210 if (!probetype)
211 printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
212 fd_status[0], fd_status[1], fd_status[2], fd_status[3],
213 fd_status[4], fd_status[5], fd_status[6] );
214 if (numretry) goto retry;
215 return -1;
216 }
217 if (func == F_READ)
218 bcopy(bounce,address,FDBLK);
219 return 0;
220}
221
222/****************************************************************************/
223/* fdc in/out */
224/****************************************************************************/
225int
226in_fdc()
227{
228 int i;
229 while ((i = inb(fdc+fdsts) & 192) != 192) if (i == 128) return -1;
230 return inb(0x3f5);
231}
232
233dump_stat()
234{
235 int i;
236 for(i=0;i<7;i++) {
237 fd_status[i] = in_fdc();
238 if (fd_status[i] < 0) break;
239 }
240#ifdef FDDEBUGx
241printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
242 fd_status[0], fd_status[1], fd_status[2], fd_status[3],
243 fd_status[4], fd_status[5], fd_status[6] );
244#endif
245}
246
247set_intr()
248{
249 /* initialize 8259's */
250 outb(0x20,0x11);
251 outb(0x21,32);
252 outb(0x21,4);
253 outb(0x21,1);
254 outb(0x21,0x0f); /* turn on int 6 */
255
256/*
257 outb(0xa0,0x11);
258 outb(0xa1,40);
259 outb(0xa1,2);
260 outb(0xa1,1);
261 outb(0xa1,0xff); */
262
263}
264
265
266
267waitio()
268{
269char c;
270int n;
271
272 do
273 outb(0x20,0xc); /* read polled interrupt */
274 while ((c=inb(0x20))&0x7f != 6); /* wait for int */
275 outb(0x20,0x20);
276}
277
278out_fdc(x)
279int x;
280{
281 int r;
282 do {
283 r = (inb(fdc+fdsts) & 192);
284 if (r==128) break;
285 if (r==192) {
286 dump_stat(); /* error: direction. eat up output */
287 }
288 } while (1);
289 outb(0x3f5,x&0xFF);
290}
291
292
293/****************************************************************************/
294/* fdopen/fdclose */
295/****************************************************************************/
296fdopen(io)
297 register struct iob *io;
298{
299 int unit, type, i;
300 struct fd_type *ft;
301 char buf[512];
302
303 unit = io->i_unit;
304 /* type = io->i_part; */
305 io->i_boff = 0; /* no disklabels -- tar/dump wont work */
306#ifdef FDDEBUG
307 printf("fdopen %d %d ", unit, type);
308#endif
309 ft = &fd_types[0];
310 fd_drive = unit;
311
312 set_intr(); /* init intr cont */
313
314 /* Try a reset, keep motor on */
315 outb(0x3f2,0);
316 for(i=0; i < 100000; i++);
317 outb(0x3f2,unit | (unit ? 32 : 16) );
318 for(i=0; i < 100000; i++);
319 outb(0x3f2,unit | 0xC | (unit ? 32 : 16) );
320 outb(0x3f7,ft->trans);
321 fd_motor = 1;
322
323 waitio();
324
325 out_fdc(3); /* specify command */
326 out_fdc(0xDF);
327 out_fdc(2);
328
329 out_fdc(7); /* Recalibrate Function */
330 out_fdc(unit);
331
332 waitio();
333 probetype = 1;
334 for (fd_type = 0; fd_type < sizeof(fd_types)/sizeof(fd_types[0]);
335 fd_type++, ft++) {
336 /*for(i=0; i < 100000; i++);
337 outb(0x3f7,ft->trans);
338 for(i=0; i < 100000; i++);*/
339 if (fdio(F_READ, unit, ft->sectrac-1, buf) >= 0){
340 probetype = 0;
341 return(0);
342 }
343 }
344 printf("failed fdopen");
345 return(-1);
346}
347
348
349/****************************************************************************/
350/* fd_dma */
351/* set up DMA read/write operation and virtual address addr for nbytes */
352/****************************************************************************/
353fd_dma(read,addr,nbytes)
354int read;
355unsigned long addr;
356int nbytes;
357{
358 /* Set read/write bytes */
359 if (read) {
360 outb(0xC,0x46); outb(0xB,0x46);
361 } else {
362 outb(0xC,0x4A); outb(0xB,0x4A);
363 }
364 /* Send start address */
365 outb(0x4,addr & 0xFF);
366 outb(0x4,(addr>>8) & 0xFF);
367 outb(0x81,(addr>>16) & 0xFF);
368 /* Send count */
369 nbytes--;
370 outb(0x5,nbytes & 0xFF);
371 outb(0x5,(nbytes>>8) & 0xFF);
372 /* set channel 2 */
373 outb(0x0A,2);
374}
375