Bug Summary

File:dev/ic/ami.c
Warning:line 1874, column 7
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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ami.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/ic/ami.c
1/* $OpenBSD: ami.c,v 1.262 2022/04/16 19:19:58 naddy Exp $ */
2
3/*
4 * Copyright (c) 2001 Michael Shalayeff
5 * Copyright (c) 2005 Marco Peereboom
6 * Copyright (c) 2006 David Gwynne
7 * All rights reserved.
8 *
9 * The SCSI emulation layer is derived from gdt(4) driver,
10 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33/*
34 * American Megatrends Inc. MegaRAID controllers driver
35 *
36 * This driver was made because these ppl and organizations
37 * donated hardware and provided documentation:
38 *
39 * - 428 model card
40 * John Kerbawy, Stephan Matis, Mark Stovall;
41 *
42 * - 467 and 475 model cards, docs
43 * American Megatrends Inc.;
44 *
45 * - uninterruptible electric power for cvs
46 * Theo de Raadt.
47 */
48
49#include "bio.h"
50
51/* #define AMI_DEBUG */
52
53#include <sys/param.h>
54#include <sys/systm.h>
55#include <sys/buf.h>
56#include <sys/ioctl.h>
57#include <sys/device.h>
58#include <sys/kernel.h>
59#include <sys/malloc.h>
60#include <sys/rwlock.h>
61#include <sys/pool.h>
62#include <sys/sensors.h>
63
64#include <machine/bus.h>
65
66#include <scsi/scsi_all.h>
67#include <scsi/scsi_disk.h>
68#include <scsi/scsiconf.h>
69
70#include <dev/biovar.h>
71#include <dev/ic/amireg.h>
72#include <dev/ic/amivar.h>
73
74#ifdef AMI_DEBUG
75#define AMI_DPRINTF(m,a) do { if (ami_debug & (m)) printf a; } while (0)
76#define AMI_D_CMD 0x0001
77#define AMI_D_INTR 0x0002
78#define AMI_D_MISC 0x0004
79#define AMI_D_DMA 0x0008
80#define AMI_D_IOCTL 0x0010
81int ami_debug = 0
82/* | AMI_D_CMD */
83/* | AMI_D_INTR */
84/* | AMI_D_MISC */
85/* | AMI_D_DMA */
86/* | AMI_D_IOCTL */
87 ;
88#else
89#define AMI_DPRINTF(m,a) /* m, a */
90#endif
91
92struct cfdriver ami_cd = {
93 NULL((void *)0), "ami", DV_DULL
94};
95
96void ami_scsi_cmd(struct scsi_xfer *);
97int ami_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int);
98
99const struct scsi_adapter ami_switch = {
100 ami_scsi_cmd, NULL((void *)0), NULL((void *)0), NULL((void *)0), ami_scsi_ioctl
101};
102
103void ami_scsi_raw_cmd(struct scsi_xfer *);
104
105const struct scsi_adapter ami_raw_switch = {
106 ami_scsi_raw_cmd, NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0)
107};
108
109void * ami_get_ccb(void *);
110void ami_put_ccb(void *, void *);
111
112u_int32_t ami_read(struct ami_softc *, bus_size_t);
113void ami_write(struct ami_softc *, bus_size_t, u_int32_t);
114
115void ami_copyhds(struct ami_softc *, const u_int32_t *,
116 const u_int8_t *, const u_int8_t *);
117struct ami_mem *ami_allocmem(struct ami_softc *, size_t);
118void ami_freemem(struct ami_softc *, struct ami_mem *);
119int ami_alloc_ccbs(struct ami_softc *, int);
120
121int ami_poll(struct ami_softc *, struct ami_ccb *);
122void ami_start(struct ami_softc *, struct ami_ccb *);
123void ami_complete(struct ami_softc *, struct ami_ccb *, int);
124void ami_runqueue_tick(void *);
125void ami_runqueue(struct ami_softc *);
126
127void ami_start_xs(struct ami_softc *sc, struct ami_ccb *,
128 struct scsi_xfer *);
129void ami_done_xs(struct ami_softc *, struct ami_ccb *);
130void ami_done_pt(struct ami_softc *, struct ami_ccb *);
131void ami_done_flush(struct ami_softc *, struct ami_ccb *);
132void ami_done_sysflush(struct ami_softc *, struct ami_ccb *);
133
134void ami_done_dummy(struct ami_softc *, struct ami_ccb *);
135void ami_done_ioctl(struct ami_softc *, struct ami_ccb *);
136void ami_done_init(struct ami_softc *, struct ami_ccb *);
137
138int ami_load_ptmem(struct ami_softc*, struct ami_ccb *,
139 void *, size_t, int, int);
140
141#if NBIO1 > 0
142int ami_mgmt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t,
143 u_int8_t, size_t, void *);
144int ami_drv_pt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t *,
145 int, int, void *);
146int ami_drv_readcap(struct ami_softc *, u_int8_t, u_int8_t,
147 daddr_t *);
148int ami_drv_inq(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t,
149 void *);
150int ami_ioctl(struct device *, u_long, caddr_t);
151int ami_ioctl_inq(struct ami_softc *, struct bioc_inq *);
152int ami_vol(struct ami_softc *, struct bioc_vol *,
153 struct ami_big_diskarray *);
154int ami_disk(struct ami_softc *, struct bioc_disk *,
155 struct ami_big_diskarray *);
156int ami_ioctl_vol(struct ami_softc *, struct bioc_vol *);
157int ami_ioctl_disk(struct ami_softc *, struct bioc_disk *);
158int ami_ioctl_alarm(struct ami_softc *, struct bioc_alarm *);
159int ami_ioctl_setstate(struct ami_softc *, struct bioc_setstate *);
160
161#ifndef SMALL_KERNEL
162int ami_create_sensors(struct ami_softc *);
163void ami_refresh_sensors(void *);
164#endif
165#endif /* NBIO > 0 */
166
167#define DEVNAME(_s)((_s)->sc_dev.dv_xname) ((_s)->sc_dev.dv_xname)
168
169void *
170ami_get_ccb(void *xsc)
171{
172 struct ami_softc *sc = xsc;
173 struct ami_ccb *ccb;
174
175 mtx_enter(&sc->sc_ccb_freeq_mtx);
176 ccb = TAILQ_FIRST(&sc->sc_ccb_freeq)((&sc->sc_ccb_freeq)->tqh_first);
177 if (ccb != NULL((void *)0)) {
178 TAILQ_REMOVE(&sc->sc_ccb_freeq, 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_ccb_freeq)->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)
;
179 ccb->ccb_state = AMI_CCB_READY;
180 }
181 mtx_leave(&sc->sc_ccb_freeq_mtx);
182
183 return (ccb);
184}
185
186void
187ami_put_ccb(void *xsc, void *xccb)
188{
189 struct ami_softc *sc = xsc;
190 struct ami_ccb *ccb = xccb;
191
192 ccb->ccb_state = AMI_CCB_FREE;
193 ccb->ccb_xs = NULL((void *)0);
194 ccb->ccb_flags = 0;
195 ccb->ccb_done = NULL((void *)0);
196
197 mtx_enter(&sc->sc_ccb_freeq_mtx);
198 TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccb_freeq)->tqh_last; *(&sc
->sc_ccb_freeq)->tqh_last = (ccb); (&sc->sc_ccb_freeq
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
199 mtx_leave(&sc->sc_ccb_freeq_mtx);
200}
201
202u_int32_t
203ami_read(struct ami_softc *sc, bus_size_t r)
204{
205 u_int32_t rv;
206
207 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
208 BUS_SPACE_BARRIER_READ0x01);
209 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r)((sc->sc_iot)->read_4((sc->sc_ioh), (r)));
210
211 AMI_DPRINTF(AMI_D_CMD, ("ari 0x%lx 0x08%x ", r, rv));
212 return (rv);
213}
214
215void
216ami_write(struct ami_softc *sc, bus_size_t r, u_int32_t v)
217{
218 AMI_DPRINTF(AMI_D_CMD, ("awo 0x%lx 0x%08x ", r, v));
219
220 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v)((sc->sc_iot)->write_4((sc->sc_ioh), (r), (v)));
221 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
222 BUS_SPACE_BARRIER_WRITE0x02);
223}
224
225struct ami_mem *
226ami_allocmem(struct ami_softc *sc, size_t size)
227{
228 struct ami_mem *am;
229 int nsegs;
230
231 am = malloc(sizeof(struct ami_mem), M_DEVBUF2, M_NOWAIT0x0002|M_ZERO0x0008);
232 if (am == NULL((void *)0))
233 return (NULL((void *)0));
234
235 am->am_size = size;
236
237 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (size
), (1), (size), (0), (0x0001 | 0x0002), (&am->am_map))
238 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &am->am_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (size
), (1), (size), (0), (0x0001 | 0x0002), (&am->am_map))
!= 0)
239 goto amfree;
240
241 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &am->am_seg, 1,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (size
), ((1 << 12)), (0), (&am->am_seg), (1), (&nsegs
), (0x0001 | 0x1000))
242 &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (size
), ((1 << 12)), (0), (&am->am_seg), (1), (&nsegs
), (0x0001 | 0x1000))
!= 0)
243 goto destroy;
244
245 if (bus_dmamem_map(sc->sc_dmat, &am->am_seg, nsegs, size, &am->am_kva,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&am
->am_seg), (nsegs), (size), (&am->am_kva), (0x0001)
)
246 BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&am
->am_seg), (nsegs), (size), (&am->am_kva), (0x0001)
)
!= 0)
247 goto free;
248
249 if (bus_dmamap_load(sc->sc_dmat, am->am_map, am->am_kva, size, NULL,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (am->
am_map), (am->am_kva), (size), (((void *)0)), (0x0001))
250 BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (am->
am_map), (am->am_kva), (size), (((void *)0)), (0x0001))
!= 0)
251 goto unmap;
252
253 return (am);
254
255unmap:
256 bus_dmamem_unmap(sc->sc_dmat, am->am_kva, size)(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), (am->
am_kva), (size))
;
257free:
258 bus_dmamem_free(sc->sc_dmat, &am->am_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
am->am_seg), (1))
;
259destroy:
260 bus_dmamap_destroy(sc->sc_dmat, am->am_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (am
->am_map))
;
261amfree:
262 free(am, M_DEVBUF2, sizeof *am);
263
264 return (NULL((void *)0));
265}
266
267void
268ami_freemem(struct ami_softc *sc, struct ami_mem *am)
269{
270 bus_dmamap_unload(sc->sc_dmat, am->am_map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (am->
am_map))
;
271 bus_dmamem_unmap(sc->sc_dmat, am->am_kva, am->am_size)(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), (am->
am_kva), (am->am_size))
;
272 bus_dmamem_free(sc->sc_dmat, &am->am_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (&
am->am_seg), (1))
;
273 bus_dmamap_destroy(sc->sc_dmat, am->am_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (am
->am_map))
;
274 free(am, M_DEVBUF2, sizeof *am);
275}
276
277void
278ami_copyhds(struct ami_softc *sc, const u_int32_t *sizes,
279 const u_int8_t *props, const u_int8_t *stats)
280{
281 int i;
282
283 for (i = 0; i < sc->sc_nunits; i++) {
284 sc->sc_hdr[i].hd_present = 1;
285 sc->sc_hdr[i].hd_is_logdrv = 1;
286 sc->sc_hdr[i].hd_size = letoh32(sizes[i])((__uint32_t)(sizes[i]));
287 sc->sc_hdr[i].hd_prop = props[i];
288 sc->sc_hdr[i].hd_stat = stats[i];
289 }
290}
291
292int
293ami_alloc_ccbs(struct ami_softc *sc, int nccbs)
294{
295 struct ami_ccb *ccb;
296 struct ami_ccbmem *ccbmem, *mem;
297 int i, error;
298
299 sc->sc_ccbs = mallocarray(nccbs, sizeof(struct ami_ccb),
300 M_DEVBUF2, M_NOWAIT0x0002);
301 if (sc->sc_ccbs == NULL((void *)0)) {
302 printf(": unable to allocate ccbs\n");
303 return (1);
304 }
305
306 sc->sc_ccbmem_am = ami_allocmem(sc, sizeof(struct ami_ccbmem) * nccbs);
307 if (sc->sc_ccbmem_am == NULL((void *)0)) {
308 printf(": unable to allocate ccb dmamem\n");
309 goto free_ccbs;
310 }
311 ccbmem = AMIMEM_KVA(sc->sc_ccbmem_am)((void *)(sc->sc_ccbmem_am)->am_kva);
312
313 TAILQ_INIT(&sc->sc_ccb_freeq)do { (&sc->sc_ccb_freeq)->tqh_first = ((void *)0); (
&sc->sc_ccb_freeq)->tqh_last = &(&sc->sc_ccb_freeq
)->tqh_first; } while (0)
;
314 mtx_init(&sc->sc_ccb_freeq_mtx, IPL_BIO)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_ccb_freeq_mtx), ((((0x3)) > 0x0 && ((0x3)) <
0x9) ? 0x9 : ((0x3)))); } while (0)
;
315 TAILQ_INIT(&sc->sc_ccb_preq)do { (&sc->sc_ccb_preq)->tqh_first = ((void *)0); (
&sc->sc_ccb_preq)->tqh_last = &(&sc->sc_ccb_preq
)->tqh_first; } while (0)
;
316 TAILQ_INIT(&sc->sc_ccb_runq)do { (&sc->sc_ccb_runq)->tqh_first = ((void *)0); (
&sc->sc_ccb_runq)->tqh_last = &(&sc->sc_ccb_runq
)->tqh_first; } while (0)
;
317 timeout_set(&sc->sc_run_tmo, ami_runqueue_tick, sc);
318
319 scsi_iopool_init(&sc->sc_iopool, sc, ami_get_ccb, ami_put_ccb);
320
321 for (i = 0; i < nccbs; i++) {
322 ccb = &sc->sc_ccbs[i];
323 mem = &ccbmem[i];
324
325 error = bus_dmamap_create(sc->sc_dmat, AMI_MAXFER,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((26
* (1 << 12))), (26), ((26 * (1 << 12))), (0), (0x0001
| 0x0002), (&ccb->ccb_dmamap))
326 AMI_MAXOFFSETS, AMI_MAXFER, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((26
* (1 << 12))), (26), ((26 * (1 << 12))), (0), (0x0001
| 0x0002), (&ccb->ccb_dmamap))
327 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((26
* (1 << 12))), (26), ((26 * (1 << 12))), (0), (0x0001
| 0x0002), (&ccb->ccb_dmamap))
;
328 if (error) {
329 printf(": cannot create ccb dmamap (%d)\n", error);
330 goto free_list;
331 }
332
333 ccb->ccb_sc = sc;
334
335 ccb->ccb_cmd.acc_id = i + 1;
336 ccb->ccb_offset = sizeof(struct ami_ccbmem) * i;
337
338 ccb->ccb_pt = &mem->cd_pt;
339 ccb->ccb_ptpa = htole32(AMIMEM_DVA(sc->sc_ccbmem_am) +((__uint32_t)(((sc->sc_ccbmem_am)->am_map->dm_segs[0
].ds_addr) + ccb->ccb_offset))
340 ccb->ccb_offset)((__uint32_t)(((sc->sc_ccbmem_am)->am_map->dm_segs[0
].ds_addr) + ccb->ccb_offset))
;
341
342 ccb->ccb_sglist = mem->cd_sg;
343 ccb->ccb_sglistpa = htole32(AMIMEM_DVA(sc->sc_ccbmem_am) +((__uint32_t)(((sc->sc_ccbmem_am)->am_map->dm_segs[0
].ds_addr) + ccb->ccb_offset + sizeof(struct ami_passthrough
)))
344 ccb->ccb_offset + sizeof(struct ami_passthrough))((__uint32_t)(((sc->sc_ccbmem_am)->am_map->dm_segs[0
].ds_addr) + ccb->ccb_offset + sizeof(struct ami_passthrough
)))
;
345
346 /* override last command for management */
347 if (i == nccbs - 1) {
348 ccb->ccb_cmd.acc_id = 0xfe;
349 sc->sc_mgmtccb = ccb;
350 } else {
351 ami_put_ccb(sc, ccb);
352 }
353 }
354
355 return (0);
356
357free_list:
358 while ((ccb = ami_get_ccb(sc)) != NULL((void *)0))
359 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (ccb
->ccb_dmamap))
;
360
361 ami_freemem(sc, sc->sc_ccbmem_am);
362free_ccbs:
363 free(sc->sc_ccbs, M_DEVBUF2, 0);
364
365 return (1);
366}
367
368int
369ami_attach(struct ami_softc *sc)
370{
371 struct scsibus_attach_args saa;
372 struct ami_rawsoftc *rsc;
373 struct ami_ccb iccb;
374 struct ami_iocmd *cmd;
375 struct ami_mem *am;
376 struct ami_inquiry *inq;
377 struct ami_fc_einquiry *einq;
378 struct ami_fc_prodinfo *pi;
379 const char *p;
380 paddr_t pa;
381
382 mtx_init(&sc->sc_cmd_mtx, IPL_BIO)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_cmd_mtx), ((((0x3)) > 0x0 && ((0x3)) < 0x9) ?
0x9 : ((0x3)))); } while (0)
;
383
384 am = ami_allocmem(sc, NBPG(1 << 12));
385 if (am == NULL((void *)0)) {
386 printf(": unable to allocate init data\n");
387 return (1);
388 }
389 pa = htole32(AMIMEM_DVA(am))((__uint32_t)(((am)->am_map->dm_segs[0].ds_addr)));
390
391 sc->sc_mbox_am = ami_allocmem(sc, sizeof(struct ami_iocmd));
392 if (sc->sc_mbox_am == NULL((void *)0)) {
393 printf(": unable to allocate mbox\n");
394 goto free_idata;
395 }
396 sc->sc_mbox = (volatile struct ami_iocmd *)AMIMEM_KVA(sc->sc_mbox_am)((void *)(sc->sc_mbox_am)->am_kva);
397 sc->sc_mbox_pa = htole32(AMIMEM_DVA(sc->sc_mbox_am))((__uint32_t)(((sc->sc_mbox_am)->am_map->dm_segs[0].
ds_addr)))
;
398 AMI_DPRINTF(AMI_D_CMD, ("mbox=%p ", sc->sc_mbox));
399 AMI_DPRINTF(AMI_D_CMD, ("mbox_pa=0x%llx ", (long long)sc->sc_mbox_pa));
400
401 /* create a spartan ccb for use with ami_poll */
402 bzero(&iccb, sizeof(iccb))__builtin_bzero((&iccb), (sizeof(iccb)));
403 iccb.ccb_sc = sc;
404 iccb.ccb_done = ami_done_init;
405 cmd = &iccb.ccb_cmd;
406
407 (sc->sc_init)(sc);
408
409 /* try FC inquiry first */
410 cmd->acc_cmd = AMI_FCOP0xa1;
411 cmd->acc_io_._ami_io.aio_channel = AMI_FC_EINQ30x0f;
412 cmd->acc_io_._ami_io.aio_param = AMI_FC_EINQ3_SOLICITED_FULL0x02;
413 cmd->acc_io_._ami_io.aio_data = pa;
414 if (ami_poll(sc, &iccb) == 0) {
415 einq = AMIMEM_KVA(am)((void *)(am)->am_kva);
416 pi = AMIMEM_KVA(am)((void *)(am)->am_kva);
417
418 sc->sc_nunits = einq->ain_nlogdrv;
419 sc->sc_drvinscnt = einq->ain_drvinscnt + 1; /* force scan */
420 ami_copyhds(sc, einq->ain_ldsize, einq->ain_ldprop,
421 einq->ain_ldstat);
422
423 cmd->acc_cmd = AMI_FCOP0xa1;
424 cmd->acc_io_._ami_io.aio_channel = AMI_FC_PRODINF0x0e;
425 cmd->acc_io_._ami_io.aio_param = 0;
426 cmd->acc_io_._ami_io.aio_data = pa;
427 if (ami_poll(sc, &iccb) == 0) {
428 sc->sc_maxunits = AMI_BIG_MAX_LDRIVES40;
429
430 bcopy (pi->api_fwver, sc->sc_fwver, 16);
431 sc->sc_fwver[15] = '\0';
432 bcopy (pi->api_biosver, sc->sc_biosver, 16);
433 sc->sc_biosver[15] = '\0';
434 sc->sc_channels = pi->api_channels;
435 sc->sc_targets = pi->api_fcloops;
436 sc->sc_memory = letoh16(pi->api_ramsize)((__uint16_t)(pi->api_ramsize));
437 sc->sc_maxcmds = pi->api_maxcmd;
438 p = "FC loop";
439 }
440 }
441
442 if (sc->sc_maxunits == 0) {
443 inq = AMIMEM_KVA(am)((void *)(am)->am_kva);
444
445 cmd->acc_cmd = AMI_EINQUIRY0x04;
446 cmd->acc_io_._ami_io.aio_channel = 0;
447 cmd->acc_io_._ami_io.aio_param = 0;
448 cmd->acc_io_._ami_io.aio_data = pa;
449 if (ami_poll(sc, &iccb) != 0) {
450 cmd->acc_cmd = AMI_INQUIRY0x05;
451 cmd->acc_io_._ami_io.aio_channel = 0;
452 cmd->acc_io_._ami_io.aio_param = 0;
453 cmd->acc_io_._ami_io.aio_data = pa;
454 if (ami_poll(sc, &iccb) != 0) {
455 printf(": cannot do inquiry\n");
456 goto free_mbox;
457 }
458 }
459
460 sc->sc_maxunits = AMI_MAX_LDRIVES8;
461 sc->sc_nunits = inq->ain_nlogdrv;
462 ami_copyhds(sc, inq->ain_ldsize, inq->ain_ldprop,
463 inq->ain_ldstat);
464
465 bcopy (inq->ain_fwver, sc->sc_fwver, 4);
466 sc->sc_fwver[4] = '\0';
467 bcopy (inq->ain_biosver, sc->sc_biosver, 4);
468 sc->sc_biosver[4] = '\0';
469 sc->sc_channels = inq->ain_channels;
470 sc->sc_targets = inq->ain_targets;
471 sc->sc_memory = inq->ain_ramsize;
472 sc->sc_maxcmds = inq->ain_maxcmd;
473 sc->sc_drvinscnt = inq->ain_drvinscnt + 1; /* force scan */
474 p = "target";
475 }
476
477 if (sc->sc_flags & AMI_BROKEN0x0002) {
478 sc->sc_maxcmds = 1;
479 sc->sc_maxunits = 1;
480 } else {
481 sc->sc_maxunits = AMI_BIG_MAX_LDRIVES40;
482 if (sc->sc_maxcmds > AMI_MAXCMDS126)
483 sc->sc_maxcmds = AMI_MAXCMDS126;
484 /*
485 * Reserve ccb's for ioctl's and raw commands to
486 * processors/enclosures by lowering the number of
487 * openings available for logical units.
488 */
489 sc->sc_maxcmds -= AMI_MAXIOCTLCMDS1 + AMI_MAXPROCS2 *
490 AMI_MAXRAWCMDS2 * sc->sc_channels;
491 }
492
493 if (ami_alloc_ccbs(sc, AMI_MAXCMDS126 + 1) != 0) {
494 /* error already printed */
495 goto free_mbox;
496 }
497
498 ami_freemem(sc, am);
499
500 /* hack for hp netraid version encoding */
501 if ('A' <= sc->sc_fwver[2] && sc->sc_fwver[2] <= 'Z' &&
502 sc->sc_fwver[1] < ' ' && sc->sc_fwver[0] < ' ' &&
503 'A' <= sc->sc_biosver[2] && sc->sc_biosver[2] <= 'Z' &&
504 sc->sc_biosver[1] < ' ' && sc->sc_biosver[0] < ' ') {
505
506 snprintf(sc->sc_fwver, sizeof sc->sc_fwver, "%c.%02d.%02d",
507 sc->sc_fwver[2], sc->sc_fwver[1], sc->sc_fwver[0]);
508 snprintf(sc->sc_biosver, sizeof sc->sc_biosver, "%c.%02d.%02d",
509 sc->sc_biosver[2], sc->sc_biosver[1], sc->sc_biosver[0]);
510 }
511
512 /* TODO: fetch & print cache strategy */
513 /* TODO: fetch & print scsi and raid info */
514
515#ifdef AMI_DEBUG
516 printf(", FW %s, BIOS v%s, %dMB RAM\n"
517 "%s: %d channels, %d %ss, %d logical drives, "
518 "max commands %d, quirks: %04x\n",
519 sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc)((sc)->sc_dev.dv_xname),
520 sc->sc_channels, sc->sc_targets, p, sc->sc_nunits,
521 sc->sc_maxcmds, sc->sc_flags);
522#else
523 printf(", FW %s, BIOS v%s, %dMB RAM\n"
524 "%s: %d channels, %d %ss, %d logical drives\n",
525 sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc)((sc)->sc_dev.dv_xname),
526 sc->sc_channels, sc->sc_targets, p, sc->sc_nunits);
527#endif /* AMI_DEBUG */
528
529 if (sc->sc_flags & AMI_BROKEN0x0002 && sc->sc_nunits > 1)
530 printf("%s: firmware buggy, limiting access to first logical "
531 "disk\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
532
533 /* lock around ioctl requests */
534 rw_init(&sc->sc_lock, NULL)_rw_init_flags(&sc->sc_lock, ((void *)0), 0, ((void *)
0))
;
535
536 saa.saa_adapter_softc = sc;
537 saa.saa_adapter = &ami_switch;
538 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET0xffff;
539 saa.saa_adapter_buswidth = sc->sc_maxunits;
540 saa.saa_luns = 8;
541 saa.saa_openings = sc->sc_maxcmds;
542 saa.saa_pool = &sc->sc_iopool;
543 saa.saa_quirks = saa.saa_flags = 0;
544 saa.saa_wwpn = saa.saa_wwnn = 0;
545
546 sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, &saa,config_found_sm((&sc->sc_dev), (&saa), (scsiprint)
, ((void *)0))
547 scsiprint)config_found_sm((&sc->sc_dev), (&saa), (scsiprint)
, ((void *)0))
;
548
549 /* can't do bioctls, sensors, or pass-through on broken devices */
550 if (sc->sc_flags & AMI_BROKEN0x0002)
551 return (0);
552
553#if NBIO1 > 0
554 if (bio_register(&sc->sc_dev, ami_ioctl) != 0)
555 printf("%s: controller registration failed\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
556 else
557 sc->sc_ioctl = ami_ioctl;
558
559#ifndef SMALL_KERNEL
560 if (ami_create_sensors(sc) != 0)
561 printf("%s: unable to create sensors\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
562#endif
563#endif
564
565 rsc = mallocarray(sc->sc_channels, sizeof(struct ami_rawsoftc),
566 M_DEVBUF2, M_NOWAIT0x0002|M_ZERO0x0008);
567 if (!rsc) {
568 printf("%s: no memory for raw interface\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
569 return (0);
570 }
571
572 for (sc->sc_rawsoftcs = rsc;
573 rsc < &sc->sc_rawsoftcs[sc->sc_channels]; rsc++) {
574
575 struct scsibus_softc *ptbus;
576 struct scsi_link *proclink;
577 struct device *procdev;
578
579 rsc->sc_softc = sc;
580 rsc->sc_channel = rsc - sc->sc_rawsoftcs;
581 rsc->sc_proctarget = -1;
582
583 /* TODO fetch adapter_target from the controller */
584
585 saa.saa_adapter_softc = rsc;
586 saa.saa_adapter = &ami_raw_switch;
587 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET0xffff;
588 saa.saa_adapter_buswidth = 16;
589 saa.saa_luns = 8;
590 saa.saa_openings = sc->sc_maxcmds;
591 saa.saa_pool = &sc->sc_iopool;
592 saa.saa_quirks = saa.saa_flags = 0;
593 saa.saa_wwpn = saa.saa_wwnn = 0;
594
595 ptbus = (struct scsibus_softc *)config_found(&sc->sc_dev,config_found_sm((&sc->sc_dev), (&saa), (scsiprint)
, ((void *)0))
596 &saa, scsiprint)config_found_sm((&sc->sc_dev), (&saa), (scsiprint)
, ((void *)0))
;
597
598 if (ptbus == NULL((void *)0) || rsc->sc_proctarget == -1)
599 continue;
600
601 proclink = scsi_get_link(ptbus, rsc->sc_proctarget, 0);
602 if (proclink == NULL((void *)0))
603 continue;
604
605 procdev = proclink->device_softc;
606 strlcpy(rsc->sc_procdev, procdev->dv_xname,
607 sizeof(rsc->sc_procdev));
608 }
609
610 return (0);
611
612free_mbox:
613 ami_freemem(sc, sc->sc_mbox_am);
614free_idata:
615 ami_freemem(sc, am);
616
617 return (1);
618}
619
620int
621ami_quartz_init(struct ami_softc *sc)
622{
623 ami_write(sc, AMI_QIDB0x20, 0);
624
625 return (0);
626}
627
628int
629ami_quartz_exec(struct ami_softc *sc, struct ami_iocmd *cmd)
630{
631 if (sc->sc_mbox->acc_busy) {
632 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
633 return (EBUSY16);
634 }
635
636 memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16)__builtin_memcpy(((struct ami_iocmd *)sc->sc_mbox), (cmd),
(16))
;
637 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x04
|0x01))
638 sizeof(struct ami_iocmd), BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x04
|0x01))
;
639
640 sc->sc_mbox->acc_busy = 1;
641 sc->sc_mbox->acc_poll = 0;
642 sc->sc_mbox->acc_ack = 0;
643
644 ami_write(sc, AMI_QIDB0x20, sc->sc_mbox_pa | htole32(AMI_QIDB_EXEC)((__uint32_t)(0x01)));
645
646 return (0);
647}
648
649int
650ami_quartz_done(struct ami_softc *sc, struct ami_iocmd *mbox)
651{
652 u_int32_t i, n;
653 u_int8_t nstat, status;
654 u_int8_t completed[AMI_MAXSTATACK0x2e];
655
656 if (ami_read(sc, AMI_QODB0x2c) != AMI_QODB_READY0x10001234)
657 return (0); /* nothing to do */
658
659 ami_write(sc, AMI_QODB0x2c, AMI_QODB_READY0x10001234);
660
661 /*
662 * The following sequence is not supposed to have a timeout clause
663 * since the firmware has a "guarantee" that all commands will
664 * complete. The choice is either panic or hoping for a miracle
665 * and that the IOs will complete much later.
666 */
667 i = 0;
668 while ((nstat = sc->sc_mbox->acc_nstat) == 0xff) {
669 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x02
))
670 sizeof(struct ami_iocmd), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x02
))
;
671 delay(1)(*delay_func)(1);
672 if (i++ > 1000000)
673 return (0); /* nothing to do */
674 }
675 sc->sc_mbox->acc_nstat = 0xff;
676 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x08
))
677 sizeof(struct ami_iocmd), BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x08
))
;
678
679 /* wait until fw wrote out all completions */
680 i = 0;
681 AMI_DPRINTF(AMI_D_CMD, ("aqd %d ", nstat));
682 for (n = 0; n < nstat; n++) {
683 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x01
))
684 sizeof(struct ami_iocmd), BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x01
))
;
685 while ((completed[n] = sc->sc_mbox->acc_cmplidl[n]) == 0xff) {
686 delay(1)(*delay_func)(1);
687 if (i++ > 1000000)
688 return (0); /* nothing to do */
689 }
690 sc->sc_mbox->acc_cmplidl[n] = 0xff;
691 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x08
))
692 sizeof(struct ami_iocmd), BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x08
))
;
693 }
694
695 /* this should never happen, someone screwed up the completion status */
696 if ((status = sc->sc_mbox->acc_status) == 0xff)
697 panic("%s: status 0xff from the firmware", DEVNAME(sc)((sc)->sc_dev.dv_xname));
698
699 sc->sc_mbox->acc_status = 0xff;
700
701 /* copy mailbox to temporary one and fixup other changed values */
702 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (16), (0x08))
703 BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (16), (0x08))
;
704 memcpy(mbox, (struct ami_iocmd *)sc->sc_mbox, 16)__builtin_memcpy((mbox), ((struct ami_iocmd *)sc->sc_mbox)
, (16))
;
705 mbox->acc_nstat = nstat;
706 mbox->acc_status = status;
707 for (n = 0; n < nstat; n++)
708 mbox->acc_cmplidl[n] = completed[n];
709
710 /* ack interrupt */
711 ami_write(sc, AMI_QIDB0x20, AMI_QIDB_ACK0x02);
712
713 return (1); /* ready to complete all IOs in acc_cmplidl */
714}
715
716int
717ami_quartz_poll(struct ami_softc *sc, struct ami_iocmd *cmd)
718{
719 /* struct scsi_xfer *xs = ccb->ccb_xs; */
720 u_int32_t i;
721 u_int8_t status;
722
723 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x3, __func__
); } } while (0)
;
724
725 if (sc->sc_dis_poll)
726 return (-1); /* fail */
727
728 i = 0;
729 while (sc->sc_mbox->acc_busy && (i < AMI_MAX_BUSYWAIT10)) {
730 delay(1)(*delay_func)(1);
731 i++;
732 }
733 if (sc->sc_mbox->acc_busy) {
734 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
735 return (-1);
736 }
737
738 memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16)__builtin_memcpy(((struct ami_iocmd *)sc->sc_mbox), (cmd),
(16))
;
739 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (16), (0x04|0x01))
740 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (16), (0x04|0x01))
;
741
742 sc->sc_mbox->acc_id = 0xfe;
743 sc->sc_mbox->acc_busy = 1;
744 sc->sc_mbox->acc_poll = 0;
745 sc->sc_mbox->acc_ack = 0;
746 sc->sc_mbox->acc_nstat = 0xff;
747 sc->sc_mbox->acc_status = 0xff;
748
749 /* send command to firmware */
750 ami_write(sc, AMI_QIDB0x20, sc->sc_mbox_pa | htole32(AMI_QIDB_EXEC)((__uint32_t)(0x01)));
751
752 i = 0;
753 while ((sc->sc_mbox->acc_nstat == 0xff) && (i < AMI_MAX_POLLWAIT1000000)) {
754 delay(1)(*delay_func)(1);
755 i++;
756 }
757 if (i >= AMI_MAX_POLLWAIT1000000) {
758 printf("%s: command not accepted, polling disabled\n",
759 DEVNAME(sc)((sc)->sc_dev.dv_xname));
760 sc->sc_dis_poll = 1;
761 return (-1);
762 }
763
764 /* poll firmware */
765 i = 0;
766 while ((sc->sc_mbox->acc_poll != 0x77) && (i < AMI_MAX_POLLWAIT1000000)) {
767 delay(1)(*delay_func)(1);
768 i++;
769 }
770 if (i >= AMI_MAX_POLLWAIT1000000) {
771 printf("%s: firmware didn't reply, polling disabled\n",
772 DEVNAME(sc)((sc)->sc_dev.dv_xname));
773 sc->sc_dis_poll = 1;
774 return (-1);
775 }
776
777 /* ack */
778 ami_write(sc, AMI_QIDB0x20, sc->sc_mbox_pa | htole32(AMI_QIDB_ACK)((__uint32_t)(0x02)));
779
780 i = 0;
781 while((ami_read(sc, AMI_QIDB0x20) & AMI_QIDB_ACK0x02) &&
782 (i < AMI_MAX_POLLWAIT1000000)) {
783 delay(1)(*delay_func)(1);
784 i++;
785 }
786 if (i >= AMI_MAX_POLLWAIT1000000) {
787 printf("%s: firmware didn't ack the ack, polling disabled\n",
788 DEVNAME(sc)((sc)->sc_dev.dv_xname));
789 sc->sc_dis_poll = 1;
790 return (-1);
791 }
792
793 sc->sc_mbox->acc_poll = 0;
794 sc->sc_mbox->acc_ack = 0x77;
795 status = sc->sc_mbox->acc_status;
796 sc->sc_mbox->acc_nstat = 0xff;
797 sc->sc_mbox->acc_status = 0xff;
798
799 for (i = 0; i < AMI_MAXSTATACK0x2e; i++)
800 sc->sc_mbox->acc_cmplidl[i] = 0xff;
801
802 return (status);
803}
804
805int
806ami_schwartz_init(struct ami_softc *sc)
807{
808 u_int32_t a = (u_int32_t)sc->sc_mbox_pa;
809
810 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AMI_SMBADDR, a)((sc->sc_iot)->write_4((sc->sc_ioh), (0x14), (a)));
811 /* XXX 40bit address ??? */
812 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SMBENA, 0)((sc->sc_iot)->write_1((sc->sc_ioh), (0x18), (0)));
813
814 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_ACK)((sc->sc_iot)->write_1((sc->sc_ioh), (0x10), (0x08))
)
;
815 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SIEM, AMI_SEIM_ENA |((sc->sc_iot)->write_1((sc->sc_ioh), (0x11), (0xc0 |
((sc->sc_iot)->read_1((sc->sc_ioh), (0x11))))))
816 bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SIEM))((sc->sc_iot)->write_1((sc->sc_ioh), (0x11), (0xc0 |
((sc->sc_iot)->read_1((sc->sc_ioh), (0x11))))))
;
817
818 return (0);
819}
820
821int
822ami_schwartz_exec(struct ami_softc *sc, struct ami_iocmd *cmd)
823{
824 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT)((sc->sc_iot)->read_1((sc->sc_ioh), (0x10))) &
825 AMI_SMBST_BUSY0x10) {
826 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
827 return (EBUSY16);
828 }
829
830 memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16)__builtin_memcpy(((struct ami_iocmd *)sc->sc_mbox), (cmd),
(16))
;
831 sc->sc_mbox->acc_busy = 1;
832 sc->sc_mbox->acc_poll = 0;
833 sc->sc_mbox->acc_ack = 0;
834
835 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_EXEC)((sc->sc_iot)->write_1((sc->sc_ioh), (0x10), (0x10))
)
;
836 return (0);
837}
838
839int
840ami_schwartz_done(struct ami_softc *sc, struct ami_iocmd *mbox)
841{
842 u_int8_t stat;
843
844#if 0
845 /* do not scramble the busy mailbox */
846 if (sc->sc_mbox->acc_busy)
847 return (0);
848#endif
849 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT)((sc->sc_iot)->read_1((sc->sc_ioh), (0x10))) &
850 AMI_SMBST_BUSY0x10)
851 return (0);
852
853 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT)((sc->sc_iot)->read_1((sc->sc_ioh), (0x1a)));
854 if (stat & AMI_ISTAT_PEND0x40) {
855 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT, stat)((sc->sc_iot)->write_1((sc->sc_ioh), (0x1a), (stat))
)
;
856
857 *mbox = *sc->sc_mbox;
858 AMI_DPRINTF(AMI_D_CMD, ("asd %d ", mbox->acc_nstat));
859
860 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD,((sc->sc_iot)->write_1((sc->sc_ioh), (0x10), (0x08))
)
861 AMI_SCMD_ACK)((sc->sc_iot)->write_1((sc->sc_ioh), (0x10), (0x08))
)
;
862
863 return (1);
864 }
865
866 return (0);
867}
868
869int
870ami_schwartz_poll(struct ami_softc *sc, struct ami_iocmd *mbox)
871{
872 u_int8_t status;
873 u_int32_t i;
874 int rv;
875
876 splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x3, __func__
); } } while (0)
;
877
878 if (sc->sc_dis_poll)
879 return (-1); /* fail */
880
881 for (i = 0; i < AMI_MAX_POLLWAIT1000000; i++) {
882 if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT)((sc->sc_iot)->read_1((sc->sc_ioh), (0x10))) &
883 AMI_SMBST_BUSY0x10))
884 break;
885 delay(1)(*delay_func)(1);
886 }
887 if (i >= AMI_MAX_POLLWAIT1000000) {
888 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
889 return (-1);
890 }
891
892 memcpy((struct ami_iocmd *)sc->sc_mbox, mbox, 16)__builtin_memcpy(((struct ami_iocmd *)sc->sc_mbox), (mbox)
, (16))
;
893 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (16), (0x04|0x01))
894 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (16), (0x04|0x01))
;
895
896 sc->sc_mbox->acc_busy = 1;
897 sc->sc_mbox->acc_poll = 0;
898 sc->sc_mbox->acc_ack = 0;
899 /* send command to firmware */
900 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_EXEC)((sc->sc_iot)->write_1((sc->sc_ioh), (0x10), (0x10))
)
;
901
902 /* wait until no longer busy */
903 for (i = 0; i < AMI_MAX_POLLWAIT1000000; i++) {
904 if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT)((sc->sc_iot)->read_1((sc->sc_ioh), (0x10))) &
905 AMI_SMBST_BUSY0x10))
906 break;
907 delay(1)(*delay_func)(1);
908 }
909 if (i >= AMI_MAX_POLLWAIT1000000) {
910 printf("%s: command not accepted, polling disabled\n",
911 DEVNAME(sc)((sc)->sc_dev.dv_xname));
912 sc->sc_dis_poll = 1;
913 return (-1);
914 }
915
916 /* wait for interrupt bit */
917 for (i = 0; i < AMI_MAX_POLLWAIT1000000; i++) {
918 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT)((sc->sc_iot)->read_1((sc->sc_ioh), (0x1a)));
919 if (status & AMI_ISTAT_PEND0x40)
920 break;
921 delay(1)(*delay_func)(1);
922 }
923 if (i >= AMI_MAX_POLLWAIT1000000) {
924 printf("%s: interrupt didn't arrive, polling disabled\n",
925 DEVNAME(sc)((sc)->sc_dev.dv_xname));
926 sc->sc_dis_poll = 1;
927 return (-1);
928 }
929
930 /* write ststus back to firmware */
931 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT, status)((sc->sc_iot)->write_1((sc->sc_ioh), (0x1a), (status
)))
;
932
933 /* copy mailbox and status back */
934 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x01
))
935 sizeof(struct ami_iocmd), BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_mbox_am)->am_map)), (0), (sizeof(struct ami_iocmd)), (0x01
))
;
936 *mbox = *sc->sc_mbox;
937 rv = sc->sc_mbox->acc_status;
938
939 /* ack interrupt */
940 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_ACK)((sc->sc_iot)->write_1((sc->sc_ioh), (0x10), (0x08))
)
;
941
942 return (rv);
943}
944
945void
946ami_start_xs(struct ami_softc *sc, struct ami_ccb *ccb, struct scsi_xfer *xs)
947{
948 if (xs->flags & SCSI_POLL0x00002)
949 ami_complete(sc, ccb, xs->timeout);
950 else
951 ami_start(sc, ccb);
952}
953
954void
955ami_start(struct ami_softc *sc, struct ami_ccb *ccb)
956{
957 mtx_enter(&sc->sc_cmd_mtx);
958 ccb->ccb_state = AMI_CCB_PREQUEUED;
959 TAILQ_INSERT_TAIL(&sc->sc_ccb_preq, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccb_preq)->tqh_last; *(&sc
->sc_ccb_preq)->tqh_last = (ccb); (&sc->sc_ccb_preq
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
960 mtx_leave(&sc->sc_cmd_mtx);
961
962 ami_runqueue(sc);
963}
964
965void
966ami_runqueue_tick(void *arg)
967{
968 ami_runqueue(arg);
969}
970
971void
972ami_runqueue(struct ami_softc *sc)
973{
974 struct ami_ccb *ccb;
975 int add = 0;
976
977 mtx_enter(&sc->sc_cmd_mtx);
978 if (!sc->sc_drainio) {
979 while ((ccb = TAILQ_FIRST(&sc->sc_ccb_preq)((&sc->sc_ccb_preq)->tqh_first)) != NULL((void *)0)) {
980 if (sc->sc_exec(sc, &ccb->ccb_cmd) != 0) {
981 add = 1;
982 break;
983 }
984
985 TAILQ_REMOVE(&sc->sc_ccb_preq, 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_ccb_preq)->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)
;
986 ccb->ccb_state = AMI_CCB_QUEUED;
987 TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccb_runq)->tqh_last; *(&sc
->sc_ccb_runq)->tqh_last = (ccb); (&sc->sc_ccb_runq
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
988 }
989 }
990 mtx_leave(&sc->sc_cmd_mtx);
991
992 if (add)
993 timeout_add(&sc->sc_run_tmo, 1);
994}
995
996int
997ami_poll(struct ami_softc *sc, struct ami_ccb *ccb)
998{
999 int error;
1000
1001 mtx_enter(&sc->sc_cmd_mtx);
1002 error = sc->sc_poll(sc, &ccb->ccb_cmd);
1003 if (error == -1)
1004 ccb->ccb_flags |= AMI_CCB_F_ERR(1<<0);
1005 mtx_leave(&sc->sc_cmd_mtx);
1006
1007 ccb->ccb_done(sc, ccb);
1008
1009 return (error);
1010}
1011
1012void
1013ami_complete(struct ami_softc *sc, struct ami_ccb *ccb, int timeout)
1014{
1015 void (*done)(struct ami_softc *, struct ami_ccb *);
1016 int ready;
1017 int i = 0;
1018 int s;
1019
1020 done = ccb->ccb_done;
1021 ccb->ccb_done = ami_done_dummy;
1022
1023 /*
1024 * since exec will return if the mbox is busy we have to busy wait
1025 * ourselves. once its in, jam it into the runq.
1026 */
1027 mtx_enter(&sc->sc_cmd_mtx);
1028 while (i < AMI_MAX_BUSYWAIT10) {
1029 if (sc->sc_exec(sc, &ccb->ccb_cmd) == 0) {
1030 ccb->ccb_state = AMI_CCB_QUEUED;
1031 TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link)do { (ccb)->ccb_link.tqe_next = ((void *)0); (ccb)->ccb_link
.tqe_prev = (&sc->sc_ccb_runq)->tqh_last; *(&sc
->sc_ccb_runq)->tqh_last = (ccb); (&sc->sc_ccb_runq
)->tqh_last = &(ccb)->ccb_link.tqe_next; } while (0
)
;
1032 break;
1033 }
1034 DELAY(1000)(*delay_func)(1000);
1035 i++;
1036 }
1037 ready = (ccb->ccb_state == AMI_CCB_QUEUED);
1038 mtx_leave(&sc->sc_cmd_mtx);
1039
1040 if (!ready) {
1041 ccb->ccb_flags |= AMI_CCB_F_ERR(1<<0);
1042 ccb->ccb_state = AMI_CCB_READY;
1043 goto done;
1044 }
1045
1046 /*
1047 * Override timeout for PERC3. The first command triggers a chip
1048 * reset on the QL12160 chip which causes the firmware to reload.
1049 * 30000 is slightly less than double of how long it takes for the
1050 * firmware to be up again. After the first two commands the
1051 * timeouts are as expected.
1052 */
1053 timeout = MAX(30000, timeout)(((30000)>(timeout))?(30000):(timeout)); /* timeout */
1054
1055 while (ccb->ccb_state == AMI_CCB_QUEUED) {
1056 s = splbio()splraise(0x3); /* interrupt handlers are called at their IPL */
1057 ready = ami_intr(sc);
1058 splx(s)spllower(s);
1059
1060 if (ready == 0) {
1061 if (timeout-- == 0) {
1062 /* XXX */
1063 printf("%s: timeout\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
1064 return;
1065 }
1066
1067 delay(1000)(*delay_func)(1000);
1068 continue;
1069 }
1070 }
1071
1072done:
1073 done(sc, ccb);
1074}
1075
1076void
1077ami_done_pt(struct ami_softc *sc, struct ami_ccb *ccb)
1078{
1079 struct scsi_xfer *xs = ccb->ccb_xs;
1080 struct scsi_link *link = xs->sc_link;
1081 struct ami_rawsoftc *rsc = link->bus->sb_adapter_softc;
1082 u_int8_t target = link->target, type;
1083
1084 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
1085 ccb->ccb_offset, sizeof(struct ami_ccbmem),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
1086 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
;
1087
1088 if (xs->data != NULL((void *)0)) {
1089 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
1090 ccb->ccb_dmamap->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
1091 (xs->flags & SCSI_DATA_IN) ?(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
1092 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
;
1093
1094 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (ccb
->ccb_dmamap))
;
1095 }
1096
1097 xs->resid = 0;
1098
1099 if (ccb->ccb_flags & AMI_CCB_F_ERR(1<<0))
1100 xs->error = XS_DRIVER_STUFFUP2;
1101 else if (ccb->ccb_status != 0x00)
1102 xs->error = XS_DRIVER_STUFFUP2;
1103 else if (xs->flags & SCSI_POLL0x00002 && xs->cmd.opcode == INQUIRY0x12) {
1104 type = ((struct scsi_inquiry_data *)xs->data)->device &
1105 SID_TYPE0x1f;
1106 if (!(type == T_PROCESSOR0x03 || type == T_ENCLOSURE0x0d))
1107 xs->error = XS_DRIVER_STUFFUP2;
1108 else
1109 rsc->sc_proctarget = target;
1110 }
1111
1112 scsi_done(xs);
1113}
1114
1115void
1116ami_done_xs(struct ami_softc *sc, struct ami_ccb *ccb)
1117{
1118 struct scsi_xfer *xs = ccb->ccb_xs;
1119
1120 if (xs->data != NULL((void *)0)) {
1121 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
1122 ccb->ccb_dmamap->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
1123 (xs->flags & SCSI_DATA_IN) ?(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
1124 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x02 : 0x08))
;
1125
1126 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
1127 ccb->ccb_offset, sizeof(struct ami_ccbmem),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
1128 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
;
1129
1130 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (ccb
->ccb_dmamap))
;
1131 }
1132
1133 xs->resid = 0;
1134
1135 if (ccb->ccb_flags & AMI_CCB_F_ERR(1<<0))
1136 xs->error = XS_DRIVER_STUFFUP2;
1137
1138 scsi_done(xs);
1139}
1140
1141void
1142ami_done_flush(struct ami_softc *sc, struct ami_ccb *ccb)
1143{
1144 struct scsi_xfer *xs = ccb->ccb_xs;
1145 struct ami_iocmd *cmd = &ccb->ccb_cmd;
1146
1147 if (ccb->ccb_flags & AMI_CCB_F_ERR(1<<0)) {
1148 xs->error = XS_DRIVER_STUFFUP2;
1149 xs->resid = 0;
1150
1151 scsi_done(xs);
1152 return;
1153 }
1154
1155 /* reuse the ccb for the sysflush command */
1156 ccb->ccb_done = ami_done_sysflush;
1157 cmd->acc_cmd = AMI_SYSFLUSH0xfe;
1158
1159 ami_start_xs(sc, ccb, xs);
1160}
1161
1162void
1163ami_done_sysflush(struct ami_softc *sc, struct ami_ccb *ccb)
1164{
1165 struct scsi_xfer *xs = ccb->ccb_xs;
1166
1167 xs->resid = 0;
1168 if (ccb->ccb_flags & AMI_CCB_F_ERR(1<<0))
1169 xs->error = XS_DRIVER_STUFFUP2;
1170
1171 scsi_done(xs);
1172}
1173
1174void
1175ami_done_dummy(struct ami_softc *sc, struct ami_ccb *ccb)
1176{
1177}
1178
1179void
1180ami_done_ioctl(struct ami_softc *sc, struct ami_ccb *ccb)
1181{
1182 wakeup(ccb);
1183}
1184
1185void
1186ami_done_init(struct ami_softc *sc, struct ami_ccb *ccb)
1187{
1188 /* the ccb is going to be reused, so do nothing with it */
1189}
1190
1191void
1192ami_scsi_raw_cmd(struct scsi_xfer *xs)
1193{
1194 struct scsi_link *link = xs->sc_link;
1195 struct ami_rawsoftc *rsc = link->bus->sb_adapter_softc;
1196 struct ami_softc *sc = rsc->sc_softc;
1197 u_int8_t channel = rsc->sc_channel, target = link->target;
1198 struct ami_ccb *ccb;
1199
1200 AMI_DPRINTF(AMI_D_CMD, ("ami_scsi_raw_cmd "));
1201
1202 if (xs->cmdlen > AMI_MAX_CDB10) {
1203 AMI_DPRINTF(AMI_D_CMD, ("CDB too big %p ", xs));
1204 bzero(&xs->sense, sizeof(xs->sense))__builtin_bzero((&xs->sense), (sizeof(xs->sense)));
1205 xs->sense.error_code = SSD_ERRCODE_VALID0x80 | SSD_ERRCODE_CURRENT0x70;
1206 xs->sense.flags = SKEY_ILLEGAL_REQUEST0x05;
1207 xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
1208 xs->error = XS_SENSE1;
1209 scsi_done(xs);
1210 return;
1211 }
1212
1213 xs->error = XS_NOERROR0;
1214
1215 ccb = xs->io;
1216
1217 memset(ccb->ccb_pt, 0, sizeof(struct ami_passthrough))__builtin_memset((ccb->ccb_pt), (0), (sizeof(struct ami_passthrough
)))
;
1218
1219 ccb->ccb_xs = xs;
1220 ccb->ccb_done = ami_done_pt;
1221
1222 ccb->ccb_cmd.acc_cmd = AMI_PASSTHRU0x03;
1223 ccb->ccb_cmd.acc_passthru_._ami_passthru.apt_data = ccb->ccb_ptpa;
1224
1225 ccb->ccb_pt->apt_param = AMI_PTPARAM(AMI_TIMEOUT_6,1,0)(((0) << 7) | (((1) & 1) << 3) | ((0) & 3
))
;
1226 ccb->ccb_pt->apt_channel = channel;
1227 ccb->ccb_pt->apt_target = target;
1228 bcopy(&xs->cmd, ccb->ccb_pt->apt_cdb, AMI_MAX_CDB10);
1229 ccb->ccb_pt->apt_ncdb = xs->cmdlen;
1230 ccb->ccb_pt->apt_nsense = AMI_MAX_SENSE32;
1231 ccb->ccb_pt->apt_datalen = xs->datalen;
1232 ccb->ccb_pt->apt_data = 0;
1233
1234 if (ami_load_ptmem(sc, ccb, xs->data, xs->datalen,
1235 xs->flags & SCSI_DATA_IN0x00800, xs->flags & SCSI_NOSLEEP0x00001) != 0) {
1236 xs->error = XS_DRIVER_STUFFUP2;
1237 scsi_done(xs);
1238 return;
1239 }
1240
1241 ami_start_xs(sc, ccb, xs);
1242}
1243
1244int
1245ami_load_ptmem(struct ami_softc *sc, struct ami_ccb *ccb, void *data,
1246 size_t len, int read, int nowait)
1247{
1248 bus_dmamap_t dmap = ccb->ccb_dmamap;
1249 bus_dma_segment_t *sgd;
1250 int error, i;
1251
1252 if (data != NULL((void *)0)) {
1253 error = bus_dmamap_load(sc->sc_dmat, dmap, data, len, NULL,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (dmap)
, (data), (len), (((void *)0)), (nowait ? 0x0001 : 0x0000))
1254 nowait ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (dmap)
, (data), (len), (((void *)0)), (nowait ? 0x0001 : 0x0000))
;
1255 if (error) {
1256 if (error == EFBIG27)
1257 printf("more than %d dma segs\n",
1258 AMI_MAXOFFSETS26);
1259 else
1260 printf("error %d loading dma map\n", error);
1261
1262 return (1);
1263 }
1264
1265 sgd = dmap->dm_segs;
1266 if (dmap->dm_nsegs > 1) {
1267 struct ami_sgent *sgl = ccb->ccb_sglist;
1268
1269 ccb->ccb_pt->apt_nsge = dmap->dm_nsegs;
1270 ccb->ccb_pt->apt_data = ccb->ccb_sglistpa;
1271
1272 for (i = 0; i < dmap->dm_nsegs; i++) {
1273 sgl[i].asg_addr = htole32(sgd[i].ds_addr)((__uint32_t)(sgd[i].ds_addr));
1274 sgl[i].asg_len = htole32(sgd[i].ds_len)((__uint32_t)(sgd[i].ds_len));
1275 }
1276 } else {
1277 ccb->ccb_pt->apt_nsge = 0;
1278 ccb->ccb_pt->apt_data = htole32(sgd->ds_addr)((__uint32_t)(sgd->ds_addr));
1279 }
1280
1281 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dmap)
, (0), (dmap->dm_mapsize), (read ? 0x01 : 0x04))
1282 read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dmap)
, (0), (dmap->dm_mapsize), (read ? 0x01 : 0x04))
;
1283 }
1284
1285 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x01 | 0x04))
1286 ccb->ccb_offset, sizeof(struct ami_ccbmem),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x01 | 0x04))
1287 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x01 | 0x04))
;
1288
1289 return (0);
1290}
1291
1292void
1293ami_scsi_cmd(struct scsi_xfer *xs)
1294{
1295 struct scsi_link *link = xs->sc_link;
1296 struct ami_softc *sc = link->bus->sb_adapter_softc;
1297 struct device *dev = link->device_softc;
1298 struct ami_ccb *ccb;
1299 struct ami_iocmd *cmd;
1300 struct scsi_inquiry_data inq;
1301 struct scsi_sense_data sd;
1302 struct scsi_read_cap_data rcd;
1303 u_int8_t target = link->target;
1304 u_int32_t blockno, blockcnt;
1305 struct scsi_rw *rw;
1306 struct scsi_rw_10 *rw10;
1307 bus_dma_segment_t *sgd;
1308 int error;
1309 int i;
1310
1311 AMI_DPRINTF(AMI_D_CMD, ("ami_scsi_cmd "));
1312
1313 if (target >= sc->sc_nunits || !sc->sc_hdr[target].hd_present ||
1314 link->lun != 0) {
1315 AMI_DPRINTF(AMI_D_CMD, ("no target %d ", target));
1316 /* XXX should be XS_SENSE and sense filled out */
1317 xs->error = XS_DRIVER_STUFFUP2;
1318 scsi_done(xs);
1319 return;
1320 }
1321
1322 xs->error = XS_NOERROR0;
1323
1324 switch (xs->cmd.opcode) {
1325 case READ_COMMAND0x08:
1326 case READ_100x28:
1327 case WRITE_COMMAND0x0a:
1328 case WRITE_100x2a:
1329 /* deal with io outside the switch */
1330 break;
1331
1332 case SYNCHRONIZE_CACHE0x35:
1333 ccb = xs->io;
1334
1335 ccb->ccb_xs = xs;
1336 ccb->ccb_done = ami_done_flush;
1337 if (xs->timeout < 30000)
1338 xs->timeout = 30000; /* at least 30sec */
1339
1340 cmd = &ccb->ccb_cmd;
1341 cmd->acc_cmd = AMI_FLUSH0x0a;
1342
1343 ami_start_xs(sc, ccb, xs);
1344 return;
1345
1346 case TEST_UNIT_READY0x00:
1347 /* save off sd? after autoconf */
1348 if (!cold) /* XXX bogus */
1349 strlcpy(sc->sc_hdr[target].dev, dev->dv_xname,
1350 sizeof(sc->sc_hdr[target].dev));
1351 case START_STOP0x1b:
1352#if 0
1353 case VERIFY:
1354#endif
1355 case PREVENT_ALLOW0x1e:
1356 AMI_DPRINTF(AMI_D_CMD, ("opc %d tgt %d ", xs->cmd.opcode,
1357 target));
1358 xs->error = XS_NOERROR0;
1359 scsi_done(xs);
1360 return;
1361
1362 case REQUEST_SENSE0x03:
1363 AMI_DPRINTF(AMI_D_CMD, ("REQUEST SENSE tgt %d ", target));
1364 bzero(&sd, sizeof(sd))__builtin_bzero((&sd), (sizeof(sd)));
1365 sd.error_code = SSD_ERRCODE_CURRENT0x70;
1366 sd.segment = 0;
1367 sd.flags = SKEY_NO_SENSE0x00;
1368 *(u_int32_t*)sd.info = htole32(0)((__uint32_t)(0));
1369 sd.extra_len = 0;
1370 scsi_copy_internal_data(xs, &sd, sizeof(sd));
1371
1372 xs->error = XS_NOERROR0;
1373 scsi_done(xs);
1374 return;
1375
1376 case INQUIRY0x12:
1377 if (ISSET(((struct scsi_inquiry *)&xs->cmd)->flags, SI_EVPD)((((struct scsi_inquiry *)&xs->cmd)->flags) & (
0x01))
) {
1378 xs->error = XS_DRIVER_STUFFUP2;
1379 scsi_done(xs);
1380 return;
1381 }
1382
1383 AMI_DPRINTF(AMI_D_CMD, ("INQUIRY tgt %d ", target));
1384 bzero(&inq, sizeof(inq))__builtin_bzero((&inq), (sizeof(inq)));
1385 inq.device = T_DIRECT0x00;
1386 inq.dev_qual2 = 0;
1387 inq.version = SCSI_REV_20x02;
1388 inq.response_format = SID_SCSI2_RESPONSE0x02;
1389 inq.additional_length = SID_SCSI2_ALEN31;
1390 inq.flags |= SID_CmdQue0x02;
1391 strlcpy(inq.vendor, "AMI ", sizeof(inq.vendor));
1392 snprintf(inq.product, sizeof(inq.product),
1393 "Host drive #%02d", target);
1394 strlcpy(inq.revision, " ", sizeof(inq.revision));
1395 scsi_copy_internal_data(xs, &inq, sizeof(inq));
1396
1397 xs->error = XS_NOERROR0;
1398 scsi_done(xs);
1399 return;
1400
1401 case READ_CAPACITY0x25:
1402 AMI_DPRINTF(AMI_D_CMD, ("READ CAPACITY tgt %d ", target));
1403 bzero(&rcd, sizeof(rcd))__builtin_bzero((&rcd), (sizeof(rcd)));
1404 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
1405 _lto4b(AMI_SECTOR_SIZE512, rcd.length);
1406 scsi_copy_internal_data(xs, &rcd, sizeof(rcd));
1407
1408 xs->error = XS_NOERROR0;
1409 scsi_done(xs);
1410 return;
1411
1412 default:
1413 AMI_DPRINTF(AMI_D_CMD, ("unsupported scsi command %#x tgt %d ",
1414 xs->cmd.opcode, target));
1415
1416 xs->error = XS_DRIVER_STUFFUP2;
1417 scsi_done(xs);
1418 return;
1419 }
1420
1421 /* A read or write operation. */
1422 if (xs->cmdlen == 6) {
1423 rw = (struct scsi_rw *)&xs->cmd;
1424 blockno = _3btol(rw->addr) & (SRW_TOPADDR0x1F << 16 | 0xffff);
1425 blockcnt = rw->length ? rw->length : 0x100;
1426 } else {
1427 rw10 = (struct scsi_rw_10 *)&xs->cmd;
1428 blockno = _4btol(rw10->addr);
1429 blockcnt = _2btol(rw10->length);
1430 }
1431
1432 if (blockno >= sc->sc_hdr[target].hd_size ||
1433 blockno + blockcnt > sc->sc_hdr[target].hd_size) {
1434 printf("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc)((sc)->sc_dev.dv_xname),
1435 blockno, blockcnt, sc->sc_hdr[target].hd_size);
1436 xs->error = XS_DRIVER_STUFFUP2;
1437 scsi_done(xs);
1438 return;
1439 }
1440
1441 ccb = xs->io;
1442
1443 ccb->ccb_xs = xs;
1444 ccb->ccb_done = ami_done_xs;
1445
1446 cmd = &ccb->ccb_cmd;
1447 cmd->acc_cmd = (xs->flags & SCSI_DATA_IN0x00800) ? AMI_READ0x01 : AMI_WRITE0x02;
1448 cmd->acc_mbox_._ami_mbox.amb_nsect = htole16(blockcnt)((__uint16_t)(blockcnt));
1449 cmd->acc_mbox_._ami_mbox.amb_lba = htole32(blockno)((__uint32_t)(blockno));
1450 cmd->acc_mbox_._ami_mbox.amb_ldn = target;
1451
1452 error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (ccb->
ccb_dmamap), (xs->data), (xs->datalen), (((void *)0)), (
(xs->flags & 0x00001) ? 0x0001 : 0x0000))
1453 xs->data, xs->datalen, NULL,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (ccb->
ccb_dmamap), (xs->data), (xs->datalen), (((void *)0)), (
(xs->flags & 0x00001) ? 0x0001 : 0x0000))
1454 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (ccb->
ccb_dmamap), (xs->data), (xs->datalen), (((void *)0)), (
(xs->flags & 0x00001) ? 0x0001 : 0x0000))
;
1455 if (error) {
1456 if (error == EFBIG27)
1457 printf("more than %d dma segs\n", AMI_MAXOFFSETS26);
1458 else
1459 printf("error %d loading dma map\n", error);
1460
1461 xs->error = XS_DRIVER_STUFFUP2;
1462 scsi_done(xs);
1463 return;
1464 }
1465
1466 sgd = ccb->ccb_dmamap->dm_segs;
1467 if (ccb->ccb_dmamap->dm_nsegs > 1) {
1468 struct ami_sgent *sgl = ccb->ccb_sglist;
1469
1470 cmd->acc_mbox_._ami_mbox.amb_nsge = ccb->ccb_dmamap->dm_nsegs;
1471 cmd->acc_mbox_._ami_mbox.amb_data = ccb->ccb_sglistpa;
1472
1473 for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
1474 sgl[i].asg_addr = htole32(sgd[i].ds_addr)((__uint32_t)(sgd[i].ds_addr));
1475 sgl[i].asg_len = htole32(sgd[i].ds_len)((__uint32_t)(sgd[i].ds_len));
1476 }
1477 } else {
1478 cmd->acc_mbox_._ami_mbox.amb_nsge = 0;
1479 cmd->acc_mbox_._ami_mbox.amb_data = htole32(sgd->ds_addr)((__uint32_t)(sgd->ds_addr));
1480 }
1481
1482 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x01 | 0x04))
1483 ccb->ccb_offset, sizeof(struct ami_ccbmem),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x01 | 0x04))
1484 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x01 | 0x04))
;
1485
1486 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x01 : 0x04))
1487 ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x01 : 0x04))
1488 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), ((xs->
flags & 0x00800) ? 0x01 : 0x04))
;
1489
1490 ami_start_xs(sc, ccb, xs);
1491}
1492
1493int
1494ami_intr(void *v)
1495{
1496 struct ami_iocmd mbox;
1497 struct ami_softc *sc = v;
1498 struct ami_ccb *ccb;
1499 int i, rv = 0, ready;
1500
1501 mtx_enter(&sc->sc_cmd_mtx);
1502 while (!TAILQ_EMPTY(&sc->sc_ccb_runq)(((&sc->sc_ccb_runq)->tqh_first) == ((void *)0)) && sc->sc_done(sc, &mbox)) {
1503 AMI_DPRINTF(AMI_D_CMD, ("got#%d ", mbox.acc_nstat));
1504 for (i = 0; i < mbox.acc_nstat; i++ ) {
1505 ready = mbox.acc_cmplidl[i] - 1;
1506 AMI_DPRINTF(AMI_D_CMD, ("ready=%d ", ready));
1507
1508 ccb = &sc->sc_ccbs[ready];
1509 ccb->ccb_status = mbox.acc_status;
1510 ccb->ccb_state = AMI_CCB_READY;
1511 TAILQ_REMOVE(&ccb->ccb_sc->sc_ccb_runq, 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 (&ccb->ccb_sc->sc_ccb_runq)->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)
;
1512
1513 mtx_leave(&sc->sc_cmd_mtx);
1514 ccb->ccb_done(sc, ccb);
1515 mtx_enter(&sc->sc_cmd_mtx);
1516
1517 rv = 1;
1518 }
1519 }
1520 ready = (sc->sc_drainio && TAILQ_EMPTY(&sc->sc_ccb_runq)(((&sc->sc_ccb_runq)->tqh_first) == ((void *)0)));
1521 mtx_leave(&sc->sc_cmd_mtx);
1522
1523 if (ready)
1524 wakeup(sc);
1525 else if (rv)
1526 ami_runqueue(sc);
1527
1528 AMI_DPRINTF(AMI_D_INTR, ("exit "));
1529 return (rv);
1530}
1531
1532int
1533ami_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
1534{
1535 struct ami_softc *sc = link->bus->sb_adapter_softc;
1536 /* struct device *dev = (struct device *)link->device_softc; */
1537 /* u_int8_t target = link->target; */
1538
1539 if (sc->sc_ioctl)
1540 return (sc->sc_ioctl(&sc->sc_dev, cmd, addr));
1541 else
1542 return (ENOTTY25);
1543}
1544
1545#if NBIO1 > 0
1546int
1547ami_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1548{
1549 struct ami_softc *sc = (struct ami_softc *)dev;
1550 int error = 0;
1551
1552 AMI_DPRINTF(AMI_D_IOCTL, ("%s: ioctl ", DEVNAME(sc)));
1553
1554 if (sc->sc_flags & AMI_BROKEN0x0002)
1555 return (ENODEV19); /* can't do this to broken device for now */
1556
1557 switch (cmd) {
1558 case BIOCINQ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct bioc_inq) & 0x1fff) << 16) | ((('B')) <<
8) | ((32)))
:
1559 AMI_DPRINTF(AMI_D_IOCTL, ("inq "));
1560 error = ami_ioctl_inq(sc, (struct bioc_inq *)addr);
1561 break;
1562
1563 case BIOCVOL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct bioc_vol) & 0x1fff) << 16) | ((('B')) <<
8) | ((34)))
:
1564 AMI_DPRINTF(AMI_D_IOCTL, ("vol "));
1565 error = ami_ioctl_vol(sc, (struct bioc_vol *)addr);
1566 break;
1567
1568 case BIOCDISK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct bioc_disk) & 0x1fff) << 16) | ((('B')) <<
8) | ((33)))
:
1569 AMI_DPRINTF(AMI_D_IOCTL, ("disk "));
1570 error = ami_ioctl_disk(sc, (struct bioc_disk *)addr);
1571 break;
1572
1573 case BIOCALARM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct bioc_alarm) & 0x1fff) << 16) | ((('B')) <<
8) | ((35)))
:
1574 AMI_DPRINTF(AMI_D_IOCTL, ("alarm "));
1575 error = ami_ioctl_alarm(sc, (struct bioc_alarm *)addr);
1576 break;
1577
1578 case BIOCSETSTATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct bioc_setstate) & 0x1fff) << 16) | ((('B')) <<
8) | ((37)))
:
1579 AMI_DPRINTF(AMI_D_IOCTL, ("setstate "));
1580 error = ami_ioctl_setstate(sc, (struct bioc_setstate *)addr);
1581 break;
1582
1583 default:
1584 AMI_DPRINTF(AMI_D_IOCTL, (" invalid ioctl\n"));
1585 error = ENOTTY25;
1586 }
1587
1588 return (error);
1589}
1590
1591int
1592ami_drv_pt(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, u_int8_t *cmd,
1593 int clen, int blen, void *buf)
1594{
1595 struct ami_ccb *ccb;
1596 struct ami_passthrough *pt;
1597 int error = 0;
1598
1599 rw_enter_write(&sc->sc_lock);
1600
1601 ccb = scsi_io_get(&sc->sc_iopool, 0);
1602 if (ccb == NULL((void *)0)) {
1603 error = ENOMEM12;
1604 goto err;
1605 }
1606
1607 ccb->ccb_done = ami_done_ioctl;
1608
1609 ccb->ccb_cmd.acc_cmd = AMI_PASSTHRU0x03;
1610 ccb->ccb_cmd.acc_passthru_._ami_passthru.apt_data = ccb->ccb_ptpa;
1611
1612 pt = ccb->ccb_pt;
1613 memset(pt, 0, sizeof *pt)__builtin_memset((pt), (0), (sizeof *pt));
1614 pt->apt_channel = ch;
1615 pt->apt_target = tg;
1616 pt->apt_ncdb = clen;
1617 pt->apt_nsense = sizeof(struct scsi_sense_data);
1618 pt->apt_datalen = blen;
1619 pt->apt_data = 0;
1620
1621 bcopy(cmd, pt->apt_cdb, clen);
1622
1623 if (ami_load_ptmem(sc, ccb, buf, blen, 1, 0) != 0) {
1624 error = ENOMEM12;
1625 goto ptmemerr;
1626 }
1627
1628 ami_start(sc, ccb);
1629
1630 while (ccb->ccb_state != AMI_CCB_READY)
1631 tsleep_nsec(ccb, PRIBIO16, "ami_drv_pt", INFSLP0xffffffffffffffffULL);
1632
1633 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), (0x02)
)
1634 ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ccb->
ccb_dmamap), (0), (ccb->ccb_dmamap->dm_mapsize), (0x02)
)
;
1635 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
1636 ccb->ccb_offset, sizeof(struct ami_ccbmem),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
1637 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((sc->
sc_ccbmem_am)->am_map)), (ccb->ccb_offset), (sizeof(struct
ami_ccbmem)), (0x02 | 0x08))
;
1638 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (ccb
->ccb_dmamap))
;
1639
1640 if (ccb->ccb_flags & AMI_CCB_F_ERR(1<<0))
1641 error = EIO5;
1642 else if (pt->apt_scsistat != 0x00)
1643 error = EIO5;
1644
1645ptmemerr:
1646 scsi_io_put(&sc->sc_iopool, ccb);
1647
1648err:
1649 rw_exit_write(&sc->sc_lock);
1650 return (error);
1651}
1652
1653int
1654ami_drv_inq(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, u_int8_t page,
1655 void *inqbuf)
1656{
1657 struct scsi_inquiry_data *inq = inqbuf;
1658 u_int8_t cdb[6];
1659 int error = 0;
1660
1661 bzero(&cdb, sizeof cdb)__builtin_bzero((&cdb), (sizeof cdb));
1662
1663 cdb[0] = INQUIRY0x12;
1664 cdb[1] = 0;
1665 cdb[2] = 0;
1666 cdb[3] = 0;
1667 cdb[4] = sizeof(struct scsi_inquiry_data);
1668 cdb[5] = 0;
1669 if (page != 0) {
1670 cdb[1] = SI_EVPD0x01;
1671 cdb[2] = page;
1672 }
1673
1674 error = ami_drv_pt(sc, ch, tg, cdb, 6, sizeof *inq, inqbuf);
1675 if (error)
1676 return (error);
1677
1678 if ((inq->device & SID_TYPE0x1f) != T_DIRECT0x00)
1679 error = EINVAL22;
1680
1681 return (error);
1682}
1683
1684int
1685ami_drv_readcap(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, daddr_t *sz)
1686{
1687 struct scsi_read_cap_data *rcd = NULL((void *)0);
1688 struct scsi_read_cap_data_16 *rcd16 = NULL((void *)0);
1689 u_int8_t cdb[16];
1690 u_int32_t blksz;
1691 daddr_t noblk;
1692 int error = 0;
1693
1694 bzero(&cdb, sizeof cdb)__builtin_bzero((&cdb), (sizeof cdb));
1695 cdb[0] = READ_CAPACITY0x25;
1696 rcd = dma_alloc(sizeof(*rcd), PR_WAITOK0x0001);
1697
1698 error = ami_drv_pt(sc, ch, tg, cdb, 10, sizeof(*rcd), rcd);
1699 if (error)
1700 goto fail;
1701
1702 noblk = _4btol(rcd->addr);
1703 if (noblk == 0xffffffffllu) {
1704 /* huge disk */
1705 bzero(&cdb, sizeof cdb)__builtin_bzero((&cdb), (sizeof cdb));
1706 cdb[0] = READ_CAPACITY_160x9e;
1707 rcd16 = dma_alloc(sizeof(*rcd16), PR_WAITOK0x0001);
1708
1709 error = ami_drv_pt(sc, ch, tg, cdb, 16, sizeof(*rcd16), rcd16);
1710 if (error)
1711 goto fail;
1712
1713 noblk = _8btol(rcd16->addr);
1714 blksz = _4btol(rcd16->length);
1715 } else
1716 blksz = _4btol(rcd->length);
1717
1718 if (blksz == 0)
1719 blksz = 512;
1720 *sz = noblk * blksz;
1721
1722fail:
1723 if (rcd16)
1724 dma_free(rcd16, sizeof(*rcd16));
1725 dma_free(rcd, sizeof(*rcd));
1726 return (error);
1727}
1728
1729int
1730ami_mgmt(struct ami_softc *sc, u_int8_t opcode, u_int8_t par1, u_int8_t par2,
1731 u_int8_t par3, size_t size, void *buffer)
1732{
1733 struct ami_ccb *ccb;
1734 struct ami_iocmd *cmd;
1735 struct ami_mem *am = NULL((void *)0);
1736 char *idata = NULL((void *)0);
1737 int error = 0;
1738
1739 rw_enter_write(&sc->sc_lock);
1740
1741 if (opcode != AMI_CHSTATE0x06) {
1742 ccb = scsi_io_get(&sc->sc_iopool, 0);
1743 if (ccb == NULL((void *)0)) {
1744 error = ENOMEM12;
1745 goto err;
1746 }
1747 ccb->ccb_done = ami_done_ioctl;
1748 } else
1749 ccb = sc->sc_mgmtccb;
1750
1751 if (size) {
1752 if ((am = ami_allocmem(sc, size)) == NULL((void *)0)) {
1753 error = ENOMEM12;
1754 goto memerr;
1755 }
1756 idata = AMIMEM_KVA(am)((void *)(am)->am_kva);
1757 }
1758
1759 cmd = &ccb->ccb_cmd;
1760 cmd->acc_cmd = opcode;
1761
1762 /*
1763 * some commands require data to be written to idata before sending
1764 * command to fw
1765 */
1766 switch (opcode) {
1767 case AMI_SPEAKER0x51:
1768 *idata = par1;
1769 break;
1770 default:
1771 cmd->acc_io_._ami_io.aio_channel = par1;
1772 cmd->acc_io_._ami_io.aio_param = par2;
1773 cmd->acc_io_._ami_io.aio_pad[0] = par3;
1774 break;
1775 };
1776
1777 cmd->acc_io_._ami_io.aio_data = am ? htole32(AMIMEM_DVA(am))((__uint32_t)(((am)->am_map->dm_segs[0].ds_addr))) : 0;
1778
1779 if (opcode != AMI_CHSTATE0x06) {
1780 ami_start(sc, ccb);
1781 mtx_enter(&sc->sc_cmd_mtx);
1782 while (ccb->ccb_state != AMI_CCB_READY)
1783 msleep_nsec(ccb, &sc->sc_cmd_mtx, PRIBIO16, "ami_mgmt",
1784 INFSLP0xffffffffffffffffULL);
1785 mtx_leave(&sc->sc_cmd_mtx);
1786 } else {
1787 /* change state must be run with id 0xfe and MUST be polled */
1788 mtx_enter(&sc->sc_cmd_mtx);
1789 sc->sc_drainio = 1;
1790 while (!TAILQ_EMPTY(&sc->sc_ccb_runq)(((&sc->sc_ccb_runq)->tqh_first) == ((void *)0))) {
1791 if (msleep_nsec(sc, &sc->sc_cmd_mtx, PRIBIO16,
1792 "amimgmt", SEC_TO_NSEC(60)) == EWOULDBLOCK35) {
1793 printf("%s: drain io timeout\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
1794 ccb->ccb_flags |= AMI_CCB_F_ERR(1<<0);
1795 goto restartio;
1796 }
1797 }
1798
1799 error = sc->sc_poll(sc, &ccb->ccb_cmd);
1800 if (error == -1)
1801 ccb->ccb_flags |= AMI_CCB_F_ERR(1<<0);
1802
1803restartio:
1804 /* restart io */
1805 sc->sc_drainio = 0;
1806 mtx_leave(&sc->sc_cmd_mtx);
1807 ami_runqueue(sc);
1808 }
1809
1810 if (ccb->ccb_flags & AMI_CCB_F_ERR(1<<0))
1811 error = EIO5;
1812 else if (buffer && size)
1813 memcpy(buffer, idata, size)__builtin_memcpy((buffer), (idata), (size));
1814
1815 if (am)
1816 ami_freemem(sc, am);
1817memerr:
1818 if (opcode != AMI_CHSTATE0x06) {
1819 scsi_io_put(&sc->sc_iopool, ccb);
1820 } else {
1821 ccb->ccb_flags = 0;
1822 ccb->ccb_state = AMI_CCB_FREE;
1823 }
1824
1825err:
1826 rw_exit_write(&sc->sc_lock);
1827 return (error);
1828}
1829
1830int
1831ami_ioctl_inq(struct ami_softc *sc, struct bioc_inq *bi)
1832{
1833 struct ami_big_diskarray *p; /* struct too large for stack */
1834 struct scsi_inquiry_data *inqbuf;
1835 struct ami_fc_einquiry einq;
1836 int ch, tg;
1837 int i, s, t, off;
1838 int error = 0, changes = 0;
1839
1840 if ((error = ami_mgmt(sc, AMI_FCOP0xa1, AMI_FC_EINQ30x0f,
1841 AMI_FC_EINQ3_SOLICITED_FULL0x02, 0, sizeof einq, &einq)))
1842 return (EINVAL22);
1843
1844 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK0x0001);
1845
1846 if (einq.ain_drvinscnt == sc->sc_drvinscnt) {
1847 /* poke existing known drives to make sure they aren't gone */
1848 for(i = 0; i < sc->sc_channels * 16; i++) {
1849 if (sc->sc_plist[i] == 0)
1850 continue;
1851
1852 ch = (i & 0xf0) >> 4;
1853 tg = i & 0x0f;
1854 if (ami_drv_inq(sc, ch, tg, 0, inqbuf)) {
1855 /* drive is gone, force rescan */
1856 changes = 1;
1857 break;
1858 }
1859 }
1860 if (changes == 0) {
1861 bcopy(&sc->sc_bi, bi, sizeof *bi);
1862 goto done;
1863 }
1864 }
1865
1866 sc->sc_drvinscnt = einq.ain_drvinscnt;
1867
1868 p = malloc(sizeof *p, M_DEVBUF2, M_NOWAIT0x0002);
1869 if (!p) {
1870 error = ENOMEM12;
1871 goto done;
1872 }
1873
1874 if ((error = ami_mgmt(sc, AMI_FCOP0xa1, AMI_FC_RDCONF0x04, 0, 0, sizeof *p,
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
1875 p))) {
1876 error = EINVAL22;
1877 goto bail;
1878 }
1879
1880 bzero(sc->sc_plist, sizeof sc->sc_plist)__builtin_bzero((sc->sc_plist), (sizeof sc->sc_plist));
1881
1882 bi->bi_novol = p->ada_nld;
1883 bi->bi_nodisk = 0;
1884 strlcpy(bi->bi_dev, DEVNAME(sc)((sc)->sc_dev.dv_xname), sizeof(bi->bi_dev));
1885
1886 /* count used disks, including failed ones */
1887 for (i = 0; i < p->ada_nld; i++)
1888 for (s = 0; s < p->aldada_ldrv[i].adl_spandepth; s++)
1889 for (t = 0; t < p->aldada_ldrv[i].adl_nstripes; t++) {
1890 off = p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_channel *
1891 AMI_MAX_TARGET16 +
1892 p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_target;
1893
1894 /* account for multi raid vol on same disk */
1895 if (!sc->sc_plist[off]) {
1896 sc->sc_plist[off] = 1;
1897 bi->bi_nodisk++;
1898 }
1899 }
1900
1901 /* count unused disks */
1902 for(i = 0; i < sc->sc_channels * 16; i++) {
1903 if (sc->sc_plist[i])
1904 continue; /* skip claimed drives */
1905
1906 /*
1907 * hack to invalidate device type, needed for initiator id
1908 * on an unconnected channel.
1909 * XXX find out if we can determine this differently
1910 */
1911 memset(inqbuf, 0xff, sizeof(*inqbuf))__builtin_memset((inqbuf), (0xff), (sizeof(*inqbuf)));
1912
1913 ch = (i & 0xf0) >> 4;
1914 tg = i & 0x0f;
1915 if (!ami_drv_inq(sc, ch, tg, 0, inqbuf)) {
1916 if ((inqbuf->device & SID_TYPE0x1f) != T_DIRECT0x00)
1917 continue;
1918 bi->bi_novol++;
1919 bi->bi_nodisk++;
1920 sc->sc_plist[i] = 2;
1921 } else
1922 sc->sc_plist[i] = 0;
1923 }
1924
1925 bcopy(bi, &sc->sc_bi, sizeof sc->sc_bi);
1926 error = 0;
1927bail:
1928 free(p, M_DEVBUF2, sizeof *p);
1929done:
1930 dma_free(inqbuf, sizeof(*inqbuf));
1931 return (error);
1932}
1933
1934int
1935ami_vol(struct ami_softc *sc, struct bioc_vol *bv, struct ami_big_diskarray *p)
1936{
1937 int i, ld = p->ada_nld, error = EINVAL22;
1938
1939 for(i = 0; i < sc->sc_channels * 16; i++) {
1940 /* skip claimed/unused drives */
1941 if (sc->sc_plist[i] != 2)
1942 continue;
1943
1944 /* are we it? */
1945 if (ld != bv->bv_volid) {
1946 ld++;
1947 continue;
1948 }
1949
1950 bv->bv_status = BIOC_SVONLINE0x00;
1951 bv->bv_size = (uint64_t)p->apdada_pdrv[i].adp_size *
1952 (uint64_t)512;
1953 bv->bv_nodisk = 1;
1954 strlcpy(bv->bv_dev,
1955 sc->sc_hdr[bv->bv_volid].dev,
1956 sizeof(bv->bv_dev));
1957
1958 if (p->apdada_pdrv[i].adp_ostatus == AMI_PD_HOTSPARE6
1959 && p->apdada_pdrv[i].adp_type == 0)
1960 bv->bv_level = -1;
1961 else
1962 bv->bv_level = -2;
1963
1964 error = 0;
1965 goto bail;
1966 }
1967
1968bail:
1969 return (error);
1970}
1971
1972int
1973ami_disk(struct ami_softc *sc, struct bioc_disk *bd,
1974 struct ami_big_diskarray *p)
1975{
1976 char vend[8+16+4+1], *vendp;
1977 char ser[32 + 1];
1978 struct scsi_inquiry_data *inqbuf;
1979 struct scsi_vpd_serial *vpdbuf;
1980 int i, ld = p->ada_nld, error = EINVAL22;
1981 u_int8_t ch, tg;
1982 daddr_t sz = 0;
1983
1984 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK0x0001);
1985 vpdbuf = dma_alloc(sizeof(*vpdbuf), PR_WAITOK0x0001);
1986
1987 for(i = 0; i < sc->sc_channels * 16; i++) {
1988 /* skip claimed/unused drives */
1989 if (sc->sc_plist[i] != 2)
1990 continue;
1991
1992 /* are we it? */
1993 if (ld != bd->bd_volid) {
1994 ld++;
1995 continue;
1996 }
1997
1998 ch = (i & 0xf0) >> 4;
1999 tg = i & 0x0f;
2000 if (ami_drv_inq(sc, ch, tg, 0, inqbuf))
2001 goto bail;
2002
2003 vendp = inqbuf->vendor;
2004 bcopy(vendp, vend, sizeof vend - 1);
2005
2006 vend[sizeof vend - 1] = '\0';
2007 strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
2008
2009 if (!ami_drv_inq(sc, ch, tg, 0x80, vpdbuf)) {
2010 bcopy(vpdbuf->serial, ser, sizeof ser - 1);
2011 ser[sizeof ser - 1] = '\0';
2012 if (_2btol(vpdbuf->hdr.page_length) < sizeof ser)
2013 ser[_2btol(vpdbuf->hdr.page_length)] = '\0';
2014 strlcpy(bd->bd_serial, ser, sizeof(bd->bd_serial));
2015 }
2016
2017 error = ami_drv_readcap(sc, ch, tg, &sz);
2018 if (error)
2019 goto bail;
2020
2021 bd->bd_size = sz;
2022 bd->bd_channel = ch;
2023 bd->bd_target = tg;
2024
2025 strlcpy(bd->bd_procdev, sc->sc_rawsoftcs[ch].sc_procdev,
2026 sizeof(bd->bd_procdev));
2027
2028 if (p->apdada_pdrv[i].adp_ostatus == AMI_PD_HOTSPARE6)
2029 bd->bd_status = BIOC_SDHOTSPARE0x04;
2030 else
2031 bd->bd_status = BIOC_SDUNUSED0x05;
2032
2033#ifdef AMI_DEBUG
2034 if (p->apdada_pdrv[i].adp_type != 0)
2035 printf("invalid disk type: %d %d %x inquiry type: %x\n",
2036 ch, tg, p->apdada_pdrv[i].adp_type, inqbuf->device);
2037#endif /* AMI_DEBUG */
2038
2039 error = 0;
2040 goto bail;
2041 }
2042
2043bail:
2044 dma_free(inqbuf, sizeof(*inqbuf));
2045 dma_free(vpdbuf, sizeof(*vpdbuf));
2046 return (error);
2047}
2048
2049int
2050ami_ioctl_vol(struct ami_softc *sc, struct bioc_vol *bv)
2051{
2052 struct ami_big_diskarray *p; /* struct too large for stack */
2053 int i, s, t, off;
2054 int error = 0;
2055 struct ami_progress perc;
2056 u_int8_t bgi[5]; /* 40 LD, 1 bit per LD if BGI is active */
2057
2058 p = malloc(sizeof *p, M_DEVBUF2, M_NOWAIT0x0002);
2059 if (!p)
2060 return (ENOMEM12);
2061
2062 if ((error = ami_mgmt(sc, AMI_FCOP0xa1, AMI_FC_RDCONF0x04, 0, 0, sizeof *p, p)))
2063 goto bail;
2064
2065 if (bv->bv_volid >= p->ada_nld) {
2066 error = ami_vol(sc, bv, p);
2067 goto bail;
2068 }
2069
2070 i = bv->bv_volid;
2071
2072 switch (p->aldada_ldrv[i].adl_status) {
2073 case AMI_RDRV_OFFLINE0:
2074 bv->bv_status = BIOC_SVOFFLINE0x01;
2075 break;
2076
2077 case AMI_RDRV_DEGRADED1:
2078 bv->bv_status = BIOC_SVDEGRADED0x02;
2079 break;
2080
2081 case AMI_RDRV_OPTIMAL2:
2082 bv->bv_status = BIOC_SVONLINE0x00;
2083 bv->bv_percent = -1;
2084
2085 /* get BGI progress here and over-ride status if so */
2086 memset(bgi, 0, sizeof bgi)__builtin_memset((bgi), (0), (sizeof bgi));
2087 if (ami_mgmt(sc, AMI_MISC0xa4, AMI_GET_BGI0x13, 0, 0, sizeof bgi, &bgi))
2088 break;
2089
2090 if ((bgi[i / 8] & (1 << i % 8)) == 0)
2091 break;
2092
2093 if (!ami_mgmt(sc, AMI_GCHECKPROGR0x19, i, 0, 0, sizeof perc, &perc))
2094 if (perc.apr_progress < 100) {
2095 bv->bv_status = BIOC_SVSCRUB0x04;
2096 bv->bv_percent = perc.apr_progress >= 100 ? -1 :
2097 perc.apr_progress;
2098 }
2099 break;
2100
2101 default:
2102 bv->bv_status = BIOC_SVINVALID0xff;
2103 }
2104
2105 /* over-ride status if a pd is in rebuild status for this ld */
2106 for (s = 0; s < p->aldada_ldrv[i].adl_spandepth; s++)
2107 for (t = 0; t < p->aldada_ldrv[i].adl_nstripes; t++) {
2108 off = p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_channel *
2109 AMI_MAX_TARGET16 +
2110 p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_target;
2111
2112 if (p->apdada_pdrv[off].adp_ostatus != AMI_PD_RBLD5)
2113 continue;
2114
2115 /* get rebuild progress from pd 0 */
2116 bv->bv_status = BIOC_SVREBUILD0x05;
2117 if (ami_mgmt(sc, AMI_GRBLDPROGR0x18,
2118 p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_channel,
2119 p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_target, 0,
2120 sizeof perc, &perc))
2121 bv->bv_percent = -1;
2122 else
2123 bv->bv_percent = perc.apr_progress >= 100 ? -1 :
2124 perc.apr_progress;
2125 break;
2126 }
2127
2128 bv->bv_size = 0;
2129 bv->bv_level = p->aldada_ldrv[i].adl_raidlvl;
2130 bv->bv_nodisk = 0;
2131
2132 for (s = 0; s < p->aldada_ldrv[i].adl_spandepth; s++) {
2133 for (t = 0; t < p->aldada_ldrv[i].adl_nstripes; t++)
2134 bv->bv_nodisk++;
2135
2136 switch (bv->bv_level) {
2137 case 0:
2138 bv->bv_size += p->aldada_ldrv[i].aspadl_spans[s].ads_length *
2139 p->aldada_ldrv[i].adl_nstripes;
2140 break;
2141
2142 case 1:
2143 bv->bv_size += p->aldada_ldrv[i].aspadl_spans[s].ads_length;
2144 break;
2145
2146 case 5:
2147 bv->bv_size += p->aldada_ldrv[i].aspadl_spans[s].ads_length *
2148 (p->aldada_ldrv[i].adl_nstripes - 1);
2149 break;
2150 }
2151 }
2152
2153 if (p->aldada_ldrv[i].adl_spandepth > 1)
2154 bv->bv_level *= 10;
2155
2156 bv->bv_size *= (uint64_t)512;
2157
2158 strlcpy(bv->bv_dev, sc->sc_hdr[i].dev, sizeof(bv->bv_dev));
2159
2160bail:
2161 free(p, M_DEVBUF2, sizeof *p);
2162
2163 return (error);
2164}
2165
2166int
2167ami_ioctl_disk(struct ami_softc *sc, struct bioc_disk *bd)
2168{
2169 struct scsi_inquiry_data *inqbuf;
2170 struct scsi_vpd_serial *vpdbuf;
2171 struct ami_big_diskarray *p; /* struct too large for stack */
2172 int i, s, t, d;
2173 int off;
2174 int error = EINVAL22;
2175 u_int16_t ch, tg;
2176 char vend[8+16+4+1], *vendp;
2177 char ser[32 + 1];
2178
2179 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK0x0001);
2180 vpdbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK0x0001);
2181 p = malloc(sizeof *p, M_DEVBUF2, M_WAITOK0x0001);
2182
2183 if ((error = ami_mgmt(sc, AMI_FCOP0xa1, AMI_FC_RDCONF0x04, 0, 0, sizeof *p, p)))
2184 goto bail;
2185
2186 if (bd->bd_volid >= p->ada_nld) {
2187 error = ami_disk(sc, bd, p);
2188 goto bail;
2189 }
2190
2191 i = bd->bd_volid;
2192 for (s = 0, d = 0; s < p->aldada_ldrv[i].adl_spandepth; s++)
2193 for (t = 0; t < p->aldada_ldrv[i].adl_nstripes; t++) {
2194 if (d != bd->bd_diskid) {
2195 d++;
2196 continue;
2197 }
2198
2199 off = p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_channel *
2200 AMI_MAX_TARGET16 +
2201 p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_target;
2202
2203 bd->bd_size = (uint64_t)p->apdada_pdrv[off].adp_size *
2204 (uint64_t)512;
2205
2206 switch (p->apdada_pdrv[off].adp_ostatus) {
2207 case AMI_PD_UNCNF0:
2208 bd->bd_status = BIOC_SDUNUSED0x05;
2209 break;
2210
2211 case AMI_PD_ONLINE3:
2212 bd->bd_status = BIOC_SDONLINE0x00;
2213 break;
2214
2215 case AMI_PD_FAILED4:
2216 bd->bd_status = BIOC_SDFAILED0x02;
2217 bd->bd_size = 0;
2218 break;
2219
2220 case AMI_PD_RBLD5:
2221 bd->bd_status = BIOC_SDREBUILD0x03;
2222 break;
2223
2224 case AMI_PD_HOTSPARE6:
2225 bd->bd_status = BIOC_SDHOTSPARE0x04;
2226 break;
2227
2228 default:
2229 bd->bd_status = BIOC_SDINVALID0xff;
2230 bd->bd_size = 0;
2231 }
2232
2233
2234 ch = p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_target >> 4;
2235 tg = p->aldada_ldrv[i].aspadl_spans[s].advads_devs[t].add_target & 0x0f;
2236
2237 bd->bd_channel = ch;
2238 bd->bd_target = tg;
2239 strlcpy(bd->bd_procdev, sc->sc_rawsoftcs[ch].sc_procdev,
2240 sizeof(bd->bd_procdev));
2241
2242 /* if we are failed don't query drive */
2243 if (bd->bd_size == 0) {
2244 bzero(&bd->bd_vendor, sizeof(bd->bd_vendor))__builtin_bzero((&bd->bd_vendor), (sizeof(bd->bd_vendor
)))
;
2245 bzero(&bd->bd_serial, sizeof(bd->bd_serial))__builtin_bzero((&bd->bd_serial), (sizeof(bd->bd_serial
)))
;
2246 goto done;
2247 }
2248
2249 if (!ami_drv_inq(sc, ch, tg, 0, inqbuf)) {
2250 vendp = inqbuf->vendor;
2251 bcopy(vendp, vend, sizeof vend - 1);
2252 vend[sizeof vend - 1] = '\0';
2253 strlcpy(bd->bd_vendor, vend,
2254 sizeof(bd->bd_vendor));
2255 }
2256
2257 if (!ami_drv_inq(sc, ch, tg, 0x80, vpdbuf)) {
2258 bcopy(vpdbuf->serial, ser, sizeof ser - 1);
2259 ser[sizeof ser - 1] = '\0';
2260 if (_2btol(vpdbuf->hdr.page_length) <
2261 sizeof(ser))
2262 ser[_2btol(vpdbuf->hdr.page_length)] =
2263 '\0';
2264 strlcpy(bd->bd_serial, ser,
2265 sizeof(bd->bd_serial));
2266 }
2267 goto done;
2268 }
2269
2270done:
2271 error = 0;
2272bail:
2273 free(p, M_DEVBUF2, sizeof *p);
2274 dma_free(vpdbuf, sizeof(*vpdbuf));
2275 dma_free(inqbuf, sizeof(*inqbuf));
2276
2277 return (error);
2278}
2279
2280int ami_ioctl_alarm(struct ami_softc *sc, struct bioc_alarm *ba)
2281{
2282 int error = 0;
2283 u_int8_t func, ret;
2284
2285 switch(ba->ba_opcode) {
2286 case BIOC_SADISABLE0x00:
2287 func = AMI_SPKR_OFF0;
2288 break;
2289
2290 case BIOC_SAENABLE0x01:
2291 func = AMI_SPKR_ON1;
2292 break;
2293
2294 case BIOC_SASILENCE0x02:
2295 func = AMI_SPKR_SHUT2;
2296 break;
2297
2298 case BIOC_GASTATUS0x03:
2299 func = AMI_SPKR_GVAL3;
2300 break;
2301
2302 case BIOC_SATEST0x04:
2303 func = AMI_SPKR_TEST4;
2304 break;
2305
2306 default:
2307 AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocalarm invalid opcode %x\n",
2308 DEVNAME(sc), ba->ba_opcode));
2309 return (EINVAL22);
2310 }
2311
2312 if (!(error = ami_mgmt(sc, AMI_SPEAKER0x51, func, 0, 0, sizeof ret,
2313 &ret))) {
2314 if (ba->ba_opcode == BIOC_GASTATUS0x03)
2315 ba->ba_status = ret;
2316 else
2317 ba->ba_status = 0;
2318 }
2319
2320 return (error);
2321}
2322
2323int
2324ami_ioctl_setstate(struct ami_softc *sc, struct bioc_setstate *bs)
2325{
2326 struct scsi_inquiry_data *inqbuf;
2327 int func, error = 0;
2328
2329 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK0x0001);
2330
2331 switch (bs->bs_status) {
2332 case BIOC_SSONLINE0x00:
2333 func = AMI_STATE_ON3;
2334 break;
2335
2336 case BIOC_SSOFFLINE0x01:
2337 func = AMI_STATE_FAIL4;
2338 break;
2339
2340 case BIOC_SSHOTSPARE0x02:
2341 if (ami_drv_inq(sc, bs->bs_channel, bs->bs_target, 0,
2342 inqbuf)) {
2343 error = EINVAL22;
2344 goto done;
2345 }
2346
2347 func = AMI_STATE_SPARE6;
2348 break;
2349
2350 default:
2351 AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocsetstate invalid opcode %x\n"
2352 , DEVNAME(sc), bs->bs_status));
2353 error = EINVAL22;
2354 goto done;
2355 }
2356
2357 if ((error = ami_mgmt(sc, AMI_CHSTATE0x06, bs->bs_channel, bs->bs_target,
2358 func, 0, NULL((void *)0))))
2359 goto done;
2360
2361done:
2362 dma_free(inqbuf, sizeof(*inqbuf));
2363 return (error);
2364}
2365
2366#ifndef SMALL_KERNEL
2367int
2368ami_create_sensors(struct ami_softc *sc)
2369{
2370 struct device *dev;
2371 struct scsibus_softc *ssc = NULL((void *)0);
2372 struct scsi_link *link;
2373 int i;
2374
2375 TAILQ_FOREACH(dev, &alldevs, dv_list)for((dev) = ((&alldevs)->tqh_first); (dev) != ((void *
)0); (dev) = ((dev)->dv_list.tqe_next))
{
2376 if (dev->dv_parent != &sc->sc_dev)
2377 continue;
2378
2379 /* check if this is the scsibus for the logical disks */
2380 ssc = (struct scsibus_softc *)dev;
2381 if (ssc == sc->sc_scsibus)
2382 break;
2383 }
2384
2385 if (ssc == NULL((void *)0))
2386 return (1);
2387
2388 sc->sc_sensors = mallocarray(sc->sc_nunits, sizeof(struct ksensor),
2389 M_DEVBUF2, M_WAITOK0x0001|M_CANFAIL0x0004|M_ZERO0x0008);
2390 if (sc->sc_sensors == NULL((void *)0))
2391 return (1);
2392
2393 strlcpy(sc->sc_sensordev.xname, DEVNAME(sc)((sc)->sc_dev.dv_xname),
2394 sizeof(sc->sc_sensordev.xname));
2395
2396 for (i = 0; i < sc->sc_nunits; i++) {
2397 link = scsi_get_link(ssc, i, 0);
2398 if (link == NULL((void *)0))
2399 goto bad;
2400
2401 dev = link->device_softc;
2402
2403 sc->sc_sensors[i].type = SENSOR_DRIVE;
2404 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2405
2406 strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
2407 sizeof(sc->sc_sensors[i].desc));
2408
2409 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
2410 }
2411
2412 sc->sc_bd = malloc(sizeof(*sc->sc_bd), M_DEVBUF2, M_WAITOK0x0001|M_CANFAIL0x0004);
2413 if (sc->sc_bd == NULL((void *)0))
2414 goto bad;
2415
2416 if (sensor_task_register(sc, ami_refresh_sensors, 10) == NULL((void *)0))
2417 goto freebd;
2418
2419 sensordev_install(&sc->sc_sensordev);
2420
2421 return (0);
2422
2423freebd:
2424 free(sc->sc_bd, M_DEVBUF2, sizeof(*sc->sc_bd));
2425bad:
2426 free(sc->sc_sensors, M_DEVBUF2, sc->sc_nunits * sizeof(struct ksensor));
2427
2428 return (1);
2429}
2430
2431void
2432ami_refresh_sensors(void *arg)
2433{
2434 struct ami_softc *sc = arg;
2435 int i;
2436
2437 if (ami_mgmt(sc, AMI_FCOP0xa1, AMI_FC_RDCONF0x04, 0, 0, sizeof(*sc->sc_bd),
2438 sc->sc_bd)) {
2439 for (i = 0; i < sc->sc_nunits; i++) {
2440 sc->sc_sensors[i].value = 0; /* unknown */
2441 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2442 }
2443 return;
2444 }
2445
2446 for (i = 0; i < sc->sc_nunits; i++) {
2447 switch (sc->sc_bd->aldada_ldrv[i].adl_status) {
2448 case AMI_RDRV_OFFLINE0:
2449 sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL9;
2450 sc->sc_sensors[i].status = SENSOR_S_CRIT;
2451 break;
2452
2453 case AMI_RDRV_DEGRADED1:
2454 sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL10;
2455 sc->sc_sensors[i].status = SENSOR_S_WARN;
2456 break;
2457
2458 case AMI_RDRV_OPTIMAL2:
2459 sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE4;
2460 sc->sc_sensors[i].status = SENSOR_S_OK;
2461 break;
2462
2463 default:
2464 sc->sc_sensors[i].value = 0; /* unknown */
2465 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2466 }
2467 }
2468}
2469#endif /* SMALL_KERNEL */
2470#endif /* NBIO > 0 */
2471
2472#ifdef AMI_DEBUG
2473void
2474ami_print_mbox(struct ami_iocmd *mbox)
2475{
2476 int i;
2477
2478 printf("acc_cmd: %d aac_id: %d acc_busy: %d acc_nstat: %d ",
2479 mbox->acc_cmd, mbox->acc_id, mbox->acc_busy, mbox->acc_nstat);
2480 printf("acc_status: %d acc_poll: %d acc_ack: %d\n",
2481 mbox->acc_status, mbox->acc_poll, mbox->acc_ack);
2482
2483 printf("acc_cmplidl: ");
2484 for (i = 0; i < AMI_MAXSTATACK0x2e; i++) {
2485 printf("[%d] = %d ", i, mbox->acc_cmplidl[i]);
2486 }
2487
2488 printf("\n");
2489}
2490#endif /* AMI_DEBUG */