aac driver patch for FreeBSD 8.2

Achim Leubner Achim_Leubner at pmc-sierra.com
Tue Apr 5 15:55:38 UTC 2011


Hi Ed, Hi Scott,

 

Attached you find an aac driver patch to support PMC-Sierra's SRC based controller family. It includes the following changes:

-          New hardware device id 0x28b interface 

-          New XPORT header required

-          Sync. command interface: small changes, doorbell bits shifted

-          Async. Interface: different inbound queue handling, no outbound I2O queue available, using doorbell and response buffer in host memory for status

-          Changed AIF (adapter initiated FIB) interface 

-          Passthrough (raw_srb) IOCTL handling changed

 

The driver package shipped with the new controller family  is tested in an release cycle and I adapted the changes to the FreeBSD 8.2 inbox driver because we want to become inbox with that driver as soon as possible. 

Any comments are greatly appreciated.

 

Thanks,

Achim

 

Achim Leubner

Firmware Design Engineer

PMC-Sierra Germany GmbH

Sitz/Registered Office: Ismaning bei Muenchen

Amtsgericht/Local Court Muenchen, HRB 189193

Geschäftsführer/Managing Director: Michael W. Zellner

 

-------------- next part --------------
diff -pruN old/aac.c new/aac.c
--- old/aac.c	2011-03-31 14:57:34.000000000 +0000
+++ new/aac.c	2011-04-01 12:42:49.000000000 +0000
@@ -2,7 +2,8 @@
  * Copyright (c) 2000 Michael Smith
  * Copyright (c) 2001 Scott Long
  * Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Adaptec, Inc.
+ * Copyright (c) 2001-2010 Adaptec, Inc.
+ * Copyright (c) 2010 PMC-Sierra, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -97,7 +98,7 @@ static int	aac_check_firmware(struct aac
 static int	aac_init(struct aac_softc *sc);
 static int	aac_sync_command(struct aac_softc *sc, u_int32_t command,
 				 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
-				 u_int32_t arg3, u_int32_t *sp);
+				 u_int32_t arg3, u_int32_t *sp, u_int32_t *r1);
 static int	aac_setup_intr(struct aac_softc *sc);
 static int	aac_enqueue_fib(struct aac_softc *sc, int queue,
 				struct aac_command *cm);
@@ -182,6 +183,33 @@ struct aac_interface aac_rkt_interface =
 	aac_rkt_set_outb_queue
 };
 
+/* PMC SRC interface */
+static int	aac_src_get_fwstatus(struct aac_softc *sc);
+static void	aac_src_qnotify(struct aac_softc *sc, int qbit);
+static int	aac_src_get_istatus(struct aac_softc *sc);
+static void	aac_src_clear_istatus(struct aac_softc *sc, int mask);
+static void	aac_src_set_mailbox(struct aac_softc *sc, u_int32_t command,
+				    u_int32_t arg0, u_int32_t arg1,
+				    u_int32_t arg2, u_int32_t arg3);
+static int	aac_src_get_mailbox(struct aac_softc *sc, int mb);
+static void	aac_src_set_interrupts(struct aac_softc *sc, int enable);
+static int aac_src_send_command(struct aac_softc *sc, struct aac_command *cm);
+static int aac_src_get_outb_queue(struct aac_softc *sc);
+static void aac_src_set_outb_queue(struct aac_softc *sc, int index);
+
+struct aac_interface aac_src_interface = {
+	aac_src_get_fwstatus,
+	aac_src_qnotify,
+	aac_src_get_istatus,
+	aac_src_clear_istatus,
+	aac_src_set_mailbox,
+	aac_src_get_mailbox,
+	aac_src_set_interrupts,
+	aac_src_send_command,
+	aac_src_get_outb_queue,
+	aac_src_set_outb_queue
+};
+
 /* Debugging and Diagnostics */
 static void	aac_describe_controller(struct aac_softc *sc);
 static char	*aac_describe_code(struct aac_code_lookup *table,
@@ -196,6 +224,7 @@ static int		aac_ioctl_sendfib(struct aac
 static int		aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg);
 static void		aac_handle_aif(struct aac_softc *sc,
 					   struct aac_fib *fib);
+static void		aac_request_aif(struct aac_softc *sc);
 static int		aac_rev_check(struct aac_softc *sc, caddr_t udata);
 static int		aac_open_aif(struct aac_softc *sc, caddr_t arg);
 static int		aac_close_aif(struct aac_softc *sc, caddr_t arg);
@@ -207,8 +236,11 @@ static int		aac_get_pci_info(struct aac_
 static int		aac_supported_features(struct aac_softc *sc, caddr_t uptr);
 static void		aac_ioctl_event(struct aac_softc *sc,
 					struct aac_event *event, void *arg);
+static int		aac_reset_adapter(struct aac_softc *sc);
 static struct aac_mntinforesp *
 	aac_get_container_info(struct aac_softc *sc, struct aac_fib *fib, int cid);
+static u_int32_t
+	aac_check_adapter_health(struct aac_softc *sc, u_int8_t *bled);
 
 static struct cdevsw aac_cdevsw = {
 	.d_version =	D_VERSION,
@@ -237,7 +269,7 @@ aac_attach(struct aac_softc *sc)
 	int error, unit;
 
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
-
+	sc->hint_flags = device_get_flags(sc->aac_dev);
 	/*
 	 * Initialize per-controller queues.
 	 */
@@ -487,6 +519,7 @@ aac_add_container(struct aac_softc *sc, 
 static int
 aac_alloc(struct aac_softc *sc)
 {
+	bus_size_t maxsize;
 
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
@@ -514,6 +547,11 @@ aac_alloc(struct aac_softc *sc)
 	/*
 	 * Create DMA tag for mapping FIBs into controller-addressable space..
 	 */
+	if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) 
+		maxsize = sc->aac_max_fibs_alloc * (sc->aac_max_fib_size +
+			sizeof(struct aac_fib_xporthdr) + 31);
+	else
+		maxsize = sc->aac_max_fibs_alloc * sc->aac_max_fib_size;
 	if (bus_dma_tag_create(sc->aac_parent_dmat,	/* parent */
 			       1, 0, 			/* algnmnt, boundary */
 			       (sc->flags & AAC_FLAGS_4GB_WINDOW) ?
@@ -521,11 +559,9 @@ aac_alloc(struct aac_softc *sc)
 			       0x7fffffff,		/* lowaddr */
 			       BUS_SPACE_MAXADDR, 	/* highaddr */
 			       NULL, NULL, 		/* filter, filterarg */
-			       sc->aac_max_fibs_alloc *
-			       sc->aac_max_fib_size,  /* maxsize */
+			       maxsize,  		/* maxsize */
 			       1,			/* nsegments */
-			       sc->aac_max_fibs_alloc *
-			       sc->aac_max_fib_size,	/* maxsize */
+			       maxsize,			/* maxsize */
 			       0,			/* flags */
 			       NULL, NULL,		/* No locking needed */
 			       &sc->aac_fib_dmat)) {
@@ -536,6 +572,9 @@ aac_alloc(struct aac_softc *sc)
 	/*
 	 * Create DMA tag for the common structure and allocate it.
 	 */
+	maxsize = 8192 + sizeof(struct aac_common);
+	if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) 
+		maxsize += sc->aac_max_fibs * sizeof(u_int32_t);
 	if (bus_dma_tag_create(sc->aac_parent_dmat, 	/* parent */
 			       1, 0,			/* algnmnt, boundary */
 			       (sc->flags & AAC_FLAGS_4GB_WINDOW) ?
@@ -543,9 +582,9 @@ aac_alloc(struct aac_softc *sc)
 			       0x7fffffff,		/* lowaddr */
 			       BUS_SPACE_MAXADDR, 	/* highaddr */
 			       NULL, NULL, 		/* filter, filterarg */
-			       8192 + sizeof(struct aac_common), /* maxsize */
+			       maxsize, 		/* maxsize */
 			       1,			/* nsegments */
-			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
+			       maxsize,			/* maxsegsize */
 			       0,			/* flags */
 			       NULL, NULL,		/* No locking needed */
 			       &sc->aac_common_dmat)) {
@@ -566,7 +605,7 @@ aac_alloc(struct aac_softc *sc)
 	 * of ignored?
 	 */
 	(void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap,
-			sc->aac_common, 8192 + sizeof(*sc->aac_common),
+			sc->aac_common, maxsize,
 			aac_common_map, sc, 0);
 
 	if (sc->aac_common_busaddr < 8192) {
@@ -574,7 +613,7 @@ aac_alloc(struct aac_softc *sc)
 		    ((uint8_t *)sc->aac_common + 8192);
 		sc->aac_common_busaddr += 8192;
 	}
-	bzero(sc->aac_common, sizeof(*sc->aac_common));
+	bzero(sc->aac_common, maxsize - 8192);
 
 	/* Allocate some FIBs and associated command structs */
 	TAILQ_INIT(&sc->aac_fibmap_tqh);
@@ -640,7 +679,8 @@ aac_free(struct aac_softc *sc)
 	if (sc->aac_regs_res0 != NULL)
 		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
 				     sc->aac_regs_rid0, sc->aac_regs_res0);
-	if (sc->aac_hwif == AAC_HWIF_NARK && sc->aac_regs_res1 != NULL)
+	if ((sc->aac_hwif == AAC_HWIF_SRC || sc->aac_hwif == AAC_HWIF_NARK)
+		&& sc->aac_regs_res1 != NULL)
 		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
 				     sc->aac_regs_rid1, sc->aac_regs_res1);
 }
@@ -800,6 +840,107 @@ aac_resume(device_t dev)
 }
 
 /*
+ * Interrupt handler for NEW_COMM_TYPE1 interface.
+ */
+void
+aac_new_intr_type1(void *arg)
+{
+	struct aac_softc *sc;
+	struct aac_command *cm;
+	struct aac_fib *fib;
+	u_int32_t bellbits, bellbits_shifted, index, handle;
+	int isFastResponse, isAif, noMoreAif;
+	int our_interrupt = 0;
+
+	sc = (struct aac_softc *)arg;
+
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+	mtx_lock(&sc->aac_io_lock);
+	bellbits = AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R);
+	if (bellbits & AAC_DB_RESPONSE_SENT_NS) {
+		bellbits = AAC_DB_RESPONSE_SENT_NS;
+		/* handle async. status */
+		our_interrupt = 1;
+		index = sc->aac_host_rrq_idx;
+		if (sc->aac_common->ac_host_rrq[index] == 0) {
+			u_int32_t old_index = index;
+			/* adjust index */
+			do {
+				index++;
+				if (index == sc->aac_max_fibs) 
+					index = 0;
+				if (sc->aac_common->ac_host_rrq[index] != 0) 
+					break;
+			} while (index != old_index);
+			sc->aac_host_rrq_idx = index;
+		}
+		for (;;) {
+			isFastResponse = isAif = noMoreAif = 0;
+			/* remove toggle bit (31) */
+			handle = (sc->aac_common->ac_host_rrq[index] & 0x7fffffff);
+			/* check fast response bit (30) */
+			if (handle & 0x40000000) 
+				isFastResponse = 1;
+			/* check AIF bit (23) */
+			else if (handle & 0x00800000) 
+				isAif = TRUE;
+			handle &= 0x0000ffff;
+			if (handle == 0) 
+				break;
+
+			cm = sc->aac_commands + (handle - 1);
+			fib = cm->cm_fib;
+			if (isAif) {
+				noMoreAif = (fib->Header.XferState & AAC_FIBSTATE_NOMOREAIF) ? 1:0;
+				if (!noMoreAif) 
+					aac_handle_aif(sc, fib);
+				aac_remove_busy(cm);
+				aac_release_command(cm);
+			} else {
+				if (isFastResponse) {
+					fib->Header.XferState |= AAC_FIBSTATE_DONEADAP;
+					*((u_int32_t *)(fib->data)) = AAC_ERROR_NORMAL;
+				}
+				aac_remove_busy(cm);
+				aac_unmap_command(cm);
+				cm->cm_flags |= AAC_CMD_COMPLETED;
+
+				/* is there a completion handler? */
+				if (cm->cm_complete != NULL) {
+					cm->cm_complete(cm);
+				} else {
+					/* assume that someone is sleeping on this command */
+					wakeup(cm);
+				}
+				sc->flags &= ~AAC_QUEUE_FRZN;
+			}
+
+			sc->aac_common->ac_host_rrq[index++] = 0;
+			if (index == sc->aac_max_fibs) 
+				index = 0;
+			sc->aac_host_rrq_idx = index;
+
+			if ((isAif && !noMoreAif) || sc->aif_pending) 
+				aac_request_aif(sc);
+		}
+	} else {
+		bellbits_shifted = (bellbits >> AAC_SRC_ODR_SHIFT);
+		if (bellbits_shifted & AAC_DB_AIF_PENDING) {
+			our_interrupt = 1;
+			/* handle AIF */
+			aac_request_aif(sc);
+		}
+    }
+	if (our_interrupt) 
+		AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, bellbits);
+
+	/* see if we can start some more I/O */
+	if ((sc->flags & AAC_QUEUE_FRZN) == 0)
+		aac_startio(sc);
+	mtx_unlock(&sc->aac_io_lock);
+}
+
+/*
  * Interrupt handler for NEW_COMM interface.
  */
 void
