PERFORCE change 167102 for review
Alexander Motin
mav at FreeBSD.org
Sat Aug 8 13:14:46 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167102
Change 167102 by mav at 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;
More information about the p4-projects
mailing list