Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Apr 2011 16:20:54 +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: r220602 - in head/sys: cam cam/ata dev/ahci dev/mvs dev/siis sys
Message-ID:  <201104131620.p3DGKsZX001977@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Apr 13 16:20:54 2011
New Revision: 220602
URL: http://svn.freebsd.org/changeset/base/220602

Log:
  Improve SATA Asynchronous Notification feature support in CAM:
   - make SATA SIMs announce capabilities to handle SDB with Notification bit;
   - make PMP driver honor this SIMs capability;
   - make SATA XPT to negotiate and enable this feature for ATAPI devices.
  
  This feature allows supporting SATA ATAPI devices to inform system about
  some events happened, that may require attention. In my case this allows
  LG GH22LS50 SATA DVR-RW drive to report tray open/close events. Events
  reported to CAM in form of AC_SCSI_AEN async. Further they could be used
  as a hints for checking device status and reporting media change to upper
  layers, for example, via spoiling mechanism of GEOM.

Modified:
  head/sys/cam/ata/ata_pmp.c
  head/sys/cam/ata/ata_xpt.c
  head/sys/cam/cam_ccb.h
  head/sys/dev/ahci/ahci.c
  head/sys/dev/mvs/mvs.c
  head/sys/dev/siis/siis.c
  head/sys/sys/ata.h

Modified: head/sys/cam/ata/ata_pmp.c
==============================================================================
--- head/sys/cam/ata/ata_pmp.c	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/cam/ata/ata_pmp.c	Wed Apr 13 16:20:54 2011	(r220602)
@@ -533,7 +533,8 @@ pmpstart(struct cam_periph *periph, unio
 		      /*data_ptr*/NULL,
 		      /*dxfer_len*/0,
 		      pmp_default_timeout * 1000);
-		ata_pm_write_cmd(ataio, 0x60, 15, 0xf);
+		ata_pm_write_cmd(ataio, 0x60, 15, 0x07 |
+		    ((softc->caps & CTS_SATA_CAPS_H_AN) ? 0x08 : 0));
 		break;
 	default:
 		break;