@@ -945,6 +1086,8 @@ aac_startio(struct aac_softc *sc)
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
 	for (;;) {
+		if (sc->aac_state & AAC_STATE_RESET)
+			break;
 		/*
 		 * This flag might be set if the card is out of resources.
 		 * Checking it here prevents an infinite loop of deferrals.
@@ -1190,6 +1333,16 @@ aac_bio_command(struct aac_softc *sc, st
 	if ((bp = aac_dequeue_bio(sc)) == NULL)
 		goto fail;
 
+	ad = (struct aac_disk *)bp->bio_disk->d_drv1;
+	/* container still valid? */
+	if (ad->ad_container == NULL) {
+		bp->bio_flags |= BIO_ERROR;
+		bp->bio_error = EINVAL;
+		biodone(bp);
+		bp = NULL;
+		goto fail;
+	}
+
 	/* fill out the command */
 	cm->cm_data = (void *)bp->bio_data;
 	cm->cm_datalen = bp->bio_bcount;
@@ -1211,8 +1364,6 @@ aac_bio_command(struct aac_softc *sc, st
 		AAC_FIBSTATE_FAST_RESPONSE;
 
 	/* build the read/write request */
-	ad = (struct aac_disk *)bp->bio_disk->d_drv1;
-
 	if (sc->flags & AAC_FLAGS_RAW_IO) {
 		struct aac_raw_io *raw;
 		raw = (struct aac_raw_io *)&fib->data[0];
@@ -1308,7 +1459,9 @@ aac_bio_complete(struct aac_command *cm)
 
 	/* fetch relevant status and then release the command */
 	bp = (struct bio *)cm->cm_private;
-	if (bp->bio_cmd == BIO_READ) {
+	if (cm->cm_flags & AAC_CMD_RESET) {
+		status = ST_BUS_RESET;
+	} else if (bp->bio_cmd == BIO_READ) {
 		brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
 		status = brr->Status;
 	} else {
@@ -1321,7 +1474,7 @@ aac_bio_complete(struct aac_command *cm)
 	if (status == ST_OK) {
 		bp->bio_resid = 0;
 	} else {
-		bp->bio_error = EIO;
+		bp->bio_error = (status == ST_NOT_READY ? EBUSY : EIO);
 		bp->bio_flags |= BIO_ERROR;
 		/* pass an error string out to the disk layer */
 		bp->bio_driver1 = aac_describe_code(aac_command_status_table,
@@ -1400,6 +1553,7 @@ aac_release_command(struct aac_command *
 	cm->cm_complete = NULL;
 	cm->cm_private = NULL;
 	cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
+	cm->cm_passthr_dmat = 0;
 	cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
 	cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
 	cm->cm_fib->Header.Flags = 0;
@@ -1448,6 +1602,7 @@ aac_alloc_commands(struct aac_softc *sc)
 	struct aac_fibmap *fm;
 	uint64_t fibphys;
 	int i, error;
+	u_int32_t maxsize;
 
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
@@ -1467,27 +1622,40 @@ aac_alloc_commands(struct aac_softc *sc)
 		return (ENOMEM);
 	}
 
+	maxsize = sc->aac_max_fib_size;
+	if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) 
+		maxsize += sizeof(struct aac_fib_xporthdr) + 31;
+
 	/* Ignore errors since this doesn't bounce */
 	(void)bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs,
-			      sc->aac_max_fibs_alloc * sc->aac_max_fib_size,
+			      sc->aac_max_fibs_alloc * maxsize,
 			      aac_map_command_helper, &fibphys, 0);
 
 	/* initialize constant fields in the command structure */
-	bzero(fm->aac_fibs, sc->aac_max_fibs_alloc * sc->aac_max_fib_size);
+	bzero(fm->aac_fibs, sc->aac_max_fibs_alloc * maxsize);
 	for (i = 0; i < sc->aac_max_fibs_alloc; i++) {
 		cm = sc->aac_commands + sc->total_fibs;
 		fm->aac_commands = cm;
 		cm->cm_sc = sc;
 		cm->cm_fib = (struct aac_fib *)
-			((u_int8_t *)fm->aac_fibs + i*sc->aac_max_fib_size);
-		cm->cm_fibphys = fibphys + i*sc->aac_max_fib_size;
+			((u_int8_t *)fm->aac_fibs + i * maxsize);
+		cm->cm_fibphys = fibphys + i * maxsize;
+		if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) {
+			u_int64_t fibphys_aligned;
+			fibphys_aligned = 
+				(cm->cm_fibphys + sizeof(struct aac_fib_xporthdr) + 31) & ~31;
+			cm->cm_fib = (struct aac_fib *)
+				((u_int8_t *)cm->cm_fib + (fibphys_aligned - cm->cm_fibphys));
+			cm->cm_fibphys = fibphys_aligned;
+		}
 		cm->cm_index = sc->total_fibs;
 
 		if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0,
 					       &cm->cm_datamap)) != 0)
 			break;
 		mtx_lock(&sc->aac_io_lock);
-		aac_release_command(cm);
+		if (sc->aac_max_fibs <= 1 || sc->aac_max_fibs - sc->total_fibs > 1)
+			aac_release_command(cm);
 		sc->total_fibs++;
 		mtx_unlock(&sc->aac_io_lock);
 	}
@@ -1598,14 +1766,17 @@ aac_map_command_sg(void *arg, bus_dma_se
 	cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
 
 	/* save a pointer to the command for speedy reverse-lookup */
-	cm->cm_fib->Header.SenderData = cm->cm_index;
+	cm->cm_fib->Header.SenderData += cm->cm_index;
+
+	if (cm->cm_passthr_dmat == 0) {
+		if (cm->cm_flags & AAC_CMD_DATAIN)
+			bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
+							BUS_DMASYNC_PREREAD);
+		if (cm->cm_flags & AAC_CMD_DATAOUT)
+			bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
+							BUS_DMASYNC_PREWRITE);
+	}
 
-	if (cm->cm_flags & AAC_CMD_DATAIN)
-		bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
-				BUS_DMASYNC_PREREAD);
-	if (cm->cm_flags & AAC_CMD_DATAOUT)
-		bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
-				BUS_DMASYNC_PREWRITE);
 	cm->cm_flags |= AAC_CMD_MAPPED;
 
 	if (sc->flags & AAC_FLAGS_NEW_COMM) {
@@ -1644,7 +1815,7 @@ aac_unmap_command(struct aac_command *cm
 	if (!(cm->cm_flags & AAC_CMD_MAPPED))
 		return;
 
-	if (cm->cm_datalen != 0) {
+	if (cm->cm_datalen != 0 && cm->cm_passthr_dmat == 0) {
 		if (cm->cm_flags & AAC_CMD_DATAIN)
 			bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
 					BUS_DMASYNC_POSTREAD);
@@ -1678,7 +1849,8 @@ aac_common_map(void *arg, bus_dma_segmen
 static int
 aac_check_firmware(struct aac_softc *sc)
 {
-	u_int32_t code, major, minor, options = 0, atu_size = 0;
+	u_int32_t code, major, minor, maxsize;
+	u_int32_t options = 0, atu_size = 0;
 	int status;
 	time_t then;
 
@@ -1712,7 +1884,7 @@ aac_check_firmware(struct aac_softc *sc)
 	 */
 	if (sc->flags & AAC_FLAGS_PERC2QC) {
 		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
-				     NULL)) {
+				     NULL, NULL)) {
 			device_printf(sc->aac_dev,
 				      "Error reading firmware version\n");
 			return (EIO);
@@ -1728,13 +1900,12 @@ aac_check_firmware(struct aac_softc *sc)
 			return (EINVAL);
 		}
 	}
-
 	/*
 	 * Retrieve the capabilities/supported options word so we know what
 	 * work-arounds to enable.  Some firmware revs don't support this
 	 * command.
 	 */
-	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
+	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status, NULL)) {
 		if (status != AAC_SRB_STS_INVALID_REQUEST) {
 			device_printf(sc->aac_dev,
 			     "RequestAdapterInfo failed\n");
@@ -1751,14 +1922,18 @@ aac_check_firmware(struct aac_softc *sc)
 		if (options & AAC_SUPPORTED_NONDASD)
 			sc->flags |= AAC_FLAGS_ENABLE_CAM;
 		if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0
-		     && (sizeof(bus_addr_t) > 4)) {
+			&& (sizeof(bus_addr_t) > 4)
+			&& (sc->hint_flags & 0x1)) {
 			device_printf(sc->aac_dev,
 			    "Enabling 64-bit address support\n");
 			sc->flags |= AAC_FLAGS_SG_64BIT;
 		}
-		if ((options & AAC_SUPPORTED_NEW_COMM)
-		 && sc->aac_if.aif_send_command)
-			sc->flags |= AAC_FLAGS_NEW_COMM;
+		if (sc->aac_if.aif_send_command) {
+			if (options & AAC_SUPPORTED_NEW_COMM_TYPE1)
+				sc->flags |= AAC_FLAGS_NEW_COMM | AAC_FLAGS_NEW_COMM_TYPE1;
+			else if (options & AAC_SUPPORTED_NEW_COMM)
+				sc->flags |= AAC_FLAGS_NEW_COMM;
+		}
 		if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE)
 			sc->flags |= AAC_FLAGS_ARRAY_64BIT;
 	}
@@ -1767,39 +1942,71 @@ aac_check_firmware(struct aac_softc *sc)
 	sc->aac_max_fibs = (sc->flags & AAC_FLAGS_256FIBS ? 256:512);
 
 	/* Remap mem. resource, if required */
-	if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
-		atu_size > rman_get_size(sc->aac_regs_res1)) {
-		bus_release_resource(
-			sc->aac_dev, SYS_RES_MEMORY,
-			sc->aac_regs_rid1, sc->aac_regs_res1);
-		sc->aac_regs_res1 = bus_alloc_resource(
-			sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid1,
-			0ul, ~0ul, atu_size, RF_ACTIVE);
-		if (sc->aac_regs_res1 == NULL) {
-			sc->aac_regs_res1 = bus_alloc_resource_any(
+	if (sc->aac_hwif == AAC_HWIF_NARK) {
+		if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
+			atu_size > rman_get_size(sc->aac_regs_res1)) {
+			bus_release_resource(
 				sc->aac_dev, SYS_RES_MEMORY,
-				&sc->aac_regs_rid1, RF_ACTIVE);
+				sc->aac_regs_rid1, sc->aac_regs_res1);
+			sc->aac_regs_res1 = bus_alloc_resource(
+				sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid1,
+				0ul, ~0ul, atu_size, RF_ACTIVE);
 			if (sc->aac_regs_res1 == NULL) {
-				device_printf(sc->aac_dev,
-				    "couldn't allocate register window\n");
-				return (ENXIO);
+				sc->aac_regs_res1 = bus_alloc_resource_any(
+					sc->aac_dev, SYS_RES_MEMORY,
+					&sc->aac_regs_rid1, RF_ACTIVE);
+				if (sc->aac_regs_res1 == NULL) {
+					device_printf(sc->aac_dev,
+						"couldn't allocate register window\n");
+					return (ENXIO);
+				}
+				sc->flags &= ~AAC_FLAGS_NEW_COMM;
 			}
-			sc->flags &= ~AAC_FLAGS_NEW_COMM;
+			sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1);
+			sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1);
 		}
