Merge with sys/i386/isa/wd.c revision 1.192 and 1.193.
Submitted by: Takahashi Yoshihiro <nyan@wyvern.cc.kogakuin.ac.jp>
This commit is contained in:
parent
87f01fc1bb
commit
9e3964cc57
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
|
||||
* $Id: wd.c,v 1.80 1999/05/07 07:03:44 phk Exp $
|
||||
* $Id: wd.c,v 1.81 1999/05/09 04:42:10 kato Exp $
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
@ -100,14 +100,7 @@
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
|
||||
#ifdef ATAPI
|
||||
#include <i386/isa/atapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef CMD640
|
||||
#include <i386/isa/wdc_p.h>
|
||||
#endif /*CMD640*/
|
||||
|
||||
extern void wdstart(int ctrlr);
|
||||
|
||||
@ -173,9 +166,7 @@ struct disk {
|
||||
u_int dk_bc; /* byte count left */
|
||||
short dk_skip; /* blocks already transferred */
|
||||
int dk_ctrlr; /* physical controller number */
|
||||
#ifdef CMD640
|
||||
int dk_ctrlr_cmd640;/* controller number for CMD640 quirk */
|
||||
#endif
|
||||
u_int32_t dk_unit; /* physical unit number */
|
||||
u_int32_t dk_lunit; /* logical unit number */
|
||||
u_int32_t dk_interface; /* interface (two ctrlrs per interface) */
|
||||
@ -210,9 +201,6 @@ struct disk {
|
||||
void *dk_dmacookie; /* handle for DMA services */
|
||||
|
||||
struct devstat dk_stats; /* devstat entry */
|
||||
#ifdef PC98
|
||||
short single_sector;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define WD_COUNT_RETRIES
|
||||
@ -288,25 +276,21 @@ static struct cdevsw wd_cdevsw = {
|
||||
D_DISK, 0, -1 };
|
||||
|
||||
|
||||
#ifdef CMD640
|
||||
static int atapictrlr;
|
||||
static int eide_quirks;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Here we use the pci-subsystem to find out, whether there is
|
||||
* a cmd640b-chip attached on this pci-bus. This public routine
|
||||
* will be called by wdc_p.c .
|
||||
* will be called by ide_pci.c
|
||||
*/
|
||||
|
||||
#ifdef CMD640
|
||||
void
|
||||
wdc_pci(int quirks)
|
||||
{
|
||||
eide_quirks = quirks;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Probe for controller.
|
||||
@ -368,20 +352,17 @@ wdprobe(struct isa_device *dvp)
|
||||
outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */
|
||||
outb(du->dk_port + wd_cyl_lo, 0xa5); /* wd_cyl_lo is read/write */
|
||||
if (inb(du->dk_port + wd_cyl_lo) == 0xff) { /* XXX too weak */
|
||||
#ifdef ATAPI
|
||||
/* There is no master, try the ATAPI slave. */
|
||||
du->dk_unit = 1;
|
||||
outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10);
|
||||
outb(du->dk_port + wd_cyl_lo, 0xa5);
|
||||
if (inb(du->dk_port + wd_cyl_lo) == 0xff)
|
||||
#endif
|
||||
goto nodevice;
|
||||
}
|
||||
#endif /* PC98 */
|
||||
|
||||
if (wdreset(du) == 0)
|
||||
goto reset_ok;
|
||||
#ifdef ATAPI
|
||||
/* test for ATAPI signature */
|
||||
outb(du->dk_port + wd_sdh, WDSD_IBM); /* master */
|
||||
if (inb(du->dk_port + wd_cyl_lo) == 0x14 &&
|
||||
@ -411,7 +392,6 @@ wdprobe(struct isa_device *dvp)
|
||||
if (inb(du->dk_port + wd_cyl_lo) == 0x14 &&
|
||||
inb(du->dk_port + wd_cyl_hi) == 0xeb)
|
||||
goto reset_ok;
|
||||
#endif
|
||||
#endif
|
||||
DELAY(RECOVERYTIME);
|
||||
if (wdreset(du) != 0) {
|
||||
@ -442,7 +422,7 @@ wdprobe(struct isa_device *dvp)
|
||||
du->dk_error = inb(du->dk_port + wd_error);
|
||||
|
||||
if(du->dk_error != 0x01 && du->dk_error != 0) {
|
||||
if(du->dk_error & 0x80) { /* drive 1 failure */
|
||||
if(du->dk_error & 0x80) { /* drive 1 failure */
|
||||
|
||||
/* first set the DRV bit */
|
||||
u_int sdh;
|
||||
@ -506,7 +486,6 @@ wdattach(struct isa_device *dvp)
|
||||
if (dvp->id_unit >= NWDC)
|
||||
return (0);
|
||||
|
||||
#ifdef CMD640
|
||||
if (eide_quirks & Q_CMD640B) {
|
||||
if (dvp->id_unit == PRIMARY) {
|
||||
printf("wdc0: CMD640B workaround enabled\n");
|
||||
@ -515,10 +494,6 @@ wdattach(struct isa_device *dvp)
|
||||
} else
|
||||
bufq_init(&wdtab[dvp->id_unit].controller_queue);
|
||||
|
||||
#else
|
||||
bufq_init(&wdtab[dvp->id_unit].controller_queue);
|
||||
#endif
|
||||
|
||||
sprintf(buf, "wdc%d", dvp->id_unit);
|
||||
for (i = resource_query_string(-1, "at", buf);
|
||||
i != -1;
|
||||
@ -552,13 +527,11 @@ wdattach(struct isa_device *dvp)
|
||||
bufq_init(&drive_queue[lunit]);
|
||||
bzero(du, sizeof *du);
|
||||
du->dk_ctrlr = dvp->id_unit;
|
||||
#ifdef CMD640
|
||||
if (eide_quirks & Q_CMD640B) {
|
||||
du->dk_ctrlr_cmd640 = PRIMARY;
|
||||
} else {
|
||||
du->dk_ctrlr_cmd640 = du->dk_ctrlr;
|
||||
}
|
||||
#endif
|
||||
du->dk_unit = unit;
|
||||
du->dk_lunit = lunit;
|
||||
du->dk_port = dvp->id_iobase;
|
||||
@ -651,11 +624,6 @@ wdattach(struct isa_device *dvp)
|
||||
wddrives[lunit] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PC98
|
||||
outb(0x432,(du->dk_unit)%2);
|
||||
#endif
|
||||
#ifdef ATAPI
|
||||
/*
|
||||
* Probe all free IDE units, searching for ATAPI drives.
|
||||
*/
|
||||
@ -670,28 +638,19 @@ wdattach(struct isa_device *dvp)
|
||||
wddrives[lunit]->dk_ctrlr == dvp->id_unit &&
|
||||
wddrives[lunit]->dk_unit == unit)
|
||||
goto next;
|
||||
#ifdef CMD640
|
||||
if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase))
|
||||
atapictrlr = dvp->id_unit;
|
||||
#else
|
||||
atapi_attach (dvp->id_unit, unit, dvp->id_iobase);
|
||||
#endif
|
||||
next: ;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Discard any interrupts generated by wdgetctlr(). wdflushirq()
|
||||
* doesn't work now because the ambient ipl is too high.
|
||||
*/
|
||||
#ifdef CMD640
|
||||
if (eide_quirks & Q_CMD640B) {
|
||||
wdtab[PRIMARY].b_active = 2;
|
||||
} else {
|
||||
wdtab[dvp->id_unit].b_active = 2;
|
||||
}
|
||||
#else
|
||||
wdtab[dvp->id_unit].b_active = 2;
|
||||
#endif
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -770,11 +729,7 @@ wdstrategy(register struct buf *bp)
|
||||
if (wdutab[lunit].b_active == 0)
|
||||
wdustart(du); /* start drive */
|
||||
|
||||
#ifdef CMD640
|
||||
if (wdtab[du->dk_ctrlr_cmd640].b_active == 0)
|
||||
#else
|
||||
if (wdtab[du->dk_ctrlr].b_active == 0)
|
||||
#endif
|
||||
wdstart(du->dk_ctrlr); /* start controller */
|
||||
|
||||
/* Tell devstat that we have started a transaction on this drive */
|
||||
@ -807,11 +762,7 @@ static void
|
||||
wdustart(register struct disk *du)
|
||||
{
|
||||
register struct buf *bp;
|
||||
#ifdef CMD640
|
||||
int ctrlr = du->dk_ctrlr_cmd640;
|
||||
#else
|
||||
int ctrlr = du->dk_ctrlr;
|
||||
#endif
|
||||
|
||||
#ifdef PC98
|
||||
outb(0x432,(du->dk_unit)%2);
|
||||
@ -858,7 +809,6 @@ wdstart(int ctrlr)
|
||||
long secpertrk, secpercyl;
|
||||
u_int lunit;
|
||||
u_int count;
|
||||
#ifdef CMD640
|
||||
int ctrlr_atapi;
|
||||
|
||||
if (eide_quirks & Q_CMD640B) {
|
||||
@ -867,27 +817,17 @@ wdstart(int ctrlr)
|
||||
} else {
|
||||
ctrlr_atapi = ctrlr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ATAPI
|
||||
if (wdtab[ctrlr].b_active == 2)
|
||||
wdtab[ctrlr].b_active = 0;
|
||||
if (wdtab[ctrlr].b_active)
|
||||
return;
|
||||
#endif
|
||||
/* is there a drive for the controller to do a transfer with? */
|
||||
bp = bufq_first(&wdtab[ctrlr].controller_queue);
|
||||
if (bp == NULL) {
|
||||
#ifdef ATAPI
|
||||
#ifdef CMD640
|
||||
if (atapi_start && atapi_start (ctrlr_atapi))
|
||||
wdtab[ctrlr].b_active = 3;
|
||||
#else
|
||||
if (atapi_start && atapi_start (ctrlr))
|
||||
/* mark controller active in ATAPI mode */
|
||||
wdtab[ctrlr].b_active = 3;
|
||||
#endif
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -897,9 +837,6 @@ wdstart(int ctrlr)
|
||||
|
||||
#ifdef PC98
|
||||
outb(0x432,(du->dk_unit)%2);
|
||||
if ( du->single_sector == 1 ) {
|
||||
du->dk_flags |= DKFL_SINGLE; /* XXX */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if not really a transfer, do control operations specially */
|
||||
@ -1157,7 +1094,6 @@ wdintr(void *unitnum)
|
||||
int dmastat = 0; /* Shut up GCC */
|
||||
int unit = (int)unitnum;
|
||||
|
||||
#ifdef CMD640
|
||||
int ctrlr_atapi;
|
||||
|
||||
if (eide_quirks & Q_CMD640B) {
|
||||
@ -1166,7 +1102,6 @@ wdintr(void *unitnum)
|
||||
} else {
|
||||
ctrlr_atapi = unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wdtab[unit].b_active == 2)
|
||||
return; /* intr in wdflushirq() */
|
||||
@ -1181,14 +1116,9 @@ wdintr(void *unitnum)
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef ATAPI
|
||||
if (wdtab[unit].b_active == 3) {
|
||||
/* process an ATAPI interrupt */
|
||||
#ifdef CMD640
|
||||
if (atapi_intr && atapi_intr (ctrlr_atapi))
|
||||
#else
|
||||
if (atapi_intr && atapi_intr (unit))
|
||||
#endif
|
||||
/* ATAPI op continues */
|
||||
return;
|
||||
/* controller is free, start new op */
|
||||
@ -1196,7 +1126,6 @@ wdintr(void *unitnum)
|
||||
wdstart (unit);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bp = bufq_first(&wdtab[unit].controller_queue);
|
||||
du = wddrives[dkunit(bp->b_dev)];
|
||||
|
||||
@ -1400,11 +1329,7 @@ done: ;
|
||||
/* anything more on drive queue? */
|
||||
wdustart(du);
|
||||
/* anything more for controller to do? */
|
||||
#ifndef ATAPI
|
||||
/* This is not valid in ATAPI mode. */
|
||||
if (bufq_first(&wdtab[unit].controller_queue) != NULL)
|
||||
#endif
|
||||
wdstart(unit);
|
||||
wdstart(unit);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1429,13 +1354,8 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
|
||||
#endif
|
||||
|
||||
/* Finish flushing IRQs left over from wdattach(). */
|
||||
#ifdef CMD640
|
||||
if (wdtab[du->dk_ctrlr_cmd640].b_active == 2)
|
||||
wdtab[du->dk_ctrlr_cmd640].b_active = 0;
|
||||
#else
|
||||
if (wdtab[du->dk_ctrlr].b_active == 2)
|
||||
wdtab[du->dk_ctrlr].b_active = 0;
|
||||
#endif
|
||||
|
||||
du->dk_flags &= ~DKFL_BADSCAN;
|
||||
|
||||
@ -1601,11 +1521,7 @@ wdcontrol(register struct buf *bp)
|
||||
int ctrlr;
|
||||
|
||||
du = wddrives[dkunit(bp->b_dev)];
|
||||
#ifdef CMD640
|
||||
ctrlr = du->dk_ctrlr_cmd640;
|
||||
#else
|
||||
ctrlr = du->dk_ctrlr;
|
||||
#endif
|
||||
|
||||
#ifdef PC98
|
||||
outb(0x432,(du->dk_unit)%2);
|
||||
@ -1751,7 +1667,7 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
|
||||
outb(wdc + wd_sector, sector);
|
||||
else
|
||||
outb(wdc + wd_sector, sector + 1);
|
||||
outb(wdc + wd_seccnt, count);
|
||||
outb(wdc + wd_seccnt, count);
|
||||
}
|
||||
}
|
||||
if (wdwait(du, (command == WDCC_DIAGNOSE || command == WDCC_IDC)
|
||||
@ -1829,11 +1745,7 @@ wdsetctlr(struct disk *du)
|
||||
error = 1;
|
||||
}
|
||||
if (error) {
|
||||
#ifdef CMD640
|
||||
wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES;
|
||||
#else
|
||||
wdtab[du->dk_ctrlr].b_errcnt += RETRIES;
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
|
||||
@ -2504,17 +2416,10 @@ wderror(struct buf *bp, struct disk *du, char *mesg)
|
||||
static void
|
||||
wdflushirq(struct disk *du, int old_ipl)
|
||||
{
|
||||
#ifdef CMD640
|
||||
wdtab[du->dk_ctrlr_cmd640].b_active = 2;
|
||||
splx(old_ipl);
|
||||
(void)splbio();
|
||||
wdtab[du->dk_ctrlr_cmd640].b_active = 0;
|
||||
#else
|
||||
wdtab[du->dk_ctrlr].b_active = 2;
|
||||
splx(old_ipl);
|
||||
(void)splbio();
|
||||
wdtab[du->dk_ctrlr].b_active = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2530,7 +2435,7 @@ wdreset(struct disk *du)
|
||||
#endif
|
||||
if ((du->dk_flags & (DKFL_DMA|DKFL_SINGLE)) == DKFL_DMA)
|
||||
wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie);
|
||||
(void)wdwait(du, 0, TIMEOUT);
|
||||
(void)wdwait(du, 0, TIMEOUT);
|
||||
#ifdef PC98
|
||||
if (old_epson_note) {
|
||||
epson_outb(du->dk_altport, WDCTL_IDS | WDCTL_RST);
|
||||
@ -2544,22 +2449,15 @@ wdreset(struct disk *du)
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
outb(du->dk_altport, WDCTL_IDS | WDCTL_RST);
|
||||
DELAY(10 * 1000);
|
||||
outb(du->dk_altport, WDCTL_IDS);
|
||||
outb(du->dk_altport, WDCTL_IDS | WDCTL_RST);
|
||||
DELAY(10 * 1000);
|
||||
outb(du->dk_altport, WDCTL_IDS);
|
||||
outb(du->dk_port + wd_sdh, WDSD_IBM | (du->dk_unit << 4));
|
||||
#ifdef ATAPI
|
||||
if (wdwait(du, 0, TIMEOUT) != 0)
|
||||
err = 1; /* no IDE drive found */
|
||||
du->dk_error = inb(du->dk_port + wd_error);
|
||||
if (du->dk_error != 0x01)
|
||||
err = 1; /* the drive is incompatible */
|
||||
#else
|
||||
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) {
|
||||
printf("wdreset: error1: 0x%x\n", du->dk_error);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
err = 1; /* no IDE drive found */
|
||||
du->dk_error = inb(du->dk_port + wd_error);
|
||||
if (du->dk_error != 0x01)
|
||||
err = 1; /* the drive is incompatible */
|
||||
outb(du->dk_altport, WDCTL_4BIT);
|
||||
#ifdef PC98
|
||||
}
|
||||
@ -2576,10 +2474,8 @@ static void
|
||||
wdsleep(int ctrlr, char *wmesg)
|
||||
{
|
||||
int s = splbio();
|
||||
#ifdef CMD640
|
||||
if (eide_quirks & Q_CMD640B)
|
||||
ctrlr = PRIMARY;
|
||||
#endif
|
||||
while (wdtab[ctrlr].b_active)
|
||||
tsleep((caddr_t)&wdtab[ctrlr].b_active, PZERO - 1, wmesg, 1);
|
||||
splx(s);
|
||||
@ -2685,7 +2581,7 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
|
||||
|
||||
/*
|
||||
* This delay is really too long, but does not impact the performance
|
||||
* as much when using the NSECS_MULTI option. Shorter delays have
|
||||
* as much when using the multi-sector option. Shorter delays have
|
||||
* caused I/O errors on some drives and system configs. This should
|
||||
* probably be fixed if we develop a better short term delay mechanism.
|
||||
*/
|
||||
@ -2705,7 +2601,6 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
|
||||
#else
|
||||
du->dk_status = status = inb(wdc + wd_status);
|
||||
#endif
|
||||
#ifdef ATAPI
|
||||
/*
|
||||
* Atapi drives have a very interesting feature, when attached
|
||||
* as a slave on the IDE bus, and there is no master.
|
||||
@ -2716,7 +2611,6 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
|
||||
outb(wdc + wd_sdh, WDSD_IBM | du->dk_unit << 4);
|
||||
du->dk_status = status = inb(wdc + wd_status);
|
||||
}
|
||||
#endif
|
||||
if (!(status & WDCS_BUSY)) {
|
||||
if (status & WDCS_ERR) {
|
||||
if (old_epson_note)
|
||||
|
Loading…
Reference in New Issue
Block a user