summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-all.c16
-rw-r--r--sys/dev/ata/atapi-all.h1
-rw-r--r--sys/dev/ata/atapi-cam.c61
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)
{
OpenPOWER on IntegriCloud