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/i386ipsc/sdintr.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  * Mach Operating System
    3  * Copyright (c) 1991 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * Copyright 1988, 1989, 1990, 1991 by Intel Corporation,
   28  * Santa Clara, California.
   29  * 
   30  *                          All Rights Reserved
   31  * 
   32  * Permission to use, copy, modify, and distribute this software and its
   33  * documentation for any purpose and without fee is hereby granted,
   34  * provided that the above copyright notice appears in all copies and that
   35  * both the copyright notice and this permission notice appear in
   36  * supporting documentation, and that the name of Intel not be used in
   37  * advertising or publicity pertaining to distribution of the software
   38  * without specific, written prior permission.
   39  * 
   40  * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
   41  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
   42  * SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
   43  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   44  * PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS
   45  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
   46  * THIS SOFTWARE.
   47  */
   48 /*
   49  * HISTORY
   50  * $Log:        sdintr.c,v $
   51  * Revision 2.4  91/07/01  08:24:24  jsb
   52  *      Replace "Wrong direction DATAOUT" assertion with printf.
   53  *      I seem to hit this a lot when running a STD+iPSC+NORMA+TEST kernel.
   54  *      [91/06/29  16:13:34  jsb]
   55  * 
   56  * Revision 2.3  91/06/18  20:50:37  jsb
   57  *      New copyright from Intel.
   58  *      [91/06/18  20:08:01  jsb]
   59  * 
   60  * Revision 2.2  90/12/04  14:47:48  jsb
   61  *      First checkin.
   62  *      [90/12/04  10:58:42  jsb]
   63  * 
   64  */ 
   65 /* 
   66  * sdintr.c Don Cameron September 1989
   67  *
   68  *    This is the bottom half of the SCSI disk driver for MACH on the iPSC/2.
   69  *    The code is a rewrite of scsiphase.c for NX on the iPSC/2 and portions
   70  *    of hd.c for MACH on the AT. 
   71  */
   72  
   73 #include <sys/types.h>
   74 #include <i386ipsc/scsi.h>
   75 #include <i386at/disk.h>
   76 
   77 #ifdef  MACH_KERNEL
   78 #include <i386/mach_param.h>
   79 #include <device/buf.h>
   80 #include <i386ipsc/sd.h>
   81 #include <device/errno.h>
   82 #else   MACH_KERNEL
   83 #include <i386ipsc/hz.h>
   84 #include <sys/ioctl.h>
   85 #include <sys/param.h>
   86 #include <sys/buf.h>
   87 #include <i386ipsc/sd.h>
   88 #include <sys/errno.h>
   89 #include <sys/user.h>
   90 #include <sys/vmparam.h>
   91 #include <sys/uio.h>
   92 #endif  MACH_KERNEL
   93 
   94 #define ONE_SECOND      (666000)        /* Best guess of one second delay */
   95 #ifdef MACH_KERNEL
   96 unsigned long   elapsed_ticks;                  /* Used to wait for a retry */
   97 #else MACH_KERNEL
   98 extern time_t lbolt;                    /* Used to wait for a retry */
   99 #endif MACH_KERNEL
  100 
  101 int target_id = -1;             /* Current active drive on SCSI bus */
  102 int command_waiting = 0;        /* Bit set of drives with pending commands */
  103 unsigned short  scsi_st;        /* SCSI controller status */
  104 unsigned char   scsi_ist;       /* SCSI controller interrupt status */
  105 unsigned char   scsi_msg;       /* Recent message byte */
  106 unsigned long   data_count;     /* Byte count for current transfer phase */
  107 unsigned long   read_fifo;      /* Byte count transferred from read fifo */
  108 unsigned long   write_fifo;     /* Byte count transferred to write fifo */
  109 
  110 int     step;                   /* Driver state */
  111 
  112 #define ASSERT(t,m) if (!(t)) panic(m)
  113 
  114 /* Variables defined in sd.c */
  115 extern struct hh        hh[NDRIVES];
  116 extern int              scanning;       /* In drive scan, timeouts OK */
  117 extern int              write_reserved; /* Write fifo lock variable */
  118 extern volatile caddr_t scsiphys0;
  119 extern volatile caddr_t scsiphys1;
  120 extern volatile caddr_t scsiphys2;
  121 extern volatile caddr_t scsiphys3;
  122 
  123 static int      fsi;                    /* Controller fifo save count */
  124 static unsigned char    fifo_save[16];          /* Controller fifo save area */
  125 
  126 typedef struct { unsigned char byte[2048]; } B2048;
  127 typedef struct { unsigned char byte[4096]; } B4096;
  128 
  129 static char priority[] = {              /* Priority array for drive selection */
  130         0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
  131         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  132         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  133         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  134         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  135         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  136         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  137         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  138         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  139         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  140         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  141         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  142         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  143         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  144         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  145         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
  146 };
  147 
  148 /* forward declarations */
  149 static void sendcmd();
  150 static void delay_one_second();
  151 
  152 static dbgbuf[128]; /* DFC DBG */
  153 
  154 /***************************************************************************
  155  *      
  156  *      Calling Sequence:
  157  *            sdintr();
  158  *      
  159  *      Description:
  160  *            Service SCSI interrupt.
  161  *      
  162  *      Parameters:
  163  *            none
  164  *      
  165  *      Returns:
  166  *            none
  167  *      
  168  */
  169 
  170 sdintr()
  171 {
  172         SCSI_SENSE sense;       /* Struct to read sense data into */
  173         struct hh *hh_p;
  174 
  175         if (target_id != -1)
  176                 hh_p = &hh[target_id];
  177 
  178         /*
  179          * Get status
  180          */
  181         scsi_st = SCSI_STATUS;
  182 
  183         /*
  184          * Check for major error
  185          */
  186 
  187         if ((scsi_st & ESP_GROSS_STAT) != 0) {
  188                 return;
  189         }
  190 
  191 
  192         /*
  193          * Test for SCSI controller interrupt
  194          */
  195 
  196         if ((scsi_st & SCSI_EINT_STAT) == 0) {
  197 
  198                 /* Read (and clear) interrupt status */
  199                 scsi_ist = SCSI_INT_STATUS;
  200 
  201                 /*
  202                  * If a data transfer was in progress,
  203                  * clean up FIFO and complete the transfer.
  204                  */
  205 
  206                 if (data_count != 0) {
  207                         int cnt;
  208 
  209                         /*
  210                          * Set cnt to the number of bytes transferred
  211                          * by the controller.  Read the transfer counter
  212                          * if necessary.
  213                          */
  214 
  215                         if ((scsi_st & ESP_COUNT_STAT) == 0) {
  216                                 unsigned short t;
  217 
  218                                 t = SCSI_COUNT_LO;
  219                                 shortdelay();
  220                                 t |= (unsigned short)(SCSI_COUNT_HI) << 8;
  221 
  222                                 cnt = data_count - t;
  223 
  224                         } else {
  225                                 cnt = data_count;
  226                         }
  227 
  228                         if (hh_p->direction == 1) {     /* Read */
  229                                 unsigned long *dp;
  230 
  231                                 /*
  232                                  * Take all remaining bytes from
  233                                  * the read FIFO.
  234                                  */
  235 
  236                                 cnt -= read_fifo;
  237                                 dp = (unsigned long *)hh_p->rw_addr;
  238                                 hh_p->transfer_length -= cnt;
  239                                 if (hh_p->buf_io) {
  240                                         hh_p->buflst.b_actf->b_resid -= cnt;
  241                                 }
  242                                 hh_p->rw_addr += cnt;
  243 
  244                                 /*
  245                                  * Transfer the data
  246                                  */
  247 
  248                                 if (cnt >= 4096) {
  249                                         *(B4096 *)dp = *(B4096 *)(SCSI_FIFO);
  250                                         (char *) dp += 4096;
  251                                         cnt -= 4096;
  252                                 }
  253                                 if (cnt >= 2048) {
  254                                         *(B2048 *)dp = *(B2048 *)(SCSI_FIFO);
  255                                         (char *) dp += 2048;
  256                                         cnt -= 2048;
  257                                 }
  258                                 for (; cnt > 0; cnt -= 4) {
  259                                         *dp++ = *(unsigned long *)(SCSI_FIFO);
  260                                 }
  261 
  262                                 read_fifo = 0;
  263 
  264                         } else {                /* Write */
  265 
  266                                 /*
  267                                  * Save the SCSI controller FIFO in fifo_save
  268                                  */
  269 
  270                                 fsi = SCSI_FIFO_FLAGS;
  271                                 if (fsi != 0) {
  272                                         int i;
  273 
  274                                         for (i = 0; i < fsi; i++)
  275                                                 fifo_save[i] = SCSI_ESP_FIFO;
  276                                 }
  277 
  278                                 /*
  279                                  * Adjust write_fifo to reflect the amount
  280                                  * of data remaining in the write FIFO
  281                                  */
  282 
  283                                 write_fifo -= cnt;
  284                         }
  285                         data_count = 0;
  286                 }
  287 
  288                 /*
  289                  * Check for special kinds of interrupts
  290                  */
  291 
  292                 if (scsi_ist & ESP_ILLCMD_INT) {
  293 
  294                         if (step == RSEL_STEP) {
  295                                 time_t t;
  296 
  297                                 /*
  298                                  * Illegal command interrupt comes from
  299                                  * select command executing after
  300                                  * reselection occurs.  The reselection
  301                                  * interrupt has already been processed
  302                                  * and a ESP_MSGACCEPT command queued.
  303                                  *                      
  304                                  * Give the ESP 5 ms to respond to the
  305                                  * ESP_MSGACCEPT command.  If it does, go on;
  306                                  * otherwise reissue the command.
  307                                  *
  308                                  * NB: Trying to wait for 5ms under UNIX is 
  309                                  *     a joke of course, because the clock
  310                                  *     ticks occur in increments like 10ms
  311                                  *     and we need to wait for two clicks
  312                                  *     because the first one may not have 
  313                                  *     been a whole one.
  314                                  */
  315 #ifdef MACH_KERNEL
  316                                 t = elapsed_ticks + MIN(2, HZ/200);
  317 #else MACH_KERNEL
  318                                 t = lbolt + MIN(2, HZ/200);
  319 #endif MACH_KERNEL
  320                                 do {
  321                                         scsi_st = SCSI_STATUS;
  322                                 } while ((scsi_st & SCSI_EINT_STAT) != 0 &&
  323 #ifdef MACH_KERNEL
  324                                          elapsed_ticks < t);
  325 #else MACH_KERNEL
  326                                          lbolt < t);
  327 #endif MACH_KERNEL
  328                                 if ((scsi_st & SCSI_EINT_STAT) != 0) {
  329                                         SCSI_COMMAND = ESP_MSGACCEPT;
  330                                 }
  331                                 goto exitint;
  332                         }
  333 
  334 
  335                 } else if (scsi_ist & ESP_RESET_INT) {
  336                         /*
  337                          * Ignore SCSI bus reset
  338                          */
  339 
  340                         goto exitint;
  341 
  342                 } else if (scsi_ist & ESP_RESEL_INT) {
  343                         unsigned char   id;
  344 
  345                         /*
  346                          * Controller has been reselected by a drive
  347                          */
  348 
  349                         if (step == CMD_STEP) {
  350 
  351                                 /*
  352                                  * Reselection overrides a command
  353                                  * being sent to another drive.
  354                                  * Set command_waiting flag for the other drive.
  355                                  */
  356 
  357                                 command_waiting |= 1 << target_id;
  358                                 step = NULL_STEP;
  359                                 target_id = -1;
  360                         }
  361 
  362                         /*
  363                          * Get ID and message bytes from controller FIFO
  364                          */
  365 
  366                         id = SCSI_ESP_FIFO;
  367                         scsi_msg = SCSI_ESP_FIFO;
  368                         shortdelay();
  369                         if (SCSI_FIFO_FLAGS != 0) {
  370                                 /*
  371                                  * The FIFO had some bytes in it from a
  372                                  * command that was being sent to
  373                                  * another drive
  374                                  */
  375 
  376                                 SCSI_COMMAND = ESP_FLUSH_FIFO;
  377                         }
  378 
  379                         /*
  380                          * Decode drive number from id byte
  381                          * and accept reselection message
  382                          */
  383 
  384                         for (target_id = 0;
  385                              (id & (1 << target_id)) == 0;
  386                              target_id++);
  387 
  388                         SCSI_COMMAND = ESP_MSGACCEPT;
  389                         step = RSEL_STEP;
  390                         goto exitint;
  391 
  392                 } else if (scsi_ist & ESP_DISC_INT) {
  393                         int     drive, st;
  394 
  395                         /*
  396                          * The current target drive has disconnected
  397                          */
  398 
  399                         drive = target_id;
  400                         target_id = -1;
  401 
  402                         st = step;
  403                         step = NULL_STEP;
  404 
  405                         if (st == DONE_STEP) {
  406 
  407                                 /*
  408                                  * Current operation is complete.
  409                                  * Check for error status.
  410                                  */
  411 
  412                                 if (hh_p->cmd_st == CMD_ST_CHECK) {
  413                                         /*
  414                                          * Send request sense command
  415                                          */
  416 
  417                                         bzero(hh_p->cmd, 6);
  418                                         hh_p->cmd_len = 6;
  419                                         hh_p->cmd[0] = SCSI_SENSE_CMD;
  420                                         hh_p->cmd[4] = sizeof(SCSI_SENSE);
  421                                         hh_p->transfer_length = sizeof(SCSI_SENSE);
  422                                         hh_p->rw_addr = (paddr_t)&sense;
  423                                         hh_p->buf_io = 0;
  424                                         hh_p->direction = 1;
  425                                         command_waiting |= 1 << drive;
  426                                 } else if (hh_p->buf_io) {
  427                                         struct buf *bp;
  428 
  429                                         bp = hh_p->buflst.b_actf;
  430                                         if (bp->b_resid != 0) {
  431                                                 sdrestart();
  432                                         }
  433                                         else {
  434                                                 hh_p->cmd_busy = 0;
  435                                                 hh_p->buflst.b_actf =
  436                                                         bp->av_forw;
  437                                                 biodone(bp);
  438                                                 sdstart();
  439                                                 wakeup(&hh_p->cmd_busy);
  440                                         }
  441                                 } else {
  442                                         hh_p->cmd_busy = 0;
  443                                         wakeup(&hh_p->cmd_busy);
  444                                 }
  445 
  446                         } else if (st != DISC_STEP) {
  447 
  448                                 /*
  449                                  * If disconnect was unexpected, set
  450                                  * timeout status
  451                                  */
  452 
  453                                 hh_p->cmd_st = CMD_ST_TIMEOUT;
  454                                 hh_p->cmd_busy = 0;
  455                                 SCSI_COMMAND = ESP_FLUSH_FIFO;
  456                                 shortdelay();
  457                                 SCSI_COMMAND = ESP_ENABLE_SEL;
  458                                 ASSERT(scanning, "Unexpected disconnect");
  459                                 wakeup(&hh_p->cmd_busy);
  460                                 goto exitint;
  461                         }
  462 
  463                         /*
  464                          * Enable reselection by any drive
  465                          */
  466 
  467                         SCSI_COMMAND = ESP_ENABLE_SEL;
  468 
  469                         /*
  470                          * If there are commands waiting, attempt to
  471                          * send one now while the bus is available
  472                          */
  473 
  474                         if (command_waiting != 0) {
  475                                 sendcmd(priority[command_waiting], 1);
  476                         }
  477                         goto exitint;
  478                 }
  479 
  480                 /*
  481                  * The distinction of CMD_STEP and RSEL_STEP is
  482                  * not important at this stage
  483                  */
  484 
  485                 if (step == CMD_STEP || step == RSEL_STEP) {
  486                         step = NULL_STEP;
  487                 }
  488 
  489                 /*
  490                  * Switch according to the bus phase asserted by the drive
  491                  */
  492 
  493                 switch (scsi_st & ESP_PHASE_STAT) {
  494 
  495                 case ESP_COMMAND_PH:
  496                         ASSERT(0, "Unexpected SCSI phase");
  497 
  498                 case ESP_MSGIN_PH:
  499                         if (step == NULL_STEP) {
  500                                 ASSERT(SCSI_FIFO_FLAGS == 0,
  501                                         "ESP FIFO not clear in MSGIN");
  502 
  503                                 /* Initiate transfer of a message byte */
  504                                 SCSI_COMMAND = ESP_TRANSFER;
  505                                 step = MSG_STEP;
  506 
  507                         } else if (step == MSG_STEP) {
  508                                 unsigned char msg;
  509 
  510                                 step = NULL_STEP;
  511 
  512                                 /*
  513                                  * Obtain a message byte
  514                                  */
  515 
  516                                 msg = SCSI_ESP_FIFO;
  517                                 shortdelay();
  518 
  519                                 /*
  520                                  * Accept the message
  521                                  */
  522 
  523                                 SCSI_COMMAND = ESP_MSGACCEPT;
  524 
  525                                 /*
  526                                  * Switch based on the message contents
  527                                  */
  528 
  529                                 switch(msg) {
  530 
  531                                 case MSG_SAVE_DP:
  532                                         break;  /* Ignore */
  533 
  534                                 case MSG_REST_DP:
  535                                         break;  /* Ignore */
  536 
  537                                 case MSG_DISCONNECT:
  538                                         /* Expect disconnect interrupt */
  539                                         step = DISC_STEP;
  540                                         break;
  541 
  542                                 case MSG_REJECT:
  543                                         ASSERT(0, "Message rejected");
  544 
  545                                 case MSG_NOP:
  546                                         break;  /* Ignore */
  547 
  548                                 default:
  549                                         ASSERT(0, "Invalid message in");
  550                                 }
  551 
  552                         } else /* step == STATUS_STEP */ {
  553                                 unsigned long t;
  554 
  555                                 /*
  556                                  * Obtain status and message bytes
  557                                  */
  558 
  559                                 t = *(unsigned long *)(SCSI_FIFO);
  560 
  561                                 hh_p->cmd_st = t;
  562                                 hh_p->cmd_msg = t >> 8;
  563 
  564                                 /*
  565                                  * Accept message and expect command
  566                                  * completion disconnect
  567                                  */
  568 
  569                                 SCSI_COMMAND = ESP_MSGACCEPT;
  570                                 step = DONE_STEP;
  571 
  572                                 /*
  573                                  * If write command completed, release
  574                                  * write FIFO lock
  575                                  */
  576 
  577                                 if (hh_p->cmd[0] == SCSI_WRITE_CMD) {
  578                                         write_reserved = 0;
  579                                 }
  580 
  581                         }
  582                         break;
  583 
  584                 case ESP_MSGOUT_PH:
  585                         ASSERT(0, "Unexpected phase MSGOUT");
  586                         break;
  587 
  588                 case ESP_DATAOUT_PH:
  589                         if (hh_p->direction != 0) {
  590                                 printf("sd%d: false interrupt\n", target_id);
  591                                 return;
  592                         }
  593 
  594                         /*
  595                          * Set up write transfer
  596                          */
  597 
  598                         set_fifo_write();
  599                         data_count = hh_p->transfer_length + write_fifo;
  600 
  601                         SCSI_COUNT_LO = data_count;
  602                         shortdelay();
  603                         SCSI_COUNT_HI = data_count >> 8;
  604 
  605                         /*
  606                          * Replace data in the controller FIFO from
  607                          * a previous transfer phase
  608                          */
  609 
  610                         if (fsi != 0) {
  611                                 int     i;
  612 
  613                                 for (i = 0; i < fsi; i++)
  614                                         SCSI_ESP_FIFO = fifo_save[i];
  615                                 fsi = 0;
  616                         }
  617 
  618                         /*
  619                          * Start filling the write FIFO if there is room in it
  620                          */
  621 
  622                         if ((scsi_st & SCSI_WHF_STAT) == 0) {
  623                                 unsigned long *dp;
  624                                 unsigned long cnt;
  625 
  626                                 cnt = hh_p->transfer_length;
  627                                 if (cnt > 4096)
  628                                         cnt = 4096;
  629                                 if (cnt > 2048 &&
  630                                     (scsi_st & SCSI_WEF_STAT) != 0)
  631                                         cnt = 2048;
  632 
  633                                 dp = (unsigned long *)(hh_p->rw_addr);
  634                                 hh_p->transfer_length -= cnt;
  635                                 if (hh_p->buf_io) {
  636                                         hh_p->buflst.b_actf->b_resid -= cnt;
  637                                 }
  638                                 hh_p->rw_addr += cnt;
  639                                 write_fifo += cnt;
  640 
  641                                 if (cnt == 4096) {
  642                                         *(B4096 *)(SCSI_FIFO) = *(B4096 *)dp;
  643 
  644                                 } else {
  645                                         if (cnt >= 2048) {
  646                                                 *(B2048 *)(SCSI_FIFO) = *(B2048 *)dp;
  647                                                 (char *) dp += 2048;
  648                                                 cnt -= 2048;
  649                                         }
  650                                         for (; cnt > 0; cnt -= 4) {
  651                                                 *(unsigned long *)(SCSI_FIFO) = *dp++;
  652                                         }
  653                                 }
  654                         }
  655 
  656                         /*
  657                          * Issue transfer command.  Early versions
  658                          * of controller chip require NOP before
  659                          * transfer.
  660                          */
  661 
  662                         shortdelay();
  663                         SCSI_COMMAND = ESP_NOP;
  664                         shortdelay();
  665                         SCSI_COMMAND = ESP_TRANSFER | ESP_DMA;
  666                         break;
  667 
  668                 case ESP_DATAIN_PH:
  669                         ASSERT(hh_p->direction == 1,
  670                                 "Wrong direction DATAIN");
  671 
  672                         /*
  673                          * Set up read transfer
  674                          */
  675 
  676                         set_fifo_read();
  677                         data_count = hh_p->transfer_length;
  678                         SCSI_COUNT_LO = data_count;
  679                         shortdelay();
  680                         SCSI_COUNT_HI = data_count >> 8;
  681 
  682                         /*
  683                          * Issue transfer command.  Early versions
  684                          * of controller chip require NOP before
  685                          * transfer.
  686                          */
  687 
  688                         shortdelay();
  689                         SCSI_COMMAND = ESP_NOP;
  690                         shortdelay();
  691                         SCSI_COMMAND = ESP_TRANSFER | ESP_DMA;
  692                         break;
  693 
  694                 case ESP_STATUS_PH:
  695 
  696                         /*
  697                          * Set up controller to DMA status and message
  698                          * bytes into the read FIFO.  This saves an
  699                          * interrupt compared with using the controller FIFO.
  700                          */
  701 
  702                         set_fifo_read();
  703                         SCSI_COUNT_LO = 2;
  704                         shortdelay();
  705                         SCSI_COUNT_HI = 0;
  706                         shortdelay();
  707                         SCSI_COMMAND = ESP_COMPLETE | ESP_DMA;
  708                         step = STATUS_STEP;
  709                         break;
  710                 }
  711 
  712         }
  713 
  714 exitint:
  715         ;
  716 }
  717 
  718 /***************************************************************************
  719  *      Calling Sequence:
  720  *            sendcmd(drive);
  721  *      
  722  *      Description:
  723  *            Send command to selected drive.
  724  *      
  725  *      Parameters:
  726  *            drive             Drive index.
  727  *      
  728  *      Returns:
  729  *            none
  730  *      
  731  */
  732 
  733 static void sendcmd(drive)
  734         int     drive;
  735 {
  736         int     i;
  737         struct hh *hh_p;
  738 
  739         hh_p = &hh[drive];
  740         if (hh_p->cmd[0] == SCSI_WRITE_CMD) {
  741                 write_reserved = 1;
  742         }
  743         hh_p->cmd_busy = 1;
  744         if (target_id == -1) {
  745                 data_count = 0;
  746                 command_waiting &= ~(1 << drive);
  747                 step = CMD_STEP;
  748                 target_id = drive;
  749 
  750 
  751                 SCSI_ESP_FIFO = MSG_IDENTIFY;
  752                 shortdelay();
  753                 SCSI_ID = target_id;
  754                 for (i = 0; i < hh_p->cmd_len; i++) {
  755                         SCSI_ESP_FIFO = hh_p->cmd[i];
  756                 }
  757                 SCSI_COMMAND = ESP_SELATN;
  758         } else {
  759                 command_waiting |= 1 << drive;
  760 
  761         }
  762 }
  763 
  764 /***************************************************************************
  765  *      
  766  *      Calling Sequence:
  767  *            reset_controller();
  768  *      
  769  *      Description:
  770  *            Reset ESP.
  771  *      
  772  *      Parameters:
  773  *            none
  774  */
  775 
  776 reset_controller()
  777 {
  778         int     tmp;    /* dummy var to force read of SCSI chip */
  779 
  780         /*
  781          * Initialize operating globals
  782          */
  783 
  784         target_id = -1;
  785         write_reserved = 0;
  786         command_waiting = 0;
  787 
  788         tmp = SCSI_RESET_ESP;
  789         shortdelay();
  790         tmp = SCSI_RESET_FIFO;
  791         shortdelay();
  792         write_fifo = SCSI_CLEAR_CNT;
  793         shortdelay();
  794         set_fifo_read();
  795         shortdelay();
  796 
  797         data_count = 0;
  798         SCSI_COMMAND = ESP_RESET_CHIP;
  799         shortdelay();
  800         SCSI_COMMAND = ESP_NOP;
  801         shortdelay();
  802 
  803         SCSI_CLOCK = 5;
  804         shortdelay();
  805         SCSI_CONFIG = 0x97;
  806         shortdelay();
  807         SCSI_TIMEOUT = 0x93;
  808         shortdelay();
  809         SCSI_SYNC_PER = 0x05;
  810         shortdelay();
  811         SCSI_SYNC_OFF = 0x00;
  812         shortdelay();
  813 
  814         data_count = 0;
  815         read_fifo = 0;
  816         write_fifo = 0;
  817         fsi = 0;
  818 }
  819 
  820 /***************************************************************************
  821  *      
  822  *      Calling Sequence:
  823  *            reset_bus();
  824  *      
  825  *      Description:
  826  *            Reset SCSI bus.
  827  *      
  828  *      Parameters:
  829  *            none
  830  *      
  831  *      Returns:
  832  *            none
  833  *      
  834  */
  835 
  836 reset_bus()
  837 {
  838         data_count = 0;
  839         SCSI_COMMAND = ESP_RESET_BUS;
  840 
  841         delay_one_second();
  842 
  843         scsi_st = SCSI_STATUS;
  844         shortdelay();
  845         scsi_ist = SCSI_INT_STATUS;
  846 }
  847 
  848 /***************************************************************************
  849  *      
  850  *      Calling Sequence:
  851  *            shortdelay();
  852  *      
  853  *      Description:
  854  *            Short delay for ESP.
  855  *      
  856  *      Parameters:
  857  *            none
  858  *      
  859  *      Returns:
  860  *            none
  861  */
  862 
  863 
  864 #define SHORTDELAY 10
  865 
  866 shortdelay()
  867 {
  868         volatile unsigned long  t;
  869 
  870         for (t = SHORTDELAY; t; t--);
  871 }
  872 
  873 /***************************************************************************
  874  *      
  875  *      Calling Sequence:
  876  *            set_fifo_read();
  877  *      
  878  *      Description:
  879  *            Put SCSI controller FIFO's in read mode.
  880  *      
  881  *      Parameters:
  882  *            none
  883  *      
  884  *      Returns:
  885  *            none
  886  *      
  887  */
  888 
  889 
  890 set_fifo_read()
  891 {
  892 
  893         SCSI_READ_MODE = SCSI_CLEAR_CNT;
  894 }
  895 
  896 /***************************************************************************
  897  *      
  898  *      Calling Sequence:
  899  *            set_fifo_write();
  900  *      
  901  *      Description:
  902  *            Put SCSI controller FIFO's in write mode.
  903  *      
  904  *      Parameters:
  905  *            none
  906  *      
  907  *      Returns:
  908  *            none
  909  *      
  910  */
  911 
  912 set_fifo_write()
  913 {
  914 
  915         SCSI_WRITE_MODE = SCSI_CLEAR_CNT;
  916 }
  917 
  918 /***************************************************************************
  919  *      
  920  *      Calling Sequence:
  921  *            reverse_long(p);
  922  *      
  923  *      Description:
  924  *            Reverse the bytes of a long.
  925  *      
  926  *      Parameters:
  927  *            p:        Pointer to a long.
  928  *      
  929  *      Returns:
  930  *            Side effect in *p.
  931  *      
  932  */
  933 
  934 reverse_long(p)
  935         unsigned char *p;
  936 {
  937         unsigned char   t;
  938 
  939         t = p[0];
  940         p[0] = p[3];
  941         p[3] = t;
  942 
  943         t = p[1];
  944         p[1] = p[2];
  945         p[2] = t;
  946 }
  947 
  948 /*
  949  * delay_one_second 
  950  *      Delay for one second.
  951  */
  952 static void delay_one_second()
  953 {
  954         long time;
  955         /* Have to brute force this */
  956         time = ONE_SECOND;
  957         while (time--);
  958 }

Cache object: 3dd7c41103abcbd0394e0287d4c9238c


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