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