svn commit: r198897 - in head: sbin/camcontrol sys/cam/ata sys/sys

Alexander Motin mav at FreeBSD.org
Wed Nov 4 15:24:33 UTC 2009


Author: mav
Date: Wed Nov  4 15:24:32 2009
New Revision: 198897
URL: http://svn.freebsd.org/changeset/base/198897

Log:
  MFp4:
  - Add support for sector size > 512 bytes and physical sector of several
  logical sectors, introduced by ATA-7 specification.
  - Remove some obsoleted code.

Modified:
  head/sbin/camcontrol/camcontrol.c
  head/sys/cam/ata/ata_all.c
  head/sys/cam/ata/ata_all.h
  head/sys/cam/ata/ata_da.c
  head/sys/cam/ata/ata_xpt.c
  head/sys/sys/ata.h

Modified: head/sbin/camcontrol/camcontrol.c
==============================================================================
--- head/sbin/camcontrol/camcontrol.c	Wed Nov  4 15:10:46 2009	(r198896)
+++ head/sbin/camcontrol/camcontrol.c	Wed Nov  4 15:24:32 2009	(r198897)
@@ -1061,6 +1061,10 @@ atacapprint(struct ata_params *parm)
 	printf("cylinders             %d\n", parm->cylinders);
 	printf("heads                 %d\n", parm->heads);
 	printf("sectors/track         %d\n", parm->sectors);
+	printf("sector size           logical %u, physical %lu, offset %lu\n",
+	    ata_logical_sector_size(parm),
+	    (unsigned long)ata_physical_sector_size(parm),
+	    (unsigned long)ata_logical_sector_offset(parm));
 
 	if (parm->config == ATA_PROTO_CFA ||
 	    (parm->support.command2 & ATA_SUPPORT_CFA))

Modified: head/sys/cam/ata/ata_all.c
==============================================================================
--- head/sys/cam/ata/ata_all.c	Wed Nov  4 15:10:46 2009	(r198896)
+++ head/sys/cam/ata/ata_all.c	Wed Nov  4 15:24:32 2009	(r198897)
@@ -271,6 +271,38 @@ ata_print_ident(struct ata_params *ident
 	printf(" device\n");
 }
 
