diff --git a/sys/dev/disk/ahci/ahci.c b/sys/dev/disk/ahci/ahci.c
index 00a230b..d32a17c 100644
--- a/sys/dev/disk/ahci/ahci.c
+++ b/sys/dev/disk/ahci/ahci.c
@@ -138,9 +138,12 @@ ahci_init(struct ahci_softc *sc)
 	 * Unconditionally reset the controller, do not conditionalize on
 	 * trying to figure it if it was previously active or not.
 	 *
-	 * NOTE on AE before HR. This is against the spec which neither
-	 * indicates nor implies any such requirement, but both the linux
-	 * and freebsd drivers do it so we will too.
+	 * NOTE: On AE before HR.  The AHCI-1.1 spec has a note in section
+	 *	 5.2.2.1 regarding this.  HR should be set to 1 only after
+	 *	 AE is set to 1.  The reset sequence will clear HR when
+	 *	 it completes, and will also clear AE if SAM is 0.  AE must
+	 *	 then be set again.  When SAM is 1 the AE bit typically reads
+	 *	 as 1 (and is read-only).
 	 *
 	 * NOTE BRICKS (1)
 	 *
@@ -153,7 +156,7 @@ ahci_init(struct ahci_softc *sc)
 	 *	host port).  This issue is unrelated to CLO.
 	 */
 	ahci_write(sc, AHCI_REG_GHC, AHCI_REG_GHC_AE);
