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