PERFORCE change 163734 for review

Alexander Motin mav at FreeBSD.org
Sun Jun 7 20:30:05 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=163734

Change 163734 by mav at mav_mavbook on 2009/06/07 20:29:25

	Remove all device probe functionality from AHCI driver and move
	it ot the SATA XPT. Now AHCI driver only cares of SATA PHY and
	command queue management. All stuff about Soft-Resetting devices
	and checking their signatures is now handled by SATA XPT.
	PM support also going to be implemented on SATA XPT layer.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#7 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#7 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#13 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#20 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#90 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#17 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#7 (text+ko) ====

@@ -133,4 +133,11 @@
 	ataio->cmd.features_exp = sector_count >> 8;
 }
 
+void	ata_reset_cmd(struct ccb_ataio *ataio, int reset)
+{
+	bzero(&ataio->cmd, sizeof(ataio->cmd));
+	ataio->cmd.flags = CAM_ATAIO_CONTROL;
+	ataio->cmd.control = reset ? 0x04 : 0;
+}
+
 #endif /* _KERNEL */

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#7 (text+ko) ====

@@ -85,5 +85,6 @@
     uint64_t lba, uint16_t sector_count);
 void	ata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd,
     uint64_t lba, uint16_t sector_count);
+void	ata_reset_cmd(struct ccb_ataio *ataio, int reset);
 
 #endif

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#13 (text+ko) ====

@@ -91,6 +91,8 @@
 PERIPHDRIVER_DECLARE(probe, probe_driver);
 
 typedef enum {
+	PROBE_RESET,
+	PROBE_UNRESET,
 	PROBE_IDENTIFY,
 	PROBE_INQUIRY,
 	PROBE_FULL_INQUIRY,
@@ -98,6 +100,8 @@
 } probe_action;
 
 static char *probe_action_text[] = {
+	"PROBE_RESET",
+	"PROBE_UNRESET",
 	"PROBE_IDENTIFY",
 	"PROBE_INQUIRY",
 	"PROBE_FULL_INQUIRY",
@@ -160,7 +164,7 @@
 static struct cam_ed *
 		 ata_alloc_device(struct cam_eb *bus, struct cam_et *target,
 				   lun_id_t lun_id);
-static void	 ata_devise_transport(struct cam_path *path);
+static void	 ata_device_transport(struct cam_path *path);
 static void	 scsi_set_transfer_settings(struct ccb_trans_settings *cts,
 					    struct cam_ed *device,
 					    int async_update);
@@ -277,8 +281,8 @@
 	 * delay before attempting to probe the device.
 	 * For HBAs that don't do bus resets, this won't make a difference.
 	 */
-	cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
-				      scsi_delay);
+//	cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
+//				      scsi_delay);
 	probeschedule(periph);
 	return(CAM_REQ_CMP);
 }
@@ -297,7 +301,10 @@
 	cpi.ccb_h.func_code = XPT_PATH_INQ;
 	xpt_action((union ccb *)&cpi);
 
-	PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
+	if (periph->path->device->flags & CAM_DEV_UNCONFIGURED)
+		PROBE_SET_ACTION(softc, PROBE_RESET);
+	else
+		PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
 
 	if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE)
 		softc->flags |= PROBE_NO_ANNOUNCE;
