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/scsi/rz_cpu.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,1990 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  * HISTORY
   28  * $Log:        rz_cpu.c,v $
   29  * Revision 2.9  93/05/15  19:43:23  mrt
   30  *      machparam.h -> machspl.h
   31  * 
   32  * Revision 2.8  93/02/01  09:55:39  danner
   33  *      Removed unused variable 'tgt' from sccpu_act_as_target().
   34  *      [93/01/25            jfriedl]
   35  * 
   36  * Revision 2.7  93/01/14  17:55:15  danner
   37  *      Some more code, good enough for experimenting.
   38  *      [92/12/10  20:22:19  af]
   39  * 
   40  * Revision 2.6  92/08/03  17:53:22  jfriedl
   41  *      removed silly prototypes
   42  *      [92/08/02            jfriedl]
   43  * 
   44  * Revision 2.5  92/05/21  17:23:22  jfriedl
   45  *      Cleanup to quiet gcc warnings.
   46  *      [92/05/16            jfriedl]
   47  * 
   48  * Revision 2.4  92/04/06  23:22:56  rpd
   49  *      On bad errors, be loquacious and decode all sense data.
   50  *      Do not retry IO_INTERNAL operations, cuz we donno what it is.
   51  *      [92/04/06            af]
   52  * 
   53  * Revision 2.3  92/02/23  22:44:15  elf
   54  *      Changed the interface of a number of functions not to
   55  *      require the scsi_softc pointer any longer.  It was
   56  *      mostly unused, now it can be found via tgt->masterno.
   57  *      [92/02/22  19:30:48  af]
   58  * 
   59  * Revision 2.2  91/08/24  12:27:47  af
   60  *      Created.
   61  *      [91/08/02  03:52:11  af]
   62  * 
   63  */
   64 /*
   65  *      File: rz_cpu.c
   66  *      Author: Alessandro Forin, Carnegie Mellon University
   67  *      Date:   7/91
   68  *
   69  *      Top layer of the SCSI driver: interface with the MI.
   70  *      This file contains operations specific to CPU-like devices.
   71  *
   72  * We handle here the case of simple devices which do not use any
   73  * sophisticated host-to-host communication protocol, they look
   74  * very much like degenerative cases of TAPE devices.
   75  *
   76  * For documentation and debugging, we also provide code to act like one.
   77  */
   78 
   79 #include <mach/std_types.h>
   80 #include <scsi/compat_30.h>
   81 
   82 #include <scsi/scsi.h>
   83 #include <scsi/scsi_defs.h>
   84 #include <scsi/rz.h>
   85 
   86 
   87 
   88 void sccpu_act_as_target(); /* forwards */
   89 void sccpu_start();
   90 
   91 /*
   92  * This function decides which 'protocol' we well speak
   93  * to a cpu target. For now the decision is left to a
   94  * global var. XXXXXXX
   95  */
   96 extern scsi_devsw_t scsi_host;
   97 scsi_devsw_t    *scsi_cpu_protocol = /* later &scsi_host*/
   98                         &scsi_devsw[SCSI_CPU];
   99 
  100 void sccpu_new_initiator(self, initiator)
  101         target_info_t   *self, *initiator;
  102 {
  103         initiator->dev_ops = scsi_cpu_protocol;
  104         if (initiator == self) {
  105                 self->flags = TGT_DID_SYNCH|TGT_FULLY_PROBED|TGT_ONLINE|
  106                              TGT_ALIVE|TGT_US;
  107                 self->dev_info.cpu.req_pending = FALSE;
  108         } else {
  109                 initiator->flags = TGT_ONLINE|TGT_ALIVE;
  110                 initiator->dev_info.cpu.req_pending = TRUE;
  111         }
  112 }
  113 
  114 void sccpu_strategy(ior)
  115         register io_req_t       ior;
  116 {
  117         void                    sccpu_start();
  118 
  119         rz_simpleq_strategy(ior, sccpu_start);
  120 }
  121 
  122 void sccpu_start(tgt, done)
  123         target_info_t   *tgt;
  124         boolean_t       done;
  125 {
  126         io_req_t                head, ior;
  127         scsi_ret_t              ret;
  128 
  129         /* this is to the doc & debug code mentioned in the beginning */
  130         if (!done && tgt->dev_info.cpu.req_pending) {
  131                 sccpu_act_as_target( tgt);
  132                 return;
  133         }
  134 
  135         ior = tgt->ior;
  136         if (ior == 0)
  137                 return;
  138 
  139         if (done) {
  140 
  141                 /* see if we must retry */
  142                 if ((tgt->done == SCSI_RET_RETRY) &&
  143                     ((ior->io_op & IO_INTERNAL) == 0)) {
  144                         delay(1000000);/*XXX*/
  145                         goto start;
  146                 } else
  147                 /* got a bus reset ? shouldn't matter */
  148                 if ((tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) &&
  149                     ((ior->io_op & IO_INTERNAL) == 0)) {
  150                         goto start;
  151                 } else
  152 
  153                 /* check completion status */
  154 
  155                 if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
  156                         scsi_sense_data_t *sns;
  157 
  158                         ior->io_op = ior->io_temporary;
  159                         ior->io_error = D_IO_ERROR;
  160                         ior->io_op |= IO_ERROR;
  161 
  162                         sns = (scsi_sense_data_t *)tgt->cmd_ptr;
  163                         if (scsi_debug)
  164                                 scsi_print_sense_data(sns);
  165 
  166                         if (scsi_check_sense_data(tgt, sns)) {
  167                             if (sns->u.xtended.ili) {
  168                                 if (ior->io_op & IO_READ) {
  169                                     int residue;
  170 
  171                                     residue =   sns->u.xtended.info0 << 24 |
  172                                                 sns->u.xtended.info1 << 16 |
  173                                                 sns->u.xtended.info2 <<  8 |
  174                                                 sns->u.xtended.info3;
  175                                     if (scsi_debug)
  176                                         printf("Cpu Short Read (%d)\n", residue);
  177                                     /*
  178                                      * NOTE: residue == requested - actual
  179                                      * We only care if > 0
  180                                      */
  181                                     if (residue < 0) residue = 0;/* sanity */
  182                                     ior->io_residual += residue;
  183                                     ior->io_error = 0;
  184                                     ior->io_op &= ~IO_ERROR;
  185                                     /* goto ok */
  186                                 }
  187                             }
  188                         }
  189                 }
  190 
  191                 else if (tgt->done != SCSI_RET_SUCCESS) {
  192 
  193                     if (tgt->done == SCSI_RET_NEED_SENSE) {
  194 
  195                         ior->io_temporary = ior->io_op;
  196                         ior->io_op = IO_INTERNAL;
  197                         if (scsi_debug)
  198                                 printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count);
  199                         scsi_request_sense(tgt, ior, 0);
  200                         return;
  201 
  202                     } else if (tgt->done == SCSI_RET_RETRY) {
  203                         /* only retry here READs and WRITEs */
  204                         if ((ior->io_op & IO_INTERNAL) == 0) {
  205                                 ior->io_residual = 0;
  206                                 goto start;
  207                         } else{
  208                                 ior->io_error = D_WOULD_BLOCK;
  209                                 ior->io_op |= IO_ERROR;
  210                         }
  211                     } else {
  212                         ior->io_error = D_IO_ERROR;
  213                         ior->io_op |= IO_ERROR;
  214                     }
  215                 }
  216 
  217                 if (scsi_debug)
  218                         printf("[Resid x%x]", ior->io_residual);
  219 
  220                 /* dequeue next one */
  221                 head = ior;
  222 
  223                 simple_lock(&tgt->target_lock);
  224                 ior = head->io_next;
  225                 tgt->ior = ior;
  226                 if (ior)
  227                         ior->io_prev = head->io_prev;
  228                 simple_unlock(&tgt->target_lock);
  229 
  230                 iodone(head);
  231 
  232                 if (ior == 0)
  233                         return;
  234         }
  235         ior->io_residual = 0;
  236 start:
  237         if (ior->io_op & IO_READ) {
  238                 ret = scsi_receive( tgt, ior );
  239         } else if ((ior->io_op & IO_INTERNAL) == 0) {
  240                 ret = scsi_send( tgt, ior );
  241         }
  242 }
  243 
  244 
  245 /*
  246  * This is a simple code to make us act as a dumb
  247  * processor type.  Use for debugging only.
  248  */
  249 static struct io_req    sccpu_ior;
  250 vm_offset_t             sccpu_buffer; /* set this with debugger */
  251 
  252 void sccpu_act_as_target(self)
  253         target_info_t   *self;
  254 {
  255         static char     inq_data[] = "\3\0\1\0\040\0\0\0Mach3.0 Processor Link  v0.1";
  256         static char     sns_data[] = "\160\0\0\0\0\0\0\0\0";
  257 
  258         self->dev_info.cpu.req_pending = FALSE;
  259         sccpu_ior.io_next = 0;
  260 #define MAXSIZE 1024*64
  261         sccpu_ior.io_count = (MAXSIZE < self->dev_info.cpu.req_len) ?
  262                 MAXSIZE : self->dev_info.cpu.req_len;
  263 
  264         switch (self->dev_info.cpu.req_cmd) {
  265         case SCSI_CMD_INQUIRY:
  266                 sccpu_ior.io_data = inq_data; break;
  267         case SCSI_CMD_REQUEST_SENSE:
  268                 sccpu_ior.io_data = sns_data; break;
  269         default:
  270                 if (sccpu_buffer == 0) {
  271                     /* ( read my lips :-) */
  272                     extern char end[];
  273                     sccpu_buffer = trunc_page(end);
  274                 }
  275                 sccpu_ior.io_data = (char*)sccpu_buffer; break;
  276         }
  277 
  278         if (self->dev_info.cpu.req_cmd == SCSI_CMD_SEND) {
  279                 self->cur_cmd = SCSI_CMD_READ;
  280                 sccpu_ior.io_op = IO_READ;
  281         } else {
  282                 self->cur_cmd = SCSI_CMD_WRITE;
  283                 sccpu_ior.io_op = IO_WRITE;
  284         }
  285         self->ior = &sccpu_ior;
  286 }
  287 
  288 /*#define PERF*/
  289 #ifdef  PERF
  290 int test_read_size = 512;
  291 int test_read_nreads = 1000;
  292 int test_read_bdev = 0;
  293 int test_read_or_write = 1;
  294 
  295 #include <sys/time.h>
  296 #include <machine/machspl.h>    /* spl */
  297 
  298 test_read(max)
  299 {
  300         int i, ssk, usecs;
  301         struct timeval start, stop;
  302         spl_t s;
  303 
  304         if (max != 0)
  305                 test_read_nreads = max;
  306 
  307         s = spl0();
  308         start = time;
  309         if (test_read_or_write) read_test(); else write_test();
  310         stop = time;
  311         splx(s);
  312 
  313         usecs = stop.tv_usec - start.tv_usec;
  314         if (usecs < 0) {
  315                 stop.tv_sec -= 1;
  316                 usecs += 1000000;
  317         }
  318         printf("Size %d count %d time %3d sec %d us\n",
  319                         test_read_size, test_read_nreads,
  320                         stop.tv_sec - start.tv_sec, usecs);
  321 }
  322 
  323 read_test()
  324 {
  325         struct io_req   io, io1;
  326         register int    i;
  327 
  328         bzero(&io, sizeof(io));
  329         io.io_unit = test_read_bdev;
  330         io.io_op = IO_READ;
  331         io.io_count = test_read_size;
  332         io.io_data = (char*)sccpu_buffer;
  333         io1 = io;
  334 
  335         sccpu_strategy(&io);
  336         for (i = 1; i < test_read_nreads; i += 2) {
  337                 io1.io_op = IO_READ;
  338                 sccpu_strategy(&io1);
  339                 iowait(&io);
  340                 io.io_op = IO_READ;
  341                 sccpu_strategy(&io);
  342                 iowait(&io1);
  343         }
  344         iowait(&io);
  345 }
  346 
  347 write_test()
  348 {
  349         struct io_req   io, io1;
  350         register int    i;
  351 
  352         bzero(&io, sizeof(io));
  353         io.io_unit = test_read_bdev;
  354         io.io_op = IO_WRITE;
  355         io.io_count = test_read_size;
  356         io.io_data = (char*)sccpu_buffer;
  357         io1 = io;
  358 
  359         sccpu_strategy(&io);
  360         for (i = 1; i < test_read_nreads; i += 2) {
  361                 io1.io_op = IO_WRITE;
  362                 sccpu_strategy(&io1);
  363                 iowait(&io);
  364                 io.io_op = IO_WRITE;
  365                 sccpu_strategy(&io);
  366                 iowait(&io1);
  367         }
  368         iowait(&io);
  369 }
  370 
  371 tur_test()
  372 {
  373         struct io_req   io;
  374         register int    i;
  375         char            *a;
  376         struct timeval start, stop;
  377         spl_t s;
  378         target_info_t   *tgt;
  379 
  380         bzero(&io, sizeof(io));
  381         io.io_unit = test_read_bdev;
  382         io.io_data = (char*)&io;/*unused but kernel space*/
  383 
  384         rz_check(io.io_unit, &a, &tgt);
  385         s = spl0();
  386         start = time;
  387         for (i = 0; i < test_read_nreads; i++) {
  388                 io.io_op = IO_INTERNAL;
  389                 scsi_test_unit_ready(tgt,&io);
  390         }
  391         stop = time;
  392         splx(s);
  393         i = stop.tv_usec - start.tv_usec;
  394         if (i < 0) {
  395                 stop.tv_sec -= 1;
  396                 i += 1000000;
  397         }
  398         printf("%d test-unit-ready took %3d sec %d us\n",
  399                         test_read_nreads,
  400                         stop.tv_sec - start.tv_sec, i);
  401 }
  402 
  403 /*#define       MEM_PERF*/
  404 #ifdef  MEM_PERF
  405 int mem_read_size = 1024; /* ints! */
  406 int mem_read_nreads = 1000;
  407 volatile int *mem_read_address = (volatile int*)0xb0080000;
  408 volatile int *mem_write_address = (volatile int*)0xb0081000;
  409 
  410 mem_test(max, which)
  411 {
  412         int i, ssk, usecs;
  413         struct timeval start, stop;
  414         int (*fun)(), mwrite_test(), mread_test(), mcopy_test();
  415         spl_t s;
  416 
  417         if (max == 0)
  418                 max = mem_read_nreads;
  419 
  420         switch (which) {
  421         case 1: fun = mwrite_test; break;
  422         case 2: fun = mcopy_test; break;
  423         default:fun = mread_test; break;
  424         }
  425 
  426         s = spl0();
  427         start = time;
  428         for (i = 0; i < max; i++)
  429                 (*fun)(mem_read_size);
  430         stop = time;
  431         splx(s);
  432 
  433         usecs = stop.tv_usec - start.tv_usec;
  434         if (usecs < 0) {
  435                 stop.tv_sec -= 1;
  436                 usecs += 1000000;
  437         }
  438         printf("Size %d count %d time %3d sec %d us\n",
  439                         mem_read_size*4, max,
  440                         stop.tv_sec - start.tv_sec, usecs);
  441 }
  442 
  443 mread_test(max)
  444         register int max;
  445 {
  446         register int    i;
  447         register volatile int *addr = mem_read_address;
  448 
  449         for (i = 0; i < max; i++) {
  450                 register int j = *addr++;
  451         }
  452 }
  453 mwrite_test(max)
  454         register int max;
  455 {
  456         register int    i;
  457         register volatile int *addr = mem_read_address;
  458 
  459         for (i = 0; i < max; i++) {
  460                 *addr++ = i;
  461         }
  462 }
  463 
  464 mcopy_test(max)
  465         register int max;
  466 {
  467         register volatile int *from = mem_read_address;
  468         register volatile int *to = mem_write_address;
  469         register volatile int *endaddr;
  470 
  471         endaddr = to + max;
  472         while (to < endaddr)
  473                 *to++ = *from++;
  474 
  475 }
  476 #endif  /*MEM_PERF*/
  477 
  478 #endif  /*PERF*/
  479 

Cache object: a3b50619cac7c57352c1f12bb4df1867


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