From owner-p4-projects@FreeBSD.ORG Sat Aug 8 13:14:45 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 84BFA1065670; Sat, 8 Aug 2009 13:14:45 +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 44CA3106566C for ; Sat, 8 Aug 2009 13:14:45 +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 340648FC1F for ; Sat, 8 Aug 2009 13:14:45 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n78DEjPP021952 for ; Sat, 8 Aug 2009 13:14:45 GMT (envelope-from mav@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n78DEjnt021950 for perforce@freebsd.org; Sat, 8 Aug 2009 13:14:45 GMT (envelope-from mav@freebsd.org) Date: Sat, 8 Aug 2009 13:14:45 GMT Message-Id: <200908081314.n78DEjnt021950@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 167102 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, 08 Aug 2009 13:14:46 -0000 http://perforce.freebsd.org/chv.cgi?CH=167102 Change 167102 by mav@mav_mavbook on 2009/08/08 13:13:58 Add PIO mode support for DMA incapable devices. Affected files ... .. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_da.c#23 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_da.c#23 (text+ko) ==== @@ -63,7 +63,8 @@ #define ATA_MAX_28BIT_LBA 268435455UL typedef enum { - ADA_STATE_NORMAL + ADA_STATE_NORMAL, + ADA_STATE_SET_MULTI } ada_state; typedef enum { @@ -71,6 +72,7 @@ ADA_FLAG_CAN_48BIT = 0x002, ADA_FLAG_CAN_FLUSHCACHE = 0x004, 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, @@ -83,8 +85,7 @@ } 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, @@ -113,6 +114,7 @@ ada_quirks quirks; int ordered_tag_count; int outstanding_cmds; + int secsperint; struct disk_params params; struct disk *disk; union ccb saved_ccb; @@ -565,6 +567,12 @@ softc = (struct ada_softc *)periph->softc; /* + * Restore device configuration. + */ + softc->state = ADA_STATE_SET_MULTI; + (void)cam_periph_hold(periph, PRIBIO); + xpt_schedule(periph, CAM_PRIORITY_DEV); + /* * Don't fail on the expected unit attention * that will occur. */ @@ -640,9 +648,10 @@ } 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) @@ -650,6 +659,8 @@ if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ && cgd->ident_data.queue >= 31) softc->flags |= ADA_FLAG_CAN_NCQ; + softc->secsperint = max(1, min(cgd->ident_data.sectors_intr, 16)); + softc->state = ADA_STATE_SET_MULTI; periph->softc = softc; @@ -695,9 +706,9 @@ 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; @@ -744,8 +755,8 @@ * 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, CAM_PRIORITY_DEV); + (void)cam_periph_hold(periph, PRIBIO); + xpt_schedule(periph, CAM_PRIORITY_DEV); /* * Schedule a periodic event to occasionally send an @@ -762,9 +773,8 @@ 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: @@ -787,7 +797,6 @@ } 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); @@ -826,21 +835,43 @@ } } 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_36bit_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_36bit_cmd(ataio, ATA_READ_DMA, + 0, lba, count); + } else { + ata_36bit_cmd(ataio, ATA_WRITE_DMA, + 0, lba, count); + } } else { - ata_36bit_cmd(ataio, ATA_WRITE_DMA, - 0, lba, count); + if (bp->bio_cmd == BIO_READ) { + ata_36bit_cmd(ataio, ATA_READ_MUL, + 0, lba, count); + } else { + ata_36bit_cmd(ataio, ATA_WRITE_MUL, + 0, lba, count); + } } } } @@ -858,7 +889,7 @@ if (softc->flags & ADA_FLAG_CAN_48BIT) ata_48bit_cmd(ataio, ATA_FLUSHCACHE48, 0, 0, 0); else - ata_48bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0); + ata_36bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0); break; } start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO; @@ -889,6 +920,21 @@ } 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_36bit_cmd(ataio, ATA_SET_MULTI, 0, 0, softc->secsperint); + start_ccb->ccb_h.ccb_state = ADA_CCB_SET_MULTI; + xpt_action(start_ccb); + } } } @@ -909,7 +955,7 @@ 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 @@ -980,6 +1026,34 @@ 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 scheuled, 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); + cam_periph_unhold(periph); + return; + } case ADA_CCB_DUMP: /* No-op. We're polling */ return;