@@ -322,6 +329,18 @@
 	csio = &start_ccb->csio;
 
 	switch (softc->action) {
+	case PROBE_RESET:
+	case PROBE_UNRESET:
+		cam_fill_ataio(ataio,
+		      4,
+		      probedone,
+		      /*flags*/CAM_DIR_NONE,
+		      MSG_SIMPLE_Q_TAG,
+		      /*data_ptr*/NULL,
+		      /*dxfer_len*/0,
+		      30 * 1000);
+		ata_reset_cmd(ataio, softc->action == PROBE_RESET ? 1 : 0);
+		break;
 	case PROBE_IDENTIFY:
 	{
 		struct ata_params *ident_buf;
@@ -538,6 +557,52 @@
 	priority = done_ccb->ccb_h.pinfo.priority;
 
 	switch (softc->action) {
+	case PROBE_RESET:
+		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+			PROBE_SET_ACTION(softc, PROBE_UNRESET);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		} else if (cam_periph_error(done_ccb, 0,
+					    done_ccb->ccb_h.target_lun > 0
+					    ? SF_RETRY_UA|SF_QUIET_IR
+					    : SF_RETRY_UA,
+					    &softc->saved_ccb) == ERESTART) {
+			return;
+		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+			/* Don't wedge the queue */
+			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+					 /*run_queue*/TRUE);
+		}
+		xpt_release_ccb(done_ccb);
+		break;
+	case PROBE_UNRESET:
+		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+			printf("SIGNATURE: %02x%02x%02x%02x\n",
+			    done_ccb->ataio.res.lba_high, done_ccb->ataio.res.lba_mid,
+			    done_ccb->ataio.res.lba_low, done_ccb->ataio.res.sector_count);
+			if (done_ccb->ataio.res.lba_high == 0xeb &&
+			    done_ccb->ataio.res.lba_mid == 0x14)
+				path->device->protocol = PROTO_SCSI;
+			else
+				path->device->protocol = PROTO_ATA;
+			PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		} else if (cam_periph_error(done_ccb, 0,
+					    done_ccb->ccb_h.target_lun > 0
+					    ? SF_RETRY_UA|SF_QUIET_IR
+					    : SF_RETRY_UA,
+					    &softc->saved_ccb) == ERESTART) {
+			return;
+		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+			/* Don't wedge the queue */
+			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+					 /*run_queue*/TRUE);
+		}
+		xpt_release_ccb(done_ccb);
+		break;
 	case PROBE_IDENTIFY:
 	{
 		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
@@ -612,7 +677,7 @@
 
 			scsi_find_quirk(path->device);
 
-			ata_devise_transport(path);
+			ata_device_transport(path);
 //			if (INQ_DATA_TQ_ENABLED(inq_buf))
 //				PROBE_SET_ACTION(softc, PROBE_MODE_SENSE);
 //			else
@@ -1090,7 +1155,7 @@
 				 bus->path_id,
 				 target->target_id,
 				 lun_id);
-		ata_devise_transport(&path);
+		ata_device_transport(&path);
 		xpt_release_path(&path);
 	}
 
@@ -1098,7 +1163,7 @@
 }
 
 static void
-ata_devise_transport(struct cam_path *path)
+ata_device_transport(struct cam_path *path)
 {
 	struct ccb_pathinq cpi;
 //	struct ccb_trans_settings cts;
@@ -1112,7 +1177,7 @@
 	inq_buf = NULL;
 //	if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0)
 //		inq_buf = &path->device->inq_data;
-	path->device->protocol = cpi.protocol;
+//	path->device->protocol = cpi.protocol;
 //	path->device->protocol_version =
 //	    inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version;
 	path->device->transport = cpi.transport;

==== //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#20 (text+ko) ====

@@ -631,14 +631,10 @@
 struct ccb_ataio {
 	struct	   ccb_hdr ccb_h;
 	union	   ccb *next_ccb;	/* Ptr for next CCB for action */
-	u_int8_t   *req_map;		/* Ptr to mapping info */
 	struct ata_cmd	cmd;		/* ATA command register set */
 	struct ata_res	res;		/* ATA result register set */
 	u_int8_t   *data_ptr;		/* Ptr to the data buf/SG list */
 	u_int32_t  dxfer_len;		/* Data transfer length */
-					/* Autosense storage */	
-	u_int16_t  sglist_cnt;		/* Number of SG list entries */
-	u_int8_t   status;		/* Returned ATA status */
 	u_int32_t  resid;		/* Transfer residual length: 2's comp */
 	u_int8_t   tag_action;		/* What to do for tag queueing */
 	/*

==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#90 (text+ko) ====

@@ -2459,7 +2459,7 @@
 		/* FALLTHROUGH */
 	case XPT_ATA_IO:
 		if (start_ccb->ccb_h.func_code == XPT_ATA_IO) {
-			start_ccb->ataio.status = 0;
+			start_ccb->ataio.resid = 0;
 		}
 	case XPT_RESET_DEV:
 	case XPT_ENG_EXEC:
@@ -3788,8 +3788,6 @@
 	if (status != CAM_REQ_CMP)
 		printf("xpt_compile_path returned %d\n", status);
 
-	xpt_print_path(&path);
-	
 	xpt_setup_ccb(&cpi.ccb_h, &path, /*priority*/1);
 	cpi.ccb_h.func_code = XPT_PATH_INQ;
 	xpt_action((union ccb *)&cpi);

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#17 (text+ko) ====

@@ -69,7 +69,6 @@
 static void ahci_timeout(struct ahci_slot *slot);
 static void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et);
 static int ahci_hardreset(device_t dev, int port, uint32_t *signature);
-static u_int32_t ahci_softreset(device_t dev, int port);
 static int ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag);
 static void ahci_dmainit(device_t dev);
 static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
