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