Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/mmc/mmc_da.c
Show First 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | static const char *mmc_errmsg[] = | ||||
"Failed", | "Failed", | ||||
"Invalid", | "Invalid", | ||||
"NO MEMORY" | "NO MEMORY" | ||||
}; | }; | ||||
#define ccb_bp ppriv_ptr1 | #define ccb_bp ppriv_ptr1 | ||||
static disk_strategy_t sddastrategy; | static disk_strategy_t sddastrategy; | ||||
static dumper_t sddadump; | |||||
static periph_init_t sddainit; | static periph_init_t sddainit; | ||||
static void sddaasync(void *callback_arg, u_int32_t code, | static void sddaasync(void *callback_arg, u_int32_t code, | ||||
struct cam_path *path, void *arg); | struct cam_path *path, void *arg); | ||||
static periph_ctor_t sddaregister; | static periph_ctor_t sddaregister; | ||||
static periph_dtor_t sddacleanup; | static periph_dtor_t sddacleanup; | ||||
static periph_start_t sddastart; | static periph_start_t sddastart; | ||||
static periph_oninv_t sddaoninvalidate; | static periph_oninv_t sddaoninvalidate; | ||||
static void sddadone(struct cam_periph *periph, | static void sddadone(struct cam_periph *periph, | ||||
▲ Show 20 Lines • Show All 1,390 Lines • ▼ Show 20 Lines | part->disk->d_devstat = devstat_new_entry(part->name, | ||||
cnt, 512, | cnt, 512, | ||||
DEVSTAT_ALL_SUPPORTED, | DEVSTAT_ALL_SUPPORTED, | ||||
DEVSTAT_TYPE_DIRECT | XPORT_DEVSTAT_TYPE(cpi.transport), | DEVSTAT_TYPE_DIRECT | XPORT_DEVSTAT_TYPE(cpi.transport), | ||||
DEVSTAT_PRIORITY_DISK); | DEVSTAT_PRIORITY_DISK); | ||||
part->disk->d_open = sddaopen; | part->disk->d_open = sddaopen; | ||||
part->disk->d_close = sddaclose; | part->disk->d_close = sddaclose; | ||||
part->disk->d_strategy = sddastrategy; | part->disk->d_strategy = sddastrategy; | ||||
if (cam_sim_pollable(periph->sim)) | |||||
part->disk->d_dump = sddadump; | |||||
part->disk->d_getattr = sddagetattr; | part->disk->d_getattr = sddagetattr; | ||||
part->disk->d_gone = sddadiskgonecb; | part->disk->d_gone = sddadiskgonecb; | ||||
part->disk->d_name = part->name; | part->disk->d_name = part->name; | ||||
part->disk->d_drv1 = part; | part->disk->d_drv1 = part; | ||||
part->disk->d_maxsize = | part->disk->d_maxsize = | ||||
MIN(maxphys, sdda_get_max_data(periph, | MIN(maxphys, sdda_get_max_data(periph, | ||||
(union ccb *)&cpi) * mmc_get_sector_size(periph)); | (union ccb *)&cpi) * mmc_get_sector_size(periph)); | ||||
part->disk->d_unit = cnt; | part->disk->d_unit = cnt; | ||||
▲ Show 20 Lines • Show All 419 Lines • ▼ Show 20 Lines | sddadone(struct cam_periph *periph, union ccb *done_ccb) | ||||
biodone(bp); | biodone(bp); | ||||
} | } | ||||
static int | static int | ||||
sddaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) | sddaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) | ||||
{ | { | ||||
return(cam_periph_error(ccb, cam_flags, sense_flags)); | return(cam_periph_error(ccb, cam_flags, sense_flags)); | ||||
} | } | ||||
static int | |||||
sddadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, | |||||
size_t length) | |||||
{ | |||||
struct ccb_mmcio mmcio; | |||||
struct disk *dp; | |||||
struct sdda_part *part; | |||||
struct sdda_softc *softc; | |||||
struct cam_periph *periph; | |||||
struct mmc_params *mmcp; | |||||
uint16_t count; | |||||
uint16_t opcode; | |||||
int error; | |||||
dp = arg; | |||||
part = dp->d_drv1; | |||||
softc = part->sc; | |||||
periph = softc->periph; | |||||
mmcp = &periph->path->device->mmc_ident_data; | |||||
if (softc->state != SDDA_STATE_NORMAL) | |||||
return (ENXIO); | |||||
count = length / 512; | |||||
if (count == 0) | |||||
return (0); | |||||
if (softc->part[softc->part_curr] != part) | |||||
return (EIO); /* TODO implement polled partition switch */ | |||||
imp: when would that be possible during a system core dump? | |||||
Done Inline ActionsI guess it can happen if a different eMMC partition is accessed right before a crash / panic. avg: I guess it can happen if a different eMMC partition is accessed right before a crash / panic. | |||||
memset(&mmcio, 0, sizeof(mmcio)); | |||||
xpt_setup_ccb(&mmcio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); /* XXX needed? */ | |||||
mmcio.ccb_h.func_code = XPT_MMC_IO; | |||||
mmcio.ccb_h.flags = CAM_DIR_OUT; | |||||
mmcio.ccb_h.retry_count = 0; | |||||
mmcio.ccb_h.timeout = 15 * 1000; | |||||
if (count > 1) | |||||
opcode = MMC_WRITE_MULTIPLE_BLOCK; | |||||
else | |||||
opcode = MMC_WRITE_BLOCK; | |||||
mmcio.cmd.opcode = opcode; | |||||
mmcio.cmd.arg = offset / 512; | |||||
Not Done Inline Actions/ MMC_SECTOR_SIZE would be more clear. manu: / MMC_SECTOR_SIZE would be more clear. | |||||
Done Inline ActionsLet me do this as a follow-up commit (I promise!) and cover sddastart as well. avg: Let me do this as a follow-up commit (I promise!) and cover sddastart as well.
Thanks! | |||||
Not Done Inline ActionsSure :) manu: Sure :) | |||||
if (!(mmcp->card_features & CARD_FEATURE_SDHC)) | |||||
mmcio.cmd.arg <<= 9; | |||||
Not Done Inline ActionsWe really should make a define for this but that's out of scope of this review. manu: We really should make a define for this but that's out of scope of this review. | |||||
mmcio.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | |||||
mmcio.cmd.data = softc->mmcdata; | |||||
memset(mmcio.cmd.data, 0, sizeof(struct mmc_data)); | |||||
mmcio.cmd.data->data = virtual; | |||||
mmcio.cmd.data->len = 512 * count; | |||||
Not Done Inline ActionsMMC_SECTOR_SIZE * count would be more clear manu: MMC_SECTOR_SIZE * count would be more clear | |||||
mmcio.cmd.data->flags = MMC_DATA_WRITE; | |||||
/* Direct h/w to issue CMD12 upon completion */ | |||||
if (count > 1) { | |||||
mmcio.cmd.data->flags |= MMC_DATA_MULTI; | |||||
mmcio.stop.opcode = MMC_STOP_TRANSMISSION; | |||||
mmcio.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | |||||
mmcio.stop.arg = 0; | |||||
} | |||||
error = cam_periph_runccb((union ccb *)&mmcio, cam_periph_error, | |||||
0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); | |||||
if (error != 0) | |||||
printf("Aborting dump due to I/O error.\n"); | |||||
return (error); | |||||
} | |||||
#endif /* _KERNEL */ | #endif /* _KERNEL */ |
when would that be possible during a system core dump?