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