xref: /dflybsd-src/sys/dev/raid/tws/tws_services.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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