@@ -79,7 +78,7 @@
 static void ahci_reset(device_t dev);
 static void ahci_start(device_t dev);
 static void ahci_stop(device_t dev);
-static void ahci_clo(device_t dev);
+//static void ahci_clo(device_t dev);
 static void ahci_start_fr(device_t dev);
 static void ahci_stop_fr(device_t dev);
 
@@ -539,7 +538,6 @@
 		return (ENXIO);
 	}
 	
-	ahci_reset(dev);
 	mtx_unlock(&ch->mtx);
 	return 0;
 }
@@ -579,8 +577,7 @@
 	ahci_stop(dev);
 	ahci_stop_fr(dev);
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD, 0);
-
-	/* Allow everything including partial and slumber modes. */
+	/* Allow everything, including partial and slumber modes. */
 	ATA_IDX_OUTL(ch, ATA_SCONTROL, 0);
 	/* Request slumber mode transition and give some time to get there. */
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD, AHCI_P_CMD_SLUMBER);
@@ -598,17 +595,14 @@
 
 	/* Disable port interrupts */
 	ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
-
-	/* setup work areas */
+	/* Setup work areas */
 	work = ch->dma.work_bus + AHCI_CL_OFFSET;
 	ATA_OUTL(ch->r_mem, AHCI_P_CLB, work & 0xffffffff);
 	ATA_OUTL(ch->r_mem, AHCI_P_CLBU, work >> 32);
-
 	work = ch->dma.work_bus + AHCI_FB_OFFSET;
 	ATA_OUTL(ch->r_mem, AHCI_P_FB, work & 0xffffffff); 
 	ATA_OUTL(ch->r_mem, AHCI_P_FBU, work >> 32);