-		sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1);
-		sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1);
-
-		if (sc->aac_hwif == AAC_HWIF_NARK) {
-			sc->aac_regs_res0 = sc->aac_regs_res1;
-			sc->aac_regs_rid0 = sc->aac_regs_rid1;
-			sc->aac_btag0 = sc->aac_btag1;
-			sc->aac_bhandle0 = sc->aac_bhandle1;
+	} else {
+		if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
+			atu_size > rman_get_size(sc->aac_regs_res0)) {
+			bus_release_resource(
+				sc->aac_dev, SYS_RES_MEMORY,
+				sc->aac_regs_rid0, sc->aac_regs_res0);
+			sc->aac_regs_res0 = bus_alloc_resource(
+				sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid0,
+				0ul, ~0ul, atu_size, RF_ACTIVE);
+			if (sc->aac_regs_res0 == NULL) {
+				sc->aac_regs_res0 = bus_alloc_resource_any(
+					sc->aac_dev, SYS_RES_MEMORY,
+					&sc->aac_regs_rid0, RF_ACTIVE);
+				if (sc->aac_regs_res0 == NULL) {
+					device_printf(sc->aac_dev,
+						"couldn't allocate register window\n");
+					return (ENXIO);
+				}
+				sc->flags &= ~AAC_FLAGS_NEW_COMM;
+			}
+			sc->aac_btag0 = rman_get_bustag(sc->aac_regs_res0);
+			sc->aac_bhandle0 = rman_get_bushandle(sc->aac_regs_res0);
+		}
+		if (sc->aac_hwif != AAC_HWIF_SRC) {
+			sc->aac_regs_res1 = sc->aac_regs_res0;
+			sc->aac_regs_rid1 = sc->aac_regs_rid0;
+			sc->aac_btag1 = sc->aac_btag0;
+			sc->aac_bhandle1 = sc->aac_bhandle0;
 		}
 	}
 
+	if (sc->aac_hwif == AAC_HWIF_SRC && 
+		!(sc->flags & AAC_FLAGS_NEW_COMM_TYPE1)) {
+		device_printf(sc->aac_dev,
+			"invalid command interface for that controller family!\n");
+		return (EINVAL);
+	}
+
 	/* Read preferred settings */
 	sc->aac_max_fib_size = sizeof(struct aac_fib);
 	sc->aac_max_sectors = 128;				/* 64KB */
+	sc->aac_max_aif = 1;
 	if (sc->flags & AAC_FLAGS_SG_64BIT)
 		sc->aac_sg_tablesize = (AAC_FIB_DATASIZE
 		 - sizeof(struct aac_blockwrite64))
@@ -1809,7 +2016,7 @@ aac_check_firmware(struct aac_softc *sc)
 		 - sizeof(struct aac_blockwrite))
 		 / sizeof(struct aac_sg_entry);
 
-	if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
+	if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL, NULL)) {
 		options = AAC_GET_MAILBOX(sc, 1);
 		sc->aac_max_fib_size = (options & 0xFFFF);
 		sc->aac_max_sectors = (options >> 16) << 1;
@@ -1817,10 +2024,18 @@ aac_check_firmware(struct aac_softc *sc)
 		sc->aac_sg_tablesize = (options >> 16);
 		options = AAC_GET_MAILBOX(sc, 3);
 		sc->aac_max_fibs = (options & 0xFFFF);
+		options = AAC_GET_MAILBOX(sc, 4);
+		sc->aac_max_aif = (options & 0xFFFF);
+	}
+
+	maxsize = sc->aac_max_fib_size;
+	if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) 
+		maxsize += sizeof(struct aac_fib_xporthdr) + 31;
+	if (maxsize > PAGE_SIZE) {
+    	sc->aac_max_fib_size -= (maxsize - PAGE_SIZE);
+		maxsize = PAGE_SIZE;
 	}
-	if (sc->aac_max_fib_size > PAGE_SIZE)
-		sc->aac_max_fib_size = PAGE_SIZE;
-	sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size;
+	sc->aac_max_fibs_alloc = PAGE_SIZE / maxsize;
 
 	if (sc->aac_max_fib_size > sizeof(struct aac_fib)) {
 		sc->flags |= AAC_FLAGS_RAW_IO;
@@ -1880,10 +2095,28 @@ aac_init(struct aac_softc *sc)
 	ip->HostElapsedSeconds = time_uptime;	/* reset later if invalid */
 
 	ip->InitFlags = 0;
-	if (sc->flags & AAC_FLAGS_NEW_COMM) {
+	if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) {
+		ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_6;
+		ip->InitFlags |= AAC_INITFLAGS_NEW_COMM_TYPE1_SUPPORTED;
+		device_printf(sc->aac_dev, "New comm. interface type1 enabled\n");
+	} else if (sc->flags & AAC_FLAGS_NEW_COMM) {
 		ip->InitFlags |= AAC_INITFLAGS_NEW_COMM_SUPPORTED;
 		device_printf(sc->aac_dev, "New comm. interface enabled\n");
 	}
+	ip->MaxNumAif = sc->aac_max_aif;
+	ip->HostRRQ_AddrLow = 
+		sc->aac_common_busaddr + offsetof(struct aac_common, ac_host_rrq);
+	/* always 32-bit address */
+	ip->HostRRQ_AddrHigh = 0;
+
+	/* ADPml10863: Disable Power Management support */
+	sc->aac_support_opt2 &= ~AAC_SUPPORTED_POWER_MANAGEMENT;
+
+	if (sc->aac_support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) {
+		ip->InitFlags |= AAC_INITFLAGS_DRIVER_SUPPORTS_PM;
+		ip->InitFlags |= AAC_INITFLAGS_DRIVER_USES_UTC_TIME;
+		device_printf(sc->aac_dev, "Power Management enabled\n");
+	}
 
 	ip->MaxIoCommands = sc->aac_max_fibs;
 	ip->MaxIoSize = sc->aac_max_sectors << 9;
@@ -1970,6 +2203,9 @@ aac_init(struct aac_softc *sc)
 	case AAC_HWIF_RKT:
 		AAC_MEM0_SETREG4(sc, AAC_RKT_ODBR, ~0);
 		break;
+	case AAC_HWIF_SRC:
+		AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, ~0);
+		break;
 	default:
 		break;
 	}
@@ -1980,7 +2216,7 @@ aac_init(struct aac_softc *sc)
 	if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
 			     sc->aac_common_busaddr +
 			     offsetof(struct aac_common, ac_init), 0, 0, 0,
-			     NULL)) {
+			     NULL, NULL)) {
 		device_printf(sc->aac_dev,
 			      "error establishing init structure\n");
 		error = EIO;
@@ -2003,7 +2239,14 @@ aac_setup_intr(struct aac_softc *sc)
 		device_printf(sc->aac_dev, "can't allocate interrupt\n");
 		return (EINVAL);
 	}
-	if (sc->flags & AAC_FLAGS_NEW_COMM) {
+	if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1) {
+		if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
+				   INTR_MPSAFE|INTR_TYPE_BIO, NULL, 
+				   aac_new_intr_type1, sc, &sc->aac_intr)) {
+			device_printf(sc->aac_dev, "can't set up interrupt\n");
+			return (EINVAL);
+		}
+	} else if (sc->flags & AAC_FLAGS_NEW_COMM) {
 		if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
 				   INTR_MPSAFE|INTR_TYPE_BIO, NULL, 
 				   aac_new_intr, sc, &sc->aac_intr)) {
@@ -2029,7 +2272,7 @@ aac_setup_intr(struct aac_softc *sc)
 static int
 aac_sync_command(struct aac_softc *sc, u_int32_t command,
 		 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3,
-		 u_int32_t *sp)
+		 u_int32_t *sp, u_int32_t *r1)
 {
 	time_t then;
 	u_int32_t status;
@@ -2062,6 +2305,10 @@ aac_sync_command(struct aac_softc *sc, u
 	if (sp != NULL)
 		*sp = status;
 
+	/* return parameter */
+	if (r1 != NULL) 
+		*r1 = AAC_GET_MAILBOX(sc, 0);
+
 	if (status != AAC_SRB_STS_SUCCESS)
 		return (-1);
 	return(0);
@@ -2097,7 +2344,7 @@ aac_sync_fib(struct aac_softc *sc, u_int
 	 * Give the FIB to the controller, wait for a response.
 	 */
 	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
-			     fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
+			     fib->Header.ReceiverFibAddress, 0, 0, 0, NULL, NULL)) {
 		fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "IO error");
 		return(EIO);
 	}
@@ -2349,12 +2596,11 @@ aac_timeout(struct aac_softc *sc)
 	deadline = time_uptime - AAC_CMD_TIMEOUT;
 	TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
 		if ((cm->cm_timestamp  < deadline)
-		    && !(cm->cm_flags & AAC_CMD_TIMEDOUT)) {
+			/* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
 			cm->cm_flags |= AAC_CMD_TIMEDOUT;
 			device_printf(sc->aac_dev,
-			    "COMMAND %p (TYPE %d) TIMEOUT AFTER %d SECONDS\n",
-			    cm, cm->cm_fib->Header.Command,
-			    (int)(time_uptime-cm->cm_timestamp));
+				      "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
+				      cm, (int)(time_uptime-cm->cm_timestamp));
 			AAC_PRINT_FIB(sc, cm->cm_fib);
 			timedout++;
 		}
@@ -2365,6 +2611,7 @@ aac_timeout(struct aac_softc *sc)
 		if (code != AAC_UP_AND_RUNNING) {
 			device_printf(sc->aac_dev, "WARNING! Controller is no "
 				      "longer running! code= 0x%x\n", code);
+			aac_reset_adapter(sc);
 		}
 	}
 	return;
@@ -2390,8 +2637,7 @@ aac_rx_get_fwstatus(struct aac_softc *sc
 {
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
-	return(AAC_MEM0_GETREG4(sc, sc->flags & AAC_FLAGS_NEW_COMM ?
-	    AAC_RX_OMR0 : AAC_RX_FWSTATUS));
+	return(AAC_MEM0_GETREG4(sc, AAC_RX_OMR0));
 }
 
 static int
@@ -2399,8 +2645,15 @@ aac_rkt_get_fwstatus(struct aac_softc *s
 {
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
-	return(AAC_MEM0_GETREG4(sc, sc->flags & AAC_FLAGS_NEW_COMM ?
-	    AAC_RKT_OMR0 : AAC_RKT_FWSTATUS));
+	return(AAC_MEM0_GETREG4(sc, AAC_RKT_OMR0));
+}
+
+static int
+aac_src_get_fwstatus(struct aac_softc *sc)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	return(AAC_MEM0_GETREG4(sc, AAC_SRC_OMR));
 }
 
 /*
@@ -2431,6 +2684,14 @@ aac_rkt_qnotify(struct aac_softc *sc, in
 	AAC_MEM0_SETREG4(sc, AAC_RKT_IDBR, qbit);
 }
 
+static void
+aac_src_qnotify(struct aac_softc *sc, int qbit)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, qbit << AAC_SRC_IDR_SHIFT);
+}
+
 /*
  * Get the interrupt reason bits
  */
@@ -2458,6 +2719,14 @@ aac_rkt_get_istatus(struct aac_softc *sc
 	return(AAC_MEM0_GETREG4(sc, AAC_RKT_ODBR));
 }
 
+static int
+aac_src_get_istatus(struct aac_softc *sc)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	return(AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R) >> AAC_SRC_ODR_SHIFT);
+}
+
 /*
  * Clear some interrupt reason bits
  */
