The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/gdt_common.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 151d1d08a501e397389db7a24f11b270


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.