-
-	/* activate the channel and power/spin up device */
+	/* Activate the channel and power/spin up device */
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD,
 	     (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
 	     ((ch->pm_level > 1) ? AHCI_P_CMD_ALPE : 0) |
@@ -638,25 +632,26 @@
 static void
 ahci_phy_check_events(device_t dev)
 {
-    struct ahci_channel *ch = device_get_softc(dev);
-    u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
+	struct ahci_channel *ch = device_get_softc(dev);
+	u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
 
-    /* clear error bits/interrupt */
-    ATA_IDX_OUTL(ch, ATA_SERROR, error);
-
-    /* if we have a connection event deal with it */
-    if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
-	if (bootverbose) {
-	    u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
-	    if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
-		((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
-		((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
-		    device_printf(dev, "CONNECT requested\n");
-	    } else
-		    device_printf(dev, "DISCONNECT requested\n");
+	/* Clear error bits/interrupt */
+	ATA_IDX_OUTL(ch, ATA_SERROR, error);
+	/* If we have a connection event deal with it */
+	if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
+		u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
+		if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
+		    ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
+		    ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
+			if (bootverbose)
+				device_printf(dev, "CONNECT requested\n");
+			ahci_reset(dev);
+		} else {
+			if (bootverbose)
+				device_printf(dev, "DISCONNECT requested\n");
+			ch->devices = 0;
+		}
 	}
-//	taskqueue_enqueue(taskqueue_thread, &ch->conntask);
-    }
 }
 
 static void
@@ -684,7 +679,6 @@
 
 #define AHCI_STATBITS \
 	(AHCI_P_IX_IF|AHCI_P_IX_HBD|AHCI_P_IX_HBF|AHCI_P_IX_TFE)
-
 	if ((istatus & AHCI_STATBITS) && ((cstatus | sstatus) & ch->rslots)) {
 device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x\n", __func__, istatus, cstatus, sstatus, ch->rslots);
 		ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
@@ -817,85 +811,82 @@
 
 //device_printf(slot->dev, "%s slot %d\n", __func__, slot->slot);
 	slot->state = AHCI_SLOT_LOADED;
-
-	/* get a piece of the workspace for this request */
+	/* Get a piece of the workspace for this request */
 	ctp = (struct ahci_cmd_tab *)
 		(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot));
-
-	/* setup the FIS for this request */
+	/* Setup the FIS for this request */
 	if (!(fis_size = ahci_setup_fis(ctp, slot->ccb, slot->slot))) {
 		device_printf(ch->dev, "setting up SATA FIS failed\n");
 		slot->ccb->ccb_h.status = CAM_REQ_INVALID;
 		xpt_done(slot->ccb);
 		return;
 	}
-
-	/* setup the command list entry */
+	/* Setup the command list entry */
 	clp = (struct ahci_cmd_list *)
 	    (ch->dma.work + AHCI_CL_OFFSET + (AHCI_CL_SIZE * slot->slot));
-
 	clp->prd_length = slot->dma.nsegs;
 	clp->cmd_flags = (slot->ccb->ccb_h.flags & CAM_DIR_OUT ? AHCI_CMD_WRITE : 0) |
 		     (slot->ccb->ccb_h.func_code == XPT_SCSI_IO ?
 		      (AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH) : 0) |
 		     (fis_size / sizeof(u_int32_t)) |
 		     (port << 12);
+	/* Special handling for Soft Reset command. */
+	if ((slot->ccb->ccb_h.func_code == XPT_ATA_IO) &&
+	    (slot->ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
+	    slot->ccb->ataio.cmd.control & ATA_A_RESET) {
+		clp->cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY;
+	}
 	clp->bytecount = 0;
 	clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET +
 				  (AHCI_CT_SIZE * slot->slot));
-
-	/* set command type bit */
-	if (slot->ccb->ccb_h.func_code == XPT_SCSI_IO) {
-		ATA_OUTL(ch->r_mem, AHCI_P_CMD,
-		    ATA_INL(ch->r_mem, AHCI_P_CMD) | AHCI_P_CMD_ATAPI);
-	} else {
-		ATA_OUTL(ch->r_mem, AHCI_P_CMD,
-		    ATA_INL(ch->r_mem, AHCI_P_CMD) & ~AHCI_P_CMD_ATAPI);
-	}
-
-	slot->state = AHCI_SLOT_RUNNING;
-	ch->rslots |= (1 << slot->slot);
+	/* Set ACTIVE bit for NCQ commands. */
 	if ((slot->ccb->ccb_h.func_code == XPT_ATA_IO) &&
 	    (slot->ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
-		/* Set ACTIVE bit */
 		ch->aslots |= (1 << slot->slot);
 		ATA_IDX_OUTL(ch, ATA_SACTIVE, 1 << slot->slot);
 	}
-
-	/* issue command to controller */
+	/* Issue command to the controller. */
+	slot->state = AHCI_SLOT_RUNNING;
+	ch->rslots |= (1 << slot->slot);
 	ATA_OUTL(ch->r_mem, AHCI_P_CI, (1 << slot->slot));
 /*
-printf("ci %08x is %08x tfd %08x serr %08x\n",
+printf("ci %08x is %08x tfd %08x serr %08x sign %08x\n",
     ATA_INL(ch->r_mem, AHCI_P_CI),
     ATA_INL(ch->r_mem, AHCI_P_IS),
     ATA_INL(ch->r_mem, AHCI_P_TFD),
-    ATA_IDX_INL(ch, ATA_SERROR));
+    ATA_IDX_INL(ch, ATA_SERROR),
+    ATA_INL(ch->r_mem, AHCI_P_SIG));
 DELAY(100000);
-printf("ci %08x is %08x tfd %08x serr %08x\n",
+printf("ci %08x is %08x tfd %08x serr %08x sign %08x\n",
     ATA_INL(ch->r_mem, AHCI_P_CI),
     ATA_INL(ch->r_mem, AHCI_P_IS),
     ATA_INL(ch->r_mem, AHCI_P_TFD),
-    ATA_IDX_INL(ch, ATA_SERROR));
+    ATA_IDX_INL(ch, ATA_SERROR),
+    ATA_INL(ch->r_mem, AHCI_P_SIG));
 */
-
+	/* Device reset commands doesn't interrupt. Poll them. */
 	if (slot->ccb->ccb_h.func_code == XPT_ATA_IO &&
-	    slot->ccb->ataio.cmd.command == ATA_DEVICE_RESET) {
-		/* device reset doesn't interrupt */
-		u_int32_t tf_data;
-		int timeout = 1000000;
+	    (slot->ccb->ataio.cmd.command == ATA_DEVICE_RESET ||
+	    (slot->ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL))) {
+		u_int32_t status;
+		int count, timeout = slot->ccb->ccb_h.timeout;
+		enum ahci_err_type et = AHCI_ERR_NONE;
 
-		do {
-			DELAY(10);
-			tf_data = ATA_INL(ch->r_mem, AHCI_P_TFD + (ch->unit<<7));
-		} while ((tf_data & ATA_S_BUSY) && timeout--);
-		if (bootverbose)
-			device_printf(ch->dev, "device_reset timeout=%dus\n",
-			    (1000000-timeout)*10);
-		slot->ccb->ataio.status = tf_data;
-//		if (request->status & ATA_S_ERROR)
-//			request->error = tf_data >> 8;
-		slot->ccb->ccb_h.status = CAM_REQ_CMP;
-		xpt_done(slot->ccb);
+		for (count = 0; count < timeout; count++) {
+			DELAY(1000);
+			if (!((status = ATA_INL(ch->r_mem, AHCI_P_CI)) &
+			    (1 << slot->slot))) {
+				break;
+			}
+		}
+		if (timeout && (count >= timeout)) {
+device_printf(ch->dev, "Poll timeout on slot %d\n", slot->slot);
+			et = CAM_CMD_TIMEOUT;
+			/* kick controller into sane state */
+			ahci_stop(ch->dev);
+			ahci_start(ch->dev);
+		}
+		ahci_end_transaction(slot, et);
 		return;
 	}
 
@@ -936,22 +927,10 @@
 	device_t dev = slot->dev;
 	struct ahci_channel *ch = device_get_softc(dev);
 //	struct ahci_cmd_list *clp;
-	u_int32_t tf_data;
 
 //device_printf(dev, "%s slot %d\n", __func__, slot->slot);
-	/* kill the timeout */
+	/* Kill the timeout */
 	callout_stop(&slot->timeout);
-
-	/* get status */
-	tf_data = ATA_INL(ch->r_mem, AHCI_P_TFD);
-#if 0
-	if (err && slot->ccb->ccb_h.func_code == XPT_ATA_IO) {
-		slot->ccb->ataio.status = tf_data;
-		/* if error status get details */
-		if (tf_data & ATA_S_ERROR)  
-			request->error = tf_data >> 8;
-	}
-#endif
 	/* Read registers to the result struct */
 	if (slot->ccb->ccb_h.func_code == XPT_ATA_IO) {
 		struct ata_res *res = &slot->ccb->ataio.res;
@@ -981,10 +960,9 @@
 		bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
 		    (slot->ccb->ccb_h.flags & CAM_DIR_IN) ?
 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
-
 		bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map);
 	}
-
+	/* Set proper result status. */
 	switch (et) {
 	case AHCI_ERR_NONE:
 		slot->ccb->ccb_h.status = CAM_REQ_CMP;
@@ -995,10 +973,8 @@
 		if (slot->ccb->ccb_h.func_code == XPT_SCSI_IO) {
 			slot->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
 			slot->ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
-		} else {
+		} else
 			slot->ccb->ccb_h.status = CAM_REQ_CMP_ERR;
-			slot->ccb->ataio.status = tf_data;
-		}
 		break;
 	case AHCI_ERR_BTW:
 		slot->ccb->ccb_h.status = CAM_REQUEUE_REQ;
@@ -1013,67 +989,23 @@
 		slot->ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 	}
 	xpt_done(slot->ccb);
-
 	ch->rslots &= ~(1 << slot->slot);
 	slot->state = AHCI_SLOT_EMPTY;
 	slot->ccb = NULL;
 	return;
 }
 
