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