- Changed the structure name (struct disk -> struct softc).

- Converted to disk_create() interface.
- Removed unnecessary code.
This commit is contained in:
Yoshihiro Takahashi 2000-09-14 11:45:31 +00:00
parent 5c1a8c13c7
commit c400e7405e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=65831

View file

@ -66,6 +66,7 @@
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h>
#include <sys/bio.h>
@ -154,7 +155,7 @@ struct diskgeom {
/*
* The structure of a disk drive.
*/
struct disk {
struct softc {
u_int dk_bc; /* byte count left */
short dk_skip; /* blocks already transferred */
int dk_ctrlr; /* physical controller number */
@ -189,12 +190,14 @@ struct disk {
void *dk_dmacookie; /* handle for DMA services */
struct devstat dk_stats; /* devstat entry */
struct disk disk;
};
#define WD_COUNT_RETRIES
static int wdtest = 0;
static struct disk *wddrives[NWD]; /* table of units */
static struct softc *wddrives[NWD]; /* table of units */
static struct bio_queue_head drive_queue[NWD]; /* head of queue per drive */
static struct {
int b_active;
@ -220,23 +223,23 @@ static int old_epson_note;
static int wdprobe(struct isa_device *dvp);
static int wdattach(struct isa_device *dvp);
static void wdustart(struct disk *du);
static void wdustart(struct softc *du);
static int wdcontrol(struct bio *bp);
static int wdcommand(struct disk *du, u_int cylinder, u_int head,
static int wdcommand(struct softc *du, u_int cylinder, u_int head,
u_int sector, u_int count, u_int command);
static int wdsetctlr(struct disk *du);
static int wdsetctlr(struct softc *du);
#if 0
static int wdwsetctlr(struct disk *du);
static int wdwsetctlr(struct softc *du);
#endif
static int wdsetmode(int mode, void *wdinfo);
static int wdgetctlr(struct disk *du);
static void wderror(struct bio *bp, struct disk *du, char *mesg);
static void wdflushirq(struct disk *du, int old_ipl);
static int wdreset(struct disk *du);
static int wdgetctlr(struct softc *du);
static void wderror(struct bio *bp, struct softc *du, char *mesg);
static void wdflushirq(struct softc *du, int old_ipl);
static int wdreset(struct softc *du);
static void wdsleep(int ctrlr, char *wmesg);
static timeout_t wdtimeout;
static int wdunwedge(struct disk *du);
static int wdwait(struct disk *du, u_char bits_wanted, int timeout);
static int wdunwedge(struct softc *du);
static int wdwait(struct softc *du, u_char bits_wanted, int timeout);
struct isa_driver wdcdriver = {
INTR_TYPE_BIO,
@ -247,32 +250,30 @@ struct isa_driver wdcdriver = {
COMPAT_ISA_DRIVER(wdc, wdcdriver);
static d_open_t wdopen;
static d_close_t wdclose;
static d_strategy_t wdstrategy;
static d_ioctl_t wdioctl;
static d_dump_t wddump;
static d_psize_t wdsize;
#define CDEV_MAJOR 3
#define BDEV_MAJOR 0
static struct cdevsw wd_cdevsw = {
/* open */ wdopen,
/* close */ wdclose,
/* close */ nullclose,
/* read */ physread,
/* write */ physwrite,
/* ioctl */ wdioctl,
/* ioctl */ noioctl,
/* poll */ nopoll,
/* mmap */ nommap,
/* strategy */ wdstrategy,
/* name */ "wd",
/* maj */ CDEV_MAJOR,
/* dump */ wddump,
/* psize */ wdsize,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ D_DISK,
/* bmaj */ BDEV_MAJOR
};
static struct cdevsw wddisk_cdevsw;
static int atapictrlr;
static int eide_quirks;
@ -297,7 +298,7 @@ wdprobe(struct isa_device *dvp)
{
int unit = dvp->id_unit;
int interface;
struct disk *du;
struct softc *du;
if (unit >= NWDC)
return (0);
@ -471,21 +472,15 @@ static int
wdattach(struct isa_device *dvp)
{
int unit, lunit, flags, i;
struct disk *du;
struct softc *du;
struct wdparams *wp;
static char buf[] = "wdcXXX";
static int once;
dvp->id_intr = wdintr;
if (dvp->id_unit >= NWDC)
return (0);
if (!once) {
cdevsw_add(&wd_cdevsw);
once++;
}
if (eide_quirks & Q_CMD640B) {
if (dvp->id_unit == PRIMARY) {
printf("wdc0: CMD640B workaround enabled\n");
@ -597,10 +592,6 @@ wdattach(struct isa_device *dvp)
*/
wdtimeout(du);
make_dev(&wd_cdevsw,
dkmakeminor(lunit, WHOLE_DISK_SLICE, RAW_PART),
UID_ROOT, GID_OPERATOR, 0640, "rwd%d", lunit);
/*
* Export the drive to the devstat interface.
*/
@ -611,6 +602,11 @@ wdattach(struct isa_device *dvp)
DEVSTAT_TYPE_IF_IDE,
DEVSTAT_PRIORITY_DISK);
/*
* Register this media as a disk
*/
disk_create(lunit, &du->disk, 0, &wd_cdevsw,
&wddisk_cdevsw);
} else {
free(du, M_TEMP);
wddrives[lunit] = NULL;
@ -655,7 +651,7 @@ next: ;
void
wdstrategy(register struct bio *bp)
{
struct disk *du;
struct softc *du;
int lunit = dkunit(bp->bio_dev);
int s;
@ -672,12 +668,6 @@ wdstrategy(register struct bio *bp)
outb(0x432,(du->dk_unit)%2);
#endif
/*
* Do bounds checking, adjust transfer, and set bio_pblkno.
*/
if (dscheck(bp, du->dk_slices) <= 0)
goto done;
/* queue transfer on drive, activate drive and controller if idle */
s = splbio();
@ -712,7 +702,7 @@ wdstrategy(register struct bio *bp)
* If the controller is idle, the transfer is started.
*/
static void
wdustart(register struct disk *du)
wdustart(register struct softc *du)
{
register struct bio *bp;
int ctrlr = du->dk_ctrlr_cmd640;
@ -755,7 +745,7 @@ wdustart(register struct disk *du)
void
wdstart(int ctrlr)
{
register struct disk *du;
register struct softc *du;
register struct bio *bp;
struct diskgeom *lp; /* XXX sic */
long blknum;
@ -1012,7 +1002,7 @@ wdstart(int ctrlr)
void
wdintr(void *unitnum)
{
register struct disk *du;
register struct softc *du;
register struct bio *bp;
int dmastat = 0; /* Shut up GCC */
int unit = (int)unitnum;
@ -1246,8 +1236,8 @@ int
wdopen(dev_t dev, int flags, int fmt, struct proc *p)
{
register unsigned int lunit;
register struct disk *du;
int error;
register struct softc *du;
struct disklabel *dl;
lunit = dkunit(dev);
if (lunit >= NWD || dktype(dev) != 0)
@ -1270,146 +1260,24 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
/* spin waiting for anybody else reading the disk label */
while (du->dk_flags & DKFL_LABELLING)
tsleep((caddr_t)&du->dk_flags, PZERO - 1, "wdopen", 1);
#if 1
wdsleep(du->dk_ctrlr, "wdopn1");
du->dk_flags |= DKFL_LABELLING;
du->dk_state = WANTOPEN;
{
struct disklabel label;
bzero(&label, sizeof label);
label.d_secsize = du->dk_dd.d_secsize;
label.d_nsectors = du->dk_dd.d_nsectors;
label.d_ntracks = du->dk_dd.d_ntracks;
label.d_ncylinders = du->dk_dd.d_ncylinders;
label.d_secpercyl = du->dk_dd.d_secpercyl;
label.d_secperunit = du->dk_dd.d_secperunit;
error = dsopen(dev, fmt, 0, &du->dk_slices, &label);
}
dl = &du->disk.d_label;
bzero(dl, sizeof(*dl));
dl->d_secsize = du->dk_dd.d_secsize;
dl->d_nsectors = du->dk_dd.d_nsectors;
dl->d_ntracks = du->dk_dd.d_ntracks;
dl->d_ncylinders = du->dk_dd.d_ncylinders;
dl->d_secpercyl = du->dk_dd.d_secpercyl;
dl->d_secperunit = du->dk_dd.d_secperunit;
du->dk_flags &= ~DKFL_LABELLING;
wdsleep(du->dk_ctrlr, "wdopn2");
return (error);
#else
if ((du->dk_flags & DKFL_BSDLABEL) == 0) {
/*
* wdtab[ctrlr].b_active != 0 implies XXX applicable now ??
* drive_queue[lunit].b_act == NULL (?) XXX applicable now ??
* so the following guards most things (until the next i/o).
* It doesn't guard against a new i/o starting and being
* affected by the label being changed. Sigh.
*/
wdsleep(du->dk_ctrlr, "wdopn1");
du->dk_flags |= DKFL_LABELLING;
du->dk_state = WANTOPEN;
error = dsinit(dkmodpart(dev, RAW_PART),
&du->dk_dd, &du->dk_slices);
if (error != 0) {
du->dk_flags &= ~DKFL_LABELLING;
return (error);
}
/* XXX check value returned by wdwsetctlr(). */
wdwsetctlr(du);
if (dkslice(dev) == WHOLE_DISK_SLICE) {
dsopen(dev, fmt, du->dk_slices);
return (0);
}
/*
* Read label using RAW_PART partition.
*
* If the drive has an MBR, then the current geometry (from
* wdgetctlr()) is used to read it; then the BIOS/DOS
* geometry is inferred and used to read the label off the
* 'c' partition. Otherwise the label is read using the
* current geometry. The label gives the final geometry.
* If bad sector handling is enabled, then this geometry
* is used to read the bad sector table. The geometry
* changes occur inside readdisklabel() and are propagated
* to the driver by resetting the state machine.
*
* XXX can now handle changes directly since dsinit() doesn't
* do too much.
*/
msg = correct_readdisklabel(dkmodpart(dev, RAW_PART),
&du->dk_dd);
/* XXX check value returned by wdwsetctlr(). */
wdwsetctlr(du);
du->dk_flags &= ~DKFL_LABELLING;
if (msg != NULL) {
log(LOG_WARNING, "wd%d: cannot find label (%s)\n",
lunit, msg);
if (part != RAW_PART)
return (EINVAL); /* XXX needs translation */
/*
* Soon return. This is how slices without labels
* are allowed. They only work on the raw partition.
*/
} else {
unsigned long newsize, offset, size;
#if 0
/*
* Force RAW_PART partition to be the whole disk.
*/
offset = du->dk_dd.d_partitions[RAW_PART].p_offset;
if (offset != 0) {
printf(
"wd%d: changing offset of '%c' partition from %lu to 0\n",
du->dk_lunit, 'a' + RAW_PART, offset);
du->dk_dd.d_partitions[RAW_PART].p_offset = 0;
}
size = du->dk_dd.d_partitions[RAW_PART].p_size;
newsize = du->dk_dd.d_secperunit; /* XXX */
if (size != newsize) {
printf(
"wd%d: changing size of '%c' partition from %lu to %lu\n",
du->dk_lunit, 'a' + RAW_PART, size,
newsize);
du->dk_dd.d_partitions[RAW_PART].p_size
= newsize;
}
#endif
}
/* Pick up changes made by readdisklabel(). */
wdsleep(du->dk_ctrlr, "wdopn2");
du->dk_state = WANTOPEN;
}
/*
* Warn if a partion is opened that overlaps another partition which
* is open unless one is the "raw" partition (whole disk).
*/
if ((du->dk_openpart & mask) == 0 && part != RAW_PART) {
int start, end;
pp = &du->dk_dd.d_partitions[part];
start = pp->p_offset;
end = pp->p_offset + pp->p_size;
for (pp = du->dk_dd.d_partitions;
pp < &du->dk_dd.d_partitions[du->dk_dd.d_npartitions];
pp++) {
if (pp->p_offset + pp->p_size <= start ||
pp->p_offset >= end)
continue;
if (pp - du->dk_dd.d_partitions == RAW_PART)
continue;
if (du->dk_openpart
& (1 << (pp - du->dk_dd.d_partitions)))
log(LOG_WARNING,
"wd%d%c: overlaps open partition (%c)\n",
lunit, part + 'a',
pp - du->dk_dd.d_partitions + 'a');
}
}
if (part >= du->dk_dd.d_npartitions && part != RAW_PART)
return (ENXIO);
dsopen(dev, fmt, du->dk_slices);
return (0);
#endif
return 0;
}
/*
@ -1421,7 +1289,7 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
static int
wdcontrol(register struct bio *bp)
{
register struct disk *du;
register struct softc *du;
int ctrlr;
du = wddrives[dkunit(bp->bio_dev)];
@ -1472,7 +1340,7 @@ wdcontrol(register struct bio *bp)
* command to terminate.
*/
static int
wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
wdcommand(struct softc *du, u_int cylinder, u_int head, u_int sector,
u_int count, u_int command)
{
u_int wdc;
@ -1585,7 +1453,7 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
}
static void
wdsetmulti(struct disk *du)
wdsetmulti(struct softc *du)
{
/*
* The config option flags low 8 bits define the maximum multi-block
@ -1612,7 +1480,7 @@ wdsetmulti(struct disk *du)
* issue IDC to drive to tell it just what geometry it is to be.
*/
static int
wdsetctlr(struct disk *du)
wdsetctlr(struct softc *du)
{
int error = 0;
#ifdef PC98
@ -1679,7 +1547,7 @@ wdsetctlr(struct disk *du)
* Wait until driver is inactive, then set up controller.
*/
static int
wdwsetctlr(struct disk *du)
wdwsetctlr(struct softc *du)
{
int stat;
int x;
@ -1701,7 +1569,7 @@ static int
wdsetmode(int mode, void *wdinfo)
{
int i;
struct disk *du;
struct softc *du;
du = wdinfo;
if (bootverbose)
@ -1717,7 +1585,7 @@ wdsetmode(int mode, void *wdinfo)
* issue READP to drive to ask it what it is.
*/
static int
wdgetctlr(struct disk *du)
wdgetctlr(struct softc *du)
{
int i;
char tb[DEV_BSIZE], tb2[DEV_BSIZE];
@ -2008,235 +1876,8 @@ wdgetctlr(struct disk *du)
return (0);
}
int
wdclose(dev_t dev, int flags, int fmt, struct proc *p)
{
dsclose(dev, fmt, wddrives[dkunit(dev)]->dk_slices);
return (0);
}
int
wdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
{
int lunit = dkunit(dev);
register struct disk *du;
int error;
du = wddrives[lunit];
wdsleep(du->dk_ctrlr, "wdioct");
error = dsioctl(dev, cmd, addr, flags, &du->dk_slices);
if (error != ENOIOCTL)
return (error);
#ifdef PC98
outb(0x432,(du->dk_unit)%2);
#endif
return (ENOTTY);
}
int
wdsize(dev_t dev)
{
struct disk *du;
int lunit;
lunit = dkunit(dev);
if (lunit >= NWD || dktype(dev) != 0)
return (-1);
du = wddrives[lunit];
if (du == NULL)
return (-1);
#ifdef PC98
outb(0x432,(du->dk_unit)%2);
#endif
return (dssize(dev, &du->dk_slices));
}
int
wddump(dev_t dev)
{
#ifdef PC98
/* do nothing */
printf("wddump!!\n");
return(0);
#else
register struct disk *du;
struct disklabel *lp;
long num; /* number of sectors to write */
int lunit, part;
long blkoff, blknum;
long blkcnt, blknext;
u_long ds_offset;
u_long nblocks;
static int wddoingadump = 0;
long cylin, head, sector;
long secpertrk, secpercyl;
char *addr;
/* Toss any characters present prior to dump. */
while (cncheckc() != -1)
;
/* Check for acceptable device. */
/* XXX should reset to maybe allow du->dk_state < OPEN. */
lunit = dkunit(dev); /* eventually support floppies? */
part = dkpart(dev);
if (lunit >= NWD || (du = wddrives[lunit]) == NULL
|| du->dk_state < OPEN
|| (lp = dsgetlabel(dev, du->dk_slices)) == NULL)
return (ENXIO);
#ifdef PC98
outb(0x432,(du->dk_unit)%2);
#endif
/* Size of memory to dump, in disk sectors. */
num = (u_long)Maxmem * PAGE_SIZE / du->dk_dd.d_secsize;
secpertrk = du->dk_dd.d_nsectors;
secpercyl = du->dk_dd.d_secpercyl;
nblocks = lp->d_partitions[part].p_size;
blkoff = lp->d_partitions[part].p_offset;
/* XXX */
ds_offset = du->dk_slices->dss_slices[dkslice(dev)].ds_offset;
blkoff += ds_offset;
#if 0
printf("part %d, nblocks %lu, dumplo %ld num %ld\n",
part, nblocks, dumplo, num);
#endif
/* Check transfer bounds against partition size. */
if (dumplo < 0 || dumplo + num > nblocks)
return (EINVAL);
/* Check if we are being called recursively. */
if (wddoingadump)
return (EFAULT);
#if 0
/* Mark controller active for if we panic during the dump. */
wdtab[du->dk_ctrlr].b_active = 1;
#endif
wddoingadump = 1;
/* Recalibrate the drive. */
DELAY(5); /* ATA spec XXX NOT */
if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
|| wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
|| wdsetctlr(du) != 0) {
wderror((struct bio *)NULL, du, "wddump: recalibrate failed");
return (EIO);
}
du->dk_flags |= DKFL_SINGLE;
addr = (char *) 0;
blknum = dumplo + blkoff;
while (num > 0) {
blkcnt = num;
if (blkcnt > MAXTRANSFER)
blkcnt = MAXTRANSFER;
if ((du->dk_flags & DKFL_LBA) == 0) {
/* XXX keep transfer within current cylinder. */
if ((blknum + blkcnt - 1) / secpercyl !=
blknum / secpercyl)
blkcnt = secpercyl - (blknum % secpercyl);
}
blknext = blknum + blkcnt;
/* Compute disk address. */
if (du->dk_flags & DKFL_LBA) {
sector = (blknum >> 0) & 0xff;
cylin = (blknum >> 8) & 0xffff;
head = ((blknum >> 24) & 0xf) | WDSD_LBA;
} else {
cylin = blknum / secpercyl;
head = (blknum % secpercyl) / secpertrk;
sector = blknum % secpertrk;
}
#if 0
/* Let's just talk about this first... */
printf("cylin %ld head %ld sector %ld addr %p count %ld\n",
cylin, head, sector, addr, blkcnt);
cngetc();
#endif
/* Do the write. */
if (wdcommand(du, cylin, head, sector, blkcnt, WDCC_WRITE)
!= 0) {
wderror((struct bio *)NULL, du,
"wddump: timeout waiting to to give command");
return (EIO);
}
while (blkcnt != 0) {
if (is_physical_memory((vm_offset_t)addr))
pmap_kenter((vm_offset_t)CADDR1,
trunc_page((vm_offset_t)addr));
else
pmap_kenter((vm_offset_t)CADDR1, trunc_page(0));
/* Ready to send data? */
DELAY(5); /* ATA spec */
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT)
< 0) {
wderror((struct bio *)NULL, du,
"wddump: timeout waiting for DRQ");
return (EIO);
}
if (du->dk_flags & DKFL_32BIT)
outsl(du->dk_port + wd_data,
CADDR1 + ((int)addr & PAGE_MASK),
DEV_BSIZE / sizeof(long));
else
outsw(du->dk_port + wd_data,
CADDR1 + ((int)addr & PAGE_MASK),
DEV_BSIZE / sizeof(short));
addr += DEV_BSIZE;
/*
* If we are dumping core, it may take a while.
* So reassure the user and hold off any watchdogs.
*/
if ((unsigned)addr % (1024 * 1024) == 0) {
#ifdef HW_WDOG
if (wdog_tickler)
(*wdog_tickler)();
#endif /* HW_WDOG */
printf("%ld ", num / (1024 * 1024 / DEV_BSIZE));
}
num--;
blkcnt--;
}
/* Wait for completion. */
DELAY(5); /* ATA spec XXX NOT */
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) < 0) {
wderror((struct bio *)NULL, du,
"wddump: timeout waiting for status");
return (EIO);
}
/* Check final status. */
if ((du->dk_status
& (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ | WDCS_ERR))
!= (WDCS_READY | WDCS_SEEKCMPLT)) {
wderror((struct bio *)NULL, du,
"wddump: extra DRQ, or error");
return (EIO);
}
/* Update block count. */
blknum = blknext;
/* Operator aborting dump? */
if (cncheckc() != -1)
return (EINTR);
}
return (0);
#endif
}
static void
wderror(struct bio *bp, struct disk *du, char *mesg)
wderror(struct bio *bp, struct softc *du, char *mesg)
{
if (bp == NULL)
printf("wd%d: %s", du->dk_lunit, mesg);
@ -2252,7 +1893,7 @@ wderror(struct bio *bp, struct disk *du, char *mesg)
* we were doing polled i/o.
*/
static void
wdflushirq(struct disk *du, int old_ipl)
wdflushirq(struct softc *du, int old_ipl)
{
wdtab[du->dk_ctrlr_cmd640].b_active = 2;
splx(old_ipl);
@ -2264,7 +1905,7 @@ wdflushirq(struct disk *du, int old_ipl)
* Reset the controller.
*/
static int
wdreset(struct disk *du)
wdreset(struct softc *du)
{
int err = 0;
@ -2322,11 +1963,11 @@ wdsleep(int ctrlr, char *wmesg)
static void
wdtimeout(void *cdu)
{
struct disk *du;
struct softc *du;
int x;
static int timeouts;
du = (struct disk *)cdu;
du = (struct softc *)cdu;
x = splbio();
#ifdef PC98
outb(0x432,(du->dk_unit)%2);
@ -2361,9 +2002,9 @@ wdtimeout(void *cdu)
* can restore the geometry .
*/
static int
wdunwedge(struct disk *du)
wdunwedge(struct softc *du)
{
struct disk *du1;
struct softc *du1;
int lunit;
#ifdef PC98
@ -2407,7 +2048,7 @@ static int min_retries[NWDC];
#endif
static int
wdwait(struct disk *du, u_char bits_wanted, int timeout)
wdwait(struct softc *du, u_char bits_wanted, int timeout)
{
int wdc;
u_char status;