iir.c revision 113350
1/* $FreeBSD: head/sys/dev/iir/iir.c 113350 2003-04-10 23:50:06Z mux $ */
2/*
3 *       Copyright (c) 2000-01 Intel Corporation
4 *       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 *    without modification, immediately at the beginning of the file.
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 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32 * iir.c: SCSI dependant code for the Intel Integrated RAID Controller driver
33 *
34 * Written by: Achim Leubner <achim.leubner@intel.com>
35 * Fixes/Additions: Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com>
36 *
37 * credits:     Niklas Hallqvist;       OpenBSD driver for the ICP Controllers.
38 *              Mike Smith;             Some driver source code.
39 *              FreeBSD.ORG;            Great O/S to work on and for.
40 *
41 * TODO:
42 */
43
44#ident "$Id: iir.c 1.2 2001/06/21 20:28:32 achim Exp $"
45
46#define _IIR_C_
47
48/* #include "opt_iir.h" */
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/endian.h>
52#include <sys/eventhandler.h>
53#include <sys/malloc.h>
54#include <sys/kernel.h>
55#include <sys/bus.h>
56
57#include <machine/bus_memio.h>
58#include <machine/bus_pio.h>
59#include <machine/bus.h>
60#include <machine/clock.h>
61#include <machine/stdarg.h>
62
63#include <cam/cam.h>
64#include <cam/cam_ccb.h>
65#include <cam/cam_sim.h>
66#include <cam/cam_xpt_sim.h>
67#include <cam/cam_debug.h>
68#include <cam/scsi/scsi_all.h>
69#include <cam/scsi/scsi_message.h>
70
71#include <vm/vm.h>
72#include <vm/pmap.h>
73
74#include <dev/iir/iir.h>
75
76struct gdt_softc *gdt_wait_gdt;
77int     gdt_wait_index;
78
79#ifdef GDT_DEBUG
80int     gdt_debug = GDT_DEBUG;
81#ifdef __SERIAL__
82#define MAX_SERBUF 160
83static void ser_init(void);
84static void ser_puts(char *str);
85static void ser_putc(int c);
86static char strbuf[MAX_SERBUF+1];
87#ifdef __COM2__
88#define COM_BASE 0x2f8
89#else
90#define COM_BASE 0x3f8
91#endif
92static void ser_init()
93{
94    unsigned port=COM_BASE;
95
96    outb(port+3, 0x80);
97    outb(port+1, 0);
98    /* 19200 Baud, if 9600: outb(12,port) */
99    outb(port, 6);
100    outb(port+3, 3);
101    outb(port+1, 0);
102}
103
104static void ser_puts(char *str)
105{
106    char *ptr;
107
108    ser_init();
109    for (ptr=str;*ptr;++ptr)
110        ser_putc((int)(*ptr));
111}
112
113static void ser_putc(int c)
114{
115    unsigned port=COM_BASE;
116
117    while ((inb(port+5) & 0x20)==0);
118    outb(port, c);
119    if (c==0x0a)
120    {
121        while ((inb(port+5) & 0x20)==0);
122        outb(port, 0x0d);
123    }
124}
125
126int ser_printf(const char *fmt, ...)
127{
128    va_list args;
129    int i;
130
131    va_start(args,fmt);
132    i = vsprintf(strbuf,fmt,args);
133    ser_puts(strbuf);
134    va_end(args);
135    return i;
136}
137#endif
138#endif
139
140/* The linked list of softc structures */
141struct gdt_softc_list gdt_softcs = TAILQ_HEAD_INITIALIZER(gdt_softcs);
142/* controller cnt. */
143int gdt_cnt = 0;
144/* event buffer */
145static gdt_evt_str ebuffer[GDT_MAX_EVENTS];
146static int elastidx, eoldidx;
147/* statistics */
148gdt_statist_t gdt_stat;
149
150/* Definitions for our use of the SIM private CCB area */
151#define ccb_sim_ptr     spriv_ptr0
152#define ccb_priority    spriv_field1
153
154static void     iir_action(struct cam_sim *sim, union ccb *ccb);
155static void     iir_poll(struct cam_sim *sim);
156static void     iir_shutdown(void *arg, int howto);
157static void     iir_timeout(void *arg);
158static void     iir_watchdog(void *arg);
159
160static void     gdt_eval_mapping(u_int32_t size, int *cyls, int *heads,
161                                 int *secs);
162static int      gdt_internal_cmd(struct gdt_softc *gdt, struct gdt_ccb *gccb,
163                                 u_int8_t service, u_int16_t opcode,
164                                 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3);
165static int      gdt_wait(struct gdt_softc *gdt, struct gdt_ccb *ccb,
166                         int timeout);
167
168static struct gdt_ccb *gdt_get_ccb(struct gdt_softc *gdt);
169static u_int32_t gdt_ccb_vtop(struct gdt_softc *gdt,
170                              struct gdt_ccb *gccb);
171
172static int      gdt_sync_event(struct gdt_softc *gdt, int service,
173                               u_int8_t index, struct gdt_ccb *gccb);
174static int      gdt_async_event(struct gdt_softc *gdt, int service);
175static struct gdt_ccb *gdt_raw_cmd(struct gdt_softc *gdt,
176                                   union ccb *ccb, int *lock);
177static struct gdt_ccb *gdt_cache_cmd(struct gdt_softc *gdt,
178                                     union ccb *ccb, int *lock);
179static struct gdt_ccb *gdt_ioctl_cmd(struct gdt_softc *gdt,
180                                     gdt_ucmd_t *ucmd, int *lock);
181static void     gdt_internal_cache_cmd(struct gdt_softc *gdt,union ccb *ccb);
182
183static void     gdtmapmem(void *arg, bus_dma_segment_t *dm_segs,
184                          int nseg, int error);
185static void     gdtexecuteccb(void *arg, bus_dma_segment_t *dm_segs,
186                              int nseg, int error);
187
188int
189iir_init(struct gdt_softc *gdt)
190{
191    u_int16_t cdev_cnt;
192    int i, id, drv_cyls, drv_hds, drv_secs;
193    struct gdt_ccb *gccb;
194
195    GDT_DPRINTF(GDT_D_DEBUG, ("iir_init()\n"));
196
197    gdt->sc_state = GDT_POLLING;
198    gdt_clear_events();
199    bzero(&gdt_stat, sizeof(gdt_statist_t));
200
201    SLIST_INIT(&gdt->sc_free_gccb);
202    SLIST_INIT(&gdt->sc_pending_gccb);
203    TAILQ_INIT(&gdt->sc_ccb_queue);
204    TAILQ_INIT(&gdt->sc_ucmd_queue);
205    TAILQ_INSERT_TAIL(&gdt_softcs, gdt, links);
206
207    /* DMA tag for mapping buffers into device visible space. */
208    if (bus_dma_tag_create(gdt->sc_parent_dmat, /*alignment*/1, /*boundary*/0,
209                           /*lowaddr*/BUS_SPACE_MAXADDR,
210                           /*highaddr*/BUS_SPACE_MAXADDR,
211                           /*filter*/NULL, /*filterarg*/NULL,
212                           /*maxsize*/MAXBSIZE, /*nsegments*/GDT_MAXSG,
213                           /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
214                           /*flags*/BUS_DMA_ALLOCNOW,
215                           &gdt->sc_buffer_dmat) != 0) {
216        printf("iir%d: bus_dma_tag_create(...,gdt->sc_buffer_dmat) failed\n",
217               gdt->sc_hanum);
218        return (1);
219    }
220    gdt->sc_init_level++;
221
222    /* DMA tag for our ccb structures */
223    if (bus_dma_tag_create(gdt->sc_parent_dmat, /*alignment*/1, /*boundary*/0,
224                           /*lowaddr*/BUS_SPACE_MAXADDR,
225                           /*highaddr*/BUS_SPACE_MAXADDR,
226                           /*filter*/NULL, /*filterarg*/NULL,
227                           GDT_MAXCMDS * sizeof(struct gdt_ccb),
228                           /*nsegments*/1,
229                           /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
230                           /*flags*/0, &gdt->sc_gccb_dmat) != 0) {
231        printf("iir%d: bus_dma_tag_create(...,gdt->sc_gccb_dmat) failed\n",
232               gdt->sc_hanum);
233        return (1);
234    }
235    gdt->sc_init_level++;
236
237    /* Allocation for our ccbs */
238    if (bus_dmamem_alloc(gdt->sc_gccb_dmat, (void **)&gdt->sc_gccbs,
239                         BUS_DMA_NOWAIT, &gdt->sc_gccb_dmamap) != 0) {
240        printf("iir%d: bus_dmamem_alloc(...,&gdt->sc_gccbs,...) failed\n",
241               gdt->sc_hanum);
242        return (1);
243    }
244    gdt->sc_init_level++;
245
246    /* And permanently map them */
247    bus_dmamap_load(gdt->sc_gccb_dmat, gdt->sc_gccb_dmamap,
248                    gdt->sc_gccbs, GDT_MAXCMDS * sizeof(struct gdt_ccb),
249                    gdtmapmem, &gdt->sc_gccb_busbase, /*flags*/0);
250    gdt->sc_init_level++;
251
252    /* Clear them out. */
253    bzero(gdt->sc_gccbs, GDT_MAXCMDS * sizeof(struct gdt_ccb));
254
255    /* Initialize the ccbs */
256    for (i = GDT_MAXCMDS-1; i >= 0; i--) {
257        gdt->sc_gccbs[i].gc_cmd_index = i + 2;
258        gdt->sc_gccbs[i].gc_flags = GDT_GCF_UNUSED;
259        gdt->sc_gccbs[i].gc_map_flag = FALSE;
260        if (bus_dmamap_create(gdt->sc_buffer_dmat, /*flags*/0,
261                              &gdt->sc_gccbs[i].gc_dmamap) != 0)
262            return(1);
263        gdt->sc_gccbs[i].gc_map_flag = TRUE;
264        SLIST_INSERT_HEAD(&gdt->sc_free_gccb, &gdt->sc_gccbs[i], sle);
265    }
266    gdt->sc_init_level++;
267
268    /* create the control device */
269    gdt->sc_dev = gdt_make_dev(gdt->sc_hanum);
270
271    /* allocate ccb for gdt_internal_cmd() */
272    gccb = gdt_get_ccb(gdt);
273    if (gccb == NULL) {
274        printf("iir%d: No free command index found\n",
275               gdt->sc_hanum);
276        return (1);
277    }
278
279    if (!gdt_internal_cmd(gdt, gccb, GDT_SCREENSERVICE, GDT_INIT,
280                          0, 0, 0)) {
281        printf("iir%d: Screen service initialization error %d\n",
282               gdt->sc_hanum, gdt->sc_status);
283        gdt_free_ccb(gdt, gccb);
284        return (1);
285    }
286
287    if (!gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_INIT,
288                          GDT_LINUX_OS, 0, 0)) {
289        printf("iir%d: Cache service initialization error %d\n",
290               gdt->sc_hanum, gdt->sc_status);
291        gdt_free_ccb(gdt, gccb);
292        return (1);
293    }
294    gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_UNFREEZE_IO,
295                     0, 0, 0);
296
297    if (!gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_MOUNT,
298                          0xffff, 1, 0)) {
299        printf("iir%d: Cache service mount error %d\n",
300               gdt->sc_hanum, gdt->sc_status);
301        gdt_free_ccb(gdt, gccb);
302        return (1);
303    }
304
305    if (!gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_INIT,
306                          GDT_LINUX_OS, 0, 0)) {
307        printf("iir%d: Cache service post-mount initialization error %d\n",
308               gdt->sc_hanum, gdt->sc_status);
309        gdt_free_ccb(gdt, gccb);
310        return (1);
311    }
312    cdev_cnt = (u_int16_t)gdt->sc_info;
313    gdt->sc_fw_vers = gdt->sc_service;
314
315    /* Detect number of buses */
316    gdt_enc32(gccb->gc_scratch + GDT_IOC_VERSION, GDT_IOC_NEWEST);
317    gccb->gc_scratch[GDT_IOC_LIST_ENTRIES] = GDT_MAXBUS;
318    gccb->gc_scratch[GDT_IOC_FIRST_CHAN] = 0;
319    gccb->gc_scratch[GDT_IOC_LAST_CHAN] = GDT_MAXBUS - 1;
320    gdt_enc32(gccb->gc_scratch + GDT_IOC_LIST_OFFSET, GDT_IOC_HDR_SZ);
321    if (gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_IOCTL,
322                         GDT_IOCHAN_RAW_DESC, GDT_INVALID_CHANNEL,
323                         GDT_IOC_HDR_SZ + GDT_MAXBUS * GDT_RAWIOC_SZ)) {
324        gdt->sc_bus_cnt = gccb->gc_scratch[GDT_IOC_CHAN_COUNT];
325        for (i = 0; i < gdt->sc_bus_cnt; i++) {
326            id = gccb->gc_scratch[GDT_IOC_HDR_SZ +
327                                 i * GDT_RAWIOC_SZ + GDT_RAWIOC_PROC_ID];
328            gdt->sc_bus_id[i] = id < GDT_MAXID_FC ? id : 0xff;
329        }
330    } else {
331        /* New method failed, use fallback. */
332        for (i = 0; i < GDT_MAXBUS; i++) {
333            gdt_enc32(gccb->gc_scratch + GDT_GETCH_CHANNEL_NO, i);
334            if (!gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_IOCTL,
335                                  GDT_SCSI_CHAN_CNT | GDT_L_CTRL_PATTERN,
336                                  GDT_IO_CHANNEL | GDT_INVALID_CHANNEL,
337                                  GDT_GETCH_SZ)) {
338                if (i == 0) {
339                    printf("iir%d: Cannot get channel count, "
340                           "error %d\n", gdt->sc_hanum, gdt->sc_status);
341                    gdt_free_ccb(gdt, gccb);
342                    return (1);
343                }
344                break;
345            }
346            gdt->sc_bus_id[i] =
347                (gccb->gc_scratch[GDT_GETCH_SIOP_ID] < GDT_MAXID_FC) ?
348                gccb->gc_scratch[GDT_GETCH_SIOP_ID] : 0xff;
349        }
350        gdt->sc_bus_cnt = i;
351    }
352    /* add one "virtual" channel for the host drives */
353    gdt->sc_virt_bus = gdt->sc_bus_cnt;
354    gdt->sc_bus_cnt++;
355
356    if (!gdt_internal_cmd(gdt, gccb, GDT_SCSIRAWSERVICE, GDT_INIT,
357                          0, 0, 0)) {
358            printf("iir%d: Raw service initialization error %d\n",
359                   gdt->sc_hanum, gdt->sc_status);
360            gdt_free_ccb(gdt, gccb);
361            return (1);
362    }
363
364    /* Set/get features raw service (scatter/gather) */
365    gdt->sc_raw_feat = 0;
366    if (gdt_internal_cmd(gdt, gccb, GDT_SCSIRAWSERVICE, GDT_SET_FEAT,
367                         GDT_SCATTER_GATHER, 0, 0)) {
368        if (gdt_internal_cmd(gdt, gccb, GDT_SCSIRAWSERVICE, GDT_GET_FEAT,
369                             0, 0, 0)) {
370            gdt->sc_raw_feat = gdt->sc_info;
371            if (!(gdt->sc_info & GDT_SCATTER_GATHER)) {
372                panic("iir%d: Scatter/Gather Raw Service "
373                      "required but not supported!\n", gdt->sc_hanum);
374                gdt_free_ccb(gdt, gccb);
375                return (1);
376            }
377        }
378    }
379
380    /* Set/get features cache service (scatter/gather) */
381    gdt->sc_cache_feat = 0;
382    if (gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_SET_FEAT,
383                         0, GDT_SCATTER_GATHER, 0)) {
384        if (gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_GET_FEAT,
385                             0, 0, 0)) {
386            gdt->sc_cache_feat = gdt->sc_info;
387            if (!(gdt->sc_info & GDT_SCATTER_GATHER)) {
388                panic("iir%d: Scatter/Gather Cache Service "
389                  "required but not supported!\n", gdt->sc_hanum);
390                gdt_free_ccb(gdt, gccb);
391                return (1);
392            }
393        }
394    }
395
396    /* Scan for cache devices */
397    for (i = 0; i < cdev_cnt && i < GDT_MAX_HDRIVES; i++) {
398        if (gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE, GDT_INFO,
399                             i, 0, 0)) {
400            gdt->sc_hdr[i].hd_present = 1;
401            gdt->sc_hdr[i].hd_size = gdt->sc_info;
402
403            /*
404             * Evaluate mapping (sectors per head, heads per cyl)
405             */
406            gdt->sc_hdr[i].hd_size &= ~GDT_SECS32;
407            if (gdt->sc_info2 == 0)
408                gdt_eval_mapping(gdt->sc_hdr[i].hd_size,
409                                 &drv_cyls, &drv_hds, &drv_secs);
410            else {
411                drv_hds = gdt->sc_info2 & 0xff;
412                drv_secs = (gdt->sc_info2 >> 8) & 0xff;
413                drv_cyls = gdt->sc_hdr[i].hd_size / drv_hds /
414                    drv_secs;
415            }
416            gdt->sc_hdr[i].hd_heads = drv_hds;
417            gdt->sc_hdr[i].hd_secs = drv_secs;
418            /* Round the size */
419            gdt->sc_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs;
420
421            if (gdt_internal_cmd(gdt, gccb, GDT_CACHESERVICE,
422                                 GDT_DEVTYPE, i, 0, 0))
423                gdt->sc_hdr[i].hd_devtype = gdt->sc_info;
424        }
425    }
426
427    GDT_DPRINTF(GDT_D_INIT, ("dpmem %x %d-bus %d cache device%s\n",
428                             gdt->sc_dpmembase,
429                             gdt->sc_bus_cnt, cdev_cnt,
430                             cdev_cnt == 1 ? "" : "s"));
431    gdt_free_ccb(gdt, gccb);
432
433    gdt_cnt++;
434    return (0);
435}
436
437void
438iir_free(struct gdt_softc *gdt)
439{
440    int i;
441
442    GDT_DPRINTF(GDT_D_INIT, ("iir_free()\n"));
443
444    switch (gdt->sc_init_level) {
445      default:
446        gdt_destroy_dev(gdt->sc_dev);
447      case 5:
448        for (i = GDT_MAXCMDS-1; i >= 0; i--)
449            if (gdt->sc_gccbs[i].gc_map_flag)
450                bus_dmamap_destroy(gdt->sc_buffer_dmat,
451                                   gdt->sc_gccbs[i].gc_dmamap);
452        bus_dmamap_unload(gdt->sc_gccb_dmat, gdt->sc_gccb_dmamap);
453      case 4:
454        bus_dmamem_free(gdt->sc_gccb_dmat, gdt->sc_gccbs, gdt->sc_gccb_dmamap);
455      case 3:
456        bus_dma_tag_destroy(gdt->sc_gccb_dmat);
457      case 2:
458        bus_dma_tag_destroy(gdt->sc_buffer_dmat);
459      case 1:
460        bus_dma_tag_destroy(gdt->sc_parent_dmat);
461      case 0:
462        break;
463    }
464    TAILQ_REMOVE(&gdt_softcs, gdt, links);
465}
466
467void
468iir_attach(struct gdt_softc *gdt)
469{
470    struct cam_devq *devq;
471    int i;
472
473    GDT_DPRINTF(GDT_D_INIT, ("iir_attach()\n"));
474
475    /*
476     * Create the device queue for our SIM.
477     */
478    devq = cam_simq_alloc(GDT_MAXCMDS);
479    if (devq == NULL)
480        return;
481
482    for (i = 0; i < gdt->sc_bus_cnt; i++) {
483        /*
484         * Construct our SIM entry
485         */
486        gdt->sims[i] = cam_sim_alloc(iir_action, iir_poll, "iir",
487                                     gdt, gdt->sc_hanum, /*untagged*/2,
488                                     /*tagged*/GDT_MAXCMDS, devq);
489        if (xpt_bus_register(gdt->sims[i], i) != CAM_SUCCESS) {
490            cam_sim_free(gdt->sims[i], /*free_devq*/i == 0);
491            break;
492        }
493
494        if (xpt_create_path(&gdt->paths[i], /*periph*/NULL,
495                            cam_sim_path(gdt->sims[i]),
496                            CAM_TARGET_WILDCARD,
497                            CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
498            xpt_bus_deregister(cam_sim_path(gdt->sims[i]));
499            cam_sim_free(gdt->sims[i], /*free_devq*/i == 0);
500            break;
501        }
502    }
503    if (i > 0)
504        EVENTHANDLER_REGISTER(shutdown_final, iir_shutdown,
505                              gdt, SHUTDOWN_PRI_DEFAULT);
506    /* iir_watchdog(gdt); */
507    gdt->sc_state = GDT_NORMAL;
508}
509
510static void
511gdt_eval_mapping(u_int32_t size, int *cyls, int *heads, int *secs)
512{
513    *cyls = size / GDT_HEADS / GDT_SECS;
514    if (*cyls < GDT_MAXCYLS) {
515        *heads = GDT_HEADS;
516        *secs = GDT_SECS;
517    } else {
518        /* Too high for 64 * 32 */
519        *cyls = size / GDT_MEDHEADS / GDT_MEDSECS;
520        if (*cyls < GDT_MAXCYLS) {
521            *heads = GDT_MEDHEADS;
522            *secs = GDT_MEDSECS;
523        } else {
524            /* Too high for 127 * 63 */
525            *cyls = size / GDT_BIGHEADS / GDT_BIGSECS;
526            *heads = GDT_BIGHEADS;
527            *secs = GDT_BIGSECS;
528        }
529    }
530}
531
532static int
533gdt_wait(struct gdt_softc *gdt, struct gdt_ccb *gccb,
534         int timeout)
535{
536    int rv = 0;
537
538    GDT_DPRINTF(GDT_D_INIT,
539                ("gdt_wait(%p, %p, %d)\n", gdt, gccb, timeout));
540
541    gdt->sc_state |= GDT_POLL_WAIT;
542    do {
543        iir_intr(gdt);
544        if (gdt == gdt_wait_gdt &&
545            gccb->gc_cmd_index == gdt_wait_index) {
546            rv = 1;
547            break;
548        }
549        DELAY(1);
550    } while (--timeout);
551    gdt->sc_state &= ~GDT_POLL_WAIT;
552
553    while (gdt->sc_test_busy(gdt))
554        DELAY(1);               /* XXX correct? */
555
556    return (rv);
557}
558
559static int
560gdt_internal_cmd(struct gdt_softc *gdt, struct gdt_ccb *gccb,
561                 u_int8_t service, u_int16_t opcode,
562                 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
563{
564    int retries;
565
566    GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cmd(%p, %d, %d, %d, %d, %d)\n",
567                            gdt, service, opcode, arg1, arg2, arg3));
568
569    bzero(gdt->sc_cmd, GDT_CMD_SZ);
570
571    for (retries = GDT_RETRIES; ; ) {
572        gccb->gc_service = service;
573        gccb->gc_flags = GDT_GCF_INTERNAL;
574
575        gdt->sc_set_sema0(gdt);
576        gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
577                  gccb->gc_cmd_index);
578        gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, opcode);
579
580        switch (service) {
581          case GDT_CACHESERVICE:
582            if (opcode == GDT_IOCTL) {
583                gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
584                          GDT_IOCTL_SUBFUNC, arg1);
585                gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
586                          GDT_IOCTL_CHANNEL, arg2);
587                gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION +
588                          GDT_IOCTL_PARAM_SIZE, (u_int16_t)arg3);
589                gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_P_PARAM,
590                          gdt_ccb_vtop(gdt, gccb) +
591                          offsetof(struct gdt_ccb, gc_scratch[0]));
592            } else {
593                gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION +
594                          GDT_CACHE_DEVICENO, (u_int16_t)arg1);
595                gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
596                          GDT_CACHE_BLOCKNO, arg2);
597            }
598            break;
599
600          case GDT_SCSIRAWSERVICE:
601            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
602                      GDT_RAW_DIRECTION, arg1);
603            gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
604                (u_int8_t)arg2;
605            gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
606                (u_int8_t)arg3;
607            gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
608                (u_int8_t)(arg3 >> 8);
609        }
610
611        gdt->sc_cmd_len = GDT_CMD_SZ;
612        gdt->sc_cmd_off = 0;
613        gdt->sc_cmd_cnt = 0;
614        gdt->sc_copy_cmd(gdt, gccb);
615        gdt->sc_release_event(gdt);
616        DELAY(20);
617        if (!gdt_wait(gdt, gccb, GDT_POLL_TIMEOUT))
618            return (0);
619        if (gdt->sc_status != GDT_S_BSY || --retries == 0)
620            break;
621        DELAY(1);
622    }
623    return (gdt->sc_status == GDT_S_OK);
624}
625
626static struct gdt_ccb *
627gdt_get_ccb(struct gdt_softc *gdt)
628{
629    struct gdt_ccb *gccb;
630    int lock;
631
632    GDT_DPRINTF(GDT_D_QUEUE, ("gdt_get_ccb(%p)\n", gdt));
633
634    lock = splcam();
635    gccb = SLIST_FIRST(&gdt->sc_free_gccb);
636    if (gccb != NULL) {
637        SLIST_REMOVE_HEAD(&gdt->sc_free_gccb, sle);
638        SLIST_INSERT_HEAD(&gdt->sc_pending_gccb, gccb, sle);
639        ++gdt_stat.cmd_index_act;
640        if (gdt_stat.cmd_index_act > gdt_stat.cmd_index_max)
641            gdt_stat.cmd_index_max = gdt_stat.cmd_index_act;
642    }
643    splx(lock);
644    return (gccb);
645}
646
647void
648gdt_free_ccb(struct gdt_softc *gdt, struct gdt_ccb *gccb)
649{
650    int lock;
651
652    GDT_DPRINTF(GDT_D_QUEUE, ("gdt_free_ccb(%p, %p)\n", gdt, gccb));
653
654    lock = splcam();
655    gccb->gc_flags = GDT_GCF_UNUSED;
656    SLIST_REMOVE(&gdt->sc_pending_gccb, gccb, gdt_ccb, sle);
657    SLIST_INSERT_HEAD(&gdt->sc_free_gccb, gccb, sle);
658    --gdt_stat.cmd_index_act;
659    splx(lock);
660    if (gdt->sc_state & GDT_SHUTDOWN)
661        wakeup(gccb);
662}
663
664static u_int32_t
665gdt_ccb_vtop(struct gdt_softc *gdt, struct gdt_ccb *gccb)
666{
667    return (gdt->sc_gccb_busbase
668            + (u_int32_t)((caddr_t)gccb - (caddr_t)gdt->sc_gccbs));
669}
670
671void
672gdt_next(struct gdt_softc *gdt)
673{
674    int lock;
675    union ccb *ccb;
676    gdt_ucmd_t *ucmd;
677    struct cam_sim *sim;
678    int bus, target, lun;
679    int next_cmd;
680
681    struct ccb_scsiio *csio;
682    struct ccb_hdr *ccbh;
683    struct gdt_ccb *gccb = NULL;
684    u_int8_t cmd;
685
686    GDT_DPRINTF(GDT_D_QUEUE, ("gdt_next(%p)\n", gdt));
687
688    lock = splcam();
689    if (gdt->sc_test_busy(gdt)) {
690        if (!(gdt->sc_state & GDT_POLLING)) {
691            splx(lock);
692            return;
693        }
694        while (gdt->sc_test_busy(gdt))
695            DELAY(1);
696    }
697
698    gdt->sc_cmd_cnt = gdt->sc_cmd_off = 0;
699    next_cmd = TRUE;
700    for (;;) {
701        /* I/Os in queue? controller ready? */
702        if (!TAILQ_FIRST(&gdt->sc_ucmd_queue) &&
703            !TAILQ_FIRST(&gdt->sc_ccb_queue))
704            break;
705
706        /* 1.: I/Os without ccb (IOCTLs) */
707        ucmd = TAILQ_FIRST(&gdt->sc_ucmd_queue);
708        if (ucmd != NULL) {
709            TAILQ_REMOVE(&gdt->sc_ucmd_queue, ucmd, links);
710            if ((gccb = gdt_ioctl_cmd(gdt, ucmd, &lock)) == NULL) {
711                TAILQ_INSERT_HEAD(&gdt->sc_ucmd_queue, ucmd, links);
712                break;
713            }
714            break;
715            /* wenn mehrere Kdos. zulassen: if (!gdt_polling) continue; */
716        }
717
718        /* 2.: I/Os with ccb */
719        ccb = (union ccb *)TAILQ_FIRST(&gdt->sc_ccb_queue);
720        /* ist dann immer != NULL, da oben getestet */
721        sim = (struct cam_sim *)ccb->ccb_h.ccb_sim_ptr;
722        bus = cam_sim_bus(sim);
723        target = ccb->ccb_h.target_id;
724        lun = ccb->ccb_h.target_lun;
725
726        TAILQ_REMOVE(&gdt->sc_ccb_queue, &ccb->ccb_h, sim_links.tqe);
727        --gdt_stat.req_queue_act;
728        /* ccb->ccb_h.func_code is XPT_SCSI_IO */
729        GDT_DPRINTF(GDT_D_QUEUE, ("XPT_SCSI_IO flags 0x%x)\n",
730                                  ccb->ccb_h.flags));
731        csio = &ccb->csio;
732        ccbh = &ccb->ccb_h;
733        cmd  = csio->cdb_io.cdb_bytes[0];
734        /* Max CDB length is 12 bytes */
735        if (csio->cdb_len > 12) {
736            ccbh->status = CAM_REQ_INVALID;
737            --gdt_stat.io_count_act;
738            xpt_done(ccb);
739        } else if (bus != gdt->sc_virt_bus) {
740            /* raw service command */
741            if ((gccb = gdt_raw_cmd(gdt, ccb, &lock)) == NULL) {
742                TAILQ_INSERT_HEAD(&gdt->sc_ccb_queue, &ccb->ccb_h,
743                                  sim_links.tqe);
744                ++gdt_stat.req_queue_act;
745                if (gdt_stat.req_queue_act > gdt_stat.req_queue_max)
746                    gdt_stat.req_queue_max = gdt_stat.req_queue_act;
747                next_cmd = FALSE;
748            }
749        } else if (target >= GDT_MAX_HDRIVES ||
750                   !gdt->sc_hdr[target].hd_present || lun != 0) {
751            ccbh->status = CAM_SEL_TIMEOUT;
752            --gdt_stat.io_count_act;
753            xpt_done(ccb);
754        } else {
755            /* cache service command */
756            if (cmd == READ_6  || cmd == WRITE_6 ||
757                cmd == READ_10 || cmd == WRITE_10) {
758                if ((gccb = gdt_cache_cmd(gdt, ccb, &lock)) == NULL) {
759                    TAILQ_INSERT_HEAD(&gdt->sc_ccb_queue, &ccb->ccb_h,
760                                      sim_links.tqe);
761                    ++gdt_stat.req_queue_act;
762                    if (gdt_stat.req_queue_act > gdt_stat.req_queue_max)
763                        gdt_stat.req_queue_max = gdt_stat.req_queue_act;
764                    next_cmd = FALSE;
765                }
766            } else {
767                splx(lock);
768                gdt_internal_cache_cmd(gdt, ccb);
769                lock = splcam();
770            }
771        }
772        if ((gdt->sc_state & GDT_POLLING) || !next_cmd)
773            break;
774    }
775    if (gdt->sc_cmd_cnt > 0)
776        gdt->sc_release_event(gdt);
777
778    splx(lock);
779
780    if ((gdt->sc_state & GDT_POLLING) && gdt->sc_cmd_cnt > 0) {
781        gdt_wait(gdt, gccb, GDT_POLL_TIMEOUT);
782    }
783}
784
785static struct gdt_ccb *
786gdt_raw_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
787{
788    struct gdt_ccb *gccb;
789    struct cam_sim *sim;
790
791    GDT_DPRINTF(GDT_D_CMD, ("gdt_raw_cmd(%p, %p)\n", gdt, ccb));
792
793    if (roundup(GDT_CMD_UNION + GDT_RAW_SZ, sizeof(u_int32_t)) +
794        gdt->sc_cmd_off + GDT_DPMEM_COMMAND_OFFSET >
795        gdt->sc_ic_all_size) {
796        GDT_DPRINTF(GDT_D_INVALID, ("iir%d: gdt_raw_cmd(): DPMEM overflow\n",
797                                    gdt->sc_hanum));
798        return (NULL);
799    }
800
801    bzero(gdt->sc_cmd, GDT_CMD_SZ);
802
803    gccb = gdt_get_ccb(gdt);
804    if (gccb == NULL) {
805        GDT_DPRINTF(GDT_D_INVALID, ("iir%d: No free command index found\n",
806                                    gdt->sc_hanum));
807        return (gccb);
808    }
809    sim = (struct cam_sim *)ccb->ccb_h.ccb_sim_ptr;
810    gccb->gc_ccb = ccb;
811    gccb->gc_service = GDT_SCSIRAWSERVICE;
812    gccb->gc_flags = GDT_GCF_SCSI;
813
814    if (gdt->sc_cmd_cnt == 0)
815        gdt->sc_set_sema0(gdt);
816    splx(*lock);
817    gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
818              gccb->gc_cmd_index);
819    gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_WRITE);
820
821    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_DIRECTION,
822              (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN ?
823              GDT_DATA_IN : GDT_DATA_OUT);
824    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDLEN,
825              ccb->csio.dxfer_len);
826    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CLEN,
827              ccb->csio.cdb_len);
828    bcopy(ccb->csio.cdb_io.cdb_bytes, gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CMD,
829          ccb->csio.cdb_len);
830    gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
831        ccb->ccb_h.target_id;
832    gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
833        ccb->ccb_h.target_lun;
834    gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
835        cam_sim_bus(sim);
836    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_LEN,
837              sizeof(struct scsi_sense_data));
838    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA,
839              gdt_ccb_vtop(gdt, gccb) +
840              offsetof(struct gdt_ccb, gc_scratch[0]));
841
842    /*
843     * If we have any data to send with this command,
844     * map it into bus space.
845     */
846    /* Only use S/G if there is a transfer */
847    if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
848        if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
849            if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) {
850                int s;
851                int error;
852
853                /* vorher unlock von splcam() ??? */
854                s = splsoftvm();
855                error =
856                    bus_dmamap_load(gdt->sc_buffer_dmat,
857                                    gccb->gc_dmamap,
858                                    ccb->csio.data_ptr,
859                                    ccb->csio.dxfer_len,
860                                    gdtexecuteccb,
861                                    gccb, /*flags*/0);
862                if (error == EINPROGRESS) {
863                    xpt_freeze_simq(sim, 1);
864                    gccb->gc_state |= CAM_RELEASE_SIMQ;
865                }
866                splx(s);
867            } else {
868                struct bus_dma_segment seg;
869
870                /* Pointer to physical buffer */
871                seg.ds_addr =
872                    (bus_addr_t)ccb->csio.data_ptr;
873                seg.ds_len = ccb->csio.dxfer_len;
874                gdtexecuteccb(gccb, &seg, 1, 0);
875            }
876        } else {
877            struct bus_dma_segment *segs;
878
879            if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
880                panic("iir%d: iir_action - Physical "
881                      "segment pointers unsupported", gdt->sc_hanum);
882
883            if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS)==0)
884                panic("iir%d: iir_action - Virtual "
885                      "segment addresses unsupported", gdt->sc_hanum);
886
887            /* Just use the segments provided */
888            segs = (struct bus_dma_segment *)ccb->csio.data_ptr;
889            gdtexecuteccb(gccb, segs, ccb->csio.sglist_cnt, 0);
890        }
891    } else {
892        gdtexecuteccb(gccb, NULL, 0, 0);
893    }
894
895    *lock = splcam();
896    return (gccb);
897}
898
899static struct gdt_ccb *
900gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
901{
902    struct gdt_ccb *gccb;
903    struct cam_sim *sim;
904    u_int8_t *cmdp;
905    u_int16_t opcode;
906    u_int32_t blockno, blockcnt;
907
908    GDT_DPRINTF(GDT_D_CMD, ("gdt_cache_cmd(%p, %p)\n", gdt, ccb));
909
910    if (roundup(GDT_CMD_UNION + GDT_CACHE_SZ, sizeof(u_int32_t)) +
911        gdt->sc_cmd_off + GDT_DPMEM_COMMAND_OFFSET >
912        gdt->sc_ic_all_size) {
913        GDT_DPRINTF(GDT_D_INVALID, ("iir%d: gdt_cache_cmd(): DPMEM overflow\n",
914                                    gdt->sc_hanum));
915        return (NULL);
916    }
917
918    bzero(gdt->sc_cmd, GDT_CMD_SZ);
919
920    gccb = gdt_get_ccb(gdt);
921    if (gccb == NULL) {
922        GDT_DPRINTF(GDT_D_DEBUG, ("iir%d: No free command index found\n",
923                                  gdt->sc_hanum));
924        return (gccb);
925    }
926    sim = (struct cam_sim *)ccb->ccb_h.ccb_sim_ptr;
927    gccb->gc_ccb = ccb;
928    gccb->gc_service = GDT_CACHESERVICE;
929    gccb->gc_flags = GDT_GCF_SCSI;
930
931    if (gdt->sc_cmd_cnt == 0)
932        gdt->sc_set_sema0(gdt);
933    splx(*lock);
934    gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
935              gccb->gc_cmd_index);
936    cmdp = ccb->csio.cdb_io.cdb_bytes;
937    opcode = (*cmdp == WRITE_6 || *cmdp == WRITE_10) ? GDT_WRITE : GDT_READ;
938    if ((gdt->sc_state & GDT_SHUTDOWN) && opcode == GDT_WRITE)
939        opcode = GDT_WRITE_THR;
940    gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, opcode);
941
942    gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
943              ccb->ccb_h.target_id);
944    if (ccb->csio.cdb_len == 6) {
945        struct scsi_rw_6 *rw = (struct scsi_rw_6 *)cmdp;
946        blockno = scsi_3btoul(rw->addr) & ((SRW_TOPADDR<<16) | 0xffff);
947        blockcnt = rw->length ? rw->length : 0x100;
948    } else {
949        struct scsi_rw_10 *rw = (struct scsi_rw_10 *)cmdp;
950        blockno = scsi_4btoul(rw->addr);
951        blockcnt = scsi_2btoul(rw->length);
952    }
953    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
954              blockno);
955    gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
956              blockcnt);
957
958    /*
959     * If we have any data to send with this command,
960     * map it into bus space.
961     */
962    /* Only use S/G if there is a transfer */
963    if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
964        if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) {
965            int s;
966            int error;
967
968            /* vorher unlock von splcam() ??? */
969            s = splsoftvm();
970            error =
971                bus_dmamap_load(gdt->sc_buffer_dmat,
972                                gccb->gc_dmamap,
973                                ccb->csio.data_ptr,
974                                ccb->csio.dxfer_len,
975                                gdtexecuteccb,
976                                gccb, /*flags*/0);
977            if (error == EINPROGRESS) {
978                xpt_freeze_simq(sim, 1);
979                gccb->gc_state |= CAM_RELEASE_SIMQ;
980            }
981            splx(s);
982        } else {
983            struct bus_dma_segment seg;
984
985            /* Pointer to physical buffer */
986            seg.ds_addr =
987                (bus_addr_t)ccb->csio.data_ptr;
988            seg.ds_len = ccb->csio.dxfer_len;
989            gdtexecuteccb(gccb, &seg, 1, 0);
990        }
991    } else {
992        struct bus_dma_segment *segs;
993
994        if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
995            panic("iir%d: iir_action - Physical "
996                  "segment pointers unsupported", gdt->sc_hanum);
997
998        if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS)==0)
999            panic("iir%d: iir_action - Virtual "
1000                  "segment addresses unsupported", gdt->sc_hanum);
1001
1002        /* Just use the segments provided */
1003        segs = (struct bus_dma_segment *)ccb->csio.data_ptr;
1004        gdtexecuteccb(gccb, segs, ccb->csio.sglist_cnt, 0);
1005    }
1006
1007    *lock = splcam();
1008    return (gccb);
1009}
1010
1011static struct gdt_ccb *
1012gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
1013{
1014    struct gdt_ccb *gccb;
1015    u_int32_t cnt;
1016
1017    GDT_DPRINTF(GDT_D_DEBUG, ("gdt_ioctl_cmd(%p, %p)\n", gdt, ucmd));
1018
1019    bzero(gdt->sc_cmd, GDT_CMD_SZ);
1020
1021    gccb = gdt_get_ccb(gdt);
1022    if (gccb == NULL) {
1023        GDT_DPRINTF(GDT_D_DEBUG, ("iir%d: No free command index found\n",
1024                                  gdt->sc_hanum));
1025        return (gccb);
1026    }
1027    gccb->gc_ucmd = ucmd;
1028    gccb->gc_service = ucmd->service;
1029    gccb->gc_flags = GDT_GCF_IOCTL;
1030
1031    /* check DPMEM space, copy data buffer from user space */
1032    if (ucmd->service == GDT_CACHESERVICE) {
1033        if (ucmd->OpCode == GDT_IOCTL) {
1034            gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_IOCTL_SZ,
1035                                      sizeof(u_int32_t));
1036            cnt = ucmd->u.ioctl.param_size;
1037            if (cnt > GDT_SCRATCH_SZ) {
1038                printf("iir%d: Scratch buffer too small (%d/%d)\n",
1039                       gdt->sc_hanum, GDT_SCRATCH_SZ, cnt);
1040                gdt_free_ccb(gdt, gccb);
1041                return (NULL);
1042            }
1043        } else {
1044            gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST +
1045                                      GDT_SG_SZ, sizeof(u_int32_t));
1046            cnt = ucmd->u.cache.BlockCnt * GDT_SECTOR_SIZE;
1047            if (cnt > GDT_SCRATCH_SZ) {
1048                printf("iir%d: Scratch buffer too small (%d/%d)\n",
1049                       gdt->sc_hanum, GDT_SCRATCH_SZ, cnt);
1050                gdt_free_ccb(gdt, gccb);
1051                return (NULL);
1052            }
1053        }
1054    } else {
1055        gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_RAW_SG_LST +
1056                                  GDT_SG_SZ, sizeof(u_int32_t));
1057        cnt = ucmd->u.raw.sdlen;
1058        if (cnt + ucmd->u.raw.sense_len > GDT_SCRATCH_SZ) {
1059            printf("iir%d: Scratch buffer too small (%d/%d)\n",
1060                   gdt->sc_hanum, GDT_SCRATCH_SZ, cnt + ucmd->u.raw.sense_len);
1061            gdt_free_ccb(gdt, gccb);
1062            return (NULL);
1063        }
1064    }
1065    if (cnt != 0)
1066        bcopy(ucmd->data, gccb->gc_scratch, cnt);
1067
1068    if (gdt->sc_cmd_off + gdt->sc_cmd_len + GDT_DPMEM_COMMAND_OFFSET >
1069        gdt->sc_ic_all_size) {
1070        GDT_DPRINTF(GDT_D_INVALID, ("iir%d: gdt_ioctl_cmd(): DPMEM overflow\n",
1071                                    gdt->sc_hanum));
1072        gdt_free_ccb(gdt, gccb);
1073        return (NULL);
1074    }
1075
1076    if (gdt->sc_cmd_cnt == 0)
1077        gdt->sc_set_sema0(gdt);
1078    splx(*lock);
1079
1080    /* fill cmd structure */
1081    gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
1082              gccb->gc_cmd_index);
1083    gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE,
1084              ucmd->OpCode);
1085
1086    if (ucmd->service == GDT_CACHESERVICE) {
1087        if (ucmd->OpCode == GDT_IOCTL) {
1088            /* IOCTL */
1089            gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_PARAM_SIZE,
1090                      ucmd->u.ioctl.param_size);
1091            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_SUBFUNC,
1092                      ucmd->u.ioctl.subfunc);
1093            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_CHANNEL,
1094                      ucmd->u.ioctl.channel);
1095            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_P_PARAM,
1096                      gdt_ccb_vtop(gdt, gccb) +
1097                      offsetof(struct gdt_ccb, gc_scratch[0]));
1098        } else {
1099            /* cache service command */
1100            gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
1101                      ucmd->u.cache.DeviceNo);
1102            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
1103                      ucmd->u.cache.BlockNo);
1104            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
1105                      ucmd->u.cache.BlockCnt);
1106            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
1107                      0xffffffffUL);
1108            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ,
1109                      1);
1110            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
1111                      GDT_SG_PTR, gdt_ccb_vtop(gdt, gccb) +
1112                      offsetof(struct gdt_ccb, gc_scratch[0]));
1113            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
1114                      GDT_SG_LEN, ucmd->u.cache.BlockCnt * GDT_SECTOR_SIZE);
1115        }
1116    } else {
1117        /* raw service command */
1118        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_DIRECTION,
1119                  ucmd->u.raw.direction);
1120        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDATA,
1121                  0xffffffffUL);
1122        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDLEN,
1123                  ucmd->u.raw.sdlen);
1124        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CLEN,
1125                  ucmd->u.raw.clen);
1126        bcopy(ucmd->u.raw.cmd, gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CMD,
1127              12);
1128        gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
1129            ucmd->u.raw.target;
1130        gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
1131            ucmd->u.raw.lun;
1132        gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
1133            ucmd->u.raw.bus;
1134        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_LEN,
1135                  ucmd->u.raw.sense_len);
1136        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA,
1137                  gdt_ccb_vtop(gdt, gccb) +
1138                  offsetof(struct gdt_ccb, gc_scratch[ucmd->u.raw.sdlen]));
1139        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_RANZ,
1140                  1);
1141        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
1142                  GDT_SG_PTR, gdt_ccb_vtop(gdt, gccb) +
1143                  offsetof(struct gdt_ccb, gc_scratch[0]));
1144        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
1145                  GDT_SG_LEN, ucmd->u.raw.sdlen);
1146    }
1147
1148    *lock = splcam();
1149    gdt_stat.sg_count_act = 1;
1150    gdt->sc_copy_cmd(gdt, gccb);
1151    return (gccb);
1152}
1153
1154static void
1155gdt_internal_cache_cmd(struct gdt_softc *gdt,union ccb *ccb)
1156{
1157    int t;
1158
1159    t = ccb->ccb_h.target_id;
1160    GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cache_cmd(%p, %p, 0x%x, %d)\n",
1161        gdt, ccb, ccb->csio.cdb_io.cdb_bytes[0], t));
1162
1163    switch (ccb->csio.cdb_io.cdb_bytes[0]) {
1164      case TEST_UNIT_READY:
1165      case START_STOP:
1166        break;
1167      case REQUEST_SENSE:
1168        GDT_DPRINTF(GDT_D_MISC, ("REQUEST_SENSE\n"));
1169        break;
1170      case INQUIRY:
1171        {
1172            struct scsi_inquiry_data *inq;
1173
1174            inq = (struct scsi_inquiry_data *)ccb->csio.data_ptr;
1175            bzero(inq, sizeof(struct scsi_inquiry_data));
1176            inq->device = (gdt->sc_hdr[t].hd_devtype & 4) ?
1177                T_CDROM : T_DIRECT;
1178            inq->dev_qual2 = (gdt->sc_hdr[t].hd_devtype & 1) ? 0x80 : 0;
1179            inq->version = SCSI_REV_2;
1180            inq->response_format = 2;
1181            inq->additional_length = 32;
1182            inq->flags = SID_CmdQue | SID_Sync;
1183            strcpy(inq->vendor, "IIR     ");
1184            sprintf(inq->product, "Host Drive   #%02d", t);
1185            strcpy(inq->revision, "   ");
1186            break;
1187        }
1188      case MODE_SENSE_6:
1189        {
1190            struct mpd_data {
1191                struct scsi_mode_hdr_6 hd;
1192                struct scsi_mode_block_descr bd;
1193                struct scsi_control_page cp;
1194            } *mpd;
1195            u_int8_t page;
1196
1197            mpd = (struct mpd_data *)ccb->csio.data_ptr;
1198            bzero(mpd, sizeof(struct mpd_data));
1199            mpd->hd.datalen = sizeof(struct scsi_mode_hdr_6) +
1200                sizeof(struct scsi_mode_block_descr);
1201            mpd->hd.dev_specific = (gdt->sc_hdr[t].hd_devtype & 2) ? 0x80 : 0;
1202            mpd->hd.block_descr_len = sizeof(struct scsi_mode_block_descr);
1203            mpd->bd.block_len[0] = (GDT_SECTOR_SIZE & 0x00ff0000) >> 16;
1204            mpd->bd.block_len[1] = (GDT_SECTOR_SIZE & 0x0000ff00) >> 8;
1205            mpd->bd.block_len[2] = (GDT_SECTOR_SIZE & 0x000000ff);
1206            page=((struct scsi_mode_sense_6 *)ccb->csio.cdb_io.cdb_bytes)->page;
1207            switch (page) {
1208              default:
1209                GDT_DPRINTF(GDT_D_MISC, ("MODE_SENSE_6: page 0x%x\n", page));
1210                break;
1211            }
1212            break;
1213        }
1214      case READ_CAPACITY:
1215        {
1216            struct scsi_read_capacity_data *rcd;
1217
1218            rcd = (struct scsi_read_capacity_data *)ccb->csio.data_ptr;
1219            bzero(rcd, sizeof(struct scsi_read_capacity_data));
1220            scsi_ulto4b(gdt->sc_hdr[t].hd_size - 1, rcd->addr);
1221            scsi_ulto4b(GDT_SECTOR_SIZE, rcd->length);
1222            break;
1223        }
1224      default:
1225        GDT_DPRINTF(GDT_D_MISC, ("gdt_internal_cache_cmd(%d) unknown\n",
1226                                    ccb->csio.cdb_io.cdb_bytes[0]));
1227        break;
1228    }
1229    ccb->ccb_h.status = CAM_REQ_CMP;
1230    --gdt_stat.io_count_act;
1231    xpt_done(ccb);
1232}
1233
1234static void
1235gdtmapmem(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1236{
1237    bus_addr_t *busaddrp;
1238
1239    busaddrp = (bus_addr_t *)arg;
1240    *busaddrp = dm_segs->ds_addr;
1241}
1242
1243static void
1244gdtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1245{
1246    struct gdt_ccb *gccb;
1247    union ccb *ccb;
1248    struct gdt_softc *gdt;
1249    int i, lock;
1250
1251    lock = splcam();
1252
1253    gccb = (struct gdt_ccb *)arg;
1254    ccb = gccb->gc_ccb;
1255    gdt = cam_sim_softc((struct cam_sim *)ccb->ccb_h.ccb_sim_ptr);
1256
1257    GDT_DPRINTF(GDT_D_CMD, ("gdtexecuteccb(%p, %p, %p, %d, %d)\n",
1258                            gdt, gccb, dm_segs, nseg, error));
1259    gdt_stat.sg_count_act = nseg;
1260    if (nseg > gdt_stat.sg_count_max)
1261        gdt_stat.sg_count_max = nseg;
1262
1263    /* Copy the segments into our SG list */
1264    if (gccb->gc_service == GDT_CACHESERVICE) {
1265        for (i = 0; i < nseg; ++i) {
1266            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
1267                      i * GDT_SG_SZ + GDT_SG_PTR, dm_segs->ds_addr);
1268            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
1269                      i * GDT_SG_SZ + GDT_SG_LEN, dm_segs->ds_len);
1270            dm_segs++;
1271        }
1272        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ,
1273                  nseg);
1274        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
1275                  0xffffffffUL);
1276
1277        gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST +
1278                                  nseg * GDT_SG_SZ, sizeof(u_int32_t));
1279    } else {
1280        for (i = 0; i < nseg; ++i) {
1281            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
1282                      i * GDT_SG_SZ + GDT_SG_PTR, dm_segs->ds_addr);
1283            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
1284                      i * GDT_SG_SZ + GDT_SG_LEN, dm_segs->ds_len);
1285            dm_segs++;
1286        }
1287        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_RANZ,
1288                  nseg);
1289        gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDATA,
1290                  0xffffffffUL);
1291
1292        gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_RAW_SG_LST +
1293                                  nseg * GDT_SG_SZ, sizeof(u_int32_t));
1294    }
1295
1296    if (nseg != 0) {
1297        int op;
1298
1299        if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1300            op = BUS_DMASYNC_PREREAD;
1301        else
1302            op = BUS_DMASYNC_PREWRITE;
1303        bus_dmamap_sync(gdt->sc_buffer_dmat, gccb->gc_dmamap, op);
1304    }
1305
1306    /* We must NOT abort the command here if CAM_REQ_INPROG is not set,
1307     * because command semaphore is already set!
1308     */
1309
1310    ccb->ccb_h.status |= CAM_SIM_QUEUED;
1311    /* timeout handling */
1312    ccb->ccb_h.timeout_ch =
1313        timeout(iir_timeout, (caddr_t)gccb,
1314                (ccb->ccb_h.timeout * hz) / 1000);
1315
1316    gdt->sc_copy_cmd(gdt, gccb);
1317    splx(lock);
1318}
1319
1320
1321static void
1322iir_action( struct cam_sim *sim, union ccb *ccb )
1323{
1324    struct gdt_softc *gdt;
1325    int lock, bus, target, lun;
1326
1327    gdt = (struct gdt_softc *)cam_sim_softc( sim );
1328    ccb->ccb_h.ccb_sim_ptr = sim;
1329    bus = cam_sim_bus(sim);
1330    target = ccb->ccb_h.target_id;
1331    lun = ccb->ccb_h.target_lun;
1332    GDT_DPRINTF(GDT_D_CMD,
1333                ("iir_action(%p) func 0x%x cmd 0x%x bus %d target %d lun %d\n",
1334                 gdt, ccb->ccb_h.func_code, ccb->csio.cdb_io.cdb_bytes[0],
1335                 bus, target, lun));
1336    ++gdt_stat.io_count_act;
1337    if (gdt_stat.io_count_act > gdt_stat.io_count_max)
1338        gdt_stat.io_count_max = gdt_stat.io_count_act;
1339
1340    switch (ccb->ccb_h.func_code) {
1341      case XPT_SCSI_IO:
1342        lock = splcam();
1343        TAILQ_INSERT_TAIL(&gdt->sc_ccb_queue, &ccb->ccb_h, sim_links.tqe);
1344        ++gdt_stat.req_queue_act;
1345        if (gdt_stat.req_queue_act > gdt_stat.req_queue_max)
1346            gdt_stat.req_queue_max = gdt_stat.req_queue_act;
1347        splx(lock);
1348        gdt_next(gdt);
1349        break;
1350      case XPT_RESET_DEV:   /* Bus Device Reset the specified SCSI device */
1351      case XPT_ABORT:                       /* Abort the specified CCB */
1352        /* XXX Implement */
1353        ccb->ccb_h.status = CAM_REQ_INVALID;
1354        --gdt_stat.io_count_act;
1355        xpt_done(ccb);
1356        break;
1357      case XPT_SET_TRAN_SETTINGS:
1358        ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1359        --gdt_stat.io_count_act;
1360        xpt_done(ccb);
1361        break;
1362      case XPT_GET_TRAN_SETTINGS:
1363        /* Get default/user set transfer settings for the target */
1364          {
1365              struct        ccb_trans_settings *cts;
1366              u_int target_mask;
1367
1368              cts = &ccb->cts;
1369              target_mask = 0x01 << target;
1370              if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
1371                  cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB;
1372                  cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1373                  cts->sync_period = 25; /* 10MHz */
1374                  if (cts->sync_period != 0)
1375                      cts->sync_offset = 15;
1376
1377                  cts->valid = CCB_TRANS_SYNC_RATE_VALID
1378                      | CCB_TRANS_SYNC_OFFSET_VALID
1379                      | CCB_TRANS_BUS_WIDTH_VALID
1380                      | CCB_TRANS_DISC_VALID
1381                      | CCB_TRANS_TQ_VALID;
1382                  ccb->ccb_h.status = CAM_REQ_CMP;
1383              } else {
1384                  ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1385              }
1386              --gdt_stat.io_count_act;
1387              xpt_done(ccb);
1388              break;
1389          }
1390      case XPT_CALC_GEOMETRY:
1391          {
1392              struct ccb_calc_geometry *ccg;
1393              u_int32_t secs_per_cylinder;
1394
1395              ccg = &ccb->ccg;
1396              ccg->heads = gdt->sc_hdr[target].hd_heads;
1397              ccg->secs_per_track = gdt->sc_hdr[target].hd_secs;
1398              secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1399              ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1400              ccb->ccb_h.status = CAM_REQ_CMP;
1401              --gdt_stat.io_count_act;
1402              xpt_done(ccb);
1403              break;
1404          }
1405      case XPT_RESET_BUS:           /* Reset the specified SCSI bus */
1406          {
1407              /* XXX Implement */
1408              ccb->ccb_h.status = CAM_REQ_CMP;
1409              --gdt_stat.io_count_act;
1410              xpt_done(ccb);
1411              break;
1412          }
1413      case XPT_TERM_IO:             /* Terminate the I/O process */
1414        /* XXX Implement */
1415        ccb->ccb_h.status = CAM_REQ_INVALID;
1416        --gdt_stat.io_count_act;
1417        xpt_done(ccb);
1418        break;
1419      case XPT_PATH_INQ:            /* Path routing inquiry */
1420          {
1421              struct ccb_pathinq *cpi = &ccb->cpi;
1422
1423              cpi->version_num = 1;
1424              cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
1425              cpi->hba_inquiry |= PI_WIDE_16;
1426              cpi->target_sprt = 1;
1427              cpi->hba_misc = 0;
1428              cpi->hba_eng_cnt = 0;
1429              if (bus == gdt->sc_virt_bus)
1430                  cpi->max_target = GDT_MAX_HDRIVES - 1;
1431              else if (gdt->sc_class & GDT_FC)
1432                  cpi->max_target = GDT_MAXID_FC - 1;
1433              else
1434                  cpi->max_target = GDT_MAXID - 1;
1435              cpi->max_lun = 7;
1436              cpi->unit_number = cam_sim_unit(sim);
1437              cpi->bus_id = bus;
1438              cpi->initiator_id =
1439                  (bus == gdt->sc_virt_bus ? 127 : gdt->sc_bus_id[bus]);
1440              cpi->base_transfer_speed = 3300;
1441              strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1442              strncpy(cpi->hba_vid, "Intel Corp.", HBA_IDLEN);
1443              strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1444              cpi->ccb_h.status = CAM_REQ_CMP;
1445              --gdt_stat.io_count_act;
1446              xpt_done(ccb);
1447              break;
1448          }
1449      default:
1450        GDT_DPRINTF(GDT_D_INVALID, ("gdt_next(%p) cmd 0x%x invalid\n",
1451                                    gdt, ccb->ccb_h.func_code));
1452        ccb->ccb_h.status = CAM_REQ_INVALID;
1453        --gdt_stat.io_count_act;
1454        xpt_done(ccb);
1455        break;
1456    }
1457}
1458
1459static void
1460iir_poll( struct cam_sim *sim )
1461{
1462    struct gdt_softc *gdt;
1463
1464    gdt = (struct gdt_softc *)cam_sim_softc( sim );
1465    GDT_DPRINTF(GDT_D_CMD, ("iir_poll sim %p gdt %p\n", sim, gdt));
1466    iir_intr(gdt);
1467}
1468
1469static void
1470iir_timeout(void *arg)
1471{
1472    GDT_DPRINTF(GDT_D_TIMEOUT, ("iir_timeout(%p)\n", arg));
1473}
1474
1475static void
1476iir_watchdog(void *arg)
1477{
1478    struct gdt_softc *gdt;
1479
1480    gdt = (struct gdt_softc *)arg;
1481    GDT_DPRINTF(GDT_D_DEBUG, ("iir_watchdog(%p)\n", gdt));
1482
1483    {
1484        int ccbs = 0, ucmds = 0, frees = 0, pends = 0;
1485        struct gdt_ccb *p;
1486        struct ccb_hdr *h;
1487        struct gdt_ucmd *u;
1488
1489        for (h = TAILQ_FIRST(&gdt->sc_ccb_queue); h != NULL;
1490             h = TAILQ_NEXT(h, sim_links.tqe))
1491            ccbs++;
1492        for (u = TAILQ_FIRST(&gdt->sc_ucmd_queue); u != NULL;
1493             u = TAILQ_NEXT(u, links))
1494            ucmds++;
1495        for (p = SLIST_FIRST(&gdt->sc_free_gccb); p != NULL;
1496             p = SLIST_NEXT(p, sle))
1497            frees++;
1498        for (p = SLIST_FIRST(&gdt->sc_pending_gccb); p != NULL;
1499             p = SLIST_NEXT(p, sle))
1500            pends++;
1501
1502        GDT_DPRINTF(GDT_D_TIMEOUT, ("ccbs %d ucmds %d frees %d pends %d\n",
1503                                    ccbs, ucmds, frees, pends));
1504    }
1505
1506    timeout(iir_watchdog, (caddr_t)gdt, hz * 15);
1507}
1508
1509static void
1510iir_shutdown( void *arg, int howto )
1511{
1512    struct gdt_softc *gdt;
1513    struct gdt_ccb *gccb;
1514    gdt_ucmd_t *ucmd;
1515    int lock, i;
1516
1517    gdt = (struct gdt_softc *)arg;
1518    GDT_DPRINTF(GDT_D_CMD, ("iir_shutdown(%p, %d)\n", gdt, howto));
1519
1520    printf("iir%d: Flushing all Host Drives. Please wait ...  ",
1521           gdt->sc_hanum);
1522
1523    /* allocate ucmd buffer */
1524    ucmd = malloc(sizeof(gdt_ucmd_t), M_DEVBUF, M_NOWAIT);
1525    if (ucmd == NULL) {
1526        printf("iir%d: iir_shutdown(): Cannot allocate resource\n",
1527               gdt->sc_hanum);
1528        return;
1529    }
1530    bzero(ucmd, sizeof(gdt_ucmd_t));
1531
1532    /* wait for pending IOs */
1533    lock = splcam();
1534    gdt->sc_state = GDT_SHUTDOWN;
1535    splx(lock);
1536    if ((gccb = SLIST_FIRST(&gdt->sc_pending_gccb)) != NULL)
1537        (void) tsleep((void *)gccb, PCATCH | PRIBIO, "iirshw", 100 * hz);
1538
1539    /* flush */
1540    for (i = 0; i < GDT_MAX_HDRIVES; ++i) {
1541        if (gdt->sc_hdr[i].hd_present) {
1542            ucmd->service = GDT_CACHESERVICE;
1543            ucmd->OpCode = GDT_FLUSH;
1544            ucmd->u.cache.DeviceNo = i;
1545            lock = splcam();
1546            TAILQ_INSERT_TAIL(&gdt->sc_ucmd_queue, ucmd, links);
1547            ucmd->complete_flag = FALSE;
1548            splx(lock);
1549            gdt_next(gdt);
1550            if (!ucmd->complete_flag)
1551                (void) tsleep((void *)ucmd, PCATCH|PRIBIO, "iirshw", 10*hz);
1552        }
1553    }
1554
1555    free(ucmd, M_DEVBUF);
1556    printf("Done.\n");
1557}
1558
1559void
1560iir_intr(void *arg)
1561{
1562    struct gdt_softc *gdt = arg;
1563    struct gdt_intr_ctx ctx;
1564    int lock = 0;
1565    struct gdt_ccb *gccb;
1566    gdt_ucmd_t *ucmd;
1567    u_int32_t cnt;
1568
1569    GDT_DPRINTF(GDT_D_INTR, ("gdt_intr(%p)\n", gdt));
1570
1571    /* If polling and we were not called from gdt_wait, just return */
1572    if ((gdt->sc_state & GDT_POLLING) &&
1573        !(gdt->sc_state & GDT_POLL_WAIT))
1574        return;
1575
1576    if (!(gdt->sc_state & GDT_POLLING))
1577        lock = splcam();
1578    gdt_wait_index = 0;
1579
1580    ctx.istatus = gdt->sc_get_status(gdt);
1581    if (!ctx.istatus) {
1582        if (!(gdt->sc_state & GDT_POLLING))
1583            splx(lock);
1584        gdt->sc_status = GDT_S_NO_STATUS;
1585        return;
1586    }
1587
1588    gdt->sc_intr(gdt, &ctx);
1589
1590    gdt->sc_status = ctx.cmd_status;
1591    gdt->sc_service = ctx.service;
1592    gdt->sc_info = ctx.info;
1593    gdt->sc_info2 = ctx.info2;
1594
1595    if (gdt->sc_state & GDT_POLL_WAIT) {
1596        gdt_wait_gdt = gdt;
1597        gdt_wait_index = ctx.istatus;
1598    }
1599
1600    if (ctx.istatus == GDT_ASYNCINDEX) {
1601        gdt_async_event(gdt, ctx.service);
1602        if (!(gdt->sc_state & GDT_POLLING))
1603            splx(lock);
1604        return;
1605    }
1606    if (ctx.istatus == GDT_SPEZINDEX) {
1607        GDT_DPRINTF(GDT_D_INVALID,
1608                    ("iir%d: Service unknown or not initialized!\n",
1609                     gdt->sc_hanum));
1610        gdt->sc_dvr.size = sizeof(gdt->sc_dvr.eu.driver);
1611        gdt->sc_dvr.eu.driver.ionode = gdt->sc_hanum;
1612        gdt_store_event(GDT_ES_DRIVER, 4, &gdt->sc_dvr);
1613        if (!(gdt->sc_state & GDT_POLLING))
1614            splx(lock);
1615        return;
1616    }
1617
1618    gccb = &gdt->sc_gccbs[ctx.istatus - 2];
1619    ctx.service = gccb->gc_service;
1620
1621    switch (gccb->gc_flags) {
1622      case GDT_GCF_UNUSED:
1623        GDT_DPRINTF(GDT_D_INVALID, ("iir%d: Index (%d) to unused command!\n",
1624                    gdt->sc_hanum, ctx.istatus));
1625        gdt->sc_dvr.size = sizeof(gdt->sc_dvr.eu.driver);
1626        gdt->sc_dvr.eu.driver.ionode = gdt->sc_hanum;
1627        gdt->sc_dvr.eu.driver.index = ctx.istatus;
1628        gdt_store_event(GDT_ES_DRIVER, 1, &gdt->sc_dvr);
1629        gdt_free_ccb(gdt, gccb);
1630        /* fallthrough */
1631
1632      case GDT_GCF_INTERNAL:
1633        if (!(gdt->sc_state & GDT_POLLING))
1634            splx(lock);
1635        break;
1636
1637      case GDT_GCF_IOCTL:
1638        ucmd = gccb->gc_ucmd;
1639        if (gdt->sc_status == GDT_S_BSY) {
1640            GDT_DPRINTF(GDT_D_DEBUG, ("iir_intr(%p) ioctl: gccb %p busy\n",
1641                                      gdt, gccb));
1642            TAILQ_INSERT_HEAD(&gdt->sc_ucmd_queue, ucmd, links);
1643            if (!(gdt->sc_state & GDT_POLLING))
1644                splx(lock);
1645        } else {
1646            ucmd->status = gdt->sc_status;
1647            ucmd->info = gdt->sc_info;
1648            ucmd->complete_flag = TRUE;
1649            if (ucmd->service == GDT_CACHESERVICE) {
1650                if (ucmd->OpCode == GDT_IOCTL) {
1651                    cnt = ucmd->u.ioctl.param_size;
1652                    if (cnt != 0)
1653                        bcopy(gccb->gc_scratch, ucmd->data, cnt);
1654                } else {
1655                    cnt = ucmd->u.cache.BlockCnt * GDT_SECTOR_SIZE;
1656                    if (cnt != 0)
1657                        bcopy(gccb->gc_scratch, ucmd->data, cnt);
1658                }
1659            } else {
1660                cnt = ucmd->u.raw.sdlen;
1661                if (cnt != 0)
1662                    bcopy(gccb->gc_scratch, ucmd->data, cnt);
1663                if (ucmd->u.raw.sense_len != 0)
1664                    bcopy(gccb->gc_scratch, ucmd->data, cnt);
1665            }
1666            gdt_free_ccb(gdt, gccb);
1667            if (!(gdt->sc_state & GDT_POLLING))
1668                splx(lock);
1669            /* wakeup */
1670            wakeup(ucmd);
1671        }
1672        gdt_next(gdt);
1673        break;
1674
1675      default:
1676        gdt_free_ccb(gdt, gccb);
1677        gdt_sync_event(gdt, ctx.service, ctx.istatus, gccb);
1678        if (!(gdt->sc_state & GDT_POLLING))
1679            splx(lock);
1680        gdt_next(gdt);
1681        break;
1682    }
1683}
1684
1685static int
1686gdt_async_event(struct gdt_softc *gdt, int service)
1687{
1688    struct gdt_ccb *gccb;
1689
1690    GDT_DPRINTF(GDT_D_INTR, ("gdt_async_event(%p, %d)\n", gdt, service));
1691
1692    if (service == GDT_SCREENSERVICE) {
1693        if (gdt->sc_status == GDT_MSG_REQUEST) {
1694            while (gdt->sc_test_busy(gdt))
1695                DELAY(1);
1696            bzero(gdt->sc_cmd, GDT_CMD_SZ);
1697            gccb = gdt_get_ccb(gdt);
1698            if (gccb == NULL) {
1699                printf("iir%d: No free command index found\n",
1700                       gdt->sc_hanum);
1701                return (1);
1702            }
1703            gccb->gc_service = service;
1704            gccb->gc_flags = GDT_GCF_SCREEN;
1705            gdt->sc_set_sema0(gdt);
1706            gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
1707                      gccb->gc_cmd_index);
1708            gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_READ);
1709            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
1710                      GDT_MSG_INV_HANDLE);
1711            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
1712                      gdt_ccb_vtop(gdt, gccb) +
1713                      offsetof(struct gdt_ccb, gc_scratch[0]));
1714            gdt->sc_cmd_off = 0;
1715            gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
1716                                      sizeof(u_int32_t));
1717            gdt->sc_cmd_cnt = 0;
1718            gdt->sc_copy_cmd(gdt, gccb);
1719            printf("iir%d: [PCI %d/%d] ",
1720                gdt->sc_hanum,gdt->sc_bus,gdt->sc_slot);
1721            gdt->sc_release_event(gdt);
1722        }
1723
1724    } else {
1725        if ((gdt->sc_fw_vers & 0xff) >= 0x1a) {
1726            gdt->sc_dvr.size = 0;
1727            gdt->sc_dvr.eu.async.ionode = gdt->sc_hanum;
1728            gdt->sc_dvr.eu.async.status  = gdt->sc_status;
1729            /* severity and event_string already set! */
1730        } else {
1731            gdt->sc_dvr.size = sizeof(gdt->sc_dvr.eu.async);
1732            gdt->sc_dvr.eu.async.ionode   = gdt->sc_hanum;
1733            gdt->sc_dvr.eu.async.service = service;
1734            gdt->sc_dvr.eu.async.status  = gdt->sc_status;
1735            gdt->sc_dvr.eu.async.info    = gdt->sc_info;
1736            *(u_int32_t *)gdt->sc_dvr.eu.async.scsi_coord  = gdt->sc_info2;
1737        }
1738        gdt_store_event(GDT_ES_ASYNC, service, &gdt->sc_dvr);
1739        printf("iir%d: %s\n", gdt->sc_hanum, gdt->sc_dvr.event_string);
1740    }
1741
1742    return (0);
1743}
1744
1745static int
1746gdt_sync_event(struct gdt_softc *gdt, int service,
1747               u_int8_t index, struct gdt_ccb *gccb)
1748{
1749    union ccb *ccb;
1750    int op;
1751
1752    GDT_DPRINTF(GDT_D_INTR,
1753                ("gdt_sync_event(%p, %d, %d, %p)\n", gdt,service,index,gccb));
1754
1755    ccb = gccb->gc_ccb;
1756
1757    if (service == GDT_SCREENSERVICE) {
1758        u_int32_t msg_len;
1759
1760        msg_len = gdt_dec32(gccb->gc_scratch + GDT_SCR_MSG_LEN);
1761        if (msg_len)
1762            if (!(gccb->gc_scratch[GDT_SCR_MSG_ANSWER] &&
1763                  gccb->gc_scratch[GDT_SCR_MSG_EXT])) {
1764                gccb->gc_scratch[GDT_SCR_MSG_TEXT + msg_len] = '\0';
1765                printf("%s",&gccb->gc_scratch[GDT_SCR_MSG_TEXT]);
1766            }
1767
1768        if (gccb->gc_scratch[GDT_SCR_MSG_EXT] &&
1769            !gccb->gc_scratch[GDT_SCR_MSG_ANSWER]) {
1770            while (gdt->sc_test_busy(gdt))
1771                DELAY(1);
1772            bzero(gdt->sc_cmd, GDT_CMD_SZ);
1773            gccb = gdt_get_ccb(gdt);
1774            if (gccb == NULL) {
1775                printf("iir%d: No free command index found\n",
1776                       gdt->sc_hanum);
1777                return (1);
1778            }
1779            gccb->gc_service = service;
1780            gccb->gc_flags = GDT_GCF_SCREEN;
1781            gdt->sc_set_sema0(gdt);
1782            gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
1783                      gccb->gc_cmd_index);
1784            gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_READ);
1785            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
1786                      gccb->gc_scratch[GDT_SCR_MSG_HANDLE]);
1787            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
1788                      gdt_ccb_vtop(gdt, gccb) +
1789                      offsetof(struct gdt_ccb, gc_scratch[0]));
1790            gdt->sc_cmd_off = 0;
1791            gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
1792                                      sizeof(u_int32_t));
1793            gdt->sc_cmd_cnt = 0;
1794            gdt->sc_copy_cmd(gdt, gccb);
1795            gdt->sc_release_event(gdt);
1796            return (0);
1797        }
1798
1799        if (gccb->gc_scratch[GDT_SCR_MSG_ANSWER] &&
1800            gdt_dec32(gccb->gc_scratch + GDT_SCR_MSG_ALEN)) {
1801            /* default answers (getchar() not possible) */
1802            if (gdt_dec32(gccb->gc_scratch + GDT_SCR_MSG_ALEN) == 1) {
1803                gdt_enc32(gccb->gc_scratch + GDT_SCR_MSG_ALEN, 0);
1804                gdt_enc32(gccb->gc_scratch + GDT_SCR_MSG_LEN, 1);
1805                gccb->gc_scratch[GDT_SCR_MSG_TEXT] = 0;
1806            } else {
1807                gdt_enc32(gccb->gc_scratch + GDT_SCR_MSG_ALEN,
1808                          gdt_dec32(gccb->gc_scratch + GDT_SCR_MSG_ALEN) - 2);
1809                gdt_enc32(gccb->gc_scratch + GDT_SCR_MSG_LEN, 2);
1810                gccb->gc_scratch[GDT_SCR_MSG_TEXT] = 1;
1811                gccb->gc_scratch[GDT_SCR_MSG_TEXT + 1] = 0;
1812            }
1813            gccb->gc_scratch[GDT_SCR_MSG_EXT] = 0;
1814            gccb->gc_scratch[GDT_SCR_MSG_ANSWER] = 0;
1815            while (gdt->sc_test_busy(gdt))
1816                DELAY(1);
1817            bzero(gdt->sc_cmd, GDT_CMD_SZ);
1818            gccb = gdt_get_ccb(gdt);
1819            if (gccb == NULL) {
1820                printf("iir%d: No free command index found\n",
1821                       gdt->sc_hanum);
1822                return (1);
1823            }
1824            gccb->gc_service = service;
1825            gccb->gc_flags = GDT_GCF_SCREEN;
1826            gdt->sc_set_sema0(gdt);
1827            gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
1828                      gccb->gc_cmd_index);
1829            gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_WRITE);
1830            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
1831                      gccb->gc_scratch[GDT_SCR_MSG_HANDLE]);
1832            gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
1833                      gdt_ccb_vtop(gdt, gccb) +
1834                      offsetof(struct gdt_ccb, gc_scratch[0]));
1835            gdt->sc_cmd_off = 0;
1836            gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
1837                                      sizeof(u_int32_t));
1838            gdt->sc_cmd_cnt = 0;
1839            gdt->sc_copy_cmd(gdt, gccb);
1840            gdt->sc_release_event(gdt);
1841            return (0);
1842        }
1843        printf("\n");
1844        return (0);
1845    } else {
1846        untimeout(iir_timeout, gccb, ccb->ccb_h.timeout_ch);
1847        if (gdt->sc_status == GDT_S_BSY) {
1848            GDT_DPRINTF(GDT_D_DEBUG, ("gdt_sync_event(%p) gccb %p busy\n",
1849                                      gdt, gccb));
1850            TAILQ_INSERT_HEAD(&gdt->sc_ccb_queue, &ccb->ccb_h, sim_links.tqe);
1851            ++gdt_stat.req_queue_act;
1852            if (gdt_stat.req_queue_act > gdt_stat.req_queue_max)
1853                gdt_stat.req_queue_max = gdt_stat.req_queue_act;
1854            return (2);
1855        }
1856
1857        if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1858            op = BUS_DMASYNC_POSTREAD;
1859        else
1860            op = BUS_DMASYNC_POSTWRITE;
1861        bus_dmamap_sync(gdt->sc_buffer_dmat, gccb->gc_dmamap, op);
1862
1863        ccb->csio.resid = 0;
1864        if (gdt->sc_status == GDT_S_OK) {
1865            ccb->ccb_h.status = CAM_REQ_CMP;
1866        } else {
1867            /* error */
1868            if (gccb->gc_service == GDT_CACHESERVICE) {
1869                ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
1870                ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1871                bzero(&ccb->csio.sense_data, ccb->csio.sense_len);
1872                ccb->csio.sense_data.error_code =
1873                    SSD_CURRENT_ERROR | SSD_ERRCODE_VALID;
1874                ccb->csio.sense_data.flags = SSD_KEY_NOT_READY;
1875
1876                gdt->sc_dvr.size = sizeof(gdt->sc_dvr.eu.sync);
1877                gdt->sc_dvr.eu.sync.ionode  = gdt->sc_hanum;
1878                gdt->sc_dvr.eu.sync.service = service;
1879                gdt->sc_dvr.eu.sync.status  = gdt->sc_status;
1880                gdt->sc_dvr.eu.sync.info    = gdt->sc_info;
1881                gdt->sc_dvr.eu.sync.hostdrive = ccb->ccb_h.target_id;
1882                if (gdt->sc_status >= 0x8000)
1883                    gdt_store_event(GDT_ES_SYNC, 0, &gdt->sc_dvr);
1884                else
1885                    gdt_store_event(GDT_ES_SYNC, service, &gdt->sc_dvr);
1886            } else {
1887                /* raw service */
1888                if (gdt->sc_status != GDT_S_RAW_SCSI || gdt->sc_info >= 0x100) {
1889                    ccb->ccb_h.status = CAM_SEL_TIMEOUT;
1890                } else {
1891                    ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
1892                    ccb->csio.scsi_status = gdt->sc_info;
1893                    bcopy(gccb->gc_scratch, &ccb->csio.sense_data,
1894                          ccb->csio.sense_len);
1895                }
1896            }
1897        }
1898        --gdt_stat.io_count_act;
1899        xpt_done(ccb);
1900    }
1901    return (0);
1902}
1903
1904/* Controller event handling functions */
1905gdt_evt_str *gdt_store_event(u_int16_t source, u_int16_t idx,
1906                             gdt_evt_data *evt)
1907{
1908    gdt_evt_str *e;
1909    struct timeval tv;
1910
1911    GDT_DPRINTF(GDT_D_MISC, ("gdt_store_event(%d, %d)\n", source, idx));
1912    if (source == 0)                        /* no source -> no event */
1913        return 0;
1914
1915    if (ebuffer[elastidx].event_source == source &&
1916        ebuffer[elastidx].event_idx == idx &&
1917        ((evt->size != 0 && ebuffer[elastidx].event_data.size != 0 &&
1918          !memcmp((char *)&ebuffer[elastidx].event_data.eu,
1919                  (char *)&evt->eu, evt->size)) ||
1920         (evt->size == 0 && ebuffer[elastidx].event_data.size == 0 &&
1921          !strcmp((char *)&ebuffer[elastidx].event_data.event_string,
1922                  (char *)&evt->event_string)))) {
1923        e = &ebuffer[elastidx];
1924        getmicrotime(&tv);
1925        e->last_stamp = tv.tv_sec;
1926        ++e->same_count;
1927    } else {
1928        if (ebuffer[elastidx].event_source != 0) {  /* entry not free ? */
1929            ++elastidx;
1930            if (elastidx == GDT_MAX_EVENTS)
1931                elastidx = 0;
1932            if (elastidx == eoldidx) {              /* reached mark ? */
1933                ++eoldidx;
1934                if (eoldidx == GDT_MAX_EVENTS)
1935                    eoldidx = 0;
1936            }
1937        }
1938        e = &ebuffer[elastidx];
1939        e->event_source = source;
1940        e->event_idx = idx;
1941        getmicrotime(&tv);
1942        e->first_stamp = e->last_stamp = tv.tv_sec;
1943        e->same_count = 1;
1944        e->event_data = *evt;
1945        e->application = 0;
1946    }
1947    return e;
1948}
1949
1950int gdt_read_event(int handle, gdt_evt_str *estr)
1951{
1952    gdt_evt_str *e;
1953    int eindex, lock;
1954
1955    GDT_DPRINTF(GDT_D_MISC, ("gdt_read_event(%d)\n", handle));
1956    lock = splcam();
1957    if (handle == -1)
1958        eindex = eoldidx;
1959    else
1960        eindex = handle;
1961    estr->event_source = 0;
1962
1963    if (eindex >= GDT_MAX_EVENTS) {
1964        splx(lock);
1965        return eindex;
1966    }
1967    e = &ebuffer[eindex];
1968    if (e->event_source != 0) {
1969        if (eindex != elastidx) {
1970            if (++eindex == GDT_MAX_EVENTS)
1971                eindex = 0;
1972        } else {
1973            eindex = -1;
1974        }
1975        memcpy(estr, e, sizeof(gdt_evt_str));
1976    }
1977    splx(lock);
1978    return eindex;
1979}
1980
1981void gdt_readapp_event(u_int8_t application, gdt_evt_str *estr)
1982{
1983    gdt_evt_str *e;
1984    int found = FALSE;
1985    int eindex, lock;
1986
1987    GDT_DPRINTF(GDT_D_MISC, ("gdt_readapp_event(%d)\n", application));
1988    lock = splcam();
1989    eindex = eoldidx;
1990    for (;;) {
1991        e = &ebuffer[eindex];
1992        if (e->event_source == 0)
1993            break;
1994        if ((e->application & application) == 0) {
1995            e->application |= application;
1996            found = TRUE;
1997            break;
1998        }
1999        if (eindex == elastidx)
2000            break;
2001        if (++eindex == GDT_MAX_EVENTS)
2002            eindex = 0;
2003    }
2004    if (found)
2005        memcpy(estr, e, sizeof(gdt_evt_str));
2006    else
2007        estr->event_source = 0;
2008    splx(lock);
2009}
2010
2011void gdt_clear_events()
2012{
2013    GDT_DPRINTF(GDT_D_MISC, ("gdt_clear_events\n"));
2014
2015    eoldidx = elastidx = 0;
2016    ebuffer[0].event_source = 0;
2017}
2018