Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/ata/ata_xpt.c
Show First 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | static void ata_set_transfer_settings(struct ccb_trans_settings *cts, | ||||
int async_update); | int async_update); | ||||
static void ata_dev_async(u_int32_t async_code, | static void ata_dev_async(u_int32_t async_code, | ||||
struct cam_eb *bus, | struct cam_eb *bus, | ||||
struct cam_et *target, | struct cam_et *target, | ||||
struct cam_ed *device, | struct cam_ed *device, | ||||
void *async_arg); | void *async_arg); | ||||
static void ata_action(union ccb *start_ccb); | static void ata_action(union ccb *start_ccb); | ||||
static void ata_announce_periph(struct cam_periph *periph); | static void ata_announce_periph(struct cam_periph *periph); | ||||
static void ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb); | |||||
static void ata_proto_announce(struct cam_ed *device); | static void ata_proto_announce(struct cam_ed *device); | ||||
static void ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); | |||||
static void ata_proto_denounce(struct cam_ed *device); | static void ata_proto_denounce(struct cam_ed *device); | ||||
static void ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); | |||||
static void ata_proto_debug_out(union ccb *ccb); | static void ata_proto_debug_out(union ccb *ccb); | ||||
static void semb_proto_announce(struct cam_ed *device); | static void semb_proto_announce(struct cam_ed *device); | ||||
static void semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); | |||||
static void semb_proto_denounce(struct cam_ed *device); | static void semb_proto_denounce(struct cam_ed *device); | ||||
static void semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); | |||||
static int ata_dma = 1; | static int ata_dma = 1; | ||||
static int atapi_dma = 1; | static int atapi_dma = 1; | ||||
TUNABLE_INT("hw.ata.ata_dma", &ata_dma); | TUNABLE_INT("hw.ata.ata_dma", &ata_dma); | ||||
TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); | TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); | ||||
static struct xpt_xport_ops ata_xport_ops = { | static struct xpt_xport_ops ata_xport_ops = { | ||||
.alloc_device = ata_alloc_device, | .alloc_device = ata_alloc_device, | ||||
.action = ata_action, | .action = ata_action, | ||||
.async = ata_dev_async, | .async = ata_dev_async, | ||||
.announce = ata_announce_periph, | .announce = ata_announce_periph, | ||||
.announce_sbuf = ata_announce_periph_sbuf, | |||||
}; | }; | ||||
#define ATA_XPT_XPORT(x, X) \ | #define ATA_XPT_XPORT(x, X) \ | ||||
static struct xpt_xport ata_xport_ ## x = { \ | static struct xpt_xport ata_xport_ ## x = { \ | ||||
.xport = XPORT_ ## X, \ | .xport = XPORT_ ## X, \ | ||||
.name = #x, \ | .name = #x, \ | ||||
.ops = &ata_xport_ops, \ | .ops = &ata_xport_ops, \ | ||||
}; \ | }; \ | ||||
CAM_XPT_XPORT(ata_xport_ ## x); | CAM_XPT_XPORT(ata_xport_ ## x); | ||||
ATA_XPT_XPORT(ata, ATA); | ATA_XPT_XPORT(ata, ATA); | ||||
ATA_XPT_XPORT(sata, SATA); | ATA_XPT_XPORT(sata, SATA); | ||||
#undef ATA_XPORT_XPORT | #undef ATA_XPORT_XPORT | ||||
static struct xpt_proto_ops ata_proto_ops_ata = { | static struct xpt_proto_ops ata_proto_ops_ata = { | ||||
.announce = ata_proto_announce, | .announce = ata_proto_announce, | ||||
.announce_sbuf = ata_proto_announce_sbuf, | |||||
.denounce = ata_proto_denounce, | .denounce = ata_proto_denounce, | ||||
.denounce_sbuf = ata_proto_denounce_sbuf, | |||||
.debug_out = ata_proto_debug_out, | .debug_out = ata_proto_debug_out, | ||||
}; | }; | ||||
static struct xpt_proto ata_proto_ata = { | static struct xpt_proto ata_proto_ata = { | ||||
.proto = PROTO_ATA, | .proto = PROTO_ATA, | ||||
.name = "ata", | .name = "ata", | ||||
.ops = &ata_proto_ops_ata, | .ops = &ata_proto_ops_ata, | ||||
}; | }; | ||||
static struct xpt_proto_ops ata_proto_ops_satapm = { | static struct xpt_proto_ops ata_proto_ops_satapm = { | ||||
.announce = ata_proto_announce, | .announce = ata_proto_announce, | ||||
.announce_sbuf = ata_proto_announce_sbuf, | |||||
.denounce = ata_proto_denounce, | .denounce = ata_proto_denounce, | ||||
.denounce_sbuf = ata_proto_denounce_sbuf, | |||||
.debug_out = ata_proto_debug_out, | .debug_out = ata_proto_debug_out, | ||||
}; | }; | ||||
static struct xpt_proto ata_proto_satapm = { | static struct xpt_proto ata_proto_satapm = { | ||||
.proto = PROTO_SATAPM, | .proto = PROTO_SATAPM, | ||||
.name = "satapm", | .name = "satapm", | ||||
.ops = &ata_proto_ops_satapm, | .ops = &ata_proto_ops_satapm, | ||||
}; | }; | ||||
static struct xpt_proto_ops ata_proto_ops_semb = { | static struct xpt_proto_ops ata_proto_ops_semb = { | ||||
.announce = semb_proto_announce, | .announce = semb_proto_announce, | ||||
.announce_sbuf = semb_proto_announce_sbuf, | |||||
.denounce = semb_proto_denounce, | .denounce = semb_proto_denounce, | ||||
.denounce_sbuf = semb_proto_denounce_sbuf, | |||||
.debug_out = ata_proto_debug_out, | .debug_out = ata_proto_debug_out, | ||||
}; | }; | ||||
static struct xpt_proto ata_proto_semb = { | static struct xpt_proto ata_proto_semb = { | ||||
.proto = PROTO_SEMB, | .proto = PROTO_SEMB, | ||||
.name = "semb", | .name = "semb", | ||||
.ops = &ata_proto_ops_semb, | .ops = &ata_proto_ops_semb, | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 1,811 Lines • ▼ Show 20 Lines | xpt_compile_path(&path, NULL, bus->path_id, target->target_id, | ||||
device->lun_id); | device->lun_id); | ||||
ata_set_transfer_settings(settings, &path, | ata_set_transfer_settings(settings, &path, | ||||
/*async_update*/TRUE); | /*async_update*/TRUE); | ||||
xpt_release_path(&path); | xpt_release_path(&path); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
ata_announce_periph(struct cam_periph *periph) | _ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed) | ||||
{ | { | ||||
struct ccb_pathinq cpi; | struct ccb_pathinq cpi; | ||||
struct ccb_trans_settings cts; | |||||
struct cam_path *path = periph->path; | struct cam_path *path = periph->path; | ||||
u_int speed; | |||||
u_int mb; | |||||
cam_periph_assert(periph, MA_OWNED); | cam_periph_assert(periph, MA_OWNED); | ||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); | xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL); | ||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; | cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; | ||||
cts.type = CTS_TYPE_CURRENT_SETTINGS; | cts->type = CTS_TYPE_CURRENT_SETTINGS; | ||||
xpt_action((union ccb*)&cts); | xpt_action((union ccb*)cts); | ||||
if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) | if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) | ||||
return; | return; | ||||
/* Ask the SIM for its base transfer speed */ | /* Ask the SIM for its base transfer speed */ | ||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); | xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); | ||||
cpi.ccb_h.func_code = XPT_PATH_INQ; | cpi.ccb_h.func_code = XPT_PATH_INQ; | ||||
xpt_action((union ccb *)&cpi); | xpt_action((union ccb *)&cpi); | ||||
/* Report connection speed */ | /* Report connection speed */ | ||||
speed = cpi.base_transfer_speed; | *speed = cpi.base_transfer_speed; | ||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { | if (cts->transport == XPORT_ATA) { | ||||
struct ccb_trans_settings_pata *pata = | struct ccb_trans_settings_pata *pata = | ||||
&cts.xport_specific.ata; | &cts->xport_specific.ata; | ||||
if (pata->valid & CTS_ATA_VALID_MODE) | if (pata->valid & CTS_ATA_VALID_MODE) | ||||
speed = ata_mode2speed(pata->mode); | *speed = ata_mode2speed(pata->mode); | ||||
} | } | ||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { | if (cts->transport == XPORT_SATA) { | ||||
struct ccb_trans_settings_sata *sata = | struct ccb_trans_settings_sata *sata = | ||||
&cts.xport_specific.sata; | &cts->xport_specific.sata; | ||||
if (sata->valid & CTS_SATA_VALID_REVISION) | if (sata->valid & CTS_SATA_VALID_REVISION) | ||||
speed = ata_revision2speed(sata->revision); | *speed = ata_revision2speed(sata->revision); | ||||
} | } | ||||
} | |||||
static void | |||||
ata_announce_periph(struct cam_periph *periph) | |||||
{ | |||||
struct ccb_trans_settings cts; | |||||
u_int speed, mb; | |||||
_ata_announce_periph(periph, &cts, &speed); | |||||
if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) | |||||
return; | |||||
mb = speed / 1000; | mb = speed / 1000; | ||||
if (mb > 0) | if (mb > 0) | ||||
printf("%s%d: %d.%03dMB/s transfers", | printf("%s%d: %d.%03dMB/s transfers", | ||||
periph->periph_name, periph->unit_number, | periph->periph_name, periph->unit_number, | ||||
mb, speed % 1000); | mb, speed % 1000); | ||||
else | else | ||||
printf("%s%d: %dKB/s transfers", periph->periph_name, | printf("%s%d: %dKB/s transfers", periph->periph_name, | ||||
periph->unit_number, speed); | periph->unit_number, speed); | ||||
/* Report additional information about connection */ | /* Report additional information about connection */ | ||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { | if (cts.transport == XPORT_ATA) { | ||||
struct ccb_trans_settings_pata *pata = | struct ccb_trans_settings_pata *pata = | ||||
&cts.xport_specific.ata; | &cts.xport_specific.ata; | ||||
printf(" ("); | printf(" ("); | ||||
if (pata->valid & CTS_ATA_VALID_MODE) | if (pata->valid & CTS_ATA_VALID_MODE) | ||||
printf("%s, ", ata_mode2string(pata->mode)); | printf("%s, ", ata_mode2string(pata->mode)); | ||||
if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) | if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) | ||||
printf("ATAPI %dbytes, ", pata->atapi); | printf("ATAPI %dbytes, ", pata->atapi); | ||||
if (pata->valid & CTS_ATA_VALID_BYTECOUNT) | if (pata->valid & CTS_ATA_VALID_BYTECOUNT) | ||||
printf("PIO %dbytes", pata->bytecount); | printf("PIO %dbytes", pata->bytecount); | ||||
printf(")"); | printf(")"); | ||||
} | } | ||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { | if (cts.transport == XPORT_SATA) { | ||||
struct ccb_trans_settings_sata *sata = | struct ccb_trans_settings_sata *sata = | ||||
&cts.xport_specific.sata; | &cts.xport_specific.sata; | ||||
printf(" ("); | printf(" ("); | ||||
if (sata->valid & CTS_SATA_VALID_REVISION) | if (sata->valid & CTS_SATA_VALID_REVISION) | ||||
printf("SATA %d.x, ", sata->revision); | printf("SATA %d.x, ", sata->revision); | ||||
else | else | ||||
printf("SATA, "); | printf("SATA, "); | ||||
if (sata->valid & CTS_SATA_VALID_MODE) | if (sata->valid & CTS_SATA_VALID_MODE) | ||||
printf("%s, ", ata_mode2string(sata->mode)); | printf("%s, ", ata_mode2string(sata->mode)); | ||||
if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) | if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) | ||||
printf("ATAPI %dbytes, ", sata->atapi); | printf("ATAPI %dbytes, ", sata->atapi); | ||||
if (sata->valid & CTS_SATA_VALID_BYTECOUNT) | if (sata->valid & CTS_SATA_VALID_BYTECOUNT) | ||||
printf("PIO %dbytes", sata->bytecount); | printf("PIO %dbytes", sata->bytecount); | ||||
printf(")"); | printf(")"); | ||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
static void | static void | ||||
ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) | |||||
{ | |||||
struct ccb_trans_settings cts; | |||||
u_int speed, mb; | |||||
_ata_announce_periph(periph, &cts, &speed); | |||||
if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) | |||||
return; | |||||
mb = speed / 1000; | |||||
if (mb > 0) | |||||
sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers", | |||||
periph->periph_name, periph->unit_number, | |||||
mb, speed % 1000); | |||||
else | |||||
sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name, | |||||
periph->unit_number, speed); | |||||
/* Report additional information about connection */ | |||||
if (cts.transport == XPORT_ATA) { | |||||
struct ccb_trans_settings_pata *pata = | |||||
&cts.xport_specific.ata; | |||||
sbuf_printf(sb, " ("); | |||||
if (pata->valid & CTS_ATA_VALID_MODE) | |||||
sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode)); | |||||
if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) | |||||
sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi); | |||||
if (pata->valid & CTS_ATA_VALID_BYTECOUNT) | |||||
sbuf_printf(sb, "PIO %dbytes", pata->bytecount); | |||||
sbuf_printf(sb, ")"); | |||||
} | |||||
if (cts.transport == XPORT_SATA) { | |||||
struct ccb_trans_settings_sata *sata = | |||||
&cts.xport_specific.sata; | |||||
sbuf_printf(sb, " ("); | |||||
if (sata->valid & CTS_SATA_VALID_REVISION) | |||||
sbuf_printf(sb, "SATA %d.x, ", sata->revision); | |||||
else | |||||
sbuf_printf(sb, "SATA, "); | |||||
if (sata->valid & CTS_SATA_VALID_MODE) | |||||
sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode)); | |||||
if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) | |||||
sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi); | |||||
if (sata->valid & CTS_SATA_VALID_BYTECOUNT) | |||||
sbuf_printf(sb, "PIO %dbytes", sata->bytecount); | |||||
sbuf_printf(sb, ")"); | |||||
} | |||||
sbuf_printf(sb, "\n"); | |||||
} | |||||
static void | |||||
ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) | |||||
{ | |||||
ata_print_ident_sbuf(&device->ident_data, sb); | |||||
} | |||||
static void | |||||
ata_proto_announce(struct cam_ed *device) | ata_proto_announce(struct cam_ed *device) | ||||
{ | { | ||||
ata_print_ident(&device->ident_data); | ata_print_ident(&device->ident_data); | ||||
} | } | ||||
static void | static void | ||||
ata_proto_denounce(struct cam_ed *device) | ata_proto_denounce(struct cam_ed *device) | ||||
{ | { | ||||
ata_print_ident_short(&device->ident_data); | ata_print_ident_short(&device->ident_data); | ||||
} | } | ||||
static void | static void | ||||
ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) | |||||
{ | |||||
ata_print_ident_short_sbuf(&device->ident_data, sb); | |||||
} | |||||
static void | |||||
semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) | |||||
{ | |||||
semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb); | |||||
} | |||||
static void | |||||
semb_proto_announce(struct cam_ed *device) | semb_proto_announce(struct cam_ed *device) | ||||
{ | { | ||||
semb_print_ident((struct sep_identify_data *)&device->ident_data); | semb_print_ident((struct sep_identify_data *)&device->ident_data); | ||||
} | } | ||||
static void | static void | ||||
semb_proto_denounce(struct cam_ed *device) | semb_proto_denounce(struct cam_ed *device) | ||||
{ | { | ||||
semb_print_ident_short((struct sep_identify_data *)&device->ident_data); | semb_print_ident_short((struct sep_identify_data *)&device->ident_data); | ||||
} | |||||
static void | |||||
semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) | |||||
{ | |||||
semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb); | |||||
} | } | ||||
static void | static void | ||||
ata_proto_debug_out(union ccb *ccb) | ata_proto_debug_out(union ccb *ccb) | ||||
{ | { | ||||
char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; | char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; | ||||
if (ccb->ccb_h.func_code != XPT_ATA_IO) | if (ccb->ccb_h.func_code != XPT_ATA_IO) | ||||
return; | return; | ||||
CAM_DEBUG(ccb->ccb_h.path, | CAM_DEBUG(ccb->ccb_h.path, | ||||
CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), | CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd), | ||||
ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); | ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str)))); | ||||
} | } |