-static int
-ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout)
-{
-	struct ahci_channel *ch = device_get_softc(dev);
-	struct ahci_cmd_list *clp =
-	    (struct ahci_cmd_list *)(ch->dma.work + AHCI_CL_OFFSET);
-	struct ahci_cmd_tab *ctp =
-	    (struct ahci_cmd_tab *)(ch->dma.work + AHCI_CT_OFFSET);
-	u_int32_t status = 0;
-	int port = (ctp->cfis[1] & 0x0f);
-	int count;
-
-	clp->prd_length = 0;
-	clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12);
-	clp->bytecount = 0;
-	clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET);
-
-	/* issue command to controller */
-	ATA_OUTL(ch->r_mem, AHCI_P_CI, 1);
-
-	/* poll for command finished */
-	for (count = 0; count < timeout; count++) {
-		DELAY(1000);
-		if (!((status = ATA_INL(ch->r_mem, AHCI_P_CI)) & 1))
-			break;
-	}
-
-	/* clear interrupts */
-	ATA_OUTL(ch->r_mem, AHCI_P_IS, ATA_INL(ch->r_mem, AHCI_P_IS));
-
-	if (timeout && (count >= timeout)) {
-		if (bootverbose) {
-			device_printf(dev, "ahci_issue_cmd timeout: %d of %dms, status=%08x\n",
-			    count, timeout, status);
-		}
-		return EIO;
-	}
-
-	return (0);
-}
-
 static void
 ahci_start(device_t dev)
 {
 	struct ahci_channel *ch = device_get_softc(dev);
 	u_int32_t cmd;
 
-	/* clear SATA error register */
+	/* Clear SATA error register */
 	ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
-
-	/* clear any interrupts pending on this channel */
+	/* Clear any interrupts pending on this channel */
 	ATA_OUTL(ch->r_mem, AHCI_P_IS, ATA_INL(ch->r_mem, AHCI_P_IS));
-
-	/* start operations on this channel */
+	/* Start operations on this channel */
 	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD,
 	     cmd | AHCI_P_CMD_ST |
@@ -1087,11 +1019,10 @@
 	u_int32_t cmd;
 	int timeout;
 
-	/* kill off all activity on this channel */
+	/* Kill all activity on this channel */
 	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
-	ATA_OUTL(ch->r_mem, AHCI_P_CMD,
-	     cmd & ~AHCI_P_CMD_ST);
-
+	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd & ~AHCI_P_CMD_ST);
+	/* Wait for activity stop. */
 	timeout = 0;
 	do {
 		DELAY(1000);
@@ -1102,6 +1033,7 @@
 	} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CR);
 }
 