+uint32_t
+ata_logical_sector_size(struct ata_params *ident_data)
+{
+	if ((ident_data->pss & 0xc000) == 0x4000 &&
+	    (ident_data->pss & ATA_PSS_LSSABOVE512)) {
+		return ((u_int32_t)ident_data->lss_1 |
+		    ((u_int32_t)ident_data->lss_2 << 16));
+	}
+	return (512);
+}
+
+uint64_t
+ata_physical_sector_size(struct ata_params *ident_data)
+{
+	if ((ident_data->pss & 0xc000) == 0x4000 &&
+	    (ident_data->pss & ATA_PSS_MULTLS)) {
+		return ((uint64_t)ata_logical_sector_size(ident_data) *
+		    (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+	}
+	return (512);
+}
+
+uint64_t
+ata_logical_sector_offset(struct ata_params *ident_data)
+{
+	if ((ident_data->lsalign & 0xc000) == 0x4000) {
+		return ((uint64_t)ata_logical_sector_size(ident_data) *
+		    (ident_data->lsalign & 0x3fff));
+	}
+	return (0);
+}
+
 void
 ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
     uint32_t lba, uint8_t sector_count)

Modified: head/sys/cam/ata/ata_all.h
==============================================================================
--- head/sys/cam/ata/ata_all.h	Wed Nov  4 15:10:46 2009	(r198896)
+++ head/sys/cam/ata/ata_all.h	Wed Nov  4 15:24:32 2009	(r198897)
@@ -91,6 +91,10 @@ int	ata_res_sbuf(struct ccb_ataio *ataio
 
 void	ata_print_ident(struct ata_params *ident_data);
 
+uint32_t	ata_logical_sector_size(struct ata_params *ident_data);
+uint64_t	ata_physical_sector_size(struct ata_params *ident_data);
+uint64_t	ata_logical_sector_offset(struct ata_params *ident_data);
+
 void	ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
     uint32_t lba, uint8_t sector_count);
 void	ata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features,

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c	Wed Nov  4 15:10:46 2009	(r198896)
+++ head/sys/cam/ata/ata_da.c	Wed Nov  4 15:24:32 2009	(r198897)
@@ -95,16 +95,14 @@ typedef enum {
 
 struct disk_params {
 	u_int8_t  heads;
-	u_int32_t cylinders;
 	u_int8_t  secs_per_track;
-	u_int32_t secsize;	/* Number of bytes/sector */
-	u_int64_t sectors;	/* total number sectors */
+	u_int32_t cylinders;
+	u_int32_t secsize;	/* Number of bytes/logical sector */
+	u_int64_t sectors;	/* Total number sectors */
 };
 
 struct ada_softc {
 	struct	 bio_queue_head bio_queue;
-	SLIST_ENTRY(ada_softc) links;
-	LIST_HEAD(, ccb_hdr) pending_ccbs;
 	ada_state state;
 	ada_flags flags;	
 	ada_quirks quirks;
@@ -142,7 +140,7 @@ static	void		adadone(struct cam_periph *
 			       union ccb *done_ccb);
 static  int		adaerror(union ccb *ccb, u_int32_t cam_flags,
 				u_int32_t sense_flags);
-static void		adasetgeom(struct cam_periph *periph,
+static void		adagetparams(struct cam_periph *periph,
 				struct ccb_getdev *cgd);
 static timeout_t	adasendorderedtag;
 static void		adashutdown(void *arg, int howto);
@@ -613,7 +611,6 @@ adaregister(struct cam_periph *periph, v
 		return(CAM_REQ_CMP_ERR);
 	}
 
-	LIST_INIT(&softc->pending_ccbs);
 	bioq_init(&softc->bio_queue);
 
 	if (cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA)
@@ -658,6 +655,7 @@ adaregister(struct cam_periph *periph, v
 	 * Register this media as a disk
 	 */
 	mtx_unlock(periph->sim->mtx);
+	adagetparams(periph, cgd);
 	softc->disk = disk_alloc();
 	softc->disk->d_open = adaopen;
 	softc->disk->d_close = adaclose;
@@ -671,9 +669,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, 65536 * 512);
+		maxio = min(maxio, 65536 * softc->params.secsize);
 	else					/* 28bit ATA command limit */
-		maxio = min(maxio, 256 * 512);
+		maxio = min(maxio, 256 * softc->params.secsize);
 	softc->disk->d_maxsize = maxio;
 	softc->disk->d_unit = periph->unit_number;
 	softc->disk->d_flags = 0;
@@ -682,9 +680,12 @@ adaregister(struct cam_periph *periph, v
 	strlcpy(softc->disk->d_ident, cgd->serial_num,
 	    MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1));
 
-	adasetgeom(periph, cgd);
 	softc->disk->d_sectorsize = softc->params.secsize;
-	softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
+	softc->disk->d_mediasize = (off_t)softc->params.sectors *
+	    softc->params.secsize;
+	softc->disk->d_stripesize = ata_physical_sector_size(&cgd->ident_data);
+	softc->disk->d_stripeoffset = softc->disk->d_stripesize -
+	    ata_logical_sector_offset(&cgd->ident_data);
 	/* 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;
@@ -852,19 +853,10 @@ adastart(struct cam_periph *periph, unio
 				break;
 			}
 			start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO;
-
-			/*
-			 * Block out any asyncronous callbacks
-			 * while we touch the pending ccb list.
-			 */
-			LIST_INSERT_HEAD(&softc->pending_ccbs,
-					 &start_ccb->ccb_h, periph_links.le);
-			softc->outstanding_cmds++;
-
 			start_ccb->ccb_h.ccb_bp = bp;
-			bp = bioq_first(&softc->bio_queue);
-
+			softc->outstanding_cmds++;
 			xpt_action(start_ccb);
+			bp = bioq_first(&softc->bio_queue);
 		}
 		
 		if (bp != NULL) {
@@ -941,12 +933,6 @@ adadone(struct cam_periph *periph, union
 			if (ataio->resid > 0)
 				bp->bio_flags |= BIO_ERROR;
 		}
-
-		/*
-		 * Block out any asyncronous callbacks
-		 * while we touch the pending ccb list.
-		 */
-		LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
 		softc->outstanding_cmds--;
 		if (softc->outstanding_cmds == 0)
 			softc->flags |= ADA_FLAG_WENT_IDLE;
@@ -983,14 +969,14 @@ adaerror(union ccb *ccb, u_int32_t cam_f
 }
 
 static void
-adasetgeom(struct cam_periph *periph, struct ccb_getdev *cgd)
+adagetparams(struct cam_periph *periph, struct ccb_getdev *cgd)
 {
 	struct ada_softc *softc = (struct ada_softc *)periph->softc;
 	struct disk_params *dp = &softc->params;
 	u_int64_t lbasize48;
 	u_int32_t lbasize;
 
-	dp->secsize = 512;
+	dp->secsize = ata_logical_sector_size(&cgd->ident_data);
 	if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) &&
 		cgd->ident_data.current_heads && cgd->ident_data.current_sectors) {
 		dp->heads = cgd->ident_data.current_heads;

Modified: head/sys/cam/ata/ata_xpt.c
==============================================================================
--- head/sys/cam/ata/ata_xpt.c	Wed Nov  4 15:10:46 2009	(r198896)
+++ head/sys/cam/ata/ata_xpt.c	Wed Nov  4 15:24:32 2009	(r198897)
@@ -363,10 +363,12 @@ probestart(struct cam_periph *periph, un
 		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
 		cts.type = CTS_TYPE_CURRENT_SETTINGS;
 		if (path->device->transport == XPORT_ATA) {
-			cts.xport_specific.ata.bytecount = sectors * 512;
+			cts.xport_specific.ata.bytecount = sectors *
+			    ata_logical_sector_size(ident_buf);
 			cts.xport_specific.ata.valid = CTS_ATA_VALID_BYTECOUNT;
 		} else {
-			cts.xport_specific.sata.bytecount = sectors * 512;
+			cts.xport_specific.sata.bytecount = sectors *
+			    ata_logical_sector_size(ident_buf);
 			cts.xport_specific.sata.valid = CTS_SATA_VALID_BYTECOUNT;
 		}
 		xpt_action((union ccb *)&cts);

Modified: head/sys/sys/ata.h
==============================================================================
--- head/sys/sys/ata.h	Wed Nov  4 15:10:46 2009	(r198896)
+++ head/sys/sys/ata.h	Wed Nov  4 15:24:32 2009	(r198897)
@@ -234,7 +234,7 @@ struct ata_params {
 /*176*/ u_int8_t        media_serial[60];
 /*206*/ u_int16_t       sct;
 	u_int16_t       reserved206[2];
-/*209*/ u_int16_t       lbalign;
+/*209*/ u_int16_t       lsalign;
 /*210*/ u_int16_t       wrv_sectors_m3_1;
 	u_int16_t       wrv_sectors_m3_2;
 /*212*/ u_int16_t       wrv_sectors_m2_1;


More information about the svn-src-all mailing list