xref: /dflybsd-src/sys/dev/raid/tws/tws_services.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * Copyright (c) 2010, LSI Corp.
386d7f5d3SJohn Marino  * All rights reserved.
486d7f5d3SJohn Marino  * Author : Manjunath Ranganathaiah
586d7f5d3SJohn Marino  * Support: freebsdraid@lsi.com
686d7f5d3SJohn Marino  *
786d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
886d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
986d7f5d3SJohn Marino  * are met:
1086d7f5d3SJohn Marino  *
1186d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1286d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1386d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1486d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in
1586d7f5d3SJohn Marino  *    the documentation and/or other materials provided with the
1686d7f5d3SJohn Marino  *    distribution.
1786d7f5d3SJohn Marino  * 3. Neither the name of the <ORGANIZATION> nor the names of its
1886d7f5d3SJohn Marino  *    contributors may be used to endorse or promote products derived
1986d7f5d3SJohn Marino  *    from this software without specific prior written permission.
2086d7f5d3SJohn Marino  *
2186d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2286d7f5d3SJohn Marino  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2386d7f5d3SJohn Marino  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2486d7f5d3SJohn Marino  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2586d7f5d3SJohn Marino  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2686d7f5d3SJohn Marino  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2786d7f5d3SJohn Marino  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2886d7f5d3SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2986d7f5d3SJohn Marino  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3086d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3186d7f5d3SJohn Marino  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3286d7f5d3SJohn Marino  * POSSIBILITY OF SUCH DAMAGE.
3386d7f5d3SJohn Marino  *
3486d7f5d3SJohn Marino  * $FreeBSD: src/sys/dev/tws/tws_cam.c,v 1.3 2007/05/09 04:16:32 mrangana Exp $
3586d7f5d3SJohn Marino  */
3686d7f5d3SJohn Marino 
3786d7f5d3SJohn Marino #include <dev/raid/tws/tws.h>
3886d7f5d3SJohn Marino #include <dev/raid/tws/tws_hdm.h>
3986d7f5d3SJohn Marino #include <dev/raid/tws/tws_services.h>
4086d7f5d3SJohn Marino #include <sys/time.h>
4186d7f5d3SJohn Marino 
4286d7f5d3SJohn Marino void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
4386d7f5d3SJohn Marino                                 u_int8_t q_type );
4486d7f5d3SJohn Marino struct tws_request * tws_q_remove_request(struct tws_softc *sc,
4586d7f5d3SJohn Marino                                 struct tws_request *req, u_int8_t q_type );
4686d7f5d3SJohn Marino struct tws_request *tws_q_remove_head(struct tws_softc *sc, u_int8_t q_type );
4786d7f5d3SJohn Marino void tws_q_insert_head(struct tws_softc *sc, struct tws_request *req,
4886d7f5d3SJohn Marino                                 u_int8_t q_type );
4986d7f5d3SJohn Marino struct tws_request * tws_q_remove_tail(struct tws_softc *sc, u_int8_t q_type );
5086d7f5d3SJohn Marino void tws_print_stats(void *arg);
5186d7f5d3SJohn Marino 
5286d7f5d3SJohn Marino struct tws_sense *tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa);
5386d7f5d3SJohn Marino 
5486d7f5d3SJohn Marino 
5586d7f5d3SJohn Marino 
5686d7f5d3SJohn Marino struct error_desc array[] = {
5786d7f5d3SJohn Marino     { "Cannot add sysctl tree node", 0x2000, ERROR,
5886d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
5986d7f5d3SJohn Marino     { "Register window not available", 0x2001, ERROR,
6086d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
6186d7f5d3SJohn Marino     { "Can't allocate register window", 0x2002, ERROR,
6286d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
6386d7f5d3SJohn Marino     { "Can't allocate interrupt", 0x2003, ERROR,
6486d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
6586d7f5d3SJohn Marino     { "Can't set up interrupt", 0x2004, ERROR,
6686d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
6786d7f5d3SJohn Marino     { "Couldn't intialize CAM", 0x2007, ERROR,
6886d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
6986d7f5d3SJohn Marino     { "Couldn't create SIM device queue", 0x2100, ENOMEM,
7086d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
7186d7f5d3SJohn Marino     { "Unable to  create SIM entry", 0x2101, ENOMEM,
7286d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
7386d7f5d3SJohn Marino     { "Unable to  register the bus", 0x2102, ENXIO,
7486d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
7586d7f5d3SJohn Marino     { "Unable to  create the path", 0x2103, ENXIO,
7686d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
7786d7f5d3SJohn Marino     { "Bus scan request to CAM failed", 0x2104, ENXIO,
7886d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
7986d7f5d3SJohn Marino     { "Unable to intialize the driver", 0x2008, ENXIO,
8086d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
8186d7f5d3SJohn Marino     { "Unable to intialize the controller", 0x2009, ENXIO,
8286d7f5d3SJohn Marino        "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" },
8386d7f5d3SJohn Marino };
8486d7f5d3SJohn Marino 
8586d7f5d3SJohn 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)8686d7f5d3SJohn Marino tws_trace(const char *file, const char *fun, int linenum,
8786d7f5d3SJohn Marino           struct tws_softc *sc, char *desc, u_int64_t val1, u_int64_t val2)
8886d7f5d3SJohn Marino {
8986d7f5d3SJohn Marino 
9086d7f5d3SJohn Marino 
9186d7f5d3SJohn Marino     struct tws_trace_rec *rec = (struct tws_trace_rec *)sc->trace_q.q;
9286d7f5d3SJohn Marino     volatile u_int16_t head, tail;
9386d7f5d3SJohn Marino     char fmt[256];
9486d7f5d3SJohn Marino 
9586d7f5d3SJohn Marino     head = sc->trace_q.head;
9686d7f5d3SJohn Marino     tail = sc->trace_q.tail;
9786d7f5d3SJohn Marino /*
9886d7f5d3SJohn Marino     getnanotime(&rec[tail].ts);
9986d7f5d3SJohn Marino */
10086d7f5d3SJohn Marino     strncpy(rec[tail].fname, file, TWS_TRACE_FNAME_LEN);
10186d7f5d3SJohn Marino     strncpy(rec[tail].func, fun, TWS_TRACE_FUNC_LEN);
10286d7f5d3SJohn Marino     rec[tail].linenum = linenum;
10386d7f5d3SJohn Marino     strncpy(rec[tail].desc, desc, TWS_TRACE_DESC_LEN);
10486d7f5d3SJohn Marino     rec[tail].val1 = val1;
10586d7f5d3SJohn Marino     rec[tail].val2 = val2;
10686d7f5d3SJohn Marino 
10786d7f5d3SJohn Marino     tail = (tail+1) % sc->trace_q.depth;
10886d7f5d3SJohn Marino 
10986d7f5d3SJohn Marino     if ( head == tail ) {
11086d7f5d3SJohn Marino         sc->trace_q.overflow = 1;
11186d7f5d3SJohn Marino         sc->trace_q.head = (head+1) % sc->trace_q.depth;
11286d7f5d3SJohn Marino     }
11386d7f5d3SJohn Marino     sc->trace_q.tail = tail;
11486d7f5d3SJohn Marino 
11586d7f5d3SJohn Marino /*
11686d7f5d3SJohn Marino     tws_circular_q_insert(sc, &sc->trace_q,
11786d7f5d3SJohn Marino                               &rec, sizeof(struct tws_trace_rec));
11886d7f5d3SJohn Marino */
11986d7f5d3SJohn Marino     if ( sc->is64bit )
12086d7f5d3SJohn Marino         strcpy(fmt, "%05d:%s::%s :%s: 0x%016lx : 0x%016lx \n");
12186d7f5d3SJohn Marino     else
12286d7f5d3SJohn Marino         strcpy(fmt, "%05d:%s::%s :%s: 0x%016llx : 0x%016llx \n");
12386d7f5d3SJohn Marino 
12486d7f5d3SJohn Marino /*
12586d7f5d3SJohn Marino     kprintf("%05d:%s::%s :%s: 0x%016llx : 0x%016llx \n",
12686d7f5d3SJohn Marino             linenum, file, fun, desc, val1, val2);
12786d7f5d3SJohn Marino */
12886d7f5d3SJohn Marino     kprintf(fmt, linenum, file, fun, desc, val1, val2);
12986d7f5d3SJohn Marino }
13086d7f5d3SJohn Marino 
13186d7f5d3SJohn Marino void
tws_log(struct tws_softc * sc,int index)13286d7f5d3SJohn Marino tws_log(struct tws_softc *sc, int index)
13386d7f5d3SJohn Marino {
13486d7f5d3SJohn Marino     device_printf((sc)->tws_dev, array[index].fmt,
13586d7f5d3SJohn Marino                     array[index].error_str,
13686d7f5d3SJohn Marino                     array[index].error_code,
13786d7f5d3SJohn Marino                     array[index].severity_level,
13886d7f5d3SJohn Marino                     array[index].desc );
13986d7f5d3SJohn Marino }
14086d7f5d3SJohn Marino 
14186d7f5d3SJohn Marino /* ----------- swap functions ----------- */
14286d7f5d3SJohn Marino 
14386d7f5d3SJohn Marino 
14486d7f5d3SJohn Marino u_int16_t
tws_swap16(u_int16_t val)14586d7f5d3SJohn Marino tws_swap16(u_int16_t val)
14686d7f5d3SJohn Marino {
14786d7f5d3SJohn Marino     return((val << 8) | (val >> 8));
14886d7f5d3SJohn Marino }
14986d7f5d3SJohn Marino 
15086d7f5d3SJohn Marino u_int32_t
tws_swap32(u_int32_t val)15186d7f5d3SJohn Marino tws_swap32(u_int32_t val)
15286d7f5d3SJohn Marino {
15386d7f5d3SJohn Marino     return(((val << 24) | ((val << 8) & (0xFF0000)) |
15486d7f5d3SJohn Marino            ((val >> 8) & (0xFF00)) | (val >> 24)));
15586d7f5d3SJohn Marino }
15686d7f5d3SJohn Marino 
15786d7f5d3SJohn Marino 
15886d7f5d3SJohn Marino u_int64_t
tws_swap64(u_int64_t val)15986d7f5d3SJohn Marino tws_swap64(u_int64_t val)
16086d7f5d3SJohn Marino {
16186d7f5d3SJohn Marino     return((((u_int64_t)(tws_swap32(((u_int32_t *)(&(val)))[1]))) << 32) |
16286d7f5d3SJohn Marino            ((u_int32_t)(tws_swap32(((u_int32_t *)(&(val)))[0]))));
16386d7f5d3SJohn Marino }
16486d7f5d3SJohn Marino 
16586d7f5d3SJohn Marino 
16686d7f5d3SJohn Marino /* ----------- reg access ----------- */
16786d7f5d3SJohn Marino 
16886d7f5d3SJohn Marino 
16986d7f5d3SJohn Marino void
tws_write_reg(struct tws_softc * sc,int offset,u_int32_t value,int size)17086d7f5d3SJohn Marino tws_write_reg(struct tws_softc *sc, int offset,
17186d7f5d3SJohn Marino                   u_int32_t value, int size)
17286d7f5d3SJohn Marino {
17386d7f5d3SJohn Marino     bus_space_tag_t         bus_tag = sc->bus_tag;
17486d7f5d3SJohn Marino     bus_space_handle_t      bus_handle = sc->bus_handle;
17586d7f5d3SJohn Marino 
17686d7f5d3SJohn Marino     if (size == 4)
17786d7f5d3SJohn Marino         bus_space_write_4(bus_tag, bus_handle, offset, value);
17886d7f5d3SJohn Marino     else
17986d7f5d3SJohn Marino         if (size == 2)
18086d7f5d3SJohn Marino             bus_space_write_2(bus_tag, bus_handle, offset,
18186d7f5d3SJohn Marino                                      (u_int16_t)value);
18286d7f5d3SJohn Marino         else
18386d7f5d3SJohn Marino             bus_space_write_1(bus_tag, bus_handle, offset, (u_int8_t)value);
18486d7f5d3SJohn Marino }
18586d7f5d3SJohn Marino 
18686d7f5d3SJohn Marino u_int32_t
tws_read_reg(struct tws_softc * sc,int offset,int size)18786d7f5d3SJohn Marino tws_read_reg(struct tws_softc *sc, int offset, int size)
18886d7f5d3SJohn Marino {
18986d7f5d3SJohn Marino     bus_space_tag_t bus_tag = sc->bus_tag;
19086d7f5d3SJohn Marino     bus_space_handle_t bus_handle = sc->bus_handle;
19186d7f5d3SJohn Marino 
19286d7f5d3SJohn Marino     if (size == 4)
19386d7f5d3SJohn Marino         return((u_int32_t)bus_space_read_4(bus_tag, bus_handle, offset));
19486d7f5d3SJohn Marino     else if (size == 2)
19586d7f5d3SJohn Marino             return((u_int32_t)bus_space_read_2(bus_tag, bus_handle, offset));
19686d7f5d3SJohn Marino          else
19786d7f5d3SJohn Marino             return((u_int32_t)bus_space_read_1(bus_tag, bus_handle, offset));
19886d7f5d3SJohn Marino }
19986d7f5d3SJohn Marino 
20086d7f5d3SJohn Marino /* --------------------- Q service --------------------- */
20186d7f5d3SJohn Marino 
20286d7f5d3SJohn Marino /*
20386d7f5d3SJohn Marino  * intialize q  pointers with null.
20486d7f5d3SJohn Marino  */
20586d7f5d3SJohn Marino void
tws_init_qs(struct tws_softc * sc)20686d7f5d3SJohn Marino tws_init_qs(struct tws_softc *sc)
20786d7f5d3SJohn Marino {
20886d7f5d3SJohn Marino 
20986d7f5d3SJohn Marino     lockmgr(&sc->q_lock, LK_EXCLUSIVE);
21086d7f5d3SJohn Marino     for(int i=0;i<TWS_MAX_QS;i++) {
21186d7f5d3SJohn Marino         sc->q_head[i] = NULL;
21286d7f5d3SJohn Marino         sc->q_tail[i] = NULL;
21386d7f5d3SJohn Marino     }
21486d7f5d3SJohn Marino     lockmgr(&sc->q_lock, LK_RELEASE);
21586d7f5d3SJohn Marino 
21686d7f5d3SJohn Marino }
21786d7f5d3SJohn Marino 
21886d7f5d3SJohn Marino /* called with lock held */
21986d7f5d3SJohn Marino static void
tws_insert2_empty_q(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)22086d7f5d3SJohn Marino tws_insert2_empty_q(struct tws_softc *sc, struct tws_request *req,
22186d7f5d3SJohn Marino                                 u_int8_t q_type )
22286d7f5d3SJohn Marino {
22386d7f5d3SJohn Marino 
22486d7f5d3SJohn Marino     KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
22586d7f5d3SJohn Marino     req->next = req->prev = NULL;
22686d7f5d3SJohn Marino     sc->q_head[q_type] = sc->q_tail[q_type] = req;
22786d7f5d3SJohn Marino 
22886d7f5d3SJohn Marino }
22986d7f5d3SJohn Marino 
23086d7f5d3SJohn Marino /* called with lock held */
23186d7f5d3SJohn Marino void
tws_q_insert_head(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)23286d7f5d3SJohn Marino tws_q_insert_head(struct tws_softc *sc, struct tws_request *req,
23386d7f5d3SJohn Marino                                 u_int8_t q_type )
23486d7f5d3SJohn Marino {
23586d7f5d3SJohn Marino 
23686d7f5d3SJohn Marino     KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
23786d7f5d3SJohn Marino     if ( sc->q_head[q_type] == NULL ) {
23886d7f5d3SJohn Marino         tws_insert2_empty_q(sc, req, q_type);
23986d7f5d3SJohn Marino     } else {
24086d7f5d3SJohn Marino         req->next = sc->q_head[q_type];
24186d7f5d3SJohn Marino         req->prev = NULL;
24286d7f5d3SJohn Marino         sc->q_head[q_type]->prev = req;
24386d7f5d3SJohn Marino         sc->q_head[q_type] = req;
24486d7f5d3SJohn Marino     }
24586d7f5d3SJohn Marino 
24686d7f5d3SJohn Marino }
24786d7f5d3SJohn Marino 
24886d7f5d3SJohn Marino /* called with lock held */
24986d7f5d3SJohn Marino void
tws_q_insert_tail(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)25086d7f5d3SJohn Marino tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
25186d7f5d3SJohn Marino                                 u_int8_t q_type )
25286d7f5d3SJohn Marino {
25386d7f5d3SJohn Marino 
25486d7f5d3SJohn Marino     KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
25586d7f5d3SJohn Marino     if ( sc->q_tail[q_type] == NULL ) {
25686d7f5d3SJohn Marino         tws_insert2_empty_q(sc, req, q_type);
25786d7f5d3SJohn Marino     } else {
25886d7f5d3SJohn Marino         req->prev = sc->q_tail[q_type];
25986d7f5d3SJohn Marino         req->next = NULL;
26086d7f5d3SJohn Marino         sc->q_tail[q_type]->next = req;
26186d7f5d3SJohn Marino         sc->q_tail[q_type] = req;
26286d7f5d3SJohn Marino     }
26386d7f5d3SJohn Marino 
26486d7f5d3SJohn Marino }
26586d7f5d3SJohn Marino 
26686d7f5d3SJohn Marino /* called with lock held */
26786d7f5d3SJohn Marino struct tws_request *
tws_q_remove_head(struct tws_softc * sc,u_int8_t q_type)26886d7f5d3SJohn Marino tws_q_remove_head(struct tws_softc *sc, u_int8_t q_type )
26986d7f5d3SJohn Marino {
27086d7f5d3SJohn Marino 
27186d7f5d3SJohn Marino     struct tws_request *r;
27286d7f5d3SJohn Marino 
27386d7f5d3SJohn Marino     KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
27486d7f5d3SJohn Marino     r = sc->q_head[q_type];
27586d7f5d3SJohn Marino     if ( !r )
27686d7f5d3SJohn Marino         return(NULL);
27786d7f5d3SJohn Marino     if ( r->next == NULL &&  r->prev == NULL ) {
27886d7f5d3SJohn Marino         /* last element  */
27986d7f5d3SJohn Marino         sc->q_head[q_type] = sc->q_tail[q_type] = NULL;
28086d7f5d3SJohn Marino     } else {
28186d7f5d3SJohn Marino         sc->q_head[q_type] = r->next;
28286d7f5d3SJohn Marino         r->next->prev = NULL;
28386d7f5d3SJohn Marino         r->next = NULL;
28486d7f5d3SJohn Marino         r->prev = NULL;
28586d7f5d3SJohn Marino     }
28686d7f5d3SJohn Marino     return(r);
28786d7f5d3SJohn Marino }
28886d7f5d3SJohn Marino 
28986d7f5d3SJohn Marino /* called with lock held */
29086d7f5d3SJohn Marino struct tws_request *
tws_q_remove_tail(struct tws_softc * sc,u_int8_t q_type)29186d7f5d3SJohn Marino tws_q_remove_tail(struct tws_softc *sc, u_int8_t q_type )
29286d7f5d3SJohn Marino {
29386d7f5d3SJohn Marino 
29486d7f5d3SJohn Marino     struct tws_request *r;
29586d7f5d3SJohn Marino 
29686d7f5d3SJohn Marino     KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
29786d7f5d3SJohn Marino     r = sc->q_tail[q_type];
29886d7f5d3SJohn Marino     if ( !r )
29986d7f5d3SJohn Marino         return(NULL);
30086d7f5d3SJohn Marino     if ( r->next == NULL &&  r->prev == NULL ) {
30186d7f5d3SJohn Marino         /* last element  */
30286d7f5d3SJohn Marino         sc->q_head[q_type] = sc->q_tail[q_type] = NULL;
30386d7f5d3SJohn Marino     } else {
30486d7f5d3SJohn Marino         sc->q_tail[q_type] = r->prev;
30586d7f5d3SJohn Marino         r->prev->next = NULL;
30686d7f5d3SJohn Marino         r->next = NULL;
30786d7f5d3SJohn Marino         r->prev = NULL;
30886d7f5d3SJohn Marino     }
30986d7f5d3SJohn Marino     return(r);
31086d7f5d3SJohn Marino }
31186d7f5d3SJohn Marino 
31286d7f5d3SJohn Marino /* returns removed request if successful. return NULL otherwise */
31386d7f5d3SJohn Marino /* called with lock held */
31486d7f5d3SJohn Marino struct tws_request *
tws_q_remove_request(struct tws_softc * sc,struct tws_request * req,u_int8_t q_type)31586d7f5d3SJohn Marino tws_q_remove_request(struct tws_softc *sc, struct tws_request *req,
31686d7f5d3SJohn Marino                                  u_int8_t q_type )
31786d7f5d3SJohn Marino {
31886d7f5d3SJohn Marino 
31986d7f5d3SJohn Marino     struct tws_request *r;
32086d7f5d3SJohn Marino 
32186d7f5d3SJohn Marino     KKASSERT(lockstatus(&sc->q_lock, curthread) != 0);
32286d7f5d3SJohn Marino     if ( req == NULL ) {
32386d7f5d3SJohn Marino         TWS_TRACE_DEBUG(sc, "null req", 0, q_type);
32486d7f5d3SJohn Marino         return(NULL);
32586d7f5d3SJohn Marino     }
32686d7f5d3SJohn Marino 
32786d7f5d3SJohn Marino     if ( req == sc->q_head[q_type] )
32886d7f5d3SJohn Marino         return(tws_q_remove_head(sc, q_type));
32986d7f5d3SJohn Marino     if ( req == sc->q_tail[q_type] )
33086d7f5d3SJohn Marino         return(tws_q_remove_tail(sc, q_type));
33186d7f5d3SJohn Marino 
33286d7f5d3SJohn Marino 
33386d7f5d3SJohn Marino     /* The given node is not at head or tail.
33486d7f5d3SJohn Marino      * It's in the middle and there are more than
33586d7f5d3SJohn Marino      * 2 elements on the q.
33686d7f5d3SJohn Marino      */
33786d7f5d3SJohn Marino 
33886d7f5d3SJohn Marino     if ( req->next == NULL || req->prev == NULL ) {
33986d7f5d3SJohn Marino         TWS_TRACE_DEBUG(sc, "invalid req", 0, q_type);
34086d7f5d3SJohn Marino         return(NULL);
34186d7f5d3SJohn Marino     }
34286d7f5d3SJohn Marino 
34386d7f5d3SJohn Marino /* debug only */
34486d7f5d3SJohn Marino     r = sc->q_head[q_type];
34586d7f5d3SJohn Marino     while ( r ) {
34686d7f5d3SJohn Marino         if ( req == r )
34786d7f5d3SJohn Marino             break;
34886d7f5d3SJohn Marino         r = r->next;
34986d7f5d3SJohn Marino     }
35086d7f5d3SJohn Marino 
35186d7f5d3SJohn Marino     if ( !r ) {
35286d7f5d3SJohn Marino         TWS_TRACE_DEBUG(sc, "req not in q", 0, req->request_id);
35386d7f5d3SJohn Marino         return(NULL);
35486d7f5d3SJohn Marino     }
35586d7f5d3SJohn Marino /* debug end */
35686d7f5d3SJohn Marino 
35786d7f5d3SJohn Marino     req->prev->next = r->next;
35886d7f5d3SJohn Marino     req->next->prev = r->prev;
35986d7f5d3SJohn Marino     req->next = NULL;
36086d7f5d3SJohn Marino     req->prev = NULL;
36186d7f5d3SJohn Marino     return(req);
36286d7f5d3SJohn Marino }
36386d7f5d3SJohn Marino 
36486d7f5d3SJohn Marino struct tws_sense *
tws_find_sense_from_mfa(struct tws_softc * sc,u_int64_t mfa)36586d7f5d3SJohn Marino tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa)
36686d7f5d3SJohn Marino {
36786d7f5d3SJohn Marino     struct tws_sense *s;
36886d7f5d3SJohn Marino     int i;
36986d7f5d3SJohn Marino     TWS_TRACE_DEBUG(sc, "entry",sc,mfa);
37086d7f5d3SJohn Marino 
37186d7f5d3SJohn Marino     i = (mfa - sc->dma_mem_phys) / sizeof(struct tws_command_packet);
37286d7f5d3SJohn Marino     if ( i>= 0 && i<tws_queue_depth) {
37386d7f5d3SJohn Marino         s = &sc->sense_bufs[i];
37486d7f5d3SJohn Marino         if ( mfa == s->hdr_pkt_phy )
37586d7f5d3SJohn Marino             return(s);
37686d7f5d3SJohn Marino     }
37786d7f5d3SJohn Marino 
37886d7f5d3SJohn Marino     TWS_TRACE_DEBUG(sc, "return null",0,mfa);
37986d7f5d3SJohn Marino     return(NULL);
38086d7f5d3SJohn Marino 
38186d7f5d3SJohn Marino }
38286d7f5d3SJohn Marino 
38386d7f5d3SJohn Marino /* --------------------- Q service end --------------------- */
38486d7f5d3SJohn Marino /* --------------------- misc service start --------------------- */
38586d7f5d3SJohn Marino 
38686d7f5d3SJohn Marino 
38786d7f5d3SJohn Marino void
tws_print_stats(void * arg)38886d7f5d3SJohn Marino tws_print_stats(void *arg)
38986d7f5d3SJohn Marino {
39086d7f5d3SJohn Marino 
39186d7f5d3SJohn Marino     struct tws_softc *sc = (struct tws_softc *)arg;
39286d7f5d3SJohn Marino 
39386d7f5d3SJohn Marino     TWS_TRACE(sc, "reqs(in, out)", sc->stats.reqs_in, sc->stats.reqs_out);
39486d7f5d3SJohn Marino     TWS_TRACE(sc, "reqs(err, intrs)", sc->stats.reqs_errored
39586d7f5d3SJohn Marino                                       , sc->stats.num_intrs);
39686d7f5d3SJohn Marino     TWS_TRACE(sc, "reqs(ioctls, scsi)", sc->stats.ioctls
39786d7f5d3SJohn Marino                                       , sc->stats.scsi_ios);
39886d7f5d3SJohn Marino     callout_reset(&sc->print_stats_handle, 300*hz, tws_print_stats, sc);
39986d7f5d3SJohn Marino 
40086d7f5d3SJohn Marino }
40186d7f5d3SJohn Marino /* --------------------- misc service end --------------------- */
402