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