diff options
author | thomas <thomas@FreeBSD.org> | 2002-10-22 20:18:51 +0000 |
---|---|---|
committer | thomas <thomas@FreeBSD.org> | 2002-10-22 20:18:51 +0000 |
commit | 8caec9a500d4293aea472a3e271842d2ddacfeb6 (patch) | |
tree | f50066b5dfad8f06ed5c405fc688264b8060d81c /sys | |
parent | 2d3640fddd01b6d05253a3ebcb3159c067604907 (diff) | |
download | FreeBSD-src-8caec9a500d4293aea472a3e271842d2ddacfeb6.zip FreeBSD-src-8caec9a500d4293aea472a3e271842d2ddacfeb6.tar.gz |
Fill in missing parts of the ATAPI/CAM XPT: implement XPT_RESET_BUS
and XPT_RESET_DEV.
In order to properly handle reset requests whether they originate in the
ATA layer (atacontrol reinit) or from the CAM layer (camcontrol reset)
ata_reinit does not cause the SIM to be deallocated anymore. The SIM
is now unconditionnally created for each ATAPI bus.
This change may cause existing bus ids to change on some setups.
Reviewed by: roberto
Approved by: sos
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ata/ata-all.c | 16 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 1 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cam.c | 61 |
3 files changed, 52 insertions, 26 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 7b9a20a..4bc2097 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -210,8 +210,7 @@ ata_attach(device_t dev) atapi_attach(&ch->device[SLAVE]); #endif #ifdef DEV_ATAPICAM - if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) - atapi_cam_attach_bus(ch); + atapi_cam_attach_bus(ch); #endif } return 0; @@ -244,8 +243,7 @@ ata_detach(device_t dev) atapi_detach(&ch->device[SLAVE]); #endif #ifdef DEV_ATAPICAM - if (ch->devices & (ATA_ATAPI_SLAVE|ATA_ATAPI_MASTER)) - atapi_cam_detach_bus(ch); + atapi_cam_detach_bus(ch); #endif splx(s); @@ -585,8 +583,7 @@ ata_boot_attach(void) atapi_attach(&ch->device[SLAVE]); #endif #ifdef DEV_ATAPICAM - if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) - atapi_cam_attach_bus(ch); + atapi_cam_attach_bus(ch); #endif } } @@ -852,10 +849,6 @@ ata_reinit(struct ata_channel *ch) ata_printf(ch, -1, "resetting devices ..\n"); ata_reset(ch); -#ifdef DEV_ATAPICAM - if (devices & (ATA_ATAPI_SLAVE|ATA_ATAPI_MASTER)) - atapi_cam_detach_bus(ch); -#endif if ((misdev = devices & ~ch->devices)) { #ifdef DEV_ATADISK if (misdev & ATA_ATA_MASTER && ch->device[MASTER].driver) @@ -923,8 +916,7 @@ ata_reinit(struct ata_channel *ch) } #endif #ifdef DEV_ATAPICAM - if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) - atapi_cam_attach_bus(ch); + atapi_cam_reinit_bus(ch); #endif printf("done\n"); ATA_UNLOCK_CH(ch); diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index f545625..e77db5a 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -175,6 +175,7 @@ void atapi_attach(struct ata_device *); void atapi_cam_attach_bus(struct ata_channel *); void atapi_detach(struct ata_device *); void atapi_cam_detach_bus(struct ata_channel *); +void atapi_cam_reinit_bus(struct ata_channel *); void atapi_reinit(struct ata_device *); void atapi_start(struct ata_device *); int atapi_transfer(struct atapi_request *); diff --git a/sys/dev/ata/atapi-cam.c b/sys/dev/ata/atapi-cam.c index 3aebdab..02e234b 100644 --- a/sys/dev/ata/atapi-cam.c +++ b/sys/dev/ata/atapi-cam.c @@ -77,6 +77,8 @@ struct atapi_xpt_softc { LIST_ENTRY(atapi_xpt_softc) chain; }; +enum reinit_reason { BOOT_ATTACH, ATTACH, RESET }; + static LIST_HEAD(,atapi_xpt_softc) all_buses = LIST_HEAD_INITIALIZER(all_buses); /* CAM XPT methods */ @@ -87,6 +89,7 @@ static void atapi_async1(void *, u_int32_t, struct cam_path *, void *); static int atapi_cb(struct atapi_request *); /* internal functions */ +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); static void cam_rescan_callback(struct cam_periph *, union ccb *); @@ -95,6 +98,7 @@ 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"); @@ -147,13 +151,7 @@ atapi_cam_attach_bus(struct ata_channel *ata_ch) CAM_DEBUG(path, CAM_DEBUG_TRACE, ("Registered SIM for ata%d\n", unit)); setup_async_cb(scp, AC_LOST_DEVICE); - - if (ata_ch->devices & ATA_ATAPI_MASTER) - setup_dev(scp, &ata_ch->device[MASTER]); - if (ata_ch->devices & ATA_ATAPI_SLAVE) - setup_dev(scp, &ata_ch->device[SLAVE]); - - cam_rescan(sim); + reinit_bus(scp, cold ? BOOT_ATTACH : ATTACH); return; error: @@ -163,11 +161,32 @@ error: void atapi_cam_detach_bus(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp; + struct atapi_xpt_softc *scp = get_softc(ata_ch); + free_softc(scp); +} - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - free_softc(scp); +void +atapi_cam_reinit_bus(struct ata_channel *ata_ch) { + struct atapi_xpt_softc *scp = get_softc(ata_ch); + reinit_bus(scp, RESET); +} + +static void +reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) { + if (scp->ata_ch->devices & ATA_ATAPI_MASTER) + setup_dev(scp, &scp->ata_ch->device[MASTER]); + if (scp->ata_ch->devices & ATA_ATAPI_SLAVE) + setup_dev(scp, &scp->ata_ch->device[SLAVE]); + + switch (reason) { + case BOOT_ATTACH: + break; + case RESET: + xpt_async(AC_BUS_RESET, scp->path, NULL); + /*FALLTHROUGH*/ + case ATTACH: + cam_rescan(scp->sim); + break; } } @@ -261,16 +280,20 @@ atapi_action(struct cam_sim *sim, union ccb *ccb) return; } - case XPT_RESET_DEV: - /* should reset the device */ + case XPT_RESET_DEV: { + int tid = ccb_h->target_id; + struct ata_device *dev = get_ata_device(softc, tid); + CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("dev reset\n")); + atapi_reinit(dev); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); return; + } case XPT_RESET_BUS: - /* should reset the ATA bus */ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("bus reset\n")); + ata_reinit(softc->ata_ch); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); return; @@ -669,6 +692,16 @@ free_softc(struct atapi_xpt_softc *scp) } } +static struct atapi_xpt_softc * +get_softc(struct ata_channel *ata_ch) { + struct atapi_xpt_softc *scp; + LIST_FOREACH(scp, &all_buses, chain) { + if (scp->ata_ch == ata_ch) + return scp; + } + return NULL; +} + static struct ata_device * get_ata_device(struct atapi_xpt_softc *scp, int id) { |