root/dev/ic/gdt_common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gdt_attach
  2. gdt_eval_mapping
  3. gdt_enqueue
  4. gdt_dequeue
  5. gdt_scsi_cmd
  6. gdt_exec_ccb
  7. gdt_copy_internal_data
  8. gdt_internal_cache_cmd
  9. gdt_raw_scsi_cmd
  10. gdt_clear_events
  11. gdt_async_event
  12. gdt_sync_event
  13. gdt_intr
  14. gdtminphys
  15. gdt_wait
  16. gdt_internal_cmd
  17. gdt_get_ccb
  18. gdt_free_ccb
  19. gdt_enqueue_ccb
  20. gdt_start_ccbs
  21. gdt_chain
  22. gdt_timeout
  23. gdt_watchdog
  24. gdt_ioctl
  25. gdt_ioctl_inq
  26. gdt_ioctl_vol
  27. gdt_ioctl_disk
  28. gdt_ioctl_alarm
  29. gdt_ioctl_setstate
  30. gdt_ioctl

    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 */

/* [<][>][^][v][top][bottom][index][help] */