Sync with sys/i386/isa/fd.c revision 1.128.

This commit is contained in:
KATO Takenori 1998-12-14 09:06:23 +00:00
parent ba8d06b9f7
commit c2a3601760
2 changed files with 720 additions and 14 deletions

View File

@ -5,6 +5,10 @@
* This code is derived from software contributed to Berkeley by
* Don Ahn.
*
* Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)
* aided by the Linux floppy driver modifications from David Bateman
* (dbateman@eng.uts.edu.au).
*
* Copyright (c) 1993, 1994 by
* jc@irbs.UUCP (John Capo)
* vak@zebub.msk.su (Serge Vakulenko)
@ -43,7 +47,7 @@
* SUCH DAMAGE.
*
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
* $Id: fd.c,v 1.44 1998/12/08 08:18:58 kato Exp $
* $Id: fd.c,v 1.45 1998/12/10 19:57:00 eivind Exp $
*
*/
@ -97,6 +101,10 @@
/* configuration flags */
#define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */
#ifdef FDC_YE
#define FDC_IS_PCMCIA (1 << 1) /* if successful probe, then it's
a PCMCIA device */
#endif
/* internally used only, not really from CMOS: */
#define RTCFDT_144M_PRETENDED 0x1000
@ -296,6 +304,11 @@ int ftsize(dev_t);
int ftattach(struct isa_device *, struct isa_device *, int);
#endif
#ifdef FDC_YE
#include "card.h"
static int yeattach(struct isa_device *);
#endif
/* autoconfig functions */
static int fdprobe(struct isa_device *);
static int fdattach(struct isa_device *);
@ -339,6 +352,9 @@ static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */
#define MOTORWAIT 10
#define IOTIMEDOUT 11
#define RESETCOMPLETE 12
#ifdef FDC_YE
#define PIOREAD 13
#endif
#ifdef FDC_DEBUG
static char const * const fdstates[] =
@ -356,6 +372,9 @@ static char const * const fdstates[] =
"MOTORWAIT",
"IOTIMEDOUT",
"RESETCOMPLETE",
#ifdef FDC_YE
,"PIOREAD"
#endif
};
/* CAUTION: fd_debug causes huge amounts of logging output */
@ -367,6 +386,99 @@ static int volatile fd_debug = 0;
#define TRACE1(arg1, arg2)
#endif /* FDC_DEBUG */
#ifdef FDC_YE
#if NCARD > 0
#include <sys/select.h>
#include <pccard/cardinfo.h>
#include <pccard/driver.h>
#include <pccard/slot.h>
/*
* PC-Card (PCMCIA) specific code.
*/
static int yeinit(struct pccard_devinfo *); /* init device */
static void yeunload(struct pccard_devinfo *); /* Disable driver */
static int yeintr(struct pccard_devinfo *); /* Interrupt handler */
static struct pccard_device ye_info = {
"fdc",
yeinit,
yeunload,
yeintr,
0, /* Attributes - presently unused */
&bio_imask /* Interrupt mask for device */
};
DATA_SET(pccarddrv_set, ye_info);
/*
* this is the secret PIO data port (offset from base)
*/
#define FDC_YE_DATAPORT 6
/*
* Initialize the device - called from Slot manager.
*/
static int yeinit(struct pccard_devinfo *devi)
{
fdc_p fdc = &fdc_data[devi->isahd.id_unit];
/* validate unit number. */
if (devi->isahd.id_unit >= NFDC)
return(ENODEV);
fdc->baseport = devi->isahd.id_iobase;
/*
* reset controller
*/
outb(fdc->baseport+FDOUT, 0);
DELAY(100);
outb(fdc->baseport+FDOUT, FDO_FRST);
/*
* wire into system
*/
if (yeattach(&devi->isahd) == 0)
return(ENXIO);
return(0);
}
/*
* yeunload - unload the driver and clear the table.
* XXX TODO:
* This is usually called when the card is ejected, but
* can be caused by a modunload of a controller driver.
* The idea is to reset the driver's view of the device
* and ensure that any driver entry points such as
* read and write do not hang.
*/
static void yeunload(struct pccard_devinfo *devi)
{
if (fd_data[devi->isahd.id_unit].type == NO_TYPE)
return;
/*
* this prevents Fdopen() and fdstrategy() from attempting
* to access unloaded controller
*/
fd_data[devi->isahd.id_unit].type = NO_TYPE;
printf("fdc%d: unload\n", devi->isahd.id_unit);
}
/*
* yeintr - Shared interrupt called from
* front end of PC-Card handler.
*/
static int yeintr(struct pccard_devinfo *devi)
{
fdintr((fdcu_t)devi->isahd.id_unit);
return(1);
}
#endif /* NCARD > 0 */
#endif /* FDC_YE */
/* autoconfig structure */
struct isa_driver fdcdriver = {
@ -405,7 +517,7 @@ fdc_err(fdcu_t fdcu, const char *s)
printf("fdc%d: %s", fdcu, s);
else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX)
printf("fdc%d: too many errors, not logging any more\n",
fdcu);
fdcu);
}
return FD_FAILED;
@ -698,6 +810,14 @@ fdprobe(struct isa_device *dev)
{
return(0);
}
#ifdef FDC_YE
/*
* don't succeed on probe; wait
* for PCCARD subsystem to do it
*/
if (dev->id_flags & FDC_IS_PCMCIA)
return(0);
#endif
return (IO_FDCSIZE);
}
@ -880,7 +1000,7 @@ fdattach(struct isa_device *dev)
enable_fifo(fdc) == 0) {
printf("fdc%d: FIFO enabled", fdcu);
printf(", %d bytes threshold\n",
fifo_threshold);
fifo_threshold);
}
}
if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) &&
@ -1091,6 +1211,138 @@ fdattach(struct isa_device *dev)
#ifdef FDC_YE
/*
* this is a subset of fdattach() optimized for the Y-E Data
* PCMCIA floppy drive.
*/
static int yeattach(struct isa_device *dev)
{
fdcu_t fdcu = dev->id_unit;
fdc_p fdc = fdc_data + fdcu;
fdsu_t fdsu = 0; /* assume 1 drive per YE controller */
fdu_t fdu;
fd_p fd;
int st0, st3, i;
#ifdef DEVFS
int mynor;
int typemynor;
int typesize;
#endif
fdc->fdcu = fdcu;
/*
* the FDC_PCMCIA flag is used to to indicate special PIO is used
* instead of DMA
*/
fdc->flags = FDC_ATTACHED|FDC_PCMCIA;
fdc->state = DEVIDLE;
/* reset controller, turn motor off, clear fdout mirror reg */
outb(fdc->baseport + FDOUT, ((fdc->fdout = 0)));
bufq_init(&fdc->head);
/*
* assume 2 drives/ "normal" controller
*/
fdu = fdcu * 2;
if (fdu >= NFD) {
printf("fdu %d >= NFD\n",fdu);
return(0);
};
fd = &fd_data[fdu];
set_motor(fdcu, fdsu, TURNON);
DELAY(1000000); /* 1 sec */
fdc->fdct = FDC_NE765;
if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) &&
(st3 & NE7_ST3_T0)) {
/* if at track 0, first seek inwards */
/* seek some steps: */
(void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0);
DELAY(300000); /* ...wait a moment... */
(void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */
}
/* If we're at track 0 first seek inwards. */
if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) {
/* Seek some steps... */
if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
/* ...wait a moment... */
DELAY(300000);
/* make ctrlr happy: */
(void)fd_sense_int(fdc, 0, 0);
}
}
for(i = 0; i < 2; i++) {
/*
* we must recalibrate twice, just in case the
* heads have been beyond cylinder 76, since most
* FDCs still barf when attempting to recalibrate
* more than 77 steps
*/
/* go back to 0: */
if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
/* a second being enough for full stroke seek*/
DELAY(i == 0? 1000000: 300000);
/* anything responding? */
if (fd_sense_int(fdc, &st0, 0) == 0 &&
(st0 & NE7_ST0_EC) == 0)
break; /* already probed succesfully */
}
}
set_motor(fdcu, fdsu, TURNOFF);
if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */
return(0);
fd->track = FD_NO_TRACK;
fd->fdc = fdc;
fd->fdsu = fdsu;
fd->options = 0;
printf("fdc%d: 1.44MB 3.5in PCMCIA\n", fdcu);
fd->type = FD_1440;
#ifdef DEVFS
mynor = fdcu << 6;
fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
"fd%d", fdu);
fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR,
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d", fdu);
/*
* XXX this and the lookup in Fdopen() should be
* data driven.
*/
typemynor = mynor | FD_1440;
typesize = fd_types[FD_1440 - 1].size / 2;
/*
* XXX all these conversions give bloated code and
* confusing names.
*/
if (typesize == 1476)
typesize = 1480;
if (typesize == 1722)
typesize = 1720;
fd->bdevs[FD_1440] = devfs_add_devswf(&fd_bdevsw, typemynor,
DV_BLK, UID_ROOT, GID_OPERATOR,
0640, "fd%d.%d", fdu, typesize);
fd->cdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor,
DV_CHR, UID_ROOT, GID_OPERATOR,
0640,"rfd%d.%d", fdu, typesize);
for (i = 0; i < MAXPARTITIONS; i++) {
fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0],
"fd%d%c", fdu, 'a' + i);
fd->cdevs[1 + NUMDENS + i] = devfs_link(fd->cdevs[0],
"rfd%d%c", fdu, 'a' + i);
}
#endif /* DEVFS */
return (1);
}
#endif
/****************************************************************************/
/* motor control stuff */
/* remember to not deselect the drive we're working on */
@ -1455,6 +1707,17 @@ fdstrategy(struct buf *bp)
fd = &fd_data[fdu];
fdc = fd->fdc;
fdcu = fdc->fdcu;
#ifdef FDC_YE
if (fd->type == NO_TYPE) {
bp->b_error = ENXIO;
bp->b_flags |= B_ERROR;
/*
* I _refuse_ to use a goto
*/
biodone(bp);
return;
};
#endif
#if NFT > 0
if (FDTYPE(minor(bp->b_dev)) & F_TAPE_TYPE) {
@ -1622,6 +1885,38 @@ fdintr(fdcu_t fdcu)
;
}
#ifdef FDC_YE
/*
* magic pseudo-DMA initialization for YE FDC. Sets count and
* direction
*/
#define SET_BCDR(wr,cnt,port) outb(port,(((cnt)-1) & 0xff)); \
outb(port+1,((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f)))
/*
* fdcpio(): perform programmed IO read/write for YE PCMCIA floppy
*/
static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count)
{
u_char *cptr = (u_char *)addr;
fdc_p fdc = &fdc_data[fdcu];
int io = fdc->baseport;
if (flags & B_READ) {
if (fdc->state != PIOREAD) {
fdc->state = PIOREAD;
return(0);
};
SET_BCDR(0,count,io);
insb(io+FDC_YE_DATAPORT,cptr,count);
} else {
outsb(io+FDC_YE_DATAPORT,cptr,count);
SET_BCDR(0,count,io);
};
return(1);
}
#endif /* FDC_YE */
/***********************************************************************\
* The controller state machine. *
* if it returns a non zero value, it should be called again immediatly *
@ -1861,8 +2156,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
#ifdef EPSON_NRDISK
if (fdu != nrdu) {
#endif /* EPSON_NRDISK */
isa_dmastart(bp->b_flags, bp->b_data+fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
#ifdef FDC_YE
if (!(fdc->flags & FDC_PCMCIA))
#endif
isa_dmastart(bp->b_flags, bp->b_data+fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
sectrac = fd->ft->sectrac;
sec = blknum % (sectrac * fd->ft->heads);
head = sec / sectrac;
@ -1903,6 +2201,12 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
if(format)
{
#ifdef FDC_YE
if (fdc->flags & FDC_PCMCIA)
(void)fdcpio(fdcu,bp->b_flags,
bp->b_data+fd->skip,
bp->b_bcount);
#endif
/* formatting */
if(fd_cmd(fdcu, 6,
NE7CMD_FORMAT,
@ -1923,6 +2227,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
}
else
{
#ifdef FDC_YE
if (fdc->flags & FDC_PCMCIA) {
/*
* this seems to be necessary even when
* reading data
*/
SET_BCDR(1,fdblk,fdc->baseport);
/*
* perform the write pseudo-DMA before
* the WRITE command is sent
*/
if (!read)
(void)fdcpio(fdcu,bp->b_flags,
bp->b_data+fd->skip,
fdblk);
}
#endif
if (fd_cmd(fdcu, 9,
(read ? NE7CMD_READ : NE7CMD_WRITE),
head << 2 | fdu, /* head & unit */
@ -1943,6 +2265,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
return(retrier(fdcu));
}
}
#ifdef FDC_YE
if (fdc->flags & FDC_PCMCIA)
/*
* if this is a read, then simply await interrupt
* before performing PIO
*/
if (read && !fdcpio(fdcu,bp->b_flags,
bp->b_data+fd->skip,fdblk)) {
fd->tohandle = timeout(fd_iotimeout,
(caddr_t)fdcu, hz);
return(0); /* will return later */
};
/*
* write (or format) operation will fall through and
* await completion interrupt
*/
#endif
fdc->state = IOCOMPLETE;
fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz);
return(0); /* will return later */
@ -1975,6 +2315,16 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
nrdsec = sec;
fdc->state = IOCOMPLETE;
}
#endif
#ifdef FDC_YE
case PIOREAD:
/*
* actually perform the PIO read. The IOCOMPLETE case
* removes the timeout for us.
*/
(void)fdcpio(fdcu,bp->b_flags,bp->b_data+fd->skip,fdblk);
fdc->state = IOCOMPLETE;
/* FALLTHROUGH */
#endif
case IOCOMPLETE: /* IO DONE, post-analyze */
#ifdef EPSON_NRDISK
@ -2002,8 +2352,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
#ifdef EPSON_NRDISK
if (fdu != nrdu) {
#endif /* EPSON_NRDISK */
isa_dmadone(bp->b_flags, bp->b_data + fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
#ifdef FDC_YE
if (!(fdc->flags & FDC_PCMCIA))
#endif
isa_dmadone(bp->b_flags, bp->b_data + fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
#ifdef EPSON_NRDISK
}
else nrd_LED_off();

View File

@ -5,6 +5,10 @@
* This code is derived from software contributed to Berkeley by
* Don Ahn.
*
* Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)
* aided by the Linux floppy driver modifications from David Bateman
* (dbateman@eng.uts.edu.au).
*
* Copyright (c) 1993, 1994 by
* jc@irbs.UUCP (John Capo)
* vak@zebub.msk.su (Serge Vakulenko)
@ -43,7 +47,7 @@
* SUCH DAMAGE.
*
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
* $Id: fd.c,v 1.44 1998/12/08 08:18:58 kato Exp $
* $Id: fd.c,v 1.45 1998/12/10 19:57:00 eivind Exp $
*
*/
@ -97,6 +101,10 @@
/* configuration flags */
#define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */
#ifdef FDC_YE
#define FDC_IS_PCMCIA (1 << 1) /* if successful probe, then it's
a PCMCIA device */
#endif
/* internally used only, not really from CMOS: */
#define RTCFDT_144M_PRETENDED 0x1000
@ -296,6 +304,11 @@ int ftsize(dev_t);
int ftattach(struct isa_device *, struct isa_device *, int);
#endif
#ifdef FDC_YE
#include "card.h"
static int yeattach(struct isa_device *);
#endif
/* autoconfig functions */
static int fdprobe(struct isa_device *);
static int fdattach(struct isa_device *);
@ -339,6 +352,9 @@ static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */
#define MOTORWAIT 10
#define IOTIMEDOUT 11
#define RESETCOMPLETE 12
#ifdef FDC_YE
#define PIOREAD 13
#endif
#ifdef FDC_DEBUG
static char const * const fdstates[] =
@ -356,6 +372,9 @@ static char const * const fdstates[] =
"MOTORWAIT",
"IOTIMEDOUT",
"RESETCOMPLETE",
#ifdef FDC_YE
,"PIOREAD"
#endif
};
/* CAUTION: fd_debug causes huge amounts of logging output */
@ -367,6 +386,99 @@ static int volatile fd_debug = 0;
#define TRACE1(arg1, arg2)
#endif /* FDC_DEBUG */
#ifdef FDC_YE
#if NCARD > 0
#include <sys/select.h>
#include <pccard/cardinfo.h>
#include <pccard/driver.h>
#include <pccard/slot.h>
/*
* PC-Card (PCMCIA) specific code.
*/
static int yeinit(struct pccard_devinfo *); /* init device */
static void yeunload(struct pccard_devinfo *); /* Disable driver */
static int yeintr(struct pccard_devinfo *); /* Interrupt handler */
static struct pccard_device ye_info = {
"fdc",
yeinit,
yeunload,
yeintr,
0, /* Attributes - presently unused */
&bio_imask /* Interrupt mask for device */
};
DATA_SET(pccarddrv_set, ye_info);
/*
* this is the secret PIO data port (offset from base)
*/
#define FDC_YE_DATAPORT 6
/*
* Initialize the device - called from Slot manager.
*/
static int yeinit(struct pccard_devinfo *devi)
{
fdc_p fdc = &fdc_data[devi->isahd.id_unit];
/* validate unit number. */
if (devi->isahd.id_unit >= NFDC)
return(ENODEV);
fdc->baseport = devi->isahd.id_iobase;
/*
* reset controller
*/
outb(fdc->baseport+FDOUT, 0);
DELAY(100);
outb(fdc->baseport+FDOUT, FDO_FRST);
/*
* wire into system
*/
if (yeattach(&devi->isahd) == 0)
return(ENXIO);
return(0);
}
/*
* yeunload - unload the driver and clear the table.
* XXX TODO:
* This is usually called when the card is ejected, but
* can be caused by a modunload of a controller driver.
* The idea is to reset the driver's view of the device
* and ensure that any driver entry points such as
* read and write do not hang.
*/
static void yeunload(struct pccard_devinfo *devi)
{
if (fd_data[devi->isahd.id_unit].type == NO_TYPE)
return;
/*
* this prevents Fdopen() and fdstrategy() from attempting
* to access unloaded controller
*/
fd_data[devi->isahd.id_unit].type = NO_TYPE;
printf("fdc%d: unload\n", devi->isahd.id_unit);
}
/*
* yeintr - Shared interrupt called from
* front end of PC-Card handler.
*/
static int yeintr(struct pccard_devinfo *devi)
{
fdintr((fdcu_t)devi->isahd.id_unit);
return(1);
}
#endif /* NCARD > 0 */
#endif /* FDC_YE */
/* autoconfig structure */
struct isa_driver fdcdriver = {
@ -405,7 +517,7 @@ fdc_err(fdcu_t fdcu, const char *s)
printf("fdc%d: %s", fdcu, s);
else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX)
printf("fdc%d: too many errors, not logging any more\n",
fdcu);
fdcu);
}
return FD_FAILED;
@ -698,6 +810,14 @@ fdprobe(struct isa_device *dev)
{
return(0);
}
#ifdef FDC_YE
/*
* don't succeed on probe; wait
* for PCCARD subsystem to do it
*/
if (dev->id_flags & FDC_IS_PCMCIA)
return(0);
#endif
return (IO_FDCSIZE);
}
@ -880,7 +1000,7 @@ fdattach(struct isa_device *dev)
enable_fifo(fdc) == 0) {
printf("fdc%d: FIFO enabled", fdcu);
printf(", %d bytes threshold\n",
fifo_threshold);
fifo_threshold);
}
}
if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) &&
@ -1091,6 +1211,138 @@ fdattach(struct isa_device *dev)
#ifdef FDC_YE
/*
* this is a subset of fdattach() optimized for the Y-E Data
* PCMCIA floppy drive.
*/
static int yeattach(struct isa_device *dev)
{
fdcu_t fdcu = dev->id_unit;
fdc_p fdc = fdc_data + fdcu;
fdsu_t fdsu = 0; /* assume 1 drive per YE controller */
fdu_t fdu;
fd_p fd;
int st0, st3, i;
#ifdef DEVFS
int mynor;
int typemynor;
int typesize;
#endif
fdc->fdcu = fdcu;
/*
* the FDC_PCMCIA flag is used to to indicate special PIO is used
* instead of DMA
*/
fdc->flags = FDC_ATTACHED|FDC_PCMCIA;
fdc->state = DEVIDLE;
/* reset controller, turn motor off, clear fdout mirror reg */
outb(fdc->baseport + FDOUT, ((fdc->fdout = 0)));
bufq_init(&fdc->head);
/*
* assume 2 drives/ "normal" controller
*/
fdu = fdcu * 2;
if (fdu >= NFD) {
printf("fdu %d >= NFD\n",fdu);
return(0);
};
fd = &fd_data[fdu];
set_motor(fdcu, fdsu, TURNON);
DELAY(1000000); /* 1 sec */
fdc->fdct = FDC_NE765;
if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) &&
(st3 & NE7_ST3_T0)) {
/* if at track 0, first seek inwards */
/* seek some steps: */
(void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0);
DELAY(300000); /* ...wait a moment... */
(void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */
}
/* If we're at track 0 first seek inwards. */
if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) {
/* Seek some steps... */
if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
/* ...wait a moment... */
DELAY(300000);
/* make ctrlr happy: */
(void)fd_sense_int(fdc, 0, 0);
}
}
for(i = 0; i < 2; i++) {
/*
* we must recalibrate twice, just in case the
* heads have been beyond cylinder 76, since most
* FDCs still barf when attempting to recalibrate
* more than 77 steps
*/
/* go back to 0: */
if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
/* a second being enough for full stroke seek*/
DELAY(i == 0? 1000000: 300000);
/* anything responding? */
if (fd_sense_int(fdc, &st0, 0) == 0 &&
(st0 & NE7_ST0_EC) == 0)
break; /* already probed succesfully */
}
}
set_motor(fdcu, fdsu, TURNOFF);
if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */
return(0);
fd->track = FD_NO_TRACK;
fd->fdc = fdc;
fd->fdsu = fdsu;
fd->options = 0;
printf("fdc%d: 1.44MB 3.5in PCMCIA\n", fdcu);
fd->type = FD_1440;
#ifdef DEVFS
mynor = fdcu << 6;
fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
"fd%d", fdu);
fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR,
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d", fdu);
/*
* XXX this and the lookup in Fdopen() should be
* data driven.
*/
typemynor = mynor | FD_1440;
typesize = fd_types[FD_1440 - 1].size / 2;
/*
* XXX all these conversions give bloated code and
* confusing names.
*/
if (typesize == 1476)
typesize = 1480;
if (typesize == 1722)
typesize = 1720;
fd->bdevs[FD_1440] = devfs_add_devswf(&fd_bdevsw, typemynor,
DV_BLK, UID_ROOT, GID_OPERATOR,
0640, "fd%d.%d", fdu, typesize);
fd->cdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor,
DV_CHR, UID_ROOT, GID_OPERATOR,
0640,"rfd%d.%d", fdu, typesize);
for (i = 0; i < MAXPARTITIONS; i++) {
fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0],
"fd%d%c", fdu, 'a' + i);
fd->cdevs[1 + NUMDENS + i] = devfs_link(fd->cdevs[0],
"rfd%d%c", fdu, 'a' + i);
}
#endif /* DEVFS */
return (1);
}
#endif
/****************************************************************************/
/* motor control stuff */
/* remember to not deselect the drive we're working on */
@ -1455,6 +1707,17 @@ fdstrategy(struct buf *bp)
fd = &fd_data[fdu];
fdc = fd->fdc;
fdcu = fdc->fdcu;
#ifdef FDC_YE
if (fd->type == NO_TYPE) {
bp->b_error = ENXIO;
bp->b_flags |= B_ERROR;
/*
* I _refuse_ to use a goto
*/
biodone(bp);
return;
};
#endif
#if NFT > 0
if (FDTYPE(minor(bp->b_dev)) & F_TAPE_TYPE) {
@ -1622,6 +1885,38 @@ fdintr(fdcu_t fdcu)
;
}
#ifdef FDC_YE
/*
* magic pseudo-DMA initialization for YE FDC. Sets count and
* direction
*/
#define SET_BCDR(wr,cnt,port) outb(port,(((cnt)-1) & 0xff)); \
outb(port+1,((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f)))
/*
* fdcpio(): perform programmed IO read/write for YE PCMCIA floppy
*/
static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count)
{
u_char *cptr = (u_char *)addr;
fdc_p fdc = &fdc_data[fdcu];
int io = fdc->baseport;
if (flags & B_READ) {
if (fdc->state != PIOREAD) {
fdc->state = PIOREAD;
return(0);
};
SET_BCDR(0,count,io);
insb(io+FDC_YE_DATAPORT,cptr,count);
} else {
outsb(io+FDC_YE_DATAPORT,cptr,count);
SET_BCDR(0,count,io);
};
return(1);
}
#endif /* FDC_YE */
/***********************************************************************\
* The controller state machine. *
* if it returns a non zero value, it should be called again immediatly *
@ -1861,8 +2156,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
#ifdef EPSON_NRDISK
if (fdu != nrdu) {
#endif /* EPSON_NRDISK */
isa_dmastart(bp->b_flags, bp->b_data+fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
#ifdef FDC_YE
if (!(fdc->flags & FDC_PCMCIA))
#endif
isa_dmastart(bp->b_flags, bp->b_data+fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
sectrac = fd->ft->sectrac;
sec = blknum % (sectrac * fd->ft->heads);
head = sec / sectrac;
@ -1903,6 +2201,12 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
if(format)
{
#ifdef FDC_YE
if (fdc->flags & FDC_PCMCIA)
(void)fdcpio(fdcu,bp->b_flags,
bp->b_data+fd->skip,
bp->b_bcount);
#endif
/* formatting */
if(fd_cmd(fdcu, 6,
NE7CMD_FORMAT,
@ -1923,6 +2227,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
}
else
{
#ifdef FDC_YE
if (fdc->flags & FDC_PCMCIA) {
/*
* this seems to be necessary even when
* reading data
*/
SET_BCDR(1,fdblk,fdc->baseport);
/*
* perform the write pseudo-DMA before
* the WRITE command is sent
*/
if (!read)
(void)fdcpio(fdcu,bp->b_flags,
bp->b_data+fd->skip,
fdblk);
}
#endif
if (fd_cmd(fdcu, 9,
(read ? NE7CMD_READ : NE7CMD_WRITE),
head << 2 | fdu, /* head & unit */
@ -1943,6 +2265,24 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
return(retrier(fdcu));
}
}
#ifdef FDC_YE
if (fdc->flags & FDC_PCMCIA)
/*
* if this is a read, then simply await interrupt
* before performing PIO
*/
if (read && !fdcpio(fdcu,bp->b_flags,
bp->b_data+fd->skip,fdblk)) {
fd->tohandle = timeout(fd_iotimeout,
(caddr_t)fdcu, hz);
return(0); /* will return later */
};
/*
* write (or format) operation will fall through and
* await completion interrupt
*/
#endif
fdc->state = IOCOMPLETE;
fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz);
return(0); /* will return later */
@ -1975,6 +2315,16 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
nrdsec = sec;
fdc->state = IOCOMPLETE;
}
#endif
#ifdef FDC_YE
case PIOREAD:
/*
* actually perform the PIO read. The IOCOMPLETE case
* removes the timeout for us.
*/
(void)fdcpio(fdcu,bp->b_flags,bp->b_data+fd->skip,fdblk);
fdc->state = IOCOMPLETE;
/* FALLTHROUGH */
#endif
case IOCOMPLETE: /* IO DONE, post-analyze */
#ifdef EPSON_NRDISK
@ -2002,8 +2352,11 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
#ifdef EPSON_NRDISK
if (fdu != nrdu) {
#endif /* EPSON_NRDISK */
isa_dmadone(bp->b_flags, bp->b_data + fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
#ifdef FDC_YE
if (!(fdc->flags & FDC_PCMCIA))
#endif
isa_dmadone(bp->b_flags, bp->b_data + fd->skip,
format ? bp->b_bcount : fdblk, fdc->dmachan);
#ifdef EPSON_NRDISK
}
else nrd_LED_off();