diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index 342bed897ec3..f2122b7fe1b2 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -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;
     }
 
diff --git a/sys/dev/ciss/cissreg.h b/sys/dev/ciss/cissreg.h
index 2e5e71ec5328..c7844e90a1bd 100644
--- a/sys/dev/ciss/cissreg.h
+++ b/sys/dev/ciss/cissreg.h
@@ -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;
diff --git a/sys/dev/ciss/cissvar.h b/sys/dev/ciss/cissvar.h
index 5baa136c395a..4c102e04cc85 100644
--- a/sys/dev/ciss/cissvar.h
+++ b/sys/dev/ciss/cissvar.h
@@ -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 */
 };