Implement an atabus control device, and define some ATA bus control
IOCTLS. Implement ATABUSIORESET, which will reset the given ATA bus.
This commit is contained in:
parent
b4ae48a794
commit
011181ac3e
@ -1,4 +1,4 @@
|
||||
# $NetBSD: majors,v 1.9 2004/06/18 15:02:29 christos Exp $
|
||||
# $NetBSD: majors,v 1.10 2004/08/01 21:40:41 bouyer Exp $
|
||||
#
|
||||
# Device majors for Machine-Independent drivers.
|
||||
#
|
||||
@ -15,3 +15,4 @@ device-major vinum char 162 block 162 vinum
|
||||
device-major fss char 163 block 163 fss
|
||||
device-major pps char 164 pps
|
||||
device-major ptm char 165 pty
|
||||
device-major atabus char 166 atabus
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ata.c,v 1.29 2004/05/27 02:23:12 thorpej Exp $ */
|
||||
/* $NetBSD: ata.c,v 1.30 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.29 2004/05/27 02:23:12 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.30 2004/08/01 21:40:41 bouyer Exp $");
|
||||
|
||||
#ifndef WDCDEBUG
|
||||
#define WDCDEBUG
|
||||
@ -41,9 +41,12 @@ __KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.29 2004/05/27 02:23:12 thorpej Exp $");
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ataio.h>
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
@ -74,6 +77,18 @@ extern int wdcdebug_mask; /* init'ed in wdc.c */
|
||||
* for drives, etc.
|
||||
*****************************************************************************/
|
||||
|
||||
dev_type_open(atabusopen);
|
||||
dev_type_close(atabusclose);
|
||||
dev_type_ioctl(atabusioctl);
|
||||
|
||||
const struct cdevsw atabus_cdevsw = {
|
||||
atabusopen, atabusclose, noread, nowrite, atabusioctl,
|
||||
nostop, notty, nopoll, nommap, nokqfilter,
|
||||
};
|
||||
|
||||
extern struct cfdriver atabus_cd;
|
||||
|
||||
|
||||
/*
|
||||
* atabusprint:
|
||||
*
|
||||
@ -481,3 +496,81 @@ ata_dmaerr(struct ata_drive_datas *drvp, int flags)
|
||||
drvp->n_xfers = 1; /* restart counting from this error */
|
||||
}
|
||||
}
|
||||
|
||||
/* management of the /dev/atabus* devices */
|
||||
int atabusopen(dev, flag, fmt, p)
|
||||
dev_t dev;
|
||||
int flag, fmt;
|
||||
struct proc *p;
|
||||
{
|
||||
struct atabus_softc *sc;
|
||||
int error, unit = minor(dev);
|
||||
|
||||
if (unit >= atabus_cd.cd_ndevs ||
|
||||
(sc = atabus_cd.cd_devs[unit]) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (sc->sc_flags & ATABUSCF_OPEN)
|
||||
return (EBUSY);
|
||||
|
||||
if ((error = wdc_addref(sc->sc_chan)) != 0)
|
||||
return (error);
|
||||
|
||||
sc->sc_flags |= ATABUSCF_OPEN;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
atabusclose(dev, flag, fmt, p)
|
||||
dev_t dev;
|
||||
int flag, fmt;
|
||||
struct proc *p;
|
||||
{
|
||||
struct atabus_softc *sc = atabus_cd.cd_devs[minor(dev)];
|
||||
|
||||
wdc_delref(sc->sc_chan);
|
||||
|
||||
sc->sc_flags &= ~ATABUSCF_OPEN;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
atabusioctl(dev, cmd, addr, flag, p)
|
||||
dev_t dev;
|
||||
u_long cmd;
|
||||
caddr_t addr;
|
||||
int flag;
|
||||
struct proc *p;
|
||||
{
|
||||
struct atabus_softc *sc = atabus_cd.cd_devs[minor(dev)];
|
||||
int error;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* Enforce write permission for ioctls that change the
|
||||
* state of the bus. Host adapter specific ioctls must
|
||||
* be checked by the adapter driver.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case ATABUSIOSCAN:
|
||||
case ATABUSIODETACH:
|
||||
case ATABUSIORESET:
|
||||
if ((flag & FWRITE) == 0)
|
||||
return (EBADF);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ATABUSIORESET:
|
||||
s = splbio();
|
||||
wdc_reset_channel(sc->sc_chan, AT_WAIT | AT_POLL);
|
||||
splx(s);
|
||||
error = 0;
|
||||
break;
|
||||
default:
|
||||
error = ENOTTY;
|
||||
}
|
||||
return (error);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ata_wdc.c,v 1.58 2004/07/31 21:26:43 bouyer Exp $ */
|
||||
/* $NetBSD: ata_wdc.c,v 1.59 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
|
||||
@ -66,7 +66,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.58 2004/07/31 21:26:43 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.59 2004/08/01 21:40:41 bouyer Exp $");
|
||||
|
||||
#ifndef WDCDEBUG
|
||||
#define WDCDEBUG
|
||||
@ -133,7 +133,7 @@ static void wdc_ata_kill_pending(struct ata_drive_datas *);
|
||||
const struct ata_bustype wdc_ata_bustype = {
|
||||
SCSIPI_BUSTYPE_ATA,
|
||||
wdc_ata_bio,
|
||||
wdc_reset_channel,
|
||||
wdc_reset_drive,
|
||||
wdc_exec_command,
|
||||
ata_get_params,
|
||||
wdc_ata_addref,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atavar.h,v 1.44 2004/07/31 21:26:43 bouyer Exp $ */
|
||||
/* $NetBSD: atavar.h,v 1.45 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer.
|
||||
@ -81,6 +81,8 @@ struct ata_queue {
|
||||
struct atabus_softc {
|
||||
struct device sc_dev;
|
||||
struct wdc_channel *sc_chan; /* XXXwdc */
|
||||
int sc_flags;
|
||||
#define ATABUSCF_OPEN 0x01
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc.c,v 1.182 2004/07/31 21:26:42 bouyer Exp $ */
|
||||
/* $NetBSD: wdc.c,v 1.183 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
|
||||
@ -70,7 +70,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.182 2004/07/31 21:26:42 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.183 2004/08/01 21:40:41 bouyer Exp $");
|
||||
|
||||
#ifndef WDCDEBUG
|
||||
#define WDCDEBUG
|
||||
@ -146,7 +146,6 @@ const struct ata_bustype wdc_ata_bustype = {
|
||||
static int wdcprobe1(struct wdc_channel*, int);
|
||||
static void __wdcerror(struct wdc_channel*, char *);
|
||||
static int __wdcwait_reset(struct wdc_channel *, int, int);
|
||||
static void __wdc_reset_channel(struct wdc_channel *, int);
|
||||
static void __wdccommand_done(struct wdc_channel *, struct ata_xfer *);
|
||||
static void __wdccommand_done_end(struct wdc_channel *, struct ata_xfer *);
|
||||
static void __wdccommand_kill_xfer(struct wdc_channel *,
|
||||
@ -965,7 +964,7 @@ wdcintr(void *arg)
|
||||
|
||||
/* Put all disk in RESET state */
|
||||
void
|
||||
wdc_reset_channel(struct ata_drive_datas *drvp, int flags)
|
||||
wdc_reset_drive(struct ata_drive_datas *drvp, int flags)
|
||||
{
|
||||
struct wdc_channel *chp = drvp->chnl_softc;
|
||||
struct wdc_softc *wdc = chp->ch_wdc;
|
||||
@ -974,13 +973,13 @@ wdc_reset_channel(struct ata_drive_datas *drvp, int flags)
|
||||
DEBUG_FUNCS);
|
||||
|
||||
|
||||
__wdc_reset_channel(chp, flags);
|
||||
wdc_reset_channel(chp, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
__wdc_reset_channel(struct wdc_channel *chp, int flags)
|
||||
void
|
||||
wdc_reset_channel(struct wdc_channel *chp, int flags)
|
||||
{
|
||||
struct ata_xfer *xfer;
|
||||
struct ata_xfer *xfer, *next_xfer;
|
||||
int drive;
|
||||
|
||||
/*
|
||||
@ -994,15 +993,17 @@ __wdc_reset_channel(struct wdc_channel *chp, int flags)
|
||||
if ((flags & AT_RST_NOCMD) == 0) {
|
||||
xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer);
|
||||
if (xfer && xfer->c_chp != chp)
|
||||
__wdc_reset_channel(xfer->c_chp, flags);
|
||||
wdc_reset_channel(xfer->c_chp, flags);
|
||||
for (xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer);
|
||||
xfer != 0; ) {
|
||||
xfer != NULL; xfer = next_xfer) {
|
||||
next_xfer = TAILQ_NEXT(xfer, c_xferchain);
|
||||
if (xfer->c_chp != chp)
|
||||
continue;
|
||||
if ((flags & AT_RST_EMERG) == 0)
|
||||
xfer->c_kill_xfer(chp, xfer, KILL_RESET);
|
||||
}
|
||||
}
|
||||
chp->ch_flags &= ~(WDCF_IRQ_WAIT|WDCF_DMA_WAIT);
|
||||
if ((flags & AT_POLL) == 0) {
|
||||
if (chp->ch_flags & WDCF_TH_RESET) {
|
||||
/* no need to schedule a reset more than one time */
|
||||
@ -1012,7 +1013,11 @@ __wdc_reset_channel(struct wdc_channel *chp, int flags)
|
||||
wakeup(&chp->ch_thread);
|
||||
return;
|
||||
}
|
||||
(void) wdcreset(chp, RESET_POLL);
|
||||
if ((flags & AT_WAIT) == 0) {
|
||||
(void) wdcreset(chp, RESET_POLL);
|
||||
} else {
|
||||
(void) wdcreset(chp, RESET_SLEEP);
|
||||
}
|
||||
for (drive = 0; drive < 2; drive++) {
|
||||
chp->ch_drive[drive].state = 0;
|
||||
}
|
||||
@ -1604,7 +1609,7 @@ wdc_downgrade_mode(struct ata_drive_datas *drvp, int flags)
|
||||
wdc->set_modes(chp);
|
||||
wdc_print_modes(chp);
|
||||
/* reset the channel, which will shedule all drives for setup */
|
||||
wdc_reset_channel(drvp, flags | AT_RST_NOCMD);
|
||||
wdc_reset_channel(chp, flags | AT_RST_NOCMD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdcvar.h,v 1.57 2004/05/25 20:42:41 thorpej Exp $ */
|
||||
/* $NetBSD: wdcvar.h,v 1.58 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
|
||||
@ -209,7 +209,8 @@ void wdccommandext(struct wdc_channel *, u_int8_t, u_int8_t, u_int64_t,
|
||||
u_int16_t);
|
||||
void wdccommandshort(struct wdc_channel *, int, int);
|
||||
void wdctimeout(void *arg);
|
||||
void wdc_reset_channel(struct ata_drive_datas *, int);
|
||||
void wdc_reset_drive(struct ata_drive_datas *, int);
|
||||
void wdc_reset_channel(struct wdc_channel *, int);
|
||||
|
||||
int wdc_exec_command(struct ata_drive_datas *, struct wdc_command*);
|
||||
#define WDC_COMPLETE 0x01
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atapi_wdc.c,v 1.71 2004/07/31 21:26:43 bouyer Exp $ */
|
||||
/* $NetBSD: atapi_wdc.c,v 1.72 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Manuel Bouyer.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.71 2004/07/31 21:26:43 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.72 2004/08/01 21:40:41 bouyer Exp $");
|
||||
|
||||
#ifndef WDCDEBUG
|
||||
#define WDCDEBUG
|
||||
@ -175,10 +175,10 @@ wdc_atapi_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer, int reason)
|
||||
|
||||
callout_stop(&chp->ch_callout);
|
||||
/* remove this command from xfer queue */
|
||||
wdc_free_xfer(chp, xfer);
|
||||
switch (reason) {
|
||||
case KILL_GONE:
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
wdc_free_xfer(chp, xfer);
|
||||
scsipi_done(sc_xfer);
|
||||
break;
|
||||
case KILL_RESET:
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ataio.h,v 1.3 2002/09/29 23:24:00 wiz Exp $ */
|
||||
/* $NetBSD: ataio.h,v 1.4 2004/08/01 21:40:41 bouyer Exp $ */
|
||||
|
||||
#ifndef _SYS_ATAIO_H_
|
||||
#define _SYS_ATAIO_H_
|
||||
@ -35,4 +35,21 @@ typedef struct atareq {
|
||||
|
||||
#define ATAIOCCOMMAND _IOWR('Q', 8, atareq_t)
|
||||
|
||||
/*
|
||||
* ATA bus IOCTL
|
||||
*/
|
||||
/* Scan bus for new devices. */
|
||||
struct atabusioscan_args {
|
||||
int at_dev; /* device to scan, -1 for wildcard */
|
||||
};
|
||||
#define ATABUSIOSCAN _IOW('A', 0, struct atabusioscan_args)
|
||||
|
||||
#define ATABUSIORESET _IO('A', 1) /* reset ATA bus */
|
||||
|
||||
struct atabusiodetach_args {
|
||||
int at_dev; /* device to detach; -1 for wildcard */
|
||||
};
|
||||
#define ATABUSIODETACH _IOW('A', 2, struct atabusiodetach_args)
|
||||
|
||||
|
||||
#endif /* _SYS_ATAIO_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user