386BSD 0.1 development
[unix-history] / usr / src / sys.386bsd / i386 / stand / fd.c
CommitLineData
196ee958
WJ
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 *
36 * @(#)fd.c 7.3 (Berkeley) 5/25/91
37 */
38
39/****************************************************************************/
40/* standalone fd driver */
41/****************************************************************************/
42#include "param.h"
43#include "disklabel.h"
44#include "i386/isa/fdreg.h"
45#include "i386/isa/isa.h"
46#include "saio.h"
47
48#define NUMRETRY 10
49/*#define FDDEBUG*/
50
51#define NFD 2
52#define FDBLK 512
53
54extern struct disklabel disklabel;
55
56struct fd_type {
57 int sectrac; /* sectors per track */
58 int secsize; /* size code for sectors */
59 int datalen; /* data len when secsize = 0 */
60 int gap; /* gap len between sectors */
61 int tracks; /* total num of tracks */
62 int size; /* size of disk in sectors */
63 int steptrac; /* steps per cylinder */
64 int trans; /* transfer speed code */
65};
66
67struct fd_type fd_types[] = {
68 { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy */
69 { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy */
70 /* need 720K 3.5in here as well */
71#ifdef noway
72 { 9,2,0xFF,0x23,40,720,2,1 }, /* 360k floppy in 1.2meg drive */
73 { 9,2,0xFF,0x2A,40,720,1,1 }, /* 360k floppy in DD drive */
74#endif
75};
76
77
78/* state needed for current transfer */
79static int probetype;
80static int fd_type;
81static int fd_motor;
82static int fd_retry;
83static int fd_drive;
84static int fd_status[7];
85
86static int fdc = IO_FD1; /* floppy disk base */
87
88/* Make sure DMA buffer doesn't cross 64k boundary */
89char bounce[FDBLK];
90
91
92/****************************************************************************/
93/* fdstrategy */
94/****************************************************************************/
95int
96fdstrategy(io,func)
97register struct iob *io;
98int func;
99{
100 char *address;
101 long nblocks,blknum;
102 int unit, iosize;
103
104#ifdef FDDEBUG
105printf("fdstrat ");
106#endif
107 unit = io->i_unit;
108 /*fd_type = io->i_part;*/
109
110 /*
111 * Set up block calculations.
112 */
113 iosize = io->i_cc / FDBLK;
114 blknum = (unsigned long) io->i_bn * DEV_BSIZE / FDBLK;
115 nblocks = fd_types[fd_type].size /* disklabel.d_secperunit */;
116 if ((blknum + iosize > nblocks) || blknum < 0) {
117#ifdef nope
118 printf("bn = %d; sectors = %d; type = %d; fssize = %d ",
119 blknum, iosize, fd_type, nblocks);
120 printf("fdstrategy - I/O out of filesystem boundaries\n");
121#endif
122 return(-1);
123 }
124
125 address = io->i_ma;
126 while (iosize > 0) {
127/*printf("iosize %d ", iosize);*/
128 if (fdio(func, unit, blknum, address))
129 return(-1);
130 iosize--;
131 blknum++;
132 address += FDBLK;
133 }
134 return(io->i_cc);
135}
136
137int ccyl = -1;
138
139int
140fdio(func, unit, blknum, address)
141int func,unit,blknum;
142char *address;
143{
144 int i,j, cyl, sectrac,sec,head,numretry;
145 struct fd_type *ft;
146
147/*printf("fdio ");*/
148 ft = &fd_types[fd_type];
149
150 sectrac = ft->sectrac;
151 cyl = blknum / (sectrac*2);
152 numretry = NUMRETRY;
153
154 if (func == F_WRITE)
155 bcopy(address,bounce,FDBLK);
156
157retry:
158 if (ccyl != cyl) {
159 out_fdc(15); /* Seek function */
160 out_fdc(unit); /* Drive number */
161 out_fdc(cyl);
162
163 waitio();
164 }
165
166 out_fdc(0x8);
167 i = in_fdc(); j = in_fdc();
168 if (!(i&0x20) || (cyl != j)) {
169 numretry--;
170 ccyl = j;
171 if (numretry) goto retry;
172
173 printf("Seek error %d, req = %d, at = %d\n",i,cyl,j);
174 printf("unit %d, type %d, sectrac %d, blknum %d\n",
175 unit,fd_type,sectrac,blknum);
176
177 return -1;
178 }
179 ccyl = cyl;
180
181 /* set up transfer */
182 fd_dma(func == F_READ, bounce, FDBLK);
183 sec = blknum % (sectrac * 2) /*disklabel.d_secpercyl*/;
184 head = sec / sectrac;
185 sec = sec % sectrac + 1;
186#ifdef FDDEBUG
187 printf("sec %d hd %d cyl %d ", sec, head, cyl);
188#endif
189
190 if (func == F_READ) out_fdc(0xE6);/* READ */
191 else out_fdc(0xC5); /* WRITE */
192 out_fdc(head << 2 | fd_drive); /* head & unit */
193 out_fdc(cyl); /* track */
194 out_fdc(head);
195 out_fdc(sec); /* sector */
196 out_fdc(ft->secsize); /* sector size */
197 out_fdc(sectrac); /* sectors/track */
198 out_fdc(ft->gap); /* gap size */
199 out_fdc(ft->datalen); /* data length */
200
201 waitio();
202
203 for(i=0;i<7;i++) {
204 fd_status[i] = in_fdc();
205 }
206 if (fd_status[0]&0xF8) {
207 numretry--;
208
209 if (!probetype)
210 printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
211 fd_status[0], fd_status[1], fd_status[2], fd_status[3],
212 fd_status[4], fd_status[5], fd_status[6] );
213 if (numretry) goto retry;
214 return -1;
215 }
216 if (func == F_READ)
217 bcopy(bounce,address,FDBLK);
218 return 0;
219}
220
221/****************************************************************************/
222/* fdc in/out */
223/****************************************************************************/
224int
225in_fdc()
226{
227 int i;
228 while ((i = inb(fdc+fdsts) & 192) != 192) if (i == 128) return -1;
229 return inb(0x3f5);
230}
231
232dump_stat()
233{
234 int i;
235 for(i=0;i<7;i++) {
236 fd_status[i] = in_fdc();
237 if (fd_status[i] < 0) break;
238 }
239#ifdef FDDEBUGx
240printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
241 fd_status[0], fd_status[1], fd_status[2], fd_status[3],
242 fd_status[4], fd_status[5], fd_status[6] );
243#endif
244}
245
246set_intr()
247{
248 /* initialize 8259's */
249 outb(0x20,0x11);
250 outb(0x21,32);
251 outb(0x21,4);
252 outb(0x21,1);
253 outb(0x21,0x0f); /* turn on int 6 */
254
255/*
256 outb(0xa0,0x11);
257 outb(0xa1,40);
258 outb(0xa1,2);
259 outb(0xa1,1);
260 outb(0xa1,0xff); */
261
262}
263
264
265
266waitio()
267{
268char c;
269int n;
270
271 do
272 outb(0x20,0xc); /* read polled interrupt */
273 while ((c=inb(0x20))&0x7f != 6); /* wait for int */
274 outb(0x20,0x20);
275}
276
277out_fdc(x)
278int x;
279{
280 int r;
281 do {
282 r = (inb(fdc+fdsts) & 192);
283 if (r==128) break;
284 if (r==192) {
285 dump_stat(); /* error: direction. eat up output */
286 }
287 } while (1);
288 outb(0x3f5,x&0xFF);
289}
290
291
292/****************************************************************************/
293/* fdopen/fdclose */
294/****************************************************************************/
295fdopen(io)
296 register struct iob *io;
297{
298 int unit, type, i;
299 struct fd_type *ft;
300 char buf[512];
301
302 unit = io->i_unit;
303 /* type = io->i_part; */
304 io->i_boff = 0; /* no disklabels -- tar/dump wont work */
305#ifdef FDDEBUG
306 printf("fdopen %d %d ", unit, type);
307#endif
308 ft = &fd_types[0];
309 fd_drive = unit;
310
311 set_intr(); /* init intr cont */
312
313 /* Try a reset, keep motor on */
314 outb(0x3f2,0);
315 for(i=0; i < 100000; i++);
316 outb(0x3f2,unit | (unit ? 32 : 16) );
317 for(i=0; i < 100000; i++);
318 outb(0x3f2,unit | 0xC | (unit ? 32 : 16) );
319 outb(0x3f7,ft->trans);
320 fd_motor = 1;
321
322 waitio();
323
324 out_fdc(3); /* specify command */
325 out_fdc(0xDF);
326 out_fdc(2);
327
328 out_fdc(7); /* Recalibrate Function */
329 out_fdc(unit);
330
331 waitio();
332 probetype = 1;
333 for (fd_type = 0; fd_type < sizeof(fd_types)/sizeof(fd_types[0]);
334 fd_type++, ft++) {
335 /*for(i=0; i < 100000; i++);
336 outb(0x3f7,ft->trans);
337 for(i=0; i < 100000; i++);*/
338 if (fdio(F_READ, unit, ft->sectrac-1, buf) >= 0){
339 probetype = 0;
340 return(0);
341 }
342 }
343 printf("failed fdopen");
344 return(-1);
345}
346
347
348/****************************************************************************/
349/* fd_dma */
350/* set up DMA read/write operation and virtual address addr for nbytes */
351/****************************************************************************/
352fd_dma(read,addr,nbytes)
353int read;
354unsigned long addr;
355int nbytes;
356{
357 /* Set read/write bytes */
358 if (read) {
359 outb(0xC,0x46); outb(0xB,0x46);
360 } else {
361 outb(0xC,0x4A); outb(0xB,0x4A);
362 }
363 /* Send start address */
364 outb(0x4,addr & 0xFF);
365 outb(0x4,(addr>>8) & 0xFF);
366 outb(0x81,(addr>>16) & 0xFF);
367 /* Send count */
368 nbytes--;
369 outb(0x5,nbytes & 0xFF);
370 outb(0x5,(nbytes>>8) & 0xFF);
371 /* set channel 2 */
372 outb(0x0A,2);
373}
374