1226026Sdelphij/*
2226026Sdelphij * Copyright (c) 2010, LSI Corp.
3226026Sdelphij * All rights reserved.
4226026Sdelphij * Author : Manjunath Ranganathaiah
5226026Sdelphij * Support: freebsdraid@lsi.com
6226026Sdelphij *
7226026Sdelphij * Redistribution and use in source and binary forms, with or without
8226026Sdelphij * modification, are permitted provided that the following conditions
9226026Sdelphij * are met:
10226026Sdelphij *
11226026Sdelphij * 1. Redistributions of source code must retain the above copyright
12226026Sdelphij *    notice, this list of conditions and the following disclaimer.
13226026Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
14226026Sdelphij *    notice, this list of conditions and the following disclaimer in
15226026Sdelphij *    the documentation and/or other materials provided with the
16226026Sdelphij *    distribution.
17226026Sdelphij * 3. Neither the name of the <ORGANIZATION> nor the names of its
18226026Sdelphij *    contributors may be used to endorse or promote products derived
19226026Sdelphij *    from this software without specific prior written permission.
20226026Sdelphij *
21226026Sdelphij * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22226026Sdelphij * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23226026Sdelphij * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24226026Sdelphij * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25226026Sdelphij * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26226026Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27226026Sdelphij * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28226026Sdelphij * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29226026Sdelphij * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30226026Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31226026Sdelphij * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32226026Sdelphij * POSSIBILITY OF SUCH DAMAGE.
33226026Sdelphij *
34226026Sdelphij * $FreeBSD: releng/11.0/sys/dev/tws/tws_hdm.c 298955 2016-05-03 03:41:25Z pfg $
35226026Sdelphij */
36226026Sdelphij
37226026Sdelphij
38226026Sdelphij#include <dev/tws/tws.h>
39226026Sdelphij#include <dev/tws/tws_services.h>
40226026Sdelphij#include <dev/tws/tws_hdm.h>
41226026Sdelphij
42226026Sdelphij
43226026Sdelphijint tws_use_32bit_sgls=0;
44226026Sdelphijextern u_int64_t mfa_base;
45226026Sdelphijextern struct tws_request *tws_get_request(struct tws_softc *sc,
46226026Sdelphij                                           u_int16_t type);
47226026Sdelphijextern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
48226026Sdelphij                                u_int8_t q_type );
49226026Sdelphijextern struct tws_request * tws_q_remove_request(struct tws_softc *sc,
50226026Sdelphij                                   struct tws_request *req, u_int8_t q_type );
51226026Sdelphij
52226026Sdelphijextern void tws_cmd_complete(struct tws_request *req);
53226026Sdelphijextern void tws_print_stats(void *arg);
54226026Sdelphijextern int tws_send_scsi_cmd(struct tws_softc *sc, int cmd);
55226026Sdelphijextern int tws_set_param(struct tws_softc *sc, u_int32_t table_id,
56226026Sdelphij           u_int32_t param_id, u_int32_t param_size, void *data);
57226026Sdelphijextern int tws_get_param(struct tws_softc *sc, u_int32_t table_id,
58226026Sdelphij            u_int32_t param_id, u_int32_t param_size, void *data);
59226026Sdelphijextern void tws_reset(void *arg);
60226026Sdelphij
61226026Sdelphijint tws_init_connect(struct tws_softc *sc, u_int16_t mc);
62226026Sdelphijint tws_init_ctlr(struct tws_softc *sc);
63226026Sdelphijint tws_submit_command(struct tws_softc *sc, struct tws_request *req);
64226026Sdelphijvoid tws_nop_cmd(void *arg);
65226026Sdelphiju_int16_t tws_poll4_response(struct tws_softc *sc, u_int64_t *mfa);
66226026Sdelphijboolean tws_get_response(struct tws_softc *sc, u_int16_t *req_id,
67226026Sdelphij                                               u_int64_t *mfa);
68226026Sdelphijboolean tws_ctlr_ready(struct tws_softc *sc);
69226026Sdelphijvoid tws_turn_on_interrupts(struct tws_softc *sc);
70226026Sdelphijvoid tws_turn_off_interrupts(struct tws_softc *sc);
71226026Sdelphijboolean tws_ctlr_reset(struct tws_softc *sc);
72226026Sdelphijvoid tws_assert_soft_reset(struct tws_softc *sc);
73226026Sdelphij
74226026Sdelphijint tws_send_generic_cmd(struct tws_softc *sc, u_int8_t opcode);
75226026Sdelphijvoid tws_fetch_aen(void *arg);
76226026Sdelphijvoid tws_disable_db_intr(struct tws_softc *sc);
77226026Sdelphijvoid tws_enable_db_intr(struct tws_softc *sc);
78226026Sdelphijvoid tws_aen_synctime_with_host(struct tws_softc *sc);
79226026Sdelphijvoid tws_init_obfl_q(struct tws_softc *sc);
80226026Sdelphijvoid tws_display_ctlr_info(struct tws_softc *sc);
81226026Sdelphij
82226026Sdelphijint
83226026Sdelphijtws_init_ctlr(struct tws_softc *sc)
84226026Sdelphij{
85226026Sdelphij    u_int64_t reg;
86226026Sdelphij    u_int32_t regh, regl;
87226026Sdelphij
88226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", sc, sc->is64bit);
89226026Sdelphij    sc->obfl_q_overrun = false;
90226026Sdelphij    if ( tws_init_connect(sc, tws_queue_depth) )
91226026Sdelphij    {
92226026Sdelphij        TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit);
93226026Sdelphij        return(FAILURE);
94226026Sdelphij
95226026Sdelphij    }
96226026Sdelphij
97226026Sdelphij
98226026Sdelphij    while( 1 ) {
99226026Sdelphij        regh = tws_read_reg(sc, TWS_I2O0_IOPOBQPH, 4);
100226026Sdelphij        regl = tws_read_reg(sc, TWS_I2O0_IOPOBQPL, 4);
101226026Sdelphij        reg = (((u_int64_t)regh) << 32) | regl;
102247551Skevlo        TWS_TRACE_DEBUG(sc, "host outbound cleanup",reg, regl);
103226026Sdelphij        if ( regh == TWS_FIFO_EMPTY32 )
104226026Sdelphij            break;
105226026Sdelphij    }
106226026Sdelphij
107226026Sdelphij    tws_init_obfl_q(sc);
108226026Sdelphij    tws_display_ctlr_info(sc);
109226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4);
110226026Sdelphij    tws_turn_on_interrupts(sc);
111226026Sdelphij    return(SUCCESS);
112226026Sdelphij}
113226026Sdelphij
114226026Sdelphijvoid
115226026Sdelphijtws_init_obfl_q(struct tws_softc *sc)
116226026Sdelphij{
117226026Sdelphij    int i=0;
118226026Sdelphij    u_int64_t paddr;
119226026Sdelphij    u_int32_t paddrh, paddrl, status;
120226026Sdelphij
121226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, sc->obfl_q_overrun);
122226026Sdelphij
123226026Sdelphij    while ( i < tws_queue_depth ) {
124226026Sdelphij        paddr = sc->sense_bufs[i].hdr_pkt_phy;
125226026Sdelphij        paddrh = (u_int32_t)( paddr>>32);
126226026Sdelphij        paddrl = (u_int32_t) paddr;
127226026Sdelphij        tws_write_reg(sc, TWS_I2O0_HOBQPH, paddrh, 4);
128226026Sdelphij        tws_write_reg(sc, TWS_I2O0_HOBQPL, paddrl, 4);
129226026Sdelphij
130226026Sdelphij        status = tws_read_reg(sc, TWS_I2O0_STATUS, 4);
131226026Sdelphij        if ( status & TWS_BIT13 ) {
132226026Sdelphij            device_printf(sc->tws_dev,  "OBFL Overrun\n");
133226026Sdelphij            sc->obfl_q_overrun = true;
134226026Sdelphij            break;
135226026Sdelphij        }
136226026Sdelphij        i++;
137226026Sdelphij    }
138226026Sdelphij
139226026Sdelphij    if ( i == tws_queue_depth )
140226026Sdelphij        sc->obfl_q_overrun = false;
141226026Sdelphij}
142226026Sdelphij
143226026Sdelphijint
144226026Sdelphijtws_init_connect(struct tws_softc *sc, u_int16_t mcreadits )
145226026Sdelphij{
146226026Sdelphij    struct tws_request *req;
147226026Sdelphij    struct tws_cmd_init_connect *initc;
148226026Sdelphij    u_int16_t reqid;
149226026Sdelphij    u_int64_t mfa;
150226026Sdelphij
151226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, mcreadits);
152226026Sdelphij#if       0
153226026Sdelphij    req = tws_get_request(sc, TWS_REQ_TYPE_INTERNAL_CMD);
154226026Sdelphij#else  // 0
155226026Sdelphij    req = &sc->reqs[TWS_REQ_TYPE_INTERNAL_CMD];
156226026Sdelphij    bzero(&req->cmd_pkt->cmd, sizeof(struct tws_command_apache));
157226026Sdelphij    req->data = NULL;
158226026Sdelphij    req->length = 0;
159226026Sdelphij    req->type = TWS_REQ_TYPE_INTERNAL_CMD;
160226026Sdelphij    req->flags = TWS_DIR_UNKNOWN;
161226026Sdelphij    req->error_code = TWS_REQ_RET_INVALID;
162226026Sdelphij    req->cb = NULL;
163226026Sdelphij    req->ccb_ptr = NULL;
164272000Sjhb    callout_stop(&req->timeout);
165226026Sdelphij    req->next = req->prev = NULL;
166226026Sdelphij    req->state = TWS_REQ_STATE_BUSY;
167226026Sdelphij#endif // 0
168226026Sdelphij
169226026Sdelphij    if ( req == NULL ) {
170226026Sdelphij        TWS_TRACE_DEBUG(sc, "no requests", 0, 0);
171226026Sdelphij//      device_printf(sc->tws_dev,  "No requests for initConnect\n");
172226026Sdelphij        return(FAILURE);
173226026Sdelphij    }
174226026Sdelphij
175226026Sdelphij    tws_swap16(0xbeef); /* just for test */
176226026Sdelphij    tws_swap32(0xdeadbeef); /* just for test */
177226026Sdelphij    tws_swap64(0xdeadbeef); /* just for test */
178226026Sdelphij    initc = &(req->cmd_pkt->cmd.pkt_g.init_connect);
179226026Sdelphij    /* req->cmd_pkt->hdr.header_desc.size_header = 128; */
180226026Sdelphij
181226026Sdelphij    initc->res1__opcode =
182226026Sdelphij              BUILD_RES__OPCODE(0, TWS_FW_CMD_INIT_CONNECTION);
183226026Sdelphij    initc->size = 6;
184226026Sdelphij    initc->request_id = req->request_id;
185226026Sdelphij    initc->message_credits = mcreadits;
186226026Sdelphij    initc->features |= TWS_BIT_EXTEND;
187226026Sdelphij    if ( sc->is64bit && !tws_use_32bit_sgls )
188226026Sdelphij        initc->features |= TWS_64BIT_SG_ADDRESSES;
189226026Sdelphij    /* assuming set features is always on */
190226026Sdelphij
191226026Sdelphij    initc->size = 6;
192226026Sdelphij    initc->fw_srl = sc->cinfo.working_srl = TWS_CURRENT_FW_SRL;
193226026Sdelphij    initc->fw_arch_id = 0;
194226026Sdelphij    initc->fw_branch = sc->cinfo.working_branch = 0;
195226026Sdelphij    initc->fw_build = sc->cinfo.working_build = 0;
196226026Sdelphij
197226026Sdelphij    req->error_code = tws_submit_command(sc, req);
198226026Sdelphij    reqid = tws_poll4_response(sc, &mfa);
199226026Sdelphij    if ( reqid != TWS_INVALID_REQID && reqid == req->request_id ) {
200226026Sdelphij        sc->cinfo.fw_on_ctlr_srl = initc->fw_srl;
201226026Sdelphij        sc->cinfo.fw_on_ctlr_branch = initc->fw_branch;
202226026Sdelphij        sc->cinfo.fw_on_ctlr_build = initc->fw_build;
203226026Sdelphij        sc->stats.reqs_out++;
204226026Sdelphij        req->state = TWS_REQ_STATE_FREE;
205226026Sdelphij    }
206226026Sdelphij    else {
207226026Sdelphij        /*
208226026Sdelphij         * REVISIT::If init connect fails we need to reset the ctlr
209226026Sdelphij         * and try again?
210226026Sdelphij         */
211226026Sdelphij        TWS_TRACE(sc, "unexpected req_id ", reqid, 0);
212226026Sdelphij        TWS_TRACE(sc, "INITCONNECT FAILED", reqid, 0);
213226026Sdelphij        return(FAILURE);
214226026Sdelphij    }
215226026Sdelphij    return(SUCCESS);
216226026Sdelphij}
217226026Sdelphij
218226026Sdelphijvoid
219226026Sdelphijtws_display_ctlr_info(struct tws_softc *sc)
220226026Sdelphij{
221226026Sdelphij
222226026Sdelphij    uint8_t fw_ver[16], bios_ver[16], ctlr_model[16], num_phys=0;
223226026Sdelphij    uint32_t error[4];
224226026Sdelphij
225226026Sdelphij    error[0] = tws_get_param(sc, TWS_PARAM_PHYS_TABLE,
226226026Sdelphij                             TWS_PARAM_CONTROLLER_PHYS_COUNT, 1, &num_phys);
227226026Sdelphij    error[1] = tws_get_param(sc, TWS_PARAM_VERSION_TABLE,
228226026Sdelphij                             TWS_PARAM_VERSION_FW, 16, fw_ver);
229226026Sdelphij    error[2] = tws_get_param(sc, TWS_PARAM_VERSION_TABLE,
230226026Sdelphij                             TWS_PARAM_VERSION_BIOS, 16, bios_ver);
231226026Sdelphij    error[3] = tws_get_param(sc, TWS_PARAM_VERSION_TABLE,
232226026Sdelphij                             TWS_PARAM_CTLR_MODEL, 16, ctlr_model);
233226026Sdelphij
234226026Sdelphij    if ( !error[0] && !error[1] && !error[2] && !error[3] ) {
235226026Sdelphij        device_printf( sc->tws_dev,
236226026Sdelphij        "Controller details: Model %.16s, %d Phys, Firmware %.16s, BIOS %.16s\n",
237226026Sdelphij         ctlr_model, num_phys, fw_ver, bios_ver);
238226026Sdelphij    }
239226026Sdelphij
240226026Sdelphij}
241226026Sdelphij
242226026Sdelphijint
243226026Sdelphijtws_send_generic_cmd(struct tws_softc *sc, u_int8_t opcode)
244226026Sdelphij{
245226026Sdelphij    struct tws_request *req;
246226026Sdelphij    struct tws_cmd_generic *cmd;
247226026Sdelphij
248226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", sc, opcode);
249226026Sdelphij    req = tws_get_request(sc, TWS_REQ_TYPE_INTERNAL_CMD);
250226026Sdelphij
251226026Sdelphij    if ( req == NULL ) {
252226026Sdelphij        TWS_TRACE_DEBUG(sc, "no requests", 0, 0);
253226026Sdelphij        return(FAILURE);
254226026Sdelphij    }
255226026Sdelphij
256226026Sdelphij    cmd = &(req->cmd_pkt->cmd.pkt_g.generic);
257226026Sdelphij    bzero(cmd, sizeof(struct tws_cmd_generic));
258226026Sdelphij    /* req->cmd_pkt->hdr.header_desc.size_header = 128; */
259226026Sdelphij    req->cb = tws_cmd_complete;
260226026Sdelphij
261226026Sdelphij    cmd->sgl_off__opcode = BUILD_RES__OPCODE(0, opcode);
262226026Sdelphij    cmd->size = 2;
263226026Sdelphij    cmd->request_id = req->request_id;
264226026Sdelphij    cmd->host_id__unit = 0;
265226026Sdelphij    cmd->status = 0;
266226026Sdelphij    cmd->flags = 0;
267226026Sdelphij    cmd->count = 0;
268226026Sdelphij
269226026Sdelphij    req->error_code = tws_submit_command(sc, req);
270226026Sdelphij
271226026Sdelphij    return(SUCCESS);
272226026Sdelphij
273226026Sdelphij}
274226026Sdelphij
275226026Sdelphij
276226026Sdelphijint
277226026Sdelphijtws_submit_command(struct tws_softc *sc, struct tws_request *req)
278226026Sdelphij{
279226026Sdelphij    u_int32_t regl, regh;
280226026Sdelphij    u_int64_t mfa=0;
281226026Sdelphij
282226026Sdelphij    /*
283226026Sdelphij     * mfa register  read and write must be in order.
284226026Sdelphij     * Get the io_lock to protect against simultinous
285226026Sdelphij     * passthru calls
286226026Sdelphij     */
287226026Sdelphij    mtx_lock(&sc->io_lock);
288226026Sdelphij
289226026Sdelphij    if ( sc->obfl_q_overrun ) {
290226026Sdelphij        tws_init_obfl_q(sc);
291226026Sdelphij    }
292226026Sdelphij
293226026Sdelphij#ifdef TWS_PULL_MODE_ENABLE
294226026Sdelphij    regh = (u_int32_t)(req->cmd_pkt_phy >> 32);
295226026Sdelphij    /* regh = regh | TWS_MSG_ACC_MASK; */
296226026Sdelphij    mfa = regh;
297226026Sdelphij    mfa = mfa << 32;
298226026Sdelphij    regl = (u_int32_t)req->cmd_pkt_phy;
299226026Sdelphij    regl = regl | TWS_BIT0;
300226026Sdelphij    mfa = mfa | regl;
301226026Sdelphij#else
302226026Sdelphij    regh = tws_read_reg(sc, TWS_I2O0_HIBQPH, 4);
303226026Sdelphij    mfa = regh;
304226026Sdelphij    mfa = mfa << 32;
305226026Sdelphij    regl = tws_read_reg(sc, TWS_I2O0_HIBQPL, 4);
306226026Sdelphij    mfa = mfa | regl;
307226026Sdelphij#endif
308226026Sdelphij
309226026Sdelphij    mtx_unlock(&sc->io_lock);
310226026Sdelphij
311226026Sdelphij    if ( mfa == TWS_FIFO_EMPTY ) {
312226026Sdelphij        TWS_TRACE_DEBUG(sc, "inbound fifo empty", mfa, 0);
313226026Sdelphij
314226026Sdelphij        /*
315298955Spfg         * Generally we should not get here.
316226026Sdelphij         * If the fifo was empty we can't do any thing much
317226026Sdelphij         * retry later
318226026Sdelphij         */
319226026Sdelphij        return(TWS_REQ_RET_PEND_NOMFA);
320226026Sdelphij
321226026Sdelphij    }
322226026Sdelphij
323226026Sdelphij#ifndef TWS_PULL_MODE_ENABLE
324226026Sdelphij    for (int i=mfa; i<(sizeof(struct tws_command_packet)+ mfa -
325226026Sdelphij                            sizeof( struct tws_command_header)); i++) {
326226026Sdelphij
327226026Sdelphij        bus_space_write_1(sc->bus_mfa_tag, sc->bus_mfa_handle,i,
328226026Sdelphij                               ((u_int8_t *)&req->cmd_pkt->cmd)[i-mfa]);
329226026Sdelphij
330226026Sdelphij    }
331226026Sdelphij#endif
332226026Sdelphij
333226026Sdelphij    if ( req->type == TWS_REQ_TYPE_SCSI_IO ) {
334226026Sdelphij        mtx_lock(&sc->q_lock);
335226026Sdelphij        tws_q_insert_tail(sc, req, TWS_BUSY_Q);
336226026Sdelphij        mtx_unlock(&sc->q_lock);
337226026Sdelphij    }
338226026Sdelphij
339226026Sdelphij    /*
340226026Sdelphij     * mfa register  read and write must be in order.
341226026Sdelphij     * Get the io_lock to protect against simultinous
342226026Sdelphij     * passthru calls
343226026Sdelphij     */
344226026Sdelphij    mtx_lock(&sc->io_lock);
345226026Sdelphij
346226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIBQPH, regh, 4);
347226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIBQPL, regl, 4);
348226026Sdelphij
349226026Sdelphij    sc->stats.reqs_in++;
350226026Sdelphij    mtx_unlock(&sc->io_lock);
351226026Sdelphij
352226026Sdelphij    return(TWS_REQ_RET_SUBMIT_SUCCESS);
353226026Sdelphij
354226026Sdelphij}
355226026Sdelphij
356226026Sdelphij/*
357226026Sdelphij * returns true if the respose was available othewise, false.
358226026Sdelphij * In the case of error the arg mfa will contain the address and
359226026Sdelphij * req_id will be TWS_INVALID_REQID
360226026Sdelphij */
361226026Sdelphijboolean
362226026Sdelphijtws_get_response(struct tws_softc *sc, u_int16_t *req_id, u_int64_t *mfa)
363226026Sdelphij{
364226026Sdelphij    u_int64_t out_mfa=0, val=0;
365226026Sdelphij    struct tws_outbound_response out_res;
366226026Sdelphij
367226026Sdelphij    *req_id = TWS_INVALID_REQID;
368226026Sdelphij    out_mfa = (u_int64_t)tws_read_reg(sc, TWS_I2O0_HOBQPH, 4);
369226026Sdelphij
370226026Sdelphij    if ( out_mfa == TWS_FIFO_EMPTY32 ) {
371226026Sdelphij        return(false);
372226026Sdelphij
373226026Sdelphij    }
374226026Sdelphij    out_mfa = out_mfa << 32;
375226026Sdelphij    val = tws_read_reg(sc, TWS_I2O0_HOBQPL, 4);
376226026Sdelphij    out_mfa = out_mfa | val;
377226026Sdelphij
378226026Sdelphij    out_res =  *(struct tws_outbound_response *)&out_mfa;
379226026Sdelphij
380226026Sdelphij    if ( !out_res.not_mfa ) {
381226026Sdelphij        *mfa = out_mfa;
382226026Sdelphij        return(true);
383226026Sdelphij    } else {
384226026Sdelphij        *req_id = out_res.request_id;
385226026Sdelphij    }
386226026Sdelphij
387226026Sdelphij    return(true);
388226026Sdelphij}
389226026Sdelphij
390226026Sdelphij
391226026Sdelphij
392226026Sdelphij
393226026Sdelphiju_int16_t
394226026Sdelphijtws_poll4_response(struct tws_softc *sc, u_int64_t *mfa)
395226026Sdelphij{
396226026Sdelphij    u_int16_t req_id;
397226026Sdelphij    time_t endt;
398226026Sdelphij
399226026Sdelphij    endt = TWS_LOCAL_TIME + TWS_POLL_TIMEOUT;
400226026Sdelphij    do {
401226026Sdelphij        if(tws_get_response(sc, &req_id, mfa)) {
402226026Sdelphij
403226026Sdelphij            if ( req_id == TWS_INVALID_REQID ) {
404226026Sdelphij                TWS_TRACE_DEBUG(sc, "invalid req_id", 0, req_id);
405226026Sdelphij                return(TWS_INVALID_REQID);
406226026Sdelphij            }
407226026Sdelphij            return(req_id);
408226026Sdelphij        }
409226026Sdelphij    } while (TWS_LOCAL_TIME <= endt);
410226026Sdelphij    TWS_TRACE_DEBUG(sc, "poll timeout", 0, 0);
411226026Sdelphij    return(TWS_INVALID_REQID);
412226026Sdelphij}
413226026Sdelphij
414226026Sdelphijboolean
415226026Sdelphijtws_ctlr_ready(struct tws_softc *sc)
416226026Sdelphij{
417226026Sdelphij    u_int32_t reg;
418226026Sdelphij
419226026Sdelphij    reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4);
420226026Sdelphij    if ( reg & TWS_BIT13 )
421226026Sdelphij        return(true);
422226026Sdelphij    else
423226026Sdelphij        return(false);
424226026Sdelphij}
425226026Sdelphij
426226026Sdelphijvoid
427226026Sdelphijtws_turn_on_interrupts(struct tws_softc *sc)
428226026Sdelphij{
429226026Sdelphij
430226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
431298955Spfg    /* turn on response and db interrupt only */
432226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIMASK, TWS_BIT0, 4);
433226026Sdelphij
434226026Sdelphij}
435226026Sdelphij
436226026Sdelphijvoid
437226026Sdelphijtws_turn_off_interrupts(struct tws_softc *sc)
438226026Sdelphij{
439226026Sdelphij
440226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
441226026Sdelphij
442226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIMASK, ~0, 4);
443226026Sdelphij
444226026Sdelphij}
445226026Sdelphij
446226026Sdelphijvoid
447226026Sdelphijtws_disable_db_intr(struct tws_softc *sc)
448226026Sdelphij{
449226026Sdelphij    u_int32_t reg;
450226026Sdelphij
451226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
452226026Sdelphij    reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4);
453226026Sdelphij    reg = reg | TWS_BIT2;
454226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIMASK, reg, 4);
455226026Sdelphij}
456226026Sdelphij
457226026Sdelphijvoid
458226026Sdelphijtws_enable_db_intr(struct tws_softc *sc)
459226026Sdelphij{
460226026Sdelphij    u_int32_t reg;
461226026Sdelphij
462226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
463226026Sdelphij    reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4);
464226026Sdelphij    reg = reg & ~TWS_BIT2;
465226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIMASK, reg, 4);
466226026Sdelphij}
467226026Sdelphij
468226026Sdelphijboolean
469226026Sdelphijtws_ctlr_reset(struct tws_softc *sc)
470226026Sdelphij{
471226026Sdelphij
472226026Sdelphij    u_int32_t reg;
473226026Sdelphij    time_t endt;
474226026Sdelphij    /* int i=0; */
475226026Sdelphij
476226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
477226026Sdelphij
478226026Sdelphij    tws_assert_soft_reset(sc);
479226026Sdelphij
480226026Sdelphij    do {
481226026Sdelphij        reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4);
482226026Sdelphij    } while ( reg & TWS_BIT13 );
483226026Sdelphij
484226026Sdelphij    endt = TWS_LOCAL_TIME + TWS_RESET_TIMEOUT;
485226026Sdelphij    do {
486226026Sdelphij        if(tws_ctlr_ready(sc))
487226026Sdelphij            return(true);
488226026Sdelphij    } while (TWS_LOCAL_TIME <= endt);
489226026Sdelphij    return(false);
490226026Sdelphij
491226026Sdelphij}
492226026Sdelphij
493226026Sdelphijvoid
494226026Sdelphijtws_assert_soft_reset(struct tws_softc *sc)
495226026Sdelphij{
496226026Sdelphij    u_int32_t reg;
497226026Sdelphij
498226026Sdelphij    reg = tws_read_reg(sc, TWS_I2O0_HIBDB, 4);
499226026Sdelphij    TWS_TRACE_DEBUG(sc, "in bound door bell read ", reg, TWS_I2O0_HIBDB);
500226026Sdelphij    tws_write_reg(sc, TWS_I2O0_HIBDB, reg | TWS_BIT8, 4);
501226026Sdelphij
502226026Sdelphij}
503226026Sdelphij
504226026Sdelphijvoid
505226026Sdelphijtws_fetch_aen(void *arg)
506226026Sdelphij{
507226026Sdelphij    struct tws_softc *sc = (struct tws_softc *)arg;
508226026Sdelphij    int error = 0;
509226026Sdelphij
510226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
511226026Sdelphij
512226026Sdelphij    if ((error = tws_send_scsi_cmd(sc, 0x03 /* REQUEST_SENSE */))) {
513226026Sdelphij        TWS_TRACE_DEBUG(sc, "aen fetch send in progress", 0, 0);
514226026Sdelphij    }
515226026Sdelphij}
516226026Sdelphij
517226026Sdelphijvoid
518226026Sdelphijtws_aen_synctime_with_host(struct tws_softc *sc)
519226026Sdelphij{
520226026Sdelphij
521226026Sdelphij    int error;
522226026Sdelphij    long int sync_time;
523226026Sdelphij
524226026Sdelphij    TWS_TRACE_DEBUG(sc, "entry", sc, 0);
525226026Sdelphij
526226026Sdelphij    sync_time = (TWS_LOCAL_TIME - (3 * 86400)) % 604800;
527226026Sdelphij    TWS_TRACE_DEBUG(sc, "sync_time,ts", sync_time, time_second);
528226026Sdelphij    TWS_TRACE_DEBUG(sc, "utc_offset", utc_offset(), 0);
529226026Sdelphij    error = tws_set_param(sc, TWS_PARAM_TIME_TABLE, TWS_PARAM_TIME_SCHED_TIME,
530226026Sdelphij                           4, &sync_time);
531226026Sdelphij    if ( error )
532226026Sdelphij        TWS_TRACE_DEBUG(sc, "set param failed", sync_time, error);
533226026Sdelphij}
534226026Sdelphij
535226026SdelphijTUNABLE_INT("hw.tws.use_32bit_sgls", &tws_use_32bit_sgls);
536