1144966Svkashyap/*
2169400Sscottl * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3144966Svkashyap * Copyright (c) 2004-05 Vinod Kashyap.
4144966Svkashyap * Copyright (c) 2000 Michael Smith
5144966Svkashyap * Copyright (c) 2000 BSDi
6144966Svkashyap * All rights reserved.
7144966Svkashyap *
8144966Svkashyap * Redistribution and use in source and binary forms, with or without
9144966Svkashyap * modification, are permitted provided that the following conditions
10144966Svkashyap * are met:
11144966Svkashyap * 1. Redistributions of source code must retain the above copyright
12144966Svkashyap *    notice, this list of conditions and the following disclaimer.
13144966Svkashyap * 2. Redistributions in binary form must reproduce the above copyright
14144966Svkashyap *    notice, this list of conditions and the following disclaimer in the
15144966Svkashyap *    documentation and/or other materials provided with the distribution.
16144966Svkashyap *
17144966Svkashyap * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18144966Svkashyap * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19144966Svkashyap * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20144966Svkashyap * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21144966Svkashyap * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22144966Svkashyap * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23144966Svkashyap * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24144966Svkashyap * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25144966Svkashyap * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26144966Svkashyap * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27144966Svkashyap * SUCH DAMAGE.
28144966Svkashyap */
29144966Svkashyap
30229093Shselasky#include <sys/cdefs.h>
31229093Shselasky__FBSDID("$FreeBSD$");
32229093Shselasky
33144966Svkashyap/*
34144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers.
35144966Svkashyap *
36144966Svkashyap * Author: Vinod Kashyap
37169400Sscottl * Modifications by: Adam Radford
38172496Sscottl * Modifications by: Manjunath Ranganathaiah
39144966Svkashyap */
40144966Svkashyap
41144966Svkashyap
42144966Svkashyap/*
43144966Svkashyap * FreeBSD specific functions not related to CAM, and other
44144966Svkashyap * miscellaneous functions.
45144966Svkashyap */
46144966Svkashyap
47144966Svkashyap
48149968Sobrien#include <dev/twa/tw_osl_includes.h>
49149968Sobrien#include <dev/twa/tw_cl_fwif.h>
50149968Sobrien#include <dev/twa/tw_cl_ioctl.h>
51149968Sobrien#include <dev/twa/tw_osl_ioctl.h>
52144966Svkashyap
53144966Svkashyap#ifdef TW_OSL_DEBUG
54144966SvkashyapTW_INT32	TW_DEBUG_LEVEL_FOR_OSL = TW_OSL_DEBUG;
55144966SvkashyapTW_INT32	TW_OSL_DEBUG_LEVEL_FOR_CL = TW_OSL_DEBUG;
56144966Svkashyap#endif /* TW_OSL_DEBUG */
57144966Svkashyap
58249132Smavstatic MALLOC_DEFINE(TW_OSLI_MALLOC_CLASS, "twa_commands", "twa commands");
59144966Svkashyap
60144966Svkashyap
61144966Svkashyapstatic	d_open_t		twa_open;
62144966Svkashyapstatic	d_close_t		twa_close;
63144966Svkashyapstatic	d_ioctl_t		twa_ioctl;
64144966Svkashyap
65144966Svkashyapstatic struct cdevsw twa_cdevsw = {
66144966Svkashyap	.d_version =	D_VERSION,
67144966Svkashyap	.d_open =	twa_open,
68144966Svkashyap	.d_close =	twa_close,
69144966Svkashyap	.d_ioctl =	twa_ioctl,
70144966Svkashyap	.d_name =	"twa",
71144966Svkashyap};
72144966Svkashyap
73144966Svkashyapstatic devclass_t	twa_devclass;
74144966Svkashyap
75144966Svkashyap
76144966Svkashyap/*
77144966Svkashyap * Function name:	twa_open
78144966Svkashyap * Description:		Called when the controller is opened.
79144966Svkashyap *			Simply marks the controller as open.
80144966Svkashyap *
81144966Svkashyap * Input:		dev	-- control device corresponding to the ctlr
82144966Svkashyap *			flags	-- mode of open
83144966Svkashyap *			fmt	-- device type (character/block etc.)
84144966Svkashyap *			proc	-- current process
85144966Svkashyap * Output:		None
86144966Svkashyap * Return value:	0	-- success
87144966Svkashyap *			non-zero-- failure
88144966Svkashyap */
89144966Svkashyapstatic TW_INT32
90192450Simptwa_open(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, struct thread *proc)
91144966Svkashyap{
92191060Sed	struct twa_softc	*sc = (struct twa_softc *)(dev->si_drv1);
93144966Svkashyap
94144966Svkashyap	tw_osli_dbg_dprintf(5, sc, "entered");
95208969Sdelphij	sc->open = TW_CL_TRUE;
96144966Svkashyap	return(0);
97144966Svkashyap}
98144966Svkashyap
99144966Svkashyap
100144966Svkashyap
101144966Svkashyap/*
102144966Svkashyap * Function name:	twa_close
103144966Svkashyap * Description:		Called when the controller is closed.
104144966Svkashyap *			Simply marks the controller as not open.
105144966Svkashyap *
106144966Svkashyap * Input:		dev	-- control device corresponding to the ctlr
107144966Svkashyap *			flags	-- mode of corresponding open
108144966Svkashyap *			fmt	-- device type (character/block etc.)
109144966Svkashyap *			proc	-- current process
110144966Svkashyap * Output:		None
111144966Svkashyap * Return value:	0	-- success
112144966Svkashyap *			non-zero-- failure
113144966Svkashyap */
114144966Svkashyapstatic TW_INT32
115192450Simptwa_close(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, struct thread *proc)
116144966Svkashyap{
117191060Sed	struct twa_softc	*sc = (struct twa_softc *)(dev->si_drv1);
118144966Svkashyap
119144966Svkashyap	tw_osli_dbg_dprintf(5, sc, "entered");
120208969Sdelphij	sc->open = TW_CL_FALSE;
121144966Svkashyap	return(0);
122144966Svkashyap}
123144966Svkashyap
124144966Svkashyap
125144966Svkashyap
126144966Svkashyap/*
127144966Svkashyap * Function name:	twa_ioctl
128144966Svkashyap * Description:		Called when an ioctl is posted to the controller.
129144966Svkashyap *			Handles any OS Layer specific cmds, passes the rest
130144966Svkashyap *			on to the Common Layer.
131144966Svkashyap *
132144966Svkashyap * Input:		dev	-- control device corresponding to the ctlr
133144966Svkashyap *			cmd	-- ioctl cmd
134144966Svkashyap *			buf	-- ptr to buffer in kernel memory, which is
135144966Svkashyap *				   a copy of the input buffer in user-space
136144966Svkashyap *			flags	-- mode of corresponding open
137144966Svkashyap *			proc	-- current process
138144966Svkashyap * Output:		buf	-- ptr to buffer in kernel memory, which will
139144966Svkashyap *				   be copied to the output buffer in user-space
140144966Svkashyap * Return value:	0	-- success
141144966Svkashyap *			non-zero-- failure
142144966Svkashyap */
143144966Svkashyapstatic TW_INT32
144192450Simptwa_ioctl(struct cdev *dev, u_long cmd, caddr_t buf, TW_INT32 flags, struct thread *proc)
145144966Svkashyap{
146144966Svkashyap	struct twa_softc	*sc = (struct twa_softc *)(dev->si_drv1);
147144966Svkashyap	TW_INT32		error;
148144966Svkashyap
149144966Svkashyap	tw_osli_dbg_dprintf(5, sc, "entered");
150144966Svkashyap
151144966Svkashyap	switch (cmd) {
152144966Svkashyap	case TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH:
153144966Svkashyap		tw_osli_dbg_dprintf(6, sc, "ioctl: fw_passthru");
154144966Svkashyap		error = tw_osli_fw_passthru(sc, (TW_INT8 *)buf);
155144966Svkashyap		break;
156144966Svkashyap
157144966Svkashyap	case TW_OSL_IOCTL_SCAN_BUS:
158144966Svkashyap		/* Request CAM for a bus scan. */
159144966Svkashyap		tw_osli_dbg_dprintf(6, sc, "ioctl: scan bus");
160144966Svkashyap		error = tw_osli_request_bus_scan(sc);
161144966Svkashyap		break;
162144966Svkashyap
163144966Svkashyap	default:
164144966Svkashyap		tw_osli_dbg_dprintf(6, sc, "ioctl: 0x%lx", cmd);
165144966Svkashyap		error = tw_cl_ioctl(&sc->ctlr_handle, cmd, buf);
166144966Svkashyap		break;
167144966Svkashyap	}
168144966Svkashyap	return(error);
169144966Svkashyap}
170144966Svkashyap
171144966Svkashyap
172144966Svkashyap
173144966Svkashyapstatic TW_INT32	twa_probe(device_t dev);
174144966Svkashyapstatic TW_INT32	twa_attach(device_t dev);
175144966Svkashyapstatic TW_INT32	twa_detach(device_t dev);
176144966Svkashyapstatic TW_INT32	twa_shutdown(device_t dev);
177144966Svkashyapstatic TW_VOID	twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op);
178166901Spisostatic TW_VOID	twa_pci_intr(TW_VOID *arg);
179212008Sdelphijstatic TW_VOID	twa_watchdog(TW_VOID *arg);
180212008Sdelphijint twa_setup_intr(struct twa_softc *sc);
181212008Sdelphijint twa_teardown_intr(struct twa_softc *sc);
182144966Svkashyap
183144966Svkashyapstatic TW_INT32	tw_osli_alloc_mem(struct twa_softc *sc);
184144966Svkashyapstatic TW_VOID	tw_osli_free_resources(struct twa_softc *sc);
185144966Svkashyap
186144966Svkashyapstatic TW_VOID	twa_map_load_data_callback(TW_VOID *arg,
187144966Svkashyap	bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error);
188144966Svkashyapstatic TW_VOID	twa_map_load_callback(TW_VOID *arg,
189144966Svkashyap	bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error);
190144966Svkashyap
191144966Svkashyap
192144966Svkashyapstatic device_method_t	twa_methods[] = {
193144966Svkashyap	/* Device interface */
194144966Svkashyap	DEVMETHOD(device_probe,		twa_probe),
195144966Svkashyap	DEVMETHOD(device_attach,	twa_attach),
196144966Svkashyap	DEVMETHOD(device_detach,	twa_detach),
197144966Svkashyap	DEVMETHOD(device_shutdown,	twa_shutdown),
198144966Svkashyap
199229093Shselasky	DEVMETHOD_END
200144966Svkashyap};
201144966Svkashyap
202144966Svkashyapstatic driver_t	twa_pci_driver = {
203144966Svkashyap	"twa",
204144966Svkashyap	twa_methods,
205144966Svkashyap	sizeof(struct twa_softc)
206144966Svkashyap};
207144966Svkashyap
208144966SvkashyapDRIVER_MODULE(twa, pci, twa_pci_driver, twa_devclass, 0, 0);
209169400SscottlMODULE_DEPEND(twa, cam, 1, 1, 1);
210165106SmjacobMODULE_DEPEND(twa, pci, 1, 1, 1);
211144966Svkashyap
212144966Svkashyap
213144966Svkashyap/*
214144966Svkashyap * Function name:	twa_probe
215144966Svkashyap * Description:		Called at driver load time.  Claims 9000 ctlrs.
216144966Svkashyap *
217144966Svkashyap * Input:		dev	-- bus device corresponding to the ctlr
218144966Svkashyap * Output:		None
219144966Svkashyap * Return value:	<= 0	-- success
220144966Svkashyap *			> 0	-- failure
221144966Svkashyap */
222144966Svkashyapstatic TW_INT32
223144966Svkashyaptwa_probe(device_t dev)
224144966Svkashyap{
225144966Svkashyap	static TW_UINT8	first_ctlr = 1;
226144966Svkashyap
227144966Svkashyap	tw_osli_dbg_printf(3, "entered");
228144966Svkashyap
229144966Svkashyap	if (tw_cl_ctlr_supported(pci_get_vendor(dev), pci_get_device(dev))) {
230144966Svkashyap		device_set_desc(dev, TW_OSLI_DEVICE_NAME);
231144966Svkashyap		/* Print the driver version only once. */
232144966Svkashyap		if (first_ctlr) {
233144966Svkashyap			printf("3ware device driver for 9000 series storage "
234144966Svkashyap				"controllers, version: %s\n",
235144966Svkashyap				TW_OSL_DRIVER_VERSION_STRING);
236144966Svkashyap			first_ctlr = 0;
237144966Svkashyap		}
238144966Svkashyap		return(0);
239144966Svkashyap	}
240144966Svkashyap	return(ENXIO);
241144966Svkashyap}
242144966Svkashyap
243212008Sdelphijint twa_setup_intr(struct twa_softc *sc)
244212008Sdelphij{
245212008Sdelphij	int error = 0;
246144966Svkashyap
247212008Sdelphij	if (!(sc->intr_handle) && (sc->irq_res)) {
248212008Sdelphij		error = bus_setup_intr(sc->bus_dev, sc->irq_res,
249212008Sdelphij					INTR_TYPE_CAM | INTR_MPSAFE,
250212008Sdelphij					NULL, twa_pci_intr,
251212008Sdelphij					sc, &sc->intr_handle);
252212008Sdelphij	}
253212008Sdelphij	return( error );
254212008Sdelphij}
255144966Svkashyap
256212008Sdelphij
257212008Sdelphijint twa_teardown_intr(struct twa_softc *sc)
258212008Sdelphij{
259212008Sdelphij	int error = 0;
260212008Sdelphij
261212008Sdelphij	if ((sc->intr_handle) && (sc->irq_res)) {
262212008Sdelphij		error = bus_teardown_intr(sc->bus_dev,
263212008Sdelphij						sc->irq_res, sc->intr_handle);
264212008Sdelphij		sc->intr_handle = NULL;
265212008Sdelphij	}
266212008Sdelphij	return( error );
267212008Sdelphij}
268212008Sdelphij
269212008Sdelphij
270212008Sdelphij
271144966Svkashyap/*
272144966Svkashyap * Function name:	twa_attach
273144966Svkashyap * Description:		Allocates pci resources; updates sc; adds a node to the
274144966Svkashyap *			sysctl tree to expose the driver version; makes calls
275144966Svkashyap *			(to the Common Layer) to initialize ctlr, and to
276144966Svkashyap *			attach to CAM.
277144966Svkashyap *
278144966Svkashyap * Input:		dev	-- bus device corresponding to the ctlr
279144966Svkashyap * Output:		None
280144966Svkashyap * Return value:	0	-- success
281144966Svkashyap *			non-zero-- failure
282144966Svkashyap */
283144966Svkashyapstatic TW_INT32
284144966Svkashyaptwa_attach(device_t dev)
285144966Svkashyap{
286144966Svkashyap	struct twa_softc	*sc = device_get_softc(dev);
287152213Svkashyap	TW_INT32		bar_num;
288152213Svkashyap	TW_INT32		bar0_offset;
289152213Svkashyap	TW_INT32		bar_size;
290144966Svkashyap	TW_INT32		error;
291144966Svkashyap
292144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
293144966Svkashyap
294144966Svkashyap	sc->ctlr_handle.osl_ctlr_ctxt = sc;
295144966Svkashyap
296144966Svkashyap	/* Initialize the softc structure. */
297144966Svkashyap	sc->bus_dev = dev;
298152213Svkashyap	sc->device_id = pci_get_device(dev);
299144966Svkashyap
300144966Svkashyap	/* Initialize the mutexes right here. */
301144966Svkashyap	sc->io_lock = &(sc->io_lock_handle);
302144966Svkashyap	mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN);
303144966Svkashyap	sc->q_lock = &(sc->q_lock_handle);
304144966Svkashyap	mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN);
305172496Sscottl	sc->sim_lock = &(sc->sim_lock_handle);
306172496Sscottl	mtx_init(sc->sim_lock, "tw_osl_sim_lock", NULL, MTX_DEF | MTX_RECURSE);
307144966Svkashyap
308144966Svkashyap	sysctl_ctx_init(&sc->sysctl_ctxt);
309144966Svkashyap	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt,
310144966Svkashyap		SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
311144966Svkashyap		device_get_nameunit(dev), CTLFLAG_RD, 0, "");
312144966Svkashyap	if (sc->sysctl_tree == NULL) {
313144966Svkashyap		tw_osli_printf(sc, "error = %d",
314144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
315144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
316144966Svkashyap			0x2000,
317144966Svkashyap			"Cannot add sysctl tree node",
318144966Svkashyap			ENXIO);
319144966Svkashyap		return(ENXIO);
320144966Svkashyap	}
321144966Svkashyap	SYSCTL_ADD_STRING(&sc->sysctl_ctxt, SYSCTL_CHILDREN(sc->sysctl_tree),
322144966Svkashyap		OID_AUTO, "driver_version", CTLFLAG_RD,
323144966Svkashyap		TW_OSL_DRIVER_VERSION_STRING, 0, "TWA driver version");
324144966Svkashyap
325144966Svkashyap	/* Force the busmaster enable bit on, in case the BIOS forgot. */
326254306Sscottl	pci_enable_busmaster(dev);
327144966Svkashyap
328144966Svkashyap	/* Allocate the PCI register window. */
329152213Svkashyap	if ((error = tw_cl_get_pci_bar_info(sc->device_id, TW_CL_BAR_TYPE_MEM,
330152213Svkashyap		&bar_num, &bar0_offset, &bar_size))) {
331152213Svkashyap		tw_osli_printf(sc, "error = %d",
332152213Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
333152213Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
334152213Svkashyap			0x201F,
335152213Svkashyap			"Can't get PCI BAR info",
336152213Svkashyap			error);
337152213Svkashyap		tw_osli_free_resources(sc);
338152213Svkashyap		return(error);
339152213Svkashyap	}
340152213Svkashyap	sc->reg_res_id = PCIR_BARS + bar0_offset;
341152213Svkashyap	if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
342144966Svkashyap				&(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
343144966Svkashyap				== NULL) {
344144966Svkashyap		tw_osli_printf(sc, "error = %d",
345144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
346144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
347144966Svkashyap			0x2002,
348144966Svkashyap			"Can't allocate register window",
349144966Svkashyap			ENXIO);
350144966Svkashyap		tw_osli_free_resources(sc);
351144966Svkashyap		return(ENXIO);
352144966Svkashyap	}
353144966Svkashyap	sc->bus_tag = rman_get_bustag(sc->reg_res);
354144966Svkashyap	sc->bus_handle = rman_get_bushandle(sc->reg_res);
355144966Svkashyap
356144966Svkashyap	/* Allocate and register our interrupt. */
357144966Svkashyap	sc->irq_res_id = 0;
358144966Svkashyap	if ((sc->irq_res = bus_alloc_resource(sc->bus_dev, SYS_RES_IRQ,
359144966Svkashyap				&(sc->irq_res_id), 0, ~0, 1,
360144966Svkashyap				RF_SHAREABLE | RF_ACTIVE)) == NULL) {
361144966Svkashyap		tw_osli_printf(sc, "error = %d",
362144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
363144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
364144966Svkashyap			0x2003,
365144966Svkashyap			"Can't allocate interrupt",
366144966Svkashyap			ENXIO);
367144966Svkashyap		tw_osli_free_resources(sc);
368144966Svkashyap		return(ENXIO);
369144966Svkashyap	}
370212008Sdelphij	if ((error = twa_setup_intr(sc))) {
371144966Svkashyap		tw_osli_printf(sc, "error = %d",
372144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
373144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
374144966Svkashyap			0x2004,
375144966Svkashyap			"Can't set up interrupt",
376144966Svkashyap			error);
377144966Svkashyap		tw_osli_free_resources(sc);
378144966Svkashyap		return(error);
379144966Svkashyap	}
380144966Svkashyap
381144966Svkashyap	if ((error = tw_osli_alloc_mem(sc))) {
382144966Svkashyap		tw_osli_printf(sc, "error = %d",
383144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
384144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
385144966Svkashyap			0x2005,
386144966Svkashyap			"Memory allocation failure",
387144966Svkashyap			error);
388144966Svkashyap		tw_osli_free_resources(sc);
389144966Svkashyap		return(error);
390144966Svkashyap	}
391144966Svkashyap
392144966Svkashyap	/* Initialize the Common Layer for this controller. */
393152213Svkashyap	if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags, sc->device_id,
394208969Sdelphij			TW_OSLI_MAX_NUM_REQUESTS, TW_OSLI_MAX_NUM_AENS,
395144966Svkashyap			sc->non_dma_mem, sc->dma_mem,
396144966Svkashyap			sc->dma_mem_phys
397144966Svkashyap			))) {
398144966Svkashyap		tw_osli_printf(sc, "error = %d",
399144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
400144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
401144966Svkashyap			0x2006,
402144966Svkashyap			"Failed to initialize Common Layer/controller",
403144966Svkashyap			error);
404144966Svkashyap		tw_osli_free_resources(sc);
405144966Svkashyap		return(error);
406144966Svkashyap	}
407144966Svkashyap
408144966Svkashyap	/* Create the control device. */
409144966Svkashyap	sc->ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->bus_dev),
410144966Svkashyap			UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
411144966Svkashyap			"twa%d", device_get_unit(sc->bus_dev));
412144966Svkashyap	sc->ctrl_dev->si_drv1 = sc;
413144966Svkashyap
414144966Svkashyap	if ((error = tw_osli_cam_attach(sc))) {
415144966Svkashyap		tw_osli_free_resources(sc);
416144966Svkashyap		tw_osli_printf(sc, "error = %d",
417144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
418144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
419144966Svkashyap			0x2007,
420144966Svkashyap			"Failed to initialize CAM",
421144966Svkashyap			error);
422144966Svkashyap		return(error);
423144966Svkashyap	}
424144966Svkashyap
425212008Sdelphij	sc->watchdog_index = 0;
426212008Sdelphij	callout_init(&(sc->watchdog_callout[0]), CALLOUT_MPSAFE);
427212008Sdelphij	callout_init(&(sc->watchdog_callout[1]), CALLOUT_MPSAFE);
428212008Sdelphij	callout_reset(&(sc->watchdog_callout[0]), 5*hz, twa_watchdog, &sc->ctlr_handle);
429212008Sdelphij
430144966Svkashyap	return(0);
431144966Svkashyap}
432144966Svkashyap
433144966Svkashyap
434212008Sdelphijstatic TW_VOID
435212008Sdelphijtwa_watchdog(TW_VOID *arg)
436212008Sdelphij{
437212008Sdelphij	struct tw_cl_ctlr_handle *ctlr_handle =
438212008Sdelphij		(struct tw_cl_ctlr_handle *)arg;
439212008Sdelphij	struct twa_softc		*sc = ctlr_handle->osl_ctlr_ctxt;
440212008Sdelphij	int				i;
441212008Sdelphij	int				i_need_a_reset = 0;
442212008Sdelphij	int				driver_is_active = 0;
443212008Sdelphij	int				my_watchdog_was_pending = 1234;
444212008Sdelphij	TW_UINT64			current_time;
445212008Sdelphij	struct tw_osli_req_context	*my_req;
446144966Svkashyap
447212008Sdelphij
448212008Sdelphij//==============================================================================
449212008Sdelphij	current_time = (TW_UINT64) (tw_osl_get_local_time());
450212008Sdelphij
451212008Sdelphij	for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
452212008Sdelphij		my_req = &(sc->req_ctx_buf[i]);
453212008Sdelphij
454212008Sdelphij		if ((my_req->state == TW_OSLI_REQ_STATE_BUSY) &&
455212008Sdelphij			(my_req->deadline) &&
456212008Sdelphij			(my_req->deadline < current_time)) {
457212008Sdelphij			tw_cl_set_reset_needed(ctlr_handle);
458212008Sdelphij#ifdef    TW_OSL_DEBUG
459212210Sbz			device_printf((sc)->bus_dev, "Request %d timed out! d = %llu, c = %llu\n", i, my_req->deadline, current_time);
460212008Sdelphij#else  /* TW_OSL_DEBUG */
461212008Sdelphij			device_printf((sc)->bus_dev, "Request %d timed out!\n", i);
462212008Sdelphij#endif /* TW_OSL_DEBUG */
463212008Sdelphij			break;
464212008Sdelphij		}
465212008Sdelphij	}
466212008Sdelphij//==============================================================================
467212008Sdelphij
468212008Sdelphij	i_need_a_reset = tw_cl_is_reset_needed(ctlr_handle);
469212008Sdelphij
470212008Sdelphij	i = (int) ((sc->watchdog_index++) & 1);
471212008Sdelphij
472212008Sdelphij	driver_is_active = tw_cl_is_active(ctlr_handle);
473212008Sdelphij
474212008Sdelphij	if (i_need_a_reset) {
475212008Sdelphij#ifdef    TW_OSL_DEBUG
476212008Sdelphij		device_printf((sc)->bus_dev, "Watchdog rescheduled in 70 seconds\n");
477212008Sdelphij#endif /* TW_OSL_DEBUG */
478212008Sdelphij		my_watchdog_was_pending =
479212008Sdelphij			callout_reset(&(sc->watchdog_callout[i]), 70*hz, twa_watchdog, &sc->ctlr_handle);
480212008Sdelphij		tw_cl_reset_ctlr(ctlr_handle);
481212008Sdelphij#ifdef    TW_OSL_DEBUG
482212008Sdelphij		device_printf((sc)->bus_dev, "Watchdog reset completed!\n");
483212008Sdelphij#endif /* TW_OSL_DEBUG */
484212008Sdelphij	} else if (driver_is_active) {
485212008Sdelphij		my_watchdog_was_pending =
486212008Sdelphij			callout_reset(&(sc->watchdog_callout[i]),  5*hz, twa_watchdog, &sc->ctlr_handle);
487212008Sdelphij	}
488212008Sdelphij#ifdef    TW_OSL_DEBUG
489212008Sdelphij	if (i_need_a_reset || my_watchdog_was_pending)
490212008Sdelphij		device_printf((sc)->bus_dev, "i_need_a_reset = %d, "
491212008Sdelphij		"driver_is_active = %d, my_watchdog_was_pending = %d\n",
492212008Sdelphij		i_need_a_reset, driver_is_active, my_watchdog_was_pending);
493212008Sdelphij#endif /* TW_OSL_DEBUG */
494212008Sdelphij}
495212008Sdelphij
496212008Sdelphij
497144966Svkashyap/*
498144966Svkashyap * Function name:	tw_osli_alloc_mem
499144966Svkashyap * Description:		Allocates memory needed both by CL and OSL.
500144966Svkashyap *
501144966Svkashyap * Input:		sc	-- OSL internal controller context
502144966Svkashyap * Output:		None
503144966Svkashyap * Return value:	0	-- success
504144966Svkashyap *			non-zero-- failure
505144966Svkashyap */
506144966Svkashyapstatic TW_INT32
507144966Svkashyaptw_osli_alloc_mem(struct twa_softc *sc)
508144966Svkashyap{
509144966Svkashyap	struct tw_osli_req_context	*req;
510144966Svkashyap	TW_UINT32			max_sg_elements;
511144966Svkashyap	TW_UINT32			non_dma_mem_size;
512144966Svkashyap	TW_UINT32			dma_mem_size;
513144966Svkashyap	TW_INT32			error;
514144966Svkashyap	TW_INT32			i;
515144966Svkashyap
516144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
517144966Svkashyap
518144966Svkashyap	sc->flags |= (sizeof(bus_addr_t) == 8) ? TW_CL_64BIT_ADDRESSES : 0;
519144966Svkashyap	sc->flags |= (sizeof(bus_size_t) == 8) ? TW_CL_64BIT_SG_LENGTH : 0;
520144966Svkashyap
521144966Svkashyap	max_sg_elements = (sizeof(bus_addr_t) == 8) ?
522144966Svkashyap		TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS;
523144966Svkashyap
524144966Svkashyap	if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags,
525208969Sdelphij			sc->device_id, TW_OSLI_MAX_NUM_REQUESTS,  TW_OSLI_MAX_NUM_AENS,
526144966Svkashyap			&(sc->alignment), &(sc->sg_size_factor),
527144966Svkashyap			&non_dma_mem_size, &dma_mem_size
528144966Svkashyap			))) {
529144966Svkashyap		tw_osli_printf(sc, "error = %d",
530144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
531144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
532144966Svkashyap			0x2008,
533144966Svkashyap			"Can't get Common Layer's memory requirements",
534144966Svkashyap			error);
535144966Svkashyap		return(error);
536144966Svkashyap	}
537144966Svkashyap
538144966Svkashyap	if ((sc->non_dma_mem = malloc(non_dma_mem_size, TW_OSLI_MALLOC_CLASS,
539144966Svkashyap				M_WAITOK)) == NULL) {
540144966Svkashyap		tw_osli_printf(sc, "error = %d",
541144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
542144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
543144966Svkashyap			0x2009,
544144966Svkashyap			"Can't allocate non-dma memory",
545144966Svkashyap			ENOMEM);
546144966Svkashyap		return(ENOMEM);
547144966Svkashyap	}
548144966Svkashyap
549144966Svkashyap	/* Create the parent dma tag. */
550233705Sjhb	if (bus_dma_tag_create(bus_get_dma_tag(sc->bus_dev), /* parent */
551144966Svkashyap				sc->alignment,		/* alignment */
552233705Sjhb				0,			/* boundary */
553190329Sjhb				BUS_SPACE_MAXADDR,	/* lowaddr */
554144966Svkashyap				BUS_SPACE_MAXADDR, 	/* highaddr */
555144966Svkashyap				NULL, NULL, 		/* filter, filterarg */
556144966Svkashyap				TW_CL_MAX_IO_SIZE,	/* maxsize */
557144966Svkashyap				max_sg_elements,	/* nsegments */
558144966Svkashyap				TW_CL_MAX_IO_SIZE,	/* maxsegsize */
559144966Svkashyap				0,			/* flags */
560144966Svkashyap				NULL,			/* lockfunc */
561144966Svkashyap				NULL,			/* lockfuncarg */
562144966Svkashyap				&sc->parent_tag		/* tag */)) {
563144966Svkashyap		tw_osli_printf(sc, "error = %d",
564144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
565144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
566144966Svkashyap			0x200A,
567144966Svkashyap			"Can't allocate parent DMA tag",
568144966Svkashyap			ENOMEM);
569144966Svkashyap		return(ENOMEM);
570144966Svkashyap	}
571144966Svkashyap
572144966Svkashyap	/* Create a dma tag for Common Layer's DMA'able memory (dma_mem). */
573144966Svkashyap	if (bus_dma_tag_create(sc->parent_tag,		/* parent */
574144966Svkashyap				sc->alignment,		/* alignment */
575144966Svkashyap				0,			/* boundary */
576190329Sjhb				BUS_SPACE_MAXADDR,	/* lowaddr */
577144966Svkashyap				BUS_SPACE_MAXADDR, 	/* highaddr */
578144966Svkashyap				NULL, NULL, 		/* filter, filterarg */
579144966Svkashyap				dma_mem_size,		/* maxsize */
580144966Svkashyap				1,			/* nsegments */
581144966Svkashyap				BUS_SPACE_MAXSIZE,	/* maxsegsize */
582144966Svkashyap				0,			/* flags */
583144966Svkashyap				NULL,			/* lockfunc */
584144966Svkashyap				NULL,			/* lockfuncarg */
585144966Svkashyap				&sc->cmd_tag		/* tag */)) {
586144966Svkashyap		tw_osli_printf(sc, "error = %d",
587144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
588144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
589144966Svkashyap			0x200B,
590144966Svkashyap			"Can't allocate DMA tag for Common Layer's "
591144966Svkashyap			"DMA'able memory",
592144966Svkashyap			ENOMEM);
593144966Svkashyap		return(ENOMEM);
594144966Svkashyap	}
595144966Svkashyap
596144966Svkashyap	if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
597144966Svkashyap		BUS_DMA_NOWAIT, &sc->cmd_map)) {
598144966Svkashyap		/* Try a second time. */
599144966Svkashyap		if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
600144966Svkashyap			BUS_DMA_NOWAIT, &sc->cmd_map)) {
601144966Svkashyap			tw_osli_printf(sc, "error = %d",
602144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
603144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
604144966Svkashyap				0x200C,
605144966Svkashyap				"Can't allocate DMA'able memory for the"
606144966Svkashyap				"Common Layer",
607144966Svkashyap				ENOMEM);
608144966Svkashyap			return(ENOMEM);
609144966Svkashyap		}
610144966Svkashyap	}
611144966Svkashyap
612144966Svkashyap	bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem,
613144966Svkashyap		dma_mem_size, twa_map_load_callback,
614144966Svkashyap		&sc->dma_mem_phys, 0);
615144966Svkashyap
616144966Svkashyap	/*
617144966Svkashyap	 * Create a dma tag for data buffers; size will be the maximum
618144966Svkashyap	 * possible I/O size (128kB).
619144966Svkashyap	 */
620144966Svkashyap	if (bus_dma_tag_create(sc->parent_tag,		/* parent */
621144966Svkashyap				sc->alignment,		/* alignment */
622144966Svkashyap				0,			/* boundary */
623190329Sjhb				BUS_SPACE_MAXADDR,	/* lowaddr */
624144966Svkashyap				BUS_SPACE_MAXADDR, 	/* highaddr */
625144966Svkashyap				NULL, NULL, 		/* filter, filterarg */
626144966Svkashyap				TW_CL_MAX_IO_SIZE,	/* maxsize */
627144966Svkashyap				max_sg_elements,	/* nsegments */
628144966Svkashyap				TW_CL_MAX_IO_SIZE,	/* maxsegsize */
629144966Svkashyap				BUS_DMA_ALLOCNOW,	/* flags */
630144966Svkashyap				twa_busdma_lock,	/* lockfunc */
631144966Svkashyap				sc->io_lock,		/* lockfuncarg */
632144966Svkashyap				&sc->dma_tag		/* tag */)) {
633144966Svkashyap		tw_osli_printf(sc, "error = %d",
634144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
635144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
636144966Svkashyap			0x200F,
637144966Svkashyap			"Can't allocate DMA tag for data buffers",
638144966Svkashyap			ENOMEM);
639144966Svkashyap		return(ENOMEM);
640144966Svkashyap	}
641144966Svkashyap
642144966Svkashyap	/*
643144966Svkashyap	 * Create a dma tag for ioctl data buffers; size will be the maximum
644144966Svkashyap	 * possible I/O size (128kB).
645144966Svkashyap	 */
646144966Svkashyap	if (bus_dma_tag_create(sc->parent_tag,		/* parent */
647144966Svkashyap				sc->alignment,		/* alignment */
648144966Svkashyap				0,			/* boundary */
649190329Sjhb				BUS_SPACE_MAXADDR,	/* lowaddr */
650144966Svkashyap				BUS_SPACE_MAXADDR, 	/* highaddr */
651144966Svkashyap				NULL, NULL, 		/* filter, filterarg */
652144966Svkashyap				TW_CL_MAX_IO_SIZE,	/* maxsize */
653144966Svkashyap				max_sg_elements,	/* nsegments */
654144966Svkashyap				TW_CL_MAX_IO_SIZE,	/* maxsegsize */
655144966Svkashyap				BUS_DMA_ALLOCNOW,	/* flags */
656144966Svkashyap				twa_busdma_lock,	/* lockfunc */
657144966Svkashyap				sc->io_lock,		/* lockfuncarg */
658144966Svkashyap				&sc->ioctl_tag		/* tag */)) {
659144966Svkashyap		tw_osli_printf(sc, "error = %d",
660144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
661144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
662144966Svkashyap			0x2010,
663144966Svkashyap			"Can't allocate DMA tag for ioctl data buffers",
664144966Svkashyap			ENOMEM);
665144966Svkashyap		return(ENOMEM);
666144966Svkashyap	}
667144966Svkashyap
668144966Svkashyap	/* Create just one map for all ioctl request data buffers. */
669144966Svkashyap	if (bus_dmamap_create(sc->ioctl_tag, 0, &sc->ioctl_map)) {
670144966Svkashyap		tw_osli_printf(sc, "error = %d",
671144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
672144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
673144966Svkashyap			0x2011,
674144966Svkashyap			"Can't create ioctl map",
675144966Svkashyap			ENOMEM);
676144966Svkashyap		return(ENOMEM);
677144966Svkashyap	}
678144966Svkashyap
679144966Svkashyap
680144966Svkashyap	/* Initialize request queues. */
681144966Svkashyap	tw_osli_req_q_init(sc, TW_OSLI_FREE_Q);
682144966Svkashyap	tw_osli_req_q_init(sc, TW_OSLI_BUSY_Q);
683144966Svkashyap
684208969Sdelphij	if ((sc->req_ctx_buf = (struct tw_osli_req_context *)
685144966Svkashyap			malloc((sizeof(struct tw_osli_req_context) *
686208969Sdelphij				TW_OSLI_MAX_NUM_REQUESTS),
687144966Svkashyap				TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
688144966Svkashyap		tw_osli_printf(sc, "error = %d",
689144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
690144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
691144966Svkashyap			0x2012,
692144966Svkashyap			"Failed to allocate request packets",
693144966Svkashyap			ENOMEM);
694144966Svkashyap		return(ENOMEM);
695144966Svkashyap	}
696208969Sdelphij	bzero(sc->req_ctx_buf,
697208969Sdelphij		sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_REQUESTS);
698144966Svkashyap
699208969Sdelphij	for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
700208969Sdelphij		req = &(sc->req_ctx_buf[i]);
701144966Svkashyap		req->ctlr = sc;
702144966Svkashyap		if (bus_dmamap_create(sc->dma_tag, 0, &req->dma_map)) {
703144966Svkashyap			tw_osli_printf(sc, "request # = %d, error = %d",
704144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
705144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
706144966Svkashyap				0x2013,
707144966Svkashyap				"Can't create dma map",
708144966Svkashyap				i, ENOMEM);
709144966Svkashyap			return(ENOMEM);
710144966Svkashyap		}
711144966Svkashyap
712208969Sdelphij		/* Initialize the ioctl wakeup/ timeout mutex */
713208969Sdelphij		req->ioctl_wake_timeout_lock = &(req->ioctl_wake_timeout_lock_handle);
714208969Sdelphij		mtx_init(req->ioctl_wake_timeout_lock, "tw_ioctl_wake_timeout_lock", NULL, MTX_DEF);
715208969Sdelphij
716144966Svkashyap		/* Insert request into the free queue. */
717144966Svkashyap		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
718144966Svkashyap	}
719144966Svkashyap
720144966Svkashyap	return(0);
721144966Svkashyap}
722144966Svkashyap
723144966Svkashyap
724144966Svkashyap
725144966Svkashyap/*
726144966Svkashyap * Function name:	tw_osli_free_resources
727144966Svkashyap * Description:		Performs clean-up at the time of going down.
728144966Svkashyap *
729144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
730144966Svkashyap * Output:		None
731144966Svkashyap * Return value:	None
732144966Svkashyap */
733144966Svkashyapstatic TW_VOID
734144966Svkashyaptw_osli_free_resources(struct twa_softc *sc)
735144966Svkashyap{
736144966Svkashyap	struct tw_osli_req_context	*req;
737144966Svkashyap	TW_INT32			error = 0;
738144966Svkashyap
739144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
740144966Svkashyap
741144966Svkashyap	/* Detach from CAM */
742144966Svkashyap	tw_osli_cam_detach(sc);
743144966Svkashyap
744208969Sdelphij	if (sc->req_ctx_buf)
745144966Svkashyap		while ((req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q)) !=
746208969Sdelphij			NULL) {
747208969Sdelphij			mtx_destroy(req->ioctl_wake_timeout_lock);
748208969Sdelphij
749144966Svkashyap			if ((error = bus_dmamap_destroy(sc->dma_tag,
750144966Svkashyap					req->dma_map)))
751144966Svkashyap				tw_osli_dbg_dprintf(1, sc,
752144966Svkashyap					"dmamap_destroy(dma) returned %d",
753144966Svkashyap					error);
754208969Sdelphij		}
755144966Svkashyap
756152213Svkashyap	if ((sc->ioctl_tag) && (sc->ioctl_map))
757152213Svkashyap		if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map)))
758152213Svkashyap			tw_osli_dbg_dprintf(1, sc,
759152213Svkashyap				"dmamap_destroy(ioctl) returned %d", error);
760144966Svkashyap
761144966Svkashyap	/* Free all memory allocated so far. */
762208969Sdelphij	if (sc->req_ctx_buf)
763208969Sdelphij		free(sc->req_ctx_buf, TW_OSLI_MALLOC_CLASS);
764144966Svkashyap
765144966Svkashyap	if (sc->non_dma_mem)
766144966Svkashyap		free(sc->non_dma_mem, TW_OSLI_MALLOC_CLASS);
767144966Svkashyap
768144966Svkashyap	if (sc->dma_mem) {
769144966Svkashyap		bus_dmamap_unload(sc->cmd_tag, sc->cmd_map);
770144966Svkashyap		bus_dmamem_free(sc->cmd_tag, sc->dma_mem,
771144966Svkashyap			sc->cmd_map);
772144966Svkashyap	}
773144966Svkashyap	if (sc->cmd_tag)
774144966Svkashyap		if ((error = bus_dma_tag_destroy(sc->cmd_tag)))
775144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
776144966Svkashyap				"dma_tag_destroy(cmd) returned %d", error);
777144966Svkashyap
778144966Svkashyap	if (sc->dma_tag)
779144966Svkashyap		if ((error = bus_dma_tag_destroy(sc->dma_tag)))
780144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
781144966Svkashyap				"dma_tag_destroy(dma) returned %d", error);
782144966Svkashyap
783144966Svkashyap	if (sc->ioctl_tag)
784144966Svkashyap		if ((error = bus_dma_tag_destroy(sc->ioctl_tag)))
785144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
786144966Svkashyap				"dma_tag_destroy(ioctl) returned %d", error);
787144966Svkashyap
788144966Svkashyap	if (sc->parent_tag)
789144966Svkashyap		if ((error = bus_dma_tag_destroy(sc->parent_tag)))
790144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
791144966Svkashyap				"dma_tag_destroy(parent) returned %d", error);
792144966Svkashyap
793144966Svkashyap
794144966Svkashyap	/* Disconnect the interrupt handler. */
795212008Sdelphij	if ((error = twa_teardown_intr(sc)))
796144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
797144966Svkashyap				"teardown_intr returned %d", error);
798144966Svkashyap
799144966Svkashyap	if (sc->irq_res != NULL)
800144966Svkashyap		if ((error = bus_release_resource(sc->bus_dev,
801144966Svkashyap				SYS_RES_IRQ, sc->irq_res_id, sc->irq_res)))
802144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
803144966Svkashyap				"release_resource(irq) returned %d", error);
804144966Svkashyap
805144966Svkashyap
806144966Svkashyap	/* Release the register window mapping. */
807144966Svkashyap	if (sc->reg_res != NULL)
808144966Svkashyap		if ((error = bus_release_resource(sc->bus_dev,
809152213Svkashyap				SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)))
810144966Svkashyap			tw_osli_dbg_dprintf(1, sc,
811144966Svkashyap				"release_resource(io) returned %d", error);
812144966Svkashyap
813144966Svkashyap
814144966Svkashyap	/* Destroy the control device. */
815144966Svkashyap	if (sc->ctrl_dev != (struct cdev *)NULL)
816144966Svkashyap		destroy_dev(sc->ctrl_dev);
817144966Svkashyap
818144966Svkashyap	if ((error = sysctl_ctx_free(&sc->sysctl_ctxt)))
819144966Svkashyap		tw_osli_dbg_dprintf(1, sc,
820144966Svkashyap			"sysctl_ctx_free returned %d", error);
821144966Svkashyap
822144966Svkashyap}
823144966Svkashyap
824144966Svkashyap
825144966Svkashyap
826144966Svkashyap/*
827144966Svkashyap * Function name:	twa_detach
828144966Svkashyap * Description:		Called when the controller is being detached from
829144966Svkashyap *			the pci bus.
830144966Svkashyap *
831144966Svkashyap * Input:		dev	-- bus device corresponding to the ctlr
832144966Svkashyap * Output:		None
833144966Svkashyap * Return value:	0	-- success
834144966Svkashyap *			non-zero-- failure
835144966Svkashyap */
836144966Svkashyapstatic TW_INT32
837144966Svkashyaptwa_detach(device_t dev)
838144966Svkashyap{
839144966Svkashyap	struct twa_softc	*sc = device_get_softc(dev);
840144966Svkashyap	TW_INT32		error;
841144966Svkashyap
842144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
843144966Svkashyap
844144966Svkashyap	error = EBUSY;
845208969Sdelphij	if (sc->open) {
846144966Svkashyap		tw_osli_printf(sc, "error = %d",
847144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
848144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
849144966Svkashyap			0x2014,
850144966Svkashyap			"Device open",
851144966Svkashyap			error);
852144966Svkashyap		goto out;
853144966Svkashyap	}
854144966Svkashyap
855144966Svkashyap	/* Shut the controller down. */
856144966Svkashyap	if ((error = twa_shutdown(dev)))
857144966Svkashyap		goto out;
858144966Svkashyap
859144966Svkashyap	/* Free all resources associated with this controller. */
860144966Svkashyap	tw_osli_free_resources(sc);
861144966Svkashyap	error = 0;
862144966Svkashyap
863144966Svkashyapout:
864144966Svkashyap	return(error);
865144966Svkashyap}
866144966Svkashyap
867144966Svkashyap
868144966Svkashyap
869144966Svkashyap/*
870144966Svkashyap * Function name:	twa_shutdown
871144966Svkashyap * Description:		Called at unload/shutdown time.  Lets the controller
872144966Svkashyap *			know that we are going down.
873144966Svkashyap *
874144966Svkashyap * Input:		dev	-- bus device corresponding to the ctlr
875144966Svkashyap * Output:		None
876144966Svkashyap * Return value:	0	-- success
877144966Svkashyap *			non-zero-- failure
878144966Svkashyap */
879144966Svkashyapstatic TW_INT32
880144966Svkashyaptwa_shutdown(device_t dev)
881144966Svkashyap{
882144966Svkashyap	struct twa_softc	*sc = device_get_softc(dev);
883144966Svkashyap	TW_INT32		error = 0;
884144966Svkashyap
885144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
886144966Svkashyap
887212008Sdelphij	/* Disconnect interrupts. */
888212008Sdelphij	error = twa_teardown_intr(sc);
889212008Sdelphij
890212028Sdelphij	/* Stop watchdog task. */
891212028Sdelphij	callout_drain(&(sc->watchdog_callout[0]));
892212028Sdelphij	callout_drain(&(sc->watchdog_callout[1]));
893212028Sdelphij
894144966Svkashyap	/* Disconnect from the controller. */
895144966Svkashyap	if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) {
896144966Svkashyap		tw_osli_printf(sc, "error = %d",
897144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
898144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
899144966Svkashyap			0x2015,
900144966Svkashyap			"Failed to shutdown Common Layer/controller",
901144966Svkashyap			error);
902144966Svkashyap	}
903144966Svkashyap	return(error);
904144966Svkashyap}
905144966Svkashyap
906144966Svkashyap
907144966Svkashyap
908144966Svkashyap/*
909144966Svkashyap * Function name:	twa_busdma_lock
910144966Svkashyap * Description:		Function to provide synchronization during busdma_swi.
911144966Svkashyap *
912144966Svkashyap * Input:		lock_arg -- lock mutex sent as argument
913144966Svkashyap *			op -- operation (lock/unlock) expected of the function
914144966Svkashyap * Output:		None
915144966Svkashyap * Return value:	None
916144966Svkashyap */
917144966SvkashyapTW_VOID
918144966Svkashyaptwa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op)
919144966Svkashyap{
920144966Svkashyap	struct mtx	*lock;
921144966Svkashyap
922144966Svkashyap	lock = (struct mtx *)lock_arg;
923144966Svkashyap	switch (op) {
924144966Svkashyap	case BUS_DMA_LOCK:
925144966Svkashyap		mtx_lock_spin(lock);
926144966Svkashyap		break;
927144966Svkashyap
928144966Svkashyap	case BUS_DMA_UNLOCK:
929144966Svkashyap		mtx_unlock_spin(lock);
930144966Svkashyap		break;
931144966Svkashyap
932144966Svkashyap	default:
933144966Svkashyap		panic("Unknown operation 0x%x for twa_busdma_lock!", op);
934144966Svkashyap	}
935144966Svkashyap}
936144966Svkashyap
937144966Svkashyap
938166901Spiso/*
939144966Svkashyap * Function name:	twa_pci_intr
940144966Svkashyap * Description:		Interrupt handler.  Wrapper for twa_interrupt.
941144966Svkashyap *
942144966Svkashyap * Input:		arg	-- ptr to OSL internal ctlr context
943144966Svkashyap * Output:		None
944144966Svkashyap * Return value:	None
945144966Svkashyap */
946144966Svkashyapstatic TW_VOID
947144966Svkashyaptwa_pci_intr(TW_VOID *arg)
948144966Svkashyap{
949144966Svkashyap	struct twa_softc	*sc = (struct twa_softc *)arg;
950144966Svkashyap
951144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entered");
952208969Sdelphij	tw_cl_interrupt(&(sc->ctlr_handle));
953144966Svkashyap}
954144966Svkashyap
955152213Svkashyap
956144966Svkashyap/*
957144966Svkashyap * Function name:	tw_osli_fw_passthru
958144966Svkashyap * Description:		Builds a fw passthru cmd pkt, and submits it to CL.
959144966Svkashyap *
960144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
961144966Svkashyap *			buf	-- ptr to ioctl pkt understood by CL
962144966Svkashyap * Output:		None
963144966Svkashyap * Return value:	0	-- success
964144966Svkashyap *			non-zero-- failure
965144966Svkashyap */
966144966SvkashyapTW_INT32
967144966Svkashyaptw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf)
968144966Svkashyap{
969144966Svkashyap	struct tw_osli_req_context		*req;
970144966Svkashyap	struct tw_osli_ioctl_no_data_buf	*user_buf =
971144966Svkashyap		(struct tw_osli_ioctl_no_data_buf *)buf;
972144966Svkashyap	TW_TIME					end_time;
973144966Svkashyap	TW_UINT32				timeout = 60;
974144966Svkashyap	TW_UINT32				data_buf_size_adjusted;
975144966Svkashyap	struct tw_cl_req_packet			*req_pkt;
976144966Svkashyap	struct tw_cl_passthru_req_packet	*pt_req;
977144966Svkashyap	TW_INT32				error;
978144966Svkashyap
979144966Svkashyap	tw_osli_dbg_dprintf(5, sc, "ioctl: passthru");
980144966Svkashyap
981144966Svkashyap	if ((req = tw_osli_get_request(sc)) == NULL)
982144966Svkashyap		return(EBUSY);
983144966Svkashyap
984144966Svkashyap	req->req_handle.osl_req_ctxt = req;
985144966Svkashyap	req->orig_req = buf;
986144966Svkashyap	req->flags |= TW_OSLI_REQ_FLAGS_PASSTHRU;
987144966Svkashyap
988144966Svkashyap	req_pkt = &(req->req_pkt);
989144966Svkashyap	req_pkt->status = 0;
990144966Svkashyap	req_pkt->tw_osl_callback = tw_osl_complete_passthru;
991144966Svkashyap	/* Let the Common Layer retry the request on cmd queue full. */
992144966Svkashyap	req_pkt->flags |= TW_CL_REQ_RETRY_ON_BUSY;
993144966Svkashyap
994144966Svkashyap	pt_req = &(req_pkt->gen_req_pkt.pt_req);
995144966Svkashyap	/*
996144966Svkashyap	 * Make sure that the data buffer sent to firmware is a
997144966Svkashyap	 * 512 byte multiple in size.
998144966Svkashyap	 */
999144966Svkashyap	data_buf_size_adjusted =
1000144966Svkashyap		(user_buf->driver_pkt.buffer_length +
1001144966Svkashyap		(sc->sg_size_factor - 1)) & ~(sc->sg_size_factor - 1);
1002144966Svkashyap	if ((req->length = data_buf_size_adjusted)) {
1003144966Svkashyap		if ((req->data = malloc(data_buf_size_adjusted,
1004144966Svkashyap			TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) {
1005144966Svkashyap			error = ENOMEM;
1006144966Svkashyap			tw_osli_printf(sc, "error = %d",
1007144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
1008144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1009144966Svkashyap				0x2016,
1010144966Svkashyap				"Could not alloc mem for "
1011144966Svkashyap				"fw_passthru data_buf",
1012144966Svkashyap				error);
1013144966Svkashyap			goto fw_passthru_err;
1014144966Svkashyap		}
1015144966Svkashyap		/* Copy the payload. */
1016144966Svkashyap		if ((error = copyin((TW_VOID *)(user_buf->pdata),
1017144966Svkashyap			req->data,
1018144966Svkashyap			user_buf->driver_pkt.buffer_length)) != 0) {
1019144966Svkashyap			tw_osli_printf(sc, "error = %d",
1020144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
1021144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1022144966Svkashyap				0x2017,
1023144966Svkashyap				"Could not copyin fw_passthru data_buf",
1024144966Svkashyap				error);
1025144966Svkashyap			goto fw_passthru_err;
1026144966Svkashyap		}
1027144966Svkashyap		pt_req->sgl_entries = 1; /* will be updated during mapping */
1028144966Svkashyap		req->flags |= (TW_OSLI_REQ_FLAGS_DATA_IN |
1029144966Svkashyap			TW_OSLI_REQ_FLAGS_DATA_OUT);
1030144966Svkashyap	} else
1031144966Svkashyap		pt_req->sgl_entries = 0; /* no payload */
1032144966Svkashyap
1033144966Svkashyap	pt_req->cmd_pkt = (TW_VOID *)(&(user_buf->cmd_pkt));
1034144966Svkashyap	pt_req->cmd_pkt_length = sizeof(struct tw_cl_command_packet);
1035144966Svkashyap
1036144966Svkashyap	if ((error = tw_osli_map_request(req)))
1037144966Svkashyap		goto fw_passthru_err;
1038144966Svkashyap
1039144966Svkashyap	end_time = tw_osl_get_local_time() + timeout;
1040144966Svkashyap	while (req->state != TW_OSLI_REQ_STATE_COMPLETE) {
1041208969Sdelphij		mtx_lock(req->ioctl_wake_timeout_lock);
1042144966Svkashyap		req->flags |= TW_OSLI_REQ_FLAGS_SLEEPING;
1043144966Svkashyap
1044208969Sdelphij		error = mtx_sleep(req, req->ioctl_wake_timeout_lock, 0,
1045208969Sdelphij			    "twa_passthru", timeout*hz);
1046208969Sdelphij		mtx_unlock(req->ioctl_wake_timeout_lock);
1047208969Sdelphij
1048144966Svkashyap		if (!(req->flags & TW_OSLI_REQ_FLAGS_SLEEPING))
1049144966Svkashyap			error = 0;
1050144966Svkashyap		req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING;
1051144966Svkashyap
1052144966Svkashyap		if (! error) {
1053144966Svkashyap			if (((error = req->error_code)) ||
1054144966Svkashyap				((error = (req->state !=
1055144966Svkashyap				TW_OSLI_REQ_STATE_COMPLETE))) ||
1056144966Svkashyap				((error = req_pkt->status)))
1057144966Svkashyap				goto fw_passthru_err;
1058144966Svkashyap			break;
1059144966Svkashyap		}
1060144966Svkashyap
1061144966Svkashyap		if (req_pkt->status) {
1062144966Svkashyap			error = req_pkt->status;
1063144966Svkashyap			goto fw_passthru_err;
1064144966Svkashyap		}
1065144966Svkashyap
1066144966Svkashyap		if (error == EWOULDBLOCK) {
1067144966Svkashyap			/* Time out! */
1068208969Sdelphij			if ((!(req->error_code))                       &&
1069208969Sdelphij			    (req->state == TW_OSLI_REQ_STATE_COMPLETE) &&
1070208969Sdelphij			    (!(req_pkt->status))			  ) {
1071208969Sdelphij#ifdef    TW_OSL_DEBUG
1072208969Sdelphij				tw_osli_printf(sc, "request = %p",
1073208969Sdelphij					TW_CL_SEVERITY_ERROR_STRING,
1074208969Sdelphij					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1075208969Sdelphij					0x7777,
1076208969Sdelphij					"FALSE Passthru timeout!",
1077208969Sdelphij					req);
1078208969Sdelphij#endif /* TW_OSL_DEBUG */
1079208969Sdelphij				error = 0; /* False error */
1080208969Sdelphij				break;
1081208969Sdelphij			}
1082212008Sdelphij			if (!(tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
1083212008Sdelphij#ifdef    TW_OSL_DEBUG
1084212008Sdelphij				tw_osli_printf(sc, "request = %p",
1085212008Sdelphij					TW_CL_SEVERITY_ERROR_STRING,
1086212008Sdelphij					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1087212008Sdelphij					0x2018,
1088212008Sdelphij					"Passthru request timed out!",
1089212008Sdelphij					req);
1090212008Sdelphij#else  /* TW_OSL_DEBUG */
1091212008Sdelphij			device_printf((sc)->bus_dev, "Passthru request timed out!\n");
1092212008Sdelphij#endif /* TW_OSL_DEBUG */
1093212008Sdelphij				tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
1094212008Sdelphij			}
1095212008Sdelphij
1096212008Sdelphij			error = 0;
1097212008Sdelphij			end_time = tw_osl_get_local_time() + timeout;
1098212008Sdelphij			continue;
1099144966Svkashyap			/*
1100144966Svkashyap			 * Don't touch req after a reset.  It (and any
1101212008Sdelphij			 * associated data) will be
1102172496Sscottl			 * unmapped by the callback.
1103144966Svkashyap			 */
1104144966Svkashyap		}
1105144966Svkashyap		/*
1106144966Svkashyap		 * Either the request got completed, or we were woken up by a
1107144966Svkashyap		 * signal.  Calculate the new timeout, in case it was the latter.
1108144966Svkashyap		 */
1109144966Svkashyap		timeout = (end_time - tw_osl_get_local_time());
1110212008Sdelphij	} /* End of while loop */
1111144966Svkashyap
1112144966Svkashyap	/* If there was a payload, copy it back. */
1113144966Svkashyap	if ((!error) && (req->length))
1114144966Svkashyap		if ((error = copyout(req->data, user_buf->pdata,
1115144966Svkashyap			user_buf->driver_pkt.buffer_length)))
1116144966Svkashyap			tw_osli_printf(sc, "error = %d",
1117144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
1118144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1119144966Svkashyap				0x2019,
1120144966Svkashyap				"Could not copyout fw_passthru data_buf",
1121144966Svkashyap				error);
1122144966Svkashyap
1123144966Svkashyapfw_passthru_err:
1124144966Svkashyap
1125212008Sdelphij	if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET)
1126212008Sdelphij		error = EBUSY;
1127212008Sdelphij
1128144966Svkashyap	user_buf->driver_pkt.os_status = error;
1129144966Svkashyap	/* Free resources. */
1130144966Svkashyap	if (req->data)
1131144966Svkashyap		free(req->data, TW_OSLI_MALLOC_CLASS);
1132144966Svkashyap	tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
1133144966Svkashyap	return(error);
1134144966Svkashyap}
1135144966Svkashyap
1136144966Svkashyap
1137144966Svkashyap
1138144966Svkashyap/*
1139144966Svkashyap * Function name:	tw_osl_complete_passthru
1140144966Svkashyap * Description:		Called to complete passthru requests.
1141144966Svkashyap *
1142144966Svkashyap * Input:		req_handle	-- ptr to request handle
1143144966Svkashyap * Output:		None
1144144966Svkashyap * Return value:	None
1145144966Svkashyap */
1146144966SvkashyapTW_VOID
1147144966Svkashyaptw_osl_complete_passthru(struct tw_cl_req_handle *req_handle)
1148144966Svkashyap{
1149144966Svkashyap	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
1150212008Sdelphij	struct tw_cl_req_packet		*req_pkt =
1151212008Sdelphij		(struct tw_cl_req_packet *)(&req->req_pkt);
1152144966Svkashyap	struct twa_softc		*sc = req->ctlr;
1153144966Svkashyap
1154144966Svkashyap	tw_osli_dbg_dprintf(5, sc, "entered");
1155144966Svkashyap
1156144966Svkashyap	if (req->state != TW_OSLI_REQ_STATE_BUSY) {
1157144966Svkashyap		tw_osli_printf(sc, "request = %p, status = %d",
1158144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
1159144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1160144966Svkashyap			0x201B,
1161144966Svkashyap			"Unposted command completed!!",
1162144966Svkashyap			req, req->state);
1163144966Svkashyap	}
1164144966Svkashyap
1165144966Svkashyap	/*
1166144966Svkashyap	 * Remove request from the busy queue.  Just mark it complete.
1167144966Svkashyap	 * There's no need to move it into the complete queue as we are
1168144966Svkashyap	 * going to be done with it right now.
1169144966Svkashyap	 */
1170144966Svkashyap	req->state = TW_OSLI_REQ_STATE_COMPLETE;
1171144966Svkashyap	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
1172144966Svkashyap
1173144966Svkashyap	tw_osli_unmap_request(req);
1174144966Svkashyap
1175144966Svkashyap	/*
1176144966Svkashyap	 * Don't do a wake up if there was an error even before the request
1177144966Svkashyap	 * was sent down to the Common Layer, and we hadn't gotten an
1178144966Svkashyap	 * EINPROGRESS.  The request originator will then be returned an
1179144966Svkashyap	 * error, and he can do the clean-up.
1180144966Svkashyap	 */
1181208969Sdelphij	if ((req->error_code) && (!(req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS)))
1182144966Svkashyap		return;
1183144966Svkashyap
1184144966Svkashyap	if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1185144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_SLEEPING) {
1186144966Svkashyap			/* Wake up the sleeping command originator. */
1187144966Svkashyap			tw_osli_dbg_dprintf(5, sc,
1188144966Svkashyap				"Waking up originator of request %p", req);
1189144966Svkashyap			req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING;
1190144966Svkashyap			wakeup_one(req);
1191144966Svkashyap		} else {
1192144966Svkashyap			/*
1193208969Sdelphij			 * If the request completed even before mtx_sleep
1194144966Svkashyap			 * was called, simply return.
1195144966Svkashyap			 */
1196144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_MAPPED)
1197144966Svkashyap				return;
1198144966Svkashyap
1199212008Sdelphij			if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET)
1200212008Sdelphij				return;
1201212008Sdelphij
1202144966Svkashyap			tw_osli_printf(sc, "request = %p",
1203144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
1204144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1205144966Svkashyap				0x201C,
1206144966Svkashyap				"Passthru callback called, "
1207144966Svkashyap				"and caller not sleeping",
1208144966Svkashyap				req);
1209144966Svkashyap		}
1210144966Svkashyap	} else {
1211144966Svkashyap		tw_osli_printf(sc, "request = %p",
1212144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
1213144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1214144966Svkashyap			0x201D,
1215144966Svkashyap			"Passthru callback called for non-passthru request",
1216144966Svkashyap			req);
1217144966Svkashyap	}
1218144966Svkashyap}
1219144966Svkashyap
1220144966Svkashyap
1221144966Svkashyap
1222144966Svkashyap/*
1223144966Svkashyap * Function name:	tw_osli_get_request
1224144966Svkashyap * Description:		Gets a request pkt from the free queue.
1225144966Svkashyap *
1226144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
1227144966Svkashyap * Output:		None
1228144966Svkashyap * Return value:	ptr to request pkt	-- success
1229144966Svkashyap *			NULL			-- failure
1230144966Svkashyap */
1231144966Svkashyapstruct tw_osli_req_context *
1232144966Svkashyaptw_osli_get_request(struct twa_softc *sc)
1233144966Svkashyap{
1234144966Svkashyap	struct tw_osli_req_context	*req;
1235144966Svkashyap
1236144966Svkashyap	tw_osli_dbg_dprintf(4, sc, "entered");
1237144966Svkashyap
1238144966Svkashyap	/* Get a free request packet. */
1239144966Svkashyap	req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q);
1240144966Svkashyap
1241144966Svkashyap	/* Initialize some fields to their defaults. */
1242144966Svkashyap	if (req) {
1243144966Svkashyap		req->req_handle.osl_req_ctxt = NULL;
1244144966Svkashyap		req->req_handle.cl_req_ctxt = NULL;
1245208969Sdelphij		req->req_handle.is_io = 0;
1246144966Svkashyap		req->data = NULL;
1247144966Svkashyap		req->length = 0;
1248212008Sdelphij		req->deadline = 0;
1249144966Svkashyap		req->real_data = NULL;
1250144966Svkashyap		req->real_length = 0;
1251144966Svkashyap		req->state = TW_OSLI_REQ_STATE_INIT;/* req being initialized */
1252144966Svkashyap		req->flags = 0;
1253144966Svkashyap		req->error_code = 0;
1254144966Svkashyap		req->orig_req = NULL;
1255144966Svkashyap
1256144966Svkashyap		bzero(&(req->req_pkt), sizeof(struct tw_cl_req_packet));
1257144966Svkashyap
1258144966Svkashyap	}
1259144966Svkashyap	return(req);
1260144966Svkashyap}
1261144966Svkashyap
1262144966Svkashyap
1263144966Svkashyap
1264144966Svkashyap/*
1265144966Svkashyap * Function name:	twa_map_load_data_callback
1266144966Svkashyap * Description:		Callback of bus_dmamap_load for the buffer associated
1267144966Svkashyap *			with data.  Updates the cmd pkt (size/sgl_entries
1268144966Svkashyap *			fields, as applicable) to reflect the number of sg
1269144966Svkashyap *			elements.
1270144966Svkashyap *
1271144966Svkashyap * Input:		arg	-- ptr to OSL internal request context
1272144966Svkashyap *			segs	-- ptr to a list of segment descriptors
1273144966Svkashyap *			nsegments--# of segments
1274144966Svkashyap *			error	-- 0 if no errors encountered before callback,
1275144966Svkashyap *				   non-zero if errors were encountered
1276144966Svkashyap * Output:		None
1277144966Svkashyap * Return value:	None
1278144966Svkashyap */
1279144966Svkashyapstatic TW_VOID
1280144966Svkashyaptwa_map_load_data_callback(TW_VOID *arg, bus_dma_segment_t *segs,
1281144966Svkashyap	TW_INT32 nsegments, TW_INT32 error)
1282144966Svkashyap{
1283144966Svkashyap	struct tw_osli_req_context	*req =
1284144966Svkashyap		(struct tw_osli_req_context *)arg;
1285144966Svkashyap	struct twa_softc		*sc = req->ctlr;
1286144966Svkashyap	struct tw_cl_req_packet		*req_pkt = &(req->req_pkt);
1287144966Svkashyap
1288144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entered");
1289144966Svkashyap
1290212008Sdelphij	if (error == EINVAL) {
1291212008Sdelphij		req->error_code = error;
1292212008Sdelphij		return;
1293212008Sdelphij	}
1294212008Sdelphij
1295144966Svkashyap	/* Mark the request as currently being processed. */
1296144966Svkashyap	req->state = TW_OSLI_REQ_STATE_BUSY;
1297144966Svkashyap	/* Move the request into the busy queue. */
1298144966Svkashyap	tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q);
1299144966Svkashyap
1300144966Svkashyap	req->flags |= TW_OSLI_REQ_FLAGS_MAPPED;
1301144966Svkashyap
1302144966Svkashyap	if (error == EFBIG) {
1303144966Svkashyap		req->error_code = error;
1304144966Svkashyap		goto out;
1305144966Svkashyap	}
1306144966Svkashyap
1307144966Svkashyap	if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1308144966Svkashyap		struct tw_cl_passthru_req_packet	*pt_req;
1309144966Svkashyap
1310144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN)
1311144966Svkashyap			bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
1312144966Svkashyap				BUS_DMASYNC_PREREAD);
1313144966Svkashyap
1314144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) {
1315144966Svkashyap			/*
1316144966Svkashyap			 * If we're using an alignment buffer, and we're
1317144966Svkashyap			 * writing data, copy the real data out.
1318144966Svkashyap			 */
1319144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1320144966Svkashyap				bcopy(req->real_data, req->data, req->real_length);
1321144966Svkashyap			bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
1322144966Svkashyap				BUS_DMASYNC_PREWRITE);
1323144966Svkashyap		}
1324144966Svkashyap
1325144966Svkashyap		pt_req = &(req_pkt->gen_req_pkt.pt_req);
1326144966Svkashyap		pt_req->sg_list = (TW_UINT8 *)segs;
1327144966Svkashyap		pt_req->sgl_entries += (nsegments - 1);
1328144966Svkashyap		error = tw_cl_fw_passthru(&(sc->ctlr_handle), req_pkt,
1329144966Svkashyap			&(req->req_handle));
1330144966Svkashyap	} else {
1331144966Svkashyap		struct tw_cl_scsi_req_packet	*scsi_req;
1332144966Svkashyap
1333144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN)
1334144966Svkashyap			bus_dmamap_sync(sc->dma_tag, req->dma_map,
1335144966Svkashyap				BUS_DMASYNC_PREREAD);
1336144966Svkashyap
1337144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) {
1338144966Svkashyap			/*
1339144966Svkashyap			 * If we're using an alignment buffer, and we're
1340144966Svkashyap			 * writing data, copy the real data out.
1341144966Svkashyap			 */
1342144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1343144966Svkashyap				bcopy(req->real_data, req->data, req->real_length);
1344144966Svkashyap			bus_dmamap_sync(sc->dma_tag, req->dma_map,
1345144966Svkashyap				BUS_DMASYNC_PREWRITE);
1346144966Svkashyap		}
1347144966Svkashyap
1348144966Svkashyap		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
1349144966Svkashyap		scsi_req->sg_list = (TW_UINT8 *)segs;
1350144966Svkashyap		scsi_req->sgl_entries += (nsegments - 1);
1351144966Svkashyap		error = tw_cl_start_io(&(sc->ctlr_handle), req_pkt,
1352144966Svkashyap			&(req->req_handle));
1353144966Svkashyap	}
1354144966Svkashyap
1355144966Svkashyapout:
1356144966Svkashyap	if (error) {
1357144966Svkashyap		req->error_code = error;
1358144966Svkashyap		req_pkt->tw_osl_callback(&(req->req_handle));
1359144966Svkashyap		/*
1360144966Svkashyap		 * If the caller had been returned EINPROGRESS, and he has
1361144966Svkashyap		 * registered a callback for handling completion, the callback
1362144966Svkashyap		 * will never get called because we were unable to submit the
1363144966Svkashyap		 * request.  So, free up the request right here.
1364144966Svkashyap		 */
1365144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS)
1366144966Svkashyap			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
1367144966Svkashyap	}
1368144966Svkashyap}
1369144966Svkashyap
1370144966Svkashyap
1371144966Svkashyap
1372144966Svkashyap/*
1373144966Svkashyap * Function name:	twa_map_load_callback
1374144966Svkashyap * Description:		Callback of bus_dmamap_load for the buffer associated
1375144966Svkashyap *			with a cmd pkt.
1376144966Svkashyap *
1377144966Svkashyap * Input:		arg	-- ptr to variable to hold phys addr
1378144966Svkashyap *			segs	-- ptr to a list of segment descriptors
1379144966Svkashyap *			nsegments--# of segments
1380144966Svkashyap *			error	-- 0 if no errors encountered before callback,
1381144966Svkashyap *				   non-zero if errors were encountered
1382144966Svkashyap * Output:		None
1383144966Svkashyap * Return value:	None
1384144966Svkashyap */
1385144966Svkashyapstatic TW_VOID
1386144966Svkashyaptwa_map_load_callback(TW_VOID *arg, bus_dma_segment_t *segs,
1387144966Svkashyap	TW_INT32 nsegments, TW_INT32 error)
1388144966Svkashyap{
1389208969Sdelphij	*((bus_addr_t *)arg) = segs[0].ds_addr;
1390144966Svkashyap}
1391144966Svkashyap
1392144966Svkashyap
1393144966Svkashyap
1394144966Svkashyap/*
1395144966Svkashyap * Function name:	tw_osli_map_request
1396144966Svkashyap * Description:		Maps a cmd pkt and data associated with it, into
1397144966Svkashyap *			DMA'able memory.
1398144966Svkashyap *
1399144966Svkashyap * Input:		req	-- ptr to request pkt
1400144966Svkashyap * Output:		None
1401144966Svkashyap * Return value:	0	-- success
1402144966Svkashyap *			non-zero-- failure
1403144966Svkashyap */
1404144966SvkashyapTW_INT32
1405144966Svkashyaptw_osli_map_request(struct tw_osli_req_context *req)
1406144966Svkashyap{
1407144966Svkashyap	struct twa_softc	*sc = req->ctlr;
1408144966Svkashyap	TW_INT32		error = 0;
1409144966Svkashyap
1410144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entered");
1411144966Svkashyap
1412144966Svkashyap	/* If the command involves data, map that too. */
1413144966Svkashyap	if (req->data != NULL) {
1414144966Svkashyap		/*
1415144966Svkashyap		 * It's sufficient for the data pointer to be 4-byte aligned
1416144966Svkashyap		 * to work with 9000.  However, if 4-byte aligned addresses
1417144966Svkashyap		 * are passed to bus_dmamap_load, we can get back sg elements
1418144966Svkashyap		 * that are not 512-byte multiples in size.  So, we will let
1419144966Svkashyap		 * only those buffers that are 512-byte aligned to pass
1420144966Svkashyap		 * through, and bounce the rest, so as to make sure that we
1421144966Svkashyap		 * always get back sg elements that are 512-byte multiples
1422144966Svkashyap		 * in size.
1423144966Svkashyap		 */
1424144966Svkashyap		if (((vm_offset_t)req->data % sc->sg_size_factor) ||
1425144966Svkashyap			(req->length % sc->sg_size_factor)) {
1426144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED;
1427144966Svkashyap			/* Save original data pointer and length. */
1428144966Svkashyap			req->real_data = req->data;
1429144966Svkashyap			req->real_length = req->length;
1430144966Svkashyap			req->length = (req->length +
1431144966Svkashyap				(sc->sg_size_factor - 1)) &
1432144966Svkashyap				~(sc->sg_size_factor - 1);
1433144966Svkashyap			req->data = malloc(req->length, TW_OSLI_MALLOC_CLASS,
1434144966Svkashyap					M_NOWAIT);
1435144966Svkashyap			if (req->data == NULL) {
1436144966Svkashyap				tw_osli_printf(sc, "error = %d",
1437144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
1438144966Svkashyap					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1439144966Svkashyap					0x201E,
1440144966Svkashyap					"Failed to allocate memory "
1441144966Svkashyap					"for bounce buffer",
1442144966Svkashyap					ENOMEM);
1443144966Svkashyap				/* Restore original data pointer and length. */
1444144966Svkashyap				req->data = req->real_data;
1445144966Svkashyap				req->length = req->real_length;
1446144966Svkashyap				return(ENOMEM);
1447144966Svkashyap			}
1448144966Svkashyap		}
1449144966Svkashyap
1450144966Svkashyap		/*
1451144966Svkashyap		 * Map the data buffer into bus space and build the SG list.
1452144966Svkashyap		 */
1453144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1454144966Svkashyap			/* Lock against multiple simultaneous ioctl calls. */
1455144966Svkashyap			mtx_lock_spin(sc->io_lock);
1456144966Svkashyap			error = bus_dmamap_load(sc->ioctl_tag, sc->ioctl_map,
1457144966Svkashyap				req->data, req->length,
1458144966Svkashyap				twa_map_load_data_callback, req,
1459144966Svkashyap				BUS_DMA_WAITOK);
1460144966Svkashyap			mtx_unlock_spin(sc->io_lock);
1461251874Sscottl		} else if (req->flags & TW_OSLI_REQ_FLAGS_CCB) {
1462251874Sscottl			error = bus_dmamap_load_ccb(sc->dma_tag, req->dma_map,
1463251938Smav				req->orig_req, twa_map_load_data_callback, req,
1464251874Sscottl				BUS_DMA_WAITOK);
1465144966Svkashyap		} else {
1466144966Svkashyap			/*
1467144966Svkashyap			 * There's only one CAM I/O thread running at a time.
1468144966Svkashyap			 * So, there's no need to hold the io_lock.
1469144966Svkashyap			 */
1470144966Svkashyap			error = bus_dmamap_load(sc->dma_tag, req->dma_map,
1471144966Svkashyap				req->data, req->length,
1472144966Svkashyap				twa_map_load_data_callback, req,
1473144966Svkashyap				BUS_DMA_WAITOK);
1474144966Svkashyap		}
1475144966Svkashyap
1476144966Svkashyap		if (!error)
1477144966Svkashyap			error = req->error_code;
1478144966Svkashyap		else {
1479144966Svkashyap			if (error == EINPROGRESS) {
1480144966Svkashyap				/*
1481144966Svkashyap				 * Specifying sc->io_lock as the lockfuncarg
1482144966Svkashyap				 * in ...tag_create should protect the access
1483144966Svkashyap				 * of ...FLAGS_MAPPED from the callback.
1484144966Svkashyap				 */
1485144966Svkashyap				mtx_lock_spin(sc->io_lock);
1486208969Sdelphij				if (!(req->flags & TW_OSLI_REQ_FLAGS_MAPPED))
1487208969Sdelphij					req->flags |= TW_OSLI_REQ_FLAGS_IN_PROGRESS;
1488208969Sdelphij				tw_osli_disallow_new_requests(sc, &(req->req_handle));
1489144966Svkashyap				mtx_unlock_spin(sc->io_lock);
1490144966Svkashyap				error = 0;
1491144966Svkashyap			} else {
1492212008Sdelphij				tw_osli_printf(sc, "error = %d",
1493212008Sdelphij					TW_CL_SEVERITY_ERROR_STRING,
1494212008Sdelphij					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1495212008Sdelphij					0x9999,
1496212008Sdelphij					"Failed to map DMA memory "
1497212008Sdelphij					"for I/O request",
1498212008Sdelphij					error);
1499212008Sdelphij				req->flags |= TW_OSLI_REQ_FLAGS_FAILED;
1500144966Svkashyap				/* Free alignment buffer if it was used. */
1501144966Svkashyap				if (req->flags &
1502144966Svkashyap					TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
1503144966Svkashyap					free(req->data, TW_OSLI_MALLOC_CLASS);
1504144966Svkashyap					/*
1505144966Svkashyap					 * Restore original data pointer
1506144966Svkashyap					 * and length.
1507144966Svkashyap					 */
1508144966Svkashyap					req->data = req->real_data;
1509144966Svkashyap					req->length = req->real_length;
1510144966Svkashyap				}
1511144966Svkashyap			}
1512144966Svkashyap		}
1513144966Svkashyap
1514144966Svkashyap	} else {
1515144966Svkashyap		/* Mark the request as currently being processed. */
1516144966Svkashyap		req->state = TW_OSLI_REQ_STATE_BUSY;
1517144966Svkashyap		/* Move the request into the busy queue. */
1518144966Svkashyap		tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q);
1519144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU)
1520144966Svkashyap			error = tw_cl_fw_passthru(&sc->ctlr_handle,
1521144966Svkashyap					&(req->req_pkt), &(req->req_handle));
1522144966Svkashyap		else
1523144966Svkashyap			error = tw_cl_start_io(&sc->ctlr_handle,
1524144966Svkashyap					&(req->req_pkt), &(req->req_handle));
1525144966Svkashyap		if (error) {
1526144966Svkashyap			req->error_code = error;
1527144966Svkashyap			req->req_pkt.tw_osl_callback(&(req->req_handle));
1528144966Svkashyap		}
1529144966Svkashyap	}
1530144966Svkashyap	return(error);
1531144966Svkashyap}
1532144966Svkashyap
1533144966Svkashyap
1534144966Svkashyap
1535144966Svkashyap/*
1536144966Svkashyap * Function name:	tw_osli_unmap_request
1537144966Svkashyap * Description:		Undoes the mapping done by tw_osli_map_request.
1538144966Svkashyap *
1539144966Svkashyap * Input:		req	-- ptr to request pkt
1540144966Svkashyap * Output:		None
1541144966Svkashyap * Return value:	None
1542144966Svkashyap */
1543144966SvkashyapTW_VOID
1544144966Svkashyaptw_osli_unmap_request(struct tw_osli_req_context *req)
1545144966Svkashyap{
1546144966Svkashyap	struct twa_softc	*sc = req->ctlr;
1547144966Svkashyap
1548144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entered");
1549144966Svkashyap
1550144966Svkashyap	/* If the command involved data, unmap that too. */
1551144966Svkashyap	if (req->data != NULL) {
1552144966Svkashyap		if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) {
1553144966Svkashyap			/* Lock against multiple simultaneous ioctl calls. */
1554144966Svkashyap			mtx_lock_spin(sc->io_lock);
1555144966Svkashyap
1556144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) {
1557144966Svkashyap				bus_dmamap_sync(sc->ioctl_tag,
1558144966Svkashyap					sc->ioctl_map, BUS_DMASYNC_POSTREAD);
1559144966Svkashyap
1560144966Svkashyap				/*
1561144966Svkashyap				 * If we are using a bounce buffer, and we are
1562144966Svkashyap				 * reading data, copy the real data in.
1563144966Svkashyap				 */
1564144966Svkashyap				if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1565144966Svkashyap					bcopy(req->data, req->real_data,
1566144966Svkashyap						req->real_length);
1567144966Svkashyap			}
1568144966Svkashyap
1569144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT)
1570144966Svkashyap				bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map,
1571144966Svkashyap					BUS_DMASYNC_POSTWRITE);
1572144966Svkashyap
1573144966Svkashyap			bus_dmamap_unload(sc->ioctl_tag, sc->ioctl_map);
1574144966Svkashyap
1575144966Svkashyap			mtx_unlock_spin(sc->io_lock);
1576144966Svkashyap		} else {
1577144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) {
1578144966Svkashyap				bus_dmamap_sync(sc->dma_tag,
1579144966Svkashyap					req->dma_map, BUS_DMASYNC_POSTREAD);
1580144966Svkashyap
1581144966Svkashyap				/*
1582144966Svkashyap				 * If we are using a bounce buffer, and we are
1583144966Svkashyap				 * reading data, copy the real data in.
1584144966Svkashyap				 */
1585144966Svkashyap				if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED)
1586144966Svkashyap					bcopy(req->data, req->real_data,
1587144966Svkashyap						req->real_length);
1588144966Svkashyap			}
1589144966Svkashyap			if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT)
1590144966Svkashyap				bus_dmamap_sync(sc->dma_tag, req->dma_map,
1591144966Svkashyap					BUS_DMASYNC_POSTWRITE);
1592144966Svkashyap
1593144966Svkashyap			bus_dmamap_unload(sc->dma_tag, req->dma_map);
1594144966Svkashyap		}
1595144966Svkashyap	}
1596144966Svkashyap
1597144966Svkashyap	/* Free alignment buffer if it was used. */
1598144966Svkashyap	if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
1599144966Svkashyap		free(req->data, TW_OSLI_MALLOC_CLASS);
1600144966Svkashyap		/* Restore original data pointer and length. */
1601144966Svkashyap		req->data = req->real_data;
1602144966Svkashyap		req->length = req->real_length;
1603144966Svkashyap	}
1604144966Svkashyap}
1605144966Svkashyap
1606144966Svkashyap
1607144966Svkashyap
1608144966Svkashyap#ifdef TW_OSL_DEBUG
1609144966Svkashyap
1610144966SvkashyapTW_VOID	twa_report_stats(TW_VOID);
1611144966SvkashyapTW_VOID	twa_reset_stats(TW_VOID);
1612144966SvkashyapTW_VOID	tw_osli_print_ctlr_stats(struct twa_softc *sc);
1613144966SvkashyapTW_VOID twa_print_req_info(struct tw_osli_req_context *req);
1614144966Svkashyap
1615144966Svkashyap
1616144966Svkashyap/*
1617144966Svkashyap * Function name:	twa_report_stats
1618144966Svkashyap * Description:		For being called from ddb.  Calls functions that print
1619144966Svkashyap *			OSL and CL internal stats for the controller.
1620144966Svkashyap *
1621144966Svkashyap * Input:		None
1622144966Svkashyap * Output:		None
1623144966Svkashyap * Return value:	None
1624144966Svkashyap */
1625144966SvkashyapTW_VOID
1626144966Svkashyaptwa_report_stats(TW_VOID)
1627144966Svkashyap{
1628144966Svkashyap	struct twa_softc	*sc;
1629144966Svkashyap	TW_INT32		i;
1630144966Svkashyap
1631144966Svkashyap	for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
1632144966Svkashyap		tw_osli_print_ctlr_stats(sc);
1633144966Svkashyap		tw_cl_print_ctlr_stats(&sc->ctlr_handle);
1634144966Svkashyap	}
1635144966Svkashyap}
1636144966Svkashyap
1637144966Svkashyap
1638144966Svkashyap
1639144966Svkashyap/*
1640144966Svkashyap * Function name:	tw_osli_print_ctlr_stats
1641144966Svkashyap * Description:		For being called from ddb.  Prints OSL controller stats
1642144966Svkashyap *
1643144966Svkashyap * Input:		sc	-- ptr to OSL internal controller context
1644144966Svkashyap * Output:		None
1645144966Svkashyap * Return value:	None
1646144966Svkashyap */
1647144966SvkashyapTW_VOID
1648144966Svkashyaptw_osli_print_ctlr_stats(struct twa_softc *sc)
1649144966Svkashyap{
1650144966Svkashyap	twa_printf(sc, "osl_ctlr_ctxt = %p\n", sc);
1651144966Svkashyap	twa_printf(sc, "OSLq type  current  max\n");
1652144966Svkashyap	twa_printf(sc, "free      %04d     %04d\n",
1653144966Svkashyap		sc->q_stats[TW_OSLI_FREE_Q].cur_len,
1654144966Svkashyap		sc->q_stats[TW_OSLI_FREE_Q].max_len);
1655144966Svkashyap	twa_printf(sc, "busy      %04d     %04d\n",
1656144966Svkashyap		sc->q_stats[TW_OSLI_BUSY_Q].cur_len,
1657144966Svkashyap		sc->q_stats[TW_OSLI_BUSY_Q].max_len);
1658144966Svkashyap}
1659144966Svkashyap
1660144966Svkashyap
1661144966Svkashyap
1662144966Svkashyap/*
1663144966Svkashyap * Function name:	twa_print_req_info
1664144966Svkashyap * Description:		For being called from ddb.  Calls functions that print
1665144966Svkashyap *			OSL and CL internal details for the request.
1666144966Svkashyap *
1667144966Svkashyap * Input:		req	-- ptr to OSL internal request context
1668144966Svkashyap * Output:		None
1669144966Svkashyap * Return value:	None
1670144966Svkashyap */
1671144966SvkashyapTW_VOID
1672144966Svkashyaptwa_print_req_info(struct tw_osli_req_context *req)
1673144966Svkashyap{
1674144966Svkashyap	struct twa_softc	*sc = req->ctlr;
1675144966Svkashyap
1676144966Svkashyap	twa_printf(sc, "OSL details for request:\n");
1677144966Svkashyap	twa_printf(sc, "osl_req_ctxt = %p, cl_req_ctxt = %p\n"
1678144966Svkashyap		"data = %p, length = 0x%x, real_data = %p, real_length = 0x%x\n"
1679144966Svkashyap		"state = 0x%x, flags = 0x%x, error = 0x%x, orig_req = %p\n"
1680144966Svkashyap		"next_req = %p, prev_req = %p, dma_map = %p\n",
1681144966Svkashyap		req->req_handle.osl_req_ctxt, req->req_handle.cl_req_ctxt,
1682144966Svkashyap		req->data, req->length, req->real_data, req->real_length,
1683144966Svkashyap		req->state, req->flags, req->error_code, req->orig_req,
1684144966Svkashyap		req->link.next, req->link.prev, req->dma_map);
1685144966Svkashyap	tw_cl_print_req_info(&(req->req_handle));
1686144966Svkashyap}
1687144966Svkashyap
1688144966Svkashyap
1689144966Svkashyap
1690144966Svkashyap/*
1691144966Svkashyap * Function name:	twa_reset_stats
1692144966Svkashyap * Description:		For being called from ddb.
1693144966Svkashyap *			Resets some OSL controller stats.
1694144966Svkashyap *
1695144966Svkashyap * Input:		None
1696144966Svkashyap * Output:		None
1697144966Svkashyap * Return value:	None
1698144966Svkashyap */
1699144966SvkashyapTW_VOID
1700144966Svkashyaptwa_reset_stats(TW_VOID)
1701144966Svkashyap{
1702144966Svkashyap	struct twa_softc	*sc;
1703144966Svkashyap	TW_INT32		i;
1704144966Svkashyap
1705144966Svkashyap	for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) {
1706144966Svkashyap		sc->q_stats[TW_OSLI_FREE_Q].max_len = 0;
1707144966Svkashyap		sc->q_stats[TW_OSLI_BUSY_Q].max_len = 0;
1708144966Svkashyap		tw_cl_reset_stats(&sc->ctlr_handle);
1709144966Svkashyap	}
1710144966Svkashyap}
1711144966Svkashyap
1712144966Svkashyap#endif /* TW_OSL_DEBUG */
1713