fd.c revision 1.9 1 1.9 cegger /* $NetBSD: fd.c,v 1.9 2009/03/18 10:22:27 cegger Exp $ */
2 1.1 sakamoto
3 1.1 sakamoto /*-
4 1.5 keihan * Copyright (C) 1997-1998 Kazuki Sakamoto (sakamoto (at) NetBSD.org)
5 1.1 sakamoto * All rights reserved.
6 1.1 sakamoto *
7 1.1 sakamoto * Floppy Disk Drive standalone device driver
8 1.1 sakamoto *
9 1.1 sakamoto * Redistribution and use in source and binary forms, with or without
10 1.1 sakamoto * modification, are permitted provided that the following conditions
11 1.1 sakamoto * are met:
12 1.1 sakamoto * 1. Redistributions of source code must retain the above copyright
13 1.1 sakamoto * notice, this list of conditions and the following disclaimer.
14 1.1 sakamoto * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 sakamoto * notice, this list of conditions and the following disclaimer in the
16 1.1 sakamoto * documentation and/or other materials provided with the distribution.
17 1.1 sakamoto * 3. All advertising materials mentioning features or use of this software
18 1.1 sakamoto * must display the following acknowledgement:
19 1.1 sakamoto * This product includes software developed by Kazuki Sakamoto.
20 1.1 sakamoto * 4. The name of the author may not be used to endorse or promote products
21 1.1 sakamoto * derived from this software without specific prior written permission.
22 1.1 sakamoto *
23 1.1 sakamoto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 1.1 sakamoto * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 1.1 sakamoto * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 1.1 sakamoto * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 1.1 sakamoto * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 1.1 sakamoto * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 1.1 sakamoto * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 1.1 sakamoto * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 1.1 sakamoto * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 1.1 sakamoto * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 1.1 sakamoto */
34 1.1 sakamoto
35 1.1 sakamoto #include <sys/param.h>
36 1.6 junyoung #include <lib/libsa/stand.h>
37 1.3 sakamoto #include "boot.h"
38 1.1 sakamoto
39 1.1 sakamoto /*---------------------------------------------------------------------------*
40 1.1 sakamoto * Floppy Disk Controller Define *
41 1.1 sakamoto *---------------------------------------------------------------------------*/
42 1.3 sakamoto /* Floppy Disk Controller Registers */
43 1.1 sakamoto int FDC_PORT[] = { /* fdc base I/O port */
44 1.1 sakamoto 0x3f0, /* primary */
45 1.1 sakamoto };
46 1.3 sakamoto #define FDC_DOR(x) (FDC_PORT[x] + 0x2) /* motor drive control bits */
47 1.3 sakamoto #define FDC_STATUS(x) (FDC_PORT[x] + 0x4) /* fdc main status register */
48 1.3 sakamoto #define FDC_DATA(x) (FDC_PORT[x] + 0x5) /* fdc data register */
49 1.3 sakamoto #define FDC_RATE(x) (FDC_PORT[x] + 0x7) /* transfer rate register */
50 1.1 sakamoto
51 1.1 sakamoto #define FDC_IRQ 6
52 1.1 sakamoto #define FD_DMA_CHAN 2
53 1.1 sakamoto
54 1.1 sakamoto /* fdc main status register */
55 1.1 sakamoto #define RQM 0x80 /* the host can transfer data if set */
56 1.1 sakamoto #define DIO 0x40 /* direction of data transfer. write required if set */
57 1.3 sakamoto #define NON_DMA 0x20 /* fdc have date for transfer in non dma mode */
58 1.1 sakamoto #define CMD_BUSY 0x10 /* command busy if set */
59 1.1 sakamoto
60 1.1 sakamoto /* fdc result status */
61 1.1 sakamoto #define ST0_IC_MASK 0xc0 /* interrupt code 00:normal terminate */
62 1.1 sakamoto #define ST1_EN 0x80 /* end of cylinder */
63 1.1 sakamoto
64 1.1 sakamoto /* fdc digtal output register */
65 1.1 sakamoto #define DOR_DMAEN 0x08 /* DRQ, nDACK, TC and FINTR output enable */
66 1.1 sakamoto #define DOR_RESET 0x04 /* fdc software reset */
67 1.1 sakamoto
68 1.1 sakamoto /* fdc command */
69 1.1 sakamoto #define CMD_RECALIBRATE 0x07 /* recalibrate */
70 1.1 sakamoto #define CMD_SENSE_INT 0x08 /* sense interrupt status */
71 1.1 sakamoto #define CMD_DRV_SENSE 0x04 /* sense drive status */
72 1.1 sakamoto #define CMD_SEEK 0x0f /* seek */
73 1.1 sakamoto #define CMD_FORMAT 0x4d /* format */
74 1.1 sakamoto #define CMD_READ 0x46 /* read e6 */
75 1.1 sakamoto #define CMD_WRITE 0xc5 /* write */
76 1.1 sakamoto #define CMD_VERIFY 0xf6 /* verify */
77 1.1 sakamoto #define CMD_READID 0x4a /* readID */
78 1.1 sakamoto #define CMD_SPECIFY 0x03 /* specify */
79 1.1 sakamoto #define CMD_CONFIG 0x13 /* config */
80 1.1 sakamoto #define CMD_VERSION 0x10 /* version */
81 1.1 sakamoto
82 1.1 sakamoto /* command specify value */
83 1.1 sakamoto #define SPECIFY1 ((0x0d<<4)|0x0f)
84 1.1 sakamoto #define SPECIFY2 ((0x01<<1)|0) /* DMA MODE */
85 1.1 sakamoto
86 1.1 sakamoto /* fdc result */
87 1.1 sakamoto #define STATUS_MAX 16 /* result status max number */
88 1.3 sakamoto #define RESULT_VERSION 0x90 /* enhanced controller */
89 1.1 sakamoto #define RESULT_SEEK 0x20 /* seek & recalibrate complete flag on status0 */
90 1.1 sakamoto
91 1.1 sakamoto /*---------------------------------------------------------------------------*
92 1.1 sakamoto * Floppy Disk Type Define *
93 1.1 sakamoto *---------------------------------------------------------------------------*/
94 1.1 sakamoto struct fdd_type {
95 1.1 sakamoto int seccount; /* sector per track */
96 1.1 sakamoto int secsize; /* byte per sector (uPD765 paramater) */
97 1.1 sakamoto int datalen; /* data length */
98 1.1 sakamoto int gap; /* gap */
99 1.1 sakamoto int gaplen; /* gap length */
100 1.1 sakamoto int cylinder; /* track per media */
101 1.1 sakamoto int maxseccount; /* media max sector count */
102 1.1 sakamoto int step; /* seek step */
103 1.1 sakamoto int rate; /* drive rate (250 or 500kbps) */
104 1.1 sakamoto int heads; /* heads */
105 1.1 sakamoto int f_gap; /* format gap */
106 1.1 sakamoto int mselect; /* drive mode select */
107 1.1 sakamoto char *type_name; /* media type name */
108 1.1 sakamoto };
109 1.1 sakamoto typedef struct fdd_type FDDTYPE;
110 1.1 sakamoto
111 1.3 sakamoto #define FDTYPE_MAX 5
112 1.1 sakamoto FDDTYPE fdd_types[FDTYPE_MAX] = {
113 1.1 sakamoto { 18,2,0xff,0x1b,0x54,80,2880,1,0,2,0x6c,0,"2HQ" }, /* 2HD (PC/AT) */
114 1.1 sakamoto { 8,3,0xff,0x35,0x74,77,1232,1,0,2,0x54,1,"2HD" }, /* 2HD (98) */
115 1.1 sakamoto { 15,2,0xff,0x1b,0x54,80,2400,1,0,2,0x54,1,"2HC" }, /* 2HC */
116 1.1 sakamoto { 9,2,0xff,0x23,0x50,80,1440,1,2,2,0x50,1,"2DD9" },/* 2DD 9 sector */
117 1.1 sakamoto { 8,2,0xff,0x3a,0x50,80,1280,1,2,2,0x50,1,"2DD8" },/* 2DD 8 sector */
118 1.1 sakamoto };
119 1.1 sakamoto
120 1.1 sakamoto int fdsectors[] = {128, 256, 512, 1024, 2048, 4096};
121 1.1 sakamoto #define SECTOR_MAX 4096
122 1.1 sakamoto #define FDBLK (fdsectors[un->un_type->secsize])
123 1.1 sakamoto
124 1.1 sakamoto #define START_CYL 0
125 1.1 sakamoto #define START_SECTOR 1
126 1.1 sakamoto
127 1.1 sakamoto #define DELAY(x) delay(100000 * x) /* about 100ms */
128 1.3 sakamoto #define INT_TIMEOUT 3000000
129 1.1 sakamoto
130 1.1 sakamoto /*---------------------------------------------------------------------------*
131 1.1 sakamoto * FDC Device Driver Define *
132 1.1 sakamoto *---------------------------------------------------------------------------*/
133 1.1 sakamoto #define CTLR_MAX 1
134 1.1 sakamoto #define UNIT_MAX 2
135 1.1 sakamoto
136 1.1 sakamoto struct fd_unit {
137 1.1 sakamoto int ctlr;
138 1.1 sakamoto int unit;
139 1.1 sakamoto int part;
140 1.1 sakamoto u_int un_flags; /* unit status flag */
141 1.1 sakamoto int stat[STATUS_MAX]; /* result code */
142 1.1 sakamoto FDDTYPE *un_type; /* floppy type (pointer) */
143 1.1 sakamoto };
144 1.1 sakamoto typedef struct fd_unit FD_UNIT;
145 1.1 sakamoto FD_UNIT fd_unit[CTLR_MAX][UNIT_MAX];
146 1.1 sakamoto
147 1.3 sakamoto /*
148 1.1 sakamoto * un_flags flags
149 1.1 sakamoto */
150 1.3 sakamoto #define INT_ALIVE 0x00000001 /* Device is Alive and Available */
151 1.3 sakamoto #define INT_READY 0x00000002 /* Device is Ready */
152 1.3 sakamoto #define INT_BUSY 0x00000004 /* Device is busy */
153 1.1 sakamoto
154 1.1 sakamoto /*---------------------------------------------------------------------------*
155 1.1 sakamoto * Misc define *
156 1.1 sakamoto *---------------------------------------------------------------------------*/
157 1.1 sakamoto #define TIMEOUT 10000000
158 1.1 sakamoto #define ND_TIMEOUT 10000000
159 1.1 sakamoto
160 1.3 sakamoto #define SUCCESS 0
161 1.3 sakamoto #define FAIL -1
162 1.1 sakamoto
163 1.1 sakamoto /*
164 1.1 sakamoto * function declaration
165 1.1 sakamoto */
166 1.8 kiyohara int fdinit(FD_UNIT *);
167 1.8 kiyohara int fdopen(struct open_file *, int, int, int);
168 1.8 kiyohara int fdclose(struct open_file *);
169 1.8 kiyohara int fdioctl(struct open_file *, u_long, void *);
170 1.8 kiyohara int fdstrategy(void *, int, daddr_t, size_t, void *, size_t *);
171 1.8 kiyohara int fdc_out(int, int);
172 1.8 kiyohara int fdc_in(int, u_char *);
173 1.8 kiyohara int fdc_intr_wait(void);
174 1.8 kiyohara int fd_check(FD_UNIT *);
175 1.8 kiyohara void motor_on(int, int);
176 1.8 kiyohara void motor_off(int, int);
177 1.8 kiyohara void fdReset(int);
178 1.8 kiyohara void fdRecalibrate(int, int);
179 1.8 kiyohara void fdSpecify(int);
180 1.8 kiyohara void fdDriveStatus(int, int, int, int *);
181 1.8 kiyohara int fdSeek(int, int, int);
182 1.8 kiyohara int fdSenseInt(int, int *);
183 1.8 kiyohara int fdReadWrite(FD_UNIT *, int, int, int, int, u_char *);
184 1.8 kiyohara void irq_init(void);
185 1.8 kiyohara int irq_polling(int, int);
186 1.8 kiyohara void dma_setup(u_char *, int, int, int);
187 1.8 kiyohara int dma_finished(int);
188 1.1 sakamoto
189 1.1 sakamoto /*===========================================================================*
190 1.1 sakamoto * fdinit *
191 1.1 sakamoto *===========================================================================*/
192 1.3 sakamoto int
193 1.8 kiyohara fdinit(FD_UNIT *un)
194 1.1 sakamoto {
195 1.1 sakamoto int ctlr = un->ctlr;
196 1.3 sakamoto u_char result;
197 1.1 sakamoto
198 1.1 sakamoto #if 0
199 1.1 sakamoto irq_init();
200 1.4 simonb #endif
201 1.1 sakamoto fdReset(ctlr);
202 1.3 sakamoto
203 1.1 sakamoto if (fdc_out(ctlr, CMD_VERSION) != SUCCESS) { /* version check */
204 1.3 sakamoto printf ("fdc%d:fatal error: CMD_VERSION cmd fail\n", ctlr);
205 1.1 sakamoto return (FAIL);
206 1.1 sakamoto }
207 1.1 sakamoto if (fdc_in(ctlr, &result) != SUCCESS) {
208 1.3 sakamoto printf ("fdc%d:fatal error: CMD_VERSION exec fail\n", ctlr);
209 1.1 sakamoto return (FAIL);
210 1.1 sakamoto }
211 1.3 sakamoto if (result != (u_char)RESULT_VERSION) {
212 1.3 sakamoto printf ("fdc%d:fatal error: unknown version fdc\n", ctlr);
213 1.1 sakamoto return (FAIL);
214 1.1 sakamoto }
215 1.1 sakamoto
216 1.1 sakamoto un->un_flags = INT_ALIVE;
217 1.1 sakamoto return (SUCCESS);
218 1.1 sakamoto }
219 1.1 sakamoto
220 1.1 sakamoto /*===========================================================================*
221 1.1 sakamoto * fdopen *
222 1.1 sakamoto *===========================================================================*/
223 1.3 sakamoto int
224 1.8 kiyohara fdopen(struct open_file *f, int ctlr, int unit, int part)
225 1.1 sakamoto {
226 1.1 sakamoto FD_UNIT *un;
227 1.8 kiyohara int *stat;
228 1.1 sakamoto
229 1.1 sakamoto if (ctlr >= CTLR_MAX)
230 1.1 sakamoto return (ENXIO);
231 1.1 sakamoto if (unit >= UNIT_MAX)
232 1.1 sakamoto return (ENXIO);
233 1.1 sakamoto un = &fd_unit[ctlr][unit];
234 1.8 kiyohara stat = un->stat;
235 1.1 sakamoto
236 1.1 sakamoto if (!(un->un_flags & INT_ALIVE)) {
237 1.1 sakamoto if (fdinit(un) != SUCCESS)
238 1.1 sakamoto return (ENXIO);
239 1.1 sakamoto }
240 1.1 sakamoto
241 1.1 sakamoto motor_on(ctlr, unit);
242 1.1 sakamoto
243 1.1 sakamoto fdRecalibrate(ctlr, unit);
244 1.1 sakamoto fdSenseInt(ctlr, stat);
245 1.1 sakamoto if (stat[1] != START_CYL) {
246 1.1 sakamoto printf("fdc%d: unit:%d recalibrate failed. status:0x%x cyl:%d\n",
247 1.1 sakamoto ctlr, unit, stat[0], stat[1]);
248 1.1 sakamoto motor_off(ctlr, unit);
249 1.1 sakamoto return (EIO);
250 1.1 sakamoto }
251 1.1 sakamoto
252 1.1 sakamoto if (fd_check(un) != SUCCESS) /* research disk type */
253 1.1 sakamoto return (EIO);
254 1.1 sakamoto
255 1.1 sakamoto f->f_devdata = (void *)un;
256 1.1 sakamoto return (SUCCESS);
257 1.1 sakamoto }
258 1.1 sakamoto
259 1.1 sakamoto /*===========================================================================*
260 1.1 sakamoto * fdclose *
261 1.1 sakamoto *===========================================================================*/
262 1.3 sakamoto int
263 1.8 kiyohara fdclose(struct open_file *f)
264 1.1 sakamoto {
265 1.1 sakamoto FD_UNIT *un = f->f_devdata;
266 1.1 sakamoto
267 1.1 sakamoto fdRecalibrate(un->ctlr, un->unit);
268 1.1 sakamoto fdSenseInt(un->ctlr, un->stat);
269 1.1 sakamoto motor_off(un->ctlr, un->unit);
270 1.1 sakamoto un->un_flags = 0;
271 1.1 sakamoto return (SUCCESS);
272 1.1 sakamoto }
273 1.1 sakamoto
274 1.1 sakamoto /*===========================================================================*
275 1.1 sakamoto * fdioctl *
276 1.1 sakamoto *===========================================================================*/
277 1.3 sakamoto int
278 1.8 kiyohara fdioctl(struct open_file *f, u_long cmd, void *arg)
279 1.1 sakamoto {
280 1.8 kiyohara
281 1.3 sakamoto switch (cmd) {
282 1.1 sakamoto default:
283 1.1 sakamoto return (EIO);
284 1.1 sakamoto }
285 1.1 sakamoto
286 1.1 sakamoto return (SUCCESS);
287 1.1 sakamoto }
288 1.1 sakamoto
289 1.1 sakamoto /*===========================================================================*
290 1.1 sakamoto * fdstrategy *
291 1.1 sakamoto *===========================================================================*/
292 1.3 sakamoto int
293 1.8 kiyohara fdstrategy(void *devdata, int func, daddr_t blk, size_t size, void *buf,
294 1.8 kiyohara size_t *rsize)
295 1.1 sakamoto {
296 1.1 sakamoto int sectrac, cyl, head, sec;
297 1.1 sakamoto FD_UNIT *un = devdata;
298 1.1 sakamoto int ctlr = un->ctlr;
299 1.1 sakamoto int unit = un->unit;
300 1.1 sakamoto int *stat = un->stat;
301 1.1 sakamoto long nblock, blknum;
302 1.1 sakamoto int fd_skip = 0;
303 1.8 kiyohara u_char *cbuf = (u_char *)buf;
304 1.1 sakamoto
305 1.3 sakamoto if (un->un_flags & INT_BUSY) {
306 1.1 sakamoto return (ENXIO);
307 1.1 sakamoto }
308 1.1 sakamoto fdDriveStatus(ctlr, unit, 0, stat);
309 1.1 sakamoto
310 1.1 sakamoto nblock = un->un_type->maxseccount;
311 1.1 sakamoto sectrac = un->un_type->seccount; /* sector per track */
312 1.1 sakamoto *rsize = 0;
313 1.1 sakamoto
314 1.1 sakamoto while (fd_skip < size) {
315 1.1 sakamoto blknum = (u_long)blk * DEV_BSIZE/FDBLK + fd_skip/FDBLK;
316 1.1 sakamoto cyl = blknum / (sectrac * 2);
317 1.1 sakamoto fdSeek(ctlr, unit, cyl);
318 1.1 sakamoto fdSenseInt(ctlr, stat);
319 1.1 sakamoto if (!(stat[0] & RESULT_SEEK)) {
320 1.1 sakamoto printf("fdc%d: unit:%d seek failed."
321 1.1 sakamoto "status:0x%x cyl:%d pcyl:%d\n",
322 1.1 sakamoto ctlr, unit, stat[0], cyl, stat[1]);
323 1.1 sakamoto goto bad;
324 1.1 sakamoto }
325 1.1 sakamoto
326 1.1 sakamoto sec = blknum % (sectrac * 2);
327 1.1 sakamoto head = sec / sectrac;
328 1.1 sakamoto sec = sec % sectrac + 1;
329 1.1 sakamoto
330 1.1 sakamoto if (fdReadWrite(un, func, cyl, head, sec, cbuf) == FAIL) {
331 1.1 sakamoto printf("fdc%d: unit%d fdReadWrite error [%s]\n",
332 1.1 sakamoto ctlr, unit, (func==F_READ?"READ":"WRITE"));
333 1.1 sakamoto goto bad;
334 1.1 sakamoto }
335 1.1 sakamoto
336 1.1 sakamoto *rsize += FDBLK;
337 1.1 sakamoto cbuf += FDBLK;
338 1.1 sakamoto fd_skip += FDBLK;
339 1.1 sakamoto }
340 1.1 sakamoto return (SUCCESS);
341 1.1 sakamoto
342 1.1 sakamoto bad:
343 1.3 sakamoto return (FAIL);
344 1.1 sakamoto }
345 1.1 sakamoto
346 1.1 sakamoto /*===========================================================================*
347 1.1 sakamoto * fd_check *
348 1.1 sakamoto *===========================================================================*/
349 1.1 sakamoto /*
350 1.1 sakamoto * this function is Check floppy disk Type
351 1.1 sakamoto */
352 1.1 sakamoto int
353 1.8 kiyohara fd_check(FD_UNIT *un)
354 1.1 sakamoto {
355 1.1 sakamoto int ctlr = un->ctlr;
356 1.1 sakamoto int unit = un->unit;
357 1.1 sakamoto int *stat = un->stat;
358 1.1 sakamoto int type;
359 1.1 sakamoto static u_char sec_buff[SECTOR_MAX];
360 1.1 sakamoto
361 1.1 sakamoto un->un_type = (FDDTYPE *)FAIL;
362 1.1 sakamoto for (type = 0; type < FDTYPE_MAX; type++) {
363 1.1 sakamoto un->un_type = &fdd_types[type];
364 1.1 sakamoto
365 1.1 sakamoto /* try read start sector */
366 1.1 sakamoto outb(FDC_RATE(ctlr), un->un_type->rate); /* rate set */
367 1.1 sakamoto fdSpecify(ctlr);
368 1.1 sakamoto fdSeek(ctlr, unit, START_CYL);
369 1.1 sakamoto fdSenseInt(ctlr, stat);
370 1.1 sakamoto if (!(stat[0] & RESULT_SEEK) || stat[1] != START_CYL) {
371 1.1 sakamoto printf("fdc%d: unit:%d seek failed. status:0x%x\n",
372 1.1 sakamoto ctlr, unit, stat[0]);
373 1.1 sakamoto goto bad;
374 1.1 sakamoto }
375 1.1 sakamoto if (fdReadWrite(un, F_READ,
376 1.1 sakamoto START_CYL, 0, START_SECTOR, sec_buff) == FAIL) {
377 1.1 sakamoto continue; /* bad disk type */
378 1.1 sakamoto }
379 1.1 sakamoto break;
380 1.1 sakamoto }
381 1.1 sakamoto if (un->un_type == (FDDTYPE *)FAIL) {
382 1.1 sakamoto printf("fdc%d: unit:%d check disk type failed.\n",
383 1.1 sakamoto ctlr, unit);
384 1.1 sakamoto goto bad;
385 1.1 sakamoto }
386 1.1 sakamoto return (SUCCESS);
387 1.1 sakamoto bad:
388 1.1 sakamoto return (FAIL);
389 1.1 sakamoto }
390 1.1 sakamoto
391 1.1 sakamoto /*
392 1.1 sakamoto * for FDC routines.
393 1.1 sakamoto */
394 1.1 sakamoto /*===========================================================================*
395 1.1 sakamoto * fdc_out *
396 1.1 sakamoto *===========================================================================*/
397 1.1 sakamoto int
398 1.8 kiyohara fdc_out(int ctlr, int cmd)
399 1.1 sakamoto {
400 1.1 sakamoto volatile int status;
401 1.1 sakamoto int time_out;
402 1.1 sakamoto
403 1.1 sakamoto time_out = TIMEOUT;
404 1.1 sakamoto while (((status = inb(FDC_STATUS(ctlr))) & (RQM | DIO))
405 1.1 sakamoto != (RQM | 0) && time_out-- > 0);
406 1.1 sakamoto if (time_out <= 0) {
407 1.3 sakamoto printf("fdc_out: timeout status = 0x%x\n", status);
408 1.1 sakamoto return (FAIL);
409 1.1 sakamoto }
410 1.1 sakamoto
411 1.1 sakamoto outb(FDC_DATA(ctlr), cmd);
412 1.1 sakamoto
413 1.1 sakamoto return (SUCCESS);
414 1.1 sakamoto }
415 1.1 sakamoto
416 1.1 sakamoto /*===========================================================================*
417 1.1 sakamoto * fdc_in *
418 1.1 sakamoto *===========================================================================*/
419 1.1 sakamoto int
420 1.8 kiyohara fdc_in(int ctlr, u_char *data)
421 1.1 sakamoto {
422 1.1 sakamoto volatile int status;
423 1.1 sakamoto int time_out;
424 1.1 sakamoto
425 1.1 sakamoto time_out = TIMEOUT;
426 1.1 sakamoto while ((status = inb(FDC_STATUS(ctlr)) & (RQM | DIO))
427 1.1 sakamoto != (RQM | DIO) && time_out-- > 0) {
428 1.1 sakamoto if (status == RQM) {
429 1.1 sakamoto printf("fdc_in:error:ready for output\n");
430 1.1 sakamoto return (FAIL);
431 1.1 sakamoto }
432 1.1 sakamoto }
433 1.1 sakamoto
434 1.1 sakamoto if (time_out <= 0) {
435 1.1 sakamoto printf("fdc_in:input ready timeout\n");
436 1.1 sakamoto return (FAIL);
437 1.1 sakamoto }
438 1.1 sakamoto
439 1.3 sakamoto if (data) *data = (u_char)inb(FDC_DATA(ctlr));
440 1.1 sakamoto
441 1.1 sakamoto return (SUCCESS);
442 1.1 sakamoto }
443 1.1 sakamoto
444 1.1 sakamoto /*===========================================================================*
445 1.1 sakamoto * fdc_intr_wait *
446 1.1 sakamoto *===========================================================================*/
447 1.1 sakamoto int
448 1.9 cegger fdc_intr_wait(void)
449 1.1 sakamoto {
450 1.8 kiyohara
451 1.3 sakamoto return (irq_polling(FDC_IRQ, INT_TIMEOUT)); /* wait interrupt */
452 1.1 sakamoto }
453 1.1 sakamoto
454 1.1 sakamoto /*===========================================================================*
455 1.1 sakamoto * fdc command function *
456 1.1 sakamoto *===========================================================================*/
457 1.1 sakamoto void
458 1.8 kiyohara motor_on(int ctlr, int unit)
459 1.1 sakamoto {
460 1.8 kiyohara
461 1.1 sakamoto outb(FDC_DOR(ctlr), DOR_RESET | DOR_DMAEN | unit
462 1.1 sakamoto | (1 << (unit + 4))); /* reset & unit motor on */
463 1.1 sakamoto DELAY(1); /* wait 100msec */
464 1.1 sakamoto }
465 1.1 sakamoto
466 1.1 sakamoto void
467 1.8 kiyohara motor_off(int ctlr, int unit)
468 1.1 sakamoto {
469 1.8 kiyohara
470 1.8 kiyohara outb(FDC_DOR(ctlr), DOR_RESET); /* reset & motor off */
471 1.3 sakamoto if (fdc_intr_wait() == FAIL) /* wait interrupt */
472 1.1 sakamoto printf("fdc: motor off failed.\n");
473 1.1 sakamoto }
474 1.1 sakamoto
475 1.1 sakamoto void
476 1.8 kiyohara fdReset(int ctlr)
477 1.1 sakamoto {
478 1.8 kiyohara
479 1.1 sakamoto outb(FDC_DOR(ctlr), 0); /* fdc reset */
480 1.1 sakamoto DELAY(3);
481 1.1 sakamoto outb(FDC_DOR(ctlr), DOR_RESET);
482 1.1 sakamoto DELAY(8);
483 1.1 sakamoto }
484 1.1 sakamoto
485 1.1 sakamoto void
486 1.8 kiyohara fdRecalibrate(int ctlr, int unit)
487 1.1 sakamoto {
488 1.8 kiyohara
489 1.1 sakamoto fdc_out(ctlr, CMD_RECALIBRATE);
490 1.1 sakamoto fdc_out(ctlr, unit);
491 1.1 sakamoto
492 1.1 sakamoto if (fdc_intr_wait() == FAIL) /* wait interrupt */
493 1.1 sakamoto printf("fdc: recalibrate Timeout\n");
494 1.1 sakamoto }
495 1.1 sakamoto
496 1.1 sakamoto void
497 1.8 kiyohara fdSpecify(int ctlr)
498 1.1 sakamoto {
499 1.8 kiyohara
500 1.1 sakamoto fdc_out(ctlr, CMD_SPECIFY);
501 1.1 sakamoto fdc_out(ctlr, SPECIFY1);
502 1.1 sakamoto fdc_out(ctlr, SPECIFY2);
503 1.1 sakamoto }
504 1.1 sakamoto
505 1.1 sakamoto void
506 1.8 kiyohara fdDriveStatus(int ctlr, register int unit, register int head,
507 1.8 kiyohara register int *stat)
508 1.1 sakamoto {
509 1.3 sakamoto u_char result;
510 1.1 sakamoto
511 1.1 sakamoto fdc_out(ctlr, CMD_DRV_SENSE);
512 1.1 sakamoto fdc_out(ctlr, (head << 2) | unit);
513 1.1 sakamoto fdc_in(ctlr, &result);
514 1.1 sakamoto *stat = (int)(result & 0xff);
515 1.1 sakamoto }
516 1.1 sakamoto
517 1.1 sakamoto int
518 1.8 kiyohara fdSeek(int ctlr, int unit, int cyl)
519 1.1 sakamoto {
520 1.1 sakamoto int ret_val = 0;
521 1.1 sakamoto
522 1.1 sakamoto fdc_out(ctlr, CMD_SEEK);
523 1.1 sakamoto fdc_out(ctlr, unit);
524 1.1 sakamoto fdc_out(ctlr, cyl);
525 1.1 sakamoto
526 1.3 sakamoto if (fdc_intr_wait() == FAIL) { /* wait interrupt */
527 1.1 sakamoto printf("fdc: fdSeek Timeout\n");
528 1.1 sakamoto ret_val = FAIL;
529 1.1 sakamoto }
530 1.1 sakamoto
531 1.1 sakamoto return(ret_val);
532 1.1 sakamoto }
533 1.1 sakamoto
534 1.1 sakamoto int
535 1.8 kiyohara fdSenseInt(int ctlr, int *stat)
536 1.1 sakamoto {
537 1.3 sakamoto u_char result;
538 1.1 sakamoto
539 1.1 sakamoto fdc_out(ctlr, CMD_SENSE_INT);
540 1.1 sakamoto
541 1.1 sakamoto fdc_in(ctlr, &result);
542 1.1 sakamoto *stat++ = (int)(result & 0xff);
543 1.1 sakamoto fdc_in(ctlr, &result);
544 1.1 sakamoto *stat++ = (int)(result & 0xff);
545 1.1 sakamoto
546 1.3 sakamoto return (0);
547 1.1 sakamoto }
548 1.1 sakamoto
549 1.1 sakamoto int
550 1.8 kiyohara fdReadWrite(FD_UNIT *un, int func, int cyl, int head, int sec, u_char *adrs)
551 1.1 sakamoto {
552 1.1 sakamoto int i;
553 1.1 sakamoto int ctlr = un->ctlr;
554 1.1 sakamoto int unit = un->unit;
555 1.1 sakamoto int *stat = un->stat;
556 1.3 sakamoto u_char result;
557 1.1 sakamoto
558 1.1 sakamoto #if 0
559 1.1 sakamoto printf("%s:", (func == F_READ ? "READ" : "WRITE"));
560 1.1 sakamoto printf("cyl = %d", cyl);
561 1.1 sakamoto printf("head = %d", head);
562 1.1 sakamoto printf("sec = %d", sec);
563 1.1 sakamoto printf("secsize = %d", un->un_type->secsize);
564 1.1 sakamoto printf("seccount = %d", un->un_type->seccount);
565 1.1 sakamoto printf("gap = %d", un->un_type->gap);
566 1.1 sakamoto printf("datalen = %d\n", un->un_type->datalen);
567 1.1 sakamoto #endif
568 1.1 sakamoto
569 1.1 sakamoto dma_setup(adrs, FDBLK, func, FD_DMA_CHAN);
570 1.1 sakamoto fdc_out(ctlr, (func == F_READ ? CMD_READ : CMD_WRITE));
571 1.1 sakamoto fdc_out(ctlr, (head<<2) | unit);
572 1.1 sakamoto fdc_out(ctlr, cyl); /* cyl */
573 1.1 sakamoto fdc_out(ctlr, head); /* head */
574 1.1 sakamoto fdc_out(ctlr, sec); /* sec */
575 1.1 sakamoto fdc_out(ctlr, un->un_type->secsize); /* secsize */
576 1.1 sakamoto fdc_out(ctlr, un->un_type->seccount); /* EOT (end of track) */
577 1.1 sakamoto fdc_out(ctlr, un->un_type->gap); /* GAP3 */
578 1.1 sakamoto fdc_out(ctlr, un->un_type->datalen); /* DTL (data length) */
579 1.1 sakamoto
580 1.1 sakamoto if (fdc_intr_wait() == FAIL) { /* wait interrupt */
581 1.1 sakamoto printf("fdc: DMA transfer Timeout\n");
582 1.1 sakamoto return (FAIL);
583 1.1 sakamoto }
584 1.1 sakamoto
585 1.1 sakamoto for (i = 0; i < 7; i++) {
586 1.1 sakamoto fdc_in(ctlr, &result);
587 1.1 sakamoto stat[i] = (int)(result & 0xff);
588 1.1 sakamoto }
589 1.1 sakamoto if (stat[0] & ST0_IC_MASK) { /* not normal terminate */
590 1.1 sakamoto if ((stat[1] & ~ST1_EN) || stat[2])
591 1.1 sakamoto goto bad;
592 1.1 sakamoto }
593 1.1 sakamoto if (!dma_finished(FD_DMA_CHAN)) {
594 1.1 sakamoto printf("DMA not finished\n");
595 1.1 sakamoto goto bad;
596 1.1 sakamoto }
597 1.1 sakamoto return (SUCCESS);
598 1.1 sakamoto
599 1.1 sakamoto bad:
600 1.1 sakamoto printf(" func: %s\n", (func == F_READ ? "F_READ" : "F_WRITE"));
601 1.1 sakamoto printf(" st0 = 0x%x\n", stat[0]);
602 1.1 sakamoto printf(" st1 = 0x%x\n", stat[1]);
603 1.1 sakamoto printf(" st2 = 0x%x\n", stat[2]);
604 1.1 sakamoto printf(" c = 0x%x\n", stat[3]);
605 1.1 sakamoto printf(" h = 0x%x\n", stat[4]);
606 1.1 sakamoto printf(" r = 0x%x\n", stat[5]);
607 1.1 sakamoto printf(" n = 0x%x\n", stat[6]);
608 1.1 sakamoto return (FAIL);
609 1.1 sakamoto }
610 1.1 sakamoto
611 1.1 sakamoto /*-----------------------------------------------------------------------
612 1.1 sakamoto * Interrupt Controller Operation Functions
613 1.1 sakamoto *-----------------------------------------------------------------------
614 1.1 sakamoto */
615 1.1 sakamoto
616 1.1 sakamoto /* 8259A interrupt controller register */
617 1.3 sakamoto #define INT_CTL0 0x20
618 1.3 sakamoto #define INT_CTL1 0x21
619 1.3 sakamoto #define INT2_CTL0 0xA0
620 1.3 sakamoto #define INT2_CTL1 0xA1
621 1.1 sakamoto
622 1.1 sakamoto #define CASCADE_IRQ 2
623 1.1 sakamoto
624 1.3 sakamoto #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
625 1.3 sakamoto #define ICW4_AT 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
626 1.1 sakamoto #define OCW3_PL 0x0e /* polling mode */
627 1.1 sakamoto #define OCW2_CLEAR 0x20 /* interrupt clear */
628 1.1 sakamoto
629 1.1 sakamoto /*
630 1.3 sakamoto * IRC programing sequence
631 1.1 sakamoto *
632 1.1 sakamoto * after reset
633 1.1 sakamoto * 1. ICW1 (write port:INT_CTL0 data:bit4=1)
634 1.1 sakamoto * 2. ICW2 (write port:INT_CTL1)
635 1.1 sakamoto * 3. ICW3 (write port:INT_CTL1)
636 1.1 sakamoto * 4. ICW4 (write port:INT_CTL1)
637 1.3 sakamoto *
638 1.1 sakamoto * after ICW
639 1.1 sakamoto * OCW1 (write port:INT_CTL1)
640 1.1 sakamoto * OCW2 (write port:INT_CTL0 data:bit3=0,bit4=0)
641 1.1 sakamoto * OCW3 (write port:INT_CTL0 data:bit3=1,bit4=0)
642 1.1 sakamoto *
643 1.1 sakamoto * IMR (read port:INT_CTL1)
644 1.1 sakamoto * IRR (read port:INT_CTL0) OCW3(bit1=1,bit0=0)
645 1.1 sakamoto * ISR (read port:INT_CTL0) OCW3(bit1=1,bit0=1)
646 1.1 sakamoto * PL (read port:INT_CTL0) OCW3(bit2=1,bit1=1)
647 1.1 sakamoto */
648 1.1 sakamoto
649 1.3 sakamoto u_int INT_MASK;
650 1.3 sakamoto u_int INT2_MASK;
651 1.1 sakamoto
652 1.1 sakamoto /*===========================================================================*
653 1.1 sakamoto * irq initialize *
654 1.1 sakamoto *===========================================================================*/
655 1.3 sakamoto void
656 1.9 cegger irq_init(void)
657 1.1 sakamoto {
658 1.1 sakamoto outb(INT_CTL0, ICW1_AT); /* ICW1 */
659 1.1 sakamoto outb(INT_CTL1, 0); /* ICW2 for master */
660 1.1 sakamoto outb(INT_CTL1, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
661 1.1 sakamoto outb(INT_CTL1, ICW4_AT); /* ICW4 */
662 1.1 sakamoto
663 1.1 sakamoto outb(INT_CTL1, (INT_MASK = ~(1 << CASCADE_IRQ)));
664 1.1 sakamoto /* IRQ mask(exclusive of cascade) */
665 1.1 sakamoto
666 1.1 sakamoto outb(INT2_CTL0, ICW1_AT); /* ICW1 */
667 1.1 sakamoto outb(INT2_CTL1, 8); /* ICW2 for slave */
668 1.1 sakamoto outb(INT2_CTL1, CASCADE_IRQ); /* ICW3 is slave nr */
669 1.1 sakamoto outb(INT2_CTL1, ICW4_AT); /* ICW4 */
670 1.1 sakamoto
671 1.1 sakamoto outb(INT2_CTL1, (INT2_MASK = ~0)); /* IRQ 8-15 mask */
672 1.1 sakamoto }
673 1.1 sakamoto
674 1.1 sakamoto /*===========================================================================*
675 1.1 sakamoto * irq polling check *
676 1.1 sakamoto *===========================================================================*/
677 1.3 sakamoto int
678 1.8 kiyohara irq_polling(int irq_no, int timeout)
679 1.1 sakamoto {
680 1.1 sakamoto int irc_no;
681 1.1 sakamoto int data;
682 1.1 sakamoto int ret;
683 1.1 sakamoto
684 1.1 sakamoto if (irq_no > 8) irc_no = 1;
685 1.1 sakamoto else irc_no = 0;
686 1.1 sakamoto
687 1.1 sakamoto outb(irc_no ? INT2_CTL1 : INT_CTL1, ~(1 << (irq_no >> (irc_no * 3))));
688 1.1 sakamoto
689 1.3 sakamoto while (--timeout > 0) {
690 1.1 sakamoto outb(irc_no ? INT2_CTL0 : INT_CTL0, OCW3_PL);
691 1.1 sakamoto /* set polling mode */
692 1.1 sakamoto data = inb(irc_no ? INT2_CTL0 : INT_CTL0);
693 1.1 sakamoto if (data & 0x80) { /* if interrupt request */
694 1.1 sakamoto if ((irq_no >> (irc_no * 3)) == (data & 0x7)) {
695 1.1 sakamoto ret = SUCCESS;
696 1.1 sakamoto break;
697 1.1 sakamoto }
698 1.1 sakamoto }
699 1.1 sakamoto }
700 1.1 sakamoto if (!timeout) ret = FAIL;
701 1.1 sakamoto
702 1.1 sakamoto if (irc_no) { /* interrupt clear */
703 1.1 sakamoto outb(INT2_CTL0, OCW2_CLEAR | (irq_no >> 3));
704 1.1 sakamoto outb(INT_CTL0, OCW2_CLEAR | CASCADE_IRQ);
705 1.1 sakamoto } else {
706 1.1 sakamoto outb(INT_CTL0, OCW2_CLEAR | irq_no);
707 1.1 sakamoto }
708 1.1 sakamoto
709 1.1 sakamoto outb(INT_CTL1, INT_MASK);
710 1.1 sakamoto outb(INT2_CTL1, INT2_MASK);
711 1.1 sakamoto
712 1.1 sakamoto return (ret);
713 1.1 sakamoto }
714 1.1 sakamoto
715 1.1 sakamoto /*---------------------------------------------------------------------------*
716 1.1 sakamoto * DMA Controller Define *
717 1.1 sakamoto *---------------------------------------------------------------------------*/
718 1.1 sakamoto /* DMA Controller Registers */
719 1.3 sakamoto #define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */
720 1.3 sakamoto #define DMA_LTOP 0x081 /* port for top low 8bit DMA addr(ch2) */
721 1.3 sakamoto #define DMA_HTOP 0x481 /* port for top high 8bit DMA addr(ch2) */
722 1.3 sakamoto #define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */
723 1.1 sakamoto #define DMA_DEVCON 0x008 /* DMA device control register */
724 1.1 sakamoto #define DMA_SR 0x008 /* DMA status register */
725 1.1 sakamoto #define DMA_RESET 0x00D /* DMA software reset register */
726 1.3 sakamoto #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flip-flop */
727 1.3 sakamoto #define DMA_MODE 0x00B /* DMA mode port */
728 1.3 sakamoto #define DMA_INIT 0x00A /* DMA init port */
729 1.1 sakamoto
730 1.3 sakamoto #define DMA_RESET_VAL 0x06
731 1.1 sakamoto /* DMA channel commands. */
732 1.3 sakamoto #define DMA_READ 0x46 /* DMA read opcode */
733 1.3 sakamoto #define DMA_WRITE 0x4A /* DMA write opcode */
734 1.1 sakamoto
735 1.1 sakamoto /*===========================================================================*
736 1.1 sakamoto * dma_setup *
737 1.1 sakamoto *===========================================================================*/
738 1.3 sakamoto void
739 1.8 kiyohara dma_setup(u_char *buf, int size, int func, int chan)
740 1.1 sakamoto {
741 1.3 sakamoto u_long pbuf = local_to_PCI((u_long)buf);
742 1.1 sakamoto
743 1.1 sakamoto #if 0
744 1.1 sakamoto outb(DMA_RESET, 0);
745 1.1 sakamoto DELAY(1);
746 1.1 sakamoto outb(DMA_DEVCON, 0x00);
747 1.3 sakamoto outb(DMA_INIT, DMA_RESET_VAL); /* reset the dma controller */
748 1.1 sakamoto #endif
749 1.1 sakamoto outb(DMA_MODE, func == F_READ ? DMA_READ : DMA_WRITE);
750 1.3 sakamoto outb(DMA_FLIPFLOP, 0); /* write anything to reset it */
751 1.1 sakamoto
752 1.1 sakamoto outb(DMA_ADDR, (int)pbuf >> 0);
753 1.1 sakamoto outb(DMA_ADDR, (int)pbuf >> 8);
754 1.1 sakamoto outb(DMA_LTOP, (int)pbuf >> 16);
755 1.1 sakamoto outb(DMA_HTOP, (int)pbuf >> 24);
756 1.1 sakamoto
757 1.1 sakamoto outb(DMA_COUNT, (size - 1) >> 0);
758 1.1 sakamoto outb(DMA_COUNT, (size - 1) >> 8);
759 1.3 sakamoto outb(DMA_INIT, chan); /* some sort of enable */
760 1.1 sakamoto }
761 1.1 sakamoto
762 1.1 sakamoto int
763 1.8 kiyohara dma_finished(int chan)
764 1.1 sakamoto {
765 1.8 kiyohara
766 1.1 sakamoto return ((inb(DMA_SR) & 0x0f) == (1 << chan));
767 1.1 sakamoto }
768