Line data Source code
1 : /* $OpenBSD: gdt_common.c,v 1.64 2018/08/14 05:22:21 jmatthew Exp $ */
2 :
3 : /*
4 : * Copyright (c) 1999, 2000, 2003 Niklas Hallqvist. All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : * 1. Redistributions of source code must retain the above copyright
10 : * notice, this list of conditions and the following disclaimer.
11 : * 2. Redistributions in binary form must reproduce the above copyright
12 : * notice, this list of conditions and the following disclaimer in the
13 : * documentation and/or other materials provided with the distribution.
14 : *
15 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 : */
26 :
27 : /*
28 : * This driver would not have written if it was not for the hardware donations
29 : * from both ICP-Vortex and Öko.neT. I want to thank them for their support.
30 : */
31 :
32 : #include <sys/param.h>
33 : #include <sys/buf.h>
34 : #include <sys/device.h>
35 : #include <sys/ioctl.h>
36 : #include <sys/kernel.h>
37 : #include <sys/malloc.h>
38 : #include <sys/systm.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/biovar.h>
47 : #include <dev/ic/gdtreg.h>
48 : #include <dev/ic/gdtvar.h>
49 :
50 : #include "bio.h"
51 :
52 : #ifdef GDT_DEBUG
53 : int gdt_maxcmds = GDT_MAXCMDS;
54 : #undef GDT_MAXCMDS
55 : #define GDT_MAXCMDS gdt_maxcmds
56 : #endif
57 :
58 : #define GDT_DRIVER_VERSION 1
59 : #define GDT_DRIVER_SUBVERSION 2
60 :
61 : int gdt_async_event(struct gdt_softc *, int);
62 : void gdt_chain(struct gdt_softc *);
63 : void gdt_clear_events(struct gdt_softc *);
64 : void gdt_copy_internal_data(struct scsi_xfer *, u_int8_t *, size_t);
65 : struct scsi_xfer *gdt_dequeue(struct gdt_softc *);
66 : void gdt_enqueue(struct gdt_softc *, struct scsi_xfer *, int);
67 : void gdt_enqueue_ccb(struct gdt_softc *, struct gdt_ccb *);
68 : void gdt_eval_mapping(u_int32_t, int *, int *, int *);
69 : int gdt_exec_ccb(struct gdt_ccb *);
70 : void gdt_ccb_free(void *, void *);
71 : void *gdt_ccb_alloc(void *);
72 : void gdt_internal_cache_cmd(struct scsi_xfer *);
73 : int gdt_internal_cmd(struct gdt_softc *, u_int8_t, u_int16_t,
74 : u_int32_t, u_int32_t, u_int32_t);
75 : #if NBIO > 0
76 : int gdt_ioctl(struct device *, u_long, caddr_t);
77 : int gdt_ioctl_inq(struct gdt_softc *, struct bioc_inq *);
78 : int gdt_ioctl_vol(struct gdt_softc *, struct bioc_vol *);
79 : int gdt_ioctl_disk(struct gdt_softc *, struct bioc_disk *);
80 : int gdt_ioctl_alarm(struct gdt_softc *, struct bioc_alarm *);
81 : int gdt_ioctl_setstate(struct gdt_softc *, struct bioc_setstate *);
82 : #endif /* NBIO > 0 */
83 : void gdt_scsi_cmd(struct scsi_xfer *);
84 : void gdt_start_ccbs(struct gdt_softc *);
85 : int gdt_sync_event(struct gdt_softc *, int, u_int8_t,
86 : struct scsi_xfer *);
87 : void gdt_timeout(void *);
88 : int gdt_wait(struct gdt_softc *, struct gdt_ccb *, int);
89 : void gdt_watchdog(void *);
90 :
91 : struct cfdriver gdt_cd = {
92 : NULL, "gdt", DV_DULL
93 : };
94 :
95 : struct scsi_adapter gdt_switch = {
96 : gdt_scsi_cmd, gdtminphys, 0, 0,
97 : };
98 :
99 : int gdt_cnt = 0;
100 : u_int8_t gdt_polling;
101 : u_int8_t gdt_from_wait;
102 : struct gdt_softc *gdt_wait_gdt;
103 : int gdt_wait_index;
104 : #ifdef GDT_DEBUG
105 : int gdt_debug = GDT_DEBUG;
106 : #endif
107 :
108 : int
109 0 : gdt_attach(struct gdt_softc *sc)
110 : {
111 0 : struct scsibus_attach_args saa;
112 : u_int16_t cdev_cnt;
113 0 : int i, id, drv_cyls, drv_hds, drv_secs, error, nsegs;
114 :
115 0 : gdt_polling = 1;
116 0 : gdt_from_wait = 0;
117 :
118 0 : if (bus_dmamem_alloc(sc->sc_dmat, GDT_SCRATCH_SZ, PAGE_SIZE, 0,
119 : &sc->sc_scratch_seg, 1, &nsegs, BUS_DMA_NOWAIT))
120 0 : panic("%s: bus_dmamem_alloc failed", DEVNAME(sc));
121 0 : if (bus_dmamem_map(sc->sc_dmat, &sc->sc_scratch_seg, 1,
122 : GDT_SCRATCH_SZ, &sc->sc_scratch, BUS_DMA_NOWAIT))
123 0 : panic("%s: bus_dmamem_map failed", DEVNAME(sc));
124 :
125 0 : gdt_clear_events(sc);
126 :
127 0 : TAILQ_INIT(&sc->sc_free_ccb);
128 0 : TAILQ_INIT(&sc->sc_ccbq);
129 0 : TAILQ_INIT(&sc->sc_ucmdq);
130 0 : SIMPLEQ_INIT(&sc->sc_queue);
131 :
132 0 : mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
133 0 : scsi_iopool_init(&sc->sc_iopool, sc, gdt_ccb_alloc, gdt_ccb_free);
134 :
135 : /* Initialize the ccbs */
136 0 : for (i = 0; i < GDT_MAXCMDS; i++) {
137 0 : sc->sc_ccbs[i].gc_cmd_index = i + 2;
138 0 : error = bus_dmamap_create(sc->sc_dmat,
139 : (GDT_MAXOFFSETS - 1) << PGSHIFT, GDT_MAXOFFSETS,
140 : (GDT_MAXOFFSETS - 1) << PGSHIFT, 0,
141 : BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
142 : &sc->sc_ccbs[i].gc_dmamap_xfer);
143 0 : if (error) {
144 0 : printf("%s: cannot create ccb dmamap (%d)",
145 0 : DEVNAME(sc), error);
146 0 : return (1);
147 : }
148 0 : (void)gdt_ccb_set_cmd(sc->sc_ccbs + i, GDT_GCF_UNUSED);
149 0 : TAILQ_INSERT_TAIL(&sc->sc_free_ccb, &sc->sc_ccbs[i],
150 : gc_chain);
151 : }
152 :
153 : /* Fill in the prototype scsi_link. */
154 0 : sc->sc_link.adapter_softc = sc;
155 0 : sc->sc_link.adapter = &gdt_switch;
156 : /* openings will be filled in later. */
157 0 : sc->sc_link.adapter_buswidth =
158 0 : (sc->sc_class & GDT_FC) ? GDT_MAXID : GDT_MAX_HDRIVES;
159 0 : sc->sc_link.adapter_target = sc->sc_link.adapter_buswidth;
160 0 : sc->sc_link.pool = &sc->sc_iopool;
161 :
162 0 : if (!gdt_internal_cmd(sc, GDT_SCREENSERVICE, GDT_INIT, 0, 0, 0)) {
163 0 : printf("screen service initialization error %d\n",
164 0 : sc->sc_status);
165 0 : return (1);
166 : }
167 :
168 0 : if (!gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_INIT, GDT_LINUX_OS, 0,
169 : 0)) {
170 0 : printf("cache service initialization error %d\n",
171 0 : sc->sc_status);
172 0 : return (1);
173 : }
174 :
175 0 : cdev_cnt = (u_int16_t)sc->sc_info;
176 :
177 : /* Detect number of busses */
178 0 : gdt_enc32(sc->sc_scratch + GDT_IOC_VERSION, GDT_IOC_NEWEST);
179 0 : sc->sc_scratch[GDT_IOC_LIST_ENTRIES] = GDT_MAXBUS;
180 0 : sc->sc_scratch[GDT_IOC_FIRST_CHAN] = 0;
181 0 : sc->sc_scratch[GDT_IOC_LAST_CHAN] = GDT_MAXBUS - 1;
182 0 : gdt_enc32(sc->sc_scratch + GDT_IOC_LIST_OFFSET, GDT_IOC_HDR_SZ);
183 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL,
184 : GDT_IOCHAN_RAW_DESC, GDT_INVALID_CHANNEL,
185 : GDT_IOC_HDR_SZ + GDT_RAWIOC_SZ)) {
186 0 : sc->sc_bus_cnt = sc->sc_scratch[GDT_IOC_CHAN_COUNT];
187 0 : for (i = 0; i < sc->sc_bus_cnt; i++) {
188 0 : id = sc->sc_scratch[GDT_IOC_HDR_SZ +
189 0 : i * GDT_RAWIOC_SZ + GDT_RAWIOC_PROC_ID];
190 0 : sc->sc_bus_id[id] = id < GDT_MAXBUS ? id : 0xff;
191 : }
192 :
193 : } else {
194 : /* New method failed, use fallback. */
195 0 : gdt_enc32(sc->sc_scratch + GDT_GETCH_CHANNEL_NO, i);
196 0 : for (i = 0; i < GDT_MAXBUS; i++) {
197 0 : if (!gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL,
198 : GDT_SCSI_CHAN_CNT | GDT_L_CTRL_PATTERN,
199 : GDT_IO_CHANNEL | GDT_INVALID_CHANNEL,
200 : GDT_GETCH_SZ)) {
201 0 : if (i == 0) {
202 0 : printf("cannot get channel count, "
203 0 : "error %d\n", sc->sc_status);
204 0 : return (1);
205 : }
206 : break;
207 : }
208 0 : sc->sc_bus_id[i] =
209 0 : (sc->sc_scratch[GDT_GETCH_SIOP_ID] < GDT_MAXID) ?
210 : sc->sc_scratch[GDT_GETCH_SIOP_ID] : 0xff;
211 : }
212 0 : sc->sc_bus_cnt = i;
213 : }
214 :
215 : /* Read cache configuration */
216 0 : if (!gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL, GDT_CACHE_INFO,
217 : GDT_INVALID_CHANNEL, GDT_CINFO_SZ)) {
218 0 : printf("cannot get cache info, error %d\n", sc->sc_status);
219 0 : return (1);
220 : }
221 0 : sc->sc_cpar.cp_version =
222 0 : gdt_dec32(sc->sc_scratch + GDT_CPAR_VERSION);
223 0 : sc->sc_cpar.cp_state = gdt_dec16(sc->sc_scratch + GDT_CPAR_STATE);
224 0 : sc->sc_cpar.cp_strategy =
225 0 : gdt_dec16(sc->sc_scratch + GDT_CPAR_STRATEGY);
226 0 : sc->sc_cpar.cp_write_back =
227 0 : gdt_dec16(sc->sc_scratch + GDT_CPAR_WRITE_BACK);
228 0 : sc->sc_cpar.cp_block_size =
229 0 : gdt_dec16(sc->sc_scratch + GDT_CPAR_BLOCK_SIZE);
230 :
231 : /* Read board information and features */
232 0 : sc->sc_more_proc = 0;
233 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL, GDT_BOARD_INFO,
234 : GDT_INVALID_CHANNEL, GDT_BINFO_SZ)) {
235 : /* XXX A lot of these assignments can probably go later */
236 0 : sc->sc_binfo.bi_ser_no =
237 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_SER_NO);
238 0 : bcopy(sc->sc_scratch + GDT_BINFO_OEM_ID,
239 0 : sc->sc_binfo.bi_oem_id, sizeof sc->sc_binfo.bi_oem_id);
240 0 : sc->sc_binfo.bi_ep_flags =
241 0 : gdt_dec16(sc->sc_scratch + GDT_BINFO_EP_FLAGS);
242 0 : sc->sc_binfo.bi_proc_id =
243 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_PROC_ID);
244 0 : sc->sc_binfo.bi_memsize =
245 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_MEMSIZE);
246 0 : sc->sc_binfo.bi_mem_banks =
247 0 : sc->sc_scratch[GDT_BINFO_MEM_BANKS];
248 0 : sc->sc_binfo.bi_chan_type =
249 0 : sc->sc_scratch[GDT_BINFO_CHAN_TYPE];
250 0 : sc->sc_binfo.bi_chan_count =
251 0 : sc->sc_scratch[GDT_BINFO_CHAN_COUNT];
252 0 : sc->sc_binfo.bi_rdongle_pres =
253 0 : sc->sc_scratch[GDT_BINFO_RDONGLE_PRES];
254 0 : sc->sc_binfo.bi_epr_fw_ver =
255 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_EPR_FW_VER);
256 0 : sc->sc_binfo.bi_upd_fw_ver =
257 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_UPD_FW_VER);
258 0 : sc->sc_binfo.bi_upd_revision =
259 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_UPD_REVISION);
260 0 : bcopy(sc->sc_scratch + GDT_BINFO_TYPE_STRING,
261 0 : sc->sc_binfo.bi_type_string,
262 : sizeof sc->sc_binfo.bi_type_string);
263 0 : bcopy(sc->sc_scratch + GDT_BINFO_RAID_STRING,
264 0 : sc->sc_binfo.bi_raid_string,
265 : sizeof sc->sc_binfo.bi_raid_string);
266 0 : sc->sc_binfo.bi_update_pres =
267 0 : sc->sc_scratch[GDT_BINFO_UPDATE_PRES];
268 0 : sc->sc_binfo.bi_xor_pres =
269 0 : sc->sc_scratch[GDT_BINFO_XOR_PRES];
270 0 : sc->sc_binfo.bi_prom_type =
271 0 : sc->sc_scratch[GDT_BINFO_PROM_TYPE];
272 0 : sc->sc_binfo.bi_prom_count =
273 0 : sc->sc_scratch[GDT_BINFO_PROM_COUNT];
274 0 : sc->sc_binfo.bi_dup_pres =
275 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_DUP_PRES);
276 0 : sc->sc_binfo.bi_chan_pres =
277 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_CHAN_PRES);
278 0 : sc->sc_binfo.bi_mem_pres =
279 0 : gdt_dec32(sc->sc_scratch + GDT_BINFO_MEM_PRES);
280 0 : sc->sc_binfo.bi_ft_bus_system =
281 0 : sc->sc_scratch[GDT_BINFO_FT_BUS_SYSTEM];
282 0 : sc->sc_binfo.bi_subtype_valid =
283 0 : sc->sc_scratch[GDT_BINFO_SUBTYPE_VALID];
284 0 : sc->sc_binfo.bi_board_subtype =
285 0 : sc->sc_scratch[GDT_BINFO_BOARD_SUBTYPE];
286 0 : sc->sc_binfo.bi_rampar_pres =
287 0 : sc->sc_scratch[GDT_BINFO_RAMPAR_PRES];
288 :
289 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL,
290 : GDT_BOARD_FEATURES, GDT_INVALID_CHANNEL, GDT_BFEAT_SZ)) {
291 0 : sc->sc_bfeat.bf_chaining =
292 0 : sc->sc_scratch[GDT_BFEAT_CHAINING];
293 0 : sc->sc_bfeat.bf_striping =
294 0 : sc->sc_scratch[GDT_BFEAT_STRIPING];
295 0 : sc->sc_bfeat.bf_mirroring =
296 0 : sc->sc_scratch[GDT_BFEAT_MIRRORING];
297 0 : sc->sc_bfeat.bf_raid =
298 0 : sc->sc_scratch[GDT_BFEAT_RAID];
299 0 : sc->sc_more_proc = 1;
300 0 : }
301 : } else {
302 : /* XXX Not implemented yet */
303 : }
304 :
305 : /* Read more information */
306 0 : if (sc->sc_more_proc) {
307 : int bus, j;
308 : /* physical drives, channel addresses */
309 : /* step 1: get magical bus number from firmware */
310 0 : gdt_enc32(sc->sc_scratch + GDT_IOC_VERSION, GDT_IOC_NEWEST);
311 0 : sc->sc_scratch[GDT_IOC_LIST_ENTRIES] = GDT_MAXBUS;
312 0 : sc->sc_scratch[GDT_IOC_FIRST_CHAN] = 0;
313 0 : sc->sc_scratch[GDT_IOC_LAST_CHAN] = GDT_MAXBUS - 1;
314 0 : gdt_enc32(sc->sc_scratch + GDT_IOC_LIST_OFFSET, GDT_IOC_HDR_SZ);
315 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL,
316 : GDT_IOCHAN_DESC, GDT_INVALID_CHANNEL,
317 : GDT_IOC_HDR_SZ + GDT_IOC_SZ * GDT_MAXBUS)) {
318 : GDT_DPRINTF(GDT_D_INFO, ("method 1\n"));
319 0 : for (bus = 0; bus < sc->sc_bus_cnt; bus++) {
320 0 : sc->sc_raw[bus].ra_address =
321 0 : gdt_dec32(sc->sc_scratch +
322 0 : GDT_IOC_HDR_SZ +
323 0 : GDT_IOC_SZ * bus +
324 : GDT_IOC_ADDRESS);
325 0 : sc->sc_raw[bus].ra_local_no =
326 0 : gdt_dec8(sc->sc_scratch +
327 0 : GDT_IOC_HDR_SZ +
328 0 : GDT_IOC_SZ * bus +
329 : GDT_IOC_LOCAL_NO);
330 : GDT_DPRINTF(GDT_D_INFO, (
331 : "bus: %d address: %x local: %x\n",
332 : bus,
333 : sc->sc_raw[bus].ra_address,
334 : sc->sc_raw[bus].ra_local_no));
335 : }
336 : } else {
337 : GDT_DPRINTF(GDT_D_INFO, ("method 2\n"));
338 0 : for (bus = 0; bus < sc->sc_bus_cnt; bus++) {
339 0 : sc->sc_raw[bus].ra_address = GDT_IO_CHANNEL;
340 0 : sc->sc_raw[bus].ra_local_no = bus;
341 : GDT_DPRINTF(GDT_D_INFO, (
342 : "bus: %d address: %x local: %x\n",
343 : bus,
344 : sc->sc_raw[bus].ra_address,
345 : sc->sc_raw[bus].ra_local_no));
346 : }
347 : }
348 : /* step 2: use magical bus number to get nr of phys disks */
349 0 : for (bus = 0; bus < sc->sc_bus_cnt; bus++) {
350 0 : gdt_enc32(sc->sc_scratch + GDT_GETCH_CHANNEL_NO,
351 0 : sc->sc_raw[bus].ra_local_no);
352 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_IOCTL,
353 : GDT_SCSI_CHAN_CNT | GDT_L_CTRL_PATTERN,
354 0 : sc->sc_raw[bus].ra_address | GDT_INVALID_CHANNEL,
355 : GDT_GETCH_SZ)) {
356 0 : sc->sc_raw[bus].ra_phys_cnt =
357 0 : gdt_dec32(sc->sc_scratch +
358 : GDT_GETCH_DRIVE_CNT);
359 : GDT_DPRINTF(GDT_D_INFO, ("chan: %d disks: %d\n",
360 : bus, sc->sc_raw[bus].ra_phys_cnt));
361 0 : }
362 :
363 : /* step 3: get scsi disk nr */
364 0 : if (sc->sc_raw[bus].ra_phys_cnt > 0) {
365 0 : gdt_enc32(sc->sc_scratch +
366 : GDT_GETSCSI_CHAN,
367 0 : sc->sc_raw[bus].ra_local_no);
368 0 : gdt_enc32(sc->sc_scratch +
369 : GDT_GETSCSI_CNT,
370 0 : sc->sc_raw[bus].ra_phys_cnt);
371 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE,
372 : GDT_IOCTL,
373 : GDT_SCSI_DR_LIST | GDT_L_CTRL_PATTERN,
374 0 : sc->sc_raw[bus].ra_address |
375 : GDT_INVALID_CHANNEL,
376 : GDT_GETSCSI_SZ))
377 0 : for (j = 0;
378 0 : j < sc->sc_raw[bus].ra_phys_cnt;
379 0 : j++) {
380 0 : sc->sc_raw[bus].ra_id_list[j] =
381 0 : gdt_dec32(sc->sc_scratch +
382 0 : GDT_GETSCSI_LIST +
383 0 : GDT_GETSCSI_LIST_SZ * j);
384 : GDT_DPRINTF(GDT_D_INFO,
385 : (" diskid: %d\n",
386 : sc->sc_raw[bus].ra_id_list[j]));
387 : }
388 : else
389 0 : sc->sc_raw[bus].ra_phys_cnt = 0;
390 : }
391 : /* add found disks to grand total */
392 0 : sc->sc_total_disks += sc->sc_raw[bus].ra_phys_cnt;
393 : }
394 0 : } /* if (sc->sc_more_proc) */
395 :
396 0 : if (!gdt_internal_cmd(sc, GDT_SCSIRAWSERVICE, GDT_INIT, 0, 0, 0)) {
397 0 : printf("raw service initialization error %d\n",
398 0 : sc->sc_status);
399 0 : return (1);
400 : }
401 :
402 : /* Set/get features raw service (scatter/gather) */
403 0 : sc->sc_raw_feat = 0;
404 0 : if (gdt_internal_cmd(sc, GDT_SCSIRAWSERVICE, GDT_SET_FEAT,
405 : GDT_SCATTER_GATHER, 0, 0))
406 0 : if (gdt_internal_cmd(sc, GDT_SCSIRAWSERVICE, GDT_GET_FEAT, 0,
407 : 0, 0))
408 0 : sc->sc_raw_feat = sc->sc_info;
409 :
410 : /* Set/get features cache service (scatter/gather) */
411 0 : sc->sc_cache_feat = 0;
412 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_SET_FEAT, 0,
413 : GDT_SCATTER_GATHER, 0))
414 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_GET_FEAT, 0, 0,
415 : 0))
416 0 : sc->sc_cache_feat = sc->sc_info;
417 :
418 : /* XXX Linux reserve drives here, potentially */
419 :
420 0 : sc->sc_ndevs = 0;
421 : /* Scan for cache devices */
422 0 : for (i = 0; i < cdev_cnt && i < GDT_MAX_HDRIVES; i++)
423 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE, GDT_INFO, i, 0,
424 : 0)) {
425 0 : sc->sc_hdr[i].hd_present = 1;
426 0 : sc->sc_hdr[i].hd_size = sc->sc_info;
427 :
428 0 : if (sc->sc_hdr[i].hd_size > 0)
429 0 : sc->sc_ndevs++;
430 :
431 : /*
432 : * Evaluate mapping (sectors per head, heads per cyl)
433 : */
434 0 : sc->sc_hdr[i].hd_size &= ~GDT_SECS32;
435 0 : if (sc->sc_info2 == 0)
436 0 : gdt_eval_mapping(sc->sc_hdr[i].hd_size,
437 : &drv_cyls, &drv_hds, &drv_secs);
438 : else {
439 0 : drv_hds = sc->sc_info2 & 0xff;
440 0 : drv_secs = (sc->sc_info2 >> 8) & 0xff;
441 0 : drv_cyls = sc->sc_hdr[i].hd_size / drv_hds /
442 : drv_secs;
443 : }
444 0 : sc->sc_hdr[i].hd_heads = drv_hds;
445 0 : sc->sc_hdr[i].hd_secs = drv_secs;
446 : /* Round the size */
447 0 : sc->sc_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs;
448 :
449 0 : if (gdt_internal_cmd(sc, GDT_CACHESERVICE,
450 : GDT_DEVTYPE, i, 0, 0))
451 0 : sc->sc_hdr[i].hd_devtype = sc->sc_info;
452 : }
453 :
454 0 : if (sc->sc_ndevs == 0)
455 0 : sc->sc_link.openings = 0;
456 : else
457 0 : sc->sc_link.openings = (GDT_MAXCMDS - GDT_CMD_RESERVE) /
458 : sc->sc_ndevs;
459 :
460 0 : printf("dpmem %llx %d-bus %d cache device%s\n",
461 0 : (long long)sc->sc_dpmembase,
462 0 : sc->sc_bus_cnt, cdev_cnt, cdev_cnt == 1 ? "" : "s");
463 0 : printf("%s: ver %x, cache %s, strategy %d, writeback %s, blksz %d\n",
464 0 : DEVNAME(sc), sc->sc_cpar.cp_version,
465 0 : sc->sc_cpar.cp_state ? "on" : "off", sc->sc_cpar.cp_strategy,
466 0 : sc->sc_cpar.cp_write_back ? "on" : "off",
467 0 : sc->sc_cpar.cp_block_size);
468 : #if 1
469 0 : printf("%s: raw feat %x cache feat %x\n", DEVNAME(sc),
470 0 : sc->sc_raw_feat, sc->sc_cache_feat);
471 : #endif
472 :
473 : #if NBIO > 0
474 0 : if (bio_register(&sc->sc_dev, gdt_ioctl) != 0)
475 0 : panic("%s: controller registration failed", DEVNAME(sc));
476 : #endif
477 0 : gdt_cnt++;
478 :
479 0 : bzero(&saa, sizeof(saa));
480 0 : saa.saa_sc_link = &sc->sc_link;
481 :
482 0 : config_found(&sc->sc_dev, &saa, scsiprint);
483 :
484 0 : gdt_polling = 0;
485 0 : return (0);
486 0 : }
487 :
488 : void
489 0 : gdt_eval_mapping(u_int32_t size, int *cyls, int *heads, int *secs)
490 : {
491 0 : *cyls = size / GDT_HEADS / GDT_SECS;
492 0 : if (*cyls < GDT_MAXCYLS) {
493 0 : *heads = GDT_HEADS;
494 0 : *secs = GDT_SECS;
495 0 : } else {
496 : /* Too high for 64 * 32 */
497 0 : *cyls = size / GDT_MEDHEADS / GDT_MEDSECS;
498 0 : if (*cyls < GDT_MAXCYLS) {
499 0 : *heads = GDT_MEDHEADS;
500 0 : *secs = GDT_MEDSECS;
501 0 : } else {
502 : /* Too high for 127 * 63 */
503 0 : *cyls = size / GDT_BIGHEADS / GDT_BIGSECS;
504 0 : *heads = GDT_BIGHEADS;
505 0 : *secs = GDT_BIGSECS;
506 : }
507 : }
508 0 : }
509 :
510 : /*
511 : * Insert a command into the driver queue, either at the front or at the tail.
512 : * It's ok to overload the freelist link as these structures are never on
513 : * the freelist at this time.
514 : */
515 : void
516 0 : gdt_enqueue(struct gdt_softc *sc, struct scsi_xfer *xs, int infront)
517 : {
518 0 : if (infront)
519 0 : SIMPLEQ_INSERT_HEAD(&sc->sc_queue, xs, xfer_list);
520 : else
521 0 : SIMPLEQ_INSERT_TAIL(&sc->sc_queue, xs, xfer_list);
522 0 : }
523 :
524 : /*
525 : * Pull a command off the front of the driver queue.
526 : */
527 : struct scsi_xfer *
528 0 : gdt_dequeue(struct gdt_softc *sc)
529 : {
530 : struct scsi_xfer *xs;
531 :
532 0 : xs = SIMPLEQ_FIRST(&sc->sc_queue);
533 0 : if (xs != NULL)
534 0 : SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, xfer_list);
535 :
536 0 : return (xs);
537 : }
538 :
539 : /*
540 : * Start a SCSI operation on a cache device.
541 : * XXX Polled operation is not yet complete. What kind of locking do we need?
542 : */
543 : void
544 0 : gdt_scsi_cmd(struct scsi_xfer *xs)
545 : {
546 0 : struct scsi_link *link = xs->sc_link;
547 0 : struct gdt_softc *sc = link->adapter_softc;
548 0 : u_int8_t target = link->target;
549 : struct gdt_ccb *ccb;
550 : u_int32_t blockno, blockcnt;
551 : struct scsi_rw *rw;
552 : struct scsi_rw_big *rwb;
553 : bus_dmamap_t xfer;
554 : int error;
555 : int s;
556 : int polled;
557 :
558 : GDT_DPRINTF(GDT_D_CMD, ("gdt_scsi_cmd "));
559 :
560 0 : s = splbio();
561 :
562 0 : xs->error = XS_NOERROR;
563 :
564 0 : if (target >= GDT_MAX_HDRIVES || !sc->sc_hdr[target].hd_present ||
565 0 : link->lun != 0) {
566 : /*
567 : * XXX Should be XS_SENSE but that would require setting up a
568 : * faked sense too.
569 : */
570 0 : xs->error = XS_DRIVER_STUFFUP;
571 0 : scsi_done(xs);
572 0 : splx(s);
573 0 : return;
574 : }
575 :
576 : /* Don't double enqueue if we came from gdt_chain. */
577 0 : if (xs != SIMPLEQ_FIRST(&sc->sc_queue))
578 0 : gdt_enqueue(sc, xs, 0);
579 :
580 0 : while ((xs = gdt_dequeue(sc)) != NULL) {
581 0 : xs->error = XS_NOERROR;
582 : ccb = NULL;
583 0 : link = xs->sc_link;
584 0 : target = link->target;
585 0 : polled = ISSET(xs->flags, SCSI_POLL);
586 :
587 0 : if (!gdt_polling && !(xs->flags & SCSI_POLL) &&
588 0 : sc->sc_test_busy(sc)) {
589 : /*
590 : * Put it back in front. XXX Should we instead
591 : * set xs->error to XS_BUSY?
592 : */
593 0 : gdt_enqueue(sc, xs, 1);
594 0 : break;
595 : }
596 :
597 0 : switch (xs->cmd->opcode) {
598 : case TEST_UNIT_READY:
599 : case REQUEST_SENSE:
600 : case INQUIRY:
601 : case MODE_SENSE:
602 : case START_STOP:
603 : case READ_CAPACITY:
604 : #if 0
605 : case VERIFY:
606 : #endif
607 0 : gdt_internal_cache_cmd(xs);
608 0 : scsi_done(xs);
609 0 : goto ready;
610 :
611 : case PREVENT_ALLOW:
612 : GDT_DPRINTF(GDT_D_CMD, ("PREVENT/ALLOW "));
613 : /* XXX Not yet implemented */
614 0 : xs->error = XS_NOERROR;
615 0 : scsi_done(xs);
616 0 : goto ready;
617 :
618 : default:
619 : GDT_DPRINTF(GDT_D_CMD,
620 : ("unknown opc %d ", xs->cmd->opcode));
621 : /* XXX Not yet implemented */
622 0 : xs->error = XS_DRIVER_STUFFUP;
623 0 : scsi_done(xs);
624 0 : goto ready;
625 :
626 : case READ_COMMAND:
627 : case READ_BIG:
628 : case WRITE_COMMAND:
629 : case WRITE_BIG:
630 : case SYNCHRONIZE_CACHE:
631 : /*
632 : * A new command chain, start from the beginning.
633 : */
634 0 : sc->sc_cmd_off = 0;
635 :
636 0 : if (xs->cmd->opcode == SYNCHRONIZE_CACHE) {
637 : blockno = blockcnt = 0;
638 0 : } else {
639 : /* A read or write operation. */
640 0 : if (xs->cmdlen == 6) {
641 0 : rw = (struct scsi_rw *)xs->cmd;
642 0 : blockno = _3btol(rw->addr) &
643 : (SRW_TOPADDR << 16 | 0xffff);
644 : blockcnt =
645 0 : rw->length ? rw->length : 0x100;
646 0 : } else {
647 0 : rwb = (struct scsi_rw_big *)xs->cmd;
648 0 : blockno = _4btol(rwb->addr);
649 0 : blockcnt = _2btol(rwb->length);
650 : }
651 0 : if (blockno >= sc->sc_hdr[target].hd_size ||
652 0 : blockno + blockcnt >
653 : sc->sc_hdr[target].hd_size) {
654 0 : printf(
655 : "%s: out of bounds %u-%u >= %u\n",
656 0 : DEVNAME(sc), blockno,
657 : blockcnt,
658 0 : sc->sc_hdr[target].hd_size);
659 : /*
660 : * XXX Should be XS_SENSE but that
661 : * would require setting up a faked
662 : * sense too.
663 : */
664 0 : xs->error = XS_DRIVER_STUFFUP;
665 0 : scsi_done(xs);
666 0 : goto ready;
667 : }
668 : }
669 :
670 0 : ccb = xs->io;
671 0 : ccb->gc_blockno = blockno;
672 0 : ccb->gc_blockcnt = blockcnt;
673 0 : ccb->gc_xs = xs;
674 0 : ccb->gc_timeout = xs->timeout;
675 0 : ccb->gc_service = GDT_CACHESERVICE;
676 0 : ccb->gc_flags = 0;
677 0 : gdt_ccb_set_cmd(ccb, GDT_GCF_SCSI);
678 :
679 0 : if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
680 0 : xfer = ccb->gc_dmamap_xfer;
681 0 : error = bus_dmamap_load(sc->sc_dmat, xfer,
682 : xs->data, xs->datalen, NULL,
683 : (xs->flags & SCSI_NOSLEEP) ?
684 : BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
685 0 : if (error) {
686 0 : printf("%s: gdt_scsi_cmd: ",
687 0 : DEVNAME(sc));
688 0 : if (error == EFBIG)
689 0 : printf(
690 : "more than %d dma segs\n",
691 : GDT_MAXOFFSETS);
692 : else
693 0 : printf("error %d "
694 : "loading dma map\n",
695 : error);
696 :
697 0 : xs->error = XS_DRIVER_STUFFUP;
698 0 : scsi_done(xs);
699 0 : goto ready;
700 : }
701 0 : bus_dmamap_sync(sc->sc_dmat, xfer, 0,
702 : xfer->dm_mapsize,
703 : (xs->flags & SCSI_DATA_IN) ?
704 : BUS_DMASYNC_PREREAD :
705 : BUS_DMASYNC_PREWRITE);
706 0 : }
707 :
708 0 : gdt_enqueue_ccb(sc, ccb);
709 : /* XXX what if enqueue did not start a transfer? */
710 0 : if (gdt_polling || (xs->flags & SCSI_POLL)) {
711 0 : if (!gdt_wait(sc, ccb, ccb->gc_timeout)) {
712 0 : printf("%s: command %d timed out\n",
713 0 : DEVNAME(sc),
714 0 : ccb->gc_cmd_index);
715 0 : xs->error = XS_TIMEOUT;
716 0 : scsi_done(xs);
717 0 : splx(s);
718 0 : return;
719 : }
720 : }
721 : }
722 :
723 : ready:
724 : /*
725 : * Don't process the queue if we are polling.
726 : */
727 0 : if (polled) {
728 : break;
729 : }
730 : }
731 :
732 0 : splx(s);
733 0 : }
734 :
735 : /* XXX Currently only for cacheservice, returns 0 if busy */
736 : int
737 0 : gdt_exec_ccb(struct gdt_ccb *ccb)
738 : {
739 0 : struct scsi_xfer *xs = ccb->gc_xs;
740 0 : struct scsi_link *link = xs->sc_link;
741 0 : struct gdt_softc *sc = link->adapter_softc;
742 0 : u_int8_t target = link->target;
743 : u_int32_t sg_canz;
744 : bus_dmamap_t xfer;
745 : int i;
746 : #if 1 /* XXX */
747 : static int __level = 0;
748 :
749 0 : if (__level++ > 0)
750 0 : panic("level > 0");
751 : #endif
752 : GDT_DPRINTF(GDT_D_CMD, ("gdt_exec_ccb(%p, %p) ", xs, ccb));
753 :
754 0 : sc->sc_cmd_cnt = 0;
755 :
756 : /*
757 : * XXX Yeah I know it's an always-true condition, but that may change
758 : * later.
759 : */
760 0 : if (sc->sc_cmd_cnt == 0)
761 0 : sc->sc_set_sema0(sc);
762 :
763 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_COMMANDINDEX, ccb->gc_cmd_index);
764 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_BOARDNODE, GDT_LOCALBOARD);
765 0 : gdt_enc16(sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
766 0 : target);
767 :
768 0 : switch (xs->cmd->opcode) {
769 : case PREVENT_ALLOW:
770 : case SYNCHRONIZE_CACHE:
771 0 : if (xs->cmd->opcode == PREVENT_ALLOW) {
772 : /* XXX PREVENT_ALLOW support goes here */
773 : } else {
774 : GDT_DPRINTF(GDT_D_CMD,
775 : ("SYNCHRONIZE CACHE tgt %d ", target));
776 0 : sc->sc_cmd[GDT_CMD_OPCODE] = GDT_FLUSH;
777 : }
778 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
779 : 1);
780 : sg_canz = 0;
781 0 : break;
782 :
783 : case WRITE_COMMAND:
784 : case WRITE_BIG:
785 : /* XXX WRITE_THR could be supported too */
786 0 : sc->sc_cmd[GDT_CMD_OPCODE] = GDT_WRITE;
787 0 : break;
788 :
789 : case READ_COMMAND:
790 : case READ_BIG:
791 0 : sc->sc_cmd[GDT_CMD_OPCODE] = GDT_READ;
792 0 : break;
793 : }
794 :
795 0 : if (xs->cmd->opcode != PREVENT_ALLOW &&
796 0 : xs->cmd->opcode != SYNCHRONIZE_CACHE) {
797 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
798 0 : ccb->gc_blockno);
799 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
800 0 : ccb->gc_blockcnt);
801 :
802 0 : xfer = ccb->gc_dmamap_xfer;
803 0 : if (sc->sc_cache_feat & GDT_SCATTER_GATHER) {
804 0 : gdt_enc32(
805 : sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
806 : 0xffffffff);
807 0 : for (i = 0; i < xfer->dm_nsegs; i++) {
808 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
809 0 : GDT_CACHE_SG_LST + i * GDT_SG_SZ +
810 : GDT_SG_PTR,
811 0 : xfer->dm_segs[i].ds_addr);
812 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
813 0 : GDT_CACHE_SG_LST + i * GDT_SG_SZ +
814 : GDT_SG_LEN,
815 0 : xfer->dm_segs[i].ds_len);
816 : GDT_DPRINTF(GDT_D_IO,
817 : ("#%d va %p pa %p len %x\n", i, buf,
818 : xfer->dm_segs[i].ds_addr,
819 : xfer->dm_segs[i].ds_len));
820 : }
821 : sg_canz = xfer->dm_nsegs;
822 0 : gdt_enc32(
823 0 : sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
824 0 : sg_canz * GDT_SG_SZ + GDT_SG_LEN, 0);
825 0 : } else {
826 : /* XXX Hardly correct */
827 0 : gdt_enc32(
828 : sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
829 0 : xfer->dm_segs[0].ds_addr);
830 : sg_canz = 0;
831 : }
832 : }
833 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ, sg_canz);
834 :
835 0 : sc->sc_cmd_len =
836 0 : roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST + sg_canz * GDT_SG_SZ,
837 : sizeof (u_int32_t));
838 :
839 0 : if (sc->sc_cmd_cnt > 0 &&
840 0 : sc->sc_cmd_off + sc->sc_cmd_len + GDT_DPMEM_COMMAND_OFFSET >
841 0 : sc->sc_ic_all_size) {
842 0 : printf("%s: DPMEM overflow\n", DEVNAME(sc));
843 0 : xs->error = XS_BUSY;
844 : #if 1 /* XXX */
845 0 : __level--;
846 : #endif
847 0 : return (0);
848 : }
849 :
850 0 : sc->sc_copy_cmd(sc, ccb);
851 0 : sc->sc_release_event(sc, ccb);
852 :
853 0 : xs->error = XS_NOERROR;
854 0 : xs->resid = 0;
855 : #if 1 /* XXX */
856 0 : __level--;
857 : #endif
858 0 : return (1);
859 0 : }
860 :
861 : void
862 0 : gdt_copy_internal_data(struct scsi_xfer *xs, u_int8_t *data, size_t size)
863 : {
864 : size_t copy_cnt;
865 :
866 : GDT_DPRINTF(GDT_D_MISC, ("gdt_copy_internal_data "));
867 :
868 0 : if (!xs->datalen)
869 0 : printf("uio move not yet supported\n");
870 : else {
871 0 : copy_cnt = MIN(size, xs->datalen);
872 0 : bcopy(data, xs->data, copy_cnt);
873 : }
874 0 : }
875 :
876 : /* Emulated SCSI operation on cache device */
877 : void
878 0 : gdt_internal_cache_cmd(struct scsi_xfer *xs)
879 : {
880 0 : struct scsi_link *link = xs->sc_link;
881 0 : struct gdt_softc *sc = link->adapter_softc;
882 0 : struct scsi_inquiry_data inq;
883 0 : struct scsi_sense_data sd;
884 0 : struct scsi_read_cap_data rcd;
885 0 : u_int8_t target = link->target;
886 :
887 : GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cache_cmd "));
888 :
889 0 : switch (xs->cmd->opcode) {
890 : case TEST_UNIT_READY:
891 : case START_STOP:
892 : #if 0
893 : case VERIFY:
894 : #endif
895 : GDT_DPRINTF(GDT_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
896 : target));
897 : break;
898 :
899 : case REQUEST_SENSE:
900 : GDT_DPRINTF(GDT_D_CMD, ("REQUEST SENSE tgt %d ", target));
901 0 : bzero(&sd, sizeof sd);
902 0 : sd.error_code = SSD_ERRCODE_CURRENT;
903 0 : sd.segment = 0;
904 0 : sd.flags = SKEY_NO_SENSE;
905 0 : gdt_enc32(sd.info, 0);
906 0 : sd.extra_len = 0;
907 0 : gdt_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
908 0 : break;
909 :
910 : case INQUIRY:
911 : GDT_DPRINTF(GDT_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
912 : sc->sc_hdr[target].hd_devtype));
913 0 : bzero(&inq, sizeof inq);
914 0 : inq.device =
915 0 : (sc->sc_hdr[target].hd_devtype & 4) ? T_CDROM : T_DIRECT;
916 0 : inq.dev_qual2 =
917 0 : (sc->sc_hdr[target].hd_devtype & 1) ? SID_REMOVABLE : 0;
918 0 : inq.version = 2;
919 0 : inq.response_format = 2;
920 0 : inq.additional_length = 32;
921 0 : inq.flags |= SID_CmdQue;
922 0 : strlcpy(inq.vendor, "ICP ", sizeof inq.vendor);
923 0 : snprintf(inq.product, sizeof inq.product, "Host drive #%02d",
924 0 : target);
925 0 : strlcpy(inq.revision, " ", sizeof inq.revision);
926 0 : gdt_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
927 0 : break;
928 :
929 : case READ_CAPACITY:
930 : GDT_DPRINTF(GDT_D_CMD, ("READ CAPACITY tgt %d ", target));
931 0 : bzero(&rcd, sizeof rcd);
932 0 : _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
933 0 : _lto4b(GDT_SECTOR_SIZE, rcd.length);
934 0 : gdt_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
935 0 : break;
936 :
937 : default:
938 : GDT_DPRINTF(GDT_D_CMD, ("unsupported scsi command %#x tgt %d ",
939 : xs->cmd->opcode, target));
940 0 : xs->error = XS_DRIVER_STUFFUP;
941 0 : return;
942 : }
943 :
944 0 : xs->error = XS_NOERROR;
945 0 : }
946 :
947 : void
948 0 : gdt_clear_events(struct gdt_softc *sc)
949 : {
950 : GDT_DPRINTF(GDT_D_MISC, ("gdt_clear_events(%p) ", sc));
951 :
952 : /* XXX To be implemented */
953 0 : }
954 :
955 : int
956 0 : gdt_async_event(struct gdt_softc *sc, int service)
957 : {
958 : GDT_DPRINTF(GDT_D_INTR, ("gdt_async_event(%p, %d) ", sc, service));
959 :
960 : if (service == GDT_SCREENSERVICE) {
961 : /* XXX To be implemented */
962 : } else {
963 : /* XXX To be implemented */
964 : }
965 :
966 0 : return (0);
967 : }
968 :
969 : int
970 0 : gdt_sync_event(struct gdt_softc *sc, int service, u_int8_t index,
971 : struct scsi_xfer *xs)
972 : {
973 : GDT_DPRINTF(GDT_D_INTR,
974 : ("gdt_sync_event(%p, %d, %d, %p) ", sc, service, index, xs));
975 :
976 0 : if (service == GDT_SCREENSERVICE) {
977 : GDT_DPRINTF(GDT_D_INTR, ("service == GDT_SCREENSERVICE "));
978 : /* XXX To be implemented */
979 0 : return (0);
980 : } else {
981 0 : switch (sc->sc_status) {
982 : case GDT_S_OK:
983 : GDT_DPRINTF(GDT_D_INTR, ("sc_status == GDT_S_OK "));
984 : /* XXX To be implemented */
985 : break;
986 : case GDT_S_BSY:
987 : GDT_DPRINTF(GDT_D_INTR, ("sc_status == GDT_S_BSY "));
988 : /* XXX To be implemented */
989 0 : return (2);
990 : default:
991 : GDT_DPRINTF(GDT_D_INTR, ("sc_status is %d ",
992 : sc->sc_status));
993 : /* XXX To be implemented */
994 0 : return (0);
995 : }
996 : }
997 :
998 0 : return (1);
999 0 : }
1000 :
1001 : int
1002 0 : gdt_intr(void *arg)
1003 : {
1004 0 : struct gdt_softc *sc = arg;
1005 0 : struct gdt_intr_ctx ctx;
1006 : int chain = 1;
1007 : int sync_val = 0;
1008 : struct scsi_xfer *xs = NULL;
1009 : int prev_cmd;
1010 : struct gdt_ccb *ccb;
1011 :
1012 : GDT_DPRINTF(GDT_D_INTR, ("gdt_intr(%p) ", sc));
1013 :
1014 : /* If polling and we were not called from gdt_wait, just return */
1015 0 : if (gdt_polling && !gdt_from_wait)
1016 0 : return (0);
1017 :
1018 0 : ctx.istatus = sc->sc_get_status(sc);
1019 0 : if (!ctx.istatus) {
1020 0 : sc->sc_status = GDT_S_NO_STATUS;
1021 0 : return (0);
1022 : }
1023 :
1024 0 : gdt_wait_index = 0;
1025 0 : ctx.service = ctx.info2 = 0;
1026 :
1027 0 : sc->sc_intr(sc, &ctx);
1028 :
1029 0 : sc->sc_status = ctx.cmd_status;
1030 0 : sc->sc_info = ctx.info;
1031 0 : sc->sc_info2 = ctx.info2;
1032 :
1033 0 : if (gdt_from_wait) {
1034 0 : gdt_wait_gdt = sc;
1035 0 : gdt_wait_index = ctx.istatus;
1036 0 : }
1037 :
1038 0 : switch (ctx.istatus) {
1039 : case GDT_ASYNCINDEX:
1040 0 : gdt_async_event(sc, ctx.service);
1041 0 : goto finish;
1042 :
1043 : case GDT_SPEZINDEX:
1044 0 : printf("%s: uninitialized or unknown service (%d %d)\n",
1045 0 : DEVNAME(sc), ctx.info, ctx.info2);
1046 : chain = 0;
1047 0 : goto finish;
1048 : }
1049 :
1050 0 : ccb = &sc->sc_ccbs[ctx.istatus - 2];
1051 0 : xs = ccb->gc_xs;
1052 0 : if (!gdt_polling)
1053 0 : timeout_del(&xs->stimeout);
1054 0 : ctx.service = ccb->gc_service;
1055 0 : prev_cmd = ccb->gc_flags & GDT_GCF_CMD_MASK;
1056 0 : if (xs && xs->cmd->opcode != PREVENT_ALLOW &&
1057 0 : xs->cmd->opcode != SYNCHRONIZE_CACHE) {
1058 0 : bus_dmamap_sync(sc->sc_dmat, ccb->gc_dmamap_xfer, 0,
1059 : ccb->gc_dmamap_xfer->dm_mapsize,
1060 : (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1061 : BUS_DMASYNC_POSTWRITE);
1062 0 : bus_dmamap_unload(sc->sc_dmat, ccb->gc_dmamap_xfer);
1063 0 : }
1064 0 : switch (prev_cmd) {
1065 : case GDT_GCF_UNUSED:
1066 : /* XXX Not yet implemented */
1067 : chain = 0;
1068 0 : goto finish;
1069 : case GDT_GCF_INTERNAL:
1070 : chain = 0;
1071 0 : goto finish;
1072 : }
1073 :
1074 0 : sync_val = gdt_sync_event(sc, ctx.service, ctx.istatus, xs);
1075 :
1076 : finish:
1077 0 : switch (sync_val) {
1078 : case 0:
1079 0 : if (xs && gdt_from_wait)
1080 0 : scsi_done(xs);
1081 : break;
1082 : case 1:
1083 0 : scsi_done(xs);
1084 0 : break;
1085 :
1086 : case 2:
1087 0 : gdt_enqueue(sc, xs, 0);
1088 0 : }
1089 :
1090 0 : if (chain)
1091 0 : gdt_chain(sc);
1092 :
1093 0 : return (1);
1094 0 : }
1095 :
1096 : void
1097 0 : gdtminphys(struct buf *bp, struct scsi_link *sl)
1098 : {
1099 : GDT_DPRINTF(GDT_D_MISC, ("gdtminphys(0x%x) ", bp));
1100 :
1101 : /* As this is way more than MAXPHYS it's really not necessary. */
1102 : if ((GDT_MAXOFFSETS - 1) * PAGE_SIZE < MAXPHYS &&
1103 : bp->b_bcount > ((GDT_MAXOFFSETS - 1) * PAGE_SIZE))
1104 : bp->b_bcount = ((GDT_MAXOFFSETS - 1) * PAGE_SIZE);
1105 :
1106 0 : minphys(bp);
1107 0 : }
1108 :
1109 : int
1110 0 : gdt_wait(struct gdt_softc *sc, struct gdt_ccb *ccb, int timeout)
1111 : {
1112 : int s, rslt, rv = 0;
1113 :
1114 : GDT_DPRINTF(GDT_D_MISC,
1115 : ("gdt_wait(%p, %p, %d) ", sc, ccb, timeout));
1116 :
1117 0 : gdt_from_wait = 1;
1118 0 : do {
1119 0 : s = splbio();
1120 0 : rslt = gdt_intr(sc);
1121 0 : splx(s);
1122 0 : if (rslt && sc == gdt_wait_gdt &&
1123 0 : ccb->gc_cmd_index == gdt_wait_index) {
1124 : rv = 1;
1125 0 : break;
1126 : }
1127 0 : DELAY(1000); /* 1 millisecond */
1128 0 : } while (--timeout);
1129 0 : gdt_from_wait = 0;
1130 :
1131 0 : while (sc->sc_test_busy(sc))
1132 0 : DELAY(0); /* XXX correct? */
1133 :
1134 0 : return (rv);
1135 : }
1136 :
1137 : int
1138 0 : gdt_internal_cmd(struct gdt_softc *sc, u_int8_t service, u_int16_t opcode,
1139 : u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
1140 : {
1141 : int retries, rslt;
1142 : struct gdt_ccb *ccb;
1143 :
1144 : GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cmd(%p, %d, %d, %d, %d, %d) ",
1145 : sc, service, opcode, arg1, arg2, arg3));
1146 :
1147 0 : bzero(sc->sc_cmd, GDT_CMD_SZ);
1148 :
1149 0 : for (retries = GDT_RETRIES; ; ) {
1150 0 : ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
1151 0 : if (ccb == NULL) {
1152 0 : printf("%s: no free command index found\n",
1153 0 : DEVNAME(sc));
1154 0 : return (0);
1155 : }
1156 0 : ccb->gc_service = service;
1157 0 : ccb->gc_xs = NULL;
1158 0 : ccb->gc_blockno = ccb->gc_blockcnt = 0;
1159 0 : ccb->gc_timeout = ccb->gc_flags = 0;
1160 0 : ccb->gc_service = GDT_CACHESERVICE;
1161 0 : gdt_ccb_set_cmd(ccb, GDT_GCF_INTERNAL);
1162 :
1163 0 : sc->sc_set_sema0(sc);
1164 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_COMMANDINDEX,
1165 0 : ccb->gc_cmd_index);
1166 0 : gdt_enc16(sc->sc_cmd + GDT_CMD_OPCODE, opcode);
1167 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_BOARDNODE, GDT_LOCALBOARD);
1168 :
1169 0 : switch (service) {
1170 : case GDT_CACHESERVICE:
1171 0 : if (opcode == GDT_IOCTL) {
1172 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
1173 : GDT_IOCTL_SUBFUNC, arg1);
1174 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
1175 : GDT_IOCTL_CHANNEL, arg2);
1176 0 : gdt_enc16(sc->sc_cmd + GDT_CMD_UNION +
1177 0 : GDT_IOCTL_PARAM_SIZE, (u_int16_t)arg3);
1178 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
1179 : GDT_IOCTL_P_PARAM,
1180 0 : sc->sc_scratch_seg.ds_addr);
1181 0 : } else {
1182 0 : gdt_enc16(sc->sc_cmd + GDT_CMD_UNION +
1183 0 : GDT_CACHE_DEVICENO, (u_int16_t)arg1);
1184 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
1185 : GDT_CACHE_BLOCKNO, arg2);
1186 : }
1187 : break;
1188 :
1189 : case GDT_SCSIRAWSERVICE:
1190 0 : gdt_enc32(sc->sc_cmd + GDT_CMD_UNION +
1191 : GDT_RAW_DIRECTION, arg1);
1192 0 : sc->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
1193 0 : (u_int8_t)arg2;
1194 0 : sc->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
1195 0 : (u_int8_t)arg3;
1196 0 : sc->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
1197 0 : (u_int8_t)(arg3 >> 8);
1198 0 : }
1199 :
1200 0 : sc->sc_cmd_len = GDT_CMD_SZ;
1201 0 : sc->sc_cmd_off = 0;
1202 0 : sc->sc_cmd_cnt = 0;
1203 0 : sc->sc_copy_cmd(sc, ccb);
1204 0 : sc->sc_release_event(sc, ccb);
1205 0 : DELAY(20);
1206 :
1207 0 : rslt = gdt_wait(sc, ccb, GDT_POLL_TIMEOUT);
1208 0 : scsi_io_put(&sc->sc_iopool, ccb);
1209 :
1210 0 : if (!rslt)
1211 0 : return (0);
1212 0 : if (sc->sc_status != GDT_S_BSY || --retries == 0)
1213 : break;
1214 0 : DELAY(1);
1215 : }
1216 0 : return (sc->sc_status == GDT_S_OK);
1217 0 : }
1218 :
1219 : void *
1220 0 : gdt_ccb_alloc(void *xsc)
1221 : {
1222 0 : struct gdt_softc *sc = xsc;
1223 : struct gdt_ccb *ccb;
1224 :
1225 : GDT_DPRINTF(GDT_D_QUEUE, ("gdt_ccb_alloc(%p) ", sc));
1226 :
1227 0 : mtx_enter(&sc->sc_ccb_mtx);
1228 0 : ccb = TAILQ_FIRST(&sc->sc_free_ccb);
1229 0 : if (ccb != NULL)
1230 0 : TAILQ_REMOVE(&sc->sc_free_ccb, ccb, gc_chain);
1231 0 : mtx_leave(&sc->sc_ccb_mtx);
1232 :
1233 0 : return (ccb);
1234 : }
1235 :
1236 : void
1237 0 : gdt_ccb_free(void *xsc, void *xccb)
1238 : {
1239 0 : struct gdt_softc *sc = xsc;
1240 0 : struct gdt_ccb *ccb = xccb;
1241 : int wake = 0;
1242 :
1243 : GDT_DPRINTF(GDT_D_QUEUE, ("gdt_ccb_free(%p, %p) ", sc, ccb));
1244 :
1245 0 : mtx_enter(&sc->sc_ccb_mtx);
1246 0 : TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, gc_chain);
1247 : /* If the free list was empty, wake up potential waiters. */
1248 0 : if (TAILQ_NEXT(ccb, gc_chain) == NULL)
1249 0 : wake = 1;
1250 0 : mtx_leave(&sc->sc_ccb_mtx);
1251 :
1252 0 : if (wake)
1253 0 : wakeup(&sc->sc_free_ccb);
1254 0 : }
1255 :
1256 : void
1257 0 : gdt_enqueue_ccb(struct gdt_softc *sc, struct gdt_ccb *ccb)
1258 : {
1259 : GDT_DPRINTF(GDT_D_QUEUE, ("gdt_enqueue_ccb(%p, %p) ", sc, ccb));
1260 :
1261 0 : timeout_set(&ccb->gc_xs->stimeout, gdt_timeout, ccb);
1262 0 : TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, gc_chain);
1263 0 : gdt_start_ccbs(sc);
1264 0 : }
1265 :
1266 : void
1267 0 : gdt_start_ccbs(struct gdt_softc *sc)
1268 : {
1269 : struct gdt_ccb *ccb;
1270 : struct scsi_xfer *xs;
1271 :
1272 : GDT_DPRINTF(GDT_D_QUEUE, ("gdt_start_ccbs(%p) ", sc));
1273 :
1274 0 : while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {
1275 :
1276 0 : xs = ccb->gc_xs;
1277 0 : if (ccb->gc_flags & GDT_GCF_WATCHDOG)
1278 0 : timeout_del(&xs->stimeout);
1279 :
1280 0 : if (gdt_exec_ccb(ccb) == 0) {
1281 0 : ccb->gc_flags |= GDT_GCF_WATCHDOG;
1282 0 : timeout_set(&ccb->gc_xs->stimeout, gdt_watchdog, ccb);
1283 0 : timeout_add_msec(&xs->stimeout, GDT_WATCH_TIMEOUT);
1284 0 : break;
1285 : }
1286 0 : TAILQ_REMOVE(&sc->sc_ccbq, ccb, gc_chain);
1287 :
1288 0 : if ((xs->flags & SCSI_POLL) == 0) {
1289 0 : timeout_set(&ccb->gc_xs->stimeout, gdt_timeout, ccb);
1290 0 : timeout_add_msec(&xs->stimeout, ccb->gc_timeout);
1291 0 : }
1292 : }
1293 0 : }
1294 :
1295 : void
1296 0 : gdt_chain(struct gdt_softc *sc)
1297 : {
1298 : GDT_DPRINTF(GDT_D_INTR, ("gdt_chain(%p) ", sc));
1299 :
1300 0 : if (!SIMPLEQ_EMPTY(&sc->sc_queue))
1301 0 : gdt_scsi_cmd(SIMPLEQ_FIRST(&sc->sc_queue));
1302 0 : }
1303 :
1304 : void
1305 0 : gdt_timeout(void *arg)
1306 : {
1307 0 : struct gdt_ccb *ccb = arg;
1308 0 : struct scsi_link *link = ccb->gc_xs->sc_link;
1309 0 : struct gdt_softc *sc = link->adapter_softc;
1310 : int s;
1311 :
1312 0 : sc_print_addr(link);
1313 0 : printf("timed out\n");
1314 :
1315 : /* XXX Test for multiple timeouts */
1316 :
1317 0 : ccb->gc_xs->error = XS_TIMEOUT;
1318 0 : s = splbio();
1319 0 : gdt_enqueue_ccb(sc, ccb);
1320 0 : splx(s);
1321 0 : }
1322 :
1323 : void
1324 0 : gdt_watchdog(void *arg)
1325 : {
1326 0 : struct gdt_ccb *ccb = arg;
1327 0 : struct scsi_link *link = ccb->gc_xs->sc_link;
1328 0 : struct gdt_softc *sc = link->adapter_softc;
1329 : int s;
1330 :
1331 0 : s = splbio();
1332 0 : ccb->gc_flags &= ~GDT_GCF_WATCHDOG;
1333 0 : gdt_start_ccbs(sc);
1334 0 : splx(s);
1335 0 : }
1336 :
1337 : #if NBIO > 0
1338 : int
1339 0 : gdt_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1340 : {
1341 0 : struct gdt_softc *sc = (struct gdt_softc *)dev;
1342 : int error = 0;
1343 :
1344 : GDT_DPRINTF(GDT_D_IOCTL, ("%s: ioctl ", DEVNAME(sc)));
1345 :
1346 0 : switch (cmd) {
1347 : case BIOCINQ:
1348 : GDT_DPRINTF(GDT_D_IOCTL, ("inq "));
1349 0 : error = gdt_ioctl_inq(sc, (struct bioc_inq *)addr);
1350 0 : break;
1351 :
1352 : case BIOCVOL:
1353 : GDT_DPRINTF(GDT_D_IOCTL, ("vol "));
1354 0 : error = gdt_ioctl_vol(sc, (struct bioc_vol *)addr);
1355 0 : break;
1356 :
1357 : case BIOCDISK:
1358 : GDT_DPRINTF(GDT_D_IOCTL, ("disk "));
1359 0 : error = gdt_ioctl_disk(sc, (struct bioc_disk *)addr);
1360 0 : break;
1361 :
1362 : case BIOCALARM:
1363 : GDT_DPRINTF(GDT_D_IOCTL, ("alarm "));
1364 0 : error = gdt_ioctl_alarm(sc, (struct bioc_alarm *)addr);
1365 0 : break;
1366 :
1367 : case BIOCSETSTATE:
1368 : GDT_DPRINTF(GDT_D_IOCTL, ("setstate "));
1369 0 : error = gdt_ioctl_setstate(sc, (struct bioc_setstate *)addr);
1370 0 : break;
1371 :
1372 : default:
1373 : GDT_DPRINTF(GDT_D_IOCTL, (" invalid ioctl\n"));
1374 : error = ENOTTY;
1375 0 : }
1376 :
1377 0 : return (error);
1378 : }
1379 :
1380 : int
1381 0 : gdt_ioctl_inq(struct gdt_softc *sc, struct bioc_inq *bi)
1382 : {
1383 0 : bi->bi_novol = sc->sc_ndevs;
1384 0 : bi->bi_nodisk = sc->sc_total_disks;
1385 :
1386 0 : strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
1387 :
1388 0 : return (0);
1389 : }
1390 :
1391 : int
1392 0 : gdt_ioctl_vol(struct gdt_softc *sc, struct bioc_vol *bv)
1393 : {
1394 0 : return (1); /* XXX not yet */
1395 : }
1396 :
1397 : int
1398 0 : gdt_ioctl_disk(struct gdt_softc *sc, struct bioc_disk *bd)
1399 : {
1400 0 : return (1); /* XXX not yet */
1401 : }
1402 :
1403 : int
1404 0 : gdt_ioctl_alarm(struct gdt_softc *sc, struct bioc_alarm *ba)
1405 : {
1406 0 : return (1); /* XXX not yet */
1407 : }
1408 :
1409 : int
1410 0 : gdt_ioctl_setstate(struct gdt_softc *sc, struct bioc_setstate *bs)
1411 : {
1412 0 : return (1); /* XXX not yet */
1413 : }
1414 : #endif /* NBIO > 0 */
|