From owner-svn-src-all@FreeBSD.ORG Tue Nov 17 14:56:01 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 538081065670; Tue, 17 Nov 2009 14:56:01 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4065D8FC0A; Tue, 17 Nov 2009 14:56:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nAHEu1mK014476; Tue, 17 Nov 2009 14:56:01 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nAHEu1UG014474; Tue, 17 Nov 2009 14:56:01 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <200911171456.nAHEu1UG014474@svn.freebsd.org> From: Alexander Motin Date: Tue, 17 Nov 2009 14:56:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r199386 - stable/8/sys/cam/ata X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Nov 2009 14:56:01 -0000 Author: mav Date: Tue Nov 17 14:56:00 2009 New Revision: 199386 URL: http://svn.freebsd.org/changeset/base/199386 Log: MFC r198328: Add support for PIO-only devices. Fix maxio values and 256 sectors transactions for 28bits commands. Implement periodic ordered commands insertion, sames as da driver does. Remove some SCSIsms. Modified: stable/8/sys/cam/ata/ata_da.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/cam/ata/ata_da.c ============================================================================== --- stable/8/sys/cam/ata/ata_da.c Tue Nov 17 14:49:35 2009 (r199385) +++ stable/8/sys/cam/ata/ata_da.c Tue Nov 17 14:56:00 2009 (r199386) @@ -63,37 +63,32 @@ __FBSDID("$FreeBSD$"); #define ATA_MAX_28BIT_LBA 268435455UL typedef enum { - ADA_STATE_NORMAL + ADA_STATE_NORMAL, + ADA_STATE_SET_MULTI } ada_state; typedef enum { ADA_FLAG_PACK_INVALID = 0x001, ADA_FLAG_CAN_48BIT = 0x002, ADA_FLAG_CAN_FLUSHCACHE = 0x004, - ADA_FLAG_CAN_NCQ = 0x008, - ADA_FLAG_TAGGED_QUEUING = 0x010, + ADA_FLAG_CAN_NCQ = 0x008, + ADA_FLAG_CAN_DMA = 0x010, ADA_FLAG_NEED_OTAG = 0x020, ADA_FLAG_WENT_IDLE = 0x040, - ADA_FLAG_RETRY_UA = 0x080, ADA_FLAG_OPEN = 0x100, ADA_FLAG_SCTX_INIT = 0x200 } ada_flags; typedef enum { - ADA_Q_NONE = 0x00, - ADA_Q_NO_SYNC_CACHE = 0x01, - ADA_Q_NO_6_BYTE = 0x02, - ADA_Q_NO_PREVENT = 0x04 + ADA_Q_NONE = 0x00 } ada_quirks; typedef enum { - ADA_CCB_PROBE = 0x01, - ADA_CCB_PROBE2 = 0x02, + ADA_CCB_SET_MULTI = 0x01, ADA_CCB_BUFFER_IO = 0x03, ADA_CCB_WAITING = 0x04, ADA_CCB_DUMP = 0x05, ADA_CCB_TYPE_MASK = 0x0F, - ADA_CCB_RETRY_UA = 0x10 } ada_ccb_state; /* Offsets into our private area for storing information */ @@ -117,6 +112,7 @@ struct ada_softc { ada_quirks quirks; int ordered_tag_count; int outstanding_cmds; + int secsperint; struct disk_params params; struct disk *disk; union ccb saved_ccb; @@ -289,8 +285,7 @@ adaclose(struct disk *dp) else ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0); cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, - /*sense_flags*/SF_RETRY_UA, - softc->disk->d_devstat); + /*sense_flags*/0, softc->disk->d_devstat); if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) xpt_print(periph->path, "Synchronize cache failed\n"); @@ -331,19 +326,6 @@ adastrategy(struct bio *bp) cam_periph_lock(periph); -#if 0 - /* - * check it's not too big a transfer for our adapter - */ - scsi_minphys(bp,&sd_switch); -#endif - - /* - * Mask interrupts so that the pack cannot be invalidated until - * after we are in the queue. Otherwise, we might not properly - * clean up one of the buffers. - */ - /* * If the device has been made invalid, error out */ @@ -551,11 +533,6 @@ adaasync(void *callback_arg, u_int32_t c if (cgd->protocol != PROTO_ATA) break; -// if (SID_TYPE(&cgd->inq_data) != T_DIRECT -// && SID_TYPE(&cgd->inq_data) != T_RBC -// && SID_TYPE(&cgd->inq_data) != T_OPTICAL) -// break; - /* * Allocate a peripheral instance for * this device and start the probe @@ -576,18 +553,18 @@ adaasync(void *callback_arg, u_int32_t c case AC_SENT_BDR: case AC_BUS_RESET: { - struct ada_softc *softc; - struct ccb_hdr *ccbh; + struct ada_softc *softc = (struct ada_softc *)periph->softc; - softc = (struct ada_softc *)periph->softc; + cam_periph_async(periph, code, path, arg); + if (softc->state != ADA_STATE_NORMAL) + break; /* - * Don't fail on the expected unit attention - * that will occur. + * Restore device configuration. */ - softc->flags |= ADA_FLAG_RETRY_UA; - LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le) - ccbh->ccb_state |= ADA_CCB_RETRY_UA; - /* FALLTHROUGH*/ + softc->state = ADA_STATE_SET_MULTI; + cam_periph_acquire(periph); + xpt_schedule(periph, 0); + break; } default: cam_periph_async(periph, code, path, arg); @@ -651,14 +628,15 @@ adaregister(struct cam_periph *periph, v if (softc == NULL) { printf("adaregister: Unable to probe new device. " - "Unable to allocate softc\n"); + "Unable to allocate softc\n"); return(CAM_REQ_CMP_ERR); } LIST_INIT(&softc->pending_ccbs); - softc->state = ADA_STATE_NORMAL; bioq_init(&softc->bio_queue); + if (cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) + softc->flags |= ADA_FLAG_CAN_DMA; if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) softc->flags |= ADA_FLAG_CAN_48BIT; if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE) @@ -666,8 +644,8 @@ adaregister(struct cam_periph *periph, v if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ && cgd->ident_data.queue >= 31) softc->flags |= ADA_FLAG_CAN_NCQ; -// if ((cgd->inq_data.flags & SID_CmdQue) != 0) -// softc->flags |= ADA_FLAG_TAGGED_QUEUING; + softc->secsperint = max(1, min(cgd->ident_data.sectors_intr, 16)); + softc->state = ADA_STATE_SET_MULTI; periph->softc = softc; @@ -713,9 +691,9 @@ adaregister(struct cam_periph *periph, v else if (maxio > MAXPHYS) maxio = MAXPHYS; /* for safety */ if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) - maxio = min(maxio, 65535 * 512); + maxio = min(maxio, 65536 * 512); else /* 28bit ATA command limit */ - maxio = min(maxio, 255 * 512); + maxio = min(maxio, 256 * 512); softc->disk->d_maxsize = maxio; softc->disk->d_unit = periph->unit_number; softc->disk->d_flags = 0; @@ -730,8 +708,6 @@ adaregister(struct cam_periph *periph, v /* XXX: these are not actually "firmware" values, so they may be wrong */ softc->disk->d_fwsectors = softc->params.secs_per_track; softc->disk->d_fwheads = softc->params.heads; -// softc->disk->d_devstat->block_size = softc->params.secsize; -// softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE; disk_create(softc->disk, DISK_VERSION); mtx_lock(periph->sim->mtx); @@ -766,8 +742,8 @@ adaregister(struct cam_periph *periph, v * to finish the probe. The reference will be dropped in adadone at * the end of probe. */ -// (void)cam_periph_hold(periph, PRIBIO); -// xpt_schedule(periph, /*priority*/5); + cam_periph_acquire(periph); + xpt_schedule(periph, /*priority*/5); /* * Schedule a periodic event to occasionally send an @@ -784,9 +760,8 @@ adaregister(struct cam_periph *periph, v static void adastart(struct cam_periph *periph, union ccb *start_ccb) { - struct ada_softc *softc; - - softc = (struct ada_softc *)periph->softc; + struct ada_softc *softc = (struct ada_softc *)periph->softc; + struct ccb_ataio *ataio = &start_ccb->ataio; switch (softc->state) { case ADA_STATE_NORMAL: @@ -809,7 +784,6 @@ adastart(struct cam_periph *periph, unio } else if (bp == NULL) { xpt_release_ccb(start_ccb); } else { - struct ccb_ataio *ataio = &start_ccb->ataio; u_int8_t tag_code; bioq_remove(&softc->bio_queue, bp); @@ -817,9 +791,9 @@ adastart(struct cam_periph *periph, unio if ((softc->flags & ADA_FLAG_NEED_OTAG) != 0) { softc->flags &= ~ADA_FLAG_NEED_OTAG; softc->ordered_tag_count++; - tag_code = 0;//MSG_ORDERED_Q_TAG; + tag_code = 0; } else { - tag_code = 0;//MSG_SIMPLE_Q_TAG; + tag_code = 1; } switch (bp->bio_cmd) { case BIO_READ: @@ -838,7 +812,7 @@ adastart(struct cam_periph *periph, unio bp->bio_bcount, ada_default_timeout*1000); - if (softc->flags & ADA_FLAG_CAN_NCQ) { + if ((softc->flags & ADA_FLAG_CAN_NCQ) && tag_code) { if (bp->bio_cmd == BIO_READ) { ata_ncq_cmd(ataio, ATA_READ_FPDMA_QUEUED, lba, count); @@ -848,21 +822,43 @@ adastart(struct cam_periph *periph, unio } } else if ((softc->flags & ADA_FLAG_CAN_48BIT) && (lba + count >= ATA_MAX_28BIT_LBA || - count >= 256)) { - if (bp->bio_cmd == BIO_READ) { - ata_48bit_cmd(ataio, ATA_READ_DMA48, - 0, lba, count); + count > 256)) { + if (softc->flags & ADA_FLAG_CAN_DMA) { + if (bp->bio_cmd == BIO_READ) { + ata_48bit_cmd(ataio, ATA_READ_DMA48, + 0, lba, count); + } else { + ata_48bit_cmd(ataio, ATA_WRITE_DMA48, + 0, lba, count); + } } else { - ata_48bit_cmd(ataio, ATA_WRITE_DMA48, - 0, lba, count); + if (bp->bio_cmd == BIO_READ) { + ata_48bit_cmd(ataio, ATA_READ_MUL48, + 0, lba, count); + } else { + ata_48bit_cmd(ataio, ATA_WRITE_MUL48, + 0, lba, count); + } } } else { - if (bp->bio_cmd == BIO_READ) { - ata_28bit_cmd(ataio, ATA_READ_DMA, - 0, lba, count); + if (count == 256) + count = 0; + if (softc->flags & ADA_FLAG_CAN_DMA) { + if (bp->bio_cmd == BIO_READ) { + ata_28bit_cmd(ataio, ATA_READ_DMA, + 0, lba, count); + } else { + ata_28bit_cmd(ataio, ATA_WRITE_DMA, + 0, lba, count); + } } else { - ata_28bit_cmd(ataio, ATA_WRITE_DMA, - 0, lba, count); + if (bp->bio_cmd == BIO_READ) { + ata_28bit_cmd(ataio, ATA_READ_MUL, + 0, lba, count); + } else { + ata_28bit_cmd(ataio, ATA_WRITE_MUL, + 0, lba, count); + } } } } @@ -872,7 +868,7 @@ adastart(struct cam_periph *periph, unio 1, adadone, CAM_DIR_NONE, - tag_code, + 0, NULL, 0, ada_default_timeout*1000); @@ -893,12 +889,6 @@ adastart(struct cam_periph *periph, unio &start_ccb->ccb_h, periph_links.le); softc->outstanding_cmds++; - /* We expect a unit attention from this device */ - if ((softc->flags & ADA_FLAG_RETRY_UA) != 0) { - start_ccb->ccb_h.ccb_state |= ADA_CCB_RETRY_UA; - softc->flags &= ~ADA_FLAG_RETRY_UA; - } - start_ccb->ccb_h.ccb_bp = bp; bp = bioq_first(&softc->bio_queue); @@ -911,6 +901,21 @@ adastart(struct cam_periph *periph, unio } break; } + case ADA_STATE_SET_MULTI: + { + cam_fill_ataio(ataio, + ada_retry_count, + adadone, + CAM_DIR_NONE, + 0, + NULL, + 0, + ada_default_timeout*1000); + + ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, softc->secsperint); + start_ccb->ccb_h.ccb_state = ADA_CCB_SET_MULTI; + xpt_action(start_ccb); + } } } @@ -931,16 +936,12 @@ adadone(struct cam_periph *periph, union if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { int error; - error = adaerror(done_ccb, CAM_RETRY_SELTO, 0); + error = adaerror(done_ccb, 0, 0); if (error == ERESTART) { - /* - * A retry was scheuled, so - * just return. - */ + /* A retry was scheduled, so just return. */ return; } if (error != 0) { - if (error == ENXIO) { /* * Catastrophic error. Mark our pack as @@ -1002,6 +1003,35 @@ adadone(struct cam_periph *periph, union wakeup(&done_ccb->ccb_h.cbfcnp); return; } + case ADA_CCB_SET_MULTI: + { + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + } else { + int error; + + error = adaerror(done_ccb, 0, 0); + if (error == ERESTART) { + /* A retry was scheduled, so just return. */ + return; + } + } + softc->state = ADA_STATE_NORMAL; + /* + * Since our peripheral may be invalidated by an error + * above or an external event, we must release our CCB + * before releasing the probe lock on the peripheral. + * The peripheral will only go away once the last lock + * is removed, and we need it around for the CCB release + * operation. + */ + xpt_release_ccb(done_ccb); + if (bioq_first(&softc->bio_queue) != NULL) { + /* Have more work to do, so ensure we stay scheduled */ + xpt_schedule(periph, 1); + } + cam_periph_release_locked(periph); + return; + } case ADA_CCB_DUMP: /* No-op. We're polling */ return; @@ -1049,10 +1079,6 @@ adasetgeom(struct cam_periph *periph, st lbasize = (u_int32_t)cgd->ident_data.lba_size_1 | ((u_int32_t)cgd->ident_data.lba_size_2 << 16); - /* does this device need oldstyle CHS addressing */ -// if (!ad_version(cgd->ident_data.version_major) || !lbasize) -// atadev->flags |= ATA_D_USE_CHS; - /* use the 28bit LBA size if valid or bigger than the CHS mapping */ if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize) dp->sectors = lbasize;