Index: sys/cam/cam_ccb.h =================================================================== --- sys/cam/cam_ccb.h +++ sys/cam/cam_ccb.h @@ -247,6 +247,9 @@ 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; Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -2702,6 +2702,8 @@ 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: Index: sys/cam/mmc/mmc_sim.h =================================================================== --- sys/cam/mmc/mmc_sim.h +++ sys/cam/mmc/mmc_sim.h @@ -28,12 +28,16 @@ #ifndef __MMC_SIM_H__ #define __MMC_SIM_H__ +#include + 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); Index: sys/cam/mmc/mmc_sim.c =================================================================== --- sys/cam/mmc/mmc_sim.c +++ sys/cam/mmc/mmc_sim.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020 Emmanuel Vadot + * Copyright (c) 2020-2021 Emmanuel Vadot * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,6 +50,30 @@ return; } +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) { @@ -67,6 +91,12 @@ 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 @@ } break; case XPT_GET_TRAN_SETTINGS: + case XPT_MMC_GET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; @@ -105,6 +136,15 @@ 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 @@ { 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 @@ } mtx_unlock(&mmc_sim->mtx); + TASK_INIT(&mmc_sim->sim_task, 0, mmc_sim_task, mmc_sim); return (0); Index: sys/cam/mmc/mmc_xpt.c =================================================================== --- sys/cam/mmc/mmc_xpt.c +++ sys/cam/mmc/mmc_xpt.c @@ -90,6 +90,12 @@ 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 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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; Index: sys/dev/sdhci/sdhci.c =================================================================== --- sys/dev/sdhci/sdhci.c +++ sys/dev/sdhci/sdhci.c @@ -2537,6 +2537,7 @@ 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 @@ 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");