* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)fd.c 7.3 (Berkeley) 5/25/91
/****************************************************************************/
/* standalone fd driver */
/****************************************************************************/
#include "i386/isa/fdreg.h"
#include "i386/isa/isa.h"
extern struct disklabel disklabel
;
int sectrac
; /* sectors per track */
int secsize
; /* size code for sectors */
int datalen
; /* data len when secsize = 0 */
int gap
; /* gap len between sectors */
int tracks
; /* total num of tracks */
int size
; /* size of disk in sectors */
int steptrac
; /* steps per cylinder */
int trans
; /* transfer speed code */
struct fd_type fd_types
[] = {
{ 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy */
{ 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy */
/* need 720K 3.5in here as well */
{ 9,2,0xFF,0x23,40,720,2,1 }, /* 360k floppy in 1.2meg drive */
{ 9,2,0xFF,0x2A,40,720,1,1 }, /* 360k floppy in DD drive */
/* state needed for current transfer */
static int fdc
= IO_FD1
; /* floppy disk base */
/* Make sure DMA buffer doesn't cross 64k boundary */
/****************************************************************************/
/****************************************************************************/
/*fd_type = io->i_part;*/
* Set up block calculations.
iosize
= io
->i_cc
/ FDBLK
;
blknum
= (unsigned long) io
->i_bn
* DEV_BSIZE
/ FDBLK
;
nblocks
= fd_types
[fd_type
].size
/* disklabel.d_secperunit */;
if ((blknum
+ iosize
> nblocks
) || blknum
< 0) {
printf("bn = %d; sectors = %d; type = %d; fssize = %d ",
blknum
, iosize
, fd_type
, nblocks
);
printf("fdstrategy - I/O out of filesystem boundaries\n");
/*printf("iosize %d ", iosize);*/
if (fdio(func
, unit
, blknum
, address
))
fdio(func
, unit
, blknum
, address
)
int i
,j
, cyl
, sectrac
,sec
,head
,numretry
;
cyl
= blknum
/ (sectrac
*2);
bcopy(address
,bounce
,FDBLK
);
out_fdc(15); /* Seek function */
out_fdc(unit
); /* Drive number */
i
= in_fdc(); j
= in_fdc();
if (!(i
&0x20) || (cyl
!= j
)) {
if (numretry
) goto retry
;
printf("Seek error %d, req = %d, at = %d\n",i
,cyl
,j
);
printf("unit %d, type %d, sectrac %d, blknum %d\n",
unit
,fd_type
,sectrac
,blknum
);
fd_dma(func
== F_READ
, bounce
, FDBLK
);
sec
= blknum
% (sectrac
* 2) /*disklabel.d_secpercyl*/;
printf("sec %d hd %d cyl %d ", sec
, head
, cyl
);
if (func
== F_READ
) out_fdc(0xE6);/* READ */
else out_fdc(0xC5); /* WRITE */
out_fdc(head
<< 2 | fd_drive
); /* head & unit */
out_fdc(cyl
); /* track */
out_fdc(sec
); /* sector */
out_fdc(ft
->secsize
); /* sector size */
out_fdc(sectrac
); /* sectors/track */
out_fdc(ft
->gap
); /* gap size */
out_fdc(ft
->datalen
); /* data length */
printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
fd_status
[0], fd_status
[1], fd_status
[2], fd_status
[3],
fd_status
[4], fd_status
[5], fd_status
[6] );
if (numretry
) goto retry
;
bcopy(bounce
,address
,FDBLK
);
/****************************************************************************/
/****************************************************************************/
while ((i
= inb(fdc
+fdsts
) & 192) != 192) if (i
== 128) return -1;
if (fd_status
[i
] < 0) break;
printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
fd_status
[0], fd_status
[1], fd_status
[2], fd_status
[3],
fd_status
[4], fd_status
[5], fd_status
[6] );
outb(0x21,0x0f); /* turn on int 6 */
outb(0x20,0xc); /* read polled interrupt */
while ((c
=inb(0x20))&0x7f != 6); /* wait for int */
r
= (inb(fdc
+fdsts
) & 192);
dump_stat(); /* error: direction. eat up output */
/****************************************************************************/
/****************************************************************************/
io
->i_boff
= 0; /* no disklabels -- tar/dump wont work */
printf("fdopen %d %d ", unit
, type
);
set_intr(); /* init intr cont */
/* Try a reset, keep motor on */
for(i
=0; i
< 100000; i
++);
outb(0x3f2,unit
| (unit
? 32 : 16) );
for(i
=0; i
< 100000; i
++);
outb(0x3f2,unit
| 0xC | (unit
? 32 : 16) );
out_fdc(3); /* specify command */
out_fdc(7); /* Recalibrate Function */
for (fd_type
= 0; fd_type
< sizeof(fd_types
)/sizeof(fd_types
[0]);
/*for(i=0; i < 100000; i++);
for(i=0; i < 100000; i++);*/
if (fdio(F_READ
, unit
, ft
->sectrac
-1, buf
) >= 0){
/****************************************************************************/
/* set up DMA read/write operation and virtual address addr for nbytes */
/****************************************************************************/
/* Set read/write bytes */
outb(0xC,0x46); outb(0xB,0x46);
outb(0xC,0x4A); outb(0xB,0x4A);
outb(0x4,(addr
>>8) & 0xFF);
outb(0x81,(addr
>>16) & 0xFF);
outb(0x5,(nbytes
>>8) & 0xFF);