36#include <sys/kernel.h>
38#include <sys/sysctl.h>
39#include <sys/taskqueue.h>
43#include <sys/devicestat.h>
44#include <sys/eventhandler.h>
45#include <sys/malloc.h>
47#include <geom/geom_disk.h>
90#define ccb_state ppriv_field0
91#define ccb_bp ppriv_ptr1
107#define PMP_EV_RESET 1
108#define PMP_EV_RESCAN 2
110 struct task sysctl_task;
111 struct sysctl_ctx_list sysctl_ctx;
112 struct sysctl_oid *sysctl_tree;
116static void pmpasync(
void *callback_arg, u_int32_t code,
124 union ccb *done_ccb);
126#ifndef PMP_DEFAULT_TIMEOUT
127#define PMP_DEFAULT_TIMEOUT 30
130#ifndef PMP_DEFAULT_RETRY
131#define PMP_DEFAULT_RETRY 1
134#ifndef PMP_DEFAULT_HIDE_SPECIAL
135#define PMP_DEFAULT_HIDE_SPECIAL 1
142static SYSCTL_NODE(_kern_cam, OID_AUTO, pmp, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
143 "CAM Direct Access Disk driver");
144SYSCTL_INT(_kern_cam_pmp, OID_AUTO, retry_count, CTLFLAG_RWTUN,
146SYSCTL_INT(_kern_cam_pmp, OID_AUTO, default_timeout, CTLFLAG_RWTUN,
148SYSCTL_INT(_kern_cam_pmp, OID_AUTO, hide_special, CTLFLAG_RWTUN,
154 TAILQ_HEAD_INITIALIZER(
pmpdriver.units), 0,
172 printf(
"pmp: Failed to attach master async callback "
173 "due to status 0x%x!\n", status);
184 mask &= ~softc->frozen;
185 for (i = 0; i < 15; i++) {
186 if ((mask & (1 << i)) == 0)
191 softc->frozen |= (1 << i);
206 mask &= softc->frozen;
207 for (i = 0; i < 15; i++) {
208 if ((mask & (1 << i)) == 0)
213 softc->frozen &= ~(1 << i);
232 for (i = 0; i < 15; i++) {
256 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
260 free(softc, M_DEVBUF);
298 printf(
"pmpasync: Unable to attach to new device "
299 "due to status 0x%x\n", status);
319 if (softc->pm_pid == 0x37261095 ||
320 softc->pm_pid == 0x38261095)
343 char tmpstr[32], tmpstr2[16];
350 snprintf(tmpstr,
sizeof(tmpstr),
"CAM PMP unit %d", periph->
unit_number);
351 snprintf(tmpstr2,
sizeof(tmpstr2),
"%d", periph->
unit_number);
353 sysctl_ctx_init(&softc->sysctl_ctx);
355 softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
356 SYSCTL_STATIC_CHILDREN(_kern_cam_pmp), OID_AUTO, tmpstr2,
357 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
"device_index");
358 if (softc->sysctl_tree == NULL) {
359 printf(
"pmpsysctlinit: unable to allocate sysctl tree\n");
375 printf(
"pmpregister: no getdev CCB, can't register device\n");
379 softc = (
struct pmp_softc *)malloc(
sizeof(*softc), M_DEVBUF,
383 printf(
"pmpregister: Unable to probe new device. "
384 "Unable to allocate softc\n");
387 periph->
softc = softc;
389 softc->pm_pid = ((uint32_t *)&cgd->
ident_data)[0];
390 softc->pm_prv = ((uint32_t *)&cgd->
ident_data)[1];
430 ataio = &start_ccb->
ataio;
434 if (softc->restart) {
436 if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095)
453 revision =
cts.xport_specific.sata.revision;
457 switch (softc->state) {
503 softc->caps =
cts.xport_specific.sata.caps;
527 ((softc->found & (1 << softc->pm_step)) ? 0 : 1));
589 u_int32_t priority, res;
593 ataio = &done_ccb->
ataio;
612 if (softc->restart) {
615 if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095)
623 switch (softc->state) {
636 if ((softc->pm_pid == 0x37261095 ||
637 softc->pm_pid == 0x38261095) &&
638 softc->pm_ports == 6)
646 if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7)
652 if (softc->pm_pid == 0x57231095 ||
653 softc->pm_pid == 0x57331095 ||
654 softc->pm_pid == 0x57341095 ||
655 softc->pm_pid == 0x57441095)
658 printf(
"%s%d: %d fan-out ports\n",
661 if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095)
674 if (softc->caps & 0x1)
696 printf(
"%s%d: Disabling SiI3x26 R_OK in GSCR_POLL: %x->%x\n",
706 softc->reset |= ~softc->found;
712 if (softc->pm_step >= softc->pm_ports) {
727 if (softc->pm_step >= softc->pm_ports) {
746 if (((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) ||
747 (res & 0x600) != 0) {
749 printf(
"%s%d: port %d status: %08x\n",
751 softc->pm_step, res);
754 if ((res & 0xf0f) == 0x103 &&
762 cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
764 cts.xport_specific.sata.caps = softc->caps &
772 softc->found |= (1 << softc->pm_step);
775 if (softc->pm_try < 10) {
785 printf(
"%s%d: port %d status: %08x\n",
787 softc->pm_step, res);
789 softc->found &= ~(1 << softc->pm_step);
799 if (softc->pm_step >= softc->pm_ports) {
800 if (softc->reset & softc->found) {
816 if (softc->pm_step >= softc->pm_ports) {
824 for (i = 0; i < softc->pm_ports; i++) {
827 if ((softc->found & (1 << i)) == 0)
832 printf(
"pmpdone: xpt_create_path failed\n");
836 if ((softc->reset & softc->found & (1 << i)) != 0)
void ata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port)
void ata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint32_t val)
#define PMP_DEFAULT_HIDE_SPECIAL
static periph_ctor_t pmpregister
static void pmpsysctlinit(void *context, int pending)
#define PMP_DEFAULT_RETRY
static int pmp_retry_count
static void pmpfreeze(struct cam_periph *periph, int mask)
static void pmprelease(struct cam_periph *periph, int mask)
PERIPHDRIVER_DECLARE(pmp, pmpdriver)
static void pmpdone(struct cam_periph *periph, union ccb *done_ccb)
SYSCTL_INT(_kern_cam_pmp, OID_AUTO, retry_count, CTLFLAG_RWTUN, &pmp_retry_count, 0, "Normal I/O retry count")
static periph_dtor_t pmpcleanup
static void pmpasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
#define PMP_DEFAULT_TIMEOUT
static int pmp_default_timeout
static periph_init_t pmpinit
static periph_oninv_t pmponinvalidate
static int pmp_hide_special
static struct periph_driver pmpdriver
static periph_start_t pmpstart
static SYSCTL_NODE(_kern_cam, OID_AUTO, pmp, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Direct Access Disk driver")
#define CAM_PRIORITY_NONE
#define CTS_SATA_CAPS_H_DMAAA
#define RELSIM_RELEASE_AFTER_TIMEOUT
static __inline void cam_fill_ataio(struct ccb_ataio *ataio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int tag_action __unused, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t timeout)
@ CTS_TYPE_CURRENT_SETTINGS
#define CTS_SATA_VALID_CAPS
#define CTS_SATA_CAPS_H_AN
#define CTS_SATA_CAPS_H_PMREQ
#define CTS_SATA_VALID_REVISION
#define CAM_DEBUG(path, flag, printfargs)
void cam_periph_release_locked(struct cam_periph *periph)
void cam_freeze_devq(struct cam_path *path)
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, u_int32_t openings, u_int32_t arg, int getcount_only)
int cam_periph_acquire(struct cam_periph *periph)
void cam_periph_async(struct cam_periph *periph, u_int32_t code, struct cam_path *path, void *arg)
void cam_periph_release(struct cam_periph *periph)
int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags)
cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, periph_oninv_t *periph_oninvalidate, periph_dtor_t *periph_dtor, periph_start_t *periph_start, char *name, cam_periph_type type, struct cam_path *path, ac_callback_t *ac_callback, ac_code code, void *arg)
cam_status periph_ctor_t(struct cam_periph *periph, void *arg)
void periph_oninv_t(struct cam_periph *periph)
#define cam_periph_lock(periph)
#define CAM_PERIPH_DRV_EARLY
#define cam_periph_unlock(periph)
void periph_dtor_t(struct cam_periph *periph)
void periph_start_t(struct cam_periph *periph, union ccb *start_ccb)
void() periph_init_t(void)
void xpt_acquire_device(struct cam_ed *device)
void xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
cam_status xpt_create_path(struct cam_path **new_path_ptr, struct cam_periph *perph, path_id_t path_id, target_id_t target_id, lun_id_t lun_id)
void xpt_release_device(struct cam_ed *device)
void xpt_print(struct cam_path *path, const char *fmt,...)
void xpt_rescan(union ccb *ccb)
path_id_t xpt_path_path_id(struct cam_path *path)
void xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg)
void xpt_announce_periph(struct cam_periph *periph, char *announce_string)
void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
void xpt_action(union ccb *start_ccb)
cam_status xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg, struct cam_path *path)
union ccb * xpt_alloc_ccb_nowait(void)
void xpt_free_path(struct cam_path *path)
void xpt_release_boot(void)
void xpt_release_ccb(union ccb *free_ccb)
struct ccb_trans_settings_mmc * cts
struct cam_periph * periph
struct ata_params ident_data