+#if 0
 static void
 ahci_clo(device_t dev)
 {
@@ -1110,7 +1042,7 @@
 	u_int32_t cmd;
 	int timeout;
 
-	/* issue Command List Override if supported */ 
+	/* Issue Command List Override if supported */ 
 	if (ATA_INL(ctlr->r_mem, AHCI_CAP) & AHCI_CAP_SCLO) {
 		cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
 		cmd |= AHCI_P_CMD_CLO;
@@ -1125,6 +1057,7 @@
 		} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CLO);
 	}
 }
+#endif
 
 static void
 ahci_stop_fr(device_t dev)
@@ -1133,10 +1066,10 @@
 	u_int32_t cmd;
 	int timeout;
 
-	/* kill off all activity on this channel */
+	/* Kill all FIS reception on this channel */
 	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd & ~AHCI_P_CMD_FRE);
-
+	/* Wait for FIS reception stop. */
 	timeout = 0;
 	do {
 		DELAY(1000);
@@ -1153,7 +1086,7 @@
 	struct ahci_channel *ch = device_get_softc(dev);
 	u_int32_t cmd;
 
-	/* start FIS reception on this channel */
+	/* Start FIS reception on this channel */
 	cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_FRE);
 }
@@ -1200,55 +1133,9 @@
 	return (0);
 }
 