@@ -2485,6 +2754,14 @@ aac_rkt_clear_istatus(struct aac_softc *
 	AAC_MEM0_SETREG4(sc, AAC_RKT_ODBR, mask);
 }
 
+static void
+aac_src_clear_istatus(struct aac_softc *sc, int mask)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, mask << AAC_SRC_ODR_SHIFT);
+}
+
 /*
  * Populate the mailbox and set the command word
  */
@@ -2527,6 +2804,19 @@ aac_rkt_set_mailbox(struct aac_softc *sc
 	AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
 }
 
+static void
+aac_src_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
+		    u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	AAC_MEM0_SETREG4(sc, AAC_SRC_MAILBOX, command);
+	AAC_MEM0_SETREG4(sc, AAC_SRC_MAILBOX + 4, arg0);
+	AAC_MEM0_SETREG4(sc, AAC_SRC_MAILBOX + 8, arg1);
+	AAC_MEM0_SETREG4(sc, AAC_SRC_MAILBOX + 12, arg2);
+	AAC_MEM0_SETREG4(sc, AAC_SRC_MAILBOX + 16, arg3);
+}
+
 /*
  * Fetch the immediate command status word
  */
@@ -2554,6 +2844,14 @@ aac_rkt_get_mailbox(struct aac_softc *sc
 	return(AAC_MEM1_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
 }
 
+static int
+aac_src_get_mailbox(struct aac_softc *sc, int mb)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	return(AAC_MEM0_GETREG4(sc, AAC_SRC_MAILBOX + (mb * 4)));
+}
+
 /*
  * Set/clear interrupt masks
  */
@@ -2599,6 +2897,18 @@ aac_rkt_set_interrupts(struct aac_softc 
 	}
 }
 
+static void
+aac_src_set_interrupts(struct aac_softc *sc, int enable)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis");
+
+	if (enable) {
+		AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, ~AAC_DB_INT_NEW_COMM_TYPE1);
+	} else {
+		AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, ~0);
+	}
+}
+
 /*
  * New comm. interface: Send command functions
  */
@@ -2648,6 +2958,35 @@ aac_rkt_send_command(struct aac_softc *s
 	return 0;
 }
 
+static int
+aac_src_send_command(struct aac_softc *sc, struct aac_command *cm)
+{
+	struct aac_fib_xporthdr *pFibX;
+	u_int32_t fibsize;
+	u_int64_t address;
+
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "send command (new comm. type1)");
+
+	/* Calculate the amount to the fibsize bits */
+	fibsize = (sizeof(struct aac_fib_xporthdr) + 
+	   cm->cm_fib->Header.Size + 127) / 128 - 1; 
+	if (fibsize > 31) 
+		fibsize = 31;
+
+	/* Fill XPORT header */ 
+	pFibX = (struct aac_fib_xporthdr *)
+		((unsigned char *)cm->cm_fib - sizeof(struct aac_fib_xporthdr));
+	pFibX->Handle = cm->cm_fib->Header.SenderData + 1;
+	pFibX->HostAddress = cm->cm_fibphys;
+	pFibX->Size = cm->cm_fib->Header.Size;
+	address = cm->cm_fibphys - sizeof(struct aac_fib_xporthdr);
+
+	aac_enqueue_busy(cm);
+	AAC_MEM0_SETREG4(sc, AAC_SRC_IQUE_H, (u_int32_t)(address >> 32));
+	AAC_MEM0_SETREG4(sc, AAC_SRC_IQUE_L, (u_int32_t)address + fibsize);
+	return 0;
+}
+
 /*
  * New comm. interface: get, set outbound queue index
  */
@@ -2667,6 +3006,14 @@ aac_rkt_get_outb_queue(struct aac_softc 
 	return(AAC_MEM0_GETREG4(sc, AAC_RKT_OQUE));
 }
 
+static int
+aac_src_get_outb_queue(struct aac_softc *sc)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	return(-1);
+}
+
 static void
 aac_rx_set_outb_queue(struct aac_softc *sc, int index)
 {
@@ -2683,6 +3030,12 @@ aac_rkt_set_outb_queue(struct aac_softc 
 	AAC_MEM0_SETREG4(sc, AAC_RKT_OQUE, index);
 }
 
+static void
+aac_src_set_outb_queue(struct aac_softc *sc, int index)
+{
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+}
+
 /*
  * Debugging and Diagnostics
  */
@@ -2702,6 +3055,24 @@ aac_describe_controller(struct aac_softc
 	mtx_lock(&sc->aac_io_lock);
 	aac_alloc_sync_fib(sc, &fib);
 
+	if (sc->supported_options & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO) {
+		fib->data[0] = 0;
+		if (aac_sync_fib(sc, RequestSupplementAdapterInfo, 0, fib, 1)) 
+			device_printf(sc->aac_dev, "RequestSupplementAdapterInfo failed\n");
+		else {
+			struct aac_supplement_adapter_info *supp_info;
+
+			supp_info = ((struct aac_supplement_adapter_info *)&fib->data[0]); 
+			adapter_type = supp_info->AdapterTypeText;
+			sc->aac_feature_bits = supp_info->FeatureBits;
+			sc->aac_support_opt2 = supp_info->SupportedOptions2;
+		}
+	}
+	device_printf(sc->aac_dev, "%s, aac driver %d.%d.%d-%d\n",
+		adapter_type,
+		AAC_DRIVER_MAJOR_VERSION, AAC_DRIVER_MINOR_VERSION,
+		AAC_DRIVER_BUGFIX_LEVEL, AAC_DRIVER_BUILD);
+
 	fib->data[0] = 0;
 	if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
 		device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
@@ -2756,20 +3127,6 @@ aac_describe_controller(struct aac_softc
 			      "\24HEATSENSOR");
 	}
 
-	if (sc->supported_options & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO) {
-		fib->data[0] = 0;
-		if (aac_sync_fib(sc, RequestSupplementAdapterInfo, 0, fib, 1))
-			device_printf(sc->aac_dev,
-			    "RequestSupplementAdapterInfo failed\n");
-		else
-			adapter_type = ((struct aac_supplement_adapter_info *)
-			    &fib->data[0])->AdapterTypeText;
-	}
-	device_printf(sc->aac_dev, "%s, aac driver %d.%d.%d-%d\n",
-		adapter_type,
-		AAC_DRIVER_MAJOR_VERSION, AAC_DRIVER_MINOR_VERSION,
-		AAC_DRIVER_BUGFIX_LEVEL, AAC_DRIVER_BUILD);
-
 	aac_release_sync_fib(sc);
 	mtx_unlock(&sc->aac_io_lock);
 }
@@ -3050,25 +3407,25 @@ static int
 aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg)
 {
 	struct aac_command *cm;
-	struct aac_event *event;
 	struct aac_fib *fib;
-	struct aac_srb *srbcmd, *user_srb;
-	struct aac_sg_entry *sge;
-	struct aac_sg_entry64 *sge64;
-	void *srb_sg_address, *ureply;
-	uint32_t fibsize, srb_sg_bytecount;
-	int error, transfer_data;
+	struct aac_srb *srbcmd;
+	struct aac_srb *user_srb = (struct aac_srb *)arg;
+	void *user_reply;
+	int error, transfer_data = 0;
+	bus_dmamap_t orig_map = 0;
+	u_int32_t fibsize = 0;
+	u_int64_t srb_sg_address;
+	u_int32_t srb_sg_bytecount;
 
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
 	cm = NULL;
-	transfer_data = 0;
-	fibsize = 0;
-	user_srb = (struct aac_srb *)arg;
 
 	mtx_lock(&sc->aac_io_lock);
 	if (aac_alloc_command(sc, &cm)) {
-		 event = malloc(sizeof(struct aac_event), M_AACBUF,
+		struct aac_event *event;
+
+		event = malloc(sizeof(struct aac_event), M_AACBUF,
 		    M_NOWAIT | M_ZERO);
 		if (event == NULL) {
 			error = EBUSY;
@@ -3079,108 +3436,171 @@ aac_ioctl_send_raw_srb(struct aac_softc 
 		event->ev_callback = aac_ioctl_event;
 		event->ev_arg = &cm;
 		aac_add_event(sc, event);
-		msleep(cm, &sc->aac_io_lock, 0, "aacraw", 0);
+		msleep(cm, &sc->aac_io_lock, 0, "sndraw", 0);
 	}
 	mtx_unlock(&sc->aac_io_lock);
 
 	cm->cm_data = NULL;
+	/* save original dma map */
+	orig_map = cm->cm_datamap;
+
 	fib = cm->cm_fib;
 	srbcmd = (struct aac_srb *)fib->data;
-	error = copyin(&user_srb->data_len, &fibsize, sizeof(uint32_t));
-	if (error != 0)
+	if ((error = copyin((void *)&user_srb->data_len, &fibsize, 
+		sizeof (u_int32_t)) != 0)) 
 		goto out;
-	if (fibsize > (sc->aac_max_fib_size - sizeof(struct aac_fib_header))) {
+	if (fibsize > (sc->aac_max_fib_size-sizeof(struct aac_fib_header))) {
 		error = EINVAL;
 		goto out;
 	}
-	error = copyin(user_srb, srbcmd, fibsize);
-	if (error != 0)
+	if ((error = copyin((void *)user_srb, srbcmd, fibsize) != 0)) 
 		goto out;
-	srbcmd->function = 0;
-	srbcmd->retry_limit = 0;
+
+	srbcmd->function = 0;		/* SRBF_ExecuteScsi */
+	srbcmd->retry_limit = 0;	/* obsolete */
+
+	/* only one sg element from userspace supported */
 	if (srbcmd->sg_map.SgCount > 1) {
 		error = EINVAL;
 		goto out;
 	}
-
-	/* Retrieve correct SG entries. */
-	if (fibsize == (sizeof(struct aac_srb) +
-	    srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry))) {
-		sge = srbcmd->sg_map.SgEntry;
-		sge64 = NULL;
-		srb_sg_bytecount = sge->SgByteCount;
-		srb_sg_address = (void *)(uintptr_t)sge->SgAddress;
-	}
+	/* check fibsize */
+	if (fibsize == (sizeof(struct aac_srb) + 
+		srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry))) {
+		struct aac_sg_entry *sgp = srbcmd->sg_map.SgEntry;
+		srb_sg_bytecount = sgp->SgByteCount;
+		srb_sg_address = (u_int64_t)sgp->SgAddress;
+	} else if (fibsize == (sizeof(struct aac_srb) + 
+		srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry64))) {
 #ifdef __amd64__
-	else if (fibsize == (sizeof(struct aac_srb) +
-	    srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry64))) {
-		sge = NULL;
-		sge64 = (struct aac_sg_entry64 *)srbcmd->sg_map.SgEntry;
-		srb_sg_bytecount = sge64->SgByteCount;
-		srb_sg_address = (void *)sge64->SgAddress;
-		if (sge64->SgAddress > 0xffffffffull &&
-		    (sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
+		struct aac_sg_entry64 *sgp = 
+			(struct aac_sg_entry64 *)srbcmd->sg_map.SgEntry;
+		srb_sg_bytecount = sgp->SgByteCount;
+		srb_sg_address = sgp->SgAddress;
+		if (srb_sg_address > 0xffffffffull && 
+			!(sc->flags & AAC_FLAGS_SG_64BIT))
+#endif	
+		{
 			error = EINVAL;
 			goto out;
 		}
-	}
-#endif
-	else {
+	} else {
 		error = EINVAL;
 		goto out;
 	}
-	ureply = (char *)arg + fibsize;
+	user_reply = (char *)arg + fibsize;
 	srbcmd->data_len = srb_sg_bytecount;
-	if (srbcmd->sg_map.SgCount == 1)
+	if (srbcmd->sg_map.SgCount == 1) 
 		transfer_data = 1;
 
-	cm->cm_sgtable = (struct aac_sg_table *)&srbcmd->sg_map;
 	if (transfer_data) {
-		cm->cm_datalen = srb_sg_bytecount;
-		cm->cm_data = malloc(cm->cm_datalen, M_AACBUF, M_NOWAIT);
-		if (cm->cm_data == NULL) {
+		/*
+		 * Create DMA tag for the passthr. data buffer and allocate it.
+		 */
+		if (bus_dma_tag_create(sc->aac_parent_dmat, 	/* parent */
+			1, 0,			/* algnmnt, boundary */
+			(sc->flags & AAC_FLAGS_SG_64BIT) ?
+			BUS_SPACE_MAXADDR_32BIT :
+			0x7fffffff,		/* lowaddr */
+			BUS_SPACE_MAXADDR, 	/* highaddr */
+			NULL, NULL, 		/* filter, filterarg */
+			srb_sg_bytecount, 	/* size */
+			sc->aac_sg_tablesize,	/* nsegments */
+			srb_sg_bytecount, 	/* maxsegsize */
+			0,			/* flags */
+			NULL, NULL,		/* No locking needed */
+			&cm->cm_passthr_dmat)) {
 			error = ENOMEM;
 			goto out;
 		}
-		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN)
+		if (bus_dmamem_alloc(cm->cm_passthr_dmat, (void **)&cm->cm_data,
+			BUS_DMA_NOWAIT, &cm->cm_datamap)) {
+			error = ENOMEM;
+			goto out;
+		}
+		/* fill some cm variables */
+		cm->cm_datalen = srb_sg_bytecount;
+		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN) 
 			cm->cm_flags |= AAC_CMD_DATAIN;
-		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_OUT) {
+		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_OUT)
 			cm->cm_flags |= AAC_CMD_DATAOUT;
-			error = copyin(srb_sg_address, cm->cm_data,
-			    cm->cm_datalen);
-			if (error != 0)
+
+		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_OUT) {
+			if ((error = copyin(
+#ifdef __amd64__
+				(void *)srb_sg_address,
+#else
+				(void *)(u_int32_t)srb_sg_address,
+#endif
+				cm->cm_data, cm->cm_datalen)) != 0)
 				goto out;
+			/* sync required for bus_dmamem_alloc() alloc. mem.? */
+			bus_dmamap_sync(cm->cm_passthr_dmat, cm->cm_datamap,
+				BUS_DMASYNC_PREWRITE);
 		}
 	}
 
-	fib->Header.Size = sizeof(struct aac_fib_header) +
-	    sizeof(struct aac_srb);
+	/* build the FIB */
+	fib->Header.Size = sizeof(struct aac_fib_header) + 
+		sizeof(struct aac_srb);
 	fib->Header.XferState =
-	    AAC_FIBSTATE_HOSTOWNED   |
-	    AAC_FIBSTATE_INITIALISED |
-	    AAC_FIBSTATE_EMPTY       |
-	    AAC_FIBSTATE_FROMHOST    |
-	    AAC_FIBSTATE_REXPECTED   |
-	    AAC_FIBSTATE_NORM        |
-	    AAC_FIBSTATE_ASYNC       |
-	    AAC_FIBSTATE_FAST_RESPONSE;
-	fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) != 0 ?
-	    ScsiPortCommandU64 : ScsiPortCommand;
+		AAC_FIBSTATE_HOSTOWNED   |
+		AAC_FIBSTATE_INITIALISED |
+		AAC_FIBSTATE_EMPTY	 |
+		AAC_FIBSTATE_FROMHOST	 |
+		AAC_FIBSTATE_REXPECTED   |
+		AAC_FIBSTATE_NORM	 |
+		AAC_FIBSTATE_ASYNC	 |
+		AAC_FIBSTATE_FAST_RESPONSE;
+
+	fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) ? 
+		ScsiPortCommandU64 : ScsiPortCommand;
+	cm->cm_sgtable = (struct aac_sg_table *)&srbcmd->sg_map;
+
+	/* send command */
+	if (transfer_data) {
+		bus_dmamap_load(cm->cm_passthr_dmat,
+			cm->cm_datamap, cm->cm_data,
+			cm->cm_datalen,
+			aac_map_command_sg, cm, 0);
+	} else {
+		aac_map_command_sg(cm, NULL, 0, 0);
+	}
 
