Properly get the drive geometry from the controller. This should

fix booting off of volumes > 255GB.
This commit is contained in:
Paul Saab 2003-02-05 08:43:46 +00:00
parent e010b6bc46
commit 440baa08c3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110366
3 changed files with 108 additions and 10 deletions

View File

@ -1011,6 +1011,67 @@ ciss_init_logical(struct ciss_softc *sc)
return(error);
}
static int
ciss_inquiry_logical(struct ciss_softc *sc, struct ciss_ldrive *ld)
{
struct ciss_request *cr;
struct ciss_command *cc;
struct scsi_inquiry *inq;
int error;
int command_status;
int lun;
cr = NULL;
lun = ld->cl_address.logical.lun;
bzero(&ld->cl_geometry, sizeof(ld->cl_geometry));
if ((error = ciss_get_request(sc, &cr)) != 0)
goto out;
cc = CISS_FIND_COMMAND(cr);
cr->cr_data = &ld->cl_geometry;
cr->cr_length = sizeof(ld->cl_geometry);
cr->cr_flags = CISS_REQ_DATAIN;
cc->header.address.logical.mode = CISS_HDR_ADDRESS_MODE_LOGICAL;
cc->header.address.logical.lun = lun;
cc->cdb.cdb_length = 6;
cc->cdb.type = CISS_CDB_TYPE_COMMAND;
cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE;
cc->cdb.direction = CISS_CDB_DIRECTION_READ;
cc->cdb.timeout = 30;
inq = (struct scsi_inquiry *)&(cc->cdb.cdb[0]);
inq->opcode = INQUIRY;
inq->byte2 = SI_EVPD;
inq->page_code = CISS_VPD_LOGICAL_DRIVE_GEOMETRY;
inq->length = sizeof(ld->cl_geometry);
if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) {
ciss_printf(sc, "error getting geometry (%d)\n", error);
goto out;
}
ciss_report_request(cr, &command_status, NULL);
switch(command_status) {
case CISS_CMD_STATUS_SUCCESS:
case CISS_CMD_STATUS_DATA_UNDERRUN:
break;
case CISS_CMD_STATUS_DATA_OVERRUN:
ciss_printf(sc, "WARNING: Data overrun\n");
break;
default:
ciss_printf(sc, "Error detecting logical drive geometry (%s)\n",
ciss_name_command_status(command_status));
break;
}
out:
if (cr != NULL)
ciss_release_request(cr);
return(error);
}
/************************************************************************
* Identify a logical drive, initialise state related to it.
*/
@ -1070,6 +1131,12 @@ ciss_identify_logical(struct ciss_softc *sc, struct ciss_ldrive *ld)
if ((error = ciss_get_ldrive_status(sc, ld)) != 0)
goto out;
/*
* Get the logical drive geometry.
*/
if ((error = ciss_inquiry_logical(sc, ld)) != 0)
goto out;
/*
* Print the drive's basic characteristics.
*/
@ -2077,11 +2144,19 @@ ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
static void
ciss_cam_action(struct cam_sim *sim, union ccb *ccb)
{
struct ciss_softc *sc;
struct ccb_scsiio *csio;
int target;
sc = cam_sim_softc(sim);
csio = (struct ccb_scsiio *)&ccb->csio;
target = csio->ccb_h.target_id;
switch (ccb->ccb_h.func_code) {
/* perform SCSI I/O */
case XPT_SCSI_IO:
if (!ciss_cam_action_io(sim, (struct ccb_scsiio *)&ccb->csio))
if (!ciss_cam_action_io(sim, csio))
return;
break;
@ -2089,20 +2164,27 @@ ciss_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_CALC_GEOMETRY:
{
struct ccb_calc_geometry *ccg = &ccb->ccg;
u_int32_t secs_per_cylinder;
struct ciss_ldrive *ld = &sc->ciss_logical[target];
debug(1, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
/*
* This is the default geometry; hopefully we will have
* successfully talked to the 'disk' and obtained its private
* settings.
* Use the cached geometry settings unless the fault tolerance
* is invalid.
*/
ccg->heads = 255;
ccg->secs_per_track = 32;
secs_per_cylinder = ccg->heads * ccg->secs_per_track;
ccg->cylinders = ccg->volume_size / secs_per_cylinder;
ccb->ccb_h.status = CAM_REQ_CMP;
if (ld->cl_geometry.fault_tolerance == 0xFF) {
u_int32_t secs_per_cylinder;
ccg->heads = 255;
ccg->secs_per_track = 32;
secs_per_cylinder = ccg->heads * ccg->secs_per_track;
ccg->cylinders = ccg->volume_size / secs_per_cylinder;
} else {
ccg->heads = ld->cl_geometry.heads;
ccg->secs_per_track = ld->cl_geometry.sectors;
ccg->cylinders = ntohs(ld->cl_geometry.cylinders);
}
ccb->ccb_h.status = CAM_REQ_CMP;
break;
}

View File

@ -169,6 +169,21 @@ struct ciss_lun_report
union ciss_device_address lun[0];
} __packed;
#define CISS_VPD_LOGICAL_DRIVE_GEOMETRY 0xc1
struct ciss_ldrive_geometry
{
u_int8_t periph_qualifier:3;
u_int8_t periph_devtype:5;
u_int8_t page_code;
u_int8_t res1;
u_int8_t page_length;
u_int16_t cylinders; /* big-endian */
u_int8_t heads;
u_int8_t sectors;
u_int8_t fault_tolerance;
u_int8_t res2[3];
} __attribute__ ((packed));
struct ciss_report_cdb
{
u_int8_t opcode;

View File

@ -158,6 +158,7 @@ struct ciss_ldrive
struct ciss_bmic_id_ldrive *cl_ldrive;
struct ciss_bmic_id_lstatus *cl_lstatus;
struct ciss_ldrive_geometry cl_geometry;
char cl_name[16]; /* device name */
};