PERFORCE change 164293 for review
Alexander Motin
mav at FreeBSD.org
Sat Jun 13 20:54:34 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=164293
Change 164293 by mav at mav_mavbook on 2009/06/13 20:53:49
Add basic SATA Port Multiplier support.
Affected files ...
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#9 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#9 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#16 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#21 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#25 edit
Differences ...
==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#9 (text+ko) ====
@@ -133,11 +133,42 @@
ataio->cmd.features_exp = sector_count >> 8;
}
-void ata_reset_cmd(struct ccb_ataio *ataio)
+void
+ata_reset_cmd(struct ccb_ataio *ataio)
{
bzero(&ataio->cmd, sizeof(ataio->cmd));
ataio->cmd.flags = CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT;
ataio->cmd.control = 0x04;
}
+void
+ata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port)
+{
+ bzero(&ataio->cmd, sizeof(ataio->cmd));
+ ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_NEEDRESULT;
+ ataio->cmd.command = ATA_READ_PM;
+ ataio->cmd.features = reg;
+ ataio->cmd.features_exp = reg >> 8;
+ ataio->cmd.device = port & 0x0f;
+}
+
+void
+ata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint64_t val)
+{
+ bzero(&ataio->cmd, sizeof(ataio->cmd));
+ ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_NEEDRESULT;
+ ataio->cmd.command = ATA_WRITE_PM;
+ ataio->cmd.features = reg;
+ ataio->cmd.lba_low = val >> 8;
+ ataio->cmd.lba_mid = val >> 16;
+ ataio->cmd.lba_high = val >> 24;
+ ataio->cmd.device = port & 0x0f;
+ ataio->cmd.lba_low_exp = val >> 40;
+ ataio->cmd.lba_mid_exp = val >> 48;
+ ataio->cmd.lba_high_exp = val >> 56;
+ ataio->cmd.features_exp = reg >> 8;
+ ataio->cmd.sector_count = val;
+ ataio->cmd.sector_count_exp = val >> 32;
+}
+
#endif /* _KERNEL */
==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#9 (text+ko) ====
@@ -87,5 +87,7 @@
void ata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd,
uint64_t lba, uint16_t sector_count);
void ata_reset_cmd(struct ccb_ataio *ataio);
+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, uint64_t val);
#endif
==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#16 (text+ko) ====
@@ -95,6 +95,13 @@
PROBE_IDENTIFY,
PROBE_INQUIRY,
PROBE_FULL_INQUIRY,
+ PROBE_PM_PID,
+ PROBE_PM_PRV,
+ PROBE_PM_PORTS,
+ PROBE_PM_RESET,
+ PROBE_PM_CONNECT,
+ PROBE_PM_CHECK,
+ PROBE_PM_CLEAR,
PROBE_INVALID
} probe_action;
@@ -103,6 +110,13 @@
"PROBE_IDENTIFY",
"PROBE_INQUIRY",
"PROBE_FULL_INQUIRY",
+ "PROBE_PM_PID",
+ "PROBE_PM_PRV",
+ "PROBE_PM_PORTS",
+ "PROBE_PM_RESET",
+ "PROBE_PM_CONNECT",
+ "PROBE_PM_CHECK",
+ "PROBE_PM_CLEAR",
"PROBE_INVALID"
};
@@ -126,6 +140,12 @@
union ccb saved_ccb;
probe_flags flags;
u_int8_t digest[16];
+ uint32_t pm_pid;
+ uint32_t pm_prv;
+ int pm_ports;
+ int pm_step;
+ int pm_try;
+ int pm_found;
struct cam_periph *periph;
} probe_softc;
@@ -329,21 +349,20 @@
switch (softc->action) {
case PROBE_RESET:
cam_fill_ataio(ataio,
- 4,
+ 1,
probedone,
/*flags*/CAM_DIR_NONE,
MSG_SIMPLE_Q_TAG,
/*data_ptr*/NULL,
/*dxfer_len*/0,
- 30 * 1000);
+ 10 * 1000);
ata_reset_cmd(ataio);
break;
case PROBE_IDENTIFY:
{
- struct ata_params *ident_buf;
+ struct ata_params *ident_buf =
+ &periph->path->device->ident_data;
- ident_buf = &periph->path->device->ident_data;
-
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
/* Prepare check that it is the same device. */
MD5_CTX context;
@@ -360,16 +379,14 @@
sizeof(ident_buf->serial));
MD5Final(softc->digest, &context);
}
-
cam_fill_ataio(ataio,
- 4,
+ 1,
probedone,
/*flags*/CAM_DIR_IN,
MSG_SIMPLE_Q_TAG,
/*data_ptr*/(u_int8_t *)ident_buf,
/*dxfer_len*/sizeof(struct ata_params),
30 * 1000);
-
if (periph->path->device->protocol == PROTO_ATA)
ata_36bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
else
@@ -380,15 +397,13 @@
case PROBE_FULL_INQUIRY:
{
u_int inquiry_len;
- struct scsi_inquiry_data *inq_buf;
-
- inq_buf = &periph->path->device->inq_data;
+ struct scsi_inquiry_data *inq_buf =
+ &periph->path->device->inq_data;
if (softc->action == PROBE_INQUIRY)
inquiry_len = SHORT_INQUIRY_LENGTH;
else
inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf);
-
/*
* Some parallel SCSI devices fail to send an
* ignore wide residue message when dealing with
@@ -396,7 +411,6 @@
* safe.
*/
inquiry_len = roundup2(inquiry_len, 2);
-
scsi_inquiry(csio,
/*retries*/4,
probedone,
@@ -409,6 +423,83 @@
/*timeout*/60 * 1000);
break;
}
+ case PROBE_PM_PID:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_read_cmd(ataio, 0, 15);
+ break;
+ case PROBE_PM_PRV:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_read_cmd(ataio, 1, 15);
+ break;
+ case PROBE_PM_PORTS:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_read_cmd(ataio, 2, 15);
+ break;
+ case PROBE_PM_RESET:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_write_cmd(ataio, 2, softc->pm_step, 1);
+ break;
+ case PROBE_PM_CONNECT:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_write_cmd(ataio, 2, softc->pm_step, 0);
+ break;
+ case PROBE_PM_CHECK:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_read_cmd(ataio, 0, softc->pm_step);
+ break;
+ case PROBE_PM_CLEAR:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ 10 * 1000);
+ ata_pm_write_cmd(ataio, 1, softc->pm_step, 0xFFFFFFFF);
+ break;
case PROBE_INVALID:
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
("probestart: invalid action state\n"));
@@ -546,6 +637,7 @@
probe_softc *softc;
struct cam_path *path;
u_int32_t priority;
+ int found = 0;
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
@@ -556,15 +648,27 @@
switch (softc->action) {
case PROBE_RESET:
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
- printf("SIGNATURE: %02x%02x%02x%02x\n",
- done_ccb->ataio.res.lba_high, done_ccb->ataio.res.lba_mid,
- done_ccb->ataio.res.lba_low, done_ccb->ataio.res.sector_count);
- if (done_ccb->ataio.res.lba_high == 0xeb &&
- done_ccb->ataio.res.lba_mid == 0x14)
+ int sign = (done_ccb->ataio.res.lba_high << 8) +
+ done_ccb->ataio.res.lba_mid;
+ printf("SIGNATURE: %04x\n", sign);
+ if (sign == 0x0000 &&
+ done_ccb->ccb_h.target_id != 15) {
+ path->device->protocol = PROTO_ATA;
+ PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
+ } else if (sign == 0x9669 &&
+ done_ccb->ccb_h.target_id == 15) {
+ path->device->protocol = PROTO_SATAPM;
+ PROBE_SET_ACTION(softc, PROBE_PM_PID);
+ } else if (sign == 0xeb14 &&
+ done_ccb->ccb_h.target_id != 15) {
path->device->protocol = PROTO_SCSI;
- else
- path->device->protocol = PROTO_ATA;
- PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
+ PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
+ } else {
+ xpt_print(path,
+ "Unexpected signature 0x%04x\n", sign);
+ xpt_release_ccb(done_ccb);
+ break;
+ }
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
@@ -654,12 +758,7 @@
path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
scsi_find_quirk(path->device);
-
ata_device_transport(path);
-// if (INQ_DATA_TQ_ENABLED(inq_buf))
-// PROBE_SET_ACTION(softc, PROBE_MODE_SENSE);
-// else
-// PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0);
// if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
if (path->device->protocol == PROTO_ATA) {
@@ -779,6 +878,209 @@
xpt_release_ccb(done_ccb);
break;
}
+ case PROBE_PM_PID:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ softc->pm_pid = (done_ccb->ataio.res.lba_high << 24) +
+ (done_ccb->ataio.res.lba_mid << 16) +
+ (done_ccb->ataio.res.lba_low << 8) +
+ done_ccb->ataio.res.sector_count;
+ printf("PM Product ID: %08x\n", softc->pm_pid);
+ PROBE_SET_ACTION(softc, PROBE_PM_PRV);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_PM_PRV:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) +
+ (done_ccb->ataio.res.lba_mid << 16) +
+ (done_ccb->ataio.res.lba_low << 8) +
+ done_ccb->ataio.res.sector_count;
+ printf("PM Revision: %08x\n", softc->pm_prv);
+ PROBE_SET_ACTION(softc, PROBE_PM_PORTS);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_PM_PORTS:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ softc->pm_ports = (done_ccb->ataio.res.lba_high << 24) +
+ (done_ccb->ataio.res.lba_mid << 16) +
+ (done_ccb->ataio.res.lba_low << 8) +
+ done_ccb->ataio.res.sector_count;
+ /* This PM declares 6 ports, while only 5 of them are real.
+ * Port 5 is enclosure management bridge port, which has implementation
+ * problems, causing probe faults. Hide it for now. */
+ if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6)
+ softc->pm_ports = 5;
+ /* This PM declares 7 ports, while only 5 of them are real.
+ * Port 5 is some fake "Config Disk" with 640 sectors size,
+ * port 6 is enclosure management bridge port.
+ * Both fake ports has implementation problems, causing
+ * probe faults. Hide them for now. */
+ if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7)
+ softc->pm_ports = 5;
+ printf("PM ports: %d\n", softc->pm_ports);
+ PROBE_SET_ACTION(softc, PROBE_PM_RESET);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_PM_RESET:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ softc->pm_step++;
+ if (softc->pm_step < softc->pm_ports) {
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ } else {
+ softc->pm_step = 0;
+ DELAY(5000);
+ PROBE_SET_ACTION(softc, PROBE_PM_CONNECT);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_PM_CONNECT:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ softc->pm_step++;
+ if (softc->pm_step < softc->pm_ports) {
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ } else {
+ softc->pm_step = 0;
+ softc->pm_found = 0x8000;
+ PROBE_SET_ACTION(softc, PROBE_PM_CHECK);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_PM_CHECK:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ int res = (done_ccb->ataio.res.lba_high << 24) +
+ (done_ccb->ataio.res.lba_mid << 16) +
+ (done_ccb->ataio.res.lba_low << 8) +
+ done_ccb->ataio.res.sector_count;
+ if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) {
+ printf("PM found: %d - %08x\n", softc->pm_step, res);
+ softc->pm_found |= (1 << softc->pm_step);
+ softc->pm_step++;
+ } else {
+ if (softc->pm_try < 50) {
+ DELAY(10000);
+ softc->pm_try++;
+ } else
+ softc->pm_step++;
+ }
+ if (softc->pm_step < softc->pm_ports) {
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ } else {
+ softc->pm_step = 0;
+ PROBE_SET_ACTION(softc, PROBE_PM_CLEAR);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_PM_CLEAR:
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ softc->pm_step++;
+ if (softc->pm_step < softc->pm_ports) {
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ found = softc->pm_found;
+ } else if (cam_periph_error(done_ccb, 0,
+ done_ccb->ccb_h.target_lun > 0
+ ? SF_RETRY_UA|SF_QUIET_IR
+ : SF_RETRY_UA,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
case PROBE_INVALID:
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO,
("probedone: invalid action state\n"));
@@ -788,6 +1090,7 @@
done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe);
done_ccb->ccb_h.status = CAM_REQ_CMP;
+ done_ccb->ccb_h.ppriv_field1 = found;
xpt_done(done_ccb);
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
cam_periph_invalidate(periph);
@@ -828,6 +1131,7 @@
union ccb *request_ccb;
struct ccb_pathinq *cpi;
int counter;
+ int found;
} ata_scan_bus_info;
/*
@@ -838,17 +1142,15 @@
static void
ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
{
+ struct cam_path *path;
+ ata_scan_bus_info *scan_info;
+ union ccb *work_ccb;
+ cam_status status;
+
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
("xpt_scan_bus\n"));
switch (request_ccb->ccb_h.func_code) {
case XPT_SCAN_BUS:
- {
- ata_scan_bus_info *scan_info;
- union ccb *work_ccb;
- struct cam_path *path;
- u_int i;
- u_int max_target;
-
/* Find out the characteristics of the bus */
work_ccb = xpt_alloc_ccb_nowait();
if (work_ccb == NULL) {
@@ -877,88 +1179,36 @@
}
scan_info->request_ccb = request_ccb;
scan_info->cpi = &work_ccb->cpi;
+ scan_info->found = 0x8001;
- /* Cache on our stack so we can work asynchronously */
- max_target = scan_info->cpi->max_target;
+ /* If PM supported, probe it first. */
+ if (scan_info->cpi->hba_inquiry & PI_SATAPM)
+ scan_info->counter = 15;
- /*
- * We can scan all targets in parallel, or do it sequentially.
- */
- if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
- max_target = 0;
- scan_info->counter = 0;
- } else {
- scan_info->counter = scan_info->cpi->max_target + 1;
+ work_ccb = xpt_alloc_ccb_nowait();
+ if (work_ccb == NULL) {
+ free(scan_info, M_CAMXPT);
+ request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ xpt_done(request_ccb);
+ break;
}
-
- for (i = 0; i <= max_target; i++) {
- cam_status status;
-
- status = xpt_create_path(&path, xpt_periph,
- request_ccb->ccb_h.path_id,
- i, 0);
- if (status != CAM_REQ_CMP) {
- printf("xpt_scan_bus: xpt_create_path failed"
- " with status %#x, bus scan halted\n",
- status);
- free(scan_info, M_CAMXPT);
- request_ccb->ccb_h.status = status;
- xpt_free_ccb(work_ccb);
- xpt_done(request_ccb);
- break;
- }
- work_ccb = xpt_alloc_ccb_nowait();
- if (work_ccb == NULL) {
- free(scan_info, M_CAMXPT);
- xpt_free_path(path);
- request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
- xpt_done(request_ccb);
- break;
- }
- xpt_setup_ccb(&work_ccb->ccb_h, path,
- request_ccb->ccb_h.pinfo.priority);
- work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
- work_ccb->ccb_h.cbfcnp = ata_scan_bus;
- work_ccb->ccb_h.ppriv_ptr0 = scan_info;
- work_ccb->crcn.flags = request_ccb->crcn.flags;
- xpt_action(work_ccb);
- }
- break;
- }
+ goto scan_next;
case XPT_SCAN_LUN:
- {
- cam_status status;
- struct cam_path *path;
- ata_scan_bus_info *scan_info;
- path_id_t path_id;
- target_id_t target_id;
- int done;
-
+ work_ccb = request_ccb;
/* Reuse the same CCB to query if a device was really found */
- scan_info = (ata_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0;
- path_id = request_ccb->ccb_h.path_id;
- target_id = request_ccb->ccb_h.target_id;
+ scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0;
/*
* Free the current request path- we're done with it.
*/
- xpt_free_path(request_ccb->ccb_h.path);
-
- done = 0;
- if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
- scan_info->counter++;
- if (scan_info->counter >=
- scan_info->cpi->max_target+1) {
- done = 1;
- }
- } else {
- scan_info->counter--;
- if (scan_info->counter == 0) {
- done = 1;
- }
- }
- if (done) {
- xpt_free_ccb(request_ccb);
+ xpt_free_path(work_ccb->ccb_h.path);
+ if (scan_info->counter == 15)
+ scan_info->found = work_ccb->ccb_h.ppriv_field1;
+take_next:
+ /* Take next device. Wrap from 15 (PM) to 0. */
+ scan_info->counter = (scan_info->counter + 1 ) & 0x0f;
+ if (scan_info->counter >= scan_info->cpi->max_target+1) {
+ xpt_free_ccb(work_ccb);
xpt_free_ccb((union ccb *)scan_info->cpi);
request_ccb = scan_info->request_ccb;
free(scan_info, M_CAMXPT);
@@ -966,18 +1216,15 @@
xpt_done(request_ccb);
break;
}
-
- if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0)
- break;
-
+scan_next:
status = xpt_create_path(&path, xpt_periph,
scan_info->request_ccb->ccb_h.path_id,
scan_info->counter, 0);
if (status != CAM_REQ_CMP) {
printf("xpt_scan_bus: xpt_create_path failed"
" with status %#x, bus scan halted\n",
- status);
- xpt_free_ccb(request_ccb);
+ status);
+ xpt_free_ccb(work_ccb);
xpt_free_ccb((union ccb *)scan_info->cpi);
request_ccb = scan_info->request_ccb;
free(scan_info, M_CAMXPT);
@@ -985,16 +1232,18 @@
xpt_done(request_ccb);
break;
}
- xpt_setup_ccb(&request_ccb->ccb_h, path,
- request_ccb->ccb_h.pinfo.priority);
- request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
- request_ccb->ccb_h.cbfcnp = ata_scan_bus;
- request_ccb->ccb_h.ppriv_ptr0 = scan_info;
- request_ccb->crcn.flags =
- scan_info->request_ccb->crcn.flags;
- xpt_action(request_ccb);
+ if ((scan_info->found & (1 << scan_info->counter)) == 0) {
+ xpt_async(AC_LOST_DEVICE, path, NULL);
+ goto take_next;
+ }
+ xpt_setup_ccb(&work_ccb->ccb_h, path,
+ scan_info->request_ccb->ccb_h.pinfo.priority);
+ work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
+ work_ccb->ccb_h.cbfcnp = ata_scan_bus;
+ work_ccb->ccb_h.ppriv_ptr0 = scan_info;
+ work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags;
+ xpt_action(work_ccb);
break;
- }
default:
break;
}
==== //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#21 (text+ko) ====
==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#25 (text+ko) ====
@@ -1634,10 +1634,15 @@
cpi->version_num = 1; /* XXX??? */
cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
+ if (ch->caps & AHCI_CAP_SPM)
+ cpi->hba_inquiry |= PI_SATAPM;
cpi->target_sprt = 0;
cpi->hba_misc = PIM_SEQSCAN;
cpi->hba_eng_cnt = 0;
- cpi->max_target = 0;
+ if (ch->caps & AHCI_CAP_SPM)
+ cpi->max_target = 14;
+ else
+ cpi->max_target = 0;
cpi->max_lun = 0;
cpi->initiator_id = 0;
cpi->bus_id = cam_sim_bus(sim);
More information about the p4-projects
mailing list