1 /* $NetBSD: fd.c,v 1.8 2008/05/26 16:28:39 kiyohara Exp $ */
4 * Copyright (C) 1997-1998 Kazuki Sakamoto (sakamoto@NetBSD.org)
7 * Floppy Disk Drive standalone device driver
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kazuki Sakamoto.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <lib/libsa/stand.h>
39 /*---------------------------------------------------------------------------*
40 * Floppy Disk Controller Define *
41 *---------------------------------------------------------------------------*/
42 /* Floppy Disk Controller Registers */
43 int FDC_PORT
[] = { /* fdc base I/O port */
46 #define FDC_DOR(x) (FDC_PORT[x] + 0x2) /* motor drive control bits */
47 #define FDC_STATUS(x) (FDC_PORT[x] + 0x4) /* fdc main status register */
48 #define FDC_DATA(x) (FDC_PORT[x] + 0x5) /* fdc data register */
49 #define FDC_RATE(x) (FDC_PORT[x] + 0x7) /* transfer rate register */
54 /* fdc main status register */
55 #define RQM 0x80 /* the host can transfer data if set */
56 #define DIO 0x40 /* direction of data transfer. write required if set */
57 #define NON_DMA 0x20 /* fdc have date for transfer in non dma mode */
58 #define CMD_BUSY 0x10 /* command busy if set */
60 /* fdc result status */
61 #define ST0_IC_MASK 0xc0 /* interrupt code 00:normal terminate */
62 #define ST1_EN 0x80 /* end of cylinder */
64 /* fdc digtal output register */
65 #define DOR_DMAEN 0x08 /* DRQ, nDACK, TC and FINTR output enable */
66 #define DOR_RESET 0x04 /* fdc software reset */
69 #define CMD_RECALIBRATE 0x07 /* recalibrate */
70 #define CMD_SENSE_INT 0x08 /* sense interrupt status */
71 #define CMD_DRV_SENSE 0x04 /* sense drive status */
72 #define CMD_SEEK 0x0f /* seek */
73 #define CMD_FORMAT 0x4d /* format */
74 #define CMD_READ 0x46 /* read e6 */
75 #define CMD_WRITE 0xc5 /* write */
76 #define CMD_VERIFY 0xf6 /* verify */
77 #define CMD_READID 0x4a /* readID */
78 #define CMD_SPECIFY 0x03 /* specify */
79 #define CMD_CONFIG 0x13 /* config */
80 #define CMD_VERSION 0x10 /* version */
82 /* command specify value */
83 #define SPECIFY1 ((0x0d<<4)|0x0f)
84 #define SPECIFY2 ((0x01<<1)|0) /* DMA MODE */
87 #define STATUS_MAX 16 /* result status max number */
88 #define RESULT_VERSION 0x90 /* enhanced controller */
89 #define RESULT_SEEK 0x20 /* seek & recalibrate complete flag on status0 */
91 /*---------------------------------------------------------------------------*
92 * Floppy Disk Type Define *
93 *---------------------------------------------------------------------------*/
95 int seccount
; /* sector per track */
96 int secsize
; /* byte per sector (uPD765 paramater) */
97 int datalen
; /* data length */
99 int gaplen
; /* gap length */
100 int cylinder
; /* track per media */
101 int maxseccount
; /* media max sector count */
102 int step
; /* seek step */
103 int rate
; /* drive rate (250 or 500kbps) */
104 int heads
; /* heads */
105 int f_gap
; /* format gap */
106 int mselect
; /* drive mode select */
107 char *type_name
; /* media type name */
109 typedef struct fdd_type FDDTYPE
;
112 FDDTYPE fdd_types
[FDTYPE_MAX
] = {
113 { 18,2,0xff,0x1b,0x54,80,2880,1,0,2,0x6c,0,"2HQ" }, /* 2HD (PC/AT) */
114 { 8,3,0xff,0x35,0x74,77,1232,1,0,2,0x54,1,"2HD" }, /* 2HD (98) */
115 { 15,2,0xff,0x1b,0x54,80,2400,1,0,2,0x54,1,"2HC" }, /* 2HC */
116 { 9,2,0xff,0x23,0x50,80,1440,1,2,2,0x50,1,"2DD9" },/* 2DD 9 sector */
117 { 8,2,0xff,0x3a,0x50,80,1280,1,2,2,0x50,1,"2DD8" },/* 2DD 8 sector */
120 int fdsectors
[] = {128, 256, 512, 1024, 2048, 4096};
121 #define SECTOR_MAX 4096
122 #define FDBLK (fdsectors[un->un_type->secsize])
125 #define START_SECTOR 1
127 #define DELAY(x) delay(100000 * x) /* about 100ms */
128 #define INT_TIMEOUT 3000000
130 /*---------------------------------------------------------------------------*
131 * FDC Device Driver Define *
132 *---------------------------------------------------------------------------*/
140 u_int un_flags
; /* unit status flag */
141 int stat
[STATUS_MAX
]; /* result code */
142 FDDTYPE
*un_type
; /* floppy type (pointer) */
144 typedef struct fd_unit FD_UNIT
;
145 FD_UNIT fd_unit
[CTLR_MAX
][UNIT_MAX
];
150 #define INT_ALIVE 0x00000001 /* Device is Alive and Available */
151 #define INT_READY 0x00000002 /* Device is Ready */
152 #define INT_BUSY 0x00000004 /* Device is busy */
154 /*---------------------------------------------------------------------------*
156 *---------------------------------------------------------------------------*/
157 #define TIMEOUT 10000000
158 #define ND_TIMEOUT 10000000
164 * function declaration
166 int fdinit(FD_UNIT
*);
167 int fdopen(struct open_file
*, int, int, int);
168 int fdclose(struct open_file
*);
169 int fdioctl(struct open_file
*, u_long
, void *);
170 int fdstrategy(void *, int, daddr_t
, size_t, void *, size_t *);
171 int fdc_out(int, int);
172 int fdc_in(int, u_char
*);
173 int fdc_intr_wait(void);
174 int fd_check(FD_UNIT
*);
175 void motor_on(int, int);
176 void motor_off(int, int);
178 void fdRecalibrate(int, int);
180 void fdDriveStatus(int, int, int, int *);
181 int fdSeek(int, int, int);
182 int fdSenseInt(int, int *);
183 int fdReadWrite(FD_UNIT
*, int, int, int, int, u_char
*);
185 int irq_polling(int, int);
186 void dma_setup(u_char
*, int, int, int);
187 int dma_finished(int);
189 /*===========================================================================*
191 *===========================================================================*/
203 if (fdc_out(ctlr
, CMD_VERSION
) != SUCCESS
) { /* version check */
204 printf ("fdc%d:fatal error: CMD_VERSION cmd fail\n", ctlr
);
207 if (fdc_in(ctlr
, &result
) != SUCCESS
) {
208 printf ("fdc%d:fatal error: CMD_VERSION exec fail\n", ctlr
);
211 if (result
!= (u_char
)RESULT_VERSION
) {
212 printf ("fdc%d:fatal error: unknown version fdc\n", ctlr
);
216 un
->un_flags
= INT_ALIVE
;
220 /*===========================================================================*
222 *===========================================================================*/
224 fdopen(struct open_file
*f
, int ctlr
, int unit
, int part
)
229 if (ctlr
>= CTLR_MAX
)
231 if (unit
>= UNIT_MAX
)
233 un
= &fd_unit
[ctlr
][unit
];
236 if (!(un
->un_flags
& INT_ALIVE
)) {
237 if (fdinit(un
) != SUCCESS
)
241 motor_on(ctlr
, unit
);
243 fdRecalibrate(ctlr
, unit
);
244 fdSenseInt(ctlr
, stat
);
245 if (stat
[1] != START_CYL
) {
246 printf("fdc%d: unit:%d recalibrate failed. status:0x%x cyl:%d\n",
247 ctlr
, unit
, stat
[0], stat
[1]);
248 motor_off(ctlr
, unit
);
252 if (fd_check(un
) != SUCCESS
) /* research disk type */
255 f
->f_devdata
= (void *)un
;
259 /*===========================================================================*
261 *===========================================================================*/
263 fdclose(struct open_file
*f
)
265 FD_UNIT
*un
= f
->f_devdata
;
267 fdRecalibrate(un
->ctlr
, un
->unit
);
268 fdSenseInt(un
->ctlr
, un
->stat
);
269 motor_off(un
->ctlr
, un
->unit
);
274 /*===========================================================================*
276 *===========================================================================*/
278 fdioctl(struct open_file
*f
, u_long cmd
, void *arg
)
289 /*===========================================================================*
291 *===========================================================================*/
293 fdstrategy(void *devdata
, int func
, daddr_t blk
, size_t size
, void *buf
,
296 int sectrac
, cyl
, head
, sec
;
297 FD_UNIT
*un
= devdata
;
300 int *stat
= un
->stat
;
303 u_char
*cbuf
= (u_char
*)buf
;
305 if (un
->un_flags
& INT_BUSY
) {
308 fdDriveStatus(ctlr
, unit
, 0, stat
);
310 nblock
= un
->un_type
->maxseccount
;
311 sectrac
= un
->un_type
->seccount
; /* sector per track */
314 while (fd_skip
< size
) {
315 blknum
= (u_long
)blk
* DEV_BSIZE
/FDBLK
+ fd_skip
/FDBLK
;
316 cyl
= blknum
/ (sectrac
* 2);
317 fdSeek(ctlr
, unit
, cyl
);
318 fdSenseInt(ctlr
, stat
);
319 if (!(stat
[0] & RESULT_SEEK
)) {
320 printf("fdc%d: unit:%d seek failed."
321 "status:0x%x cyl:%d pcyl:%d\n",
322 ctlr
, unit
, stat
[0], cyl
, stat
[1]);
326 sec
= blknum
% (sectrac
* 2);
327 head
= sec
/ sectrac
;
328 sec
= sec
% sectrac
+ 1;
330 if (fdReadWrite(un
, func
, cyl
, head
, sec
, cbuf
) == FAIL
) {
331 printf("fdc%d: unit%d fdReadWrite error [%s]\n",
332 ctlr
, unit
, (func
==F_READ
?"READ":"WRITE"));
346 /*===========================================================================*
348 *===========================================================================*/
350 * this function is Check floppy disk Type
353 fd_check(FD_UNIT
*un
)
357 int *stat
= un
->stat
;
359 static u_char sec_buff
[SECTOR_MAX
];
361 un
->un_type
= (FDDTYPE
*)FAIL
;
362 for (type
= 0; type
< FDTYPE_MAX
; type
++) {
363 un
->un_type
= &fdd_types
[type
];
365 /* try read start sector */
366 outb(FDC_RATE(ctlr
), un
->un_type
->rate
); /* rate set */
368 fdSeek(ctlr
, unit
, START_CYL
);
369 fdSenseInt(ctlr
, stat
);
370 if (!(stat
[0] & RESULT_SEEK
) || stat
[1] != START_CYL
) {
371 printf("fdc%d: unit:%d seek failed. status:0x%x\n",
372 ctlr
, unit
, stat
[0]);
375 if (fdReadWrite(un
, F_READ
,
376 START_CYL
, 0, START_SECTOR
, sec_buff
) == FAIL
) {
377 continue; /* bad disk type */
381 if (un
->un_type
== (FDDTYPE
*)FAIL
) {
382 printf("fdc%d: unit:%d check disk type failed.\n",
394 /*===========================================================================*
396 *===========================================================================*/
398 fdc_out(int ctlr
, int cmd
)
404 while (((status
= inb(FDC_STATUS(ctlr
))) & (RQM
| DIO
))
405 != (RQM
| 0) && time_out
-- > 0);
407 printf("fdc_out: timeout status = 0x%x\n", status
);
411 outb(FDC_DATA(ctlr
), cmd
);
416 /*===========================================================================*
418 *===========================================================================*/
420 fdc_in(int ctlr
, u_char
*data
)
426 while ((status
= inb(FDC_STATUS(ctlr
)) & (RQM
| DIO
))
427 != (RQM
| DIO
) && time_out
-- > 0) {
429 printf("fdc_in:error:ready for output\n");
435 printf("fdc_in:input ready timeout\n");
439 if (data
) *data
= (u_char
)inb(FDC_DATA(ctlr
));
444 /*===========================================================================*
446 *===========================================================================*/
451 return (irq_polling(FDC_IRQ
, INT_TIMEOUT
)); /* wait interrupt */
454 /*===========================================================================*
455 * fdc command function *
456 *===========================================================================*/
458 motor_on(int ctlr
, int unit
)
461 outb(FDC_DOR(ctlr
), DOR_RESET
| DOR_DMAEN
| unit
462 | (1 << (unit
+ 4))); /* reset & unit motor on */
463 DELAY(1); /* wait 100msec */
467 motor_off(int ctlr
, int unit
)
470 outb(FDC_DOR(ctlr
), DOR_RESET
); /* reset & motor off */
471 if (fdc_intr_wait() == FAIL
) /* wait interrupt */
472 printf("fdc: motor off failed.\n");
479 outb(FDC_DOR(ctlr
), 0); /* fdc reset */
481 outb(FDC_DOR(ctlr
), DOR_RESET
);
486 fdRecalibrate(int ctlr
, int unit
)
489 fdc_out(ctlr
, CMD_RECALIBRATE
);
492 if (fdc_intr_wait() == FAIL
) /* wait interrupt */
493 printf("fdc: recalibrate Timeout\n");
500 fdc_out(ctlr
, CMD_SPECIFY
);
501 fdc_out(ctlr
, SPECIFY1
);
502 fdc_out(ctlr
, SPECIFY2
);
506 fdDriveStatus(int ctlr
, register int unit
, register int head
,
511 fdc_out(ctlr
, CMD_DRV_SENSE
);
512 fdc_out(ctlr
, (head
<< 2) | unit
);
513 fdc_in(ctlr
, &result
);
514 *stat
= (int)(result
& 0xff);
518 fdSeek(int ctlr
, int unit
, int cyl
)
522 fdc_out(ctlr
, CMD_SEEK
);
526 if (fdc_intr_wait() == FAIL
) { /* wait interrupt */
527 printf("fdc: fdSeek Timeout\n");
535 fdSenseInt(int ctlr
, int *stat
)
539 fdc_out(ctlr
, CMD_SENSE_INT
);
541 fdc_in(ctlr
, &result
);
542 *stat
++ = (int)(result
& 0xff);
543 fdc_in(ctlr
, &result
);
544 *stat
++ = (int)(result
& 0xff);
550 fdReadWrite(FD_UNIT
*un
, int func
, int cyl
, int head
, int sec
, u_char
*adrs
)
555 int *stat
= un
->stat
;
559 printf("%s:", (func
== F_READ
? "READ" : "WRITE"));
560 printf("cyl = %d", cyl
);
561 printf("head = %d", head
);
562 printf("sec = %d", sec
);
563 printf("secsize = %d", un
->un_type
->secsize
);
564 printf("seccount = %d", un
->un_type
->seccount
);
565 printf("gap = %d", un
->un_type
->gap
);
566 printf("datalen = %d\n", un
->un_type
->datalen
);
569 dma_setup(adrs
, FDBLK
, func
, FD_DMA_CHAN
);
570 fdc_out(ctlr
, (func
== F_READ
? CMD_READ
: CMD_WRITE
));
571 fdc_out(ctlr
, (head
<<2) | unit
);
572 fdc_out(ctlr
, cyl
); /* cyl */
573 fdc_out(ctlr
, head
); /* head */
574 fdc_out(ctlr
, sec
); /* sec */
575 fdc_out(ctlr
, un
->un_type
->secsize
); /* secsize */
576 fdc_out(ctlr
, un
->un_type
->seccount
); /* EOT (end of track) */
577 fdc_out(ctlr
, un
->un_type
->gap
); /* GAP3 */
578 fdc_out(ctlr
, un
->un_type
->datalen
); /* DTL (data length) */
580 if (fdc_intr_wait() == FAIL
) { /* wait interrupt */
581 printf("fdc: DMA transfer Timeout\n");
585 for (i
= 0; i
< 7; i
++) {
586 fdc_in(ctlr
, &result
);
587 stat
[i
] = (int)(result
& 0xff);
589 if (stat
[0] & ST0_IC_MASK
) { /* not normal terminate */
590 if ((stat
[1] & ~ST1_EN
) || stat
[2])
593 if (!dma_finished(FD_DMA_CHAN
)) {
594 printf("DMA not finished\n");
600 printf(" func: %s\n", (func
== F_READ
? "F_READ" : "F_WRITE"));
601 printf(" st0 = 0x%x\n", stat
[0]);
602 printf(" st1 = 0x%x\n", stat
[1]);
603 printf(" st2 = 0x%x\n", stat
[2]);
604 printf(" c = 0x%x\n", stat
[3]);
605 printf(" h = 0x%x\n", stat
[4]);
606 printf(" r = 0x%x\n", stat
[5]);
607 printf(" n = 0x%x\n", stat
[6]);
611 /*-----------------------------------------------------------------------
612 * Interrupt Controller Operation Functions
613 *-----------------------------------------------------------------------
616 /* 8259A interrupt controller register */
617 #define INT_CTL0 0x20
618 #define INT_CTL1 0x21
619 #define INT2_CTL0 0xA0
620 #define INT2_CTL1 0xA1
622 #define CASCADE_IRQ 2
624 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
625 #define ICW4_AT 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
626 #define OCW3_PL 0x0e /* polling mode */
627 #define OCW2_CLEAR 0x20 /* interrupt clear */
630 * IRC programing sequence
633 * 1. ICW1 (write port:INT_CTL0 data:bit4=1)
634 * 2. ICW2 (write port:INT_CTL1)
635 * 3. ICW3 (write port:INT_CTL1)
636 * 4. ICW4 (write port:INT_CTL1)
639 * OCW1 (write port:INT_CTL1)
640 * OCW2 (write port:INT_CTL0 data:bit3=0,bit4=0)
641 * OCW3 (write port:INT_CTL0 data:bit3=1,bit4=0)
643 * IMR (read port:INT_CTL1)
644 * IRR (read port:INT_CTL0) OCW3(bit1=1,bit0=0)
645 * ISR (read port:INT_CTL0) OCW3(bit1=1,bit0=1)
646 * PL (read port:INT_CTL0) OCW3(bit2=1,bit1=1)
652 /*===========================================================================*
654 *===========================================================================*/
658 outb(INT_CTL0
, ICW1_AT
); /* ICW1 */
659 outb(INT_CTL1
, 0); /* ICW2 for master */
660 outb(INT_CTL1
, (1 << CASCADE_IRQ
)); /* ICW3 tells slaves */
661 outb(INT_CTL1
, ICW4_AT
); /* ICW4 */
663 outb(INT_CTL1
, (INT_MASK
= ~(1 << CASCADE_IRQ
)));
664 /* IRQ mask(exclusive of cascade) */
666 outb(INT2_CTL0
, ICW1_AT
); /* ICW1 */
667 outb(INT2_CTL1
, 8); /* ICW2 for slave */
668 outb(INT2_CTL1
, CASCADE_IRQ
); /* ICW3 is slave nr */
669 outb(INT2_CTL1
, ICW4_AT
); /* ICW4 */
671 outb(INT2_CTL1
, (INT2_MASK
= ~0)); /* IRQ 8-15 mask */
674 /*===========================================================================*
675 * irq polling check *
676 *===========================================================================*/
678 irq_polling(int irq_no
, int timeout
)
684 if (irq_no
> 8) irc_no
= 1;
687 outb(irc_no
? INT2_CTL1
: INT_CTL1
, ~(1 << (irq_no
>> (irc_no
* 3))));
689 while (--timeout
> 0) {
690 outb(irc_no
? INT2_CTL0
: INT_CTL0
, OCW3_PL
);
691 /* set polling mode */
692 data
= inb(irc_no
? INT2_CTL0
: INT_CTL0
);
693 if (data
& 0x80) { /* if interrupt request */
694 if ((irq_no
>> (irc_no
* 3)) == (data
& 0x7)) {
700 if (!timeout
) ret
= FAIL
;
702 if (irc_no
) { /* interrupt clear */
703 outb(INT2_CTL0
, OCW2_CLEAR
| (irq_no
>> 3));
704 outb(INT_CTL0
, OCW2_CLEAR
| CASCADE_IRQ
);
706 outb(INT_CTL0
, OCW2_CLEAR
| irq_no
);
709 outb(INT_CTL1
, INT_MASK
);
710 outb(INT2_CTL1
, INT2_MASK
);
715 /*---------------------------------------------------------------------------*
716 * DMA Controller Define *
717 *---------------------------------------------------------------------------*/
718 /* DMA Controller Registers */
719 #define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */
720 #define DMA_LTOP 0x081 /* port for top low 8bit DMA addr(ch2) */
721 #define DMA_HTOP 0x481 /* port for top high 8bit DMA addr(ch2) */
722 #define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */
723 #define DMA_DEVCON 0x008 /* DMA device control register */
724 #define DMA_SR 0x008 /* DMA status register */
725 #define DMA_RESET 0x00D /* DMA software reset register */
726 #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flip-flop */
727 #define DMA_MODE 0x00B /* DMA mode port */
728 #define DMA_INIT 0x00A /* DMA init port */
730 #define DMA_RESET_VAL 0x06
731 /* DMA channel commands. */
732 #define DMA_READ 0x46 /* DMA read opcode */
733 #define DMA_WRITE 0x4A /* DMA write opcode */
735 /*===========================================================================*
737 *===========================================================================*/
739 dma_setup(u_char
*buf
, int size
, int func
, int chan
)
741 u_long pbuf
= local_to_PCI((u_long
)buf
);
746 outb(DMA_DEVCON
, 0x00);
747 outb(DMA_INIT
, DMA_RESET_VAL
); /* reset the dma controller */
749 outb(DMA_MODE
, func
== F_READ
? DMA_READ
: DMA_WRITE
);
750 outb(DMA_FLIPFLOP
, 0); /* write anything to reset it */
752 outb(DMA_ADDR
, (int)pbuf
>> 0);
753 outb(DMA_ADDR
, (int)pbuf
>> 8);
754 outb(DMA_LTOP
, (int)pbuf
>> 16);
755 outb(DMA_HTOP
, (int)pbuf
>> 24);
757 outb(DMA_COUNT
, (size
- 1) >> 0);
758 outb(DMA_COUNT
, (size
- 1) >> 8);
759 outb(DMA_INIT
, chan
); /* some sort of enable */
763 dma_finished(int chan
)
766 return ((inb(DMA_SR
) & 0x0f) == (1 << chan
));