Move the creation of ata_channel child devices to the channel code.

This allows to attach to the children (ATA devices) even without a
driver being attached. This allows atapi-cam to do its work both
with and without the pure ATAPI driver being present.

ATA patches by /me
ATAPI-cam pathes by Thomas
This commit is contained in:
sos 2005-04-15 10:20:52 +00:00
parent 953ee827d8
commit b22bb8078c
8 changed files with 136 additions and 180 deletions

View File

@ -68,7 +68,8 @@ static struct cdevsw ata_cdevsw = {
/* prototypes */
static void ata_interrupt(void *);
static void ata_boot_attach(void);
device_t ata_add_child(driver_t *driver, device_t parent, struct ata_device *atadev, const char *name, int unit);
device_t ata_add_child(device_t parent, struct ata_device *atadev, int unit);
static int ata_identify(device_t dev);
/* global vars */
MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
@ -147,8 +148,7 @@ ata_attach(device_t dev)
return 0;
/* probe and attach devices on this channel */
bus_generic_probe(dev);
bus_generic_attach(dev);
ata_identify(dev);
return 0;
}
@ -171,9 +171,6 @@ ata_detach(device_t dev)
free(children, M_TEMP);
}
/* fail outstanding requests on this channel (SOS shouldn't be any XXX ) */
ata_fail_requests(ch, NULL);
/* release resources */
bus_teardown_intr(dev, ch->r_irq, ch->ih);
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
@ -558,8 +555,7 @@ ata_boot_attach(void)
/* kick of probe and attach on all channels */
for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
if ((ch = devclass_get_softc(ata_devclass, ctlr))) {
bus_generic_probe(ch->dev);
bus_generic_attach(ch->dev);
ata_identify(ch->dev);
}
}
}
@ -568,16 +564,14 @@ ata_boot_attach(void)
* misc support functions
*/
device_t
ata_add_child(driver_t *driver, device_t parent, struct ata_device *atadev,
const char *name, int unit)
ata_add_child(device_t parent, struct ata_device *atadev, int unit)
{
struct ata_channel *ch = device_get_softc(parent);
device_t child;
if ((child = device_add_child(parent, name, unit))) {
if ((child = device_add_child(parent, NULL, unit))) {
char buffer[64];
device_set_driver(child, driver);
device_set_softc(child, atadev);
sprintf(buffer, "%.40s/%.8s",
atadev->param.model, atadev->param.revision);
@ -586,7 +580,7 @@ ata_add_child(driver_t *driver, device_t parent, struct ata_device *atadev,
atadev->dev = child;
atadev->max_iosize = DEV_BSIZE;
atadev->mode = ATA_PIO_MAX;
if ((atadev->param.config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) {
if (atadev->param.config & ATA_PROTO_ATAPI) {
if (atapi_dma && ch->dma &&
(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
ata_umode(&atadev->param) >= ATA_UDMA2)
@ -600,30 +594,30 @@ ata_add_child(driver_t *driver, device_t parent, struct ata_device *atadev,
return child;
}
void
ata_identify(driver_t *driver, device_t parent, int type, const char *name)
static int
ata_identify(device_t dev)
{
struct ata_channel *ch = device_get_softc(parent);
struct ata_channel *ch = device_get_softc(dev);
struct ata_device *master, *slave;
int master_res = EIO, slave_res = EIO, master_unit = -1, slave_unit = -1;
if (!(master = malloc(sizeof(struct ata_device),
M_ATA, M_NOWAIT | M_ZERO))) {
device_printf(parent, "out of memory\n");
return;
device_printf(dev, "out of memory\n");
return ENOMEM;
}
master->unit = ATA_MASTER;
if (!(slave = malloc(sizeof(struct ata_device),
M_ATA, M_NOWAIT | M_ZERO))) {
free(master, M_ATA);
device_printf(parent, "out of memory\n");
return;
device_printf(dev, "out of memory\n");
return ENOMEM;
}
slave->unit = ATA_SLAVE;
/* wait for the channel to be IDLE then grab it before touching HW */
while (ATA_LOCKING(parent, ATA_LF_LOCK) != ch->unit)
tsleep(ch, PRIBIO, "ataidnt2", 1);
while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit)
tsleep(ch, PRIBIO, "ataidnt1", 1);
while (1) {
mtx_lock(&ch->state_mtx);
if (ch->state == ATA_IDLE) {
@ -632,40 +626,41 @@ ata_identify(driver_t *driver, device_t parent, int type, const char *name)
break;
}
mtx_unlock(&ch->state_mtx);
tsleep(ch, PRIBIO, "ataidnt1", 1);
tsleep(ch, PRIBIO, "ataidnt2", 1);
}
if (type < 0) {
if (ch->devices & ATA_ATA_SLAVE)
slave_res = ata_getparam(parent, slave, ATA_ATA_IDENTIFY);
if (ch->devices & ATA_ATA_MASTER)
master_res = ata_getparam(parent, master, ATA_ATA_IDENTIFY);
if (ch->devices & ATA_ATA_SLAVE) {
slave_res = ata_getparam(dev, slave, ATA_ATA_IDENTIFY);
#ifdef ATA_STATIC_ID
master_unit = (device_get_unit(parent) << 1);
slave_unit = (device_get_unit(parent) << 1) + 1;
#endif
}
else {
if (ch->devices & ATA_ATAPI_SLAVE)
slave_res = ata_getparam(parent, slave, ATA_ATAPI_IDENTIFY);
if (ch->devices & ATA_ATAPI_MASTER)
master_res = ata_getparam(parent, master, ATA_ATAPI_IDENTIFY);
}
else if (ch->devices & ATA_ATAPI_SLAVE)
slave_res = ata_getparam(dev, slave, ATA_ATAPI_IDENTIFY);
if (master_res ||
!(type < 0 || (master->param.config & ATA_ATAPI_TYPE_MASK) == type) ||
!ata_add_child(driver, parent, master, name, master_unit))
if (ch->devices & ATA_ATA_MASTER) {
master_res = ata_getparam(dev, master, ATA_ATA_IDENTIFY);
#ifdef ATA_STATIC_ID
master_unit = (device_get_unit(parent) << 1);
#endif
}
else if (ch->devices & ATA_ATAPI_MASTER)
master_res = ata_getparam(dev, master, ATA_ATAPI_IDENTIFY);
if (master_res || !ata_add_child(dev, master, master_unit))
free(master, M_ATA);
if (slave_res ||
!(type < 0 || (slave->param.config & ATA_ATAPI_TYPE_MASK) == type) ||
!ata_add_child(driver, parent, slave, name, slave_unit))
if (slave_res || !ata_add_child(dev, slave, slave_unit))
free(slave, M_ATA);
mtx_lock(&ch->state_mtx);
ch->state = ATA_IDLE;
mtx_unlock(&ch->state_mtx);
ATA_LOCKING(parent, ATA_LF_UNLOCK);
ATA_LOCKING(dev, ATA_LF_UNLOCK);
bus_generic_probe(dev);
bus_generic_attach(dev);
return 0;
}
void

View File

@ -452,7 +452,6 @@ int ata_detach(device_t dev);
int ata_reinit(device_t dev);
int ata_suspend(device_t dev);
int ata_resume(device_t dev);
void ata_identify(driver_t *driver, device_t parent, int type, const char *name);
void ata_default_registers(struct ata_channel *ch);
void ata_udelay(int interval);
char *ata_mode2str(int mode);

View File

@ -66,16 +66,15 @@ static dumper_t ad_dump;
/* local vars */
static MALLOC_DEFINE(M_AD, "AD driver", "ATA disk driver");
static void
ad_identify(driver_t *driver, device_t parent)
{
ata_identify(driver, parent, -1, "ad");
}
static int
ad_probe(device_t dev)
{
return 0;
struct ata_device *atadev = device_get_softc(dev);
if (!(atadev->param.config & ATA_PROTO_ATAPI))
return 0;
else
return ENXIO;
}
static int
@ -93,8 +92,6 @@ ad_attach(device_t dev)
if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return ENOMEM;
}
device_set_ivars(dev, adp);
@ -161,7 +158,6 @@ static int
ad_detach(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ad_softc *adp = device_get_ivars(dev);
device_t *children;
int nchildren, i;
@ -187,8 +183,6 @@ ad_detach(device_t dev)
/* dont leave anything behind */
device_set_ivars(dev, NULL);
free(adp, M_AD);
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return 0;
}
@ -419,7 +413,6 @@ ad_version(u_int16_t version)
static device_method_t ad_methods[] = {
/* device interface */
DEVMETHOD(device_identify, ad_identify),
DEVMETHOD(device_probe, ad_probe),
DEVMETHOD(device_attach, ad_attach),
DEVMETHOD(device_detach, ad_detach),
@ -439,22 +432,6 @@ static driver_t ad_driver = {
devclass_t ad_devclass;
static int
ad_modevent(module_t mod, int what, void *arg)
{
device_t *devs;
int ndevs, i;
if (what == MOD_UNLOAD) {
if (!devclass_get_devices(ad_devclass, &devs, &ndevs) && devs) {
for (i = 0; i < ndevs; i++)
device_delete_child(device_get_parent(devs[i]), devs[i]);
free(devs, M_TEMP);
}
}
return 0;
}
DRIVER_MODULE(ad, ata, ad_driver, ad_devclass, ad_modevent, NULL);
DRIVER_MODULE(ad, ata, ad_driver, ad_devclass, NULL, NULL);
MODULE_VERSION(ad, 1);
MODULE_DEPEND(ad, ata, 1, 1, 1);

View File

@ -90,7 +90,7 @@ struct atapi_hcb {
enum reinit_reason { BOOT_ATTACH, ATTACH, RESET };
/* Device methods */
static int atapi_cam_identify(device_t *dev, device_t parent);
static void atapi_cam_identify(device_t *dev, device_t parent);
static int atapi_cam_probe(device_t dev);
static int atapi_cam_attach(device_t dev);
static int atapi_cam_detach(device_t dev);
@ -102,6 +102,9 @@ static void atapi_poll(struct cam_sim *);
static void atapi_async(void *, u_int32_t, struct cam_path *, void *);
static void atapi_cb(struct ata_request *);
/* Module methods */
static int atapi_cam_event_handler(module_t mod, int what, void *arg);
/* internal functions */
static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason);
static void setup_async_cb(struct atapi_xpt_softc *, uint32_t);
@ -130,24 +133,52 @@ static driver_t atapi_cam_driver = {
};
static devclass_t atapi_cam_devclass;
DRIVER_MODULE(atapicam, ata, atapi_cam_driver, atapi_cam_devclass, 0, 0);
DRIVER_MODULE(atapicam, ata,
atapi_cam_driver,
atapi_cam_devclass,
atapi_cam_event_handler,
/*arg*/NULL);
MODULE_VERSION(atapicam, 1);
MODULE_DEPEND(atapicam, ata, 1, 1, 1);
MODULE_DEPEND(atapicam, cam, 1, 1, 1);
static int
static void
atapi_cam_identify(device_t *dev, device_t parent)
{
struct atapi_xpt_softc *scp =
malloc (sizeof (struct atapi_xpt_softc), M_ATACAM, M_NOWAIT|M_ZERO);
device_t child;
if (scp == NULL) {
printf ("atapi_cam_identify: out of memory");
return;
}
/* Assume one atapicam instance per parent channel instance. */
device_add_child(parent, "atapicam", -1);
return (0);
child = device_add_child(parent, "atapicam", -1);
if (child == NULL) {
printf ("atapi_cam_identify: out of memory, can't add child");
free (scp, M_ATACAM);
return;
}
scp->atapi_cam_dev.unit = -1;
scp->atapi_cam_dev.dev = child;
device_quiet(child);
device_set_softc(child, scp);
}
static int
atapi_cam_probe(device_t dev)
{
device_set_desc(dev, "ATAPI CAM Attachment");
return (0);
struct ata_device *atadev = device_get_softc (dev);
KASSERT(atadev != NULL, ("expect valid struct ata_device"));
if (atadev->unit < 0) {
device_set_desc(dev, "ATAPI CAM Attachment");
return (0);
} else {
return ENXIO;
}
}
static int
@ -167,13 +198,6 @@ atapi_cam_attach(device_t dev)
mtx_init(&scp->state_lock, "ATAPICAM lock", NULL, MTX_DEF);
/*
* The ATA core expects all of its children to have an ata_device.
* Assign an invalid unit number so that we can be properly ignored.
*/
scp->atapi_cam_dev.unit = -1;
scp->atapi_cam_dev.dev = dev;
scp->dev = dev;
scp->parent = device_get_parent(dev);
scp->ata_ch = device_get_softc(scp->parent);
@ -846,3 +870,32 @@ free_softc(struct atapi_xpt_softc *scp)
mtx_destroy(&scp->state_lock);
}
}
static int
atapi_cam_event_handler(module_t mod, int what, void *arg) {
device_t *devlist;
int devcount;
switch (what) {
case MOD_UNLOAD:
if (devclass_get_devices(atapi_cam_devclass, &devlist, &devcount)
!= 0)
return ENXIO;
if (devlist != NULL) {
while (devlist != NULL && devcount > 0) {
device_t child = devlist[--devcount];
struct atapi_xpt_softc *scp = device_get_softc(child);
device_delete_child(device_get_parent(child),child);
if (scp != NULL)
free(scp, M_ATACAM);
}
free(devlist, M_TEMP);
}
break;
default:
break;
}
return 0;
}

View File

@ -104,28 +104,25 @@ static struct g_class acd_class = {
};
//DECLARE_GEOM_CLASS(acd_class, acd);
static void
acd_identify(driver_t *driver, device_t parent)
{
ata_identify(driver, parent, ATA_ATAPI_TYPE_CDROM, "acd");
}
static int
acd_probe(device_t dev)
{
return 0;
struct ata_device *atadev = device_get_softc(dev);
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_CDROM)
return 0;
else
return ENXIO;
}
static int
acd_attach(device_t dev)
{
struct ata_device *atadev = device_get_softc(dev);
struct acd_softc *cdp;
if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return ENOMEM;
}
cdp->block_size = 2048;
@ -196,7 +193,6 @@ static void
acd_geom_detach(void *arg, int flag)
{
struct ata_channel *ch = device_get_softc(device_get_parent(arg));
struct ata_device *atadev = device_get_softc(arg);
struct acd_softc *cdp = device_get_ivars(arg);
/* signal geom so we dont get any further requests */
@ -208,8 +204,6 @@ acd_geom_detach(void *arg, int flag)
/* dont leave anything behind */
device_set_ivars(arg, NULL);
free(cdp, M_ACD);
device_set_softc(arg, NULL);
free(atadev, M_ATA);
}
static int
@ -1920,7 +1914,6 @@ acd_describe(device_t dev)
static device_method_t acd_methods[] = {
/* device interface */
DEVMETHOD(device_identify, acd_identify),
DEVMETHOD(device_probe, acd_probe),
DEVMETHOD(device_attach, acd_attach),
DEVMETHOD(device_detach, acd_detach),
@ -1943,20 +1936,7 @@ static devclass_t acd_devclass;
static int
acd_modevent(module_t mod, int what, void *arg)
{
device_t *devs;
int ndevs, i;
if (what == MOD_LOAD) {
g_modevent(0, what, &acd_class);
}
if (what == MOD_UNLOAD) {
if (!devclass_get_devices(acd_devclass, &devs, &ndevs) && devs) {
for (i = 0; i < ndevs; i++)
device_delete_child(device_get_parent(devs[i]), devs[i]);
free(devs, M_TEMP);
}
g_modevent(0, what, &acd_class);
}
g_modevent(0, what, &acd_class);
return 0;
}

View File

@ -62,16 +62,16 @@ static int afd_test_ready(device_t);
/* internal vars */
static MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers");
static void
afd_identify(driver_t *driver, device_t parent)
{
ata_identify(driver, parent, ATA_ATAPI_TYPE_DIRECT, "afd");
}
static int
afd_probe(device_t dev)
{
return 0;
struct ata_device *atadev = device_get_softc(dev);
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_DIRECT)
return 0;
else
return ENXIO;
}
static int
@ -83,8 +83,6 @@ afd_attach(device_t dev)
if (!(fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return ENOMEM;
}
device_set_ivars(dev, fdp);
@ -93,8 +91,6 @@ afd_attach(device_t dev)
if (afd_sense(dev)) {
device_set_ivars(dev, NULL);
free(fdp, M_AFD);
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return ENXIO;
}
atadev->flags |= ATA_D_MEDIA_CHANGED;
@ -122,7 +118,6 @@ static int
afd_detach(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct afd_softc *fdp = device_get_ivars(dev);
/* detroy disk from the system so we dont get any further requests */
@ -134,8 +129,6 @@ afd_detach(device_t dev)
/* dont leave anything behind */
device_set_ivars(dev, NULL);
free(fdp, M_AFD);
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return 0;
}
@ -400,7 +393,6 @@ afd_describe(device_t dev)
static device_method_t afd_methods[] = {
/* device interface */
DEVMETHOD(device_identify, afd_identify),
DEVMETHOD(device_probe, afd_probe),
DEVMETHOD(device_attach, afd_attach),
DEVMETHOD(device_detach, afd_detach),
@ -420,23 +412,7 @@ static driver_t afd_driver = {
static devclass_t afd_devclass;
static int
afd_modevent(module_t mod, int what, void *arg)
{
device_t *devs;
int ndevs, i;
if (what == MOD_UNLOAD) {
if (!devclass_get_devices(afd_devclass, &devs, &ndevs) && devs) {
for (i = 0; i < ndevs; i++)
device_delete_child(device_get_parent(devs[i]), devs[i]);
free(devs, M_TEMP);
}
}
return 0;
}
DRIVER_MODULE(afd, ata, afd_driver, afd_devclass, afd_modevent, NULL);
DRIVER_MODULE(afd, ata, afd_driver, afd_devclass, NULL, NULL);
MODULE_VERSION(afd, 1);
MODULE_DEPEND(afd, ata, 1, 1, 1);

View File

@ -87,16 +87,16 @@ static int ast_wait_dsc(device_t, int);
static u_int64_t ast_total = 0;
static MALLOC_DEFINE(M_AST, "AST driver", "ATAPI tape driver buffers");
static void
ast_identify(driver_t *driver, device_t parent)
{
ata_identify(driver, parent, ATA_ATAPI_TYPE_TAPE, "ast");
}
static int
ast_probe(device_t dev)
{
return 0;
struct ata_device *atadev = device_get_softc(dev);
if ((atadev->param.config & ATA_PROTO_ATAPI) &&
(atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_TAPE)
return 0;
else
return ENXIO;
}
static int
@ -110,8 +110,6 @@ ast_attach(device_t dev)
if (!(stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT | M_ZERO))) {
device_printf(dev, "out of memory\n");
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return ENOMEM;
}
device_set_ivars(dev, stp);
@ -120,8 +118,6 @@ ast_attach(device_t dev)
if (ast_sense(dev)) {
device_set_ivars(dev, NULL);
free(stp, M_AST);
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return ENXIO;
}
if (!strcmp(atadev->param.model, "OnStream DI-30")) {
@ -172,7 +168,6 @@ static int
ast_detach(device_t dev)
{
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
struct ata_device *atadev = device_get_softc(dev);
struct ast_softc *stp = device_get_ivars(dev);
/* detroy devices from the system so we dont get any further requests */
@ -186,8 +181,6 @@ ast_detach(device_t dev)
devstat_remove_entry(stp->stats);
device_set_ivars(dev, NULL);
free(stp, M_AST);
device_set_softc(dev, NULL);
free(atadev, M_ATA);
return 0;
}
@ -752,7 +745,6 @@ ast_describe(device_t dev)
static device_method_t ast_methods[] = {
/* device interface */
DEVMETHOD(device_identify, ast_identify),
DEVMETHOD(device_probe, ast_probe),
DEVMETHOD(device_attach, ast_attach),
DEVMETHOD(device_detach, ast_detach),
@ -772,22 +764,6 @@ static driver_t ast_driver = {
static devclass_t ast_devclass;
static int
ast_modevent(module_t mod, int what, void *arg)
{
device_t *devs;
int ndevs, i;
if (what == MOD_UNLOAD) {
if (!devclass_get_devices(ast_devclass, &devs, &ndevs) && devs) {
for (i = 0; i < ndevs; i++)
device_delete_child(device_get_parent(devs[i]), devs[i]);
free(devs, M_TEMP);
}
}
return 0;
}
DRIVER_MODULE(ast, ata, ast_driver, ast_devclass, ast_modevent, NULL);
DRIVER_MODULE(ast, ata, ast_driver, ast_devclass, NULL, NULL);
MODULE_VERSION(ast, 1);
MODULE_DEPEND(ast, ata, 1, 1, 1);

View File

@ -37,7 +37,7 @@
struct ata_params {
/*000*/ u_int16_t config; /* configuration info */
#define ATA_PROTO_MASK 0x8003
#define ATA_PROTO_ATA 0x0000
#define ATA_PROTO_ATAPI 0x8000
#define ATA_PROTO_ATAPI_12 0x8000
#define ATA_PROTO_ATAPI_16 0x8001
#define ATA_ATAPI_TYPE_MASK 0x1f00