]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/twa/tw_osl_freebsd.c
This commit was generated by cvs2svn to compensate for changes in r167465,
[FreeBSD/FreeBSD.git] / sys / dev / twa / tw_osl_freebsd.c
1 /*
2  * Copyright (c) 2004-05 Applied Micro Circuits Corporation.
3  * Copyright (c) 2004-05 Vinod Kashyap.
4  * Copyright (c) 2000 Michael Smith
5  * Copyright (c) 2000 BSDi
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *      $FreeBSD$
30  */
31
32 /*
33  * AMCC'S 3ware driver for 9000 series storage controllers.
34  *
35  * Author: Vinod Kashyap
36  */
37
38
39 /*
40  * FreeBSD specific functions not related to CAM, and other
41  * miscellaneous functions.
42  */
43
44
45 #include <dev/twa/tw_osl_includes.h>
46 #include <dev/twa/tw_cl_fwif.h>
47 #include <dev/twa/tw_cl_ioctl.h>
48 #include <dev/twa/tw_osl_ioctl.h>
49
50 #ifdef TW_OSL_DEBUG
51 TW_INT32        TW_DEBUG_LEVEL_FOR_OSL = TW_OSL_DEBUG;
52 TW_INT32        TW_OSL_DEBUG_LEVEL_FOR_CL = TW_OSL_DEBUG;
53 #endif /* TW_OSL_DEBUG */
54
55 MALLOC_DEFINE(TW_OSLI_MALLOC_CLASS, "twa_commands", "twa commands");
56
57
58 static  d_open_t                twa_open;
59 static  d_close_t               twa_close;
60 static  d_ioctl_t               twa_ioctl;
61
62 static struct cdevsw twa_cdevsw = {
63         .d_version =    D_VERSION,
64         .d_open =       twa_open,
65         .d_close =      twa_close,
66         .d_ioctl =      twa_ioctl,
67         .d_name =       "twa",
68 };
69
70 static devclass_t       twa_devclass;
71
72
73 /*
74  * Function name:       twa_open
75  * Description:         Called when the controller is opened.
76  *                      Simply marks the controller as open.
77  *
78  * Input:               dev     -- control device corresponding to the ctlr
79  *                      flags   -- mode of open
80  *                      fmt     -- device type (character/block etc.)
81  *                      proc    -- current process
82  * Output:              None
83  * Return value:        0       -- success
84  *                      non-zero-- failure
85  */
86 static TW_INT32
87 twa_open(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, d_thread_t *proc)
88 {
89         TW_INT32                unit = minor(dev);
90         struct twa_softc        *sc = devclass_get_softc(twa_devclass, unit);
91
92         tw_osli_dbg_dprintf(5, sc, "entered");
93         sc->state |= TW_OSLI_CTLR_STATE_OPEN;
94         return(0);
95 }
96
97
98
99 /*
100  * Function name:       twa_close
101  * Description:         Called when the controller is closed.
102  *                      Simply marks the controller as not open.
103  *
104  * Input:               dev     -- control device corresponding to the ctlr
105  *                      flags   -- mode of corresponding open
106  *                      fmt     -- device type (character/block etc.)
107  *                      proc    -- current process
108  * Output:              None
109  * Return value:        0       -- success
110  *                      non-zero-- failure
111  */
112 static TW_INT32
113 twa_close(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, d_thread_t *proc)
114 {
115         TW_INT32                unit = minor(dev);
116         struct twa_softc        *sc = devclass_get_softc(twa_devclass, unit);
117
118         tw_osli_dbg_dprintf(5, sc, "entered");
119         sc->state &= ~TW_OSLI_CTLR_STATE_OPEN;
120         return(0);
121 }
122
123
124
125 /*
126  * Function name:       twa_ioctl
127  * Description:         Called when an ioctl is posted to the controller.
128  *                      Handles any OS Layer specific cmds, passes the rest
129  *                      on to the Common Layer.
130  *
131  * Input:               dev     -- control device corresponding to the ctlr
132  *                      cmd     -- ioctl cmd
133  *                      buf     -- ptr to buffer in kernel memory, which is
134  *                                 a copy of the input buffer in user-space
135  *                      flags   -- mode of corresponding open
136  *                      proc    -- current process
137  * Output:              buf     -- ptr to buffer in kernel memory, which will
138  *                                 be copied to the output buffer in user-space
139  * Return value:        0       -- success
140  *                      non-zero-- failure
141  */
142 static TW_INT32
143 twa_ioctl(struct cdev *dev, u_long cmd, caddr_t buf, TW_INT32 flags, d_thread_t *proc)
144 {
145         struct twa_softc        *sc = (struct twa_softc *)(dev->si_drv1);
146         TW_INT32                error;
147
148         tw_osli_dbg_dprintf(5, sc, "entered");
149
150         switch (cmd) {
151         case TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH:
152                 tw_osli_dbg_dprintf(6, sc, "ioctl: fw_passthru");
153                 error = tw_osli_fw_passthru(sc, (TW_INT8 *)buf);
154                 break;
155
156         case TW_OSL_IOCTL_SCAN_BUS:
157                 /* Request CAM for a bus scan. */
158                 tw_osli_dbg_dprintf(6, sc, "ioctl: scan bus");
159                 error = tw_osli_request_bus_scan(sc);
160                 break;
161
162         default:
163                 tw_osli_dbg_dprintf(6, sc, "ioctl: 0x%lx", cmd);
164                 error = tw_cl_ioctl(&sc->ctlr_handle, cmd, buf);
165                 break;
166         }
167         return(error);
168 }
169
170
171
172 static TW_INT32 twa_probe(device_t dev);
173 static TW_INT32 twa_attach(device_t dev);
174 static TW_INT32 twa_detach(device_t dev);
175 static TW_INT32 twa_shutdown(device_t dev);
176 static TW_VOID  twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op);
177 #ifdef TW_OSLI_DEFERRED_INTR_USED
178 static int      twa_pci_intr_fast(TW_VOID *arg);
179 static TW_VOID  twa_deferred_intr(TW_VOID *context, TW_INT32 pending);
180 #else
181 static TW_VOID  twa_pci_intr(TW_VOID *arg);
182 #endif /* TW_OSLI_DEFERRED_INTR_USED */
183
184 static TW_INT32 tw_osli_alloc_mem(struct twa_softc *sc);
185 static TW_VOID  tw_osli_free_resources(struct twa_softc *sc);
186
187 static TW_VOID  twa_map_load_data_callback(TW_VOID *arg,
188         bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error);
189 static TW_VOID  twa_map_load_callback(TW_VOID *arg,
190         bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error);
191
192
193 static device_method_t  twa_methods[] = {
194         /* Device interface */
195         DEVMETHOD(device_probe,         twa_probe),
196         DEVMETHOD(device_attach,        twa_attach),
197         DEVMETHOD(device_detach,        twa_detach),
198         DEVMETHOD(device_shutdown,      twa_shutdown),
199
200         DEVMETHOD(bus_print_child,      bus_generic_print_child),
201         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
202         {0, 0}
203 };
204
205 static driver_t twa_pci_driver = {
206         "twa",
207         twa_methods,
208         sizeof(struct twa_softc)
209 };
210
211 DRIVER_MODULE(twa, pci, twa_pci_driver, twa_devclass, 0, 0);
212
213 MODULE_DEPEND(twa, pci, 1, 1, 1);
214 MODULE_DEPEND(twa, cam, 1, 1, 1);
215
216
217 /*
218  * Function name:       twa_probe
219  * Description:         Called at driver load time.  Claims 9000 ctlrs.
220  *
221  * Input:               dev     -- bus device corresponding to the ctlr
222  * Output:              None
223  * Return value:        <= 0    -- success
224  *                      > 0     -- failure
225  */
226 static TW_INT32
227 twa_probe(device_t dev)
228 {
229         static TW_UINT8 first_ctlr = 1;
230
231         tw_osli_dbg_printf(3, "entered");
232
233         if (tw_cl_ctlr_supported(pci_get_vendor(dev), pci_get_device(dev))) {
234                 device_set_desc(dev, TW_OSLI_DEVICE_NAME);
235                 /* Print the driver version only once. */
236                 if (first_ctlr) {
237                         printf("3ware device driver for 9000 series storage "
238                                 "controllers, version: %s\n",
239                                 TW_OSL_DRIVER_VERSION_STRING);
240                         first_ctlr = 0;
241                 }
242                 return(0);
243         }
244         return(ENXIO);
245 }
246
247
248
249 /*
250  * Function name:       twa_attach
251  * Description:         Allocates pci resources; updates sc; adds a node to the
252  *                      sysctl tree to expose the driver version; makes calls
253  *                      (to the Common Layer) to initialize ctlr, and to
254  *                      attach to CAM.
255  *
256  * Input:               dev     -- bus device corresponding to the ctlr
257  * Output:              None
258  * Return value:        0       -- success
259  *                      non-zero-- failure
260  */
261 static TW_INT32
262 twa_attach(device_t dev)
263 {
264         struct twa_softc        *sc = device_get_softc(dev);
265         TW_UINT32               command;
266         TW_INT32                bar_num;
267         TW_INT32                bar0_offset;
268         TW_INT32                bar_size;
269         TW_INT32                error;
270
271         tw_osli_dbg_dprintf(3, sc, "entered");
272
273         sc->ctlr_handle.osl_ctlr_ctxt = sc;
274
275         /* Initialize the softc structure. */
276         sc->bus_dev = dev;
277         sc->device_id = pci_get_device(dev);
278
279         /* Initialize the mutexes right here. */
280         sc->io_lock = &(sc->io_lock_handle);
281         mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN);
282         sc->q_lock = &(sc->q_lock_handle);
283         mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN);
284
285         sysctl_ctx_init(&sc->sysctl_ctxt);
286         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt,
287                 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
288                 device_get_nameunit(dev), CTLFLAG_RD, 0, "");
289         if (sc->sysctl_tree == NULL) {
290                 tw_osli_printf(sc, "error = %d",
291                         TW_CL_SEVERITY_ERROR_STRING,
292                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
293                         0x2000,
294                         "Cannot add sysctl tree node",
295                         ENXIO);
296                 return(ENXIO);
297         }
298         SYSCTL_ADD_STRING(&sc->sysctl_ctxt, SYSCTL_CHILDREN(sc->sysctl_tree),
299                 OID_AUTO, "driver_version", CTLFLAG_RD,
300                 TW_OSL_DRIVER_VERSION_STRING, 0, "TWA driver version");
301
302         /* Make sure we are going to be able to talk to this board. */
303         command = pci_read_config(dev, PCIR_COMMAND, 2);
304         if ((command & PCIM_CMD_PORTEN) == 0) {
305                 tw_osli_printf(sc, "error = %d",
306                         TW_CL_SEVERITY_ERROR_STRING,
307                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
308                         0x2001,
309                         "Register window not available",
310                         ENXIO);
311                 tw_osli_free_resources(sc);
312                 return(ENXIO);
313         }
314
315         /* Force the busmaster enable bit on, in case the BIOS forgot. */
316         command |= PCIM_CMD_BUSMASTEREN;
317         pci_write_config(dev, PCIR_COMMAND, command, 2);
318
319         /* Allocate the PCI register window. */
320         if ((error = tw_cl_get_pci_bar_info(sc->device_id, TW_CL_BAR_TYPE_MEM,
321                 &bar_num, &bar0_offset, &bar_size))) {
322                 tw_osli_printf(sc, "error = %d",
323                         TW_CL_SEVERITY_ERROR_STRING,
324                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
325                         0x201F,
326                         "Can't get PCI BAR info",
327                         error);
328                 tw_osli_free_resources(sc);
329                 return(error);
330         }
331         sc->reg_res_id = PCIR_BARS + bar0_offset;
332         if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
333                                 &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
334                                 == NULL) {
335                 tw_osli_printf(sc, "error = %d",
336                         TW_CL_SEVERITY_ERROR_STRING,
337                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
338                         0x2002,
339                         "Can't allocate register window",
340                         ENXIO);
341                 tw_osli_free_resources(sc);
342                 return(ENXIO);
343         }
344         sc->bus_tag = rman_get_bustag(sc->reg_res);
345         sc->bus_handle = rman_get_bushandle(sc->reg_res);
346
347         /* Allocate and register our interrupt. */
348         sc->irq_res_id = 0;
349         if ((sc->irq_res = bus_alloc_resource(sc->bus_dev, SYS_RES_IRQ,
350                                 &(sc->irq_res_id), 0, ~0, 1,
351                                 RF_SHAREABLE | RF_ACTIVE)) == NULL) {
352                 tw_osli_printf(sc, "error = %d",
353                         TW_CL_SEVERITY_ERROR_STRING,
354                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
355                         0x2003,
356                         "Can't allocate interrupt",
357                         ENXIO);
358                 tw_osli_free_resources(sc);
359                 return(ENXIO);
360         }
361         if ((error = bus_setup_intr(sc->bus_dev, sc->irq_res,
362                         INTR_TYPE_CAM | INTR_MPSAFE,
363 #ifdef TW_OSLI_DEFERRED_INTR_USED
364                         twa_pci_intr_fast, NULL,
365 #else
366                         NULL, twa_pci_intr,         
367 #endif 
368                         sc, &sc->intr_handle))) {
369                 tw_osli_printf(sc, "error = %d",
370                         TW_CL_SEVERITY_ERROR_STRING,
371                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
372                         0x2004,
373                         "Can't set up interrupt",
374                         error);
375                 tw_osli_free_resources(sc);
376                 return(error);
377         }
378
379 #ifdef TW_OSLI_DEFERRED_INTR_USED
380         TASK_INIT(&sc->deferred_intr_callback, 0, twa_deferred_intr, sc);
381 #endif /* TW_OSLI_DEFERRED_INTR_USED */
382
383         if ((error = tw_osli_alloc_mem(sc))) {
384                 tw_osli_printf(sc, "error = %d",
385                         TW_CL_SEVERITY_ERROR_STRING,
386                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
387                         0x2005,
388                         "Memory allocation failure",
389                         error);
390                 tw_osli_free_resources(sc);
391                 return(error);
392         }
393
394         /* Initialize the Common Layer for this controller. */
395         if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags, sc->device_id,
396                         TW_OSLI_MAX_NUM_IOS, TW_OSLI_MAX_NUM_AENS,
397                         sc->non_dma_mem, sc->dma_mem,
398                         sc->dma_mem_phys
399 #ifdef TW_OSL_FLASH_FIRMWARE
400                         , sc->flash_dma_mem, sc->flash_dma_mem_phys
401 #endif /* TW_OSL_FLASH_FIRMWARE */
402                         ))) {
403                 tw_osli_printf(sc, "error = %d",
404                         TW_CL_SEVERITY_ERROR_STRING,
405                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
406                         0x2006,
407                         "Failed to initialize Common Layer/controller",
408                         error);
409                 tw_osli_free_resources(sc);
410                 return(error);
411         }
412
413 #ifdef TW_OSL_FLASH_FIRMWARE
414         /* Free any memory allocated for firmware flashing. */
415         if (sc->flash_dma_mem) {
416                 bus_dmamap_unload(sc->flash_tag, sc->flash_map);
417                 bus_dmamem_free(sc->flash_tag, sc->flash_dma_mem,
418                         sc->flash_map);
419         }
420         if (sc->flash_tag)
421                 bus_dma_tag_destroy(sc->flash_tag);
422         /*
423          * Set flash_tag and flash_dma_mem to 0, so we don't try freeing them
424          * again, later.
425          */
426         sc->flash_tag = 0;
427         sc->flash_dma_mem = 0;
428 #endif /* TW_OSL_FLASH_FIRMWARE */
429
430         /* Create the control device. */
431         sc->ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->bus_dev),
432                         UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
433                         "twa%d", device_get_unit(sc->bus_dev));
434         sc->ctrl_dev->si_drv1 = sc;
435
436         if ((error = tw_osli_cam_attach(sc))) {
437                 tw_osli_free_resources(sc);
438                 tw_osli_printf(sc, "error = %d",
439                         TW_CL_SEVERITY_ERROR_STRING,
440                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
441                         0x2007,
442                         "Failed to initialize CAM",
443                         error);
444                 return(error);
445         }
446
447         return(0);
448 }
449
450
451
452 /*
453  * Function name:       tw_osli_alloc_mem
454  * Description:         Allocates memory needed both by CL and OSL.
455  *
456  * Input:               sc      -- OSL internal controller context
457  * Output:              None
458  * Return value:        0       -- success
459  *                      non-zero-- failure
460  */
461 static TW_INT32
462 tw_osli_alloc_mem(struct twa_softc *sc)
463 {
464         struct tw_osli_req_context      *req;
465         TW_UINT32                       max_sg_elements;
466         TW_UINT32                       non_dma_mem_size;
467         TW_UINT32                       dma_mem_size;
468 #ifdef TW_OSL_FLASH_FIRMWARE
469         TW_UINT32                       flash_dma_mem_size;
470 #endif /* TW_OSL_FLASH_FIRMWARE */
471 #ifdef TW_OSL_DMA_MEM_ALLOC_PER_REQUEST
472         TW_UINT32                       per_req_dma_mem_size;
473 #endif /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
474         TW_INT32                        error;
475         TW_INT32                        i;
476
477         tw_osli_dbg_dprintf(3, sc, "entered");
478
479         sc->flags |= (sizeof(bus_addr_t) == 8) ? TW_CL_64BIT_ADDRESSES : 0;
480         sc->flags |= (sizeof(bus_size_t) == 8) ? TW_CL_64BIT_SG_LENGTH : 0;
481 #ifdef TW_OSL_FLASH_FIRMWARE
482         sc->flags |= TW_CL_FLASH_FIRMWARE; 
483 #endif /* TW_OSL_FLASH_FIRMWARE */
484 #ifdef TW_OSLI_DEFERRED_INTR_USED
485         sc->flags |= TW_CL_DEFERRED_INTR_USED; 
486 #endif /* TW_OSLI_DEFERRED_INTR_USED */
487
488         max_sg_elements = (sizeof(bus_addr_t) == 8) ?
489                 TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS;
490
491         if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags,
492                         sc->device_id, TW_OSLI_MAX_NUM_IOS,  TW_OSLI_MAX_NUM_AENS,
493                         &(sc->alignment), &(sc->sg_size_factor),
494                         &non_dma_mem_size, &dma_mem_size
495 #ifdef TW_OSL_FLASH_FIRMWARE
496                         , &flash_dma_mem_size
497 #endif /* TW_OSL_FLASH_FIRMWARE */
498 #ifdef TW_OSL_DMA_MEM_ALLOC_PER_REQUEST
499                         , &per_req_dma_mem_size
500 #endif /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
501                         ))) {
502                 tw_osli_printf(sc, "error = %d",
503                         TW_CL_SEVERITY_ERROR_STRING,
504                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
505                         0x2008,
506                         "Can't get Common Layer's memory requirements",
507                         error);
508                 return(error);
509         }
510
511         if ((sc->non_dma_mem = malloc(non_dma_mem_size, TW_OSLI_MALLOC_CLASS,
512                                 M_WAITOK)) == NULL) {
513                 tw_osli_printf(sc, "error = %d",
514                         TW_CL_SEVERITY_ERROR_STRING,
515                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
516                         0x2009,
517                         "Can't allocate non-dma memory",
518                         ENOMEM);
519                 return(ENOMEM);
520         }
521
522         /* Create the parent dma tag. */
523         if (bus_dma_tag_create(NULL,                    /* parent */
524                                 sc->alignment,          /* alignment */
525                                 0,                      /* boundary */
526                                 BUS_SPACE_MAXADDR,      /* lowaddr */
527                                 BUS_SPACE_MAXADDR,      /* highaddr */
528                                 NULL, NULL,             /* filter, filterarg */
529                                 TW_CL_MAX_IO_SIZE,      /* maxsize */
530                                 max_sg_elements,        /* nsegments */
531                                 TW_CL_MAX_IO_SIZE,      /* maxsegsize */
532                                 0,                      /* flags */
533                                 NULL,                   /* lockfunc */
534                                 NULL,                   /* lockfuncarg */
535                                 &sc->parent_tag         /* tag */)) {
536                 tw_osli_printf(sc, "error = %d",
537                         TW_CL_SEVERITY_ERROR_STRING,
538                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
539                         0x200A,
540                         "Can't allocate parent DMA tag",
541                         ENOMEM);
542                 return(ENOMEM);
543         }
544
545         /* Create a dma tag for Common Layer's DMA'able memory (dma_mem). */
546         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
547                                 sc->alignment,          /* alignment */
548                                 0,                      /* boundary */
549                                 BUS_SPACE_MAXADDR,      /* lowaddr */
550                                 BUS_SPACE_MAXADDR,      /* highaddr */
551                                 NULL, NULL,             /* filter, filterarg */
552 #ifdef TW_OSL_DMA_MEM_ALLOC_PER_REQUEST
553                                 (TW_OSLI_MAX_NUM_IOS *
554                                 per_req_dma_mem_size) + 
555 #endif /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
556                                 dma_mem_size,           /* maxsize */
557                                 1,                      /* nsegments */
558                                 BUS_SPACE_MAXSIZE,      /* maxsegsize */
559                                 0,                      /* flags */
560                                 NULL,                   /* lockfunc */
561                                 NULL,                   /* lockfuncarg */
562                                 &sc->cmd_tag            /* tag */)) {
563                 tw_osli_printf(sc, "error = %d",
564                         TW_CL_SEVERITY_ERROR_STRING,
565                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
566                         0x200B,
567                         "Can't allocate DMA tag for Common Layer's "
568                         "DMA'able memory",
569                         ENOMEM);
570                 return(ENOMEM);
571         }
572
573         if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
574                 BUS_DMA_NOWAIT, &sc->cmd_map)) {
575                 /* Try a second time. */
576                 if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
577                         BUS_DMA_NOWAIT, &sc->cmd_map)) {
578                         tw_osli_printf(sc, "error = %d",
579                                 TW_CL_SEVERITY_ERROR_STRING,
580                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
581                                 0x200C,
582                                 "Can't allocate DMA'able memory for the"
583                                 "Common Layer",
584                                 ENOMEM);
585                         return(ENOMEM);
586                 }
587         }
588
589         bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem,
590                 dma_mem_size, twa_map_load_callback,
591                 &sc->dma_mem_phys, 0);
592
593
594 #ifdef TW_OSL_FLASH_FIRMWARE
595         /*
596          * Create a dma tag for Common Layer's DMA'able memory,
597          * used to flash firmware (flash_dma_mem).
598          */
599         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
600                                 sc->alignment,          /* alignment */
601                                 0,                      /* boundary */
602                                 BUS_SPACE_MAXADDR,      /* lowaddr */
603                                 BUS_SPACE_MAXADDR,      /* highaddr */
604                                 NULL, NULL,             /* filter, filterarg */
605                                 flash_dma_mem_size,     /* maxsize */
606                                 1,                      /* nsegments */
607                                 flash_dma_mem_size,     /* maxsegsize */
608                                 0,                      /* flags */
609                                 NULL,                   /* lockfunc */
610                                 NULL,                   /* lockfuncarg */
611                                 &sc->flash_tag          /* tag */)) {
612                 tw_osli_printf(sc, "error = %d",
613                         TW_CL_SEVERITY_ERROR_STRING,
614                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
615                         0x200D,
616                         "Can't allocate DMA tag for Common Layer's "
617                         "firmware flash memory",
618                         ENOMEM);
619                 return(ENOMEM);
620         }
621
622         if (bus_dmamem_alloc(sc->flash_tag, &sc->flash_dma_mem,
623                 BUS_DMA_NOWAIT, &sc->flash_map)) {
624                 tw_osli_printf(sc, "error = %d",
625                         TW_CL_SEVERITY_ERROR_STRING,
626                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
627                         0x200E,
628                         "Can't allocate DMA'able memory for Common Layer's "
629                         "firmware flash",
630                         ENOMEM);
631                 return(ENOMEM);
632         }
633
634         bus_dmamap_load(sc->flash_tag, sc->flash_map, sc->flash_dma_mem,
635                 flash_dma_mem_size, twa_map_load_callback,
636                 &sc->flash_dma_mem_phys, 0);
637
638 #endif /* TW_OSL_FLASH_FIRMWARE */
639
640         /*
641          * Create a dma tag for data buffers; size will be the maximum
642          * possible I/O size (128kB).
643          */
644         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
645                                 sc->alignment,          /* alignment */
646                                 0,                      /* boundary */
647                                 BUS_SPACE_MAXADDR,      /* lowaddr */
648                                 BUS_SPACE_MAXADDR,      /* highaddr */
649                                 NULL, NULL,             /* filter, filterarg */
650                                 TW_CL_MAX_IO_SIZE,      /* maxsize */
651                                 max_sg_elements,        /* nsegments */
652                                 TW_CL_MAX_IO_SIZE,      /* maxsegsize */
653                                 BUS_DMA_ALLOCNOW,       /* flags */
654                                 twa_busdma_lock,        /* lockfunc */
655                                 sc->io_lock,            /* lockfuncarg */
656                                 &sc->dma_tag            /* tag */)) {
657                 tw_osli_printf(sc, "error = %d",
658                         TW_CL_SEVERITY_ERROR_STRING,
659                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
660                         0x200F,
661                         "Can't allocate DMA tag for data buffers",
662                         ENOMEM);
663                 return(ENOMEM);
664         }
665
666         /*
667          * Create a dma tag for ioctl data buffers; size will be the maximum
668          * possible I/O size (128kB).
669          */
670         if (bus_dma_tag_create(sc->parent_tag,          /* parent */
671                                 sc->alignment,          /* alignment */
672                                 0,                      /* boundary */
673                                 BUS_SPACE_MAXADDR,      /* lowaddr */
674                                 BUS_SPACE_MAXADDR,      /* highaddr */
675                                 NULL, NULL,             /* filter, filterarg */
676                                 TW_CL_MAX_IO_SIZE,      /* maxsize */
677                                 max_sg_elements,        /* nsegments */
678                                 TW_CL_MAX_IO_SIZE,      /* maxsegsize */
679                                 BUS_DMA_ALLOCNOW,       /* flags */
680                                 twa_busdma_lock,        /* lockfunc */
681                                 sc->io_lock,            /* lockfuncarg */
682                                 &sc->ioctl_tag          /* tag */)) {
683                 tw_osli_printf(sc, "error = %d",
684                         TW_CL_SEVERITY_ERROR_STRING,
685                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
686                         0x2010,
687                         "Can't allocate DMA tag for ioctl data buffers",
688                         ENOMEM);
689                 return(ENOMEM);
690         }
691
692         /* Create just one map for all ioctl request data buffers. */
693         if (bus_dmamap_create(sc->ioctl_tag, 0, &sc->ioctl_map)) {
694                 tw_osli_printf(sc, "error = %d",
695                         TW_CL_SEVERITY_ERROR_STRING,
696                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
697                         0x2011,
698                         "Can't create ioctl map",
699                         ENOMEM);
700                 return(ENOMEM);
701         }
702
703
704         /* Initialize request queues. */
705         tw_osli_req_q_init(sc, TW_OSLI_FREE_Q);
706         tw_osli_req_q_init(sc, TW_OSLI_BUSY_Q);
707
708         if ((sc->req_ctxt_buf = (struct tw_osli_req_context *)
709                         malloc((sizeof(struct tw_osli_req_context) *
710                                 TW_OSLI_MAX_NUM_IOS),
711                                 TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
712                 tw_osli_printf(sc, "error = %d",
713                         TW_CL_SEVERITY_ERROR_STRING,
714                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
715                         0x2012,
716                         "Failed to allocate request packets",
717                         ENOMEM);
718                 return(ENOMEM);
719         }
720         bzero(sc->req_ctxt_buf,
721                 sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_IOS);
722
723         for (i = 0; i < TW_OSLI_MAX_NUM_IOS; i++) {
724                 req = &(sc->req_ctxt_buf[i]);
725                 req->ctlr = sc;
726                 if (bus_dmamap_create(sc->dma_tag, 0, &req->dma_map)) {
727                         tw_osli_printf(sc, "request # = %d, error = %d",
728                                 TW_CL_SEVERITY_ERROR_STRING,
729                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
730                                 0x2013,
731                                 "Can't create dma map",
732                                 i, ENOMEM);
733                         return(ENOMEM);
734                 }
735
736 #ifdef TW_OSL_DMA_MEM_ALLOC_PER_REQUEST
737
738                 req->req_pkt.dma_mem = ((TW_INT8 *)(sc->dma_mem)) +
739                         (i * per_req_dma_mem_size);
740                 req->req_pkt.dma_mem_phys = sc->dma_mem_phys +
741                         (i * per_req_dma_mem_size);
742
743 #endif /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
744
745                 /* Insert request into the free queue. */
746                 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
747         }
748
749 #ifdef TW_OSL_DMA_MEM_ALLOC_PER_REQUEST
750
751         sc->dma_mem = ((TW_INT8 *)(sc->dma_mem)) +
752                 (TW_OSLI_MAX_NUM_IOS * per_req_dma_mem_size);
753         sc->dma_mem_phys += (TW_OSLI_MAX_NUM_IOS * per_req_dma_mem_size);
754
755 #endif /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
756
757         return(0);
758 }
759
760
761
762 /*
763  * Function name:       tw_osli_free_resources
764  * Description:         Performs clean-up at the time of going down.
765  *
766  * Input:               sc      -- ptr to OSL internal ctlr context
767  * Output:              None
768  * Return value:        None
769  */
770 static TW_VOID
771 tw_osli_free_resources(struct twa_softc *sc)
772 {
773         struct tw_osli_req_context      *req;
774         TW_INT32                        error = 0;
775
776         tw_osli_dbg_dprintf(3, sc, "entered");
777
778         /* Detach from CAM */
779         tw_osli_cam_detach(sc);
780
781         if (sc->req_ctxt_buf)
782                 while ((req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q)) !=
783                         NULL)
784                         if ((error = bus_dmamap_destroy(sc->dma_tag,
785                                         req->dma_map)))
786                                 tw_osli_dbg_dprintf(1, sc,
787                                         "dmamap_destroy(dma) returned %d",
788                                         error);
789
790         if ((sc->ioctl_tag) && (sc->ioctl_map))
791                 if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map)))
792                         tw_osli_dbg_dprintf(1, sc,
793                                 "dmamap_destroy(ioctl) returned %d", error);
794
795         /* Free all memory allocated so far. */
796         if (sc->req_ctxt_buf)
797                 free(sc->req_ctxt_buf, TW_OSLI_MALLOC_CLASS);
798
799         if (sc->non_dma_mem)
800                 free(sc->non_dma_mem, TW_OSLI_MALLOC_CLASS);
801
802         if (sc->dma_mem) {
803                 bus_dmamap_unload(sc->cmd_tag, sc->cmd_map);
804                 bus_dmamem_free(sc->cmd_tag, sc->dma_mem,
805                         sc->cmd_map);
806         }
807         if (sc->cmd_tag)
808                 if ((error = bus_dma_tag_destroy(sc->cmd_tag)))
809                         tw_osli_dbg_dprintf(1, sc,
810                                 "dma_tag_destroy(cmd) returned %d", error);
811
812
813 #ifdef TW_OSL_FLASH_FIRMWARE
814
815         if (sc->flash_dma_mem) {
816                 /* In case this piece of memory has already been freed. */
817                 bus_dmamap_unload(sc->flash_tag, sc->flash_map);
818                 bus_dmamem_free(sc->flash_tag, sc->flash_dma_mem,
819                         sc->flash_map);
820         }
821         if (sc->flash_tag)
822                 if ((error = bus_dma_tag_destroy(sc->flash_tag)))
823                         tw_osli_dbg_dprintf(1, sc,
824                                 "dma_tag_destroy(flash) returned %d", error);
825
826 #endif /* TW_OSL_FLASH_FIRMWARE */
827
828         if (sc->dma_tag)
829                 if ((error = bus_dma_tag_destroy(sc->dma_tag)))
830                         tw_osli_dbg_dprintf(1, sc,
831                                 "dma_tag_destroy(dma) returned %d", error);
832
833         if (sc->ioctl_tag)
834                 if ((error = bus_dma_tag_destroy(sc->ioctl_tag)))
835                         tw_osli_dbg_dprintf(1, sc,
836                                 "dma_tag_destroy(ioctl) returned %d", error);
837
838         if (sc->parent_tag)
839                 if ((error = bus_dma_tag_destroy(sc->parent_tag)))
840                         tw_osli_dbg_dprintf(1, sc,
841                                 "dma_tag_destroy(parent) returned %d", error);
842
843
844         /* Disconnect the interrupt handler. */
845         if (sc->intr_handle)
846                 if ((error = bus_teardown_intr(sc->bus_dev,
847                                 sc->irq_res, sc->intr_handle)))
848                         tw_osli_dbg_dprintf(1, sc,
849                                 "teardown_intr returned %d", error);
850
851         if (sc->irq_res != NULL)
852                 if ((error = bus_release_resource(sc->bus_dev,
853                                 SYS_RES_IRQ, sc->irq_res_id, sc->irq_res)))
854                         tw_osli_dbg_dprintf(1, sc,
855                                 "release_resource(irq) returned %d", error);
856
857
858         /* Release the register window mapping. */
859         if (sc->reg_res != NULL)
860                 if ((error = bus_release_resource(sc->bus_dev,
861                                 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)))
862                         tw_osli_dbg_dprintf(1, sc,
863                                 "release_resource(io) returned %d", error);
864
865
866         /* Destroy the control device. */
867         if (sc->ctrl_dev != (struct cdev *)NULL)
868                 destroy_dev(sc->ctrl_dev);
869
870         if ((error = sysctl_ctx_free(&sc->sysctl_ctxt)))
871                 tw_osli_dbg_dprintf(1, sc,
872                         "sysctl_ctx_free returned %d", error);
873
874 }
875
876
877
878 /*
879  * Function name:       twa_detach
880  * Description:         Called when the controller is being detached from
881  *                      the pci bus.
882  *
883  * Input:               dev     -- bus device corresponding to the ctlr
884  * Output:              None
885  * Return value:        0       -- success
886  *                      non-zero-- failure
887  */
888 static TW_INT32
889 twa_detach(device_t dev)
890 {
891         struct twa_softc        *sc = device_get_softc(dev);
892         TW_INT32                error;
893
894         tw_osli_dbg_dprintf(3, sc, "entered");
895
896         error = EBUSY;
897         if (sc->state & TW_OSLI_CTLR_STATE_OPEN) {
898                 tw_osli_printf(sc, "error = %d",
899                         TW_CL_SEVERITY_ERROR_STRING,
900                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
901                         0x2014,
902                         "Device open",
903                         error);
904                 goto out;
905         }
906
907         /* Shut the controller down. */
908         if ((error = twa_shutdown(dev)))
909                 goto out;
910
911         /* Free all resources associated with this controller. */
912         tw_osli_free_resources(sc);
913         error = 0;
914
915 out:
916         return(error);
917 }
918
919
920
921 /*
922  * Function name:       twa_shutdown
923  * Description:         Called at unload/shutdown time.  Lets the controller
924  *                      know that we are going down.
925  *
926  * Input:               dev     -- bus device corresponding to the ctlr
927  * Output:              None
928  * Return value:        0       -- success
929  *                      non-zero-- failure
930  */
931 static TW_INT32
932 twa_shutdown(device_t dev)
933 {
934         struct twa_softc        *sc = device_get_softc(dev);
935         TW_INT32                error = 0;
936
937         tw_osli_dbg_dprintf(3, sc, "entered");
938
939         /* Disconnect from the controller. */
940         if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) {
941                 tw_osli_printf(sc, "error = %d",
942                         TW_CL_SEVERITY_ERROR_STRING,
943                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
944                         0x2015,
945                         "Failed to shutdown Common Layer/controller",
946                         error);
947         }
948         return(error);
949 }
950
951
952
953 /*
954  * Function name:       twa_busdma_lock
955  * Description:         Function to provide synchronization during busdma_swi.
956  *
957  * Input:               lock_arg -- lock mutex sent as argument
958  *                      op -- operation (lock/unlock) expected of the function
959  * Output:              None
960  * Return value:        None
961  */
962 TW_VOID
963 twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op)
964 {
965         struct mtx      *lock;
966
967         lock = (struct mtx *)lock_arg;
968         switch (op) {
969         case BUS_DMA_LOCK:
970                 mtx_lock_spin(lock);
971                 break;
972
973         case BUS_DMA_UNLOCK:
974                 mtx_unlock_spin(lock);
975                 break;
976
977         default:
978                 panic("Unknown operation 0x%x for twa_busdma_lock!", op);
979         }
980 }
981
982
983 #ifdef TW_OSLI_DEFERRED_INTR_USED
984 /*
985  * Function name:       twa_pci_intr_fast
986  * Description:         Interrupt handler.  Wrapper for twa_interrupt.
987  *
988  * Input:               arg     -- ptr to OSL internal ctlr context
989  * Output:              FILTER_HANDLED or FILTER_STRAY
990  * Return value:        None
991  */
992 static int
993 twa_pci_intr_fast(TW_VOID *arg)
994 {
995         struct twa_softc        *sc = (struct twa_softc *)arg;
996
997         tw_osli_dbg_dprintf(10, sc, "entered");
998         if (tw_cl_interrupt(&(sc->ctlr_handle))) {
999                 tw_cl_deferred_interrupt(&(sc->ctlr_handle));
1000                 return(FILTER_HANDLED);
1001         }
1002         return(FILTER_STRAY);
1003 }
1004 #else
1005 /*
1006  * Function name:       twa_pci_intr
1007  * Description:         Interrupt handler.  Wrapper for twa_interrupt.
1008  *
1009  * Input:               arg     -- ptr to OSL internal ctlr context
1010  * Output:              None
1011  * Return value:        None
1012  */
1013 static TW_VOID
1014 twa_pci_intr(TW_VOID *arg)
1015 {
1016         struct twa_softc        *sc = (struct twa_softc *)arg;
1017
1018         tw_osli_dbg_dprintf(10, sc, "entered");
1019         if (tw_cl_interrupt(&(sc->ctlr_handle)))
1020                 tw_cl_deferred_interrupt(&(sc->ctlr_handle));
1021 }
1022 #endif
1023
1024 #ifdef TW_OSLI_DEFERRED_INTR_USED
1025
1026 /*
1027  * Function name:       twa_deferred_intr
1028  * Description:         Deferred interrupt handler.
1029  *
1030  * Input:               context -- ptr to OSL internal ctlr context
1031  *                      pending -- not used
1032  * Output:              None
1033  * Return value:        None
1034  */
1035 static TW_VOID
1036 twa_deferred_intr(TW_VOID *context, TW_INT32 pending)
1037 {
1038         struct twa_softc        *sc = (struct twa_softc *)context;
1039
1040         tw_osli_dbg_dprintf(10, sc, "entered");
1041
1042         tw_cl_deferred_interrupt(&(sc->ctlr_handle));
1043 }
1044
1045 #endif /* TW_OSLI_DEFERRED_INTR_USED */
1046
1047
1048
1049 /*
1050  * Function name:       tw_osli_fw_passthru
1051  * Description:         Builds a fw passthru cmd pkt, and submits it to CL.
1052  *
1053  * Input:               sc      -- ptr to OSL internal ctlr context
1054  *                      buf     -- ptr to ioctl pkt understood by CL
1055  * Output:              None
1056  * Return value:        0       -- success
1057  *                      non-zero-- failure
1058  */
1059 TW_INT32
1060 tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf)
1061 {
1062         struct tw_osli_req_context              *req;
1063         struct tw_osli_ioctl_no_data_buf        *user_buf =
1064                 (struct tw_osli_ioctl_no_data_buf *)buf;
1065         TW_TIME                                 end_time;
1066         TW_UINT32                               timeout = 60;
1067         TW_UINT32                               data_buf_size_adjusted;
1068         struct tw_cl_req_packet                 *req_pkt;
1069         struct tw_cl_passthru_req_packet        *pt_req;
1070         TW_INT32                                error;
1071
1072         tw_osli_dbg_dprintf(5, sc, "ioctl: passthru");
1073                 
1074         if ((req = tw_osli_get_request(sc)) == NULL)
1075                 return(EBUSY);
1076
1077         req->req_handle.osl_req_ctxt = req;
1078         req->orig_req = buf;
1079         req->flags |= TW_OSLI_REQ_FLAGS_PASSTHRU;
1080
1081         req_pkt = &(req->req_pkt);
1082         req_pkt->status = 0;
1083         req_pkt->tw_osl_callback = tw_osl_complete_passthru;
1084         /* Let the Common Layer retry the request on cmd queue full. */
1085         req_pkt->flags |= TW_CL_REQ_RETRY_ON_BUSY;
1086
1087         pt_req = &(req_pkt->gen_req_pkt.pt_req);
1088         /*
1089          * Make sure that the data buffer sent to firmware is a 
1090          * 512 byte multiple in size.
1091          */
1092         data_buf_size_adjusted =
1093                 (user_buf->driver_pkt.buffer_length +
1094                 (sc->sg_size_factor - 1)) & ~(sc->sg_size_factor - 1);
1095         if ((req->length = data_buf_size_adjusted)) {
1096                 if ((req->data = malloc(data_buf_size_adjusted,
1097                         TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
1098                         error = ENOMEM;
1099                         tw_osli_printf(sc, "error = %d",
1100                                 TW_CL_SEVERITY_ERROR_STRING,
1101                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1102                                 0x2016,
1103                                 "Could not alloc mem for "
1104                                 "fw_passthru data_buf",
1105                                 error);
1106                         goto fw_passthru_err;
1107                 }
1108                 /* Copy the payload. */
1109                 if ((error = copyin((TW_VOID *)(user_buf->pdata), 
1110                         req->data,
1111                         user_buf->driver_pkt.buffer_length)) != 0) {
1112                         tw_osli_printf(sc, "error = %d",
1113                                 TW_CL_SEVERITY_ERROR_STRING,
1114                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1115                                 0x2017,
1116                                 "Could not copyin fw_passthru data_buf",
1117                                 error);
1118                         goto fw_passthru_err;
1119                 }
1120                 pt_req->sgl_entries = 1; /* will be updated during mapping */
1121                 req->flags |= (TW_OSLI_REQ_FLAGS_DATA_IN |
1122                         TW_OSLI_REQ_FLAGS_DATA_OUT);
1123         } else
1124                 pt_req->sgl_entries = 0; /* no payload */
1125
1126         pt_req->cmd_pkt = (TW_VOID *)(&(user_buf->cmd_pkt));
1127         pt_req->cmd_pkt_length = sizeof(struct tw_cl_command_packet);
1128
1129         if ((error = tw_osli_map_request(req)))
1130                 goto fw_passthru_err;
1131
1132         end_time = tw_osl_get_local_time() + timeout;
1133         while (req->state != TW_OSLI_REQ_STATE_COMPLETE) {
1134                 req->flags |= TW_OSLI_REQ_FLAGS_SLEEPING;
1135                 
1136                 error = tsleep(req, PRIBIO, "twa_passthru", timeout * hz);
1137
1138                 if (!(req->flags & TW_OSLI_REQ_FLAGS_SLEEPING))
1139                         error = 0;
1140                 req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING;
1141
1142                 if (! error) {
1143                         if (((error = req->error_code)) ||
1144                                 ((error = (req->state !=
1145                                 TW_OSLI_REQ_STATE_COMPLETE))) ||
1146                                 ((error = req_pkt->status)))
1147                                 goto fw_passthru_err;
1148                         break;
1149                 }
1150
1151                 if (req_pkt->status) {
1152                         error = req_pkt->status;
1153                         goto fw_passthru_err;
1154                 }
1155
1156                 if (error == EWOULDBLOCK) {
1157                         /* Time out! */
1158                         tw_osli_printf(sc, "request = %p",
1159                                 TW_CL_SEVERITY_ERROR_STRING,
1160                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1161                                 0x2018,
1162                                 "Passthru request timed out!",
1163                                 req);
1164                         /*
1165                          * Should I check here if the timeout happened
1166                          * because of yet another reset, and not do a
1167                          * second reset?
1168                          */
1169                         tw_cl_reset_ctlr(&sc->ctlr_handle);
1170                         /*
1171                          * Don't touch req after a reset.  It (and any
1172                          * associated data) will already have been
1173                          * freed by the callback.  Just return.
1174                          */
1175                         user_buf->driver_pkt.os_status = error;
1176                         return(ETIMEDOUT);
1177                 }
1178                 /* 
1179                  * Either the request got completed, or we were woken up by a
1180                  * signal.  Calculate the new timeout, in case it was the latter.
1181                  */
1182                 timeout = (end_time - tw_osl_get_local_time());
1183         }
1184
1185         /* If there was a payload, copy it back. */
1186         if ((!error) && (req->length))
1187                 if ((error = copyout(req->data, user_buf->pdata,
1188                         user_buf->driver_pkt.buffer_length)))
1189                         tw_osli_printf(sc, "error = %d",
1190                                 TW_CL_SEVERITY_ERROR_STRING,
1191                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1192                                 0x2019,
1193                                 "Could not copyout fw_passthru data_buf",
1194                                 error);
1195         
1196 fw_passthru_err:
1197         /*
1198          * Print the failure message.  For some reason, on certain OS versions,
1199          * printing this error message during reset hangs the display (although
1200          * the rest of the system is running fine.  So, don't print it if the
1201          * failure was due to a reset.
1202          */
1203         if ((error) && (error != TW_CL_ERR_REQ_BUS_RESET))
1204                 tw_osli_printf(sc, "error = %d",                
1205                         TW_CL_SEVERITY_ERROR_STRING,
1206                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1207                         0x201A,
1208                         "Firmware passthru failed!",
1209                         error);
1210
1211         user_buf->driver_pkt.os_status = error;
1212         /* Free resources. */
1213         if (req->data)
1214                 free(req->data, TW_OSLI_MALLOC_CLASS);
1215         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
1216         return(error);
1217 }
1218
1219
1220
1221 /*
1222  * Function name:       tw_osl_complete_passthru
1223  * Description:         Called to complete passthru requests.
1224  *
1225  * Input:               req_handle      -- ptr to request handle
1226  * Output:              None
1227  * Return value:        None
1228  */
1229 TW_VOID
1230 tw_osl_complete_passthru(struct tw_cl_req_handle *req_handle)
1231 {
1232         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
1233         struct twa_softc                *sc = req->ctlr;
1234
1235         tw_osli_dbg_dprintf(5, sc, "entered");
1236
1237         if (req->state != TW_OSLI_REQ_STATE_BUSY) {
1238                 tw_osli_printf(sc, "request = %p, status = %d",
1239                         TW_CL_SEVERITY_ERROR_STRING,
1240                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1241                         0x201B,
1242                         "Unposted command completed!!",
1243                         req, req->state);
1244         }
1245
1246         /*
1247          * Remove request from the busy queue.  Just mark it complete.
1248          * There's no need to move it into the complete queue as we are
1249          * going to be done with it right now.
1250          */
1251         req->state = TW_OSLI_REQ_STATE_COMPLETE;
1252         tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
1253
1254         tw_osli_unmap_request(req);
1255
1256         /*
1257          * Don't do a wake up if there was an error even before the request
1258          * was sent down to the Common Layer, and we hadn't gotten an
1259          * EINPROGRESS.  The request originator will then be returned an
1260          * error, and he can do the clean-up.
1261          */
1262         if ((req->error_code) &&
1263                 (!(req->state & TW_OSLI_REQ_FLAGS_IN_PROGRESS)))
1264                 return;
1265
1266         if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1267                 if (req->flags & TW_OSLI_REQ_FLAGS_SLEEPING) {
1268                         /* Wake up the sleeping command originator. */
1269                         tw_osli_dbg_dprintf(5, sc,
1270                                 "Waking up originator of request %p", req);
1271                         req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING;
1272                         wakeup_one(req);
1273                 } else {
1274                         /*
1275                          * If the request completed even before tsleep
1276                          * was called, simply return.
1277                          */
1278                         if (req->flags & TW_OSLI_REQ_FLAGS_MAPPED)
1279                                 return;
1280
1281                         tw_osli_printf(sc, "request = %p",
1282                                 TW_CL_SEVERITY_ERROR_STRING,
1283                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1284                                 0x201C,
1285                                 "Passthru callback called, "
1286                                 "and caller not sleeping",
1287                                 req);
1288                 }
1289         } else {
1290                 tw_osli_printf(sc, "request = %p",
1291                         TW_CL_SEVERITY_ERROR_STRING,
1292                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1293                         0x201D,
1294                         "Passthru callback called for non-passthru request",
1295                         req);
1296         }
1297 }
1298
1299
1300
1301 /*
1302  * Function name:       tw_osli_get_request
1303  * Description:         Gets a request pkt from the free queue.
1304  *
1305  * Input:               sc      -- ptr to OSL internal ctlr context
1306  * Output:              None
1307  * Return value:        ptr to request pkt      -- success
1308  *                      NULL                    -- failure
1309  */
1310 struct tw_osli_req_context *
1311 tw_osli_get_request(struct twa_softc *sc)
1312 {
1313         struct tw_osli_req_context      *req;
1314
1315         tw_osli_dbg_dprintf(4, sc, "entered");
1316
1317         /* Get a free request packet. */
1318         req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q);
1319
1320         /* Initialize some fields to their defaults. */
1321         if (req) {
1322                 req->req_handle.osl_req_ctxt = NULL;
1323                 req->req_handle.cl_req_ctxt = NULL;
1324                 req->data = NULL;
1325                 req->length = 0;
1326                 req->real_data = NULL;
1327                 req->real_length = 0;
1328                 req->state = TW_OSLI_REQ_STATE_INIT;/* req being initialized */
1329                 req->flags = 0;
1330                 req->error_code = 0;
1331                 req->orig_req = NULL;
1332
1333 #ifdef TW_OSL_DMA_MEM_ALLOC_PER_REQUEST
1334
1335                 /* Don't zero dma_mem & dma_mem_phys in req_pkt. */
1336                 req->req_pkt.cmd = 0;
1337                 req->req_pkt.flags = 0;
1338                 req->req_pkt.status = 0;
1339                 req->req_pkt.tw_osl_callback = NULL;
1340                 bzero(&(req->req_pkt.gen_req_pkt),
1341                         sizeof(req->req_pkt.gen_req_pkt));
1342
1343 #else /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
1344
1345                 bzero(&(req->req_pkt), sizeof(struct tw_cl_req_packet));
1346
1347 #endif /* TW_OSL_DMA_MEM_ALLOC_PER_REQUEST */
1348         }
1349         return(req);
1350 }
1351
1352
1353
1354 /*
1355  * Function name:       twa_map_load_data_callback
1356  * Description:         Callback of bus_dmamap_load for the buffer associated
1357  *                      with data.  Updates the cmd pkt (size/sgl_entries
1358  *                      fields, as applicable) to reflect the number of sg
1359  *                      elements.
1360  *
1361  * Input:               arg     -- ptr to OSL internal request context
1362  *                      segs    -- ptr to a list of segment descriptors
1363  *                      nsegments--# of segments
1364  *                      error   -- 0 if no errors encountered before callback,
1365  *                                 non-zero if errors were encountered
1366  * Output:              None
1367  * Return value:        None
1368  */
1369 static TW_VOID
1370 twa_map_load_data_callback(TW_VOID *arg, bus_dma_segment_t *segs,
1371         TW_INT32 nsegments, TW_INT32 error)
1372 {
1373         struct tw_osli_req_context      *req =
1374                 (struct tw_osli_req_context *)arg;
1375         struct twa_softc                *sc = req->ctlr;
1376         struct tw_cl_req_packet         *req_pkt = &(req->req_pkt);
1377
1378         tw_osli_dbg_dprintf(10, sc, "entered");
1379
1380         /* Mark the request as currently being processed. */
1381         req->state = TW_OSLI_REQ_STATE_BUSY;
1382         /* Move the request into the busy queue. */
1383         tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q);
1384
1385         req->flags |= TW_OSLI_REQ_FLAGS_MAPPED;
1386         if (req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS)
1387                 tw_osli_allow_new_requests(sc, (TW_VOID *)(req->orig_req));
1388
1389         if (error == EFBIG) {
1390                 req->error_code = error;
1391                 goto out;
1392         }
1393
1394         if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1395                 struct tw_cl_passthru_req_packet        *pt_req;
1396
1397                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN)
1398                         bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
1399                                 BUS_DMASYNC_PREREAD);
1400
1401                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) {
1402                         /* 
1403                          * If we're using an alignment buffer, and we're
1404                          * writing data, copy the real data out.
1405                          */
1406                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1407                                 bcopy(req->real_data, req->data, req->real_length);
1408                         bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
1409                                 BUS_DMASYNC_PREWRITE);
1410                 }
1411
1412                 pt_req = &(req_pkt->gen_req_pkt.pt_req);
1413                 pt_req->sg_list = (TW_UINT8 *)segs;
1414                 pt_req->sgl_entries += (nsegments - 1);
1415                 error = tw_cl_fw_passthru(&(sc->ctlr_handle), req_pkt,
1416                         &(req->req_handle));
1417         } else {
1418                 struct tw_cl_scsi_req_packet    *scsi_req;
1419
1420                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN)
1421                         bus_dmamap_sync(sc->dma_tag, req->dma_map,
1422                                 BUS_DMASYNC_PREREAD);
1423
1424                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) {
1425                         /* 
1426                          * If we're using an alignment buffer, and we're
1427                          * writing data, copy the real data out.
1428                          */
1429                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1430                                 bcopy(req->real_data, req->data, req->real_length);
1431                         bus_dmamap_sync(sc->dma_tag, req->dma_map,
1432                                 BUS_DMASYNC_PREWRITE);
1433                 }
1434
1435                 scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
1436                 scsi_req->sg_list = (TW_UINT8 *)segs;
1437                 scsi_req->sgl_entries += (nsegments - 1);
1438                 error = tw_cl_start_io(&(sc->ctlr_handle), req_pkt,
1439                         &(req->req_handle));
1440         }
1441
1442 out:
1443         if (error) {
1444                 req->error_code = error;
1445                 req_pkt->tw_osl_callback(&(req->req_handle));
1446                 /*
1447                  * If the caller had been returned EINPROGRESS, and he has
1448                  * registered a callback for handling completion, the callback
1449                  * will never get called because we were unable to submit the
1450                  * request.  So, free up the request right here.
1451                  */
1452                 if (req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS)
1453                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
1454         }
1455 }
1456
1457
1458
1459 /*
1460  * Function name:       twa_map_load_callback
1461  * Description:         Callback of bus_dmamap_load for the buffer associated
1462  *                      with a cmd pkt.
1463  *
1464  * Input:               arg     -- ptr to variable to hold phys addr
1465  *                      segs    -- ptr to a list of segment descriptors
1466  *                      nsegments--# of segments
1467  *                      error   -- 0 if no errors encountered before callback,
1468  *                                 non-zero if errors were encountered
1469  * Output:              None
1470  * Return value:        None
1471  */
1472 static TW_VOID
1473 twa_map_load_callback(TW_VOID *arg, bus_dma_segment_t *segs,
1474         TW_INT32 nsegments, TW_INT32 error)
1475 {
1476         *((bus_addr_t *)arg) = segs[0].ds_addr;
1477 }
1478
1479
1480
1481 /*
1482  * Function name:       tw_osli_map_request
1483  * Description:         Maps a cmd pkt and data associated with it, into
1484  *                      DMA'able memory.
1485  *
1486  * Input:               req     -- ptr to request pkt
1487  * Output:              None
1488  * Return value:        0       -- success
1489  *                      non-zero-- failure
1490  */
1491 TW_INT32
1492 tw_osli_map_request(struct tw_osli_req_context *req)
1493 {
1494         struct twa_softc        *sc = req->ctlr;
1495         TW_INT32                error = 0;
1496
1497         tw_osli_dbg_dprintf(10, sc, "entered");
1498
1499         /* If the command involves data, map that too. */
1500         if (req->data != NULL) {
1501                 /*
1502                  * It's sufficient for the data pointer to be 4-byte aligned
1503                  * to work with 9000.  However, if 4-byte aligned addresses
1504                  * are passed to bus_dmamap_load, we can get back sg elements
1505                  * that are not 512-byte multiples in size.  So, we will let
1506                  * only those buffers that are 512-byte aligned to pass
1507                  * through, and bounce the rest, so as to make sure that we
1508                  * always get back sg elements that are 512-byte multiples
1509                  * in size.
1510                  */
1511                 if (((vm_offset_t)req->data % sc->sg_size_factor) ||
1512                         (req->length % sc->sg_size_factor)) {
1513                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED;
1514                         /* Save original data pointer and length. */
1515                         req->real_data = req->data;
1516                         req->real_length = req->length;
1517                         req->length = (req->length +
1518                                 (sc->sg_size_factor - 1)) &
1519                                 ~(sc->sg_size_factor - 1);
1520                         req->data = malloc(req->length, TW_OSLI_MALLOC_CLASS,
1521                                         M_NOWAIT);
1522                         if (req->data == NULL) {
1523                                 tw_osli_printf(sc, "error = %d",
1524                                         TW_CL_SEVERITY_ERROR_STRING,
1525                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1526                                         0x201E,
1527                                         "Failed to allocate memory "
1528                                         "for bounce buffer",
1529                                         ENOMEM);
1530                                 /* Restore original data pointer and length. */
1531                                 req->data = req->real_data;
1532                                 req->length = req->real_length;
1533                                 return(ENOMEM);
1534                         }
1535                 }
1536         
1537                 /*
1538                  * Map the data buffer into bus space and build the SG list.
1539                  */
1540                 if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1541                         /* Lock against multiple simultaneous ioctl calls. */
1542                         mtx_lock_spin(sc->io_lock);
1543                         error = bus_dmamap_load(sc->ioctl_tag, sc->ioctl_map,
1544                                 req->data, req->length,
1545                                 twa_map_load_data_callback, req,
1546                                 BUS_DMA_WAITOK);
1547                         mtx_unlock_spin(sc->io_lock);
1548                 } else {
1549                         /*
1550                          * There's only one CAM I/O thread running at a time.
1551                          * So, there's no need to hold the io_lock.
1552                          */
1553                         error = bus_dmamap_load(sc->dma_tag, req->dma_map,
1554                                 req->data, req->length,
1555                                 twa_map_load_data_callback, req,
1556                                 BUS_DMA_WAITOK);
1557                 }
1558                 
1559                 if (!error)
1560                         error = req->error_code;
1561                 else {
1562                         if (error == EINPROGRESS) {
1563                                 /*
1564                                  * Specifying sc->io_lock as the lockfuncarg
1565                                  * in ...tag_create should protect the access
1566                                  * of ...FLAGS_MAPPED from the callback.
1567                                  */
1568                                 mtx_lock_spin(sc->io_lock);
1569                                 if (!(req->flags & TW_OSLI_REQ_FLAGS_MAPPED)) {
1570                                         req->flags |=
1571                                                 TW_OSLI_REQ_FLAGS_IN_PROGRESS;
1572                                         tw_osli_disallow_new_requests(sc);
1573                                 }
1574                                 mtx_unlock_spin(sc->io_lock);
1575                                 error = 0;
1576                         } else {
1577                                 /* Free alignment buffer if it was used. */
1578                                 if (req->flags &
1579                                         TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
1580                                         free(req->data, TW_OSLI_MALLOC_CLASS);
1581                                         /*
1582                                          * Restore original data pointer
1583                                          * and length.
1584                                          */
1585                                         req->data = req->real_data;
1586                                         req->length = req->real_length;
1587                                 }
1588                         }
1589                 }
1590
1591         } else {
1592                 /* Mark the request as currently being processed. */
1593                 req->state = TW_OSLI_REQ_STATE_BUSY;
1594                 /* Move the request into the busy queue. */
1595                 tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q);
1596                 if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU)
1597                         error = tw_cl_fw_passthru(&sc->ctlr_handle,
1598                                         &(req->req_pkt), &(req->req_handle));
1599                 else
1600                         error = tw_cl_start_io(&sc->ctlr_handle,
1601                                         &(req->req_pkt), &(req->req_handle));
1602                 if (error) {
1603                         req->error_code = error;
1604                         req->req_pkt.tw_osl_callback(&(req->req_handle));
1605                 }
1606         }
1607         return(error);
1608 }
1609
1610
1611
1612 /*
1613  * Function name:       tw_osli_unmap_request
1614  * Description:         Undoes the mapping done by tw_osli_map_request.
1615  *
1616  * Input:               req     -- ptr to request pkt
1617  * Output:              None
1618  * Return value:        None
1619  */
1620 TW_VOID
1621 tw_osli_unmap_request(struct tw_osli_req_context *req)
1622 {
1623         struct twa_softc        *sc = req->ctlr;
1624
1625         tw_osli_dbg_dprintf(10, sc, "entered");
1626
1627         /* If the command involved data, unmap that too. */
1628         if (req->data != NULL) {
1629                 if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1630                         /* Lock against multiple simultaneous ioctl calls. */
1631                         mtx_lock_spin(sc->io_lock);
1632
1633                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) {
1634                                 bus_dmamap_sync(sc->ioctl_tag,
1635                                         sc->ioctl_map, BUS_DMASYNC_POSTREAD);
1636
1637                                 /* 
1638                                  * If we are using a bounce buffer, and we are
1639                                  * reading data, copy the real data in.
1640                                  */
1641                                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1642                                         bcopy(req->data, req->real_data,
1643                                                 req->real_length);
1644                         }
1645
1646                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT)
1647                                 bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
1648                                         BUS_DMASYNC_POSTWRITE);
1649
1650                         bus_dmamap_unload(sc->ioctl_tag, sc->ioctl_map);
1651
1652                         mtx_unlock_spin(sc->io_lock);
1653                 } else {
1654                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) {
1655                                 bus_dmamap_sync(sc->dma_tag,
1656                                         req->dma_map, BUS_DMASYNC_POSTREAD);
1657
1658                                 /* 
1659                                  * If we are using a bounce buffer, and we are
1660                                  * reading data, copy the real data in.
1661                                  */
1662                                 if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1663                                         bcopy(req->data, req->real_data,
1664                                                 req->real_length);
1665                         }
1666                         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT)
1667                                 bus_dmamap_sync(sc->dma_tag, req->dma_map,
1668                                         BUS_DMASYNC_POSTWRITE);
1669
1670                         bus_dmamap_unload(sc->dma_tag, req->dma_map);
1671                 }
1672         }
1673
1674         /* Free alignment buffer if it was used. */
1675         if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
1676                 free(req->data, TW_OSLI_MALLOC_CLASS);
1677                 /* Restore original data pointer and length. */
1678                 req->data = req->real_data;
1679                 req->length = req->real_length;
1680         }
1681 }
1682
1683
1684
1685 #ifdef TW_OSL_DEBUG
1686
1687 TW_VOID twa_report_stats(TW_VOID);
1688 TW_VOID twa_reset_stats(TW_VOID);
1689 TW_VOID tw_osli_print_ctlr_stats(struct twa_softc *sc);
1690 TW_VOID twa_print_req_info(struct tw_osli_req_context *req);
1691
1692
1693 /*
1694  * Function name:       twa_report_stats
1695  * Description:         For being called from ddb.  Calls functions that print
1696  *                      OSL and CL internal stats for the controller.
1697  *
1698  * Input:               None
1699  * Output:              None
1700  * Return value:        None
1701  */
1702 TW_VOID
1703 twa_report_stats(TW_VOID)
1704 {
1705         struct twa_softc        *sc;
1706         TW_INT32                i;
1707
1708         for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
1709                 tw_osli_print_ctlr_stats(sc);
1710                 tw_cl_print_ctlr_stats(&sc->ctlr_handle);
1711         }
1712 }
1713
1714
1715
1716 /*
1717  * Function name:       tw_osli_print_ctlr_stats
1718  * Description:         For being called from ddb.  Prints OSL controller stats
1719  *
1720  * Input:               sc      -- ptr to OSL internal controller context
1721  * Output:              None
1722  * Return value:        None
1723  */
1724 TW_VOID
1725 tw_osli_print_ctlr_stats(struct twa_softc *sc)
1726 {
1727         twa_printf(sc, "osl_ctlr_ctxt = %p\n", sc);
1728         twa_printf(sc, "OSLq type  current  max\n");
1729         twa_printf(sc, "free      %04d     %04d\n",
1730                 sc->q_stats[TW_OSLI_FREE_Q].cur_len,
1731                 sc->q_stats[TW_OSLI_FREE_Q].max_len);
1732         twa_printf(sc, "busy      %04d     %04d\n",
1733                 sc->q_stats[TW_OSLI_BUSY_Q].cur_len,
1734                 sc->q_stats[TW_OSLI_BUSY_Q].max_len);
1735 }       
1736
1737
1738
1739 /*
1740  * Function name:       twa_print_req_info
1741  * Description:         For being called from ddb.  Calls functions that print
1742  *                      OSL and CL internal details for the request.
1743  *
1744  * Input:               req     -- ptr to OSL internal request context
1745  * Output:              None
1746  * Return value:        None
1747  */
1748 TW_VOID
1749 twa_print_req_info(struct tw_osli_req_context *req)
1750 {
1751         struct twa_softc        *sc = req->ctlr;
1752
1753         twa_printf(sc, "OSL details for request:\n");
1754         twa_printf(sc, "osl_req_ctxt = %p, cl_req_ctxt = %p\n"
1755                 "data = %p, length = 0x%x, real_data = %p, real_length = 0x%x\n"
1756                 "state = 0x%x, flags = 0x%x, error = 0x%x, orig_req = %p\n"
1757                 "next_req = %p, prev_req = %p, dma_map = %p\n",
1758                 req->req_handle.osl_req_ctxt, req->req_handle.cl_req_ctxt,
1759                 req->data, req->length, req->real_data, req->real_length,
1760                 req->state, req->flags, req->error_code, req->orig_req,
1761                 req->link.next, req->link.prev, req->dma_map);
1762         tw_cl_print_req_info(&(req->req_handle));
1763 }
1764
1765
1766
1767 /*
1768  * Function name:       twa_reset_stats
1769  * Description:         For being called from ddb.
1770  *                      Resets some OSL controller stats.
1771  *
1772  * Input:               None
1773  * Output:              None
1774  * Return value:        None
1775  */
1776 TW_VOID
1777 twa_reset_stats(TW_VOID)
1778 {
1779         struct twa_softc        *sc;
1780         TW_INT32                i;
1781
1782         for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
1783                 sc->q_stats[TW_OSLI_FREE_Q].max_len = 0;
1784                 sc->q_stats[TW_OSLI_BUSY_Q].max_len = 0;
1785                 tw_cl_reset_stats(&sc->ctlr_handle);
1786         }
1787 }
1788
1789 #endif /* TW_OSL_DEBUG */