aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/cam/cam_ccb.h3
-rw-r--r--sys/cam/cam_xpt.c2
-rw-r--r--sys/cam/mmc/mmc_sim.c45
-rw-r--r--sys/cam/mmc/mmc_sim.h4
-rw-r--r--sys/cam/mmc/mmc_xpt.c109
-rw-r--r--sys/dev/sdhci/sdhci.c2
6 files changed, 137 insertions, 28 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 2545e40e192d..3a01cde1a442 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -253,6 +253,9 @@ typedef enum {
XPT_REPROBE_LUN = 0x38 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
/* Query device capacity and notify GEOM */
+ XPT_MMC_SET_TRAN_SETTINGS = 0x40 | XPT_FC_DEV_QUEUED,
+ XPT_MMC_GET_TRAN_SETTINGS = 0x41 | XPT_FC_DEV_QUEUED,
+
/* Vendor Unique codes: 0x80->0x8F */
XPT_VUNIQUE = 0x80
} xpt_opcode;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 33361cfb68a5..91bac149c061 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2702,6 +2702,8 @@ xpt_action_default(union ccb *start_ccb)
case XPT_NVME_IO:
case XPT_NVME_ADMIN:
case XPT_MMC_IO:
+ case XPT_MMC_GET_TRAN_SETTINGS:
+ case XPT_MMC_SET_TRAN_SETTINGS:
case XPT_RESET_DEV:
case XPT_ENG_EXEC:
case XPT_SMP_IO:
diff --git a/sys/cam/mmc/mmc_sim.c b/sys/cam/mmc/mmc_sim.c
index 03269a0b3d4d..1500e3f6f1cd 100644
--- a/sys/cam/mmc/mmc_sim.c
+++ b/sys/cam/mmc/mmc_sim.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2020 Emmanuel Vadot <manu@FreeBSD.org>
+ * Copyright (c) 2020-2021 Emmanuel Vadot <manu@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,6 +51,30 @@ mmc_cam_default_poll(struct cam_sim *sim)
}
static void
+mmc_sim_task(void *arg, int pending)
+{
+ struct mmc_sim *mmc_sim;
+ struct ccb_trans_settings *cts;
+ int rv;
+
+ mmc_sim = arg;
+
+ if (mmc_sim->ccb == NULL)
+ return;
+
+ cts = &mmc_sim->ccb->cts;
+ rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
+ if (rv != 0)
+ mmc_sim->ccb->ccb_h.status = CAM_REQ_INVALID;
+ else
+ mmc_sim->ccb->ccb_h.status = CAM_REQ_CMP;
+
+ xpt_done(mmc_sim->ccb);
+ mmc_sim->ccb = NULL;
+}
+
+
+static void
mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
{
struct mmc_sim *mmc_sim;
@@ -67,6 +91,12 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
mtx_assert(&mmc_sim->mtx, MA_OWNED);
+ if (mmc_sim->ccb != NULL) {
+ ccb->ccb_h.status = CAM_BUSY;
+ xpt_done(ccb);
+ return;
+ }
+
switch (ccb->ccb_h.func_code) {
case XPT_PATH_INQ:
rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &mmc);
@@ -78,6 +108,7 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
}
break;
case XPT_GET_TRAN_SETTINGS:
+ case XPT_MMC_GET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
@@ -105,6 +136,15 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
+ case XPT_MMC_SET_TRAN_SETTINGS:
+ {
+ ccb->ccb_h.status = CAM_SIM_QUEUED;
+ mmc_sim->ccb = ccb;
+ taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
+ return;
+ /* NOTREACHED */
+ break;
+ }
case XPT_RESET_BUS:
ccb->ccb_h.status = CAM_REQ_CMP;
break;
@@ -112,7 +152,7 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
{
rv = MMC_SIM_CAM_REQUEST(mmc_sim->dev, ccb);
if (rv != 0)
- ccb->ccb_h.status = CAM_REQ_INPROG;
+ ccb->ccb_h.status = CAM_SIM_QUEUED;
else
ccb->ccb_h.status = CAM_REQ_INVALID;
return;
@@ -163,6 +203,7 @@ mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
}
mtx_unlock(&mmc_sim->mtx);
+ TASK_INIT(&mmc_sim->sim_task, 0, mmc_sim_task, mmc_sim);
return (0);
diff --git a/sys/cam/mmc/mmc_sim.h b/sys/cam/mmc/mmc_sim.h
index 629144656e51..2b1159a9758e 100644
--- a/sys/cam/mmc/mmc_sim.h
+++ b/sys/cam/mmc/mmc_sim.h
@@ -28,12 +28,16 @@
#ifndef __MMC_SIM_H__
#define __MMC_SIM_H__
+#include <sys/taskqueue.h>
+
struct mmc_sim {
struct mmc_cam_sim_softc *sc;
struct mtx mtx;
struct cam_devq *devq;
struct cam_sim *sim;
device_t dev;
+ struct task sim_task;
+ union ccb *ccb;
};
int mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim);
diff --git a/sys/cam/mmc/mmc_xpt.c b/sys/cam/mmc/mmc_xpt.c
index 847fd7cdb412..6b2fecdab0fb 100644
--- a/sys/cam/mmc/mmc_xpt.c
+++ b/sys/cam/mmc/mmc_xpt.c
@@ -90,6 +90,12 @@ static void mmc_proto_debug_out(union ccb *ccb);
typedef enum {
PROBE_RESET,
PROBE_IDENTIFY,
+ PROBE_POWER_OFF,
+ PROBE_GET_HOST_OCR,
+ PROBE_RESET_BUS,
+ PROBE_SET_ID_FREQ,
+ PROBE_SET_CS,
+ PROBE_GO_IDLE_STATE,
PROBE_SDIO_RESET,
PROBE_SEND_IF_COND,
PROBE_SDIO_INIT,
@@ -107,6 +113,12 @@ typedef enum {
static char *probe_action_text[] = {
"PROBE_RESET",
"PROBE_IDENTIFY",
+ "PROBE_POWER_OFF",
+ "PROBE_GET_HOST_OCR",
+ "PROBE_RESET_BUS",
+ "PROBE_SET_ID_FREQ",
+ "PROBE_SET_CS",
+ "PROBE_GO_IDLE_STATE",
"PROBE_SDIO_RESET",
"PROBE_SEND_IF_COND",
"PROBE_SDIO_INIT",
@@ -165,6 +177,7 @@ typedef struct {
probe_action action;
int restart;
union ccb saved_ccb;
+ uint32_t host_ocr;
uint32_t flags;
#define PROBE_FLAG_ACMD_SENT 0x1 /* CMD55 is sent, card expects ACMD */
#define PROBE_FLAG_HOST_CAN_DO_18V 0x2 /* Host can do 1.8V signaling */
@@ -584,7 +597,6 @@ mmcprobe_start(struct cam_periph *periph, union ccb *start_ccb)
mmcprobe_softc *softc;
struct cam_path *path;
struct ccb_mmcio *mmcio;
- struct mtx *p_mtx = cam_periph_mtx(periph);
struct ccb_trans_settings_mmc *cts;
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("mmcprobe_start\n"));
@@ -612,25 +624,29 @@ mmcprobe_start(struct cam_periph *periph, union ccb *start_ccb)
case PROBE_IDENTIFY:
xpt_path_inq(&start_ccb->cpi, periph->path);
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("Start with PROBE_IDENTIFY\n"));
- init_standard_ccb(start_ccb, XPT_GET_TRAN_SETTINGS);
- xpt_action(start_ccb);
- if (cts->ios.power_mode != power_off) {
- init_standard_ccb(start_ccb, XPT_SET_TRAN_SETTINGS);
- cts->ios.power_mode = power_off;
- cts->ios_valid = MMC_PM;
- xpt_action(start_ccb);
- mtx_sleep(periph, p_mtx, 0, "mmcios", 100);
- }
- /* mmc_power_up */
- /* Get the host OCR */
- init_standard_ccb(start_ccb, XPT_GET_TRAN_SETTINGS);
- xpt_action(start_ccb);
+ init_standard_ccb(start_ccb, XPT_MMC_GET_TRAN_SETTINGS);
+ break;
+
+ case PROBE_POWER_OFF:
+ CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("power off the card\n"));
+ init_standard_ccb(start_ccb, XPT_MMC_SET_TRAN_SETTINGS);
+ cts->ios.power_mode = power_off;
+ cts->ios_valid = MMC_PM;
+ break;
+
+ case PROBE_GET_HOST_OCR:
+ CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("get the host ocr\n"));
+ init_standard_ccb(start_ccb, XPT_MMC_GET_TRAN_SETTINGS);
+ break;
+ case PROBE_RESET_BUS:
+ {
uint32_t host_caps = cts->host_caps;
if (host_caps & MMC_CAP_SIGNALING_180)
softc->flags |= PROBE_FLAG_HOST_CAN_DO_18V;
- uint32_t hv = mmc_highest_voltage(cts->host_ocr);
- init_standard_ccb(start_ccb, XPT_SET_TRAN_SETTINGS);
+ uint32_t hv = mmc_highest_voltage(softc->host_ocr);
+ CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("reseting the bus\n"));
+ init_standard_ccb(start_ccb, XPT_MMC_SET_TRAN_SETTINGS);
cts->ios.vdd = hv;
cts->ios.bus_mode = opendrain;
cts->ios.chip_select = cs_dontcare;
@@ -639,25 +655,26 @@ mmcprobe_start(struct cam_periph *periph, union ccb *start_ccb)
cts->ios.clock = 0;
cts->ios_valid = MMC_VDD | MMC_PM | MMC_BM |
MMC_CS | MMC_BW | MMC_CLK;
- xpt_action(start_ccb);
- mtx_sleep(periph, p_mtx, 0, "mmcios", 100);
+ break;
+ }
- init_standard_ccb(start_ccb, XPT_SET_TRAN_SETTINGS);
+ case PROBE_SET_ID_FREQ:
+ CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("setting the ID freq\n"));
+ init_standard_ccb(start_ccb, XPT_MMC_SET_TRAN_SETTINGS);
cts->ios.power_mode = power_on;
cts->ios.clock = CARD_ID_FREQUENCY;
cts->ios.timing = bus_timing_normal;
cts->ios_valid = MMC_PM | MMC_CLK | MMC_BT;
- xpt_action(start_ccb);
- mtx_sleep(periph, p_mtx, 0, "mmcios", 100);
- /* End for mmc_power_on */
+ break;
+ case PROBE_SET_CS:
/* Begin mmc_idle_cards() */
- init_standard_ccb(start_ccb, XPT_SET_TRAN_SETTINGS);
+ init_standard_ccb(start_ccb, XPT_MMC_SET_TRAN_SETTINGS);
cts->ios.chip_select = cs_high;
cts->ios_valid = MMC_CS;
- xpt_action(start_ccb);
- mtx_sleep(periph, p_mtx, 0, "mmcios", 1);
+ break;
+ case PROBE_GO_IDLE_STATE:
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("Send first XPT_MMC_IO\n"));
init_standard_ccb(start_ccb, XPT_MMC_IO);
mmcio->cmd.opcode = MMC_GO_IDLE_STATE; /* CMD 0 */
@@ -668,6 +685,7 @@ mmcprobe_start(struct cam_periph *periph, union ccb *start_ccb)
/* XXX Reset I/O portion as well */
break;
+
case PROBE_SDIO_RESET:
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE,
("Start with PROBE_SDIO_RESET\n"));
@@ -805,7 +823,7 @@ mmcprobe_done(struct cam_periph *periph, union ccb *done_ccb)
struct ccb_mmcio *mmcio;
u_int32_t priority;
- CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mmcprobe_done\n"));
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("mmcprobe_done\n"));
softc = (mmcprobe_softc *)periph->softc;
path = done_ccb->ccb_h.path;
priority = done_ccb->ccb_h.pinfo.priority;
@@ -816,6 +834,45 @@ mmcprobe_done(struct cam_periph *periph, union ccb *done_ccb)
case PROBE_IDENTIFY:
{
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_RESET\n"));
+ PROBE_SET_ACTION(softc, PROBE_POWER_OFF);
+ break;
+ }
+ case PROBE_POWER_OFF:
+ {
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_POWER_OFF\n"));
+ PROBE_SET_ACTION(softc, PROBE_GET_HOST_OCR);
+ break;
+ }
+ case PROBE_GET_HOST_OCR:
+ {
+ struct ccb_trans_settings_mmc *cts;
+ cts = &done_ccb->cts.proto_specific.mmc;
+ softc->host_ocr = cts->host_ocr;
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_GET_HOST_OCR (Got OCR=%x\n", softc->host_ocr));
+ PROBE_SET_ACTION(softc, PROBE_RESET_BUS);
+ break;
+ }
+ case PROBE_RESET_BUS:
+ {
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_RESET_BUS\n"));
+ PROBE_SET_ACTION(softc, PROBE_SET_ID_FREQ);
+ break;
+ }
+ case PROBE_SET_ID_FREQ:
+ {
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_SET_ID_FREQ\n"));
+ PROBE_SET_ACTION(softc, PROBE_SET_CS);
+ break;
+ }
+ case PROBE_SET_CS:
+ {
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_SET_CS\n"));
+ PROBE_SET_ACTION(softc, PROBE_GO_IDLE_STATE);
+ break;
+ }
+ case PROBE_GO_IDLE_STATE:
+ {
+ CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_GO_IDLE_STATE\n"));
mmcio = &done_ccb->mmcio;
err = mmcio->cmd.error;
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
index 91474cabd2d3..0441320d4b35 100644
--- a/sys/dev/sdhci/sdhci.c
+++ b/sys/dev/sdhci/sdhci.c
@@ -2537,6 +2537,7 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb)
mmc_path_inq(&ccb->cpi, "Deglitch Networks", sim, maxphys);
break;
+ case XPT_MMC_GET_TRAN_SETTINGS:
case XPT_GET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
@@ -2571,6 +2572,7 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
+ case XPT_MMC_SET_TRAN_SETTINGS:
case XPT_SET_TRAN_SETTINGS:
if (sdhci_debug > 1)
slot_printf(slot, "Got XPT_SET_TRAN_SETTINGS\n");