Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Apr 2011 09:55:24 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r220563 - head/sys/dev/ata
Message-ID:  <201104120955.p3C9tOAA017241@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Apr 12 09:55:24 2011
New Revision: 220563
URL: http://svn.freebsd.org/changeset/base/220563

Log:
  Implement automatic SCSI sense fetching for ata(4) in ATA_CAM mode.
  While it could be successfully done by CAM error recovery code, I was
  told by several people that it is also a SIM obligation.

Modified:
  head/sys/dev/ata/ata-all.c
  head/sys/dev/ata/ata-all.h

Modified: head/sys/dev/ata/ata-all.c
==============================================================================
--- head/sys/dev/ata/ata-all.c	Tue Apr 12 09:36:38 2011	(r220562)
+++ head/sys/dev/ata/ata-all.c	Tue Apr 12 09:55:24 2011	(r220563)
@@ -1475,6 +1475,72 @@ ata_cam_begin_transaction(device_t dev, 
 	}
 }
 
+static void
+ata_cam_request_sense(device_t dev, struct ata_request *request)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+	union ccb *ccb = request->ccb;
+
+	ch->requestsense = 1;
+
+	bzero(request, sizeof(&request));
+	request->dev = NULL;
+	request->parent = dev;
+	request->unit = ccb->ccb_h.target_id;
+	request->data = (void *)&ccb->csio.sense_data;
+	request->bytecount = ccb->csio.sense_len;
+	request->u.atapi.ccb[0] = ATAPI_REQUEST_SENSE;
+	request->u.atapi.ccb[4] = ccb->csio.sense_len;
+	request->flags |= ATA_R_ATAPI;
+	if (ch->curr[ccb->ccb_h.target_id].atapi == 16)
+		request->flags |= ATA_R_ATAPI16;
+	if (ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA)
+		request->flags |= ATA_R_DMA;
+	request->flags |= ATA_R_READ;
+	request->transfersize = min(request->bytecount,
+	    ch->curr[ccb->ccb_h.target_id].bytecount);
+	request->retries = 0;
+	request->timeout = (ccb->ccb_h.timeout + 999) / 1000;
+	callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED);
+	request->ccb = ccb;
+
+	ch->running = request;
+	ch->state = ATA_ACTIVE;
+	if (ch->hw.begin_transaction(request) == ATA_OP_FINISHED) {
+		ch->running = NULL;
+		ch->state = ATA_IDLE;
+		ata_cam_end_transaction(dev, request);
+		return;
+	}
+}
+
+static void
+ata_cam_process_sense(device_t dev, struct ata_request *request)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+	union ccb *ccb = request->ccb;
+	int fatalerr = 0;
+
+	ch->requestsense = 0;
+
+	if (request->flags & ATA_R_TIMEOUT)
+		fatalerr = 1;
+	if ((request->flags & ATA_R_TIMEOUT) == 0 &&
+	    (request->status & ATA_S_ERROR) == 0 &&
+	    request->result == 0) {
+		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+	} else {
+		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+		ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
+	}
+
+	ata_free_request(request);
+	xpt_done(ccb);
+	/* Do error recovery if needed. */
+	if (fatalerr)
+		ata_reinit(dev);
+}
+
 void
 ata_cam_end_transaction(device_t dev, struct ata_request *request)
 {
@@ -1482,6 +1548,11 @@ ata_cam_end_transaction(device_t dev, st
 	union ccb *ccb = request->ccb;
 	int fatalerr = 0;
 
+	if (ch->requestsense) {
+		ata_cam_process_sense(dev, request);
+		return;
+	}
+
 	ccb->ccb_h.status &= ~CAM_STATUS_MASK;
 	if (request->flags & ATA_R_TIMEOUT) {
 		xpt_freeze_simq(ch->sim, 1);
@@ -1531,8 +1602,13 @@ ata_cam_end_transaction(device_t dev, st
 			    ccb->csio.dxfer_len - request->donecount;
 		}
 	}
-	ata_free_request(request);
-	xpt_done(ccb);
+	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR &&
+	    (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)
+		ata_cam_request_sense(dev, request);
+	else {
+		ata_free_request(request);
+		xpt_done(ccb);
+	}
 	/* Do error recovery if needed. */
 	if (fatalerr)
 		ata_reinit(dev);

Modified: head/sys/dev/ata/ata-all.h
==============================================================================
--- head/sys/dev/ata/ata-all.h	Tue Apr 12 09:36:38 2011	(r220562)
+++ head/sys/dev/ata/ata-all.h	Tue Apr 12 09:55:24 2011	(r220563)
@@ -585,8 +585,9 @@ struct ata_channel {
 #ifdef ATA_CAM
 	struct cam_sim		*sim;
 	struct cam_path		*path;
-	struct ata_cam_device	user[16];       /* User-specified settings */                             
-	struct ata_cam_device	curr[16];       /* Current settings */                                    
+	struct ata_cam_device	user[16];       /* User-specified settings */
+	struct ata_cam_device	curr[16];       /* Current settings */
+	int			requestsense;	/* CCB waiting for SENSE. */
 #endif
 	struct callout		poll_callout;	/* Periodic status poll. */
 };



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104120955.p3C9tOAA017241>