-static u_int32_t
-ahci_softreset(device_t dev, int port)
-{
-	struct ahci_channel *ch = device_get_softc(dev);
-	struct ahci_cmd_tab *ctp =
-	    (struct ahci_cmd_tab *)(ch->dma.work + AHCI_CT_OFFSET);
-
-	if (bootverbose)
-		device_printf(dev, "software reset port %d...\n", port);
-
-	/* kick controller into sane state */
-	ahci_stop(dev);
-	ahci_clo(dev);
-	ahci_start(dev);
-
-	/* pull reset active */
-	bzero(ctp->cfis, 64);
-	ctp->cfis[0] = 0x27;
-	ctp->cfis[1] = port & 0x0f;
-	//ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
-	ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET);
-
-	if (ahci_issue_cmd(dev, AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY,100)) {
-		device_printf(dev, "software reset set timeout\n");
-		return (-1);
-	}
-
-	DELAY(50);
-
-	/* pull reset inactive -> device softreset */
-	bzero(ctp->cfis, 64);
-	ctp->cfis[0] = 0x27;
-	ctp->cfis[1] = port & 0x0f;
-	//ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
-	ctp->cfis[15] = ATA_A_4BIT;
-	ahci_issue_cmd(dev, 0, 3000);
-
-	if (ahci_wait_ready(dev, 0)) {
-		device_printf(dev, "software reset clear timeout\n");
-		return (-1);
-	}
-
-	return ATA_INL(ch->r_mem, AHCI_P_SIG);
-}
-
 static void
 ahci_reset(device_t dev)
 {
-	struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
 	struct ahci_channel *ch = device_get_softc(dev);
 	u_int32_t signature;
 
@@ -1257,56 +1144,25 @@
 
 	/* Disable port interrupts */
 	ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
-
+	/* Reset and reconnect PHY, */
 	if (ahci_hardreset(dev, -1, &signature)) {
 		if (bootverbose)
 			device_printf(dev,
 			    "AHCI reset done: phy reset found no device\n");
 		ch->devices = 0;
-
-		/* enable wanted port interrupts */
+		/* Enable wanted port interrupts */
 		ATA_OUTL(ch->r_mem, AHCI_P_IE,
 		    (AHCI_P_IX_CPD | AHCI_P_IX_PRC | AHCI_P_IX_PC));
 		return;
 	}
-
-	/* enable wanted port interrupts */
+	ch->devices = ATA_ATA_MASTER;
+	/* Enable wanted port interrupts */
 	ATA_OUTL(ch->r_mem, AHCI_P_IE,
 	     (AHCI_P_IX_CPD | AHCI_P_IX_TFE | AHCI_P_IX_HBF |
 	      AHCI_P_IX_HBD | AHCI_P_IX_IF | AHCI_P_IX_OF |
 	      ((ch->pm_level == 0) ? AHCI_P_IX_PRC | AHCI_P_IX_PC : 0) |
 	      AHCI_P_IX_DP | AHCI_P_IX_UF | AHCI_P_IX_SDB |
 	      AHCI_P_IX_DS | AHCI_P_IX_PS | AHCI_P_IX_DHR));
-
-	/* only probe for PortMultiplier if HW has support */
-	if (ATA_INL(ctlr->r_mem, AHCI_CAP) & AHCI_CAP_SPM) {
-		signature = ahci_softreset(dev, ATA_PM);
-		/* Workaround for some ATI chips, failing to soft-reset
-		 * when port multiplicator supported, but absent.
-		 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
-		if (signature == 0xffffffff)
-			signature = ahci_softreset(dev, 0);
-		} else {
-			signature = ahci_softreset(dev, 0);
-		}
-	if (bootverbose)
-		device_printf(dev, "SIGNATURE: %08x\n", signature);
-
-	switch (signature >> 16) {
-	case 0x0000:
-		ch->devices = ATA_ATA_MASTER;
-		break;
-	case 0x9669:
-		ch->devices = ATA_PORTMULTIPLIER | 0x0003; /* Temporary hack. */
-		break;
-	case 0xeb14:
-		ch->devices = ATA_ATAPI_MASTER;
-		break;
-	default: /* SOS XXX */
-		if (bootverbose)
-			device_printf(dev, "Unknown signature, assuming disk device\n");
-		ch->devices = ATA_ATA_MASTER;
-	}
 	if (bootverbose)
 		device_printf(dev, "AHCI reset done: devices=%08x\n", ch->devices);
 	/* If we've attached to the XPT, tell it about the event */
@@ -1421,7 +1277,7 @@
 	struct ahci_dc_cb_args dcba;
 	int i;
 
-	/* alloc and setup needed dma slots */
+	/* Alloc and setup command/dma slots */
 	bzero(ch->slot, sizeof(ch->slot));
 	for (i = 0; i < AHCI_MAX_SLOTS; i++) {
 		struct ahci_slot *slot = &ch->slot[i];
@@ -1459,7 +1315,7 @@
 	struct ahci_channel *ch = device_get_softc(dev);
 	int i;
 
-	/* free all dma slots */
+	/* Free all dma slots */
 	for (i = 0; i < AHCI_MAX_SLOTS; i++) {
 		struct ahci_slot *slot = &ch->slot[i];
 
@@ -1490,13 +1346,10 @@
 	u_int8_t *fis = &ctp->cfis[0];
 
 	bzero(ctp->cfis, 64);
+	fis[0] = 0x27;  		/* host to device */
+	fis[1] = (ccb->ccb_h.target_id & 0x0f);
 	if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
-		bzero(ctp->acmd, 32);
-		bcopy((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
-		    ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes,
-		    ctp->acmd, ccb->csio.cdb_len);
-		fis[0] = 0x27;  		/* host to device */
-		fis[1] = 0x80 | (ccb->ccb_h.target_id & 0x0f);
+		fis[1] |= 0x80;
 		fis[2] = ATA_PACKET_CMD;
 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
 			fis[3] = ATA_F_DMA;
@@ -1506,9 +1359,12 @@
 		}
 		fis[7] = ATA_D_LBA;
 		fis[15] = ATA_A_4BIT;
-	} else {
-		fis[0] = 0x27;			/* host to device */
-		fis[1] = 0x80 | (ccb->ccb_h.target_id & 0x0f);
+		bzero(ctp->acmd, 32);
+		bcopy((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+		    ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes,
+		    ctp->acmd, ccb->csio.cdb_len);
+	} else if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) == 0) {
+		fis[1] |= 0x80;
 		fis[2] = ccb->ataio.cmd.command;
 		fis[3] = ccb->ataio.cmd.features;
 		fis[4] = ccb->ataio.cmd.lba_low;
@@ -1527,6 +1383,8 @@
 			fis[13] = ccb->ataio.cmd.sector_count_exp;
 		}
 		fis[15] = ATA_A_4BIT;
+	} else {
+		fis[15] = ccb->ataio.cmd.control;
 	}
 	return (20);
 }
