MFp4:
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.
This commit is contained in:
parent
56d7cd7cf1
commit
46f118fe3f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=198328
@ -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 code,
|
||||
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 code,
|
||||
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, void *arg)
|
||||
|
||||
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, void *arg)
|
||||
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, void *arg)
|
||||
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, void *arg)
|
||||
/* 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, void *arg)
|
||||
* 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, void *arg)
|
||||
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, union ccb *start_ccb)
|
||||
} 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, union ccb *start_ccb)
|
||||
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, union ccb *start_ccb)
|
||||
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, union ccb *start_ccb)
|
||||
}
|
||||
} 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, union ccb *start_ccb)
|
||||
1,
|
||||
adadone,
|
||||
CAM_DIR_NONE,
|
||||
tag_code,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
ada_default_timeout*1000);
|
||||
@ -893,12 +889,6 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
&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, union ccb *start_ccb)
|
||||
}
|
||||
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 ccb *done_ccb)
|
||||
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 ccb *done_ccb)
|
||||
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, struct ccb_getdev *cgd)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user