1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Copyright (c) 2010, LSI Corp.
3*86d7f5d3SJohn Marino * All rights reserved.
4*86d7f5d3SJohn Marino * Author : Manjunath Ranganathaiah
5*86d7f5d3SJohn Marino * Support: freebsdraid@lsi.com
6*86d7f5d3SJohn Marino *
7*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
8*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
9*86d7f5d3SJohn Marino * are met:
10*86d7f5d3SJohn Marino *
11*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
12*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
13*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
14*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in
15*86d7f5d3SJohn Marino * the documentation and/or other materials provided with the
16*86d7f5d3SJohn Marino * distribution.
17*86d7f5d3SJohn Marino * 3. Neither the name of the <ORGANIZATION> nor the names of its
18*86d7f5d3SJohn Marino * contributors may be used to endorse or promote products derived
19*86d7f5d3SJohn Marino * from this software without specific prior written permission.
20*86d7f5d3SJohn Marino *
21*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*86d7f5d3SJohn Marino * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*86d7f5d3SJohn Marino * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*86d7f5d3SJohn Marino * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25*86d7f5d3SJohn Marino * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*86d7f5d3SJohn Marino * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*86d7f5d3SJohn Marino * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*86d7f5d3SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29*86d7f5d3SJohn Marino * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*86d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31*86d7f5d3SJohn Marino * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32*86d7f5d3SJohn Marino * POSSIBILITY OF SUCH DAMAGE.
33*86d7f5d3SJohn Marino *
34*86d7f5d3SJohn Marino * $FreeBSD: src/sys/dev/tws/tws_cam.c,v 1.3 2007/05/09 04:16:32 mrangana Exp $
35*86d7f5d3SJohn Marino */
36*86d7f5d3SJohn Marino
37*86d7f5d3SJohn Marino #include <dev/raid/tws/tws.h>
38*86d7f5d3SJohn Marino #include <dev/raid/tws/tws_hdm.h>
39*86d7f5d3SJohn Marino #include <dev/raid/tws/tws_services.h>
40*86d7f5d3SJohn Marino #include <sys/time.h>
41*86d7f5d3SJohn Marino
42*86d7f5d3SJohn Marino void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
43*86d7f5d3SJohn Marino u_int8_t q_type );
44*86d7f5d3SJohn Marino struct tws_request * tws_q_remove_request(struct tws_softc *sc,
45*86d7f5d3SJohn Marino struct tws_request *req, u_int8_t q_type );
46*86d7f5d3SJohn Marino struct tws_request *tws_q_remove_head(struct tws_softc *sc, u_int8_t q_type );
47*86d7f5d3SJohn Marino void tws_q_insert_head(struct tws_softc *sc, struct tws_request *req,
48*86d7f5d3SJohn Marino u_int8_t q_type );
49*86d7f5d3SJohn Marino struct tws_request * tws_q_remove_tail(struct tws_softc *sc, u_int8_t q_type );
50*86d7f5d3SJohn Marino void tws_print_stats(void *arg);
51*86d7f5d3SJohn Marino
52*86d7f5d3SJohn Marino struct tws_sense *tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa);
53*86d7f5d3SJohn Marino
54*86d7f5d3SJohn Marino
55*86d7f5d3SJohn Marino
56*86d7f5d3SJohn Marino struct error_desc array[] = {
57*86d7f5d3SJohn Marino { "Cannot add sysctl tree node", 0x2000, ERROR,
58*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
59*86d7f5d3SJohn Marino { "Register window not available", 0x2001, ERROR,
60*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
61*86d7f5d3SJohn Marino { "Can't allocate register window", 0x2002, ERROR,
62*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
63*86d7f5d3SJohn Marino { "Can't allocate interrupt", 0x2003, ERROR,
64*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
65*86d7f5d3SJohn Marino { "Can't set up interrupt", 0x2004, ERROR,
66*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
67*86d7f5d3SJohn Marino { "Couldn't intialize CAM", 0x2007, ERROR,
68*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
69*86d7f5d3SJohn Marino { "Couldn't create SIM device queue", 0x2100, ENOMEM,
70*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
71*86d7f5d3SJohn Marino { "Unable to create SIM entry", 0x2101, ENOMEM,
72*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
73*86d7f5d3SJohn Marino { "Unable to register the bus", 0x2102, ENXIO,
74*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
75*86d7f5d3SJohn Marino { "Unable to create the path", 0x2103, ENXIO,
76*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
77*86d7f5d3SJohn Marino { "Bus scan request to CAM failed", 0x2104, ENXIO,
78*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
79*86d7f5d3SJohn Marino { "Unable to intialize the driver", 0x2008, ENXIO,
80*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
81*86d7f5d3SJohn Marino { "Unable to intialize the controller", 0x2009, ENXIO,
82*86d7f5d3SJohn Marino "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
83*86d7f5d3SJohn Marino };
84*86d7f5d3SJohn Marino
85*86d7f5d3SJohn Marino void
tws_trace(const char * file,const char * fun,int linenum,struct tws_softc * sc,char * desc,u_int64_t val1,u_int64_t val2)86*86d7f5d3SJohn Marino tws_trace(const char *file, const char *fun, int linenum,
87*86d7f5d3SJohn Marino struct tws_softc *sc, char *desc, u_int64_t val1, u_int64_t val2)
88*86d7f5d3SJohn Marino {
89*86d7f5d3SJohn Marino
90*86d7f5d3SJohn Marino
91*86d7f5d3SJohn Marino struct tws_trace_rec *rec = (struct tws_trace_rec *)sc->trace_q.q;
92*86d7f5d3SJohn Marino volatile u_int16_t head, tail;
93*86d7f5d3SJohn Marino char fmt[256];
94*86d7f5d3SJohn Marino
95*86d7f5d3SJohn Marino head = sc->trace_q.head;
96*86d7f5d3SJohn Marino tail = sc->trace_q.tail;
97*86d7f5d3SJohn Marino /*
98*86d7f5d3SJohn Marino getnanotime(&rec[tail].ts);
99*86d7f5d3SJohn Marino */
100*86d7f5d3SJohn Marino strncpy(rec[tail].fname, file, TWS_TRACE_FNAME_LEN);
101*86d7f5d3SJohn Marino strncpy(rec[tail].func, fun, TWS_TRACE_FUNC_LEN);
102*86d7f5d3SJohn Marino rec[tail].linenum = linenum;
103*86d7f5d3SJohn Marino strncpy(rec[tail].desc, desc, TWS_TRACE_DESC_LEN);
104*86d7f5d3SJohn Marino rec[tail].val1 = val1;
105*86d7f5d3SJohn Marino rec[tail].val2 = val2;
106*86d7f5d3SJohn Marino
107*86d7f5d3SJohn Marino tail = (tail+1) % sc->trace_q.depth;
108*86d7f5d3SJohn Marino
109*86d7f5d3SJohn Marino if ( head == tail ) {
110*86d7f5d3SJohn Marino sc->trace_q.overflow = 1;
111*86d7f5d3SJohn Marino sc->trace_q.head = (head+1) % sc->trace_q.depth;
112*86d7f5d3SJohn Marino }
113*86d7f5d3SJohn Marino sc->trace_q.tail = tail;
114*86d7f5d3SJohn Marino
115*86d7f5d3SJohn Marino /*
116*86d7f5d3SJohn Marino tws_circular_q_insert(sc, &sc->trace_q,
117*86d7f5d3SJohn Marino &rec, sizeof(struct tws_trace_rec));
118*86d7f5d3SJohn Marino */
119*86d7f5d3SJohn Marino if ( sc->is64bit )
120*86d7f5d3SJohn Marino strcpy(fmt, "%05d:%s::%s :%s: 0x%016lx : 0x%016lx \n");
121*86d7f5d3SJohn Marino else
122*86d7f5d3SJohn Marino strcpy(fmt, "%05d:%s::%s :%s: 0x%016llx : 0x%016llx \n");
123*86d7f5d3SJohn Marino
124*86d7f5d3SJohn Marino /*
125*86d7f5d3SJohn Marino kprintf("%05d:%s::%s :%s: 0x%016llx : 0x%016llx \n",
126*86d7f5d3SJohn Marino linenum, file, fun, desc, val1, val2);
127*86d7f5d3SJohn Marino */
128*86d7f5d3SJohn Marino kprintf(fmt, linenum, file, fun, desc, val1, val2);
129*86d7f5d3SJohn Marino }
130*86d7f5d3SJohn Marino
131*86d7f5d3SJohn Marino void
tws_log(struct tws_softc * sc,int index)132*86d7f5d3SJohn Marino tws_log(struct tws_softc *sc, int index)
133*86d7f5d3SJohn Marino {
134*86d7f5d3SJohn Marino device_printf((sc)->tws_dev, array[index].fmt,
135*86d7f5d3SJohn Marino array[index].error_str,
136*86d7f5d3SJohn Marino array[index].error_code,
137*86d7f5d3SJohn Marino array[index].severity_level,
138*86d7f5d3SJohn Marino array[index].desc );
139*86d7f5d3SJohn Marino }
140*86d7f5d3SJohn Marino
141*86d7f5d3SJohn Marino /* ----------- swap functions ----------- */
142*86d7f5d3SJohn Marino
143*86d7f5d3SJohn Marino
144*86d7f5d3SJohn Marino u_int16_t
tws_swap16(u_int16_t val)145*86d7f5d3SJohn Marino tws_swap16(u_int16_t val)
146*86d7f5d3SJohn Marino {
147*86d7f5d3SJohn Marino return((val << 8) | (val >> 8));
148*86d7f5d3SJohn Marino }
149*86d7f5d3SJohn Marino
150*86d7f5d3SJohn Marino u_int32_t
tws_swap32(u_int32_t val)151*86d7f5d3SJohn Marino tws_swap32(u_int32_t val)
152*86d7f5d3SJohn Marino {
153*86d7f5d3SJohn Marino return(((val << 24) | ((val << 8) & (0xFF0000)) |
154*86d7f5d3SJohn Marino ((val >> 8) & (0xFF00)) | (val >> 24)));
155*86d7f5d3SJohn Marino }
156*86d7f5d3SJohn Marino
157*86d7f5d3SJohn Marino
158*86d7f5d3SJohn Marino u_int64_t
tws_swap64(u_int64_t val)159*86d7f5d3SJohn Marino tws_swap64(u_int64_t val)
160*86d7f5d3SJohn Marino {
161*86d7f5d3SJohn Marino return((((u_int64_t)(tws_swap32(((u_int32_t *)(&(val)))[1]))) << 32) |
162*86d7f5d3SJohn Marino ((u_int32_t)(tws_swap32(((u_int32_t *)(&(val)))[0]))));
163*86d7f5d3SJohn Marino }
164*86d7f5d3SJohn Marino
165*86d7f5d3SJohn Marino
166*86d7f5d3SJohn Marino /* ----------- reg access ----------- */
167*86d7f5d3SJohn Marino
168*86d7f5d3SJohn Marino
169*86d7f5d3SJohn Marino void
tws_write_reg(struct tws_softc * sc,int offset,u_int32_t value,int size)170*86d7f5d3SJohn Marino tws_write_reg(struct tws_softc *sc, int offset,
171*86d7f5d3SJohn Marino u_int32_t value, int size)
172*86d7f5d3SJohn Marino {
173*86d7f5d3SJohn Marino bus_space_tag_t bus_tag = sc->bus_tag;
174*86d7f5d3SJohn Marino bus_space_handle_t bus_handle = sc->bus_handle;
175*86d7f5d3SJohn Marino
176*86d7f5d3SJohn Marino if (size == 4)
177*86d7f5d3SJohn Marino bus_space_write_4(bus_tag, bus_handle, offset, value);
178*86d7f5d3SJohn Marino else
179*86d7f5d3SJohn Marino if (size == 2)
180*86d7f5d3SJohn Marino bus_space_write_2(bus_tag, bus_handle, offset,
181*86d7f5d3SJohn Marino (u_int16_t)value);
182*86d7f5d3SJohn Marino else
183*86d7f5d3SJohn Marino bus_space_write_1(bus_tag, bus_handle, offset, (u_int8_t)value);
184*86d7f5d3SJohn Marino }
185*86d7f5d3SJohn Marino
186*86d7f5d3SJohn Marino u_int32_t
tws_read_reg(struct tws_softc * sc,int offset,int size)187*86d7f5d3SJohn Marino tws_read_reg(struct tws_softc *sc, int offset, int size)
188*86d7f5d3SJohn Marino {
189*86d7f5d3SJohn Marino bus_space_tag_t bus_tag = sc->bus_tag;
190*86d7f5d3SJohn Marino bus_space_handle_t bus_handle = sc->bus_handle;
191*86d7f5d3SJohn Marino
192*86d7f5d3SJohn Marino if (size == 4)
193*86d7f5d3SJohn Marino return((u_int32_t)bus_space_read_4(bus_tag, bus_handle, offset));
194*86d7f5d3SJohn Marino else if (size == 2)
195*86d7f5d3SJohn Marino return((u_int32_t)bus_space_read_2(bus_tag, bus_handle, offset));
196*86d7f5d3SJohn Marino else
197*86d7f5d3SJohn Marino return((u_int32_t)bus_space_read_1(bus_tag, bus_handle, offset));
198*86d7f5d3SJohn Marino }
199*86d7f5d3SJohn Marino
200*86d7f5d3SJohn Marino /* --------------------- Q service --------------------- */
201*86d7f5d3SJohn Marino
202*86d7f5d3SJohn Marino /*
203*86d7f5d3SJohn Marino * intialize q pointers with null.
204*86d7f5d3SJohn Marino */
205*86d7f5d3SJohn Marino void
tws_init_qs(struct tws_softc * sc)206*86d7f5d3SJohn Marino tws_init_qs(struct tws_softc *sc)
207*86d7f5d3SJohn Marino {
208*86d7f5d3SJohn Marino
209*86d7f5d3SJohn Marino lockmgr(&sc->q_lock, LK_EXCLUSIVE);
210*86d7f5d3SJohn Marino for(int i=0;i<TWS_MAX_QS;i++) {
211*86d7f5d3SJohn Marino sc->q_head[i] = NULL;
212*86d7f5d3SJohn Marino sc->q_tail[i] = NULL;
213*86d7f5d3SJohn Marino }
214*86d7f5d3SJohn Marino lockmgr(&sc->q_lock, LK_RELEASE);
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino }
217*86d7f5d3SJohn Marino
218*86d7f5d3SJohn Marino /* called with lock held */
219*86d7f5d3SJohn Marino static void
tws_insert2_empty_q(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)220*86d7f5d3SJohn Marino tws_insert2_empty_q(struct tws_softc *sc, struct tws_request *req,
221*86d7f5d3SJohn Marino u_int8_t q_type )
222*86d7f5d3SJohn Marino {
223*86d7f5d3SJohn Marino
224*86d7f5d3SJohn Marino KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
225*86d7f5d3SJohn Marino req->next = req->prev = NULL;
226*86d7f5d3SJohn Marino sc->q_head[q_type] = sc->q_tail[q_type] = req;
227*86d7f5d3SJohn Marino
228*86d7f5d3SJohn Marino }
229*86d7f5d3SJohn Marino
230*86d7f5d3SJohn Marino /* called with lock held */
231*86d7f5d3SJohn Marino void
tws_q_insert_head(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)232*86d7f5d3SJohn Marino tws_q_insert_head(struct tws_softc *sc, struct tws_request *req,
233*86d7f5d3SJohn Marino u_int8_t q_type )
234*86d7f5d3SJohn Marino {
235*86d7f5d3SJohn Marino
236*86d7f5d3SJohn Marino KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
237*86d7f5d3SJohn Marino if ( sc->q_head[q_type] == NULL ) {
238*86d7f5d3SJohn Marino tws_insert2_empty_q(sc, req, q_type);
239*86d7f5d3SJohn Marino } else {
240*86d7f5d3SJohn Marino req->next = sc->q_head[q_type];
241*86d7f5d3SJohn Marino req->prev = NULL;
242*86d7f5d3SJohn Marino sc->q_head[q_type]->prev = req;
243*86d7f5d3SJohn Marino sc->q_head[q_type] = req;
244*86d7f5d3SJohn Marino }
245*86d7f5d3SJohn Marino
246*86d7f5d3SJohn Marino }
247*86d7f5d3SJohn Marino
248*86d7f5d3SJohn Marino /* called with lock held */
249*86d7f5d3SJohn Marino void
tws_q_insert_tail(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)250*86d7f5d3SJohn Marino tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
251*86d7f5d3SJohn Marino u_int8_t q_type )
252*86d7f5d3SJohn Marino {
253*86d7f5d3SJohn Marino
254*86d7f5d3SJohn Marino KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
255*86d7f5d3SJohn Marino if ( sc->q_tail[q_type] == NULL ) {
256*86d7f5d3SJohn Marino tws_insert2_empty_q(sc, req, q_type);
257*86d7f5d3SJohn Marino } else {
258*86d7f5d3SJohn Marino req->prev = sc->q_tail[q_type];
259*86d7f5d3SJohn Marino req->next = NULL;
260*86d7f5d3SJohn Marino sc->q_tail[q_type]->next = req;
261*86d7f5d3SJohn Marino sc->q_tail[q_type] = req;
262*86d7f5d3SJohn Marino }
263*86d7f5d3SJohn Marino
264*86d7f5d3SJohn Marino }
265*86d7f5d3SJohn Marino
266*86d7f5d3SJohn Marino /* called with lock held */
267*86d7f5d3SJohn Marino struct tws_request *
tws_q_remove_head(struct tws_softc * sc,u_int8_t q_type)268*86d7f5d3SJohn Marino tws_q_remove_head(struct tws_softc *sc, u_int8_t q_type )
269*86d7f5d3SJohn Marino {
270*86d7f5d3SJohn Marino
271*86d7f5d3SJohn Marino struct tws_request *r;
272*86d7f5d3SJohn Marino
273*86d7f5d3SJohn Marino KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
274*86d7f5d3SJohn Marino r = sc->q_head[q_type];
275*86d7f5d3SJohn Marino if ( !r )
276*86d7f5d3SJohn Marino return(NULL);
277*86d7f5d3SJohn Marino if ( r->next == NULL && r->prev == NULL ) {
278*86d7f5d3SJohn Marino /* last element */
279*86d7f5d3SJohn Marino sc->q_head[q_type] = sc->q_tail[q_type] = NULL;
280*86d7f5d3SJohn Marino } else {
281*86d7f5d3SJohn Marino sc->q_head[q_type] = r->next;
282*86d7f5d3SJohn Marino r->next->prev = NULL;
283*86d7f5d3SJohn Marino r->next = NULL;
284*86d7f5d3SJohn Marino r->prev = NULL;
285*86d7f5d3SJohn Marino }
286*86d7f5d3SJohn Marino return(r);
287*86d7f5d3SJohn Marino }
288*86d7f5d3SJohn Marino
289*86d7f5d3SJohn Marino /* called with lock held */
290*86d7f5d3SJohn Marino struct tws_request *
tws_q_remove_tail(struct tws_softc * sc,u_int8_t q_type)291*86d7f5d3SJohn Marino tws_q_remove_tail(struct tws_softc *sc, u_int8_t q_type )
292*86d7f5d3SJohn Marino {
293*86d7f5d3SJohn Marino
294*86d7f5d3SJohn Marino struct tws_request *r;
295*86d7f5d3SJohn Marino
296*86d7f5d3SJohn Marino KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
297*86d7f5d3SJohn Marino r = sc->q_tail[q_type];
298*86d7f5d3SJohn Marino if ( !r )
299*86d7f5d3SJohn Marino return(NULL);
300*86d7f5d3SJohn Marino if ( r->next == NULL && r->prev == NULL ) {
301*86d7f5d3SJohn Marino /* last element */
302*86d7f5d3SJohn Marino sc->q_head[q_type] = sc->q_tail[q_type] = NULL;
303*86d7f5d3SJohn Marino } else {
304*86d7f5d3SJohn Marino sc->q_tail[q_type] = r->prev;
305*86d7f5d3SJohn Marino r->prev->next = NULL;
306*86d7f5d3SJohn Marino r->next = NULL;
307*86d7f5d3SJohn Marino r->prev = NULL;
308*86d7f5d3SJohn Marino }
309*86d7f5d3SJohn Marino return(r);
310*86d7f5d3SJohn Marino }
311*86d7f5d3SJohn Marino
312*86d7f5d3SJohn Marino /* returns removed request if successful. return NULL otherwise */
313*86d7f5d3SJohn Marino /* called with lock held */
314*86d7f5d3SJohn Marino struct tws_request *
tws_q_remove_request(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)315*86d7f5d3SJohn Marino tws_q_remove_request(struct tws_softc *sc, struct tws_request *req,
316*86d7f5d3SJohn Marino u_int8_t q_type )
317*86d7f5d3SJohn Marino {
318*86d7f5d3SJohn Marino
319*86d7f5d3SJohn Marino struct tws_request *r;
320*86d7f5d3SJohn Marino
321*86d7f5d3SJohn Marino KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
322*86d7f5d3SJohn Marino if ( req == NULL ) {
323*86d7f5d3SJohn Marino TWS_TRACE_DEBUG(sc, "null req", 0, q_type);
324*86d7f5d3SJohn Marino return(NULL);
325*86d7f5d3SJohn Marino }
326*86d7f5d3SJohn Marino
327*86d7f5d3SJohn Marino if ( req == sc->q_head[q_type] )
328*86d7f5d3SJohn Marino return(tws_q_remove_head(sc, q_type));
329*86d7f5d3SJohn Marino if ( req == sc->q_tail[q_type] )
330*86d7f5d3SJohn Marino return(tws_q_remove_tail(sc, q_type));
331*86d7f5d3SJohn Marino
332*86d7f5d3SJohn Marino
333*86d7f5d3SJohn Marino /* The given node is not at head or tail.
334*86d7f5d3SJohn Marino * It's in the middle and there are more than
335*86d7f5d3SJohn Marino * 2 elements on the q.
336*86d7f5d3SJohn Marino */
337*86d7f5d3SJohn Marino
338*86d7f5d3SJohn Marino if ( req->next == NULL || req->prev == NULL ) {
339*86d7f5d3SJohn Marino TWS_TRACE_DEBUG(sc, "invalid req", 0, q_type);
340*86d7f5d3SJohn Marino return(NULL);
341*86d7f5d3SJohn Marino }
342*86d7f5d3SJohn Marino
343*86d7f5d3SJohn Marino /* debug only */
344*86d7f5d3SJohn Marino r = sc->q_head[q_type];
345*86d7f5d3SJohn Marino while ( r ) {
346*86d7f5d3SJohn Marino if ( req == r )
347*86d7f5d3SJohn Marino break;
348*86d7f5d3SJohn Marino r = r->next;
349*86d7f5d3SJohn Marino }
350*86d7f5d3SJohn Marino
351*86d7f5d3SJohn Marino if ( !r ) {
352*86d7f5d3SJohn Marino TWS_TRACE_DEBUG(sc, "req not in q", 0, req->request_id);
353*86d7f5d3SJohn Marino return(NULL);
354*86d7f5d3SJohn Marino }
355*86d7f5d3SJohn Marino /* debug end */
356*86d7f5d3SJohn Marino
357*86d7f5d3SJohn Marino req->prev->next = r->next;
358*86d7f5d3SJohn Marino req->next->prev = r->prev;
359*86d7f5d3SJohn Marino req->next = NULL;
360*86d7f5d3SJohn Marino req->prev = NULL;
361*86d7f5d3SJohn Marino return(req);
362*86d7f5d3SJohn Marino }
363*86d7f5d3SJohn Marino
364*86d7f5d3SJohn Marino struct tws_sense *
tws_find_sense_from_mfa(struct tws_softc * sc,u_int64_t mfa)365*86d7f5d3SJohn Marino tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa)
366*86d7f5d3SJohn Marino {
367*86d7f5d3SJohn Marino struct tws_sense *s;
368*86d7f5d3SJohn Marino int i;
369*86d7f5d3SJohn Marino TWS_TRACE_DEBUG(sc, "entry",sc,mfa);
370*86d7f5d3SJohn Marino
371*86d7f5d3SJohn Marino i = (mfa - sc->dma_mem_phys) / sizeof(struct tws_command_packet);
372*86d7f5d3SJohn Marino if ( i>= 0 && i<tws_queue_depth) {
373*86d7f5d3SJohn Marino s = &sc->sense_bufs[i];
374*86d7f5d3SJohn Marino if ( mfa == s->hdr_pkt_phy )
375*86d7f5d3SJohn Marino return(s);
376*86d7f5d3SJohn Marino }
377*86d7f5d3SJohn Marino
378*86d7f5d3SJohn Marino TWS_TRACE_DEBUG(sc, "return null",0,mfa);
379*86d7f5d3SJohn Marino return(NULL);
380*86d7f5d3SJohn Marino
381*86d7f5d3SJohn Marino }
382*86d7f5d3SJohn Marino
383*86d7f5d3SJohn Marino /* --------------------- Q service end --------------------- */
384*86d7f5d3SJohn Marino /* --------------------- misc service start --------------------- */
385*86d7f5d3SJohn Marino
386*86d7f5d3SJohn Marino
387*86d7f5d3SJohn Marino void
tws_print_stats(void * arg)388*86d7f5d3SJohn Marino tws_print_stats(void *arg)
389*86d7f5d3SJohn Marino {
390*86d7f5d3SJohn Marino
391*86d7f5d3SJohn Marino struct tws_softc *sc = (struct tws_softc *)arg;
392*86d7f5d3SJohn Marino
393*86d7f5d3SJohn Marino TWS_TRACE(sc, "reqs(in, out)", sc->stats.reqs_in, sc->stats.reqs_out);
394*86d7f5d3SJohn Marino TWS_TRACE(sc, "reqs(err, intrs)", sc->stats.reqs_errored
395*86d7f5d3SJohn Marino , sc->stats.num_intrs);
396*86d7f5d3SJohn Marino TWS_TRACE(sc, "reqs(ioctls, scsi)", sc->stats.ioctls
397*86d7f5d3SJohn Marino , sc->stats.scsi_ios);
398*86d7f5d3SJohn Marino callout_reset(&sc->print_stats_handle, 300*hz, tws_print_stats, sc);
399*86d7f5d3SJohn Marino
400*86d7f5d3SJohn Marino }
401*86d7f5d3SJohn Marino /* --------------------- misc service end --------------------- */
402