@@ -672,7 +673,9 @@ pmpdone(struct cam_periph *periph, union
 				cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
 				cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION;
 				cts.xport_specific.sata.caps = softc->caps &
-				    (CTS_SATA_CAPS_H_PMREQ | CTS_SATA_CAPS_H_DMAAA);
+				    (CTS_SATA_CAPS_H_PMREQ |
+				     CTS_SATA_CAPS_H_DMAAA |
+				     CTS_SATA_CAPS_H_AN);
 				cts.xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
 				xpt_action((union ccb *)&cts);
 				xpt_free_path(dpath);

Modified: head/sys/cam/ata/ata_xpt.c
==============================================================================
--- head/sys/cam/ata/ata_xpt.c	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/cam/ata/ata_xpt.c	Wed Apr 13 16:20:54 2011	(r220602)
@@ -87,6 +87,7 @@ typedef enum {
 	PROBE_SETPM,
 	PROBE_SETAPST,
 	PROBE_SETDMAAA,
+	PROBE_SETAN,
 	PROBE_SET_MULTI,
 	PROBE_INQUIRY,
 	PROBE_FULL_INQUIRY,
@@ -103,6 +104,7 @@ static char *probe_action_text[] = {
 	"PROBE_SETPM",
 	"PROBE_SETAPST",
 	"PROBE_SETDMAAA",
+	"PROBE_SETAN",
 	"PROBE_SET_MULTI",
 	"PROBE_INQUIRY",
 	"PROBE_FULL_INQUIRY",
@@ -436,6 +438,19 @@ negotiate:
 		    (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90,
 		    0, 0x02);
 		break;
+	case PROBE_SETAN:
+		cam_fill_ataio(ataio,
+		    1,
+		    probedone,
+		    CAM_DIR_NONE,
+		    0,
+		    NULL,
+		    0,
+		    30*1000);
+		ata_28bit_cmd(ataio, ATA_SETFEATURES,
+		    (softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90,
+		    0, 0x05);
+		break;
 	case PROBE_SET_MULTI:
 	{
 		u_int sectors, bytecount;
@@ -1027,6 +1042,16 @@ noerror:
 		}
 		/* FALLTHROUGH */
 	case PROBE_SETDMAAA:
+		if ((ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) &&
+		    (!(softc->caps & CTS_SATA_CAPS_H_AN)) !=
+		    (!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) {
+			PROBE_SET_ACTION(softc, PROBE_SETAN);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		}
+		/* FALLTHROUGH */
+	case PROBE_SETAN:
 notsata:
 		if (path->device->protocol == PROTO_ATA) {
 			PROBE_SET_ACTION(softc, PROBE_SET_MULTI);

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/cam/cam_ccb.h	Wed Apr 13 16:20:54 2011	(r220602)
@@ -889,6 +889,7 @@ struct ccb_trans_settings_sata {
 #define	CTS_SATA_CAPS_H_PMREQ		0x00000001
 #define	CTS_SATA_CAPS_H_APST		0x00000002
 #define	CTS_SATA_CAPS_H_DMAAA		0x00000010 /* Auto-activation */
+#define	CTS_SATA_CAPS_H_AN		0x00000020 /* Async. notification */
 #define	CTS_SATA_CAPS_D			0xffff0000
 #define	CTS_SATA_CAPS_D_PMREQ		0x00010000
 #define	CTS_SATA_CAPS_D_APST		0x00020000

Modified: head/sys/dev/ahci/ahci.c
==============================================================================
--- head/sys/dev/ahci/ahci.c	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/dev/ahci/ahci.c	Wed Apr 13 16:20:54 2011	(r220602)
@@ -914,7 +914,8 @@ ahci_ch_attach(device_t dev)
 			    CTS_SATA_CAPS_H_APST |
 			    CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
 		}
-		ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA;
+		ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA |
+		    CTS_SATA_CAPS_H_AN;
 	}
 	rid = ch->unit;
 	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -2721,6 +2722,7 @@ ahciaction(struct cam_sim *sim, union cc
 			if ((ch->caps & AHCI_CAP_SNCQ) &&
 			    (ch->quirks & AHCI_Q_NOAA) == 0)
 				cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA;
+			cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
 			cts->xport_specific.sata.caps &=
 			    ch->user[ccb->ccb_h.target_id].caps;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;

Modified: head/sys/dev/mvs/mvs.c
==============================================================================
--- head/sys/dev/mvs/mvs.c	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/dev/mvs/mvs.c	Wed Apr 13 16:20:54 2011	(r220602)
@@ -138,6 +138,7 @@ mvs_ch_attach(device_t dev)
 			    CTS_SATA_CAPS_H_APST |
 			    CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
 		}
+		ch->user[i].caps |= CTS_SATA_CAPS_H_AN;
 	}
 	rid = ch->unit;
 	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -861,6 +862,8 @@ mvs_legacy_intr(device_t dev)
 			if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
 			    device_printf(dev, "timeout waiting for read DRQ\n");
 			    et = MVS_ERR_TIMEOUT;
+			    xpt_freeze_simq(ch->sim, 1);
+			    ch->toslots |= (1 << slot->slot);
 			    goto end_finished;
 			}
 			ATA_INSW_STRM(ch->r_mem, ATA_DATA,
@@ -880,6 +883,8 @@ mvs_legacy_intr(device_t dev)
 				    device_printf(dev,
 					"timeout waiting for write DRQ\n");
 				    et = MVS_ERR_TIMEOUT;
+				    xpt_freeze_simq(ch->sim, 1);
+				    ch->toslots |= (1 << slot->slot);
 				    goto end_finished;
 				}
 				ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
@@ -1325,6 +1330,8 @@ mvs_legacy_execute_transaction(struct mv
 			if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
 				device_printf(dev,
 				    "timeout waiting for write DRQ\n");
+				xpt_freeze_simq(ch->sim, 1);
+				ch->toslots |= (1 << slot->slot);
 				mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
 				return;
 			}
@@ -1351,6 +1358,8 @@ mvs_legacy_execute_transaction(struct mv
 		/* Wait for ready to write ATAPI command block */
 		if (mvs_wait(dev, 0, ATA_S_BUSY, 1000) < 0) {
 			device_printf(dev, "timeout waiting for ATAPI !BUSY\n");
+			xpt_freeze_simq(ch->sim, 1);
+			ch->toslots |= (1 << slot->slot);
 			mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
 			return;
 		}
@@ -1367,6 +1376,8 @@ mvs_legacy_execute_transaction(struct mv
 		if (timeout <= 0) {
 			device_printf(dev,
 			    "timeout waiting for ATAPI command ready\n");
+			xpt_freeze_simq(ch->sim, 1);
+			ch->toslots |= (1 << slot->slot);
 			mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
 			return;
 		}
@@ -2205,6 +2216,7 @@ mvsaction(struct cam_sim *sim, union ccb
 			cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
 //			if (ch->pm_level)
 //				cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
+			cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
 			cts->xport_specific.sata.caps &=
 			    ch->user[ccb->ccb_h.target_id].caps;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
@@ -2212,6 +2224,9 @@ mvsaction(struct cam_sim *sim, union ccb
 			cts->xport_specific.sata.revision = d->revision;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
 			cts->xport_specific.sata.caps = d->caps;
+			if (cts->type == CTS_TYPE_CURRENT_SETTINGS/* &&
+			    (ch->quirks & MVS_Q_GENIIE) == 0*/)
+				cts->xport_specific.sata.caps &= ~CTS_SATA_CAPS_H_AN;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
 		}
 		cts->xport_specific.sata.mode = d->mode;

Modified: head/sys/dev/siis/siis.c
==============================================================================
--- head/sys/dev/siis/siis.c	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/dev/siis/siis.c	Wed Apr 13 16:20:54 2011	(r220602)
@@ -474,6 +474,7 @@ siis_ch_attach(device_t dev)
 		ch->curr[i] = ch->user[i];
 		if (ch->pm_level)
 			ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ;
+		ch->user[i].caps |= CTS_SATA_CAPS_H_AN;
 	}
 	mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF);
 	rid = ch->unit;
@@ -1869,6 +1870,7 @@ siisaction(struct cam_sim *sim, union cc
 			cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
 			if (ch->pm_level)
 				cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
+			cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
 			cts->xport_specific.sata.caps &=
 			    ch->user[ccb->ccb_h.target_id].caps;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
@@ -1876,6 +1878,9 @@ siisaction(struct cam_sim *sim, union cc
 			cts->xport_specific.sata.revision = d->revision;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
 			cts->xport_specific.sata.caps = d->caps;
+			if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
+			    (ch->quirks & SIIS_Q_SNTF) == 0)
+				cts->xport_specific.sata.caps &= ~CTS_SATA_CAPS_H_AN;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
 		}
 		cts->xport_specific.sata.mode = d->mode;

Modified: head/sys/sys/ata.h
==============================================================================
--- head/sys/sys/ata.h	Wed Apr 13 15:17:23 2011	(r220601)
+++ head/sys/sys/ata.h	Wed Apr 13 16:20:54 2011	(r220602)
@@ -135,6 +135,7 @@ struct ata_params {
 #define ATA_SUPPORT_AUTOACTIVATE        0x0004
 #define ATA_SUPPORT_IFPWRMNGT           0x0008
 #define ATA_SUPPORT_INORDERDATA         0x0010
+#define ATA_SUPPORT_ASYNCNOTIF          0x0020
 #define ATA_SUPPORT_SOFTSETPRESERVE     0x0040
 /*79*/  u_int16_t       sataenabled;
 #define ATA_ENABLED_DAPST               0x0080



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