From owner-p4-projects@FreeBSD.ORG Sat Jun 13 20:54:33 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2BBA4106567A; Sat, 13 Jun 2009 20:54:33 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DC5C71065675 for ; Sat, 13 Jun 2009 20:54:32 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id C64E98FC23 for ; Sat, 13 Jun 2009 20:54:32 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5DKsWkr075021 for ; Sat, 13 Jun 2009 20:54:32 GMT (envelope-from mav@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5DKsWMY075017 for perforce@freebsd.org; Sat, 13 Jun 2009 20:54:32 GMT (envelope-from mav@freebsd.org) Date: Sat, 13 Jun 2009 20:54:32 GMT Message-Id: <200906132054.n5DKsWMY075017@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mav@freebsd.org using -f From: Alexander Motin To: Perforce Change Reviews Cc: Subject: PERFORCE change 164293 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Jun 2009 20:54:34 -0000 http://perforce.freebsd.org/chv.cgi?CH=164293 Change 164293 by mav@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);