@@ -1537,16 +1395,16 @@
 	u_int32_t status;
 	int timeout;
 
-	/* wait up to 1 second for "connect well" */
-	for (timeout = 0; timeout < 100 ; timeout++) {
+	/* Wait up to 1 second for "connect well" */
+	for (timeout = 0; timeout < 1000 ; timeout++) {
 		status = ATA_IDX_INL(ch, ATA_SSTATUS);
 		if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
 		    ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
 		    ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
 			break;
-		DELAY(10000);
+		DELAY(1000);
 	}
-	if (timeout >= 100) {
+	if (timeout >= 1000) {
 		if (bootverbose) {
 			device_printf(ch->dev, "SATA connect timeout status=%08x\n",
 			    status);
@@ -1555,10 +1413,9 @@
 	}
 	if (bootverbose) {
 		device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
-		    timeout * 10, status);
+		    timeout, status);
 	}
-
-	/* clear SATA error register */
+	/* Clear SATA error register */
 	ATA_IDX_OUTL(ch, ATA_SERROR, 0xffffffff);
 	return (1);
 }
@@ -1567,7 +1424,6 @@
 ata_sata_phy_reset(device_t dev, int quick)
 {
 	struct ahci_channel *ch = device_get_softc(dev);
-	int loop, retry;
 	uint32_t val;
 
 	if (quick) {
@@ -1578,33 +1434,18 @@
 
 	if (bootverbose)
 		device_printf(dev, "hardware reset ...\n");
-	for (retry = 0; retry < 10; retry++) {
-		for (loop = 0; loop < 10; loop++) {
-			ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
-			DELAY(100);
-			val = ATA_IDX_INL(ch, ATA_SCONTROL);
-			if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
-				break;
-		}
-		DELAY(5000);
-		for (loop = 0; loop < 10; loop++) {
-			ATA_IDX_OUTL(ch, ATA_SCONTROL,
-			    ATA_SC_DET_IDLE | ATA_SC_SPD_SPEED_GEN1 | ((ch->pm_level > 0) ? 0 :
-			    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER));
-			DELAY(100);
-			val = ATA_IDX_INL(ch, ATA_SCONTROL);
-			if ((val & ATA_SC_DET_MASK) == 0)
-				return (ata_sata_connect(ch));
-		}
-	}
-	return (0);
+	ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
+	DELAY(50000);
+	ATA_IDX_OUTL(ch, ATA_SCONTROL,
+	    ATA_SC_DET_IDLE /*| ATA_SC_SPD_SPEED_GEN1*/ | ((ch->pm_level > 0) ? 0 :
+	    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER));
+	return (ata_sata_connect(ch));
 }
 
 static void
 ahciaction(struct cam_sim *sim, union ccb *ccb)
 {
 	struct ahci_channel *ch;
-//	int s;
 
 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahciaction func_codeL%d\n",
 	    ccb->ccb_h.func_code));
@@ -1615,8 +1456,7 @@
 	/* Common cases first */
 	case XPT_ATA_IO:	/* Execute the requested I/O operation */
 	case XPT_SCSI_IO:
-		if ((((ATA_ATA_MASTER | ATA_ATAPI_MASTER) <<
-		    ccb->ccb_h.target_id) & ch->devices) == 0) {
+		if (ch->devices == 0) {
 			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
 			xpt_done(ccb);
 			break;
@@ -1714,7 +1554,7 @@
 		cpi->target_sprt = 0;
 		cpi->hba_misc = PIM_SEQSCAN;
 		cpi->hba_eng_cnt = 0;
-		cpi->max_target = 14;
+		cpi->max_target = 0;
 		cpi->max_lun = 0;
 		cpi->initiator_id = 0;
 		cpi->bus_id = cam_sim_bus(sim);
@@ -1725,10 +1565,7 @@
 		cpi->unit_number = cam_sim_unit(sim);
 		cpi->transport = XPORT_SATA;
 		cpi->transport_version = 2;
-		if ((ATA_ATAPI_MASTER << ccb->ccb_h.target_id) & ch->devices)
-			cpi->protocol = PROTO_SCSI;
-		else
-			cpi->protocol = PROTO_ATA;
+		cpi->protocol = PROTO_ATA;
 		cpi->protocol_version = SCSI_REV_2;
 		cpi->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);


More information about the p4-projects mailing list