-	ahci_write(sc, AHCI_REG_GHC, AHCI_REG_GHC_HR);
+	ahci_write(sc, AHCI_REG_GHC, AHCI_REG_GHC_AE | AHCI_REG_GHC_HR);
 	if (ahci_wait_ne(sc, AHCI_REG_GHC,
 			 AHCI_REG_GHC_HR, AHCI_REG_GHC_HR) != 0) {
 		device_printf(sc->sc_dev,
@@ -205,12 +208,20 @@ ahci_port_alloc(struct ahci_softc *sc, u_int port)
 	 *
 	 * ap_pmcount will be reduced by the scan if we encounter the
 	 * port multiplier port prior to target 15.
+	 *
+	 * kmalloc power-of-2 allocations are guaranteed not to cross
+	 * a page boundary.  Make sure the identify sub-structure in the
+	 * at structure does not cross a page boundary, just in case the
+	 * part is AHCI-1.1 and can't handle multiple DRQ blocks.
 	 */
-	if (ap->ap_ata == NULL) {
-		ap->ap_ata = kmalloc(sizeof(*ap->ap_ata) * AHCI_MAX_PMPORTS,
-				     M_DEVBUF, M_INTWAIT | M_ZERO);
+	if (ap->ap_ata[0] == NULL) {
+		int pw2;
+
+		for (pw2 = 1; pw2 < sizeof(*at); pw2 <<= 1)
+			;
 		for (i = 0; i < AHCI_MAX_PMPORTS; ++i) {
-			at = &ap->ap_ata[i];
+			at = kmalloc(pw2, M_DEVBUF, M_INTWAIT | M_ZERO);
+			ap->ap_ata[i] = at;
 			at->at_ahci_port = ap;
 			at->at_target = i;
 			at->at_probe = ATA_PROBE_NEED_INIT;
@@ -515,7 +526,7 @@ ahci_port_state_machine(struct ahci_port *ap, int initial)
 		didsleep = 0;
 
 		for (target = 0; target < ap->ap_pmcount; ++target) {
-			at = &ap->ap_ata[target];
+			at = ap->ap_ata[target];
 
 			/*
 			 * Check the target state for targets behind the PM
@@ -629,8 +640,9 @@ ahci_port_state_machine(struct ahci_port *ap, int initial)
 void
 ahci_port_free(struct ahci_softc *sc, u_int port)
 {
-	struct ahci_port		*ap = sc->sc_ports[port];
-	struct ahci_ccb			*ccb;
+	struct ahci_port	*ap = sc->sc_ports[port];
+	struct ahci_ccb		*ccb;
+	int i;
 
 	/*
 	 * Ensure port is disabled and its interrupts are all flushed.
@@ -677,8 +689,12 @@ ahci_port_free(struct ahci_softc *sc, u_int port)
 		ap->ap_dmamem_cmd_table = NULL;
 	}
 	if (ap->ap_ata) {
-		kfree(ap->ap_ata, M_DEVBUF);
-		ap->ap_ata = NULL;
+		for (i = 0; i < AHCI_MAX_PMPORTS; ++i) {
+			if (ap->ap_ata[i]) {
+				kfree(ap->ap_ata[i], M_DEVBUF);
+				ap->ap_ata[i] = NULL;
+			}
+		}
 	}
 	if (ap->ap_err_scratch) {
 		kfree(ap->ap_err_scratch, M_DEVBUF);
@@ -1330,7 +1346,7 @@ ahci_port_hardstop(struct ahci_port *ap)
 	 * Clean up AT sub-ports on SATA port.
 	 */
 	for (i = 0; ap->ap_ata && i < AHCI_MAX_PMPORTS; ++i) {
-		at = &ap->ap_ata[i];
+		at = ap->ap_ata[i];
 		at->at_type = ATA_PORT_T_NONE;
 		at->at_probe = ATA_PROBE_FAILED;
 	}
@@ -1531,9 +1547,10 @@ ahci_load_prdt(struct ahci_ccb *ccb)
 
 	cmd_slot->prdtl = htole16(prdt - ccb->ccb_cmd_table->prdt + 1);
 
-	bus_dmamap_sync(sc->sc_tag_data, dmap,
-			(xa->flags & ATA_F_READ) ?
-			    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+	if (xa->flags & ATA_F_READ)
+		bus_dmamap_sync(sc->sc_tag_data, dmap, BUS_DMASYNC_PREREAD);
+	if (xa->flags & ATA_F_WRITE)
+		bus_dmamap_sync(sc->sc_tag_data, dmap, BUS_DMASYNC_PREWRITE);
 
 	return (0);
 }
@@ -1574,10 +1591,14 @@ ahci_unload_prdt(struct ahci_ccb *ccb)
 	bus_dmamap_t			dmap = ccb->ccb_dmamap;
 
 	if (xa->datalen != 0) {
-		bus_dmamap_sync(sc->sc_tag_data, dmap,
-				(xa->flags & ATA_F_READ) ?
-				BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
-
+		if (xa->flags & ATA_F_READ) {
+			bus_dmamap_sync(sc->sc_tag_data, dmap,
+					BUS_DMASYNC_POSTREAD);
+		}
+		if (xa->flags & ATA_F_WRITE) {
+			bus_dmamap_sync(sc->sc_tag_data, dmap,
+					BUS_DMASYNC_POSTWRITE);
+		}
 		bus_dmamap_unload(sc->sc_tag_data, dmap);
 
 		/*
@@ -2604,14 +2625,23 @@ ahci_get_err_ccb(struct ahci_port *ap)
 {
 	struct ahci_ccb *err_ccb;
 	u_int32_t sact;
+	u_int32_t ci;
 
 	/* No commands may be active on the chip. */
-	sact = ahci_pread(ap, AHCI_PREG_SACT);
-	if (sact != 0) {
-		kprintf("%s: ahci_get_err_ccb but SACT %08x != 0?\n",
-			PORTNAME(ap), sact);
+
+	if (ap->ap_sc->sc_cap & AHCI_REG_CAP_SNCQ) {
+		sact = ahci_pread(ap, AHCI_PREG_SACT);
+		if (sact != 0) {
+			kprintf("%s: ahci_get_err_ccb but SACT %08x != 0?\n",
+				PORTNAME(ap), sact);
+		}
 	}
-	KKASSERT(ahci_pread(ap, AHCI_PREG_CI) == 0);
+	ci = ahci_pread(ap, AHCI_PREG_CI);
+	if (ci) {
+		kprintf("%s: ahci_get_err_ccb: ci not 0 (%08x)\n",
+			ap->ap_name, ci);
+	}
+	KKASSERT(ci == 0);
 	KKASSERT((ap->ap_flags & AP_F_ERR_CCB_RESERVED) == 0);
 	ap->ap_flags |= AP_F_ERR_CCB_RESERVED;
 
@@ -2650,10 +2680,12 @@ ahci_put_err_ccb(struct ahci_ccb *ccb)
 	/*
 	 * No commands may be active on the chip
 	 */
-	sact = ahci_pread(ap, AHCI_PREG_SACT);
-	if (sact) {
-		panic("ahci_port_err_ccb(%d) but SACT %08x != 0\n",
-		      ccb->ccb_slot, sact);
+	if (ap->ap_sc->sc_cap & AHCI_REG_CAP_SNCQ) {
+		sact = ahci_pread(ap, AHCI_PREG_SACT);
+		if (sact) {
+			panic("ahci_port_err_ccb(%d) but SACT %08x != 0\n",
+			      ccb->ccb_slot, sact);
+		}
 	}
 	ci = ahci_pread(ap, AHCI_PREG_CI);
 	if (ci) {
@@ -2703,7 +2735,7 @@ ahci_port_read_ncq_error(struct ahci_port *ap, int target)
 	ccb->ccb_xa.data = ap->ap_err_scratch;
 	ccb->ccb_xa.datalen = 512;
 	ccb->ccb_xa.complete = ahci_dummy_done;
-	ccb->ccb_xa.at = &ap->ap_ata[target];
+	ccb->ccb_xa.at = ap->ap_ata[target];
 
 	fis = (struct ata_fis_h2d *)ccb->ccb_cmd_table->cfis;
 	bzero(fis, sizeof(*fis));
diff --git a/sys/dev/disk/ahci/ahci.h b/sys/dev/disk/ahci/ahci.h
index 67d8101..dd603a9 100644
--- a/sys/dev/disk/ahci/ahci.h
+++ b/sys/dev/disk/ahci/ahci.h
@@ -410,7 +410,7 @@ struct ahci_port {
 
 	int			ap_type;	/* ATA_PORT_T_xxx */
 	int			ap_probe;	/* ATA_PROBE_xxx */
-	struct ata_port		*ap_ata;
+	struct ata_port		*ap_ata[AHCI_MAX_PMPORTS];
 
 	u_int32_t		ap_state;
 #define AP_S_NORMAL			0
diff --git a/sys/dev/disk/ahci/ahci_cam.c b/sys/dev/disk/ahci/ahci_cam.c
index a18328b..0df5f82 100644
--- a/sys/dev/disk/ahci/ahci_cam.c
+++ b/sys/dev/disk/ahci/ahci_cam.c
@@ -251,7 +251,7 @@ ahci_cam_probe(struct ahci_port *ap, struct ata_port *atx)
 	 * an (at) pointing to target 0.
 	 */
 	if (atx == NULL) {
-		at = ap->ap_ata;	/* direct attached - device 0 */
+		at = ap->ap_ata[0];	/* direct attached - device 0 */
 		if (ap->ap_type == ATA_PORT_T_PM) {
 			kprintf("%s: Found Port Multiplier\n",
 				ATANAME(ap, atx));
@@ -492,7 +492,7 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
 	struct ata_port *at;
 	struct ata_xfer	*xa;
 
-	at = atx ? atx : ap->ap_ata;
+	at = atx ? atx : ap->ap_ata[0];
 
 	/*
 	 * Enable write cache if supported
@@ -509,11 +509,11 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
 		xa = ahci_ata_get_xfer(ap, atx);
 		xa->complete = ahci_ata_dummy_done;
 		xa->fis->command = ATA_C_SET_FEATURES;
-		/*xa->fis->features = ATA_SF_WRITECACHE_EN;*/
-		xa->fis->features = ATA_SF_LOOKAHEAD_EN;
+		xa->fis->features = ATA_SF_WRITECACHE_EN;
+		/* xa->fis->features = ATA_SF_LOOKAHEAD_EN; */
 		xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
 		xa->fis->device = 0;
-		xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
+		xa->flags = ATA_F_PIO | ATA_F_POLL;
 		xa->timeout = 1000;
 		xa->datalen = 0;
 		if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
@@ -535,7 +535,7 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
 		xa->fis->features = ATA_SF_LOOKAHEAD_EN;
 		xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
 		xa->fis->device = 0;
-		xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
+		xa->flags = ATA_F_PIO | ATA_F_POLL;
 		xa->timeout = 1000;
 		xa->datalen = 0;
 		if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
@@ -560,7 +560,7 @@ ahci_cam_probe_disk(struct ahci_port *ap, struct ata_port *atx)
 		xa->complete = ahci_ata_dummy_done;
 		xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
 		xa->fis->flags = ATA_H2D_FLAGS_CMD | at->at_target;
-		xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
+		xa->flags = ATA_F_PIO | ATA_F_POLL;
 		xa->timeout = 1000;
 		xa->datalen = 0;
 		if (ahci_ata_cmd(xa) == ATA_S_COMPLETE)
@@ -651,7 +651,7 @@ ahci_cam_rescan(struct ahci_port *ap)
 	}
 	ap->ap_flags |= AP_F_SCAN_RUNNING;
 	for (i = 0; i < AHCI_MAX_PMPORTS; ++i) {
-		ap->ap_ata[i].at_features |= ATA_PORT_F_RESCAN;
+		ap->ap_ata[i]->at_features |= ATA_PORT_F_RESCAN;
 	}
 
 	status = xpt_create_path(&path, xpt_periph, cam_sim_path(ap->ap_sim),
@@ -703,7 +703,6 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
 
 	/* XXX lock */
 	ap = cam_sim_softc(sim);
-	at = ap->ap_ata;
 	atx = NULL;
 	KKASSERT(ap != NULL);
 	ccbh = &ccb->ccb_h;
@@ -738,7 +737,7 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
 			xpt_done(ccb);
 			return;
 		}
-		at += ccbh->target_id;
+		at = ap->ap_ata[ccbh->target_id];
 		if (ap->ap_type == ATA_PORT_T_PM)
 			atx = at;
 
@@ -747,6 +746,8 @@ ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
 			xpt_done(ccb);
 			return;
 		}
+	} else {
+		at = ap->ap_ata[0];
 	}
 
 	/*
@@ -931,7 +932,7 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
 
 	ccbh = &ccb->csio.ccb_h;
 	csio = &ccb->csio;
-	at = atx ? atx : &ap->ap_ata[0];
+	at = atx ? atx : ap->ap_ata[0];
 
 	/*
 	 * XXX not passing NULL at for direct attach!
@@ -1032,7 +1033,7 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
 		if (xa->timeout < 45000)
 			xa->timeout = 45000;
 		xa->datalen = 0;
-		xa->flags = ATA_F_READ;
+		xa->flags = 0;
 		xa->complete = ahci_ata_complete_disk_synchronize_cache;
 		break;
 	case TEST_UNIT_READY:
@@ -1204,7 +1205,7 @@ ahci_xpt_scsi_atapi_io(struct ahci_port *ap, struct ata_port *atx,
 
 	ccbh = &ccb->csio.ccb_h;
 	csio = &ccb->csio;
-	at = atx ? atx : &ap->ap_ata[0];
+	at = atx ? atx : ap->ap_ata[0];
 
 	switch (ccbh->flags & CAM_DIR_MASK) {
 	case CAM_DIR_IN:
diff --git a/sys/dev/disk/ahci/ahci_pm.c b/sys/dev/disk/ahci/ahci_pm.c
index 4d1cb5d..47be498 100644
--- a/sys/dev/disk/ahci/ahci_pm.c
+++ b/sys/dev/disk/ahci/ahci_pm.c
@@ -119,7 +119,7 @@ retry:
 	ccb = ahci_get_err_ccb(ap);
 	ccb->ccb_xa.flags = ATA_F_POLL;
 	ccb->ccb_xa.complete = ahci_pm_dummy_done;
-	ccb->ccb_xa.at = &ap->ap_ata[15];
+	ccb->ccb_xa.at = ap->ap_ata[15];
 	cmd_slot = ccb->ccb_cmd_hdr;
 	KKASSERT(ccb->ccb_slot == 1);
 
@@ -213,7 +213,7 @@ retry:
 	 * Get the signature.  The caller sets the ap fields.
 	 */
 	if (ahci_port_signature_detect(ap, NULL) == ATA_PORT_T_PM) {
-		ap->ap_ata[15].at_probe = ATA_PROBE_GOOD;
+		ap->ap_ata[15]->at_probe = ATA_PROBE_GOOD;
 		error = 0;
 	} else {
 		error = EBUSY;
@@ -238,7 +238,7 @@ err:
 	 */
 	if (error == 0) {
 		for (i = 0; i < AHCI_MAX_PMPORTS; ++i) {
-			at = &ap->ap_ata[i];
+			at = ap->ap_ata[i];
 			at->at_probe = ATA_PROBE_NEED_INIT;
 			at->at_features |= ATA_PORT_F_RESCAN;
 		}
@@ -381,7 +381,7 @@ ahci_pm_hardreset(struct ahci_port *ap, int target, int hard)
 	int loop;
 	int error = EIO;
 
-	at = &ap->ap_ata[target];
+	at = ap->ap_ata[target];
 
 	/*
 	 * Turn off power management and kill the phy on the target
@@ -514,7 +514,7 @@ ahci_pm_softreset(struct ahci_port *ap, int target)
 	int			tried_longer;
 
 	error = EIO;
-	at = &ap->ap_ata[target];
+	at = ap->ap_ata[target];
 
 	DPRINTF(AHCI_D_VERBOSE, "%s: soft reset\n", PORTNAME(ap));
 
@@ -720,7 +720,7 @@ ahci_pm_set_feature(struct ahci_port *ap, int feature, int enable)
 	struct ata_xfer	*xa;
 	int error;
 
-	xa = ahci_ata_get_xfer(ap, &ap->ap_ata[15]);
+	xa = ahci_ata_get_xfer(ap, ap->ap_ata[15]);
 
 	xa->fis->type = ATA_FIS_TYPE_H2D;
 	xa->fis->flags = ATA_H2D_FLAGS_CMD | 15;
@@ -767,7 +767,7 @@ ahci_pm_check_good(struct ahci_port *ap, int target)
 
 	if (target == CAM_TARGET_WILDCARD || target >= ap->ap_pmcount)
 		return;
-	at = &ap->ap_ata[target];
+	at = ap->ap_ata[target];
 
 	/*
 	 * If the device needs an init or hard reset also make sure the
@@ -814,7 +814,7 @@ ahci_pm_read(struct ahci_port *ap, int target, int which, u_int32_t *datap)
 	struct ata_xfer	*xa;
 	int error;
 
-	xa = ahci_ata_get_xfer(ap, &ap->ap_ata[15]);
+	xa = ahci_ata_get_xfer(ap, ap->ap_ata[15]);
 
 	xa->fis->type = ATA_FIS_TYPE_H2D;
 	xa->fis->flags = ATA_H2D_FLAGS_CMD | 15;
@@ -851,7 +851,7 @@ ahci_pm_write(struct ahci_port *ap, int target, int which, u_int32_t data)
 	struct ata_xfer	*xa;
 	int error;
 
-	xa = ahci_ata_get_xfer(ap, &ap->ap_ata[15]);
+	xa = ahci_ata_get_xfer(ap, ap->ap_ata[15]);
 
 	xa->fis->type = ATA_FIS_TYPE_H2D;
 	xa->fis->flags = ATA_H2D_FLAGS_CMD | 15;