+	/* wait for completion */
 	mtx_lock(&sc->aac_io_lock);
-	aac_wait_command(cm);
+	while (!(cm->cm_flags & AAC_CMD_COMPLETED))
+		msleep(cm, &sc->aac_io_lock, 0, "sndrw2", 0);
 	mtx_unlock(&sc->aac_io_lock);
 
-	if (transfer_data && (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN) != 0) {
-		error = copyout(cm->cm_data, srb_sg_address, cm->cm_datalen);
-		if (error != 0)
+	/* copy data */
+	if (transfer_data && (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN)) {
+		if ((error = copyout(cm->cm_data, 
+#ifdef __amd64__
+			(void *)srb_sg_address,
+#else
+			(void *)(u_int32_t)srb_sg_address,
+#endif
+			cm->cm_datalen)) != 0)
 			goto out;
+		/* sync required for bus_dmamem_alloc() allocated mem.? */
+		bus_dmamap_sync(cm->cm_passthr_dmat, cm->cm_datamap,
+				BUS_DMASYNC_POSTREAD);
 	}
-	error = copyout(fib->data, ureply, sizeof(struct aac_srb_response));
+
+	/* status */
+	error = copyout(fib->data, user_reply, sizeof(struct aac_srb_response));
+
 out:
-	if (cm != NULL) {
-		if (cm->cm_data != NULL)
-			free(cm->cm_data, M_AACBUF);
+	if (cm && cm->cm_data) {
+		if (transfer_data)
+			bus_dmamap_unload(cm->cm_passthr_dmat, cm->cm_datamap);
+		bus_dmamem_free(cm->cm_passthr_dmat, cm->cm_data, cm->cm_datamap);
+		cm->cm_datamap = orig_map;
+	}
+	if (cm && cm->cm_passthr_dmat) 
+		bus_dma_tag_destroy(cm->cm_passthr_dmat);
+	if (cm) { 
 		mtx_lock(&sc->aac_io_lock);
 		aac_release_command(cm);
 		mtx_unlock(&sc->aac_io_lock);
@@ -3189,6 +3609,42 @@ out:
 }
 
 /*
+ * Request an AIF from the controller (new comm. type1)
+ */
+static void
+aac_request_aif(struct aac_softc *sc)
+{
+	struct aac_command *cm;
+	struct aac_fib *fib;
+
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	if (aac_alloc_command(sc, &cm)) {
+		sc->aif_pending = 1;
+		return;
+	}
+	sc->aif_pending = 0;
+    
+	/* build the FIB */
+	fib = cm->cm_fib;
+	fib->Header.Size = sizeof(struct aac_fib);
+	fib->Header.XferState =
+        AAC_FIBSTATE_HOSTOWNED   |
+        AAC_FIBSTATE_INITIALISED |
+        AAC_FIBSTATE_EMPTY	 |
+        AAC_FIBSTATE_FROMHOST	 |
+        AAC_FIBSTATE_REXPECTED   |
+        AAC_FIBSTATE_NORM	 |
+        AAC_FIBSTATE_ASYNC;
+	/* set AIF marker */
+	fib->Header.SenderData = 0x00800000;
+	fib->Header.Command = AifRequest;
+	((struct aac_aif_command *)fib->data)->command = AifReqEvent;
+
+	aac_map_command_sg(cm, NULL, 0, 0);
+}
+
+/*
  * cdevpriv interface private destructor.
  */
 static void
@@ -3295,6 +3751,9 @@ aac_handle_aif(struct aac_softc *sc, str
 			co = TAILQ_FIRST(&sc->aac_container_tqh);
 			while (co != NULL) {
 				if (co->co_found == 0) {
+					struct aac_disk *ad;
+					ad = device_get_softc(co->co_disk);
+					ad->ad_container = NULL;
 					mtx_unlock(&sc->aac_io_lock);
 					mtx_lock(&Giant);
 					device_delete_child(sc->aac_dev,
@@ -3612,6 +4071,7 @@ aac_supported_features(struct aac_softc 
 	 if (f.feat.fValue == 0) {
 		f.feat.fBits.largeLBA =
 		    (sc->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0;
+		f.feat.fBits.JBODSupport = 1;
 		/* TODO: In the future, add other features state here as well */
 	} else {
 		if (f.feat.fBits.largeLBA)
@@ -3783,6 +4243,7 @@ aac_get_bus_info(struct aac_softc *sc)
 		caminf->InitiatorBusId = businfo.InitiatorBusId[i];
 		caminf->aac_sc = sc;
 		caminf->sim_dev = child;
+		caminf->aac_cam = NULL;
 
 		device_set_ivars(child, caminf);
 		device_set_desc(child, "SCSI Passthrough Bus");
@@ -3796,3 +4257,164 @@ aac_get_bus_info(struct aac_softc *sc)
 
 	return;
 }
+
+/*
+ * Check to see if the kernel is up and running. If we are in a
+ * BlinkLED state, return the BlinkLED code.
+ */
+static u_int32_t
+aac_check_adapter_health(struct aac_softc *sc, u_int8_t *bled)
+{
+	u_int32_t ret;
+
+	ret = AAC_GET_FWSTATUS(sc);
+
+	if (ret & AAC_UP_AND_RUNNING)
+		ret = 0;
+	else if (ret & AAC_KERNEL_PANIC && bled)
+		*bled = (ret >> 16) & 0xff;
+
+	return (ret);
+}
+
+/*
+ * Once do an IOP reset, basically have to re-initialize the card as
+ * if coming up from a cold boot, and the driver is responsible for
+ * any IO that was outstanding to the adapter at the time of the IOP
+ * RESET. And prepare the driver for IOP RESET by making the init code
+ * modular with the ability to call it from multiple places.
+ */
+static int
+aac_reset_adapter(struct aac_softc *sc)
+{
+	struct aac_command *cm;
+	struct aac_fib *fib;
+	struct aac_pause_command *pc;
+	u_int32_t status, old_flags, reset_mask, waitCount;
+
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	if (sc->aac_state & AAC_STATE_RESET) {
+		device_printf(sc->aac_dev, "aac_reset_adapter() already in progress\n");
+		return (EINVAL);
+	}
+	sc->aac_state |= AAC_STATE_RESET;
+
+	/* disable interrupt */
+	AAC_MASK_INTERRUPTS(sc);
+
+	/*
+	 * Abort all pending commands:
+	 * a) on the controller
+	 */
+	while ((cm = aac_dequeue_busy(sc)) != NULL) {
+		cm->cm_flags |= AAC_CMD_RESET;
+
+		/* is there a completion handler? */
+		if (cm->cm_complete != NULL) {
+			cm->cm_complete(cm);
+		} else {
+			/* assume that someone is sleeping on this
+			 * command
+			 */
+			wakeup(cm);
+		}
+	}
+
+	/* b) in the waiting queues */
+	while ((cm = aac_dequeue_ready(sc)) != NULL) {
+		cm->cm_flags |= AAC_CMD_RESET;
+
+		/* is there a completion handler? */
+		if (cm->cm_complete != NULL) {
+			cm->cm_complete(cm);
+		} else {
+			/* assume that someone is sleeping on this
+			 * command
+			 */
+			wakeup(cm);
+		}
+	}
+
+	/* flush drives */
+	if (aac_check_adapter_health(sc, NULL) == 0)
+		(void) aac_shutdown(sc->aac_dev);
+
+	/* execute IOP reset */
+	if (sc->supported_options & AAC_SUPPORTED_MU_RESET) {
+		AAC_MEM0_SETREG4(sc, AAC_IRCSR, AAC_IRCSR_CORES_RST);
+
+		/* We need to wait for 5 seconds before accessing the MU again
+		 * 10000 * 100us = 1000,000us = 1000ms = 1s  
+		 */
+		waitCount = 5 * 10000;
+		while (waitCount) {
+			DELAY(100);			/* delay 100 microseconds */
+			waitCount--;
+		}
+	} else if ((aac_sync_command(sc, 
+		AAC_IOP_RESET_ALWAYS, 0, 0, 0, 0, &status, &reset_mask)) != 0) {
+		/* call IOP_RESET for older firmware */
+		if ((aac_sync_command(sc, 
+			AAC_IOP_RESET, 0, 0, 0, 0, &status, NULL)) != 0) {
+
+			if (status == AAC_SRB_STS_INVALID_REQUEST)
+				device_printf(sc->aac_dev, "IOP_RESET not supported\n");
+			else
+				/* probably timeout */
+				device_printf(sc->aac_dev, "IOP_RESET failed\n");
+
+			/* unwind aac_shutdown() */
+			aac_alloc_sync_fib(sc, &fib);
+			pc = (struct aac_pause_command *)&fib->data[0];
+			pc->Command = VM_ContainerConfig;
+			pc->Type = CT_PAUSE_IO;
+			pc->Timeout = 1;
+			pc->Min = 1;
+			pc->NoRescan = 1;
+
+			(void) aac_sync_fib(sc, ContainerCommand, 0, fib,
+				sizeof (struct aac_pause_command));
+			aac_release_sync_fib(sc);
+
+			goto finish;
+		}
+	} else if (sc->supported_options & AAC_SUPPORTED_DOORBELL_RESET) {
+		AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, reset_mask);
+		/* We need to wait for 5 seconds before accessing the doorbell again
+		 * 10000 * 100us = 1000,000us = 1000ms = 1s  
+		 */
+		waitCount = 5 * 10000;
+		while (waitCount) {
+			DELAY(100);			/* delay 100 microseconds */
+			waitCount--;
+		}
+	}
+
+	/*
+	 * Re-read and renegotiate the FIB parameters, as one of the actions
+	 * that can result from an IOP reset is the running of a new firmware
+	 * image.
+	 */
+	old_flags = sc->flags;
+	/*
+	 * Initialize the adapter.
+	 */
+	if (aac_check_firmware(sc) != 0)
+		goto finish;
+	if (aac_init(sc) != 0)
+		goto finish;
+
+	if ((old_flags & AAC_FLAGS_NEW_COMM) &&
+		!(sc->flags & AAC_FLAGS_NEW_COMM)) {
+		/* remap interrupt handler */
+		aac_setup_intr(sc);
+	}
+
+finish:
+	sc->aac_state &= ~AAC_STATE_RESET;
+	AAC_UNMASK_INTERRUPTS(sc);
+	aac_startio(sc);
+	return (0);
+}
+
diff -pruN old/aac_cam.c new/aac_cam.c
--- old/aac_cam.c	2011-03-31 14:57:34.000000000 +0000
+++ new/aac_cam.c	2011-04-01 12:57:00.000000000 +0000
@@ -538,7 +538,9 @@ aac_cam_complete(struct aac_command *cm)
 	ccb = cm->cm_private;
 	srbr = (struct aac_srb_response *)&cm->cm_fib->data[0];
 
-	if (srbr->fib_status != 0) {
+	if (cm->cm_flags & AAC_CMD_RESET) {
+		ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
+	} else if (srbr->fib_status != 0) {
 		device_printf(sc->aac_dev, "Passthru FIB failed!\n");
 		ccb->ccb_h.status = CAM_REQ_ABORTED;
 	} else {
@@ -583,9 +585,10 @@ aac_cam_complete(struct aac_command *cm)
 				 * We want DASD and PROC devices to only be
 				 * visible through the pass device.
 				 */
-				if ((device == T_DIRECT) ||
-				    (device == T_PROCESSOR) ||
-				    (sc->flags & AAC_FLAGS_CAM_PASSONLY))
+				if ((device == T_DIRECT && 
+				 	!(sc->aac_feature_bits & AAC_SUPPL_SUPPORTED_JBOD)) ||
+					(device == T_PROCESSOR) ||
+					(sc->flags & AAC_FLAGS_CAM_PASSONLY))
 					ccb->csio.data_ptr[0] =
 					    ((device & 0xe0) | T_NODEVICE);
 				} else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT &&
diff -pruN old/aac_disk.c new/aac_disk.c
--- old/aac_disk.c	2011-03-31 14:57:34.000000000 +0000
+++ new/aac_disk.c	2011-04-01 13:32:20.000000000 +0000
@@ -93,26 +93,60 @@ DRIVER_MODULE(aacd, aac, aac_disk_driver
 static int
 aac_disk_open(struct disk *dp)
 {
-	struct aac_disk	*sc;
+	struct aac_disk	*scd;
+	struct aac_softc *sc;
 
 	fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
-	sc = (struct aac_disk *)dp->d_drv1;
+	scd = (struct aac_disk *)dp->d_drv1;
 	
-	if (sc == NULL) {
+	if (scd == NULL) {
 		printf("aac_disk_open: No Softc\n");
 		return (ENXIO);
 	}
+	sc = scd->ad_controller;
 
 	/* check that the controller is up and running */
-	if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND) {
-		device_printf(sc->ad_controller->aac_dev,
-		    "Controller Suspended controller state = 0x%x\n",
-		    sc->ad_controller->aac_state);
-		return(ENXIO);
+	if (sc->aac_state & AAC_STATE_SUSPEND) {
+		device_printf(sc->aac_dev, 
+			"Controller Suspended controller state = 0x%x\n",
+			sc->aac_state);
+		return (ENXIO);
+	}          
+
+	/* already opened? */
+	if (scd->ad_flags & AAC_DISK_OPEN) 
+		return (0);
+
+	/* power management */
+	if (sc->aac_support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) {
+		struct aac_fib *fib;
+		struct aac_cnt_config *cmd;
+
+		mtx_lock(&sc->aac_io_lock);
+		aac_alloc_sync_fib(sc, &fib);
+
+		/* Start unit */
+		cmd = (struct aac_cnt_config *)&fib->data[0];
+		bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
+		cmd->Command = VM_ContainerConfig;
+		cmd->CTCommand.command = CT_PM_DRIVER_SUPPORT;
+		cmd->CTCommand.param[0] = AAC_PM_DRIVERSUP_START_UNIT;
+		cmd->CTCommand.param[1] = scd->ad_container->co_mntobj.ObjectId;
+		cmd->CTCommand.param[2] = 0;	/* 1 - immediate */
+
+		if (aac_sync_fib(sc, ContainerCommand, 0, fib,
+				 sizeof(struct aac_cnt_config)) ||
+			*(u_int32_t *)&fib->data[0] != 0) {
+			printf("Power Management: Error starting container %d\n", 
+				scd->ad_container->co_mntobj.ObjectId);
+		}
+
+		aac_release_sync_fib(sc);
+		mtx_unlock(&sc->aac_io_lock);
 	}
 
-	sc->ad_flags |= AAC_DISK_OPEN;
+	scd->ad_flags |= AAC_DISK_OPEN;
 	return (0);
 }
 
@@ -122,16 +156,50 @@ aac_disk_open(struct disk *dp)
 static int
 aac_disk_close(struct disk *dp)
 {
-	struct aac_disk	*sc;
+	struct aac_disk	*scd;
+	struct aac_softc *sc;
 
 	fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
-	sc = (struct aac_disk *)dp->d_drv1;
+	scd = (struct aac_disk *)dp->d_drv1;
 	
-	if (sc == NULL)
+	if (scd == NULL)
 		return (ENXIO);
+	sc = scd->ad_controller;
+
+	/* already closed? */
+	if (!(scd->ad_flags & AAC_DISK_OPEN)) 
+		return (0);
+
+	/* power management */
+	if (sc->aac_support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) {
+		struct aac_fib *fib;
+		struct aac_cnt_config *cmd;
+
+		mtx_lock(&sc->aac_io_lock);
+		aac_alloc_sync_fib(sc, &fib);
+
+		/* Stop unit */
+		cmd = (struct aac_cnt_config *)&fib->data[0];
+		bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
+		cmd->Command = VM_ContainerConfig;
+		cmd->CTCommand.command = CT_PM_DRIVER_SUPPORT;
+		cmd->CTCommand.param[0] = AAC_PM_DRIVERSUP_STOP_UNIT;
+		cmd->CTCommand.param[1] = scd->ad_container->co_mntobj.ObjectId;
+		cmd->CTCommand.param[2] = 0;	/* 1 - immediate */
+
+		if (aac_sync_fib(sc, ContainerCommand, 0, fib,
+				 sizeof(struct aac_cnt_config)) ||
+			*(u_int32_t *)&fib->data[0] != 0) {
+			printf("Power Management: Error stopping container %d\n", 
+				scd->ad_container->co_mntobj.ObjectId);
+		}
+
+		aac_release_sync_fib(sc);
+		mtx_unlock(&sc->aac_io_lock);
+	}
 
-	sc->ad_flags &= ~AAC_DISK_OPEN;
+	scd->ad_flags &= ~AAC_DISK_OPEN;
 	return (0);
 }
 
diff -pruN old/aac_ioctl.h new/aac_ioctl.h
--- old/aac_ioctl.h	2011-03-31 15:00:35.000000000 +0000
+++ new/aac_ioctl.h	2011-04-01 13:33:29.000000000 +0000
@@ -157,12 +157,12 @@ union aac_statrequest {
 struct aac_rev_check {
 	RevComponent		callingComponent;
 	struct FsaRevision	callingRevision;
-};
+} __packed;
 
 struct aac_rev_check_resp {
 	int			possiblyCompatible;
 	struct FsaRevision	adapterSWRevision;
-};
+} __packed;
 
 /*
  * Context passed in by a consumer looking to collect an AIF.
@@ -171,7 +171,7 @@ struct get_adapter_fib_ioctl {
 	u_int32_t	AdapterFibContext;
 	int	  	Wait;
 	caddr_t		AifFib;
-};
+} __packed;
 
 struct aac_query_disk {
 	int32_t		ContainerNumber;
@@ -184,7 +184,7 @@ struct aac_query_disk {
 	int32_t		Instance;
 	char		diskDeviceName[10];
 	u_int32_t	UnMapped;
-};
+} __packed;
 
 /* Features, asked from the tools to know if the driver
  * supports drives >2TB
@@ -192,7 +192,10 @@ struct aac_query_disk {
 typedef union {
 	struct {
 		u_int32_t largeLBA  : 1;	/* disk support greater 2TB */
-		u_int32_t fReserved : 31;
+		u_int32_t IoctlBuf  : 1;    /* ARCIOCTL call support */
+		u_int32_t AIFSupport: 1;    /* AIF support */
+		u_int32_t JBODSupport:1;    /* firmware + driver both support JBOD */
+		u_int32_t fReserved : 28;
 	} fBits;
 	u_int32_t fValue;
 } featuresState;
diff -pruN old/aac_pci.c new/aac_pci.c
--- old/aac_pci.c	2011-03-31 14:57:34.000000000 +0000
+++ new/aac_pci.c	2011-04-01 13:41:00.000000000 +0000
@@ -2,7 +2,8 @@
  * Copyright (c) 2000 Michael Smith
  * Copyright (c) 2001 Scott Long
  * Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Adaptec, Inc.
+ * Copyright (c) 2001-2010 Adaptec, Inc.
+ * Copyright (c) 2010 PMC-Sierra, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -243,15 +244,7 @@ struct aac_ident
 	{0x9005, 0x0285, 0x9005, 0x02d0, AAC_HWIF_I960RX, 0,
 	 "Adaptec RAID 52445"},
 	{0x9005, 0x0285, 0x9005, 0x02d1, AAC_HWIF_I960RX, 0,
-	 "Adaptec RAID 5405"},
-	{0x9005, 0x0285, 0x9005, 0x02d4, AAC_HWIF_I960RX, 0,
-	 "Adaptec RAID 2045"},
-	{0x9005, 0x0285, 0x9005, 0x02d5, AAC_HWIF_I960RX, 0,
-	 "Adaptec RAID 2405"},
-	{0x9005, 0x0285, 0x9005, 0x02d6, AAC_HWIF_I960RX, 0,
-	 "Adaptec RAID 2445"},
-	{0x9005, 0x0285, 0x9005, 0x02d7, AAC_HWIF_I960RX, 0,
-	 "Adaptec RAID 2805"},
+        "Adaptec RAID 5405"},
 	{0x9005, 0x0286, 0x1014, 0x9580, AAC_HWIF_RKT, 0,
 	 "IBM ServeRAID-8k"},
 	{0x9005, 0x0285, 0x1014, 0x034d, AAC_HWIF_I960RX, 0,
@@ -284,6 +277,8 @@ aac_family_identifiers[] = {
 	 "Adaptec RAID Controller"},
 	{0x9005, 0x0286, 0, 0, AAC_HWIF_RKT, 0,
 	 "Adaptec RAID Controller"},
+	{0x9005, 0x028b, 0, 0, AAC_HWIF_SRC, 0,
+	 "Adaptec RAID Controller"},
 	{0, 0, 0, 0, 0, 0, 0}
 };
 
@@ -369,6 +364,40 @@ aac_pci_attach(device_t dev)
 		goto out;
 	}
 
+	/* 
+	 * Detect the hardware interface version, set up the bus interface
+	 * indirection.
+	 */
+	id = aac_find_ident(dev);
+	sc->aac_hwif = id->hwif;
+	switch(sc->aac_hwif) {
+	case AAC_HWIF_I960RX:
+	case AAC_HWIF_NARK:
+		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for i960Rx/NARK");
+		sc->aac_if = aac_rx_interface;
+		break;
+	case AAC_HWIF_STRONGARM:
+		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for StrongARM");
+		sc->aac_if = aac_sa_interface;
+		break;
+	case AAC_HWIF_RKT:
+		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for Rocket/MIPS");
+		sc->aac_if = aac_rkt_interface;
+		break;
+	case AAC_HWIF_SRC:
+		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for PMC SRC");
+		sc->aac_if = aac_src_interface;
+		break;
+	default:
+		sc->aac_hwif = AAC_HWIF_UNKNOWN;
+		device_printf(sc->aac_dev, "unknown hardware type\n");
+		error = ENXIO;
+		goto out;
+	}
+
+	/* assume failure is 'out of memory' */
+	error = ENOMEM;
+
 	/*
 	 * Allocate the PCI register window.
 	 */
@@ -382,8 +411,8 @@ aac_pci_attach(device_t dev)
 	sc->aac_btag0 = rman_get_bustag(sc->aac_regs_res0);
 	sc->aac_bhandle0 = rman_get_bushandle(sc->aac_regs_res0);
 
-	if (sc->aac_hwif == AAC_HWIF_NARK) {
-		sc->aac_regs_rid1 = PCIR_BAR(1);
+	if (sc->aac_hwif == AAC_HWIF_SRC || sc->aac_hwif == AAC_HWIF_NARK) {
+		sc->aac_regs_rid1 = PCIR_BAR(2);
 		if ((sc->aac_regs_res1 = bus_alloc_resource_any(sc->aac_dev,
 		    SYS_RES_MEMORY, &sc->aac_regs_rid1, RF_ACTIVE)) == NULL) {
 			device_printf(sc->aac_dev,
@@ -419,33 +448,6 @@ aac_pci_attach(device_t dev)
 		goto out;
 	}
 
-	/* 
-	 * Detect the hardware interface version, set up the bus interface
-	 * indirection.
-	 */
-	id = aac_find_ident(dev);
-	sc->aac_hwif = id->hwif;
-	switch(sc->aac_hwif) {
-	case AAC_HWIF_I960RX:
-	case AAC_HWIF_NARK:
-		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for i960Rx/NARK");
-		sc->aac_if = aac_rx_interface;
-		break;
-	case AAC_HWIF_STRONGARM:
-		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for StrongARM");
-		sc->aac_if = aac_sa_interface;
-		break;
-	case AAC_HWIF_RKT:
-		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for Rocket/MIPS");
-		sc->aac_if = aac_rkt_interface;
-		break;
-	default:
-		sc->aac_hwif = AAC_HWIF_UNKNOWN;
-		device_printf(sc->aac_dev, "unknown hardware type\n");
-		error = ENXIO;
-		goto out;
-	}
-
 	/* Set up quirks */
 	sc->flags = id->quirks;
 
diff -pruN old/aacreg.h new/aacreg.h
--- old/aacreg.h	2011-03-31 14:57:34.000000000 +0000
+++ new/aacreg.h	2011-04-01 13:46:51.000000000 +0000
@@ -2,7 +2,8 @@
  * Copyright (c) 2000 Michael Smith
  * Copyright (c) 2000-2001 Scott Long
  * Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Adaptec, Inc.
+ * Copyright (c) 2001-2010 Adaptec, Inc.
+ * Copyright (c) 2010 PMC-Sierra, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -123,6 +124,14 @@ struct aac_queue_table {
 #define AAC_ADAP_NORM_RESP_QUEUE	6
 #define AAC_ADAP_HIGH_RESP_QUEUE	7
 
+/* transport FIB header (PMC) */
+struct aac_fib_xporthdr {
+	u_int64_t	HostAddress;	/* FIB host address w/o xport header */
+	u_int32_t	Size;			/* FIB size excluding xport header */
+	u_int32_t	Handle;			/* driver handle to reference the FIB */
+	u_int64_t	Reserved[2];
+} __packed;
+
 /*
  * List structure used to chain FIBs (used by the adapter - we hang FIBs off
  * our private command structure and don't touch these)
@@ -268,6 +277,7 @@ typedef enum {
 #define AAC_FIBSTATE_BIOSFIB		(1<<18)
 #define AAC_FIBSTATE_FAST_RESPONSE	(1<<19)	/* fast response capable */
 #define AAC_FIBSTATE_APIFIB		(1<<20)
+#define AAC_FIBSTATE_NOMOREAIF		(1<<21)
 
 /*
  * FIB error values
@@ -290,6 +300,7 @@ struct aac_adapter_init {
 	u_int32_t	InitStructRevision;
 #define AAC_INIT_STRUCT_REVISION		3
 #define AAC_INIT_STRUCT_REVISION_4		4
+#define AAC_INIT_STRUCT_REVISION_6		6
 	u_int32_t	MiniPortRevision;
 #define AAC_INIT_STRUCT_MINIPORT_REVISION	1
 	u_int32_t	FilesystemRevision;
@@ -306,12 +317,18 @@ struct aac_adapter_init {
 	u_int32_t	HostElapsedSeconds;
 	/* ADAPTER_INIT_STRUCT_REVISION_4 begins here */
 	u_int32_t	InitFlags;			/* flags for supported features */
-#define	AAC_INITFLAGS_NEW_COMM_SUPPORTED	1
-#define	AAC_INITFLAGS_DRIVER_USES_UTC_TIME	0x10
-#define	AAC_INITFLAGS_DRIVER_SUPPORTS_PM	0x20
+#define AAC_INITFLAGS_NEW_COMM_SUPPORTED	1
+#define AAC_INITFLAGS_DRIVER_USES_UTC_TIME	0x10
+#define AAC_INITFLAGS_DRIVER_SUPPORTS_PM	0x20
+#define AAC_INITFLAGS_NEW_COMM_TYPE1_SUPPORTED  0x41
 	u_int32_t	MaxIoCommands;		/* max outstanding commands */
 	u_int32_t	MaxIoSize;			/* largest I/O command */
 	u_int32_t	MaxFibSize;			/* largest FIB to adapter */
+	/* ADAPTER_INIT_STRUCT_REVISION_5 begins here */
+	u_int32_t	MaxNumAif;	        /* max number of aif */ 
+	/* ADAPTER_INIT_STRUCT_REVISION_6 begins here */
+	u_int32_t	HostRRQ_AddrLow;
+	u_int32_t	HostRRQ_AddrHigh;	/* Host RRQ (response queue) for SRC */
 } __packed;
 
 /*
@@ -578,6 +595,7 @@ typedef enum
 #define AAC_SUPPORTED_NEW_COMM		0x20000
 #define AAC_SUPPORTED_64BIT_ARRAYSIZE	0x40000
 #define AAC_SUPPORTED_HEAT_SENSOR	0x80000
+#define AAC_SUPPORTED_NEW_COMM_TYPE1	0x10000000  /* PMC type new comm */
 
 /* 
  * Structure used to respond to a RequestAdapterInfo fib.
@@ -606,6 +624,20 @@ struct aac_adapter_info {
 	AAC_OemFlavor	OemVariant;
 } __packed;
 
+/*
+ * More options from supplement info - SupportedOptions2
+ */
+#define AAC_SUPPORTED_MU_RESET			0x01
+#define AAC_SUPPORTED_IGNORE_RESET		0x02
+#define AAC_SUPPORTED_POWER_MANAGEMENT		0x04
+#define AAC_SUPPORTED_ARCIO_PHYDEV		0x08
+#define AAC_SUPPORTED_DOORBELL_RESET		0x4000
+
+/*
+ * FeatureBits of RequestSupplementAdapterInfo used in the driver
+ */
+#define AAC_SUPPL_SUPPORTED_JBOD	0x08000000
+
 /* 
  * Structure used to respond to a RequestSupplementAdapterInfo fib.
  */
@@ -654,8 +686,12 @@ struct aac_supplement_adapter_info {
 	u_int8_t		MfgPcbaSerialNo[MFG_PCBA_SERIAL_NUMBER_WIDTH];
 	/* WWN from the MFG sector */
 	u_int8_t		MfgWWNName[MFG_WWN_WIDTH];
-	/* Growth Area for future expansion ((7*4) - 12 - 8)/4 = 2 words */
-	u_int32_t	ReservedGrowth[2];
+	u_int32_t	SupportedOptions2;		/* more supported features */
+	u_int32_t	ExpansionFlag;			/* 1 - following fields are valid */
+	u_int32_t	FeatureBits3;
+	u_int32_t	SupportedPerformanceMode;
+	/* Growth Area for future expansion */
+	u_int32_t	ReservedGrowth[80];
 } __packed;
 
 /*
@@ -675,6 +711,8 @@ struct aac_supplement_adapter_info {
 #define AAC_MONKER_RCVTEMP	0x25
 #define AAC_MONKER_GETCOMMPREF	0x26
 #define AAC_MONKER_REINIT	0xee
+#define	AAC_IOP_RESET		0x1000
+#define	AAC_IOP_RESET_ALWAYS	0x1001
 
 /*
  *  Adapter Status Register
@@ -1004,7 +1042,8 @@ typedef enum {
 	AifReqSendAPIReport,	/* API generic report requests */
 	AifReqAPIJobStart,	/* Start a job from the API */
 	AifReqAPIJobUpdate,	/* Update a job report from the API */
-	AifReqAPIJobFinish	/* Finish a job from the API */
+	AifReqAPIJobFinish,	/* Finish a job from the API */
+	AifReqEvent = 200	/* PMC NEW COMM: Request the event data */
 } AAC_AifCommand;
 
 struct aac_aif_command {
@@ -1143,6 +1182,42 @@ typedef enum _VM_COMMANDS {
 	VM_NameServe64		 
 } AAC_VMCommand;
 
+/* Container Configuration Sub-Commands */
+#define CT_GET_SCSI_METHOD	64
+#define	CT_PAUSE_IO			65
+#define	CT_RELEASE_IO			66
+#define	CT_GET_CONFIG_STATUS		147
+#define	CT_COMMIT_CONFIG		152
+#define CT_PM_DRIVER_SUPPORT		245
+
+/* CT_PM_DRIVER_SUPPORT parameter */
+typedef enum {
+	AAC_PM_DRIVERSUP_GET_STATUS = 1,
+	AAC_PM_DRIVERSUP_START_UNIT,
+	AAC_PM_DRIVERSUP_STOP_UNIT
+} AAC_CT_PM_DRIVER_SUPPORT_SUB_COM;
+
+/*
+ * CT_PAUSE_IO is immediate minimal runtime command that is used
+ * to restart the applications and cache.
+ */
+struct aac_pause_command {
+	u_int32_t	Command;
+	u_int32_t	Type;
+	u_int32_t	Timeout;
+	u_int32_t	Min;
+	u_int32_t	NoRescan;
+	u_int32_t	Parm3;
+	u_int32_t	Parm4;
+	u_int32_t	Count;
+} __packed;
+
+/* Flag values for ContentState */
+#define AAC_FSCS_NOTCLEAN	0x1	/* fscheck is necessary before mounting */
+#define AAC_FSCS_READONLY	0x2	/* possible result of broken mirror */
+#define AAC_FSCS_HIDDEN		0x4	/* container should be ignored by driver */
+#define AAC_FSCS_NOT_READY	0x8	/* cnt is in spinn. state, not rdy for IO's */
+
 /*
  * "mountable object"
  */
@@ -1187,7 +1262,6 @@ struct aac_closecommand {
 /*
  * Container Config Command
  */
-#define CT_GET_SCSI_METHOD	64
 struct aac_ctcfg {
 	u_int32_t		Command;
 	u_int32_t		cmd;
@@ -1309,6 +1383,24 @@ typedef enum {
 	CMUNSTABLE
 } AAC_CommitLevel;
 
+
+#define	CT_FIB_PARAMS			6
+#define	MAX_FIB_PARAMS			10
+#define	CT_PACKET_SIZE \
+	(AAC_FIB_DATASIZE - sizeof (u_int32_t) - \
+	((sizeof (u_int32_t)) * (MAX_FIB_PARAMS + 1)))
+
+struct aac_fsa_ctm {
+	u_int32_t	command;
+	u_int32_t	param[CT_FIB_PARAMS];
+	int8_t		data[CT_PACKET_SIZE];
+};
+
+struct aac_cnt_config {
+	u_int32_t		Command;
+	struct aac_fsa_ctm	CTCommand;
+};
+
 /*
  * Block read/write operations.
  * These structures are packed into the 'data' area in the FIB.
@@ -1378,7 +1470,7 @@ struct aac_raw_io {
 struct aac_close_command {
 	u_int32_t		Command;
 	u_int32_t		ContainerId;
-};
+} __packed;
 
 /*
  * SCSI Passthrough structures
@@ -1395,7 +1487,7 @@ struct aac_srb {
 	u_int32_t		cdb_len;
 	u_int8_t		cdb[16];
 	struct aac_sg_table	sg_map;
-};
+} __packed;
 
 enum {
 	AAC_SRB_FUNC_EXECUTE_SCSI	= 0x00,
@@ -1436,7 +1528,7 @@ struct aac_srb_response {
 	u_int32_t	data_len;
 	u_int32_t	sense_len;
 	u_int8_t	sense[AAC_HOST_SENSE_DATA_MAX];
-};
+} __packed;
 
 /*
  * Status codes for SCSI passthrough commands.  Since they are based on ASPI,
@@ -1531,6 +1623,29 @@ enum {
 #define AAC_RKT_FWSTATUS	0x101c	/* Firmware Status (mailbox 7) */
 
 /*
+ * Register definitions for the Adaptec PMC SRC adapters.
+ */
+/* accessible via BAR0 */
+#define AAC_SRC_OMR			0xbc	/* outbound message register */
+#define AAC_SRC_IDBR		0x20	/* inbound doorbell register */
+#define AAC_SRC_IISR		0x24	/* inbound interrupt status register */
+#define AAC_SRC_ODBR_R		0x9c	/* outbound doorbell register read */
+#define AAC_SRC_ODBR_C		0xa0	/* outbound doorbell register clear */
+#define AAC_SRC_OIMR		0x34	/* outbound interrupt mask register */
+#define AAC_SRC_IQUE_L		0xc0	/* inbound queue address (low) */
+#define AAC_SRC_IQUE_H		0xc4	/* inbound queue address (high) */
+
+#define AAC_SRC_MAILBOX		0x7fc60	/* mailbox (20 bytes) */
+
+#define AAC_SRC_ODR_SHIFT 	12		/* outbound doorbell shift */
+#define AAC_SRC_IDR_SHIFT 	9		/* inbound doorbell shift */
+
+/* Sunrise Lake dual core reset */
+#define AAC_IRCSR		0x38	/* inbound dual cores reset */
+#define AAC_IRCSR_CORES_RST	3
+
+
+/*
  * Common bit definitions for the doorbell registers.
  */
 
@@ -1542,6 +1657,9 @@ enum {
 #define AAC_DB_RESPONSE_READY	(1<<2)	/* one or more commands complete */
 #define AAC_DB_COMMAND_NOT_FULL	(1<<3)	/* command queue not full */
 #define AAC_DB_RESPONSE_NOT_FULL (1<<4)	/* response queue not full */
+#define AAC_DB_AIF_PENDING		(1<<6)	/* pending AIF (new comm. type1) */
+/* PMC specific outbound doorbell bits */
+#define AAC_DB_RESPONSE_SENT_NS		(1<<1)	/* response sent (not shifted) */
 
 /*
  * The adapter can request the host print a message by setting the
@@ -1560,5 +1678,6 @@ enum {
 #define AAC_DB_INTERRUPTS	(AAC_DB_COMMAND_READY  |	\
 				 AAC_DB_RESPONSE_READY |	\
 				 AAC_DB_PRINTF)
-#define AAC_DB_INT_NEW_COMM		0x08		
+#define AAC_DB_INT_NEW_COMM		0x08  
+#define AAC_DB_INT_NEW_COMM_TYPE1	0x04
 
diff -pruN old/aacvar.h new/aacvar.h
--- old/aacvar.h	2011-03-31 14:57:34.000000000 +0000
+++ new/aacvar.h	2011-04-01 14:01:48.000000000 +0000
@@ -2,7 +2,8 @@
  * Copyright (c) 2000 Michael Smith
  * Copyright (c) 2001 Scott Long
  * Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Adaptec, Inc.
+ * Copyright (c) 2001-2010 Adaptec, Inc.
+ * Copyright (c) 2010 PMC-Sierra, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,8 +44,8 @@
 #define	AAC_TYPE_RELEASE		4
 
 #define	AAC_DRIVER_MAJOR_VERSION	2
-#define	AAC_DRIVER_MINOR_VERSION	1
-#define	AAC_DRIVER_BUGFIX_LEVEL		9
+#define	AAC_DRIVER_MINOR_VERSION	4
+#define	AAC_DRIVER_BUGFIX_LEVEL		1
 #define	AAC_DRIVER_TYPE			AAC_TYPE_RELEASE
 
 #ifndef AAC_DRIVER_BUILD
@@ -56,12 +57,6 @@
  */
 
 /*
- * The firmware interface allows for a 16-bit s/g list length.  We limit 
- * ourselves to a reasonable maximum and ensure alignment.
- */
-#define AAC_MAXSGENTRIES	64	/* max S/G entries, limit 65535 */		
-
-/*
  * We allocate a small set of FIBs for the adapter to use to send us messages.
  */
 #define AAC_ADAPTER_FIBS	8
@@ -176,14 +171,15 @@ struct aac_command
 #define AAC_ON_AACQ_AIF		(1<<8)
 #define AAC_ON_AACQ_NORM	(1<<10)
 #define AAC_ON_AACQ_MASK	((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10))
-#define AAC_QUEUE_FRZN		(1<<9)		/* Freeze the processing of
-						 * commands on the queue. */
+#define AAC_CMD_RESET		(1<<9)
 
 	void			(* cm_complete)(struct aac_command *cm);
 	void			*cm_private;
 	time_t			cm_timestamp;	/* command creation time */
 	int			cm_queue;
 	int			cm_index;
+	bus_dma_tag_t		cm_passthr_dmat;	/* passthrough buffer/command
+							 * DMA tag */
 };
 
 struct aac_fibmap {
@@ -222,6 +218,9 @@ struct aac_common {
 	
 	/* fib for synchronous commands */
 	struct aac_fib		ac_sync_fib;
+
+	/* response buffer for SRC (new comm. type1) - must be last element */
+	u_int32_t   ac_host_rrq[0];
 };
 
 /*
@@ -244,8 +243,8 @@ struct aac_interface 
 };
 extern struct aac_interface	aac_rx_interface;
 extern struct aac_interface	aac_sa_interface;
-extern struct aac_interface	aac_fa_interface;
 extern struct aac_interface	aac_rkt_interface;
+extern struct aac_interface	aac_src_interface;
 
 #define AAC_GET_FWSTATUS(sc)		((sc)->aac_if.aif_get_fwstatus((sc)))
 #define AAC_QNOTIFY(sc, qbit)		((sc)->aac_if.aif_qnotify((sc), (qbit)))
@@ -324,6 +323,7 @@ struct aac_softc 
 #define	AAC_STATE_UNUSED0	(1<<1)
 #define AAC_STATE_INTERRUPTS_ON	(1<<2)
 #define AAC_STATE_AIF_SLEEPER	(1<<3)
+#define AAC_STATE_RESET		(1<<4)
 	struct FsaRevision		aac_revision;
 
 	/* controller hardware interface */
@@ -332,6 +332,7 @@ struct aac_softc 
 #define AAC_HWIF_STRONGARM	1
 #define AAC_HWIF_RKT		3
 #define	AAC_HWIF_NARK		4
+#define AAC_HWIF_SRC		5
 #define AAC_HWIF_UNKNOWN	-1
 	bus_dma_tag_t		aac_common_dmat;	/* common structure
 							 * DMA tag */
@@ -339,6 +340,7 @@ struct aac_softc 
 							 * DMA map */
 	struct aac_common	*aac_common;
 	u_int32_t		aac_common_busaddr;
+	u_int32_t		aac_host_rrq_idx;
 	struct aac_interface	aac_if;
 
 	/* command/fib resources */
@@ -381,6 +383,7 @@ struct aac_softc 
 	struct aac_fib		aac_aifq[AAC_AIFQ_LENGTH];
 	int			aifq_idx;
 	int			aifq_filled;
+	int 			aif_pending;
 	struct aac_fib_context *fibctx;
 	struct selinfo		rcv_select;
 	struct proc		*aifthread;
@@ -409,8 +412,12 @@ struct aac_softc 
 #define AAC_FLAGS_NEW_COMM	(1 << 11)	/* New comm. interface supported */
 #define AAC_FLAGS_RAW_IO	(1 << 12)	/* Raw I/O interface */
 #define AAC_FLAGS_ARRAY_64BIT	(1 << 13)	/* 64-bit array size */
-#define	AAC_FLAGS_LBA_64BIT	(1 << 14)	/* 64-bit LBA support */
-
+#define AAC_FLAGS_LBA_64BIT	(1 << 14)	/* 64-bit LBA support */
+#define AAC_QUEUE_FRZN		(1 << 15)	/* Freeze the processing of
+						 * commands on the queue. */
+#define AAC_FLAGS_NEW_COMM_TYPE1 (1 << 16)	/* New comm. type1 supported */
+	u_int32_t		hint_flags;		/* driver parameters */
+	int	sim_freezed;				/* flag for sim_freeze/release */		
 	u_int32_t		supported_options;
 	u_int32_t		scsi_method_id;
 	TAILQ_HEAD(,aac_sim)	aac_sim_tqh;
@@ -422,6 +429,9 @@ struct aac_softc 
 	u_int32_t	aac_max_fib_size;		/* max. FIB size */
 	u_int32_t	aac_sg_tablesize;		/* max. sg count from host */
 	u_int32_t	aac_max_sectors;		/* max. I/O size from host (blocks) */
+	u_int32_t	aac_feature_bits;		/* feature bits from suppl. info */
+	u_int32_t	aac_support_opt2;		/* supp. options from suppl. info */
+	u_int32_t	aac_max_aif;			/* max. AIF count */
 #define AAC_CAM_TARGET_WILDCARD ~0
 	void			(*cam_rescan_cb)(struct aac_softc *, uint32_t,
 				    uint32_t);
@@ -453,6 +463,7 @@ extern int		aac_detach(device_t dev);
 extern int		aac_shutdown(device_t dev);
 extern int		aac_suspend(device_t dev); 
 extern int		aac_resume(device_t dev);
+extern void		aac_new_intr_type1(void *arg);
 extern void		aac_new_intr(void *arg);
 extern int		aac_filter(void *arg);
 extern void		aac_submit_bio(struct bio *bp);


More information about the freebsd-scsi mailing list