kernel: Remove some unused variables in RAID and disk drivers.
[dragonfly.git] / sys / dev / raid / tws / tws.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2010, LSI Corp.
3 * All rights reserved.
4 * Author : Manjunath Ranganathaiah
5 * Support: freebsdraid@lsi.com
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the <ORGANIZATION> nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $FreeBSD: src/sys/dev/tws/tws.c,v 1.3 2007/05/09 04:16:32 mrangana Exp $
35 */
36
37#include <dev/raid/tws/tws.h>
38#include <dev/raid/tws/tws_services.h>
39#include <dev/raid/tws/tws_hdm.h>
40
41#include <bus/cam/cam.h>
42#include <bus/cam/cam_ccb.h>
43
44MALLOC_DEFINE(M_TWS, "twsbuf", "buffers used by tws driver");
45int tws_queue_depth = TWS_MAX_REQS;
46int tws_enable_msi = 0;
47int tws_enable_msix = 0;
48
49
50
51/* externs */
52extern int tws_cam_attach(struct tws_softc *sc);
53extern void tws_cam_detach(struct tws_softc *sc);
54extern int tws_init_ctlr(struct tws_softc *sc);
55extern boolean tws_ctlr_ready(struct tws_softc *sc);
56extern void tws_turn_off_interrupts(struct tws_softc *sc);
57extern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
58 u_int8_t q_type );
59extern struct tws_request *tws_q_remove_request(struct tws_softc *sc,
60 struct tws_request *req, u_int8_t q_type );
61extern struct tws_request *tws_q_remove_head(struct tws_softc *sc,
62 u_int8_t q_type );
63extern boolean tws_get_response(struct tws_softc *sc, u_int16_t *req_id);
64extern boolean tws_ctlr_reset(struct tws_softc *sc);
65extern void tws_intr(void *arg);
66extern int tws_use_32bit_sgls;
67
68
69struct tws_request *tws_get_request(struct tws_softc *sc, u_int16_t type);
70int tws_init_connect(struct tws_softc *sc, u_int16_t mc);
71void tws_send_event(struct tws_softc *sc, u_int8_t event);
72uint8_t tws_get_state(struct tws_softc *sc);
73void tws_release_request(struct tws_request *req);
74
75
76
77/* Function prototypes */
78static d_open_t tws_open;
79static d_close_t tws_close;
80static d_read_t tws_read;
81static d_write_t tws_write;
82extern d_ioctl_t tws_ioctl;
83
84static int tws_init(struct tws_softc *sc);
85static void tws_dmamap_cmds_load_cbfn(void *arg, bus_dma_segment_t *segs,
86 int nseg, int error);
87
88static int tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size);
89static int tws_init_aen_q(struct tws_softc *sc);
90static int tws_init_trace_q(struct tws_softc *sc);
91static int tws_setup_irq(struct tws_softc *sc);
92static int tws_setup_intr(struct tws_softc *sc, int irqs);
93
94
95/* Character device entry points */
96
97static struct dev_ops tws_ops = {
98 { "tws", 0, 0 },
99 .d_open = tws_open,
100 .d_close = tws_close,
101 .d_read = tws_read,
102 .d_write = tws_write,
103 .d_ioctl = tws_ioctl,
104};
105
106/*
107 * In the cdevsw routines, we find our softc by using the si_drv1 member
108 * of struct cdev. We set this variable to point to our softc in our
109 * attach routine when we create the /dev entry.
110 */
111
112int
113tws_open(struct dev_open_args *ap)
114{
115 cdev_t dev = ap->a_head.a_dev;
116 struct tws_softc *sc = dev->si_drv1;
117
118 if ( sc )
119 TWS_TRACE_DEBUG(sc, "entry", dev, oflags);
120 return (0);
121}
122
123int
124tws_close(struct dev_close_args *ap)
125{
126 cdev_t dev = ap->a_head.a_dev;
127 struct tws_softc *sc = dev->si_drv1;
128
129 if ( sc )
130 TWS_TRACE_DEBUG(sc, "entry", dev, fflag);
131 return (0);
132}
133
134int
135tws_read(struct dev_read_args *ap)
136{
137 cdev_t dev = ap->a_head.a_dev;
138 struct tws_softc *sc = dev->si_drv1;
139
140 if ( sc )
141 TWS_TRACE_DEBUG(sc, "entry", dev, ioflag);
142 return (0);
143}
144
145int
146tws_write(struct dev_write_args *ap)
147{
148 cdev_t dev = ap->a_head.a_dev;
149 struct tws_softc *sc = dev->si_drv1;
150
151 if ( sc )
152 TWS_TRACE_DEBUG(sc, "entry", dev, ioflag);
153 return (0);
154}
155
156/* PCI Support Functions */
157
158/*
159 * Compare the device ID of this device against the IDs that this driver
160 * supports. If there is a match, set the description and return success.
161 */
162static int
163tws_probe(device_t dev)
164{
165 static u_int8_t first_ctlr = 1;
166
167 if ((pci_get_vendor(dev) == TWS_VENDOR_ID) &&
168 (pci_get_device(dev) == TWS_DEVICE_ID)) {
169 device_set_desc(dev, "LSI 3ware SAS/SATA Storage Controller");
170 if (first_ctlr) {
171 kprintf("LSI 3ware device driver for SAS/SATA storage "
172 "controllers, version: %s\n", TWS_DRIVER_VERSION_STRING);
173 first_ctlr = 0;
174 }
175
176 return(0);
177 }
178 return (ENXIO);
179}
180
181/* Attach function is only called if the probe is successful. */
182
183static int
184tws_attach(device_t dev)
185{
186 struct tws_softc *sc = device_get_softc(dev);
187 u_int32_t cmd, bar;
188 int error=0,i;
189
190 /* no tracing yet */
191 /* Look up our softc and initialize its fields. */
192 sc->tws_dev = dev;
193 sc->device_id = pci_get_device(dev);
194 sc->subvendor_id = pci_get_subvendor(dev);
195 sc->subdevice_id = pci_get_subdevice(dev);
196
197 /* Intialize mutexes */
198 lockinit(&sc->q_lock, "tws_q_lock", 0, LK_CANRECURSE);
199 lockinit(&sc->sim_lock, "tws_sim_lock", 0, LK_CANRECURSE);
200 lockinit(&sc->gen_lock, "tws_gen_lock", 0, LK_CANRECURSE);
201 lockinit(&sc->io_lock, "tws_io_lock", 0, LK_CANRECURSE);
202
203 if ( tws_init_trace_q(sc) == FAILURE )
204 kprintf("trace init failure\n");
205 /* send init event */
206 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
207 tws_send_event(sc, TWS_INIT_START);
208 lockmgr(&sc->gen_lock, LK_RELEASE);
209
210
211#if _BYTE_ORDER == _BIG_ENDIAN
212 TWS_TRACE(sc, "BIG endian", 0, 0);
213#endif
214 /* sysctl context setup */
215 sysctl_ctx_init(&sc->tws_clist);
216 sc->tws_oidp = SYSCTL_ADD_NODE(&sc->tws_clist,
217 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
218 device_get_nameunit(dev),
219 CTLFLAG_RD, 0, "");
220 if ( sc->tws_oidp == NULL ) {
221 tws_log(sc, SYSCTL_TREE_NODE_ADD);
222 goto attach_fail_1;
223 }
224 SYSCTL_ADD_STRING(&sc->tws_clist, SYSCTL_CHILDREN(sc->tws_oidp),
225 OID_AUTO, "driver_version", CTLFLAG_RD,
226 TWS_DRIVER_VERSION_STRING, 0, "TWS driver version");
227
228 cmd = pci_read_config(dev, PCIR_COMMAND, 2);
229 if ( (cmd & PCIM_CMD_PORTEN) == 0) {
230 tws_log(sc, PCI_COMMAND_READ);
231 goto attach_fail_1;
232 }
233 /* Force the busmaster enable bit on. */
234 cmd |= PCIM_CMD_BUSMASTEREN;
235 pci_write_config(dev, PCIR_COMMAND, cmd, 2);
236
237 bar = pci_read_config(dev, TWS_PCI_BAR0, 4);
238 TWS_TRACE_DEBUG(sc, "bar0 ", bar, 0);
239 bar = pci_read_config(dev, TWS_PCI_BAR1, 4);
240 bar = bar & ~TWS_BIT2;
241 TWS_TRACE_DEBUG(sc, "bar1 ", bar, 0);
242
243 /* MFA base address is BAR2 register used for
244 * push mode. Firmware will evatualy move to
245 * pull mode during witch this needs to change
246 */
247#ifndef TWS_PULL_MODE_ENABLE
248 sc->mfa_base = (u_int64_t)pci_read_config(dev, TWS_PCI_BAR2, 4);
249 sc->mfa_base = sc->mfa_base & ~TWS_BIT2;
250 TWS_TRACE_DEBUG(sc, "bar2 ", sc->mfa_base, 0);
251#endif
252
253 /* allocate MMIO register space */
254 sc->reg_res_id = TWS_PCI_BAR1; /* BAR1 offset */
255 if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
256 &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
257 == NULL) {
258 tws_log(sc, ALLOC_MEMORY_RES);
259 goto attach_fail_1;
260 }
261 sc->bus_tag = rman_get_bustag(sc->reg_res);
262 sc->bus_handle = rman_get_bushandle(sc->reg_res);
263
264#ifndef TWS_PULL_MODE_ENABLE
265 /* Allocate bus space for inbound mfa */
266 sc->mfa_res_id = TWS_PCI_BAR2; /* BAR2 offset */
267 if ((sc->mfa_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
268 &(sc->mfa_res_id), 0, ~0, 0x100000, RF_ACTIVE))
269 == NULL) {
270 tws_log(sc, ALLOC_MEMORY_RES);
271 goto attach_fail_2;
272 }
273 sc->bus_mfa_tag = rman_get_bustag(sc->mfa_res);
274 sc->bus_mfa_handle = rman_get_bushandle(sc->mfa_res);
275#endif
276
277 /* Allocate and register our interrupt. */
278 sc->intr_type = TWS_INTx; /* default */
279
280 if ( tws_enable_msi )
281 sc->intr_type = TWS_MSI;
282 if ( tws_setup_irq(sc) == FAILURE ) {
283 tws_log(sc, ALLOC_MEMORY_RES);
284 goto attach_fail_3;
285 }
286
287 /* Init callouts. */
288 callout_init(&sc->print_stats_handle);
289 callout_init(&sc->reset_cb_handle);
290 callout_init(&sc->reinit_handle);
291
292 /*
293 * Create a /dev entry for this device. The kernel will assign us
294 * a major number automatically. We use the unit number of this
295 * device as the minor number and name the character device
296 * "tws<unit>".
297 */
298 sc->tws_cdev = make_dev(&tws_ops, device_get_unit(dev),
299 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "tws%u",
300 device_get_unit(dev));
301 sc->tws_cdev->si_drv1 = sc;
302
303 if ( tws_init(sc) == FAILURE ) {
304 tws_log(sc, TWS_INIT_FAILURE);
305 goto attach_fail_4;
306 }
307 if ( tws_init_ctlr(sc) == FAILURE ) {
308 tws_log(sc, TWS_CTLR_INIT_FAILURE);
309 goto attach_fail_4;
310 }
311 if ((error = tws_cam_attach(sc))) {
312 tws_log(sc, TWS_CAM_ATTACH);
313 goto attach_fail_4;
314 }
315 /* send init complete event */
316 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
317 tws_send_event(sc, TWS_INIT_COMPLETE);
318 lockmgr(&sc->gen_lock, LK_RELEASE);
319
320 TWS_TRACE_DEBUG(sc, "attached successfully", 0, sc->device_id);
321 return(0);
322
323attach_fail_4:
324 for(i=0;i<sc->irqs;i++) {
325 if (sc->intr_handle[i]) {
326 if ((error = bus_teardown_intr(sc->tws_dev,
327 sc->irq_res[i], sc->intr_handle[i])))
328 TWS_TRACE(sc, "bus teardown intr", 0, error);
329 }
330 }
331 destroy_dev(sc->tws_cdev);
332 dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev));
333attach_fail_3:
334 for(i=0;i<sc->irqs;i++) {
335 if ( sc->irq_res[i] ){
336 if (bus_release_resource(sc->tws_dev,
337 SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
338 TWS_TRACE(sc, "bus irq res", 0, 0);
339 }
340 }
341#ifndef TWS_PULL_MODE_ENABLE
342attach_fail_2:
343#endif
344 if ( sc->mfa_res ){
345 if (bus_release_resource(sc->tws_dev,
346 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res))
347 TWS_TRACE(sc, "bus release ", 0, sc->mfa_res_id);
348 }
349 if ( sc->reg_res ){
350 if (bus_release_resource(sc->tws_dev,
351 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))
352 TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id);
353 }
354attach_fail_1:
355 lockuninit(&sc->q_lock);
356 lockuninit(&sc->sim_lock);
357 lockuninit(&sc->gen_lock);
358 lockuninit(&sc->io_lock);
359 sysctl_ctx_free(&sc->tws_clist);
360 return (ENXIO);
361}
362
363/* Detach device. */
364
365static int
366tws_detach(device_t dev)
367{
368 struct tws_softc *sc = device_get_softc(dev);
369 int error, i;
370 u_int32_t reg;
371
372 TWS_TRACE_DEBUG(sc, "entry", 0, 0);
373
374 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
375 tws_send_event(sc, TWS_UNINIT_START);
376 lockmgr(&sc->gen_lock, LK_RELEASE);
377
378 /* needs to disable interrupt before detaching from cam */
379 tws_turn_off_interrupts(sc);
380 /* clear door bell */
381 tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4);
382 reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4);
383 TWS_TRACE_DEBUG(sc, "turn-off-intr", reg, 0);
384 sc->obfl_q_overrun = false;
385 tws_init_connect(sc, 1);
386
387 /* Teardown the state in our softc created in our attach routine. */
388 /* Disconnect the interrupt handler. */
389 for(i=0;i<sc->irqs;i++) {
390 if (sc->intr_handle[i]) {
391 if ((error = bus_teardown_intr(sc->tws_dev,
392 sc->irq_res[i], sc->intr_handle[i])))
393 TWS_TRACE(sc, "bus teardown intr", 0, error);
394 }
395 }
396 /* Release irq resource */
397 for(i=0;i<sc->irqs;i++) {
398 if ( sc->irq_res[i] ){
399 if (bus_release_resource(sc->tws_dev,
400 SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
401 TWS_TRACE(sc, "bus release irq resource",
402 i, sc->irq_res_id[i]);
403 }
404 }
405 if ( sc->intr_type == TWS_MSI ) {
406 pci_release_msi(sc->tws_dev);
407 }
408
409 tws_cam_detach(sc);
410
411 /* Release memory resource */
412 if ( sc->mfa_res ){
413 if (bus_release_resource(sc->tws_dev,
414 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res))
415 TWS_TRACE(sc, "bus release mem resource", 0, sc->mfa_res_id);
416 }
417 if ( sc->reg_res ){
418 if (bus_release_resource(sc->tws_dev,
419 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))
420 TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id);
421 }
422
423 kfree(sc->reqs, M_TWS);
424 kfree(sc->sense_bufs, M_TWS);
425 kfree(sc->scan_ccb, M_TWS);
426 kfree(sc->aen_q.q, M_TWS);
427 kfree(sc->trace_q.q, M_TWS);
428 lockuninit(&sc->q_lock);
429 lockuninit(&sc->sim_lock);
430 lockuninit(&sc->gen_lock);
431 lockuninit(&sc->io_lock);
432 destroy_dev(sc->tws_cdev);
433 dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev));
434 sysctl_ctx_free(&sc->tws_clist);
435 return (0);
436}
437
438static int
439tws_setup_intr(struct tws_softc *sc, int irqs)
440{
441 int i, error;
442
443 for(i=0;i<irqs;i++) {
444 if ((error = bus_setup_intr(sc->tws_dev, sc->irq_res[i],
445 INTR_MPSAFE,
446 tws_intr, sc, &sc->intr_handle[i], NULL))) {
447 tws_log(sc, SETUP_INTR_RES);
448 return(FAILURE);
449 }
450 }
451 return(SUCCESS);
452
453}
454
455
456static int
457tws_setup_irq(struct tws_softc *sc)
458{
459 u_int16_t cmd;
460
461 cmd = pci_read_config(sc->tws_dev, PCIR_COMMAND, 2);
462 switch(sc->intr_type) {
463 case TWS_INTx :
464 cmd = cmd & ~0x0400;
465 pci_write_config(sc->tws_dev, PCIR_COMMAND, cmd, 2);
466 sc->irqs = 1;
467 sc->irq_res_id[0] = 0;
468 sc->irq_res[0] = bus_alloc_resource_any(sc->tws_dev, SYS_RES_IRQ,
469 &sc->irq_res_id[0], RF_SHAREABLE | RF_ACTIVE);
470 if ( ! sc->irq_res[0] )
471 return(FAILURE);
472 if ( tws_setup_intr(sc, sc->irqs) == FAILURE )
473 return(FAILURE);
474 device_printf(sc->tws_dev, "Using legacy INTx\n");
475 break;
476 case TWS_MSI :
477#ifdef OLD_MSI
478 cmd = cmd | 0x0400;
479 pci_write_config(sc->tws_dev, PCIR_COMMAND, cmd, 2);
480 sc->irqs = 1;
481 sc->irq_res_id[0] = 1;
482 messages = 1;
483 if (pci_alloc_msi(sc->tws_dev, &messages) != 0 ) {
484 TWS_TRACE(sc, "pci alloc msi fail", 0, messages);
485 return(FAILURE);
486 }
487 sc->irq_res[0] = bus_alloc_resource_any(sc->tws_dev, SYS_RES_IRQ,
488 &sc->irq_res_id[0], RF_SHAREABLE | RF_ACTIVE);
489
490 if ( !sc->irq_res[0] )
491 return(FAILURE);
492 if ( tws_setup_intr(sc, sc->irqs) == FAILURE )
493 return(FAILURE);
494 device_printf(sc->tws_dev, "Using MSI\n");
495#else
496 panic("%s: Using MSI", device_get_nameunit(sc->tws_dev));
497#endif
498 break;
499
500 }
501
502 return(SUCCESS);
503}
504
505static int
506tws_init(struct tws_softc *sc)
507{
508
509 u_int32_t max_sg_elements;
510 u_int32_t dma_mem_size;
511 int error;
512 u_int32_t reg;
513
514 sc->seq_id = 0;
515 if ( tws_queue_depth > TWS_MAX_REQS )
516 tws_queue_depth = TWS_MAX_REQS;
517 if (tws_queue_depth < TWS_RESERVED_REQS+1)
518 tws_queue_depth = TWS_RESERVED_REQS+1;
519 sc->is64bit = (sizeof(bus_addr_t) == 8) ? true : false;
520 max_sg_elements = (sc->is64bit && !tws_use_32bit_sgls) ?
521 TWS_MAX_64BIT_SG_ELEMENTS :
522 TWS_MAX_32BIT_SG_ELEMENTS;
523 dma_mem_size = (sizeof(struct tws_command_packet) * tws_queue_depth) +
524 (TWS_SECTOR_SIZE) ;
525 if ( bus_dma_tag_create(NULL, /* parent */
526 TWS_ALIGNMENT, /* alignment */
527 0, /* boundary */
528 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
529 BUS_SPACE_MAXADDR, /* highaddr */
530 NULL, NULL, /* filter, filterarg */
531 BUS_SPACE_MAXSIZE, /* maxsize */
532 max_sg_elements, /* numsegs */
533 BUS_SPACE_MAXSIZE, /* maxsegsize */
534 0, /* flags */
535 &sc->parent_tag /* tag */
536 )) {
537 TWS_TRACE_DEBUG(sc, "DMA parent tag Create fail", max_sg_elements,
538 sc->is64bit);
539 return(ENOMEM);
540 }
541 /* In bound message frame requires 16byte alignment.
542 * Outbound MF's can live with 4byte alignment - for now just
543 * use 16 for both.
544 */
545 if ( bus_dma_tag_create(sc->parent_tag, /* parent */
546 TWS_IN_MF_ALIGNMENT, /* alignment */
547 0, /* boundary */
548 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
549 BUS_SPACE_MAXADDR, /* highaddr */
550 NULL, NULL, /* filter, filterarg */
551 dma_mem_size, /* maxsize */
552 1, /* numsegs */
553 BUS_SPACE_MAXSIZE, /* maxsegsize */
554 0, /* flags */
555 &sc->cmd_tag /* tag */
556 )) {
557 TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit);
558 return(ENOMEM);
559 }
560
561 if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem,
562 BUS_DMA_NOWAIT, &sc->cmd_map)) {
563 TWS_TRACE_DEBUG(sc, "DMA mem alloc fail", max_sg_elements, sc->is64bit);
564 return(ENOMEM);
565 }
566
567 /* if bus_dmamem_alloc succeeds then bus_dmamap_load will succeed */
568 sc->dma_mem_phys=0;
569 error = bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem,
570 dma_mem_size, tws_dmamap_cmds_load_cbfn,
571 &sc->dma_mem_phys, 0);
572
573 if ( error == EINPROGRESS )
574 TWS_TRACE_DEBUG(sc, "req queued", max_sg_elements, sc->is64bit);
575
576 /*
577 * Create a dma tag for data buffers; size will be the maximum
578 * possible I/O size (128kB).
579 */
580 if (bus_dma_tag_create(sc->parent_tag, /* parent */
581 TWS_ALIGNMENT, /* alignment */
582 0, /* boundary */
583 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
584 BUS_SPACE_MAXADDR, /* highaddr */
585 NULL, NULL, /* filter, filterarg */
586 TWS_MAX_IO_SIZE, /* maxsize */
587 max_sg_elements, /* nsegments */
588 TWS_MAX_IO_SIZE, /* maxsegsize */
589 BUS_DMA_ALLOCALL | /* flags */
590 BUS_DMA_ALLOCNOW |
591 BUS_DMA_PRIVBZONE |
592 BUS_DMA_PROTECTED,
593 &sc->data_tag /* tag */)) {
594 TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit);
595 return(ENOMEM);
596 }
597
598 sc->reqs = kmalloc(sizeof(struct tws_request) * tws_queue_depth, M_TWS,
599 M_WAITOK | M_ZERO);
600 sc->sense_bufs = kmalloc(sizeof(struct tws_sense) * tws_queue_depth, M_TWS,
601 M_WAITOK | M_ZERO);
602 sc->scan_ccb = kmalloc(sizeof(union ccb), M_TWS, M_WAITOK | M_ZERO);
603
604 if ( !tws_ctlr_ready(sc) )
605 if( !tws_ctlr_reset(sc) )
606 return(FAILURE);
607
608 bzero(&sc->stats, sizeof(struct tws_stats));
609 tws_init_qs(sc);
610 tws_turn_off_interrupts(sc);
611
612 /*
613 * enable pull mode by setting bit1 .
614 * setting bit0 to 1 will enable interrupt coalesing
615 * will revisit.
616 */
617
618#ifdef TWS_PULL_MODE_ENABLE
619
620 reg = tws_read_reg(sc, TWS_I2O0_CTL, 4);
621 TWS_TRACE_DEBUG(sc, "i20 ctl", reg, TWS_I2O0_CTL);
622 tws_write_reg(sc, TWS_I2O0_CTL, reg | TWS_BIT1, 4);
623
624#endif
625
626 TWS_TRACE_DEBUG(sc, "dma_mem_phys", sc->dma_mem_phys, TWS_I2O0_CTL);
627 if ( tws_init_reqs(sc, dma_mem_size) == FAILURE )
628 return(FAILURE);
629 if ( tws_init_aen_q(sc) == FAILURE )
630 return(FAILURE);
631
632 return(SUCCESS);
633
634}
635
636static int
637tws_init_aen_q(struct tws_softc *sc)
638{
639 sc->aen_q.head=0;
640 sc->aen_q.tail=0;
641 sc->aen_q.depth=256;
642 sc->aen_q.overflow=0;
643 sc->aen_q.q = kmalloc(sizeof(struct tws_event_packet)*sc->aen_q.depth,
644 M_TWS, M_WAITOK | M_ZERO);
645 return(SUCCESS);
646}
647
648static int
649tws_init_trace_q(struct tws_softc *sc)
650{
651 sc->trace_q.head=0;
652 sc->trace_q.tail=0;
653 sc->trace_q.depth=256;
654 sc->trace_q.overflow=0;
655 sc->trace_q.q = kmalloc(sizeof(struct tws_trace_rec)*sc->trace_q.depth,
656 M_TWS, M_WAITOK | M_ZERO);
657 return(SUCCESS);
658}
659
660static int
661tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size)
662{
663
664 struct tws_command_packet *cmd_buf;
665 cmd_buf = (struct tws_command_packet *)sc->dma_mem;
666 int i;
667
668 bzero(cmd_buf, dma_mem_size);
669 TWS_TRACE_DEBUG(sc, "phy cmd", sc->dma_mem_phys, 0);
670 lockmgr(&sc->q_lock, LK_EXCLUSIVE);
671 for ( i=0; i< tws_queue_depth; i++)
672 {
673 if (bus_dmamap_create(sc->data_tag, 0, &sc->reqs[i].dma_map)) {
674 /* log a ENOMEM failure msg here */
675 lockmgr(&sc->q_lock, LK_RELEASE);
676 return(FAILURE);
677 }
678 sc->reqs[i].cmd_pkt = &cmd_buf[i];
679
680 sc->sense_bufs[i].hdr = &cmd_buf[i].hdr ;
681 sc->sense_bufs[i].hdr_pkt_phy = sc->dma_mem_phys +
682 (i * sizeof(struct tws_command_packet));
683 sc->sense_bufs[i].posted = false;
684
685 sc->reqs[i].cmd_pkt_phy = sc->dma_mem_phys +
686 sizeof(struct tws_command_header) +
687 (i * sizeof(struct tws_command_packet));
688 sc->reqs[i].request_id = i;
689 sc->reqs[i].sc = sc;
690
691 sc->reqs[i].cmd_pkt->hdr.header_desc.size_header = 128;
692
693 sc->reqs[i].state = TWS_REQ_STATE_FREE;
694 if ( i >= TWS_RESERVED_REQS )
695 tws_q_insert_tail(sc, &sc->reqs[i], TWS_FREE_Q);
696 }
697 lockmgr(&sc->q_lock, LK_RELEASE);
698 return(SUCCESS);
699}
700
701static void
702tws_dmamap_cmds_load_cbfn(void *arg, bus_dma_segment_t *segs,
703 int nseg, int error)
704{
705
706 /* kprintf("command load done \n"); */
707
708 *((bus_addr_t *)arg) = segs[0].ds_addr;
709}
710
711void
712tws_send_event(struct tws_softc *sc, u_int8_t event)
713{
714 KKASSERT(lockstatus(&sc->gen_lock, curthread) != 0);
715 TWS_TRACE_DEBUG(sc, "received event ", 0, event);
716 switch (event) {
717
718 case TWS_INIT_START:
719 sc->tws_state = TWS_INIT;
720 break;
721
722 case TWS_INIT_COMPLETE:
723 KASSERT(sc->tws_state == TWS_INIT , ("invalid state transition"));
724 sc->tws_state = TWS_ONLINE;
725 break;
726
727 case TWS_RESET_START:
728 /* multiple reset ? */
729 KASSERT(sc->tws_state != TWS_RESET, ("invalid state transition"));
730
731 /* we can transition to reset state from any state */
732 sc->tws_prev_state = sc->tws_state;
733 sc->tws_state = TWS_RESET;
734 break;
735
736 case TWS_RESET_COMPLETE:
737 KASSERT(sc->tws_state == TWS_RESET, ("invalid state transition"));
738 sc->tws_state = sc->tws_prev_state;
739 break;
740
741 case TWS_SCAN_FAILURE:
742 KASSERT(sc->tws_state == TWS_ONLINE , ("invalid state transition"));
743 sc->tws_state = TWS_OFFLINE;
744 break;
745
746 case TWS_UNINIT_START:
747 KASSERT(sc->tws_state == TWS_ONLINE || sc->tws_state == TWS_OFFLINE,
748 ("invalid state transition"));
749 sc->tws_state = TWS_UNINIT;
750 break;
751 }
752
753}
754
755uint8_t
756tws_get_state(struct tws_softc *sc)
757{
758
759 return((u_int8_t)sc->tws_state);
760
761}
762
763/* Called during system shutdown after sync. */
764
765static int
766tws_shutdown(device_t dev)
767{
768
769 struct tws_softc *sc = device_get_softc(dev);
770
771 TWS_TRACE_DEBUG(sc, "entry", 0, 0);
772
773 tws_turn_off_interrupts(sc);
774 tws_init_connect(sc, 1);
775
776 return (0);
777}
778
779/*
780 * Device suspend routine.
781 */
782static int
783tws_suspend(device_t dev)
784{
785 struct tws_softc *sc = device_get_softc(dev);
786
787 if ( sc )
788 TWS_TRACE_DEBUG(sc, "entry", 0, 0);
789 return (0);
790}
791
792/*
793 * Device resume routine.
794 */
795static int
796tws_resume(device_t dev)
797{
798
799 struct tws_softc *sc = device_get_softc(dev);
800
801 if ( sc )
802 TWS_TRACE_DEBUG(sc, "entry", 0, 0);
803 return (0);
804}
805
806
807struct tws_request *
808tws_get_request(struct tws_softc *sc, u_int16_t type)
809{
810 struct tws_request *r = NULL;
811
812 switch ( type ) {
813 case TWS_INTERNAL_CMD_REQ :
814 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
815 r = &sc->reqs[0];
816 if ( r->state != TWS_REQ_STATE_FREE ) {
817 r = NULL;
818 } else {
819 r->state = TWS_REQ_STATE_BUSY;
820 }
821 lockmgr(&sc->gen_lock, LK_RELEASE);
822 break;
823 case TWS_AEN_FETCH_REQ :
824 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
825 r = &sc->reqs[1];
826 if ( r->state != TWS_REQ_STATE_FREE ) {
827 r = NULL;
828 } else {
829 r->state = TWS_REQ_STATE_BUSY;
830 }
831 lockmgr(&sc->gen_lock, LK_RELEASE);
832 break;
833 case TWS_PASSTHRU_REQ :
834 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
835 r = &sc->reqs[2];
836 if ( r->state != TWS_REQ_STATE_FREE ) {
837 r = NULL;
838 } else {
839 r->state = TWS_REQ_STATE_BUSY;
840 }
841 lockmgr(&sc->gen_lock, LK_RELEASE);
842 break;
843 case TWS_GETSET_PARAM_REQ :
844 lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
845 r = &sc->reqs[3];
846 if ( r->state != TWS_REQ_STATE_FREE ) {
847 r = NULL;
848 } else {
849 r->state = TWS_REQ_STATE_BUSY;
850 }
851 lockmgr(&sc->gen_lock, LK_RELEASE);
852 break;
853 case TWS_SCSI_IO_REQ :
854 lockmgr(&sc->q_lock, LK_EXCLUSIVE);
855 r = tws_q_remove_head(sc, TWS_FREE_Q);
856 if ( r )
857 r->state = TWS_REQ_STATE_TRAN;
858 lockmgr(&sc->q_lock, LK_RELEASE);
859 break;
860 default :
861 TWS_TRACE_DEBUG(sc, "Unknown req type", 0, type);
862 r = NULL;
863
864 }
865
866 if ( r ) {
867 bzero(&r->cmd_pkt->cmd, sizeof(struct tws_command_apache));
868 callout_init(&r->thandle);
869 r->data = NULL;
870 r->length = 0;
871 r->type = type;
872 r->flags = TWS_DIR_UNKNOWN;
873 r->error_code = TWS_REQ_ERR_INVALID;
874 r->ccb_ptr = NULL;
875 r->cb = NULL;
876 r->next = r->prev = NULL;
877 }
878 return(r);
879}
880
881void
882tws_release_request(struct tws_request *req)
883{
884
885 struct tws_softc *sc = req->sc;
886
887 TWS_TRACE_DEBUG(sc, "entry", sc, 0);
888 lockmgr(&sc->q_lock, LK_EXCLUSIVE);
889 tws_q_insert_tail(sc, req, TWS_FREE_Q);
890 lockmgr(&sc->q_lock, LK_RELEASE);
891}
892
893static device_method_t tws_methods[] = {
894 /* Device interface */
895 DEVMETHOD(device_probe, tws_probe),
896 DEVMETHOD(device_attach, tws_attach),
897 DEVMETHOD(device_detach, tws_detach),
898 DEVMETHOD(device_shutdown, tws_shutdown),
899 DEVMETHOD(device_suspend, tws_suspend),
900 DEVMETHOD(device_resume, tws_resume),
901
902 DEVMETHOD(bus_print_child, bus_generic_print_child),
903 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
904 { 0, 0 }
905};
906
907static driver_t tws_driver = {
908 "tws",
909 tws_methods,
910 sizeof(struct tws_softc)
911};
912
913
914static devclass_t tws_devclass;
915
916/* DEFINE_CLASS_0(tws, tws_driver, tws_methods, sizeof(struct tws_softc)); */
917DRIVER_MODULE(tws, pci, tws_driver, tws_devclass, NULL, NULL);
918MODULE_DEPEND(tws, cam, 1, 1, 1);
919MODULE_DEPEND(tws, pci, 1, 1, 1);
920
921TUNABLE_INT("hw.tws.queue_depth", &tws_queue_depth);
922#if 0 /* XXX swildner */
923TUNABLE_INT("hw.tws.enable_msi", &tws_enable_msi);
924#endif