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/i386/isa/ultra14f.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 /*
    2  * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu)
    3  * Slight fixes to timeouts to run with the 34F
    4  * Thanks to Julian Elischer for advice and help with this port.
    5  *
    6  * Written by Julian Elischer (julian@tfs.com)
    7  * for TRW Financial Systems for use under the MACH(2.5) operating system.
    8  *
    9  * TRW Financial Systems, in accordance with their agreement with Carnegie
   10  * Mellon University, makes this software available to CMU to distribute
   11  * or use in any manner that they see fit as long as this message is kept with
   12  * the software. For this reason TFS also grants any other persons or
   13  * organisations permission to use or modify this software.
   14  *
   15  * TFS supplies this software to be publicly redistributed
   16  * on the understanding that TFS is not responsible for the correct
   17  * functioning of this software in any circumstances.
   18  *
   19  * commenced: Sun Sep 27 18:14:01 PDT 1992
   20  * slight mod to make work with 34F as well: Wed Jun  2 18:05:48 WST 1993
   21  *
   22  * today: Fri Jun  2 17:21:03 EST 1994
   23  * added 24F support  ++sg
   24  *
   25  * $FreeBSD: src/sys/i386/isa/ultra14f.c,v 1.49.2.1 1999/09/05 08:13:39 peter Exp $
   26  */
   27 
   28 #include <sys/types.h>
   29 
   30 #ifdef  KERNEL                  /* don't laugh.. this compiles to a program too.. look */
   31 #include "uha.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/errno.h>
   36 #include <sys/ioctl.h>
   37 #include <sys/malloc.h>
   38 #include <sys/buf.h>
   39 #include <sys/proc.h>
   40 
   41 #include <machine/clock.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/vm_param.h>
   45 #include <vm/pmap.h>
   46 
   47 #include <i386/isa/isa_device.h>
   48 #endif /*KERNEL */
   49 #include <scsi/scsi_all.h>
   50 #include <scsi/scsiconf.h>
   51 
   52 /* */
   53 
   54 #ifndef KERNEL
   55 #define NUHA 1
   56 #endif /*KERNEL */
   57 
   58 typedef struct {
   59         unsigned char addr[4];
   60 } physaddr;
   61 typedef struct {
   62         unsigned char len[4];
   63 } physlen;
   64 
   65 #define KVTOPHYS(x)   vtophys(x)
   66 
   67 #define UHA_MSCP_MAX    32      /* store up to 32MSCPs at any one time
   68                                  * MAX = ?
   69                                  */
   70 #define MSCP_HASH_SIZE  32      /* when we have a physical addr. for
   71                                  * a mscp and need to find the mscp in
   72                                  * space, look it up in the hash table
   73                                  */
   74 #define MSCP_HASH_SHIFT 9       /* only hash on multiples of 512 */
   75 #define MSCP_HASH(x)    ((((long int)(x))>>MSCP_HASH_SHIFT) % MSCP_HASH_SIZE)
   76 
   77 extern int hz;
   78 #define UHA_NSEG        33      /* number of dma segments supported */
   79 
   80 /************************** board definitions *******************************/
   81 struct uha_reg
   82 {
   83         int id;                 /* product id reg               */
   84         int type;               /* product type reg             */
   85         int ectl;               /* EISA expansion control bits  */
   86         int config;             /* configuration bits           */
   87         int lmask;              /* local doorbell mask reg      */
   88         int lint;               /* local doorbell int/stat reg  */
   89         int smask;              /* system doorbell mask reg     */
   90         int sint;               /* system doorbell int/stat reg */
   91         int ogmcmd;             /* outgoing mail command        */
   92         int ogmptr;             /* outgoing mail ptr            */
   93         int icmcmd;             /* incoming mail command        */
   94         int icmptr;             /* incoming mail ptr            */
   95 };
   96 
   97 struct uha_bits
   98 {
   99         /* uha_lint (read) */
  100         unsigned char ldip;
  101 
  102         /* uha_lint (write) */
  103         unsigned char adrst;
  104         unsigned char sbrst;
  105         unsigned char asrst;
  106         unsigned char abort;
  107         unsigned char ogmint;
  108 
  109         /* uha_sint (read) */
  110         unsigned char sintp;
  111         unsigned char abort_succ;
  112         unsigned char abort_fail;
  113 
  114         /* uha_sint (write) */
  115         unsigned char abort_ack;
  116         unsigned char icm_ack;
  117 };
  118 
  119 
  120 /*
  121  * UHA_LINT bits (read)
  122  */
  123 
  124 #define UHA_LDIP                0x80    /* local doorbell int pending */
  125 #define U24_LDIP                0x02
  126 
  127 /*
  128  * UHA_LINT bits (write)
  129  */
  130 
  131 #define UHA_ADRST               0x40    /* adapter soft reset */
  132 #define UHA_SBRST               0x20    /* scsi bus reset */
  133 #define UHA_ASRST               0x60    /* adapter and scsi reset */
  134 #define UHA_ABORT               0x10    /* abort MSCP */
  135 #define UHA_OGMINT              0x01    /* tell adapter to get mail */
  136 #define U24_SBRST               0x40    /* scsi bus reset */
  137 #define U24_ADRST               0x80    /* adapter soft reset */
  138 #define U24_ASRST               0xc0    /* adapter and scsi reset */
  139 #define U24_ABORT               0x10    /* same? */
  140 #define U24_OGMINT              0x02    /* enable OGM interrupt */
  141 
  142 /*
  143  * UHA_SMASK bits (read)
  144  */
  145 
  146 #define UHA_SINTEN              0x80    /* system doorbell interupt Enabled */
  147 #define UHA_ABORT_COMPLETE_EN   0x10    /* abort MSCP command complete int Enabled */
  148 #define UHA_ICM_ENABLED         0x01    /* ICM interrupt enabled */
  149 
  150 /*
  151  * UHA_SMASK bits (write)
  152  */
  153 
  154 #define UHA_ENSINT              0x80    /* enable system doorbell interrupt */
  155 #define UHA_EN_ABORT_COMPLETE   0x10    /* enable abort MSCP complete int */
  156 #define UHA_ENICM               0x01    /* enable ICM interrupt */
  157 
  158 /*
  159  * UHA_SINT bits (read)
  160  */
  161 
  162 #define UHA_SINTP               0x80    /* system doorbell int pending */
  163 #define UHA_ABORT_SUCC          0x10    /* abort MSCP successful */
  164 #define UHA_ABORT_FAIL          0x18    /* abort MSCP failed */
  165 #define U24_SINTP               0x02    /* system doorbell int pending */
  166 #define U24_ABORT_SUCC          0x10    /* same? */
  167 #define U24_ABORT_FAIL          0x18    /* same? */
  168 
  169 /*
  170  * UHA_SINT bits (write)
  171  */
  172 
  173 #define UHA_ABORT_ACK           0x18    /* acknowledge status and clear */
  174 #define UHA_ICM_ACK             0x01    /* acknowledge ICM and clear */
  175 #define U24_ABORT_ACK           0x18    /* same */
  176 #define U24_ICM_ACK             0x02    /* 24F acknowledge ICM and clear */
  177 
  178 /*
  179  * UHA_CONF1 bits (read only)
  180  */
  181 
  182 #define UHA_DMA_CH5             0x00    /* DMA channel 5 */
  183 #define UHA_DMA_CH6             0x40    /* 6 */
  184 #define UHA_DMA_CH7             0x80    /* 7 */
  185 #define UHA_IRQ15               0x00    /* IRQ 15 */
  186 #define UHA_IRQ14               0x10    /* 14 */
  187 #define UHA_IRQ11               0x20    /* 11 */
  188 #define UHA_IRQ10               0x30    /* 10 */
  189 
  190 #define EISA_CONFIG             0x0c80  /* Configuration base port */
  191 #define EISA_DISABLE            0x01    /* EISA disable bit */
  192 
  193 /*
  194  * ha_status error codes
  195  */
  196 
  197 #define UHA_NO_ERR              0x00    /* No error supposedly */
  198 #define UHA_SBUS_ABORT_ERR      0x84    /* scsi bus abort error */
  199 #define UHA_SBUS_TIMEOUT        0x91    /* scsi bus selection timeout */
  200 #define UHA_SBUS_OVER_UNDER     0x92    /* scsi bus over/underrun */
  201 #define UHA_BAD_SCSI_CMD        0x96    /* illegal scsi command */
  202 #define UHA_AUTO_SENSE_ERR      0x9b    /* auto request sense err */
  203 #define UHA_SBUS_RES_ERR        0xa3    /* scsi bus reset error */
  204 #define UHA_BAD_SG_LIST         0xff    /* invalid scatter gath list */
  205 
  206 struct uha_dma_seg {
  207         physaddr addr;
  208         physlen len;
  209 };
  210 
  211 struct mscp {
  212         unsigned char opcode:3;
  213 #define U14_HAC         0x01    /* host adapter command */
  214 #define U14_TSP         0x02    /* target scsi pass through command */
  215 #define U14_SDR         0x04    /* scsi device reset */
  216         unsigned char xdir:2;   /* xfer direction */
  217 #define U14_SDET        0x00    /* determined by scsi command */
  218 #define U14_SDIN        0x01    /* scsi data in */
  219 #define U14_SDOUT       0x02    /* scsi data out */
  220 #define U14_NODATA      0x03    /* no data xfer */
  221         unsigned char dcn:1;    /* disable disconnect for this command */
  222         unsigned char ca:1;     /* cache control */
  223         unsigned char sgth:1;   /* scatter gather flag */
  224         unsigned char target:3;
  225         unsigned char chan:2;   /* scsi channel (always 0 for 14f) */
  226         unsigned char lun:3;
  227         physaddr data;
  228         physlen datalen;
  229         physaddr link;
  230         unsigned char link_id;
  231         unsigned char sg_num;   /*number of scat gath segs */
  232         /*in s-g list if sg flag is */
  233         /*set. starts at 1, 8bytes per */
  234         unsigned char senselen;
  235         unsigned char cdblen;
  236         unsigned char cdb[12];
  237         unsigned char ha_status;
  238         unsigned char targ_status;
  239         physaddr sense;         /* if 0 no auto sense */
  240         /*-----------------end of hardware supported fields----------------*/
  241         struct mscp *next;      /* in free list */
  242         struct scsi_xfer *xs;   /* the scsi_xfer for this cmd */
  243         int     flags;
  244 #define MSCP_FREE        0
  245 #define MSCP_ACTIVE      1
  246 #define MSCP_ABORTED     2
  247         struct uha_dma_seg uha_dma[UHA_NSEG];
  248         struct scsi_sense_data mscp_sense;
  249         struct mscp *nexthash;
  250         long int hashkey;
  251 };
  252 
  253 static struct uha_data {
  254         int     flags;
  255 #define UHA_INIT        0x01
  256 #define UHA_24F         0x02
  257         int     baseport;
  258         struct  mscp *mscphash[MSCP_HASH_SIZE];
  259         struct  mscp *free_mscp;
  260         int     unit;
  261         int     our_id;         /* our scsi id */
  262         int     vect;
  263         int     dma;
  264         int     nummscps;
  265         struct  scsi_link sc_link;
  266         struct  uha_reg *ur;
  267         struct  uha_bits *ub;
  268 } *uhadata[NUHA];
  269 
  270 static int      uha_abort __P((struct uha_data *uha, struct mscp *mscp));
  271 static u_int32_t        uha_adapter_info __P((int unit));
  272 static int      uha_attach __P((struct isa_device *dev));
  273 static void     uha_done __P((struct uha_data *uha, struct mscp *mscp));
  274 static void     uha_free_mscp __P((struct uha_data *uha, struct mscp *mscp,
  275                                    int flags));
  276 static struct mscp *
  277                 uha_get_mscp __P((struct uha_data *uha, int flags));
  278 static int      uha_init __P((struct uha_data *uha));
  279 static int      uha24_init __P((struct uha_data *uha));
  280 static void     uhaminphys __P((struct buf *bp));
  281 static struct mscp *
  282                 uha_mscp_phys_kv __P((struct uha_data *uha, long mscp_phys));
  283 static int      uha_poll __P((struct uha_data *uha, int wait));
  284 #ifdef UHADEBUG
  285 static void     uha_print_active_mscp __P((struct uha_data *uha));
  286 static void     uha_print_mscp __P((struct mscp *mscp));
  287 #endif
  288 static int      uhaprobe __P((struct isa_device *dev));
  289 static int32_t  uha_scsi_cmd __P((struct scsi_xfer *xs));
  290 static void     uha_send_mbox __P((struct uha_data *uha, struct mscp *mscp));
  291 static timeout_t
  292                 uha_timeout;
  293 
  294 static  struct mscp *cheat;
  295 static unsigned long int scratch;
  296 #define EISA_MAX_SLOTS  16      /* XXX This should go into a comon header */
  297 static  uha_slot = 0;           /* slot last board was found in */
  298 static  uha_unit = 0;
  299 #define UHA_SHOWMSCPS 0x01
  300 #define UHA_SHOWINTS 0x02
  301 #define UHA_SHOWCMDS 0x04
  302 #define UHA_SHOWMISC 0x08
  303 #define FAIL    1
  304 #define SUCCESS 0
  305 #define PAGESIZ 4096
  306 
  307 #ifdef  KERNEL
  308 struct isa_driver uhadriver =
  309 {
  310         uhaprobe,
  311         uha_attach,
  312         "uha"
  313 };
  314 
  315 static struct scsi_adapter uha_switch =
  316 {
  317         uha_scsi_cmd,
  318         uhaminphys,
  319         0,
  320         0,
  321         uha_adapter_info,
  322         "uha",
  323         { 0, 0 }
  324 };
  325 
  326 /* the below structure is so we have a default dev struct for out link struct */
  327 static struct scsi_device uha_dev =
  328 {
  329     NULL,                       /* Use default error handler */
  330     NULL,                       /* have a queue, served by this */
  331     NULL,                       /* have no async handler */
  332     NULL,                       /* Use default 'done' routine */
  333     "uha",
  334     0,
  335     { 0, 0 }
  336 };
  337 
  338 #endif /*KERNEL */
  339 
  340 #ifndef KERNEL
  341 main()
  342 {
  343         printf("uha_data is %d bytes\n", sizeof(struct uha_data));
  344         printf("mscp is %d bytes\n", sizeof(struct mscp));
  345 }
  346 
  347 #else /*KERNEL*/
  348 /*
  349  * Function to send a command out through a mailbox
  350  */
  351 static void
  352 uha_send_mbox(struct uha_data *uha, struct mscp *mscp)
  353 {
  354         int     spincount = 100000;     /* 1s should be enough */
  355         struct uha_reg *ur = uha->ur;
  356         struct uha_bits *ub = uha->ub;
  357         int     s = splbio();
  358 
  359         while (--spincount) {
  360                 if ((inb(ur->lint) & ub->ldip) == 0)
  361                         break;
  362                 DELAY(100);
  363         }
  364         if (spincount == 0) {
  365                 printf("uha%d: uha_send_mbox, board is not responding\n",
  366                         uha->unit);
  367                 Debugger("ultra14f");
  368         }
  369         outl(ur->ogmptr, KVTOPHYS(mscp));
  370         if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
  371         outb(ur->lint, ub->ogmint);
  372         splx(s);
  373 }
  374 
  375 /*
  376  * Function to send abort to 14f
  377  */
  378 int
  379 uha_abort(struct uha_data *uha, struct mscp *mscp)
  380 {
  381         int     spincount = 100;        /* 1 mSec */
  382         int     abortcount = 200000;    /*2 secs */
  383         struct  uha_reg *ur = uha->ur;
  384         struct  uha_bits *ub = uha->ub;
  385         int     s = splbio();
  386 
  387         while (--spincount) {
  388                 if ((inb(ur->lint) & ub->ldip) == 0)
  389                         break;
  390                 DELAY(10);
  391         }
  392         if (spincount == 0) {
  393                 printf("uha%d: uha_abort, board is not responding\n", uha->unit);
  394                 Debugger("ultra14f");
  395         }
  396         outl(ur->ogmptr,KVTOPHYS(mscp));
  397         if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
  398         outb(ur->lint, ub->abort);
  399 
  400         while (--abortcount) {
  401                 if (inb(ur->sint) & ub->abort_fail)
  402                         break;
  403                 DELAY(10);
  404         }
  405         if (abortcount == 0) {
  406                 printf("uha%d: uha_abort, board is not responding\n", uha->unit);
  407                 Debugger("ultra14f");
  408         }
  409         if ((inb(ur->sint) & 0x10) != 0) {
  410                 outb(ur->sint, ub->abort_ack);
  411                 splx(s);
  412                 return (1);
  413         } else {
  414                 outb(ur->sint, ub->abort_ack);
  415                 splx(s);
  416                 return (0);
  417         }
  418 }
  419 
  420 /*
  421  * Function to poll for command completion when in poll mode.
  422  *
  423  *      wait = timeout in msec
  424  */
  425 static int
  426 uha_poll(struct uha_data *uha, int wait)
  427 {
  428         struct  uha_reg *ur = uha->ur;
  429         struct  uha_bits *ub = uha->ub;
  430         int     stport = ur->sint;
  431 
  432         while (--wait) {
  433                 if (inb(stport) & ub->sintp)
  434                         break;
  435                 DELAY(1000);    /* 1 mSec per loop */
  436         }
  437         if (wait == 0) {
  438                 printf("uha%d: uha_poll, board is not responding\n", uha->unit);
  439                 return (EIO);
  440         }
  441         uhaintr(uha->unit);
  442         return (0);
  443 }
  444 
  445 /*
  446  * Check if the device can be found at the port given and if so, set it up
  447  * ready for further work as an argument, takes the isa_device structure
  448  * from autoconf.c
  449  */
  450 int
  451 uhaprobe(dev)
  452         struct isa_device *dev;
  453 {
  454         int     unit = uha_unit;
  455         struct uha_data *uha;
  456 
  457         dev->id_unit = unit;    /* XXX */
  458 
  459         /*
  460          * find unit and check we have that many defined
  461          */
  462         if (unit >= NUHA) {
  463                 printf("uha: unit number (%d) too high\n", unit);
  464                 return (0);
  465         }
  466         dev->id_unit = unit;
  467 
  468         /*
  469          * Allocate a storage area for us
  470          */
  471         if (uhadata[unit]) {
  472                 printf("uha%d: memory already allocated\n", unit);
  473                 return 0;
  474         }
  475         uha = malloc(sizeof(struct uha_data), M_TEMP, M_NOWAIT);
  476         if (!uha) {
  477                 printf("uha%d: cannot malloc!\n", unit);
  478                 return 0;
  479         }
  480         bzero(uha, sizeof(struct uha_data));
  481 
  482         uha->ur = malloc(sizeof(struct uha_reg), M_TEMP, M_NOWAIT);
  483         if (!uha->ur) {
  484                 printf("uha%d: cannot malloc!\n", unit);
  485                 return 0;
  486         }
  487         bzero(uha->ur, sizeof(struct uha_reg));
  488 
  489         uha->ub = malloc(sizeof(struct uha_bits), M_TEMP, M_NOWAIT);
  490         if (!uha->ub) {
  491                 printf("uha%d: cannot malloc!\n", unit);
  492                 return 0;
  493         }
  494         bzero(uha->ub, sizeof(struct uha_bits));
  495 
  496         uhadata[unit] = uha;
  497         uha->unit = unit;
  498         uha->baseport = dev->id_iobase;
  499         /*
  500          * Try initialise a unit at this location
  501          * sets up dma and bus speed, loads uha->vect
  502          */
  503         if (uha_init(uha) != 0 && uha24_init(uha) != 0) {
  504                 uhadata[unit] = NULL;
  505                 free(uha->ur, M_TEMP);
  506                 free(uha->ub, M_TEMP);
  507                 free(uha, M_TEMP);
  508                 return (0);
  509         }
  510         /* if it's there put in its interrupt and DRQ vectors */
  511         dev->id_irq = (1 << uha->vect);
  512         dev->id_drq = uha->dma;
  513         dev->id_iobase = uha->baseport;
  514 
  515         uha_unit++;
  516         return (16);
  517 }
  518 
  519 /*
  520  * Attach all the sub-devices we can find
  521  */
  522 int
  523 uha_attach(dev)
  524         struct isa_device *dev;
  525 {
  526         int     unit = dev->id_unit;
  527         struct uha_data *uha = uhadata[unit];
  528         struct scsibus_data *scbus;
  529 
  530         /*
  531          * fill in the prototype scsi_link.
  532          */
  533         uha->sc_link.adapter_unit = unit;
  534         uha->sc_link.adapter_targ = uha->our_id;
  535         uha->sc_link.adapter_softc = uha;
  536         uha->sc_link.adapter = &uha_switch;
  537         uha->sc_link.device = &uha_dev;
  538         uha->sc_link.flags = SDEV_BOUNCE;
  539 
  540         /*
  541          * Prepare the scsibus_data area for the upperlevel
  542          * scsi code.
  543          */
  544         scbus = scsi_alloc_bus();
  545         if(!scbus)
  546                 return 0;
  547         scbus->adapter_link = &uha->sc_link;
  548 
  549         /*
  550          * ask the adapter what subunits are present
  551          */
  552         scsi_attachdevs(scbus);
  553 
  554         return 1;
  555 }
  556 
  557 /*
  558  * Return some information to the caller about
  559  * the adapter and it's capabilities
  560  */
  561 u_int32_t
  562 uha_adapter_info(unit)
  563         int     unit;
  564 {
  565         return (2);             /* 2 outstanding requests at a time per device */
  566 }
  567 
  568 /*
  569  * Catch an interrupt from the adaptor
  570  */
  571 void
  572 uhaintr(unit)
  573         int unit;
  574 {
  575         struct uha_data *uha = uhadata[unit];
  576         struct mscp *mscp;
  577         u_char  uhastat;
  578         unsigned long int mboxval;
  579         struct uha_reg *ur;
  580         struct uha_bits *ub;
  581         int     port;
  582 
  583         ur = uha->ur;
  584         ub = uha->ub;
  585         port = uha->baseport;
  586 
  587 #ifdef  UHADEBUG
  588         printf("uhaintr ");
  589 #endif /*UHADEBUG */
  590 
  591         while ((uhastat = inb(ur->sint)) & ub->sintp) {
  592                 /*
  593                  * First get all the information and then
  594                  * acknowledge the interrupt
  595                  */
  596                 mboxval = inl(ur->icmptr);
  597                 outb(ur->sint, ub->icm_ack);
  598                 if (uha->flags & UHA_24F) outb(ur->icmcmd, 0);
  599 
  600 #ifdef  UHADEBUG
  601                 printf("status = 0x%x ", uhastat);
  602 #endif /*UHADEBUG*/
  603                 /*
  604                  * Process the completed operation
  605                  */
  606 
  607                 mscp = uha_mscp_phys_kv(uha, mboxval);
  608                 if (!mscp) {
  609                         printf("uha: BAD MSCP RETURNED\n");
  610                         return;         /* whatever it was, it'll timeout */
  611                 }
  612                 untimeout(uha_timeout, (caddr_t)mscp);
  613 
  614                 uha_done(uha, mscp);
  615         }
  616 }
  617 
  618 /*
  619  * We have a mscp which has been processed by the adaptor, now we look to see
  620  * how the operation went.
  621  */
  622 void
  623 uha_done(uha, mscp)
  624         struct  uha_data *uha;
  625         struct  mscp *mscp;
  626 {
  627         struct scsi_sense_data *s1, *s2;
  628         struct scsi_xfer *xs = mscp->xs;
  629 
  630         SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
  631         /*
  632          * Otherwise, put the results of the operation
  633          * into the xfer and call whoever started it
  634          */
  635         if (((mscp->ha_status != UHA_NO_ERR) || (mscp->targ_status != SCSI_OK))
  636          && ((xs->flags & SCSI_ERR_OK) == 0)) {
  637 
  638                 s1 = &(mscp->mscp_sense);
  639                 s2 = &(xs->sense);
  640 
  641                 if (mscp->ha_status != UHA_NO_ERR) {
  642                         switch (mscp->ha_status) {
  643                         case UHA_SBUS_ABORT_ERR:
  644                         case UHA_SBUS_TIMEOUT:          /* No sel response */
  645                                 SC_DEBUG(xs->sc_link, SDEV_DB3,
  646                                     ("abort or timeout; ha_status 0x%x\n",
  647                                         mscp->ha_status));
  648                                 xs->error = XS_TIMEOUT;
  649                                 break;
  650                         case UHA_SBUS_OVER_UNDER:
  651                                 SC_DEBUG(xs->sc_link, SDEV_DB3,
  652                                     ("scsi bus xfer over/underrun\n"));
  653                                 xs->error = XS_DRIVER_STUFFUP;
  654                                 break;
  655                         default:        /* Other scsi protocol messes */
  656                                 xs->error = XS_DRIVER_STUFFUP;
  657                                 printf("uha%d: unexpected ha_status 0x%x (target status 0x%x)\n",
  658                                         uha->unit, mscp->ha_status,
  659                                         mscp->targ_status);
  660                                 break;
  661                         }
  662                 } else {
  663                         /* Target status problem */
  664                         SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
  665                                 mscp->targ_status));
  666                         switch (mscp->targ_status) {
  667                         case 0x02:
  668                                 *s2 = *s1;
  669                                 xs->error = XS_SENSE;
  670                                 break;
  671                         case 0x08:
  672                                 xs->error = XS_BUSY;
  673                                 break;
  674                         default:
  675                                 printf("uha%d: unexpected targ_status 0x%x\n",
  676                                         uha->unit, mscp->targ_status);
  677                                 xs->error = XS_DRIVER_STUFFUP;
  678                                 break;
  679                         }
  680                 }
  681         }
  682         else {
  683                 /* All went correctly  OR  errors expected */
  684                 xs->resid = 0;
  685                 xs->error = 0;
  686         }
  687         xs->flags |= ITSDONE;
  688         uha_free_mscp(uha, mscp, xs->flags);
  689         scsi_done(xs);
  690 }
  691 
  692 /*
  693  * A mscp (and hence a mbx-out) is put onto the free list.
  694  */
  695 void
  696 uha_free_mscp(uha, mscp, flags)
  697         struct uha_data *uha;
  698         struct mscp *mscp;
  699         int flags;
  700 {
  701         unsigned int opri = 0;
  702 
  703         if (!(flags & SCSI_NOMASK))
  704                 opri = splbio();
  705 
  706         mscp->next = uha->free_mscp;
  707         uha->free_mscp = mscp;
  708         mscp->flags = MSCP_FREE;
  709         /*
  710          * If there were none, wake abybody waiting for
  711          * one to come free, starting with queued entries
  712          */
  713         if (!mscp->next) {
  714                 wakeup((caddr_t)&uha->free_mscp);
  715         }
  716         if (!(flags & SCSI_NOMASK))
  717                 splx(opri);
  718 }
  719 
  720 /*
  721  * Get a free mscp
  722  *
  723  * If there are none, see if we can allocate a new one.  If so, put it in the
  724  * hash table too otherwise either return an error or sleep.
  725  */
  726 static struct mscp *
  727 uha_get_mscp(uha, flags)
  728         struct  uha_data *uha;
  729         int     flags;
  730 {
  731         unsigned opri = 0;
  732         struct mscp *mscpp;
  733         int     hashnum;
  734 
  735         if (!(flags & SCSI_NOMASK))
  736                 opri = splbio();
  737         /*
  738          * If we can and have to, sleep waiting for one to come free
  739          * but only if we can't allocate a new one
  740          */
  741         while (!(mscpp = uha->free_mscp)) {
  742                 if (uha->nummscps < UHA_MSCP_MAX) {
  743                         if (mscpp = (struct mscp *)malloc(sizeof(struct mscp),
  744                             M_TEMP,
  745                             M_NOWAIT)) {
  746                                 bzero(mscpp, sizeof(struct mscp));
  747                                 uha->nummscps++;
  748                                 mscpp->flags = MSCP_ACTIVE;
  749                                 /*
  750                                  * put in the phystokv hash table
  751                                  * Never gets taken out.
  752                                  */
  753                                 mscpp->hashkey = KVTOPHYS(mscpp);
  754                                 hashnum = MSCP_HASH(mscpp->hashkey);
  755                                 mscpp->nexthash = uha->mscphash[hashnum];
  756                                 uha->mscphash[hashnum] = mscpp;
  757                         } else {
  758                                 printf("uha%d: Can't malloc MSCP\n", uha->unit);
  759                         }
  760                         goto gottit;
  761                 } else {
  762                         if (!(flags & SCSI_NOSLEEP)) {
  763                                 tsleep((caddr_t)&uha->free_mscp, PRIBIO,
  764                                        "uhamscp", 0);
  765                         }
  766                 }
  767         }
  768         if (mscpp) {
  769                 /* Get MSCP from from free list */
  770                 uha->free_mscp = mscpp->next;
  771                 mscpp->flags = MSCP_ACTIVE;
  772         }
  773       gottit:
  774         if (!(flags & SCSI_NOMASK))
  775                 splx(opri);
  776 
  777         return (mscpp);
  778 }
  779 
  780 /*
  781  * given a physical address, find the mscp that it corresponds to.
  782  */
  783 static struct mscp *
  784 uha_mscp_phys_kv(uha, mscp_phys)
  785         struct  uha_data *uha;
  786         long    int mscp_phys;
  787 {
  788         int     hashnum = MSCP_HASH(mscp_phys);
  789         struct mscp *mscpp = uha->mscphash[hashnum];
  790 
  791         while (mscpp) {
  792                 if (mscpp->hashkey == mscp_phys)
  793                         break;
  794                 mscpp = mscpp->nexthash;
  795         }
  796         return mscpp;
  797 }
  798 
  799 /*
  800  * Start the board, ready for normal operation
  801  */
  802 int
  803 uha_init(uha)
  804         struct  uha_data *uha;
  805 {
  806         volatile unsigned char model;
  807         volatile unsigned char submodel;
  808         unsigned char config_reg1;
  809         unsigned char config_reg2;
  810         unsigned char dma_ch;
  811         unsigned char irq_ch;
  812         unsigned char uha_id;
  813         int     port = uha->baseport;
  814         int     resetcount = 4000;      /* 4 secs? */
  815         struct uha_reg *ur = uha->ur;
  816         struct uha_bits *ub = uha->ub;
  817 
  818         /*
  819          *  Prepare to use a 14/34F.
  820          */
  821         ur->id          = port + 0x04;
  822         ur->type        = port + 0x00;          /* 24F only */
  823         ur->ectl        = port + 0x00;          /* 24F only */
  824         ur->config      = port + 0x06;          /* 0-1 for 14F */
  825         ur->lmask       = port + 0x00;
  826         ur->lint        = port + 0x01;
  827         ur->smask       = port + 0x02;
  828         ur->sint        = port + 0x03;
  829         ur->ogmcmd      = port + 0x00;          /* 24F only */
  830         ur->ogmptr      = port + 0x08;
  831         ur->icmcmd      = port + 0x00;          /* 24F only */
  832         ur->icmptr      = port + 0x0c;
  833 
  834         ub->ldip        = UHA_LDIP;
  835         ub->adrst       = UHA_ADRST;
  836         ub->sbrst       = UHA_SBRST;
  837         ub->asrst       = UHA_ASRST;
  838         ub->abort       = UHA_ABORT;
  839         ub->ogmint      = UHA_OGMINT;
  840         ub->sintp       = UHA_SINTP;
  841         ub->abort_succ  = UHA_ABORT_SUCC;
  842         ub->abort_fail  = UHA_ABORT_FAIL;
  843         ub->abort_ack   = UHA_ABORT_ACK;
  844         ub->icm_ack     = UHA_ICM_ACK;
  845 
  846         model = inb(ur->id);
  847         submodel = inb(ur->id + 1);
  848         if ((model != 0x56) & (submodel != 0x40)) return(ENXIO);
  849         printf("uha%d: reading board settings, ", uha->unit);
  850 
  851         config_reg1 = inb(ur->config);
  852         config_reg2 = inb(ur->config + 1);
  853         dma_ch = (config_reg1 & 0xc0);
  854         irq_ch = (config_reg1 & 0x30);
  855         uha_id = (config_reg2 & 0x07);
  856 
  857         switch (dma_ch) {
  858         case UHA_DMA_CH5:
  859                 uha->dma = 5;
  860                 printf("dma=5 ");
  861                 break;
  862         case UHA_DMA_CH6:
  863                 uha->dma = 6;
  864                 printf("dma=6 ");
  865                 break;
  866         case UHA_DMA_CH7:
  867                 uha->dma = 7;
  868                 printf("dma=7 ");
  869                 break;
  870         default:
  871                 printf("illegal dma jumper setting\n");
  872                 return (EIO);
  873         }
  874         switch (irq_ch) {
  875         case UHA_IRQ10:
  876                 uha->vect = 10;
  877                 printf("int=10 ");
  878                 break;
  879         case UHA_IRQ11:
  880                 uha->vect = 11;
  881                 printf("int=11 ");
  882                 break;
  883         case UHA_IRQ14:
  884                 uha->vect = 14;
  885                 printf("int=14 ");
  886                 break;
  887         case UHA_IRQ15:
  888                 uha->vect = 15;
  889                 printf("int=15 ");
  890                 break;
  891         default:
  892                 printf("illegal int jumper setting\n");
  893                 return (EIO);
  894         }
  895 
  896         /* who are we on the scsi bus */
  897         printf("id=%x\n", uha_id);
  898         uha->our_id = uha_id;
  899 
  900         /*
  901          * Note that we are going and return (to probe)
  902          */
  903         outb(ur->lint, ub->asrst);
  904         while (--resetcount) {
  905                 if (inb(ur->lint))
  906                         break;
  907                 DELAY(1000);    /* 1 mSec per loop */
  908         }
  909         if (resetcount == 0) {
  910                 printf("uha%d: board timed out during reset\n", uha->unit);
  911                 return (ENXIO);
  912         }
  913         outb(ur->smask, 0x81);          /* make sure interrupts are enabled */
  914         uha->flags |= UHA_INIT;
  915         return (0);
  916 }
  917 
  918 
  919 /*
  920  *  Initialize an Ultrastor 24F
  921  */
  922 int
  923 uha24_init(uha)
  924         struct uha_data *uha;
  925 {
  926   unsigned char p0, p1, p2, p3, p5, p7;
  927   unsigned char id[7], rev, haid;
  928   int port = 0, irq;
  929   int resetcount = 4000;
  930   struct uha_reg *ur = uha->ur;
  931   struct uha_bits *ub = uha->ub;
  932 
  933   /* Search for the 24F's product ID */
  934   uha_slot++;
  935   while (uha_slot < EISA_MAX_SLOTS) {
  936         /*
  937          *  Prepare to use a 24F.
  938          */
  939         port = EISA_CONFIG | (uha_slot << 12);
  940         ur->id          = port + 0x00;
  941         ur->type        = port + 0x02;
  942         ur->ectl        = port + 0x04;
  943         ur->config      = port + 0x05;          /* 0-2 for 24F */
  944         ur->lmask       = port + 0x0c;
  945         ur->lint        = port + 0x0d;
  946         ur->smask       = port + 0x0e;
  947         ur->sint        = port + 0x0f;
  948         ur->ogmcmd      = port + 0x16;
  949         ur->ogmptr      = port + 0x17;
  950         ur->icmcmd      = port + 0x1b;
  951         ur->icmptr      = port + 0x1c;
  952 
  953         ub->ldip        = U24_LDIP;
  954         ub->adrst       = U24_ADRST;
  955         ub->sbrst       = U24_SBRST;
  956         ub->asrst       = U24_ASRST;
  957         ub->abort       = U24_ABORT;
  958         ub->ogmint      = U24_OGMINT;
  959         ub->sintp       = U24_SINTP;
  960         ub->abort_succ  = U24_ABORT_SUCC;
  961         ub->abort_fail  = U24_ABORT_FAIL;
  962         ub->abort_ack   = U24_ABORT_ACK;
  963         ub->icm_ack     = U24_ICM_ACK;
  964 
  965         /*
  966          * Make sure an EISA card is installed in this slot,
  967          * and if it is make sure that the card is enabled.
  968          */
  969         outb(ur->id, 0xff);
  970         p0 = inb(ur->id);
  971         if ((p0 == 0xff) ||
  972             ((p0 & 0x80) != 0) ||
  973             ((inb(ur->ectl) & EISA_DISABLE) == 0)) {
  974                 uha_slot++;
  975                 continue;
  976         }
  977 
  978         /* Found an enabled card.  Grab the product ID. */
  979         p1 = inb(ur->id+1);
  980         p2 = inb(ur->type);
  981         p3 = inb(ur->type+1);
  982         id[0] = 0x40 + ((p0 >> 2) & 0x1f);
  983         id[1] = 0x40 + (((p0 & 0x03) << 3) | ((p1 >> 5) & 0x07));
  984         id[2] = 0x40 + (p1 & 0x1f);
  985         id[3] = hex2ascii((p2 >> 4) & 0x0f);
  986         id[4] = hex2ascii(p2 & 0x0f);
  987         id[5] = hex2ascii((p3 >> 4) & 0x0f);
  988         id[6] = '\0';
  989         rev = p3 & 0xf;
  990 
  991         /* We only want the 24F product ID. */
  992         if (!strcmp(id, "USC024")) break;
  993         uha_slot++;
  994   }
  995   if (uha_slot == EISA_MAX_SLOTS) return(ENODEV);
  996 
  997   /* We have the card!  Grab remaining config. */
  998   p5 = inb(ur->config);
  999   p7 = inb(ur->config+2);
 1000 
 1001   switch (p5 & 0xf0) {
 1002      case 0x10: irq = 15; break;
 1003      case 0x20: irq = 14; break;
 1004      case 0x40: irq = 11; break;
 1005      case 0x80: irq = 10; break;
 1006      default:
 1007         printf("uha%d: bad 24F irq\n", uha->unit);
 1008         return(ENXIO);
 1009   }
 1010 
 1011   haid = (p7 & 0x07);
 1012   printf("uha%d: UltraStor 24F int=%d id=%d\n", uha->unit, irq, haid);
 1013 
 1014   /* Issue SCSI and adapter reset */
 1015   outb(ur->lint, ub->asrst);
 1016   while (--resetcount) {
 1017         if (inb(ur->lint))
 1018                 break;
 1019         DELAY(1000);    /* 1 mSec per loop */
 1020   }
 1021   if (resetcount == 0) {
 1022         printf("uha%d: board timed out during reset\n", uha->unit);
 1023         return (ENXIO);
 1024   }
 1025   outb(ur->smask, 0xc2);        /* make sure interrupts are enabled */
 1026   uha->flags |= (UHA_INIT | UHA_24F);
 1027   uha->baseport = port;
 1028   uha->our_id = haid;
 1029   uha->vect = irq;
 1030   uha->dma = -1;
 1031   return(0);
 1032 }
 1033 
 1034 #ifndef min
 1035 #define min(x,y) (x < y ? x : y)
 1036 #endif  /* min */
 1037 
 1038 void
 1039 uhaminphys(bp)
 1040         struct buf *bp;
 1041 {
 1042         if (bp->b_bcount > ((UHA_NSEG - 1) * PAGESIZ)) {
 1043                 bp->b_bcount = ((UHA_NSEG - 1) * PAGESIZ);
 1044         }
 1045 }
 1046 
 1047 /*
 1048  * start a scsi operation given the command and the data address.  Also
 1049  * needs the unit, target and lu.
 1050  */
 1051 static int32_t
 1052 uha_scsi_cmd(xs)
 1053         struct scsi_xfer *xs;
 1054 {
 1055         struct  mscp *mscp;
 1056         struct  uha_dma_seg *sg;
 1057         int     seg;            /* scatter gather seg being worked on */
 1058         int     thiskv;
 1059         unsigned long int thisphys, nextphys;
 1060         int     bytes_this_seg, bytes_this_page, datalen, flags;
 1061         struct  uha_data *uha;
 1062         int     s;
 1063         unsigned long int templen;
 1064 
 1065         uha = (struct uha_data *)xs->sc_link->adapter_softc;
 1066         SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
 1067         /*
 1068          * get a mscp (mbox-out) to use. If the transfer
 1069          * is from a buf (possibly from interrupt time)
 1070          * then we can't allow it to sleep
 1071          */
 1072         flags = xs->flags;
 1073         if (xs->bp)
 1074                 flags |= (SCSI_NOSLEEP);        /* just to be sure */
 1075         if (flags & ITSDONE) {
 1076                 printf("uha%d: Already done?", uha->unit);
 1077                 xs->flags &= ~ITSDONE;
 1078         }
 1079         if (!(flags & INUSE)) {
 1080                 printf("uha%d: Not in use?", uha->unit);
 1081                 xs->flags |= INUSE;
 1082         }
 1083         if (!(mscp = uha_get_mscp(uha, flags))) {
 1084                 xs->error = XS_DRIVER_STUFFUP;
 1085                 return (TRY_AGAIN_LATER);
 1086         }
 1087         cheat = mscp;
 1088         SC_DEBUG(xs->sc_link, SDEV_DB3, ("start mscp(%p)\n", mscp));
 1089         mscp->xs = xs;
 1090 
 1091         /*
 1092          * Put all the arguments for the xfer in the mscp
 1093          */
 1094         if (flags & SCSI_RESET) {
 1095                 mscp->opcode = 0x04;
 1096                 mscp->ca = 0x01;
 1097         } else {
 1098                 mscp->opcode = 0x02;
 1099                 mscp->ca = 0x01;
 1100         }
 1101         if (flags & SCSI_DATA_IN) {
 1102                 mscp->xdir = 0x01;
 1103         }
 1104         if (flags & SCSI_DATA_OUT) {
 1105                 mscp->xdir = 0x02;
 1106         }
 1107 #ifdef  GOTTABEJOKING
 1108         if (xs->sc_link->lun != 0) {
 1109                 xs->error = XS_DRIVER_STUFFUP;
 1110                 uha_free_mscp(uha, mscp, flags);
 1111                 return (HAD_ERROR);
 1112         }
 1113 #endif
 1114         mscp->dcn = 0x00;
 1115         mscp->chan = 0x00;
 1116         mscp->target = xs->sc_link->target;
 1117         mscp->lun = xs->sc_link->lun;
 1118         mscp->link.addr[0] = 0x00;
 1119         mscp->link.addr[1] = 0x00;
 1120         mscp->link.addr[2] = 0x00;
 1121         mscp->link.addr[3] = 0x00;
 1122         mscp->link_id = 0x00;
 1123         mscp->cdblen = xs->cmdlen;
 1124         scratch = KVTOPHYS(&(mscp->mscp_sense));
 1125         mscp->sense.addr[0] = (scratch & 0xff);
 1126         mscp->sense.addr[1] = ((scratch >> 8) & 0xff);
 1127         mscp->sense.addr[2] = ((scratch >> 16) & 0xff);
 1128         mscp->sense.addr[3] = ((scratch >> 24) & 0xff);
 1129         mscp->senselen = sizeof(mscp->mscp_sense);
 1130         mscp->ha_status = 0x00;
 1131         mscp->targ_status = 0x00;
 1132 
 1133         if (xs->datalen) {      /* should use S/G only if not zero length */
 1134                 scratch = KVTOPHYS(mscp->uha_dma);
 1135                 mscp->data.addr[0] = (scratch & 0xff);
 1136                 mscp->data.addr[1] = ((scratch >> 8) & 0xff);
 1137                 mscp->data.addr[2] = ((scratch >> 16) & 0xff);
 1138                 mscp->data.addr[3] = ((scratch >> 24) & 0xff);
 1139                 sg = mscp->uha_dma;
 1140                 seg = 0;
 1141                 mscp->sgth = 0x01;
 1142 
 1143 #ifdef  TFS
 1144                 if (flags & SCSI_DATA_UIO) {
 1145                         iovp = ((struct uio *) xs->data)->uio_iov;
 1146                         datalen = ((struct uio *) xs->data)->uio_iovcnt;
 1147                         xs->datalen = 0;
 1148                         while ((datalen) && (seg < UHA_NSEG)) {
 1149                                 scratch = (unsigned long) iovp->iov_base;
 1150                                 sg->addr.addr[0] = (scratch & 0xff);
 1151                                 sg->addr.addr[1] = ((scratch >> 8) & 0xff);
 1152                                 sg->addr.addr[2] = ((scratch >> 16) & 0xff);
 1153                                 sg->addr.addr[3] = ((scratch >> 24) & 0xff);
 1154                                 xs->datalen += *(unsigned long *) sg->len.len = iovp->iov_len;
 1155                                 SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)",
 1156                                         iovp->iov_len,
 1157                                         iovp->iov_base));
 1158                                 sg++;
 1159                                 iovp++;
 1160                                 seg++;
 1161                                 datalen--;
 1162                         }
 1163                 } else
 1164 #endif /*TFS */
 1165                 {
 1166                         /*
 1167                          * Set up the scatter gather block
 1168                          */
 1169 
 1170                         SC_DEBUG(xs->sc_link, SDEV_DB4,
 1171                             ("%ld @%p:- ", xs->datalen, xs->data));
 1172                         datalen = xs->datalen;
 1173                         thiskv = (int) xs->data;
 1174                         thisphys = KVTOPHYS(thiskv);
 1175                         templen = 0;
 1176 
 1177                         while ((datalen) && (seg < UHA_NSEG)) {
 1178                                 bytes_this_seg = 0;
 1179 
 1180                                 /* put in the base address */
 1181                                 sg->addr.addr[0] = (thisphys & 0xff);
 1182                                 sg->addr.addr[1] = ((thisphys >> 8) & 0xff);
 1183                                 sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
 1184                                 sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
 1185 
 1186                                 SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%lx",
 1187                                         thisphys));
 1188 
 1189                                 /* do it at least once */
 1190                                 nextphys = thisphys;
 1191                                 while ((datalen) && (thisphys == nextphys))
 1192                                         /*
 1193                                          * This page is contiguous (physically) with
 1194                                          * the the last, just extend the length
 1195                                          */
 1196                                 {
 1197                                         /* how far to the end of the page */
 1198                                         nextphys = (thisphys & (~(PAGESIZ - 1)))
 1199                                             + PAGESIZ;
 1200                                         bytes_this_page = nextphys - thisphys;
 1201                                         /**** or the data ****/
 1202                                         bytes_this_page = min(bytes_this_page
 1203                                             ,datalen);
 1204                                         bytes_this_seg += bytes_this_page;
 1205                                         datalen -= bytes_this_page;
 1206 
 1207                                         /* get more ready for the next page */
 1208                                         thiskv = (thiskv & (~(PAGESIZ - 1)))
 1209                                             + PAGESIZ;
 1210                                         if (datalen)
 1211                                                 thisphys = KVTOPHYS(thiskv);
 1212                                 }
 1213                                 /*
 1214                                  * next page isn't contiguous, finish the seg
 1215                                  */
 1216                                 SC_DEBUGN(xs->sc_link, SDEV_DB4,
 1217                                     ("(0x%x)", bytes_this_seg));
 1218                                 sg->len.len[0] = (bytes_this_seg & 0xff);
 1219                                 sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
 1220                                 sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
 1221                                 sg->len.len[3] = ((bytes_this_seg >> 24) & 0xff);
 1222                                 templen += bytes_this_seg;
 1223                                 sg++;
 1224                                 seg++;
 1225                         }
 1226                 }
 1227 
 1228                 /* end of iov/kv decision */
 1229                 mscp->datalen.len[0] = (templen & 0xff);
 1230                 mscp->datalen.len[1] = ((templen >> 8) & 0xff);
 1231                 mscp->datalen.len[2] = ((templen >> 16) & 0xff);
 1232                 mscp->datalen.len[3] = ((templen >> 24) & 0xff);
 1233                 mscp->sg_num = seg;
 1234 
 1235                 SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
 1236                 if (datalen) {  /* there's still data, must have run out of segs! */
 1237                         printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n",
 1238                             uha->unit, UHA_NSEG);
 1239                         xs->error = XS_DRIVER_STUFFUP;
 1240                         uha_free_mscp(uha, mscp, flags);
 1241                         return (HAD_ERROR);
 1242                 }
 1243         } else {                /* No data xfer, use non S/G values */
 1244                 mscp->data.addr[0] = 0x00;
 1245                 mscp->data.addr[1] = 0x00;
 1246                 mscp->data.addr[2] = 0x00;
 1247                 mscp->data.addr[3] = 0x00;
 1248                 mscp->datalen.len[0] = 0x00;
 1249                 mscp->datalen.len[1] = 0x00;
 1250                 mscp->datalen.len[2] = 0x00;
 1251                 mscp->datalen.len[3] = 0x00;
 1252                 mscp->xdir = 0x03;
 1253                 mscp->sgth = 0x00;
 1254                 mscp->sg_num = 0x00;
 1255         }
 1256 
 1257         /*
 1258          * Put the scsi command in the mscp and start it
 1259          */
 1260         bcopy(xs->cmd, mscp->cdb, xs->cmdlen);
 1261 
 1262         /*
 1263          * Usually return SUCCESSFULLY QUEUED
 1264          */
 1265         if (!(flags & SCSI_NOMASK)) {
 1266                 s = splbio();
 1267                 uha_send_mbox(uha, mscp);
 1268                 timeout(uha_timeout, (caddr_t)mscp, (xs->timeout * hz) / 1000);
 1269                 splx(s);
 1270                 SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
 1271                 return (SUCCESSFULLY_QUEUED);
 1272         }
 1273 
 1274         /*
 1275          * If we can't use interrupts, poll on completion
 1276          */
 1277         uha_send_mbox(uha, mscp);
 1278         SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n"));
 1279         do {
 1280                 if (uha_poll(uha, xs->timeout)) {
 1281                         if (!(xs->flags & SCSI_SILENT))
 1282                                 printf("uha%d: cmd fail\n", uha->unit);
 1283                         if (!(uha_abort(uha, mscp))) {
 1284                                 printf("uha%d: abort failed in wait\n",
 1285                                         uha->unit);
 1286                                 uha_free_mscp(uha, mscp, flags);
 1287                         }
 1288                         xs->error = XS_DRIVER_STUFFUP;
 1289                         return (HAD_ERROR);
 1290                 }
 1291         }
 1292         while (!(xs->flags & ITSDONE)); /* something (?) else finished */
 1293         if (xs->error) {
 1294                 return (HAD_ERROR);
 1295         }
 1296         return (COMPLETE);
 1297 }
 1298 
 1299 static void
 1300 uha_timeout(arg1)
 1301         void    *arg1;
 1302 {
 1303         struct mscp *mscp = (struct mscp *)arg1;
 1304         struct uha_data *uha;
 1305         int     s = splbio();
 1306 
 1307         uha = (struct uha_data *)mscp->xs->sc_link->adapter_softc;
 1308         printf("uha%d:%d:%d (%s%d) timed out ", uha->unit
 1309             ,mscp->xs->sc_link->target
 1310             ,mscp->xs->sc_link->lun
 1311             ,mscp->xs->sc_link->device->name
 1312             ,mscp->xs->sc_link->dev_unit);
 1313 
 1314 #ifdef  UHADEBUG
 1315         uha_print_active_mscp(uha);
 1316 #endif /*UHADEBUG */
 1317 
 1318         if ((uha_abort(uha, mscp) != 1) || (mscp->flags = MSCP_ABORTED)) {
 1319                 printf("AGAIN");
 1320                 mscp->xs->retries = 0;  /* I MEAN IT ! */
 1321                 uha_done(uha, mscp);
 1322         } else {                /* abort the operation that has timed out */
 1323                 printf("\n");
 1324                 timeout(uha_timeout, (caddr_t)mscp, 2 * hz);
 1325                 mscp->flags = MSCP_ABORTED;
 1326         }
 1327         splx(s);
 1328 }
 1329 
 1330 #ifdef  UHADEBUG
 1331 void
 1332 uha_print_mscp(mscp)
 1333         struct mscp *mscp;
 1334 {
 1335         printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
 1336             ,mscp
 1337             ,mscp->opcode
 1338             ,mscp->cdblen
 1339             ,mscp->senselen);
 1340         printf("        sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
 1341             ,mscp->sgth
 1342             ,mscp->sg_num
 1343             ,mscp->datalen
 1344             ,mscp->ha_status
 1345             ,mscp->targ_status
 1346             ,mscp->flags);
 1347         show_scsi_cmd(mscp->xs);
 1348 }
 1349 
 1350 void
 1351 uha_print_active_mscp(struct uha_data *uha)
 1352 {
 1353         struct mscp *mscp;
 1354         int     i = 0;
 1355 
 1356         while (i < MSCP_HASH_SIZE) {
 1357                 mscp = uha->mscphash[i];
 1358                 while (mscp) {
 1359                         if (mscp->flags != MSCP_FREE) {
 1360                                 uha_print_mscp(mscp);
 1361                         }
 1362                         mscp = mscp->nexthash;
 1363                 }
 1364         i++;
 1365         }
 1366 }
 1367 #endif /*UHADEBUG */
 1368 #endif /*KERNEL */

Cache object: 0f78edf61b5563a737047c31a74df7d6


[ 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.