Bug Summary

File:dev/ic/twe.c
Warning:line 885, column 8
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name twe.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/ic/twe.c
1/* $OpenBSD: twe.c,v 1.66 2021/07/14 01:11:13 daniel Exp $ */
2
3/*
4 * Copyright (c) 2000-2002 Michael Shalayeff. All rights reserved.
5 *
6 * The SCSI emulation layer is derived from gdt(4) driver,
7 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/* #define TWE_DEBUG */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/buf.h>
36#include <sys/device.h>
37#include <sys/malloc.h>
38#include <sys/kthread.h>
39
40#include <machine/bus.h>
41
42#include <scsi/scsi_all.h>
43#include <scsi/scsi_disk.h>
44#include <scsi/scsiconf.h>
45
46#include <dev/ic/twereg.h>
47#include <dev/ic/twevar.h>
48
49#ifdef TWE_DEBUG
50#define TWE_DPRINTF(m,a) if (twe_debug & (m)) printf a
51#define TWE_D_CMD 0x0001
52#define TWE_D_INTR 0x0002
53#define TWE_D_MISC 0x0004
54#define TWE_D_DMA 0x0008
55#define TWE_D_AEN 0x0010
56int twe_debug = 0;
57#else
58#define TWE_DPRINTF(m,a) /* m, a */
59#endif
60
61struct cfdriver twe_cd = {
62 NULL((void *)0), "twe", DV_DULL
63};
64
65void twe_scsi_cmd(struct scsi_xfer *);
66
67struct scsi_adapter twe_switch = {
68 twe_scsi_cmd, NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0)
69};
70
71void *twe_get_ccb(void *);
72void twe_put_ccb(void *, void *);
73void twe_dispose(struct twe_softc *sc);
74int twe_cmd(struct twe_ccb *ccb, int flags, int wait);
75int twe_start(struct twe_ccb *ccb, int wait);
76int twe_complete(struct twe_ccb *ccb);
77int twe_done(struct twe_softc *sc, struct twe_ccb *ccb);
78void twe_thread_create(void *v);
79void twe_thread(void *v);
80void twe_aen(void *, void *);
81
82void *
83twe_get_ccb(void *xsc)
84{
85 struct twe_softc *sc = xsc;
86 struct twe_ccb *ccb;
87
88 mtx_enter(&sc->sc_ccb_mtx);
89 ccb = TAILQ_LAST(&sc->sc_free_ccb, twe_queue_head)(*(((struct twe_queue_head *)((&sc->sc_free_ccb)->tqh_last
))->tqh_last))
;
90 if (ccb != NULL((void *)0))
91 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link)do { if (((ccb)->ccb_link.tqe_next) != ((void *)0)) (ccb)->
ccb_link.tqe_next->ccb_link.tqe_prev = (ccb)->ccb_link.
tqe_prev; else (&sc->sc_free_ccb)->tqh_last = (ccb)
->ccb_link.tqe_prev; *(ccb)->ccb_link.tqe_prev = (ccb)->
ccb_link.tqe_next; ((ccb)->ccb_link.tqe_prev) = ((void *)-
1); ((ccb)->ccb_link.tqe_next) = ((void *)-1); } while (0)
;
92 mtx_leave(&sc->sc_ccb_mtx);
93
94 return (ccb);
95}
96
97void
98twe_put_ccb(void *xsc, void *xccb)
99{
100 struct twe_softc *sc = xsc;
101 struct twe_ccb *ccb = xccb;
102
103 ccb->ccb_state = TWE_CCB_FREE;
104 mtx_enter(&sc->sc_ccb_mtx);
105 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_free_ccb)->tqh_last; *(&sc
->sc_free_ccb)->tqh_last = (ccb); (&sc->sc_free_ccb
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
106 mtx_leave(&sc->sc_ccb_mtx);
107}
108
109void
110twe_dispose(struct twe_softc *sc)
111{
112 register struct twe_ccb *ccb;
113 if (sc->sc_cmdmap != NULL((void *)0)) {
114 bus_dmamap_destroy(sc->dmat, sc->sc_cmdmap)(*(sc->dmat)->_dmamap_destroy)((sc->dmat), (sc->sc_cmdmap
))
;
115 /* traverse the ccbs and destroy the maps */
116 for (ccb = &sc->sc_ccbs[TWE_MAXCMDS255 - 1]; ccb >= sc->sc_ccbs; ccb--)
117 if (ccb->ccb_dmamap)
118 bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap)(*(sc->dmat)->_dmamap_destroy)((sc->dmat), (ccb->
ccb_dmamap))
;
119 }
120 bus_dmamem_unmap(sc->dmat, sc->sc_cmds,(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (sc->sc_cmds
), (sizeof(struct twe_cmd) * 255))
121 sizeof(struct twe_cmd) * TWE_MAXCMDS)(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (sc->sc_cmds
), (sizeof(struct twe_cmd) * 255))
;
122 bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1)(*(sc->dmat)->_dmamem_free)((sc->dmat), (sc->sc_cmdseg
), (1))
;
123}
124
125int
126twe_attach(struct twe_softc *sc)
127{
128 struct scsibus_attach_args saa;
129 /* this includes a buffer for drive config req, and a capacity req */
130 u_int8_t param_buf[2 * TWE_SECTOR_SIZE512 + TWE_ALIGN512 - 1];
131 struct twe_param *pb = (void *)
132 (((u_long)param_buf + TWE_ALIGN512 - 1) & ~(TWE_ALIGN512 - 1));
133 struct twe_param *cap = (void *)((u_int8_t *)pb + TWE_SECTOR_SIZE512);
134 struct twe_ccb *ccb;
135 struct twe_cmd *cmd;
136 u_int32_t status;
137 int error, i, retry, nunits, nseg;
138 const char *errstr;
139 twe_lock_t lock;
140 paddr_t pa;
141
142 error = bus_dmamem_alloc(sc->dmat, sizeof(struct twe_cmd) * TWE_MAXCMDS,(*(sc->dmat)->_dmamem_alloc)((sc->dmat), (sizeof(struct
twe_cmd) * 255), ((1 << 12)), (0), (sc->sc_cmdseg),
(1), (&nseg), (0x0001))
143 PAGE_SIZE, 0, sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT)(*(sc->dmat)->_dmamem_alloc)((sc->dmat), (sizeof(struct
twe_cmd) * 255), ((1 << 12)), (0), (sc->sc_cmdseg),
(1), (&nseg), (0x0001))
;
144 if (error) {
145 printf(": cannot allocate commands (%d)\n", error);
146 return (1);
147 }
148
149 error = bus_dmamem_map(sc->dmat, sc->sc_cmdseg, nseg,(*(sc->dmat)->_dmamem_map)((sc->dmat), (sc->sc_cmdseg
), (nseg), (sizeof(struct twe_cmd) * 255), ((caddr_t *)&sc
->sc_cmds), (0x0001))
150 sizeof(struct twe_cmd) * TWE_MAXCMDS,(*(sc->dmat)->_dmamem_map)((sc->dmat), (sc->sc_cmdseg
), (nseg), (sizeof(struct twe_cmd) * 255), ((caddr_t *)&sc
->sc_cmds), (0x0001))
151 (caddr_t *)&sc->sc_cmds, BUS_DMA_NOWAIT)(*(sc->dmat)->_dmamem_map)((sc->dmat), (sc->sc_cmdseg
), (nseg), (sizeof(struct twe_cmd) * 255), ((caddr_t *)&sc
->sc_cmds), (0x0001))
;
152 if (error) {
153 printf(": cannot map commands (%d)\n", error);
154 bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1)(*(sc->dmat)->_dmamem_free)((sc->dmat), (sc->sc_cmdseg
), (1))
;
155 return (1);
156 }
157
158 error = bus_dmamap_create(sc->dmat,(*(sc->dmat)->_dmamap_create)((sc->dmat), (sizeof(struct
twe_cmd) * 255), (255), (sizeof(struct twe_cmd) * 255), (0),
(0x0001 | 0x0002), (&sc->sc_cmdmap))
159 sizeof(struct twe_cmd) * TWE_MAXCMDS, TWE_MAXCMDS,(*(sc->dmat)->_dmamap_create)((sc->dmat), (sizeof(struct
twe_cmd) * 255), (255), (sizeof(struct twe_cmd) * 255), (0),
(0x0001 | 0x0002), (&sc->sc_cmdmap))
160 sizeof(struct twe_cmd) * TWE_MAXCMDS, 0,(*(sc->dmat)->_dmamap_create)((sc->dmat), (sizeof(struct
twe_cmd) * 255), (255), (sizeof(struct twe_cmd) * 255), (0),
(0x0001 | 0x0002), (&sc->sc_cmdmap))
161 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_cmdmap)(*(sc->dmat)->_dmamap_create)((sc->dmat), (sizeof(struct
twe_cmd) * 255), (255), (sizeof(struct twe_cmd) * 255), (0),
(0x0001 | 0x0002), (&sc->sc_cmdmap))
;
162 if (error) {
163 printf(": cannot create ccb cmd dmamap (%d)\n", error);
164 twe_dispose(sc);
165 return (1);
166 }
167 error = bus_dmamap_load(sc->dmat, sc->sc_cmdmap, sc->sc_cmds,(*(sc->dmat)->_dmamap_load)((sc->dmat), (sc->sc_cmdmap
), (sc->sc_cmds), (sizeof(struct twe_cmd) * 255), (((void *
)0)), (0x0001))
168 sizeof(struct twe_cmd) * TWE_MAXCMDS, NULL, BUS_DMA_NOWAIT)(*(sc->dmat)->_dmamap_load)((sc->dmat), (sc->sc_cmdmap
), (sc->sc_cmds), (sizeof(struct twe_cmd) * 255), (((void *
)0)), (0x0001))
;
169 if (error) {
170 printf(": cannot load command dma map (%d)\n", error);
171 twe_dispose(sc);
172 return (1);
173 }
174
175 TAILQ_INIT(&sc->sc_ccb2q)do { (&sc->sc_ccb2q)->tqh_first = ((void *)0); (&
sc->sc_ccb2q)->tqh_last = &(&sc->sc_ccb2q)->
tqh_first; } while (0)
;
176 TAILQ_INIT(&sc->sc_ccbq)do { (&sc->sc_ccbq)->tqh_first = ((void *)0); (&
sc->sc_ccbq)->tqh_last = &(&sc->sc_ccbq)->
tqh_first; } while (0)
;
177 TAILQ_INIT(&sc->sc_free_ccb)do { (&sc->sc_free_ccb)->tqh_first = ((void *)0); (
&sc->sc_free_ccb)->tqh_last = &(&sc->sc_free_ccb
)->tqh_first; } while (0)
;
178 TAILQ_INIT(&sc->sc_done_ccb)do { (&sc->sc_done_ccb)->tqh_first = ((void *)0); (
&sc->sc_done_ccb)->tqh_last = &(&sc->sc_done_ccb
)->tqh_first; } while (0)
;
179 mtx_init(&sc->sc_ccb_mtx, IPL_BIO)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_ccb_mtx), ((((0x6)) > 0x0 && ((0x6)) < 0x9) ?
0x9 : ((0x6)))); } while (0)
;
180 scsi_iopool_init(&sc->sc_iopool, sc, twe_get_ccb, twe_put_ccb);
181
182 scsi_ioh_set(&sc->sc_aen, &sc->sc_iopool, twe_aen, sc);
183
184 pa = sc->sc_cmdmap->dm_segs[0].ds_addr +
185 sizeof(struct twe_cmd) * (TWE_MAXCMDS255 - 1);
186 for (cmd = (struct twe_cmd *)sc->sc_cmds + TWE_MAXCMDS255 - 1;
187 cmd >= (struct twe_cmd *)sc->sc_cmds; cmd--, pa -= sizeof(*cmd)) {
188
189 cmd->cmd_index = cmd - (struct twe_cmd *)sc->sc_cmds;
190 ccb = &sc->sc_ccbs[cmd->cmd_index];
191 error = bus_dmamap_create(sc->dmat,(*(sc->dmat)->_dmamap_create)((sc->dmat), ((62 * (1 <<
12))), (62), ((62 * (1 << 12))), (0), (0x0001 | 0x0002
), (&ccb->ccb_dmamap))
192 TWE_MAXFER, TWE_MAXOFFSETS, TWE_MAXFER, 0,(*(sc->dmat)->_dmamap_create)((sc->dmat), ((62 * (1 <<
12))), (62), ((62 * (1 << 12))), (0), (0x0001 | 0x0002
), (&ccb->ccb_dmamap))
193 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap)(*(sc->dmat)->_dmamap_create)((sc->dmat), ((62 * (1 <<
12))), (62), ((62 * (1 << 12))), (0), (0x0001 | 0x0002
), (&ccb->ccb_dmamap))
;
194 if (error) {
195 printf(": cannot create ccb dmamap (%d)\n", error);
196 twe_dispose(sc);
197 return (1);
198 }
199 ccb->ccb_sc = sc;
200 ccb->ccb_cmd = cmd;
201 ccb->ccb_cmdpa = pa;
202 ccb->ccb_state = TWE_CCB_FREE;
203 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_free_ccb)->tqh_last; *(&sc
->sc_free_ccb)->tqh_last = (ccb); (&sc->sc_free_ccb
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
204 }
205
206 for (errstr = NULL((void *)0), retry = 3; retry--; ) {
207 int veseen_srst;
208 u_int16_t aen;
209
210 if (errstr)
211 TWE_DPRINTF(TWE_D_MISC, ("%s ", errstr));
212
213 for (i = 350000; i--; DELAY(100)(*delay_func)(100)) {
214 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
215 if (status & TWE_STAT_CPURDY0x00002000)
216 break;
217 }
218
219 if (!(status & TWE_STAT_CPURDY0x00002000)) {
220 errstr = ": card CPU is not ready\n";
221 continue;
222 }
223
224 /* soft reset, disable ints */
225 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00000100 |
0x00080000 | 0x00040000 | 0x00000200 | 0x00020000 | 0x00010000
| 0x00000040)))
226 TWE_CTRL_SRST |((sc->iot)->write_4((sc->ioh), (0x00), (0x00000100 |
0x00080000 | 0x00040000 | 0x00000200 | 0x00020000 | 0x00010000
| 0x00000040)))
227 TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR |((sc->iot)->write_4((sc->ioh), (0x00), (0x00000100 |
0x00080000 | 0x00040000 | 0x00000200 | 0x00020000 | 0x00010000
| 0x00000040)))
228 TWE_CTRL_MCMDI | TWE_CTRL_MRDYI |((sc->iot)->write_4((sc->ioh), (0x00), (0x00000100 |
0x00080000 | 0x00040000 | 0x00000200 | 0x00020000 | 0x00010000
| 0x00000040)))
229 TWE_CTRL_MINT)((sc->iot)->write_4((sc->ioh), (0x00), (0x00000100 |
0x00080000 | 0x00040000 | 0x00000200 | 0x00020000 | 0x00010000
| 0x00000040)))
;
230
231 for (i = 350000; i--; DELAY(100)(*delay_func)(100)) {
232 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
233 if (status & TWE_STAT_ATTNI0x00040000)
234 break;
235 }
236
237 if (!(status & TWE_STAT_ATTNI0x00040000)) {
238 errstr = ": cannot get card's attention\n";
239 continue;
240 }
241
242 /* drain aen queue */
243 for (veseen_srst = 0, aen = -1; aen != TWE_AEN_QEMPTY0x0000; ) {
244
245 ccb = scsi_io_get(&sc->sc_iopool, 0);
246 if (ccb == NULL((void *)0)) {
247 errstr = ": out of ccbs\n";
248 break;
249 }
250
251 ccb->ccb_xs = NULL((void *)0);
252 ccb->ccb_data = pb;
253 ccb->ccb_length = TWE_SECTOR_SIZE512;
254 ccb->ccb_state = TWE_CCB_READY;
255 cmd = ccb->ccb_cmd;
256 cmd->cmd_unit_host = TWE_UNITHOST(0, 0)(((0) & 0xf) | ((0) << 4));
257 cmd->cmd_op = TWE_CMD_GPARAM0x0252;
258 cmd->cmd_param_._cmd_param.count = 1;
259
260 pb->table_id = TWE_PARAM_AEN0x401;
261 pb->param_id = 2;
262 pb->param_size = 2;
263
264 error = twe_cmd(ccb, BUS_DMA_NOWAIT0x0001, 1);
265 scsi_io_put(&sc->sc_iopool, ccb);
266 if (error) {
267 errstr = ": error draining attention queue\n";
268 break;
269 }
270
271 aen = *(u_int16_t *)pb->data;
272 TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
273 if (aen == TWE_AEN_SRST0x0001)
274 veseen_srst++;
275 }
276
277 if (!veseen_srst) {
278 errstr = ": we don't get it\n";
279 continue;
280 }
281
282 if (status & TWE_STAT_CPUERR0x00200000) {
283 errstr = ": card CPU error detected\n";
284 continue;
285 }
286
287 if (status & TWE_STAT_PCIPAR0x00800000) {
288 errstr = ": PCI parity error detected\n";
289 continue;
290 }
291
292 if (status & TWE_STAT_QUEUEE0x00400000 ) {
293 errstr = ": queuing error detected\n";
294 continue;
295 }
296
297 if (status & TWE_STAT_PCIABR0x00100000) {
298 errstr = ": PCI abort\n";
299 continue;
300 }
301
302 while (!(status & TWE_STAT_RQE0x00004000)) {
303 bus_space_read_4(sc->iot, sc->ioh, TWE_READYQUEUE)((sc->iot)->read_4((sc->ioh), (0x0c)));
304 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
305 }
306
307 break;
308 }
309
310 if (retry < 0) {
311 printf("%s", errstr);
312 twe_dispose(sc);
313 return 1;
314 }
315
316 ccb = scsi_io_get(&sc->sc_iopool, 0);
317 if (ccb == NULL((void *)0)) {
318 printf(": out of ccbs\n");
319 twe_dispose(sc);
320 return 1;
321 }
322
323 ccb->ccb_xs = NULL((void *)0);
324 ccb->ccb_data = pb;
325 ccb->ccb_length = TWE_SECTOR_SIZE512;
326 ccb->ccb_state = TWE_CCB_READY;
327 cmd = ccb->ccb_cmd;
328 cmd->cmd_unit_host = TWE_UNITHOST(0, 0)(((0) & 0xf) | ((0) << 4));
329 cmd->cmd_op = TWE_CMD_GPARAM0x0252;
330 cmd->cmd_param_._cmd_param.count = 1;
331
332 pb->table_id = TWE_PARAM_UC0x003;
333 pb->param_id = TWE_PARAM_UC0x003;
334 pb->param_size = TWE_MAX_UNITS16;
335
336 error = twe_cmd(ccb, BUS_DMA_NOWAIT0x0001, 1);
337 scsi_io_put(&sc->sc_iopool, ccb);
338 if (error) {
339 printf(": failed to fetch unit parameters\n");
340 twe_dispose(sc);
341 return 1;
342 }
343
344 /* we are assuming last read status was good */
345 printf(": Escalade V%d.%d\n", TWE_MAJV(status)(((status) >> 28) & 0xf), TWE_MINV(status)(((status) >> 24) & 0xf));
346
347 for (nunits = i = 0; i < TWE_MAX_UNITS16; i++) {
348 if (pb->data[i] == 0)
349 continue;
350
351 ccb = scsi_io_get(&sc->sc_iopool, 0);
352 if (ccb == NULL((void *)0)) {
353 printf(": out of ccbs\n");
354 twe_dispose(sc);
355 return 1;
356 }
357
358 ccb->ccb_xs = NULL((void *)0);
359 ccb->ccb_data = cap;
360 ccb->ccb_length = TWE_SECTOR_SIZE512;
361 ccb->ccb_state = TWE_CCB_READY;
362 cmd = ccb->ccb_cmd;
363 cmd->cmd_unit_host = TWE_UNITHOST(0, 0)(((0) & 0xf) | ((0) << 4));
364 cmd->cmd_op = TWE_CMD_GPARAM0x0252;
365 cmd->cmd_param_._cmd_param.count = 1;
366
367 cap->table_id = TWE_PARAM_UI0x300 + i;
368 cap->param_id = 4;
369 cap->param_size = 4; /* 4 bytes */
370
371 lock = TWE_LOCK(sc)splraise(0x6);
372 error = twe_cmd(ccb, BUS_DMA_NOWAIT0x0001, 1);
373 TWE_UNLOCK(sc, lock)spllower(lock);
374 scsi_io_put(&sc->sc_iopool, ccb);
375 if (error) {
376 printf("%s: error fetching capacity for unit %d\n",
377 sc->sc_dev.dv_xname, i);
378 continue;
379 }
380
381 nunits++;
382 sc->sc_hdr[i].hd_present = 1;
383 sc->sc_hdr[i].hd_devtype = 0;
384 sc->sc_hdr[i].hd_size = letoh32(*(u_int32_t *)cap->data)((__uint32_t)(*(u_int32_t *)cap->data));
385 TWE_DPRINTF(TWE_D_MISC, ("twed%d: size=%d\n",
386 i, sc->sc_hdr[i].hd_size));
387 }
388
389 if (!nunits)
390 nunits++;
391
392 /* TODO: fetch & print cache params? */
393
394 saa.saa_adapter_softc = sc;
395 saa.saa_adapter = &twe_switch;
396 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET0xffff;
397 saa.saa_adapter_buswidth = TWE_MAX_UNITS16;
398 saa.saa_luns = 8;
399 saa.saa_openings = TWE_MAXCMDS255 / nunits;
400 saa.saa_pool = &sc->sc_iopool;
401 saa.saa_quirks = saa.saa_flags = 0;
402 saa.saa_wwpn = saa.saa_wwnn = 0;
403
404 config_found(&sc->sc_dev, &saa, scsiprint)config_found_sm((&sc->sc_dev), (&saa), (scsiprint)
, ((void *)0))
;
405
406 kthread_create_deferred(twe_thread_create, sc);
407
408 return (0);
409}
410
411void
412twe_thread_create(void *v)
413{
414 struct twe_softc *sc = v;
415
416 if (kthread_create(twe_thread, sc, &sc->sc_thread,
417 sc->sc_dev.dv_xname)) {
418 /* TODO disable twe */
419 printf("%s: failed to create kernel thread, disabled\n",
420 sc->sc_dev.dv_xname);
421 return;
422 }
423
424 TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
425 bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
426 /*
427 * ack all before enable, cannot be done in one
428 * operation as it seems clear is not processed
429 * if enable is specified.
430 */
431 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00080000 |
0x00040000 | 0x00000200)))
432 TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR)((sc->iot)->write_4((sc->ioh), (0x00), (0x00080000 |
0x00040000 | 0x00000200)))
;
433 TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
434 bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
435 /* enable interrupts */
436 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00000080 |
0x00004000 | 0x00020000)))
437 TWE_CTRL_EINT | TWE_CTRL_ERDYI |((sc->iot)->write_4((sc->ioh), (0x00), (0x00000080 |
0x00004000 | 0x00020000)))
438 /*TWE_CTRL_HOSTI |*/ TWE_CTRL_MCMDI)((sc->iot)->write_4((sc->ioh), (0x00), (0x00000080 |
0x00004000 | 0x00020000)))
;
439}
440
441void
442twe_thread(void *v)
443{
444 struct twe_softc *sc = v;
445 struct twe_ccb *ccb;
446 twe_lock_t lock;
447 u_int32_t status;
448 int err;
449
450 for (;;) {
451 lock = TWE_LOCK(sc)splraise(0x6);
452
453 while (!TAILQ_EMPTY(&sc->sc_done_ccb)(((&sc->sc_done_ccb)->tqh_first) == ((void *)0))) {
454 ccb = TAILQ_FIRST(&sc->sc_done_ccb)((&sc->sc_done_ccb)->tqh_first);
455 TAILQ_REMOVE(&sc->sc_done_ccb, ccb, ccb_link)do { if (((ccb)->ccb_link.tqe_next) != ((void *)0)) (ccb)->
ccb_link.tqe_next->ccb_link.tqe_prev = (ccb)->ccb_link.
tqe_prev; else (&sc->sc_done_ccb)->tqh_last = (ccb)
->ccb_link.tqe_prev; *(ccb)->ccb_link.tqe_prev = (ccb)->
ccb_link.tqe_next; ((ccb)->ccb_link.tqe_prev) = ((void *)-
1); ((ccb)->ccb_link.tqe_next) = ((void *)-1); } while (0)
;
456 if ((err = twe_done(sc, ccb)))
457 printf("%s: done failed (%d)\n",
458 sc->sc_dev.dv_xname, err);
459 }
460
461 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
462 TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
463 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
464 while (!(status & TWE_STAT_CQF0x00008000) &&
465 !TAILQ_EMPTY(&sc->sc_ccb2q)(((&sc->sc_ccb2q)->tqh_first) == ((void *)0))) {
466
467 ccb = TAILQ_LAST(&sc->sc_ccb2q, twe_queue_head)(*(((struct twe_queue_head *)((&sc->sc_ccb2q)->tqh_last
))->tqh_last))
;
468 TAILQ_REMOVE(&sc->sc_ccb2q, ccb, ccb_link)do { if (((ccb)->ccb_link.tqe_next) != ((void *)0)) (ccb)->
ccb_link.tqe_next->ccb_link.tqe_prev = (ccb)->ccb_link.
tqe_prev; else (&sc->sc_ccb2q)->tqh_last = (ccb)->
ccb_link.tqe_prev; *(ccb)->ccb_link.tqe_prev = (ccb)->ccb_link
.tqe_next; ((ccb)->ccb_link.tqe_prev) = ((void *)-1); ((ccb
)->ccb_link.tqe_next) = ((void *)-1); } while (0)
;
469
470 ccb->ccb_state = TWE_CCB_QUEUED;
471 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccbq)->tqh_last; *(&sc->
sc_ccbq)->tqh_last = (ccb); (&sc->sc_ccbq)->tqh_last
= &(ccb)->ccb_link.tqe_next; } while (0)
;
472 bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,((sc->iot)->write_4((sc->ioh), (0x08), (ccb->ccb_cmdpa
)))
473 ccb->ccb_cmdpa)((sc->iot)->write_4((sc->ioh), (0x08), (ccb->ccb_cmdpa
)))
;
474
475 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
476 TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
477 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
478 }
479
480 if (!TAILQ_EMPTY(&sc->sc_ccb2q)(((&sc->sc_ccb2q)->tqh_first) == ((void *)0)))
481 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00008000))
)
482 TWE_CTRL_ECMDI)((sc->iot)->write_4((sc->ioh), (0x00), (0x00008000))
)
;
483
484 TWE_UNLOCK(sc, lock)spllower(lock);
485 sc->sc_thread_on = 1;
486 tsleep_nsec(sc, PWAIT32, "twespank", INFSLP0xffffffffffffffffULL);
487 }
488}
489
490int
491twe_cmd(struct twe_ccb *ccb, int flags, int wait)
492{
493 struct twe_softc *sc = ccb->ccb_sc;
494 bus_dmamap_t dmap;
495 struct twe_cmd *cmd;
496 struct twe_segs *sgp;
497 int error, i;
498
499 if (ccb->ccb_data && ((u_long)ccb->ccb_data & (TWE_ALIGN512 - 1))) {
500 TWE_DPRINTF(TWE_D_DMA, ("data=%p is unaligned ",ccb->ccb_data));
501 ccb->ccb_realdata = ccb->ccb_data;
502
503 error = bus_dmamem_alloc(sc->dmat, ccb->ccb_length, PAGE_SIZE,(*(sc->dmat)->_dmamem_alloc)((sc->dmat), (ccb->ccb_length
), ((1 << 12)), (0), (ccb->ccb_2bseg), (62), (&ccb
->ccb_2nseg), (0x0001))
504 0, ccb->ccb_2bseg, TWE_MAXOFFSETS, &ccb->ccb_2nseg,(*(sc->dmat)->_dmamem_alloc)((sc->dmat), (ccb->ccb_length
), ((1 << 12)), (0), (ccb->ccb_2bseg), (62), (&ccb
->ccb_2nseg), (0x0001))
505 BUS_DMA_NOWAIT)(*(sc->dmat)->_dmamem_alloc)((sc->dmat), (ccb->ccb_length
), ((1 << 12)), (0), (ccb->ccb_2bseg), (62), (&ccb
->ccb_2nseg), (0x0001))
;
506 if (error) {
507 TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed(%d) ", error));
508 return (ENOMEM12);
509 }
510
511 error = bus_dmamem_map(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg,(*(sc->dmat)->_dmamem_map)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg), (ccb->ccb_length), ((caddr_t *)&
ccb->ccb_data), (0x0001))
512 ccb->ccb_length, (caddr_t *)&ccb->ccb_data, BUS_DMA_NOWAIT)(*(sc->dmat)->_dmamem_map)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg), (ccb->ccb_length), ((caddr_t *)&
ccb->ccb_data), (0x0001))
;
513 if (error) {
514 TWE_DPRINTF(TWE_D_DMA, ("2buf map failed(%d) ", error));
515 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg)(*(sc->dmat)->_dmamem_free)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg))
;
516 return (ENOMEM12);
517 }
518 bcopy(ccb->ccb_realdata, ccb->ccb_data, ccb->ccb_length);
519 } else
520 ccb->ccb_realdata = NULL((void *)0);
521
522 dmap = ccb->ccb_dmamap;
523 cmd = ccb->ccb_cmd;
524 cmd->cmd_status = 0;
525
526 if (ccb->ccb_data) {
527 error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data,(*(sc->dmat)->_dmamap_load)((sc->dmat), (dmap), (ccb
->ccb_data), (ccb->ccb_length), (((void *)0)), (flags))
528 ccb->ccb_length, NULL, flags)(*(sc->dmat)->_dmamap_load)((sc->dmat), (dmap), (ccb
->ccb_data), (ccb->ccb_length), (((void *)0)), (flags))
;
529 if (error) {
530 if (error == EFBIG27)
531 printf("more than %d dma segs\n", TWE_MAXOFFSETS62);
532 else
533 printf("error %d loading dma map\n", error);
534
535 if (ccb->ccb_realdata) {
536 bus_dmamem_unmap(sc->dmat, ccb->ccb_data,(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (ccb->ccb_data
), (ccb->ccb_length))
537 ccb->ccb_length)(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (ccb->ccb_data
), (ccb->ccb_length))
;
538 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,(*(sc->dmat)->_dmamem_free)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg))
539 ccb->ccb_2nseg)(*(sc->dmat)->_dmamem_free)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg))
;
540 }
541 return error;
542 }
543 /* load addresses into command */
544 switch (cmd->cmd_op) {
545 case TWE_CMD_GPARAM0x0252:
546 case TWE_CMD_SPARAM0x0253:
547 sgp = cmd->cmd_param_._cmd_param.segs;
548 break;
549 case TWE_CMD_READ0x0362:
550 case TWE_CMD_WRITE0x0363:
551 sgp = cmd->cmd_io_._cmd_io.segs;
552 break;
553 default:
554 /* no data transfer */
555 TWE_DPRINTF(TWE_D_DMA, ("twe_cmd: unknown sgp op=%x\n",
556 cmd->cmd_op));
557 sgp = NULL((void *)0);
558 break;
559 }
560 TWE_DPRINTF(TWE_D_DMA, ("data=%p<", ccb->ccb_data));
561 if (sgp) {
562 /*
563 * we know that size is in the upper byte,
564 * and we do not worry about overflow
565 */
566 cmd->cmd_op += (2 * dmap->dm_nsegs) << 8;
567 bzero (sgp, TWE_MAXOFFSETS * sizeof(*sgp))__builtin_bzero((sgp), (62 * sizeof(*sgp)));
568 for (i = 0; i < dmap->dm_nsegs; i++, sgp++) {
569 sgp->twes_addr = htole32(dmap->dm_segs[i].ds_addr)((__uint32_t)(dmap->dm_segs[i].ds_addr));
570 sgp->twes_len = htole32(dmap->dm_segs[i].ds_len)((__uint32_t)(dmap->dm_segs[i].ds_len));
571 TWE_DPRINTF(TWE_D_DMA, ("%lx[%lx] ",
572 dmap->dm_segs[i].ds_addr,
573 dmap->dm_segs[i].ds_len));
574 }
575 }
576 TWE_DPRINTF(TWE_D_DMA, ("> "));
577 bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize,(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), (0x04))
578 BUS_DMASYNC_PREWRITE)(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), (0x04))
;
579 }
580 bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sc->sc_cmdmap->dm_mapsize,(*(sc->dmat)->_dmamap_sync)((sc->dmat), (sc->sc_cmdmap
), (0), (sc->sc_cmdmap->dm_mapsize), (0x04))
581 BUS_DMASYNC_PREWRITE)(*(sc->dmat)->_dmamap_sync)((sc->dmat), (sc->sc_cmdmap
), (0), (sc->sc_cmdmap->dm_mapsize), (0x04))
;
582
583 if ((error = twe_start(ccb, wait))) {
584 bus_dmamap_unload(sc->dmat, dmap)(*(sc->dmat)->_dmamap_unload)((sc->dmat), (dmap));
585 if (ccb->ccb_realdata) {
586 bus_dmamem_unmap(sc->dmat, ccb->ccb_data,(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (ccb->ccb_data
), (ccb->ccb_length))
587 ccb->ccb_length)(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (ccb->ccb_data
), (ccb->ccb_length))
;
588 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,(*(sc->dmat)->_dmamem_free)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg))
589 ccb->ccb_2nseg)(*(sc->dmat)->_dmamem_free)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg))
;
590 }
591 return (error);
592 }
593
594 return wait? twe_complete(ccb) : 0;
595}
596
597int
598twe_start(struct twe_ccb *ccb, int wait)
599{
600 struct twe_softc*sc = ccb->ccb_sc;
601 struct twe_cmd *cmd = ccb->ccb_cmd;
602 u_int32_t status;
603 int i;
604
605 cmd->cmd_op = htole16(cmd->cmd_op)((__uint16_t)(cmd->cmd_op));
606
607 if (!wait) {
608
609 TWE_DPRINTF(TWE_D_CMD, ("prequeue(%d) ", cmd->cmd_index));
610 ccb->ccb_state = TWE_CCB_PREQUEUED;
611 TAILQ_INSERT_TAIL(&sc->sc_ccb2q, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccb2q)->tqh_last; *(&sc->
sc_ccb2q)->tqh_last = (ccb); (&sc->sc_ccb2q)->tqh_last
= &(ccb)->ccb_link.tqe_next; } while (0)
;
612 wakeup(sc);
613 return 0;
614 }
615
616 for (i = 1000; i--; DELAY(10)(*delay_func)(10)) {
617
618 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
619 if (!(status & TWE_STAT_CQF0x00008000))
620 break;
621 TWE_DPRINTF(TWE_D_CMD, ("twe_start stat=%b ",
622 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
623 }
624
625 if (!(status & TWE_STAT_CQF0x00008000)) {
626 bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,((sc->iot)->write_4((sc->ioh), (0x08), (ccb->ccb_cmdpa
)))
627 ccb->ccb_cmdpa)((sc->iot)->write_4((sc->ioh), (0x08), (ccb->ccb_cmdpa
)))
;
628
629 TWE_DPRINTF(TWE_D_CMD, ("queue(%d) ", cmd->cmd_index));
630 ccb->ccb_state = TWE_CCB_QUEUED;
631 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccbq)->tqh_last; *(&sc->
sc_ccbq)->tqh_last = (ccb); (&sc->sc_ccbq)->tqh_last
= &(ccb)->ccb_link.tqe_next; } while (0)
;
632 return 0;
633
634 } else {
635
636 printf("%s: twe_start(%d) timed out\n",
637 sc->sc_dev.dv_xname, cmd->cmd_index);
638
639 return EPERM1;
640 }
641}
642
643int
644twe_complete(struct twe_ccb *ccb)
645{
646 struct twe_softc *sc = ccb->ccb_sc;
647 struct scsi_xfer *xs = ccb->ccb_xs;
648 int i;
649
650 for (i = 100 * (xs? xs->timeout : 35000); i--; DELAY(10)(*delay_func)(10)) {
651 u_int32_t status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
652
653 /* TWE_DPRINTF(TWE_D_CMD, ("twe_intr stat=%b ",
654 status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */
655
656 while (!(status & TWE_STAT_RQE0x00004000)) {
657 struct twe_ccb *ccb1;
658 u_int32_t ready;
659
660 ready = bus_space_read_4(sc->iot, sc->ioh,((sc->iot)->read_4((sc->ioh), (0x0c)))
661 TWE_READYQUEUE)((sc->iot)->read_4((sc->ioh), (0x0c)));
662
663 TWE_DPRINTF(TWE_D_CMD, ("ready=%x ", ready));
664
665 ccb1 = &sc->sc_ccbs[TWE_READYID(ready)(((ready) >> 4) & 0xff)];
666 TAILQ_REMOVE(&sc->sc_ccbq, ccb1, ccb_link)do { if (((ccb1)->ccb_link.tqe_next) != ((void *)0)) (ccb1
)->ccb_link.tqe_next->ccb_link.tqe_prev = (ccb1)->ccb_link
.tqe_prev; else (&sc->sc_ccbq)->tqh_last = (ccb1)->
ccb_link.tqe_prev; *(ccb1)->ccb_link.tqe_prev = (ccb1)->
ccb_link.tqe_next; ((ccb1)->ccb_link.tqe_prev) = ((void *)
-1); ((ccb1)->ccb_link.tqe_next) = ((void *)-1); } while (
0)
;
667 ccb1->ccb_state = TWE_CCB_DONE;
668 if (!twe_done(sc, ccb1) && ccb1 == ccb) {
669 TWE_DPRINTF(TWE_D_CMD, ("complete\n"));
670 return 0;
671 }
672
673 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
674 /* TWE_DPRINTF(TWE_D_CMD, ("twe_intr stat=%b ",
675 status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */
676 }
677 }
678
679 return 1;
680}
681
682int
683twe_done(struct twe_softc *sc, struct twe_ccb *ccb)
684{
685 struct twe_cmd *cmd = ccb->ccb_cmd;
686 struct scsi_xfer *xs = ccb->ccb_xs;
687 bus_dmamap_t dmap;
688 twe_lock_t lock;
689
690 TWE_DPRINTF(TWE_D_CMD, ("done(%d) ", cmd->cmd_index));
691
692 if (ccb->ccb_state != TWE_CCB_DONE) {
693 printf("%s: undone ccb %d ready\n",
694 sc->sc_dev.dv_xname, cmd->cmd_index);
695 return 1;
696 }
697
698 dmap = ccb->ccb_dmamap;
699 if (xs) {
700 if (xs->cmd.opcode != PREVENT_ALLOW0x1e &&
701 xs->cmd.opcode != SYNCHRONIZE_CACHE0x35) {
702 bus_dmamap_sync(sc->dmat, dmap, 0,(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 :
0x08))
703 dmap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 :
0x08))
704 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 :
0x08))
;
705 bus_dmamap_unload(sc->dmat, dmap)(*(sc->dmat)->_dmamap_unload)((sc->dmat), (dmap));
706 }
707 } else {
708 switch (letoh16(cmd->cmd_op)((__uint16_t)(cmd->cmd_op))) {
709 case TWE_CMD_GPARAM0x0252:
710 case TWE_CMD_READ0x0362:
711 bus_dmamap_sync(sc->dmat, dmap, 0,(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), (0x02))
712 dmap->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), (0x02))
;
713 bus_dmamap_unload(sc->dmat, dmap)(*(sc->dmat)->_dmamap_unload)((sc->dmat), (dmap));
714 break;
715 case TWE_CMD_SPARAM0x0253:
716 case TWE_CMD_WRITE0x0363:
717 bus_dmamap_sync(sc->dmat, dmap, 0,(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), (0x08))
718 dmap->dm_mapsize, BUS_DMASYNC_POSTWRITE)(*(sc->dmat)->_dmamap_sync)((sc->dmat), (dmap), (0),
(dmap->dm_mapsize), (0x08))
;
719 bus_dmamap_unload(sc->dmat, dmap)(*(sc->dmat)->_dmamap_unload)((sc->dmat), (dmap));
720 break;
721 default:
722 /* no data */
723 break;
724 }
725 }
726
727 if (ccb->ccb_realdata) {
728 bcopy(ccb->ccb_data, ccb->ccb_realdata, ccb->ccb_length);
729 bus_dmamem_unmap(sc->dmat, ccb->ccb_data, ccb->ccb_length)(*(sc->dmat)->_dmamem_unmap)((sc->dmat), (ccb->ccb_data
), (ccb->ccb_length))
;
730 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg)(*(sc->dmat)->_dmamem_free)((sc->dmat), (ccb->ccb_2bseg
), (ccb->ccb_2nseg))
;
731 }
732
733 lock = TWE_LOCK(sc)splraise(0x6);
734
735 if (xs) {
736 xs->resid = 0;
737 scsi_done(xs);
738 }
739 TWE_UNLOCK(sc, lock)spllower(lock);
740
741 return 0;
742}
743
744void
745twe_scsi_cmd(struct scsi_xfer *xs)
746{
747 struct scsi_link *link = xs->sc_link;
748 struct twe_softc *sc = link->bus->sb_adapter_softc;
749 struct twe_ccb *ccb = xs->io;
750 struct twe_cmd *cmd;
751 struct scsi_inquiry_data inq;
752 struct scsi_sense_data sd;
753 struct scsi_read_cap_data rcd;
754 u_int8_t target = link->target;
755 u_int32_t blockno, blockcnt;
756 struct scsi_rw *rw;
757 struct scsi_rw_10 *rw10;
758 int error, op, flags, wait;
759 twe_lock_t lock;
760
761
762 if (target >= TWE_MAX_UNITS16 || !sc->sc_hdr[target].hd_present ||
763 link->lun != 0) {
764 xs->error = XS_DRIVER_STUFFUP2;
765 scsi_done(xs);
766 return;
767 }
768
769 TWE_DPRINTF(TWE_D_CMD, ("twe_scsi_cmd "));
770
771 xs->error = XS_NOERROR0;
772
773 switch (xs->cmd.opcode) {
774 case TEST_UNIT_READY0x00:
775 case START_STOP0x1b:
776#if 0
777 case VERIFY:
778#endif
779 TWE_DPRINTF(TWE_D_CMD, ("opc %d tgt %d ", xs->cmd.opcode,
780 target));
781 break;
782
783 case REQUEST_SENSE0x03:
784 TWE_DPRINTF(TWE_D_CMD, ("REQUEST SENSE tgt %d ", target));
785 bzero(&sd, sizeof sd)__builtin_bzero((&sd), (sizeof sd));
786 sd.error_code = SSD_ERRCODE_CURRENT0x70;
787 sd.segment = 0;
788 sd.flags = SKEY_NO_SENSE0x00;
789 *(u_int32_t*)sd.info = htole32(0)((__uint32_t)(0));
790 sd.extra_len = 0;
791 scsi_copy_internal_data(xs, &sd, sizeof(sd));
792 break;
793
794 case INQUIRY0x12:
795 TWE_DPRINTF(TWE_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
796 sc->sc_hdr[target].hd_devtype));
797 bzero(&inq, sizeof inq)__builtin_bzero((&inq), (sizeof inq));
798 inq.device =
799 (sc->sc_hdr[target].hd_devtype & 4) ? T_CDROM0x05 : T_DIRECT0x00;
800 inq.dev_qual2 =
801 (sc->sc_hdr[target].hd_devtype & 1) ? SID_REMOVABLE0x80 : 0;
802 inq.version = SCSI_REV_20x02;
803 inq.response_format = SID_SCSI2_RESPONSE0x02;
804 inq.additional_length = SID_SCSI2_ALEN31;
805 strlcpy(inq.vendor, "3WARE ", sizeof inq.vendor);
806 snprintf(inq.product, sizeof inq.product, "Host drive #%02d",
807 target);
808 strlcpy(inq.revision, " ", sizeof inq.revision);
809 scsi_copy_internal_data(xs, &inq, sizeof(inq));
810 break;
811
812 case READ_CAPACITY0x25:
813 TWE_DPRINTF(TWE_D_CMD, ("READ CAPACITY tgt %d ", target));
814 bzero(&rcd, sizeof rcd)__builtin_bzero((&rcd), (sizeof rcd));
815 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
816 _lto4b(TWE_SECTOR_SIZE512, rcd.length);
817 scsi_copy_internal_data(xs, &rcd, sizeof(rcd));
818 break;
819
820 case PREVENT_ALLOW0x1e:
821 TWE_DPRINTF(TWE_D_CMD, ("PREVENT/ALLOW "));
822 scsi_done(xs);
823 return;
824
825 case READ_COMMAND0x08:
826 case READ_100x28:
827 case WRITE_COMMAND0x0a:
828 case WRITE_100x2a:
829 case SYNCHRONIZE_CACHE0x35:
830 lock = TWE_LOCK(sc)splraise(0x6);
831
832 flags = 0;
833 if (xs->cmd.opcode == SYNCHRONIZE_CACHE0x35) {
834 blockno = blockcnt = 0;
835 } else {
836 /* A read or write operation. */
837 if (xs->cmdlen == 6) {
838 rw = (struct scsi_rw *)&xs->cmd;
839 blockno = _3btol(rw->addr) &
840 (SRW_TOPADDR0x1F << 16 | 0xffff);
841 blockcnt = rw->length ? rw->length : 0x100;
842 } else {
843 rw10 = (struct scsi_rw_10 *)&xs->cmd;
844 blockno = _4btol(rw10->addr);
845 blockcnt = _2btol(rw10->length);
846 /* reflect DPO & FUA flags */
847 if (xs->cmd.opcode == WRITE_100x2a &&
848 rw10->byte2 & 0x18)
849 flags = TWE_FLAGS_CACHEDISABLE0x01;
850 }
851 if (blockno >= sc->sc_hdr[target].hd_size ||
852 blockno + blockcnt > sc->sc_hdr[target].hd_size) {
853 printf("%s: out of bounds %u-%u >= %u\n",
854 sc->sc_dev.dv_xname, blockno, blockcnt,
855 sc->sc_hdr[target].hd_size);
856 xs->error = XS_DRIVER_STUFFUP2;
857 scsi_done(xs);
858 TWE_UNLOCK(sc, lock)spllower(lock);
859 return;
860 }
861 }
862
863 switch (xs->cmd.opcode) {
864 case READ_COMMAND0x08: op = TWE_CMD_READ0x0362; break;
865 case READ_100x28: op = TWE_CMD_READ0x0362; break;
866 case WRITE_COMMAND0x0a: op = TWE_CMD_WRITE0x0363; break;
867 case WRITE_100x2a: op = TWE_CMD_WRITE0x0363; break;
868 default: op = TWE_CMD_NOP0x0200; break;
869 }
870
871 ccb->ccb_xs = xs;
872 ccb->ccb_data = xs->data;
873 ccb->ccb_length = xs->datalen;
874 ccb->ccb_state = TWE_CCB_READY;
875 cmd = ccb->ccb_cmd;
876 cmd->cmd_unit_host = TWE_UNITHOST(target, 0)(((target) & 0xf) | ((0) << 4)); /* XXX why 0? */
877 cmd->cmd_op = op;
878 cmd->cmd_flags = flags;
879 cmd->cmd_io_._cmd_io.count = htole16(blockcnt)((__uint16_t)(blockcnt));
880 cmd->cmd_io_._cmd_io.lba = htole32(blockno)((__uint32_t)(blockno));
881 wait = xs->flags & SCSI_POLL0x00002;
882 if (!sc->sc_thread_on)
883 wait |= SCSI_POLL0x00002;
884
885 if ((error = twe_cmd(ccb, ((xs->flags & SCSI_NOSLEEP0x00001)?
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
886 BUS_DMA_NOWAIT0x0001 : BUS_DMA_WAITOK0x0000), wait))) {
887
888 TWE_DPRINTF(TWE_D_CMD, ("failed %p ", xs));
889 xs->error = XS_DRIVER_STUFFUP2;
890 scsi_done(xs);
891 }
892
893 TWE_UNLOCK(sc, lock)spllower(lock);
894 return;
895
896 default:
897 TWE_DPRINTF(TWE_D_CMD, ("unsupported scsi command %#x tgt %d ",
898 xs->cmd.opcode, target));
899 xs->error = XS_DRIVER_STUFFUP2;
900 }
901
902 scsi_done(xs);
903}
904
905int
906twe_intr(void *v)
907{
908 struct twe_softc *sc = v;
909 struct twe_ccb *ccb;
910 u_int32_t status;
911 int rv = 0;
912
913 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
914 TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
915 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
916#if 0
917 if (status & TWE_STAT_HOSTI0x00080000) {
918
919 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00080000))
)
920 TWE_CTRL_CHOSTI)((sc->iot)->write_4((sc->ioh), (0x00), (0x00080000))
)
;
921 }
922#endif
923
924 if (status & TWE_STAT_RDYI0x00010000) {
925
926 while (!(status & TWE_STAT_RQE0x00004000)) {
927
928 u_int32_t ready;
929
930 /*
931 * it seems that reading ready queue
932 * we get all the status bits in each ready word.
933 * i wonder if it's legal to use those for
934 * status and avoid extra read below
935 */
936 ready = bus_space_read_4(sc->iot, sc->ioh,((sc->iot)->read_4((sc->ioh), (0x0c)))
937 TWE_READYQUEUE)((sc->iot)->read_4((sc->ioh), (0x0c)));
938
939 ccb = &sc->sc_ccbs[TWE_READYID(ready)(((ready) >> 4) & 0xff)];
940 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link)do { if (((ccb)->ccb_link.tqe_next) != ((void *)0)) (ccb)->
ccb_link.tqe_next->ccb_link.tqe_prev = (ccb)->ccb_link.
tqe_prev; else (&sc->sc_ccbq)->tqh_last = (ccb)->
ccb_link.tqe_prev; *(ccb)->ccb_link.tqe_prev = (ccb)->ccb_link
.tqe_next; ((ccb)->ccb_link.tqe_prev) = ((void *)-1); ((ccb
)->ccb_link.tqe_next) = ((void *)-1); } while (0)
;
941 ccb->ccb_state = TWE_CCB_DONE;
942 TAILQ_INSERT_TAIL(&sc->sc_done_ccb, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_done_ccb)->tqh_last; *(&sc
->sc_done_ccb)->tqh_last = (ccb); (&sc->sc_done_ccb
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
943 rv++;
944
945 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS)((sc->iot)->read_4((sc->ioh), (0x04)));
946 TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
947 status & TWE_STAT_FLAGS, TWE_STAT_BITS));
948 }
949 }
950
951 if (status & TWE_STAT_CMDI0x00020000) {
952 rv++;
953 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00020000))
)
954 TWE_CTRL_MCMDI)((sc->iot)->write_4((sc->ioh), (0x00), (0x00020000))
)
;
955 }
956
957 if (rv)
958 wakeup(sc);
959
960 if (status & TWE_STAT_ATTNI0x00040000) {
961 /*
962 * we know no attentions of interest right now.
963 * one of those would be mirror degradation i think.
964 * or, what else exists in there?
965 * maybe 3ware can answer that?
966 */
967 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,((sc->iot)->write_4((sc->ioh), (0x00), (0x00040000))
)
968 TWE_CTRL_CATTNI)((sc->iot)->write_4((sc->ioh), (0x00), (0x00040000))
)
;
969
970 scsi_ioh_add(&sc->sc_aen);
971 }
972
973 return rv;
974}
975
976void
977twe_aen(void *cookie, void *io)
978{
979 struct twe_softc *sc = cookie;
980 struct twe_ccb *ccb = io;
981 struct twe_cmd *cmd = ccb->ccb_cmd;
982
983 u_int8_t param_buf[2 * TWE_SECTOR_SIZE512 + TWE_ALIGN512 - 1];
984 struct twe_param *pb = (void *) (((u_long)param_buf +
985 TWE_ALIGN512 - 1) & ~(TWE_ALIGN512 - 1));
986 u_int16_t aen;
987
988 twe_lock_t lock;
989 int error;
990
991 ccb->ccb_xs = NULL((void *)0);
992 ccb->ccb_data = pb;
993 ccb->ccb_length = TWE_SECTOR_SIZE512;
994 ccb->ccb_state = TWE_CCB_READY;
995 cmd->cmd_unit_host = TWE_UNITHOST(0, 0)(((0) & 0xf) | ((0) << 4));
996 cmd->cmd_op = TWE_CMD_GPARAM0x0252;
997 cmd->cmd_flags = 0;
998 cmd->cmd_param_._cmd_param.count = 1;
999
1000 pb->table_id = TWE_PARAM_AEN0x401;
1001 pb->param_id = 2;
1002 pb->param_size = 2;
1003
1004 lock = TWE_LOCK(sc)splraise(0x6);
1005 error = twe_cmd(ccb, BUS_DMA_NOWAIT0x0001, 1);
1006 TWE_UNLOCK(sc, lock)spllower(lock);
1007 scsi_io_put(&sc->sc_iopool, ccb);
1008
1009 if (error) {
1010 printf("%s: error draining attention queue\n",
1011 sc->sc_dev.dv_xname);
1012 return;
1013 }
1014
1015 aen = *(u_int16_t *)pb->data;
1016 if (aen != TWE_AEN_QEMPTY0x0000)
1017 scsi_ioh_add(&sc->sc_aen);
1018}