Index: sys/conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.957 diff -u -r1.957 files --- sys/conf/files 13 Oct 2004 05:41:09 -0000 1.957 +++ sys/conf/files 16 Oct 2004 21:19:30 -0000 @@ -341,6 +341,7 @@ dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci dev/asr/asr.c optional asr pci +dev/ata/ata_if.m optional ata dev/ata/ata-all.c optional ata dev/ata/ata-queue.c optional ata dev/ata/ata-lowlevel.c optional ata Index: sys/conf/options =================================================================== RCS file: /home/ncvs/src/sys/conf/options,v retrieving revision 1.485 diff -u -r1.485 options --- sys/conf/options 23 Sep 2004 08:34:50 -0000 1.485 +++ sys/conf/options 17 Oct 2004 23:54:00 -0000 @@ -303,7 +303,6 @@ DEV_ATAPICD opt_ata.h DEV_ATAPIST opt_ata.h DEV_ATAPIFD opt_ata.h -DEV_ATAPICAM opt_ata.h DEV_ATARAID opt_ata.h # Net stuff. Index: sys/dev/ata/ata-all.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v retrieving revision 1.232 diff -u -r1.232 ata-all.c --- sys/dev/ata/ata-all.c 13 Oct 2004 15:16:35 -0000 1.232 +++ sys/dev/ata/ata-all.c 18 Oct 2004 23:25:30 -0000 @@ -55,6 +55,7 @@ #include #include #include +#include /* device structures */ static d_ioctl_t ata_ioctl; @@ -75,6 +76,7 @@ static void btrim(int8_t *, int); static void bpack(int8_t *, int8_t *, int); static void ata_init(void); +static int ata_check_irq(device_t); /* global vars */ MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer"); @@ -105,15 +107,10 @@ int ata_probe(device_t dev) { - struct ata_channel *ch; - - if (!dev || !(ch = device_get_softc(dev))) - return ENXIO; - - if (ch->r_irq) - return EEXIST; - - return 0; + int rc = ata_check_irq (dev); + if (rc != 0) + return rc; + return bus_generic_probe(dev); } int @@ -171,9 +168,7 @@ ch->device[MASTER].attach(&ch->device[MASTER]); if (ch->device[SLAVE].attach) ch->device[SLAVE].attach(&ch->device[SLAVE]); -#ifdef DEV_ATAPICAM - atapi_cam_attach_bus(ch); -#endif + bus_generic_attach(dev); return 0; } @@ -203,9 +198,7 @@ ch->device[MASTER].detach(&ch->device[MASTER]); if (ch->device[SLAVE].detach) ch->device[SLAVE].detach(&ch->device[SLAVE]); -#ifdef DEV_ATAPICAM - atapi_cam_detach_bus(ch); -#endif + bus_generic_detach(dev); /* flush cache and powerdown device */ if (ch->device[MASTER].param) { @@ -237,6 +230,8 @@ ata_reinit(struct ata_channel *ch) { int devices, misdev, newdev; + device_t *children; + int children_count; if (!ch->r_irq) return ENXIO; @@ -316,9 +311,14 @@ ch->device[SLAVE].attach(&ch->device[SLAVE]); } -#ifdef DEV_ATAPICAM - atapi_cam_reinit_bus(ch); -#endif + if (device_get_children(ch->dev, &children, &children_count) == 0) { + if (children != NULL) { + while (children_count > 0) { + ATA_REINIT(children[--children_count]); + } + free(children, M_TEMP); + } + } if (bootverbose) ata_printf(ch, -1, "device config done ..\n"); @@ -594,7 +594,7 @@ break; } /* SOS should enable channel HW on controller XXX */ - error = ata_probe(device); + error = ata_check_irq(device); if (!error) error = ata_attach(device); break; @@ -823,9 +823,7 @@ ch->device[MASTER].attach(&ch->device[MASTER]); if (ch->device[SLAVE].attach) ch->device[SLAVE].attach(&ch->device[SLAVE]); -#ifdef DEV_ATAPICAM - atapi_cam_attach_bus(ch); -#endif + bus_generic_attach(ch->dev); } #ifdef DEV_ATARAID ata_raid_attach(); @@ -1093,4 +1091,18 @@ ata_zone = uma_zcreate("ata_request", sizeof(struct ata_request), NULL, NULL, NULL, NULL, 0, 0); } + +static int +ata_check_irq(device_t dev) { + struct ata_channel *ch; + + if (!dev || !(ch = device_get_softc(dev))) + return ENXIO; + + if (ch->r_irq) + return EEXIST; + + return 0; +} + SYSINIT(atadev, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL) Index: sys/dev/ata/ata_if.m =================================================================== RCS file: sys/dev/ata/ata_if.m diff -N sys/dev/ata/ata_if.m --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/ata/ata_if.m 17 Oct 2004 23:50:43 -0000 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +#include + +INTERFACE ata; + +# +# Reinitialize ATA bus +# +METHOD void reinit { + device_t dev; +}; Index: sys/dev/ata/atapi-cam.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/atapi-cam.c,v retrieving revision 1.35 diff -u -r1.35 atapi-cam.c --- sys/dev/ata/atapi-cam.c 17 Jun 2004 07:29:56 -0000 1.35 +++ sys/dev/ata/atapi-cam.c 18 Oct 2004 23:18:08 -0000 @@ -31,8 +31,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -41,6 +43,7 @@ #include #include #include +#include #include #include @@ -82,17 +85,30 @@ enum reinit_reason { BOOT_ATTACH, ATTACH, RESET }; -static struct mtx atapicam_softc_mtx; -static LIST_HEAD(,atapi_xpt_softc) all_buses = LIST_HEAD_INITIALIZER(all_buses); +/**** NEWBUS entry points ****/ -/* CAM XPT methods */ +/* Device methods */ +static void atapicam_identify(driver_t *, device_t); +static int atapicam_probe(device_t); +static int atapicam_attach(device_t); +static int atapicam_detach(device_t); + +/* ATA methods */ +static void atapicam_reinit(device_t); + +/* Module event handler */ +static int atapicam_event_handler(module_t, int, void *); + +/**** CAM XPT methods ****/ static void atapi_action(struct cam_sim *, union ccb *); static void atapi_poll(struct cam_sim *); static void atapi_async(void *, u_int32_t, struct cam_path *, void *); static void atapi_async1(void *, u_int32_t, struct cam_path *, void *); static void atapi_cb(struct ata_request *); -/* internal functions */ +/**** Internal functions ****/ +static int atapi_cam_setup_bus(struct atapi_xpt_softc *); +static void atapi_cam_teardown_bus(struct atapi_xpt_softc *); static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason); static void setup_dev(struct atapi_xpt_softc *, struct ata_device *); static void setup_async_cb(struct atapi_xpt_softc *, uint32_t); @@ -101,16 +117,12 @@ static void free_hcb_and_ccb_done(struct atapi_hcb *, u_int32_t); static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *); static void free_hcb(struct atapi_hcb *hcb); -static void free_softc(struct atapi_xpt_softc *scp); -static struct atapi_xpt_softc *get_softc(struct ata_channel *ata_ch); static struct ata_device *get_ata_device(struct atapi_xpt_softc *scp, int id); static MALLOC_DEFINE(M_ATACAM, "ATA CAM transport", "ATA driver CAM-XPT layer"); -void -atapi_cam_attach_bus(struct ata_channel *ata_ch) -{ - struct atapi_xpt_softc *scp = NULL; +static int +atapi_cam_setup_bus(struct atapi_xpt_softc *scp) { struct cam_devq *devq = NULL; struct cam_sim *sim = NULL; struct cam_path *path = NULL; @@ -118,28 +130,8 @@ GIANT_REQUIRED; - if (mtx_initialized(&atapicam_softc_mtx) == 0) - mtx_init(&atapicam_softc_mtx, "ATAPI/CAM softc mutex", NULL, MTX_DEF); - - mtx_lock(&atapicam_softc_mtx); - - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - break; - } - mtx_unlock(&atapicam_softc_mtx); - - if (scp != NULL) - return; - - if ((scp = malloc(sizeof(struct atapi_xpt_softc), - M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) - goto error; - - scp->ata_ch = ata_ch; TAILQ_INIT(&scp->pending_hcbs); - LIST_INSERT_HEAD(&all_buses, scp, chain); - unit = device_get_unit(ata_ch->dev); + unit = device_get_unit(scp->ata_ch->dev); if ((devq = cam_simq_alloc(16)) == NULL) goto error; @@ -167,36 +159,9 @@ setup_async_cb(scp, AC_LOST_DEVICE); reinit_bus(scp, cold ? BOOT_ATTACH : ATTACH); - return; - + return 0; error: - free_softc(scp); -} - -void -atapi_cam_detach_bus(struct ata_channel *ata_ch) -{ - struct atapi_xpt_softc *scp = get_softc(ata_ch); - - mtx_lock(&Giant); - free_softc(scp); - mtx_unlock(&Giant); -} - -void -atapi_cam_reinit_bus(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp = get_softc(ata_ch); - - /* - * scp might be null if the bus is being reinitialised during - * the boot-up sequence, before the ATAPI bus is registered. - */ - - if (scp != NULL) { - mtx_lock(&Giant); - reinit_bus(scp, RESET); - mtx_unlock(&Giant); - } + return ENXIO; } static void @@ -717,7 +682,7 @@ allocate_hcb(struct atapi_xpt_softc *softc, int unit, int bus, union ccb *ccb) { struct atapi_hcb *hcb = (struct atapi_hcb *) - malloc(sizeof(struct atapi_hcb), M_ATACAM, M_NOWAIT | M_ZERO); + malloc(sizeof(struct atapi_hcb), M_ATACAM, M_NOWAIT | M_ZERO); if (hcb != NULL) { hcb->softc = softc; @@ -739,13 +704,13 @@ } static void -free_softc(struct atapi_xpt_softc *scp) -{ +atapi_cam_teardown_bus(struct atapi_xpt_softc *scp) +{ struct atapi_hcb *hcb; GIANT_REQUIRED; - - if (scp != NULL) { + + if (scp != NULL) { TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) { free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR); } @@ -764,24 +729,9 @@ printf("Can't free %s SIM (still registered)\n", cam_sim_name(scp->sim)); } - LIST_REMOVE(scp, chain); - free(scp, M_ATACAM); } } -static struct atapi_xpt_softc * -get_softc(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp = NULL; - - mtx_lock(&atapicam_softc_mtx); - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - break; - } - mtx_unlock(&atapicam_softc_mtx); - return scp; -} - static struct ata_device * get_ata_device(struct atapi_xpt_softc *scp, int id) { @@ -800,4 +750,101 @@ default: return NULL; } +} + +static device_method_t atapicam_methods[] = { + /* Methods from the device interface */ + DEVMETHOD(device_identify, atapicam_identify), + DEVMETHOD(device_probe, atapicam_probe), + DEVMETHOD(device_attach, atapicam_attach), + DEVMETHOD(device_detach, atapicam_detach), + + /* Methods from the ata interface */ + DEVMETHOD(ata_reinit, atapicam_reinit), + + /* Terminate method list */ + { 0, 0 } +}; + +static driver_t atapicam_driver = { + .name = "atapicam", + .methods = atapicam_methods, + .size = sizeof(struct atapi_xpt_softc) +}; + +static devclass_t atapicam_devclass; + +DRIVER_MODULE(atapicam, ata, + atapicam_driver, + atapicam_devclass, + atapicam_event_handler, + /*arg*/NULL); + +static void +atapicam_identify(driver_t *driver, device_t parent) { + device_t child; + + child = device_add_child(parent, "atapicam", -1); + if (child == NULL) + return; + device_set_desc(child, "ATAPI/CAM"); + device_set_driver(child, driver); +} + +static int +atapicam_probe(device_t dev) { + return 0; +} + +static int +atapicam_attach(device_t dev) { + struct atapi_xpt_softc *scp; + int rc; + + if (!dev || (scp = device_get_softc(dev)) == NULL) + return ENXIO; + scp->ata_ch = device_get_softc(device_get_parent(dev)); + mtx_lock(&Giant); + rc = atapi_cam_setup_bus (scp); + mtx_unlock(&Giant); + return rc; +} + +static int +atapicam_detach(device_t dev) { + mtx_lock(&Giant); + atapi_cam_teardown_bus(device_get_softc(dev)); + mtx_unlock(&Giant); + return 0; +} + +static void +atapicam_reinit(device_t dev) { + mtx_lock(&Giant); + reinit_bus(device_get_softc(dev), RESET); + mtx_unlock(&Giant); +} + +static int +atapicam_event_handler(module_t mod, int what, void *arg) { + device_t *devlist; + int devcount; + switch (what) { + case MOD_UNLOAD: + if (devclass_get_devices(atapicam_devclass, &devlist, &devcount) + != 0) + return ENXIO; + if (devlist != NULL) { + while (devlist != NULL && devcount > 0) { + device_t child = devlist[--devcount]; + device_delete_child(device_get_parent(child),child); + } + free(devlist, M_TEMP); + } + break; + + default: + break; + } + return 0; } Index: sys/modules/atapicam/Makefile =================================================================== RCS file: sys/modules/atapicam/Makefile diff -N sys/modules/atapicam/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/modules/atapicam/Makefile 16 Oct 2004 21:40:08 -0000 @@ -0,0 +1,8 @@ +# $FreeBSD: src/sys/modules/sis/Makefile,v 1.10 2001/01/06 14:00:14 obrien Exp $ + +.PATH: ${.CURDIR}/../../dev/ata + +KMOD= atapicam +SRCS= atapi-cam.c opt_ata.h device_if.h bus_if.h ata_if.h + +.include