diff options
author | scottl <scottl@FreeBSD.org> | 2001-08-29 23:34:05 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2001-08-29 23:34:05 +0000 |
commit | ca93e132a40987f527cf6023647c4a067283a0f5 (patch) | |
tree | 9664aff7481b95b2f50a88ff50e381ca89fc4235 | |
parent | d118ae3895cbb757e23c8a19dfe269d7e5348b2f (diff) | |
download | FreeBSD-src-ca93e132a40987f527cf6023647c4a067283a0f5.zip FreeBSD-src-ca93e132a40987f527cf6023647c4a067283a0f5.tar.gz |
Mega update to the aac driver.
1. Correctly handle commands initiated by the adapter. These commands
are defered to a kthread responsible for their processing, then are
properly returned to the controller.
2. Add/remove disk devices when notified by the card that a container was
created/deleted/offline.
3. Implement crashdump functionality.
4. Support all ioctls needed for the management CLI to work. The linux
version of this app can be found at the Dell or HP website. A native
version will be forthcoming.
MFC-after: 4.4-RELEASE
-rw-r--r-- | share/man/man4/aac.4 | 16 | ||||
-rw-r--r-- | sys/dev/aac/aac.c | 592 | ||||
-rw-r--r-- | sys/dev/aac/aac_debug.c | 2 | ||||
-rw-r--r-- | sys/dev/aac/aac_disk.c | 116 | ||||
-rw-r--r-- | sys/dev/aac/aac_ioctl.h | 28 | ||||
-rw-r--r-- | sys/dev/aac/aac_pci.c | 8 | ||||
-rw-r--r-- | sys/dev/aac/aacreg.h | 2 | ||||
-rw-r--r-- | sys/dev/aac/aacvar.h | 54 | ||||
-rw-r--r-- | sys/sys/aac_ioctl.h | 28 |
9 files changed, 718 insertions, 128 deletions
diff --git a/share/man/man4/aac.4 b/share/man/man4/aac.4 index 4857721..630b2df 100644 --- a/share/man/man4/aac.4 +++ b/share/man/man4/aac.4 @@ -48,7 +48,7 @@ Supported controllers include: .It AAC-364 .It -AAC-3642 +Adaptec SCSI RAID 5400S .It HP NetRAID 4M .It @@ -86,12 +86,6 @@ Compiling the driver with the option enables the Linux-compatible .Xr ioctl 2 interface for the management device. -The -.Xr ioctl 2 -command set is heavily tailored to existing Linux applications. -Native -.Xr ioctl 2 -support is not present at this time. .Ss Tuning The read-only sysctl .Va hw.aac.iosize_max @@ -148,13 +142,9 @@ and is .An Scott Long .Aq scottl@FreeBSD.org .Sh BUGS -This driver has not been tested on Alpha, though it should work. +This driver will not work on systems with more than 4GB of memory. .Pp The controller is not actually paused on suspend/resume. .Pp -Adapter-initiated messages are not returned back to the controller, -possibly causing a resource leak on the controller. -.Pp -Unloading and reloading the driver as a kernel loadable module -without rebooting the system is strongly discouraged. +Unloading driver is not supported at this time. .Pp diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index d679bc8..aedd939 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -35,11 +35,12 @@ #include "opt_aac.h" -/* include <stddef.h> */ +/* #include <stddef.h> */ #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kernel.h> +#include <sys/kthread.h> #include <sys/sysctl.h> #include <dev/aac/aac_compat.h> @@ -51,6 +52,7 @@ #include <sys/file.h> #include <sys/signalvar.h> #include <sys/time.h> +#include <sys/eventhandler.h> #include <machine/bus_memio.h> #include <machine/bus.h> @@ -101,7 +103,10 @@ static int aac_sync_fib(struct aac_softc *sc, u_int32_t command, static int aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm); static int aac_dequeue_fib(struct aac_softc *sc, int queue, - u_int32_t *fib_size, struct aac_fib **fib_addr); + u_int32_t *fib_size, + struct aac_fib **fib_addr); +static int aac_enqueue_response(struct aac_softc *sc, int queue, + struct aac_fib *fib); /* StrongARM interface */ static int aac_sa_get_fwstatus(struct aac_softc *sc); @@ -147,7 +152,7 @@ struct aac_interface aac_rx_interface = { /* Debugging and Diagnostics */ static void aac_describe_controller(struct aac_softc *sc); -static char *aac_describe_code(struct aac_code_lookup *table, +static char *aac_describe_code(struct aac_code_lookup *table u_int32_t code); /* Management Interface */ @@ -156,10 +161,11 @@ static d_close_t aac_close; static d_ioctl_t aac_ioctl; static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib); static void aac_handle_aif(struct aac_softc *sc, - struct aac_aif_command *aif); + struct aac_fib *fib); static int aac_rev_check(struct aac_softc *sc, caddr_t udata); static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg); static int aac_return_aif(struct aac_softc *sc, caddr_t uptr); +static int aac_query_disk(struct aac_softc *sc, caddr_t uptr); #define AAC_CDEV_MAJOR 150 @@ -177,8 +183,13 @@ static struct cdevsw aac_cdevsw = { nodump, /* dump */ nopsize, /* psize */ 0, /* flags */ +#if __FreeBSD_version < 500005 + -1, /* bmaj */ +#endif }; +MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver"); + /* sysctl node */ SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters"); @@ -240,6 +251,9 @@ aac_attach(struct aac_softc *sc) /* * Register to probe our containers later. */ + TAILQ_INIT(&sc->aac_container_tqh); + AAC_LOCK_INIT(&sc->aac_container_lock); + sc->aac_ich.ich_func = aac_startup; sc->aac_ich.ich_arg = sc; if (config_intrhook_establish(&sc->aac_ich) != 0) { @@ -253,11 +267,27 @@ aac_attach(struct aac_softc *sc) unit = device_get_unit(sc->aac_dev); sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_WHEEL, 0644, "aac%d", unit); +#if __FreeBSD_version > 500005 (void)make_dev_alias(sc->aac_dev_t, "afa%d", unit); (void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit); - +#endif sc->aac_dev_t->si_drv1 = sc; + /* Create the AIF thread */ +#if __FreeBSD_version > 500005 + if (kthread_create((void(*)(void *))aac_host_command, sc, &sc->aifthread, + 0, "aac%daif", unit)) +#else + if (kthread_create((void(*)(void *))aac_host_command, sc, &sc->aifthread, + "aac%daif", unit)) +#endif + panic("Could not create AIF thread\n"); + + /* Register the shutdown method to only be called post-dump */ + if ((EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown, sc->aac_dev, + SHUTDOWN_PRI_DEFAULT)) == NULL) + device_printf(sc->aac_dev, "shutdown event registration failed\n"); + return(0); } @@ -270,9 +300,10 @@ aac_startup(void *arg) struct aac_softc *sc = (struct aac_softc *)arg; struct aac_mntinfo mi; struct aac_mntinforesponse mir; + struct aac_container *co; device_t child; u_int16_t rsize; - int i; + int i = 0; debug_called(1); @@ -282,7 +313,7 @@ aac_startup(void *arg) /* loop over possible containers */ mi.Command = VM_NameServe; mi.MntType = FT_FILESYS; - for (i = 0; i < AAC_MAX_CONTAINERS; i++) { + do { /* request information on this container */ mi.MntCount = i; rsize = sizeof(mir); @@ -302,6 +333,9 @@ aac_startup(void *arg) * possible types may never show up. */ if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType != CT_NONE)) { + MALLOC(co, struct aac_container *, sizeof *co, M_AACBUF, M_NOWAIT); + if (co == NULL) + panic("Out of memory?!\n"); debug(1, "%d: id %x name '%.16s' size %u type %d", i, mir.MntTable[0].ObjectId, mir.MntTable[0].FileSystemName, mir.MntTable[0].Capacity, @@ -310,14 +344,17 @@ aac_startup(void *arg) if ((child = device_add_child(sc->aac_dev, NULL, -1)) == NULL) { device_printf(sc->aac_dev, "device_add_child failed\n"); } else { - device_set_ivars(child, &sc->aac_container[i]); + device_set_ivars(child, co); } device_set_desc(child, aac_describe_code(aac_container_types, mir.MntTable[0].VolType)); - sc->aac_container[i].co_disk = child; - sc->aac_container[i].co_mntobj = mir.MntTable[0]; + co->co_disk = child; + co->co_found = 0; + bcopy(&mir.MntTable[0], &co->co_mntobj, sizeof(struct aac_mntobj)); + TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link); } - } + i++; + } while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS)); /* poke the bus to actually attach the child devices */ if (bus_generic_attach(sc->aac_dev)) @@ -390,19 +427,34 @@ int aac_detach(device_t dev) { struct aac_softc *sc = device_get_softc(dev); +#if AAC_BROKEN int error; +#endif debug_called(1); if (sc->aac_state & AAC_STATE_OPEN) return(EBUSY); +#if AAC_BROKEN + if (sc->aifflags & AAC_AIFFLAGS_RUNNING) { + sc->aifflags |= AAC_AIFFLAGS_EXIT; + wakeup(sc->aifthread); + tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz); + } + + if (sc->aifflags & AAC_AIFFLAGS_RUNNING) + panic("Cannot shutdown AIF thread\n"); + if ((error = aac_shutdown(dev))) return(error); aac_free(sc); return(0); +#else + return (EBUSY); +#endif } /****************************************************************************** @@ -439,6 +491,12 @@ aac_shutdown(device_t dev) printf("FAILED.\n"); } else { i = 0; + /* + * XXX Issuing this command to the controller makes it shut down, + * but also keeps it from coming back up without a reset of the + * PCI bus. This is not desirable if you are just unloading the + * driver module with the intent to reload it later. + */ if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i, sizeof(i), NULL, NULL)) { printf("FAILED.\n"); @@ -486,7 +544,7 @@ aac_resume(device_t dev) return(0); } -/****************************************************************************** +/******************************************************************************* * Take an interrupt. */ void @@ -499,21 +557,24 @@ aac_intr(void *arg) reason = AAC_GET_ISTATUS(sc); - /* controller wants to talk to the log? XXX should we defer this? */ + /* controller wants to talk to the log? Defer it to the AIF thread */ if (reason & AAC_DB_PRINTF) { - if (sc->aac_common->ac_printf[0]) { - device_printf(sc->aac_dev, "** %.*s", AAC_PRINTF_BUFSIZE, - sc->aac_common->ac_printf); - sc->aac_common->ac_printf[0] = 0; - } AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); - AAC_QNOTIFY(sc, AAC_DB_PRINTF); + if (sc->aifflags & AAC_AIFFLAGS_RUNNING) { + sc->aifflags |= AAC_AIFFLAGS_PENDING; + wakeup(sc->aifthread); + } else + aac_print_printf(sc); } /* controller has a message for us? */ if (reason & AAC_DB_COMMAND_READY) { AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY); - aac_host_command(sc); + /* XXX What happens if the thread is already awake? */ + if (sc->aifflags & AAC_AIFFLAGS_RUNNING) { + sc->aifflags |= AAC_AIFFLAGS_PENDING; + wakeup(sc->aifthread); + } } /* controller has a response for us? */ @@ -594,7 +655,7 @@ aac_start(struct aac_command *cm) * address issue */ /* put the FIB on the outbound queue */ - error = aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, cm); + error = aac_enqueue_fib(sc, cm->cm_queue, cm); return(error); } @@ -606,26 +667,74 @@ aac_host_command(struct aac_softc *sc) { struct aac_fib *fib; u_int32_t fib_size; + int size; - debug_called(1); + debug_called(2); - for (;;) { - if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib)) - break; /* nothing to do */ + sc->aifflags |= AAC_AIFFLAGS_RUNNING; + + while(!(sc->aifflags & AAC_AIFFLAGS_EXIT)) { + if (!(sc->aifflags & AAC_AIFFLAGS_PENDING)) + tsleep(sc->aifthread, PRIBIO, "aifthd", 15 * hz); + + sc->aifflags &= ~AAC_AIFFLAGS_PENDING; + for (;;) { + if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib)) + break; /* nothing to do */ - switch(fib->Header.Command) { - case AifRequest: - aac_handle_aif(sc, (struct aac_aif_command *)&fib->data[0]); - break; - default: - device_printf(sc->aac_dev, "unknown command from controller\n"); AAC_PRINT_FIB(sc, fib); - break; + + switch(fib->Header.Command) { + case AifRequest: + aac_handle_aif(sc, fib); + break; + default: + device_printf(sc->aac_dev, "unknown command from controller\n"); + break; + } + + /* Return the AIF to the controller. */ + if ((fib->Header.XferState == 0) || + (fib->Header.StructType != AAC_FIBTYPE_TFIB)) + break; + + if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) { + if (!(fib->Header.XferState & AAC_FIBSTATE_NORM)) { + /* + * XXX How to recover from this? If anything goes on + * the high priority queue, the controller will panic. + * Since it came on the normal priority queue, just + * punt and return it there. + */ + device_printf(sc->aac_dev, "Error: Attempted to return " + "an AIF not at normal priority\n"); + } + fib->Header.XferState |= AAC_FIBSTATE_DONEHOST; + *(AAC_FSAStatus*)fib->data = ST_OK; + + /* XXX Compute the Size field? */ + size = fib->Header.Size; + if (size > sizeof(struct aac_fib)) { + size = sizeof(struct aac_fib); + fib->Header.Size = size; + } + /* + * Since we did not generate this command, it cannot go + * through the normal enqueue->startio chain. + */ + aac_enqueue_response(sc, AAC_ADAP_NORM_RESP_QUEUE, fib); + } } + aac_print_printf(sc); - /* XXX reply to FIBs requesting responses ?? */ - /* XXX how do we return these FIBs to the controller? */ } + sc->aifflags &= ~AAC_AIFFLAGS_RUNNING; + wakeup(sc->aac_dev); + +#if __FreeBSD_version > 500005 + mtx_lock(&Giant); +#endif + kthread_exit(0); } /****************************************************************************** @@ -739,6 +848,7 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) cm->cm_complete = aac_bio_complete; cm->cm_private = bp; cm->cm_timestamp = time_second; + cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; /* build the FIB */ fib = cm->cm_fib; @@ -820,6 +930,95 @@ aac_bio_complete(struct aac_command *cm) } /****************************************************************************** + * Dump a block of data to the controller. If the queue is full, tell the + * caller to hold off and wait for the queue to drain + */ +int +aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, void *data, int dumppages) +{ + struct aac_softc *sc = ad->ad_controller; + struct aac_command *cm = NULL; + struct aac_fib *fib; + struct aac_blockwrite *bw; + + if (aac_alloc_command(sc, &cm)) + return (EBUSY); + + /* fill out the command */ + cm->cm_data = data; + cm->cm_datalen = dumppages * PAGE_SIZE; + cm->cm_complete = NULL; + cm->cm_private = NULL; + cm->cm_timestamp = time_second; + cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; + + /* build the FIB */ + fib = cm->cm_fib; + fib->Header.XferState = + AAC_FIBSTATE_HOSTOWNED | + AAC_FIBSTATE_INITIALISED | + AAC_FIBSTATE_FROMHOST | + AAC_FIBSTATE_REXPECTED | + AAC_FIBSTATE_NORM; + fib->Header.Command = ContainerCommand; + fib->Header.Size = sizeof(struct aac_fib_header); + + bw = (struct aac_blockwrite *)&fib->data[0]; + bw->Command = VM_CtBlockWrite; + bw->ContainerId = ad->ad_container->co_mntobj.ObjectId; + bw->BlockNumber = lba; + bw->ByteCount = dumppages * PAGE_SIZE; + bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */ + fib->Header.Size += sizeof(struct aac_blockwrite); + cm->cm_flags |= AAC_CMD_DATAOUT; + cm->cm_sgtable = &bw->SgMap; + + return (aac_start(cm)); +} + +/****************************************************************************** + * Wait for the card's queue to drain when dumping. Also check for monitor + * printf's + */ +void +aac_dump_complete(struct aac_softc *sc) +{ + struct aac_fib *fib; + struct aac_command *cm; + u_int16_t reason; + u_int32_t pi, ci, fib_size; + + do { + reason = AAC_GET_ISTATUS(sc); + if (reason & AAC_DB_RESPONSE_READY) { + AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); + for (;;) { + if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, + &fib_size, &fib)) + break; + cm = (struct aac_command *)fib->Header.SenderData; + if (cm == NULL) { + AAC_PRINT_FIB(sc, fib); + } else { + aac_remove_busy(cm); + aac_unmap_command(cm); + aac_enqueue_complete(cm); + aac_release_command(cm); + } + } + } + if (reason & AAC_DB_PRINTF) { + AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); + aac_print_printf(sc); + } + pi = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX]; + ci = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX]; + } while (ci != pi); + + return; +} + +/****************************************************************************** * Submit a command to the controller, return when it completes. */ static int @@ -830,11 +1029,14 @@ aac_wait_command(struct aac_command *cm, int timeout) debug_called(2); /* Put the command on the ready queue and get things going */ + cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; aac_enqueue_ready(cm); aac_startio(cm->cm_sc); s = splbio(); while(!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) { - error = tsleep(cm, PRIBIO, "aacwait", 0); + error = tsleep(cm, PRIBIO | PCATCH, "aacwait", 0); + if ((error == ERESTART) || (error == EINTR)) + break; } splx(s); return(error); @@ -1082,7 +1284,7 @@ aac_init(struct aac_softc *sc) } if (time_second > (then + AAC_BOOT_TIMEOUT)) { device_printf(sc->aac_dev, "FATAL: controller not coming ready, " - "status %x\n", code); + "status %x\n", code); return(ENXIO); } } while (!(code & AAC_UP_AND_RUNNING)); @@ -1328,7 +1530,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, return(0); } -/******************************************************************************** +/****************************************************************************** * Adapter-space FIB queue manipulation * * Note that the queue implementation here is a little funky; neither the PI or @@ -1353,8 +1555,7 @@ static struct { * EBUSY if the queue is full. * * Note: it would be more efficient to defer notifying the controller in - * the case where we may be inserting several entries in rapid succession, - * but implementing this usefully may be difficult (it would involve a + * the case where we may be inserting several entries in rapid succession, * but implementing this usefully may be difficult (it would involve a * separate queue/notify interface). */ static int @@ -1365,11 +1566,11 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm) u_int32_t fib_size; u_int32_t fib_addr; - fib_size = cm->cm_fib->Header.Size; - fib_addr = cm->cm_fib->Header.ReceiverFibAddress; - debug_called(3); + fib_size = cm->cm_fib->Header.Size; + fib_addr = cm->cm_fib->Header.ReceiverFibAddress; + s = splbio(); /* get the producer/consumer indices */ @@ -1411,8 +1612,8 @@ out: } /* - * Atomically remove one entry from the nominated queue, returns 0 on success or - * ENOENT if the queue is empty. + * Atomically remove one entry from the nominated queue, returns 0 on + * success or ENOENT if the queue is empty. */ static int aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, @@ -1462,6 +1663,58 @@ out: } /****************************************************************************** + * Put our response to an Adapter Initialed Fib on the response queue + */ +static int +aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib) +{ + u_int32_t pi, ci; + int s, error; + u_int32_t fib_size; + u_int32_t fib_addr; + + debug_called(1); + + /* Tell the adapter where the FIB is */ + fib_size = fib->Header.Size; + fib_addr = fib->Header.SenderFibAddress; + fib->Header.ReceiverFibAddress = fib_addr; + + s = splbio(); + + /* get the producer/consumer indices */ + pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; + ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; + + /* wrap the queue? */ + if (pi >= aac_qinfo[queue].size) + pi = 0; + + /* check for queue full */ + if ((pi + 1) == ci) { + error = EBUSY; + goto out; + } + + /* populate queue entry */ + (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; + (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; + + /* update producer index */ + sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; + + /* notify the adapter if we know how */ + if (aac_qinfo[queue].notify != 0) + AAC_QNOTIFY(sc, aac_qinfo[queue].notify); + + error = 0; + +out: + splx(s); + return(error); +} + +/****************************************************************************** * Check for commands that have been outstanding for a suspiciously long time, * and complain about them. */ @@ -1483,19 +1736,19 @@ aac_timeout(struct aac_softc *sc) s = splbio(); aac_intr(sc); splx(s); -#endif /* kick the I/O queue to restart it in the case of deadlock */ aac_startio(sc); +#endif /* traverse the busy command list, bitch about late commands once only */ deadline = time_second - AAC_CMD_TIMEOUT; s = splbio(); TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) { - if ((cm->cm_timestamp < deadline) - /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) { + if ((cm->cm_timestamp < deadline) + /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) { cm->cm_flags |= AAC_CMD_TIMEDOUT; - device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n", + device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm, (int)(time_second - cm->cm_timestamp)); AAC_PRINT_FIB(sc, cm->cm_fib); } @@ -1699,19 +1952,19 @@ aac_describe_controller(struct aac_softc *sc) } info = (struct aac_adapter_info *)&buf[0]; - device_printf(sc->aac_dev, "%s %dMHz, %dMB total memory, %s (%d)\n", + device_printf(sc->aac_dev, "%s %dMHz, %dMB cache memory, %s\n", aac_describe_code(aac_cpu_variant, info->CpuVariant), - info->ClockSpeed, info->TotalMem / (1024 * 1024), - aac_describe_code(aac_battery_platform, - info->batteryPlatform), info->batteryPlatform); + info->ClockSpeed, info->BufferMem / (1024 * 1024), + aac_describe_code(aac_battery_platform, info->batteryPlatform)); /* save the kernel revision structure for later use */ sc->aac_revision = info->KernelRevision; - device_printf(sc->aac_dev, "Kernel %d.%d-%d, S/N %llx\n", + device_printf(sc->aac_dev, "Kernel %d.%d-%d, Build %d, S/N %6X\n", info->KernelRevision.external.comp.major, info->KernelRevision.external.comp.minor, info->KernelRevision.external.comp.dash, - info->SerialNumber); /* XXX format? */ + info->KernelRevision.buildNumber, + (u_int32_t)(info->SerialNumber & 0xffffff)); } /****************************************************************************** @@ -1792,7 +2045,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) break; case FSACTL_SENDFIB: - arg = *(caddr_t *)arg; + arg = *(caddr_t*)arg; case FSACTL_LNX_SENDFIB: debug(1, "FSACTL_SENDFIB"); error = aac_ioctl_sendfib(sc, arg); @@ -1803,7 +2056,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) error = EINVAL; break; case FSACTL_OPEN_GET_ADAPTER_FIB: - arg = *(caddr_t *)arg; + arg = *(caddr_t*)arg; case FSACTL_LNX_OPEN_GET_ADAPTER_FIB: debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB"); /* @@ -1815,12 +2068,14 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) * * The Linux code hands the driver a pointer into kernel space, * and then trusts it when the caller hands it back. Aiee! + * Here, we give it the proc pointer of the per-adapter aif thread. + * It's only used as a sanity check in other calls. */ - i = AAC_AIF_SILLYMAGIC; + i = (int)sc->aifthread; error = copyout(&i, arg, sizeof(i)); break; case FSACTL_GET_NEXT_ADAPTER_FIB: - arg = *(caddr_t *)arg; + arg = *(caddr_t*)arg; case FSACTL_LNX_GET_NEXT_ADAPTER_FIB: debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB"); error = aac_getnext_aif(sc, arg); @@ -1831,11 +2086,21 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) /* don't do anything here */ break; case FSACTL_MINIPORT_REV_CHECK: - arg = *(caddr_t *)arg; + arg = *(caddr_t*)arg; case FSACTL_LNX_MINIPORT_REV_CHECK: debug(1, "FSACTL_MINIPORT_REV_CHECK"); error = aac_rev_check(sc, arg); break; + case FSACTL_QUERY_DISK: + arg = *(caddr_t*)arg; + case FSACTL_LNX_QUERY_DISK: + debug(1, "FSACTL_QUERY_DISK"); + error = aac_query_disk(sc, arg); + break; + case FSACTL_DELETE_DISK: + case FSACTL_LNX_DELETE_DISK: + error = 0; + break; default: device_printf(sc->aac_dev, "unsupported cmd 0x%lx\n", cmd); error = EINVAL; @@ -1907,17 +2172,140 @@ out: /****************************************************************************** * Handle an AIF sent to us by the controller; queue it for later reference. - * - * XXX what's the right thing to do here when the queue is full? Drop the older - * or newer entries? + * If the queue fills up, then drop the older entries. */ static void -aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif) +aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) { - int next, s; + device_t child; + struct aac_aif_command *aif; + struct aac_container *co, *co_next; + struct aac_mntinfo mi; + struct aac_mntinforesponse mir; + u_int16_t rsize; + int next, s, found; + int added = 0, i = 0; debug_called(2); + aif = (struct aac_aif_command*)&fib->data[0]; + aac_print_aif(sc, aif); + + /* Is it an event that we should care about? */ + switch (aif->command) { + case AifCmdEventNotify: + switch (aif->data.EN.type) { + case AifEnAddContainer: + case AifEnDeleteContainer: + /* + * A container was added or deleted, but the message doesn't tell us + * anything else! Re-enumerate the containers and sort things out. + */ + mi.Command = VM_NameServe; + mi.MntType = FT_FILESYS; + do { + /* + * Ask the controller for its containers one at a time. + * XXX What if the controller's list changes midway through + * this enumaration? + * XXX This should be done async. + */ + mi.MntCount = i; + rsize = sizeof(mir); + if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), + &mir, &rsize)) { + debug(2, "Error probing container %d\n", i); + continue; + } + if (rsize != sizeof(mir)) { + debug(2, "Container response size too large\n"); + continue; + } + /* + * Check the container against our list. co->co_found + * was already set to 0 in a previous run. + */ + if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType != + CT_NONE)) { + found = 0; + TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) { + if (co->co_mntobj.ObjectId == + mir.MntTable[0].ObjectId) { + co->co_found = 1; + found = 1; + break; + } + } + /* If the container matched, continue on in the list */ + if (found) { + i++; + continue; + } + + /* + * This is a new container. Do all the appropriate things + * to set it up. + */ + MALLOC(co, struct aac_container *, sizeof *co, M_AACBUF, + M_WAITOK); + if ((child = device_add_child(sc->aac_dev, NULL, -1)) == + NULL) { + device_printf(sc->aac_dev, "device_add_child failed\n"); + } else { + device_set_ivars(child, co); + } + device_set_desc(child, + aac_describe_code(aac_container_types, + mir.MntTable[0].VolType)); + co->co_disk = child; + co->co_found = 1; + bcopy(&mir.MntTable[0], &co->co_mntobj, + sizeof(struct aac_mntobj)); + AAC_LOCK_AQUIRE(&sc->aac_container_lock); + TAILQ_INSERT_HEAD(&sc->aac_container_tqh, co, co_link); + AAC_LOCK_RELEASE(&sc->aac_container_lock); + added = 1; + } + i++; + } while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS)); + + /* + * Go through our list of containers and see which ones were + * not marked 'found'. Since the controller didn't list them + * they must have been deleted. Do the appropriate steps to + * destroy the device. Also reset the co->co_found field. + */ + co = TAILQ_FIRST(&sc->aac_container_tqh); + while (co != NULL) { + if (co->co_found == 0) { + device_delete_child(sc->aac_dev, co->co_disk); + co_next = TAILQ_NEXT(co, co_link); + AAC_LOCK_AQUIRE(&sc->aac_container_lock); + TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link); + AAC_LOCK_RELEASE(&sc->aac_container_lock); + FREE(co, M_AACBUF); + co = co_next; + } else { + co->co_found = 0; + co = TAILQ_NEXT(co, co_link); + } + } + + /* Attach the newly created containers */ + if (added) + bus_generic_attach(sc->aac_dev); + + break; + + default: + break; + } + + default: + break; + } + + /* Copy the AIF data to the AIF queue for ioctl retrieval */ s = splbio(); next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH; if (next != sc->aac_aifq_tail) { @@ -1927,7 +2315,8 @@ aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif) wakeup(sc->aac_aifq); } splx(s); - aac_print_aif(sc, aif); + + return; } /****************************************************************************** @@ -1943,13 +2332,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif) #include <machine/../linux/linux_proto.h> #include <compat/linux/linux_ioctl.h> -#define AAC_LINUX_IOCTL_MIN 0x2000 -#define AAC_LINUX_IOCTL_MAX 0x21ff +#define AAC_LINUX_IOCTL_MIN 0x0000 +#define AAC_LINUX_IOCTL_MAX 0xffff static linux_ioctl_function_t aac_linux_ioctl; static struct linux_ioctl_handler aac_handler = {aac_linux_ioctl, - AAC_LINUX_IOCTL_MIN, - AAC_LINUX_IOCTL_MAX}; + AAC_LINUX_IOCTL_MIN, + AAC_LINUX_IOCTL_MAX}; SYSINIT (aac_register, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &aac_handler); @@ -1964,6 +2353,7 @@ aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args) struct file *fp = p->p_fd->fd_ofiles[args->fd]; u_long cmd = args->cmd; + debug_called(2); /* * Pass the ioctl off to our standard handler. */ @@ -1974,9 +2364,9 @@ aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args) /****************************************************************************** * Return the Revision of the driver to userspace and check to see if the - * userspace app is possibly compatible. This is extremely bogus right now - * because I have no idea how to handle the versioning of this driver. It is - * needed, though, to get aaccli working. + * userspace app is possibly compatible. This is extremely bogus since + * our driver doesn't follow Adaptec's versioning system. Cheat by just + * returning what the card reported. */ static int aac_rev_check(struct aac_softc *sc, caddr_t udata) @@ -2005,7 +2395,7 @@ aac_rev_check(struct aac_softc *sc, caddr_t udata) rev_check_resp.adapterSWRevision.buildNumber = sc->aac_revision.buildNumber; return(copyout((caddr_t)&rev_check_resp, udata, - sizeof(struct aac_rev_check_resp))); + sizeof(struct aac_rev_check_resp))); } /****************************************************************************** @@ -2024,7 +2414,7 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg) /* * Check the magic number that we gave the caller. */ - if (agf.AdapterFibContext != AAC_AIF_SILLYMAGIC) { + if (agf.AdapterFibContext != (int)sc->aifthread) { error = EFAULT; } else { @@ -2062,9 +2452,63 @@ aac_return_aif(struct aac_softc *sc, caddr_t uptr) } else { error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr, sizeof(struct aac_aif_command)); + if (error) + printf("aac_return_aif: copyout returned %d\n", error); if (!error) sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH; } splx(s); return(error); } + +/****************************************************************************** + * Give the userland some information about the container. The AAC arch + * expects the driver to be a SCSI passthrough type driver, so it expects + * the containers to have b:t:l numbers. Fake it. + */ +static int +aac_query_disk(struct aac_softc *sc, caddr_t uptr) +{ + struct aac_query_disk query_disk; + struct aac_container *co; + struct aac_disk *disk = NULL; + int error, id; + + debug_called(2); + + error = copyin(uptr, (caddr_t)&query_disk, sizeof(struct aac_query_disk)); + if (error) + return (error); + + id = query_disk.ContainerNumber; + if (id == -1) + return (EINVAL); + + AAC_LOCK_AQUIRE(&sc->aac_container_lock); + TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) { + if (co->co_mntobj.ObjectId == id) + break; + } + + if (co == NULL) { + query_disk.Valid = 0; + query_disk.Locked = 0; + query_disk.Deleted = 1; /* XXX is this right? */ + } else { + disk = device_get_softc(co->co_disk); + query_disk.Valid = 1; + query_disk.Locked = (disk->ad_flags & AAC_DISK_OPEN) ? 1 : 0; + query_disk.Deleted = 0; + query_disk.Bus = 0; + query_disk.Target = disk->unit; + query_disk.Lun = 0; + query_disk.UnMapped = 0; + bcopy(disk->ad_dev_t->si_name, &query_disk.diskDeviceName[0], 10); + } + AAC_LOCK_RELEASE(&sc->aac_container_lock); + + error = copyout((caddr_t)&query_disk, uptr, sizeof(struct aac_query_disk)); + + return (error); +} + diff --git a/sys/dev/aac/aac_debug.c b/sys/dev/aac/aac_debug.c index 0ebb73c..1db2d50 100644 --- a/sys/dev/aac/aac_debug.c +++ b/sys/dev/aac/aac_debug.c @@ -34,7 +34,6 @@ */ #include "opt_aac.h" -#ifdef AAC_DEBUG #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -492,4 +491,3 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) } } #endif /* AAC_DEBUG */ -#endif diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c index d8331ea..931be9d 100644 --- a/sys/dev/aac/aac_disk.c +++ b/sys/dev/aac/aac_disk.c @@ -42,6 +42,10 @@ #include <sys/devicestat.h> #include <sys/disk.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/md_var.h> #include <machine/bus.h> #include <sys/rman.h> @@ -62,6 +66,7 @@ static int aac_disk_detach(device_t dev); static d_open_t aac_disk_open; static d_close_t aac_disk_close; static d_strategy_t aac_disk_strategy; +static d_dump_t aac_disk_dump; #define AAC_DISK_CDEV_MAJOR 151 @@ -76,9 +81,12 @@ static struct cdevsw aac_disk_cdevsw = { /* strategy */ aac_disk_strategy, /* name */ "aacd", /* maj */ AAC_DISK_CDEV_MAJOR, - /* dump */ nodump, + /* dump */ aac_disk_dump, /* psize */ nopsize, /* flags */ D_DISK, +#if __FreeBSD_version < 500005 + /* bmaj */ -1 +#endif }; devclass_t aac_disk_devclass; @@ -108,7 +116,9 @@ TUNABLE_INT("hw.aac.iosize_max", &aac_iosize_max); SYSCTL_DECL(_hw_aac); SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0, - "Max I/O size per transfer to an array"); + "Max I/O size per transfer to an array"); + +#define AAC_MAXIO 65536 /****************************************************************************** * Handle open from generic layer. @@ -181,6 +191,13 @@ aac_disk_strategy(struct bio *bp) return; } + /* do-nothing operation? */ + if (bp->bio_bcount == 0) { + bp->bio_resid = bp->bio_bcount; + biodone(bp); + return; + } + /* perform accounting */ devstat_start_transaction(&sc->ad_stats); @@ -190,6 +207,82 @@ aac_disk_strategy(struct bio *bp) } /****************************************************************************** + * Dump memory out to an array + * + * This queues blocks of memory of size AAC_MAXIO to the controller and waits + * for the controller to complete the requests. + */ +static int +aac_disk_dump(dev_t dev) +{ + struct aac_disk *ad = dev->si_drv1; + struct aac_softc *sc; + vm_offset_t addr = 0; + long blkcnt; + unsigned int count, blkno, secsize; + int dumppages = AAC_MAXIO / PAGE_SIZE; + int i, error; + + if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize))) + return (error); + + if (ad == NULL) + return (ENXIO); + + sc= ad->ad_controller; + + blkcnt = howmany(PAGE_SIZE, secsize); + + while (count > 0) { + caddr_t va = NULL; + + if ((count / blkcnt) < dumppages) + dumppages = count / blkcnt; + + for (i = 0; i < dumppages; ++i) { + vm_offset_t a = addr + (i * PAGE_SIZE); + if (is_physical_memory(a)) { + va = pmap_kenter_temporary(trunc_page(a), i); + } else { + va = pmap_kenter_temporary(trunc_page(0), i); + } + } + +retry: + /* + * Queue the block to the controller. If the queue is full, EBUSY + * will be returned. + */ + error = aac_dump_enqueue(ad, blkno, va, dumppages); + if (error && (error != EBUSY)) + return (error); + + if (!error) { + if (dumpstatus(addr, (long)(count * DEV_BSIZE)) < 0) + return (EINTR); + + blkno += blkcnt * dumppages; + count -= blkcnt * dumppages; + addr += PAGE_SIZE * dumppages; + if (count > 0) + continue; + } + + /* + * Either the queue was full on the last attemp, or we have no more + * data to dump. Let the queue drain out and retry the block if + * the queue was full. + */ + aac_dump_complete(sc); + + if (error == EBUSY) + goto retry; + } + + return (0); +} + +/****************************************************************************** * Handle completion of an I/O request. */ void @@ -200,8 +293,13 @@ aac_biodone(struct bio *bp) debug_called(4); devstat_end_transaction_bio(&sc->ad_stats, bp); - if (bp->bio_flags & BIO_ERROR) + if (bp->bio_flags & BIO_ERROR) { +#if __FreeBSD_version > 500005 diskerr(bp, (char *)bp->bio_driver1, 0, &sc->ad_label); +#else + diskerr(bp, (char *)bp->bio_driver1, 0, -1, &sc->ad_label); +#endif + } biodone(bp); } @@ -212,7 +310,7 @@ static int aac_disk_probe(device_t dev) { - debug_called(4); + debug_called(2); return (0); } @@ -225,7 +323,7 @@ aac_disk_attach(device_t dev) { struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev); - debug_called(4); + debug_called(1); /* initialise our softc */ sc->ad_controller = @@ -267,6 +365,7 @@ aac_disk_attach(device_t dev) #endif sc->ad_dev_t->si_iosize_max = aac_iosize_max; + sc->unit = device_get_unit(dev); return (0); } @@ -279,17 +378,16 @@ aac_disk_detach(device_t dev) { struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev); - debug_called(4); + debug_called(2); if (sc->ad_flags & AAC_DISK_OPEN) return(EBUSY); devstat_remove_entry(&sc->ad_stats); + disk_destroy(sc->ad_dev_t); #ifdef FREEBSD_4 if (--disks_registered == 0) - cdevsw_remove(&aac_disk_disk_cdevsw); -#else - disk_destroy(sc->ad_dev_t); + cdevsw_remove(&aac_disk_cdevsw); #endif return(0); diff --git a/sys/dev/aac/aac_ioctl.h b/sys/dev/aac/aac_ioctl.h index a0b2f7e..fda2afd 100644 --- a/sys/dev/aac/aac_ioctl.h +++ b/sys/dev/aac/aac_ioctl.h @@ -1,8 +1,7 @@ /*- * Copyright (c) 2000 Michael Smith - * Copyright (c) 2000-2001 Scott Long + * Copyright (c) 2000 Scott Long * Copyright (c) 2000 BSDi - * Copyright (c) 2001 Adaptec, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,8 +58,7 @@ union aac_statrequest { * These bit encodings are actually descended from Windows NT. Ick. */ -#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) \ - | ((func) << 2) | (meth)) +#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth)) #define METHOD_BUFFERED 0 #define METHOD_IN_DIRECT 1 #define METHOD_OUT_DIRECT 2 @@ -108,15 +106,15 @@ union aac_statrequest { #define FSACTL_LNX_DELETE_DISK 0x163 #define FSACTL_LNX_QUERY_DISK 0x173 -/* Ok, this one is really lame */ +/* Ok, here it gets really lame */ #define FSACTL_LNX_PROBE_CONTAINERS 2131 /* Just guessing */ /* Do the native version of the ioctls. Since the BSD encoding scheme - * conflicts with the 'standard' AAC encoding scheme, the resulting values - * must be different. The '8' comes from the fact that the previous scheme + * conflicts with the 'standard' AAC encoding scheme, the resulting numbers + * will be different. The '8' comes from the fact that the previous scheme * used 12 bits for the number, with the the 12th bit being the only set * bit above bit 8. Thus the value of 8, with the lower 8 bits holding the - * command number. 9 is used for the odd overflow/collision case. + * command number. 9 is used for the odd overflow case. */ #define FSACTL_SENDFIB _IO('8', 2) #define FSACTL_GET_COMM_PERF_DATA _IO('8', 36) @@ -161,9 +159,21 @@ struct aac_rev_check_resp { /* * Context passed in by a consumer looking to collect an AIF. */ -#define AAC_AIF_SILLYMAGIC 0xdeadbeef struct get_adapter_fib_ioctl { u_int32_t AdapterFibContext; int Wait; caddr_t AifFib; }; + +struct aac_query_disk { + int32_t ContainerNumber; + int32_t Bus; + int32_t Target; + int32_t Lun; + u_int32_t Valid; + u_int32_t Locked; + u_int32_t Deleted; + int32_t Instance; + char diskDeviceName[10]; + u_int32_t UnMapped; +}; diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c index af1e2fd..4b362c9 100644 --- a/sys/dev/aac/aac_pci.c +++ b/sys/dev/aac/aac_pci.c @@ -65,7 +65,6 @@ static device_method_t aac_methods[] = { DEVMETHOD(device_probe, aac_pci_probe), DEVMETHOD(device_attach, aac_pci_attach), DEVMETHOD(device_detach, aac_detach), - DEVMETHOD(device_shutdown, aac_shutdown), DEVMETHOD(device_suspend, aac_suspend), DEVMETHOD(device_resume, aac_resume), @@ -99,12 +98,10 @@ struct aac_ident {0x1028, 0x0002, 0x1028, 0x00d9, AAC_HWIF_I960RX, "Dell PERC 3/Di"}, {0x1028, 0x0008, 0x1028, 0x00cf, AAC_HWIF_I960RX, "Dell PERC 3/Di"}, {0x1028, 0x000a, 0x1028, 0x0106, AAC_HWIF_I960RX, "Dell PERC 3/Di"}, - {0x9005, 0x0282, 0x9005, 0x0282, AAC_HWIF_I960RX, "Adaptec AAC-2622"}, {0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, "Adaptec AAC-364"}, {0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM, "Adaptec SCSI RAID 5400S"}, {0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, "Dell PERC 2/QC"}, - {0x1011, 0x0046, 0x9005, 0x1365, AAC_HWIF_STRONGARM, "Dell PERC 3/QC"}, /* XXX guess */ {0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, "HP NetRaid-4M"}, {0, 0, 0, 0, 0, 0} }; @@ -193,7 +190,10 @@ aac_pci_attach(device_t dev) device_printf(sc->aac_dev, "can't allocate interrupt\n"); goto out; } - if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY, +#if __FreeBSD_version < 500005 +#define INTR_ENTROPY 0 +#endif + if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY, aac_intr, sc, &sc->aac_intr)) { device_printf(sc->aac_dev, "can't set up interrupt\n"); goto out; diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h index fd5c9b9..e349a91 100644 --- a/sys/dev/aac/aacreg.h +++ b/sys/dev/aac/aacreg.h @@ -987,7 +987,7 @@ struct aac_mntinforesponse { */ struct aac_closecommand { u_int32_t Command; - u_int32_t ComainerId; + u_int32_t ContainerId; } __attribute__ ((packed)); /* diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h index 0353bcc..2ed9221 100644 --- a/sys/dev/aac/aacvar.h +++ b/sys/dev/aac/aacvar.h @@ -85,7 +85,7 @@ * Rate at which we periodically check for timed out commands and kick the * controller. */ -#define AAC_PERIODIC_INTERVAL 10 /* seconds */ +#define AAC_PERIODIC_INTERVAL 20 /* seconds */ /* * Character device major numbers. @@ -98,8 +98,6 @@ ****************************************************************************** ******************************************************************************/ -#include "opt_aac.h" - #if __FreeBSD_version >= 500005 # include <sys/taskqueue.h> #endif @@ -109,8 +107,10 @@ */ struct aac_container { - struct aac_mntobj co_mntobj; - device_t co_disk; + struct aac_mntobj co_mntobj; + device_t co_disk; + int co_found; + TAILQ_ENTRY(aac_container) co_link; }; /* @@ -131,6 +131,7 @@ struct aac_disk int ad_heads; int ad_sectors; u_int32_t ad_size; + int unit; }; /* @@ -170,6 +171,7 @@ struct aac_command void (* cm_complete)(struct aac_command *cm); void *cm_private; time_t cm_timestamp; /* command creation time */ + int cm_queue; }; /* @@ -246,6 +248,23 @@ extern struct aac_interface aac_sa_interface; #define AAC_GETREG1(sc, reg) bus_space_read_1 (sc->aac_btag, \ sc->aac_bhandle, reg) +TAILQ_HEAD(aac_container_tq, aac_container); + +/* Define the OS version specific locks */ +#if __FreeBSD_version >= 500005 +#include <sys/lock.h> +#include <sys/mutex.h> +typedef struct mtx aac_lock_t; +#define AAC_LOCK_INIT(l) mtx_init(l, "AAC Container Mutex", MTX_DEF) +#define AAC_LOCK_AQUIRE(l) mtx_lock(l) +#define AAC_LOCK_RELEASE(l) mtx_unlock(l) +#else +typedef struct simplelock aac_lock_t; +#define AAC_LOCK_INIT(l) simple_lock_init(l) +#define AAC_LOCK_AQUIRE(l) simple_lock(l) +#define AAC_LOCK_RELEASE(l) simple_unlock(l) +#endif + /* * Per-controller structure. */ @@ -308,7 +327,8 @@ struct aac_softc struct aac_qstat aac_qstat[AACQ_COUNT]; /* queue statistics */ /* connected containters */ - struct aac_container aac_container[AAC_MAX_CONTAINERS]; + struct aac_container_tq aac_container_tqh; + aac_lock_t aac_container_lock; /* delayed activity infrastructure */ #if __FreeBSD_version >= 500005 @@ -322,6 +342,12 @@ struct aac_softc struct aac_aif_command aac_aifq[AAC_AIFQ_LENGTH]; int aac_aifq_head; int aac_aifq_tail; + struct proc *aifthread; + int aifflags; +#define AAC_AIFFLAGS_RUNNING (1 << 0) +#define AAC_AIFFLAGS_PENDING (1 << 1) +#define AAC_AIFFLAGS_EXIT (1 << 2) +#define AAC_AIFFLAGS_EXITED (1 << 3) }; @@ -338,6 +364,9 @@ extern void aac_intr(void *arg); extern devclass_t aac_devclass; extern void aac_submit_bio(struct bio *bp); extern void aac_biodone(struct bio *bp); +extern int aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, + void *data, int nblks); +extern void aac_dump_complete(struct aac_softc *sc); /* * Debugging levels: @@ -370,9 +399,9 @@ extern void aac_print_aif(struct aac_softc *sc, # define aac_print_queues(sc) # define aac_panic(sc, reason) -# define aac_print_aif(sc, aif) # define AAC_PRINT_FIB(sc, fib) +# define aac_print_aif(sc, aac_aif_command) #endif struct aac_code_lookup { @@ -517,3 +546,14 @@ aac_dequeue_bio(struct aac_softc *sc) splx(s); return(bp); } + +static __inline void +aac_print_printf(struct aac_softc *sc) +{ + if (sc->aac_common->ac_printf[0]) { + device_printf(sc->aac_dev, "**Monitor** %.*s", AAC_PRINTF_BUFSIZE, + sc->aac_common->ac_printf); + sc->aac_common->ac_printf[0] = 0; + AAC_QNOTIFY(sc, AAC_DB_PRINTF); + } +} diff --git a/sys/sys/aac_ioctl.h b/sys/sys/aac_ioctl.h index a0b2f7e..fda2afd 100644 --- a/sys/sys/aac_ioctl.h +++ b/sys/sys/aac_ioctl.h @@ -1,8 +1,7 @@ /*- * Copyright (c) 2000 Michael Smith - * Copyright (c) 2000-2001 Scott Long + * Copyright (c) 2000 Scott Long * Copyright (c) 2000 BSDi - * Copyright (c) 2001 Adaptec, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,8 +58,7 @@ union aac_statrequest { * These bit encodings are actually descended from Windows NT. Ick. */ -#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) \ - | ((func) << 2) | (meth)) +#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth)) #define METHOD_BUFFERED 0 #define METHOD_IN_DIRECT 1 #define METHOD_OUT_DIRECT 2 @@ -108,15 +106,15 @@ union aac_statrequest { #define FSACTL_LNX_DELETE_DISK 0x163 #define FSACTL_LNX_QUERY_DISK 0x173 -/* Ok, this one is really lame */ +/* Ok, here it gets really lame */ #define FSACTL_LNX_PROBE_CONTAINERS 2131 /* Just guessing */ /* Do the native version of the ioctls. Since the BSD encoding scheme - * conflicts with the 'standard' AAC encoding scheme, the resulting values - * must be different. The '8' comes from the fact that the previous scheme + * conflicts with the 'standard' AAC encoding scheme, the resulting numbers + * will be different. The '8' comes from the fact that the previous scheme * used 12 bits for the number, with the the 12th bit being the only set * bit above bit 8. Thus the value of 8, with the lower 8 bits holding the - * command number. 9 is used for the odd overflow/collision case. + * command number. 9 is used for the odd overflow case. */ #define FSACTL_SENDFIB _IO('8', 2) #define FSACTL_GET_COMM_PERF_DATA _IO('8', 36) @@ -161,9 +159,21 @@ struct aac_rev_check_resp { /* * Context passed in by a consumer looking to collect an AIF. */ -#define AAC_AIF_SILLYMAGIC 0xdeadbeef struct get_adapter_fib_ioctl { u_int32_t AdapterFibContext; int Wait; caddr_t AifFib; }; + +struct aac_query_disk { + int32_t ContainerNumber; + int32_t Bus; + int32_t Target; + int32_t Lun; + u_int32_t Valid; + u_int32_t Locked; + u_int32_t Deleted; + int32_t Instance; + char diskDeviceName[10]; + u_int32_t UnMapped; +}; |