svn commit: r199386 - stable/8/sys/cam/ata
Alexander Motin
mav at FreeBSD.org
Tue Nov 17 14:56:01 UTC 2009
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;
More information about the svn-src-stable
mailing list