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/sqtsec/sec.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  * Copyright (c) 1991 Sequent Computer Systems
    5  * All Rights Reserved.
    6  * 
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation.
   12  * 
   13  * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
   14  * THIS SOFTWARE IN ITS "AS IS" CONDITION.  CARNEGIE MELLON AND
   15  * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  * 
   18  * Carnegie Mellon requests users of this software to return to
   19  * 
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  * 
   25  * any improvements or extensions that they make and grant Carnegie Mellon 
   26  * the rights to redistribute these changes.
   27  */
   28 
   29 /*
   30  * HISTORY
   31  * $Log:        sec.c,v $
   32  * Revision 2.4  93/03/10  11:30:51  danner
   33  *      u_long -> u_int
   34  *      [93/03/10            danner]
   35  * 
   36  * Revision 2.3  91/07/31  18:07:30  dbg
   37  *      Changed copyright.
   38  *      [91/07/31            dbg]
   39  * 
   40  * Revision 2.2  91/05/08  13:07:03  dbg
   41  *      Added volatile declarations.  Distribute interrupts to any CPU.
   42  *      [91/03/25            dbg]
   43  * 
   44  *      Adapted for pure kernel.
   45  *      [90/09/24            dbg]
   46  * 
   47  */
   48 
   49 #ifndef lint
   50 static  char    rcsid[] = "$Header: sec.c,v 2.4 93/03/10 11:30:51 danner Exp $";
   51 #endif
   52 
   53 /*
   54  * sec.c
   55  *      Various procedures dealing with SEC's.
   56  */
   57 
   58 /*
   59  * Revision 1.2  89/08/03  12:30:17  kak
   60  * balance -> sqt
   61  * 
   62  * Revision 1.1  89/07/05  13:20:14  kak
   63  * Initial revision
   64  * 
   65  * Revision 2.22  88/12/21  10:37:01  djg
   66  * fixed lint warnings
   67  * 
   68  * Revision 2.21  88/11/10  08:24:12  djg
   69  * bak242 now uses l.cpu_speed
   70  * 
   71  * Revision 2.20  88/06/02  09:43:19  dilip
   72  * buf_iat now flushes the tlb in both i386 and 032 cases.
   73  * 
   74  */
   75 
   76 #ifdef  MACH_KERNEL
   77 #include <sys/types.h>
   78 
   79 #include <device/param.h>
   80 #include <device/io_req.h>
   81 #include <device/buf.h>
   82 
   83 #include <sqt/macros.h>
   84 
   85 #include <sqt/vm_defs.h>
   86 #include <sqt/sqtparam.h>
   87 #include <sqt/clock.h>
   88 #include <sqt/slic.h>
   89 #include <sqt/slicreg.h>
   90 #include <sqt/cfg.h>
   91 
   92 #include <sqt/ioconf.h>
   93 #include <sqt/hwparam.h>
   94 #include <sqt/mutex.h>
   95 #include <sqt/intctl.h>
   96 #include <sqt/trap.h>
   97 
   98 #include <sqtsec/sec.h>
   99 
  100 #else   /* MACH_KERNEL */
  101 #include "sys/param.h"
  102 #include "sys/systm.h"
  103 #include "sys/map.h"
  104 #include "sys/user.h"
  105 #include "sys/proc.h"
  106 #include "sys/vm.h"
  107 #include "sys/clist.h"
  108 #include "sys/buf.h"
  109 
  110 #include "sqt/clock.h"
  111 #include "sqt/slic.h"
  112 #include "sqt/slicreg.h"
  113 #include "sqt/cfg.h"
  114 
  115 #include "sqt/ioconf.h"
  116 #include "sqt/pte.h"
  117 #include "sqt/hwparam.h"
  118 #include "sqt/mutex.h"
  119 #include "sqt/intctl.h"
  120 #include "sqt/trap.h"
  121 #include "sqt/mftpr.h"
  122 #include "sqt/plocal.h"
  123 #include "sqt/pmap.h"
  124 
  125 #include "sqtsec/sec.h"
  126 
  127 #endif  /* MACH_KERNEL */
  128 
  129 #define SEC_ERROR_BIN 7
  130 
  131 #ifdef  DEBUG
  132 int     sec_debug = 2;          /* 0=off, 1=little, 2=all */    /* XXX */
  133 #endif  DEBUG
  134 
  135 struct sec_desc *SEC_desc;      /* array alloc'd and filled by conf_scsi() */
  136 int             NSEC;           /* # SEC's to map at boot */
  137 u_int           SECvec;         /* bit-vector of existing SEC's */
  138 u_char          SEC_errbase;    /* Base vector number for SEC reported errors */
  139 u_char  SEC_accerr[MAXNUMSEC];  /* access errors reported by SEC */
  140 unsigned        sec0eaddr;      /* lower 24 bits of ether address */
  141                                 /* later used to contain # users */
  142 boolean_t       conscsi_yet;    /* Console SCSI init'd yet */
  143 boolean_t       probescsi_yet;  /* probed the SCSI bus yet */
  144 boolean_t       CCS_present;    /* are the drives embedded SCSI */
  145 
  146 /*
  147  * Distinguished location for embedded SCSI drive.  If there is a CCS disk
  148  * at this target, we will assume that all disks on the SCSI bus are
  149  * embedded, and we will scan wildcarded SEC targets from low to high.
  150  * If the device at this target is not a CCS disk (or does not exist),
  151  * assume we have target-adaptor-based disks and scan SCSI target
  152  * wildcards from high to low.
  153  */
  154 
  155 int     CCS_magic_target = 0;
  156 
  157 /*
  158  * appropriate bit is set if a target is found on a SCSI bus that
  159  * can only have one Logical Unit Number on it, or we are convinced that
  160  * there is no target there.  This bitmap allows us to scan the SCSI bus
  161  * more rapidly by eliminating possibilities.
  162  */
  163 
  164 u_char SECnoprobe[MAXNUMSEC];
  165 
  166 #define SEC_EXISTS(SEC_idx)     (SECvec & (1 << (SEC_idx)))
  167 #define WILDCARD(sd)            (((sd)->sd_sec_idx == -1) || ((sd)->sd_target == -1) || ((sd)->sd_unit == -1))
  168 
  169 #define PLURAL(x)                ((x)==1?"":"s")
  170 
  171 int             SEC_error();    /* SCED error catcher */
  172 u_char          *SECgarbuf;     /* SCED garbage buffer pointer */
  173 
  174 struct  sec_cib *SEC_alloc_channels();
  175 struct  sec_desc *SEC_probe();
  176 
  177 extern char *   calloc();       /* bootstrap memory allocator */
  178 extern int      mono_P_slic;    /* interrupt address for mono-processor
  179                                    drivers */
  180 /*
  181  * conf_sec()
  182  *      Configure SCSI boards.
  183  */
  184 
  185 conf_sec()
  186 {
  187         register struct ctlr_toc *toc;
  188         register struct ctlr_desc *cd;
  189         register struct sec_desc *sec;
  190         register int    i;
  191         register int    j;
  192 
  193         toc = PHYSTOKV(&va_CD_LOC->c_toc[SLB_SCSIBOARD], struct ctlr_toc *);
  194 
  195         SEC_desc = (struct sec_desc *)calloc((int)toc->ct_count * sizeof(*sec));
  196         printf("%d SCSI/Ether controller%s; slic",
  197                                         toc->ct_count, PLURAL(toc->ct_count));
  198         NSEC = 0;
  199         cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start], struct ctlr_desc *);
  200         for (i = 0; i < toc->ct_count; i++, cd++) {
  201                 sec = &SEC_desc[i];
  202                 sec->sec_diag_flags = cd->cd_diag_flag;
  203                 sec->sec_slicaddr = cd->cd_slic;
  204                 sec->sec_target_no = cd->cd_sc_host_num;
  205                 sec->sec_is_cons = cd->cd_sc_cons;
  206                 sec->sec_powerup =
  207                         PHYSTOKV(cd->cd_sc_init_queue, struct sec_powerup *);
  208                 sec->sec_version = cd->cd_sc_version;
  209                 for (j = 0; j < 6; ++j)
  210                         sec->sec_ether_addr[j] = cd->cd_sc_enet_addr[j];
  211                 /*
  212                  * Save lower 24 bits of ether address to be passed to init,
  213                  * if not already initialized (eg, on a B21k -- see
  214                  * conf_clkarb()).
  215                  *
  216                  * Note: sec0eaddr is later used to contain number of users.
  217                  * BTW: typecast to int gets around a compiler bug.
  218                  */
  219                 if (i == 0 && sec0eaddr == (unsigned)-1) {
  220                         u_char *s = &cd->cd_sc_enet_addr[0];
  221                         sec0eaddr = (int)s[5] | (int)(s[4]<<8) | (int)(s[3]<<16);
  222                 }
  223 
  224                 if ((cd->cd_diag_flag & (CFG_FAIL|CFG_DECONF)) == 0) {
  225                         ++NSEC;
  226                         SECvec |= 1 << i;
  227                 }
  228                 printf(" %d", sec->sec_slicaddr);
  229 #ifdef DEBUG
  230                 if (cd->cd_diag_flag)
  231                         printf(" flags 0x%b", cd->cd_diag_flag,
  232                         "\2\2FAIL\3DECONF\4BDUSE\5SCSIFAIL\6ETHERFAIL\7SLICFAIL\10TODFAIL\11PORT0FAIL\12PORT1FAIL\13SEFAIL\14DIFFFAIL");
  233 #endif DEBUG
  234         }
  235         printf(".\n");
  236 
  237         /*
  238          * Allocate SEC error interrupt vectors.
  239          * Must be allocated contiguously over all SECs.
  240          */
  241 
  242         ivecres(SEC_ERROR_BIN, toc->ct_count);
  243 
  244         if (NSEC != toc->ct_count) {
  245                 printf("Not using SCSI/Ether Controllers: slic");
  246                 for (i = 0; i < toc->ct_count; ++i) {
  247                         if (!SEC_EXISTS(i))
  248                                 printf(" %d", SEC_desc[i].sec_slicaddr);
  249                 }
  250                 printf(".\n");
  251         }
  252 }
  253 
  254 /*
  255  * probe_sec_devices()
  256  *      Probe for devices attached to SCSI controllers.
  257  *
  258  * Probing gets tricky when ambiguous specifications of devices
  259  * are allowed.  Too much wildcarding can require that we
  260  * keep track of where devices were found, to avoid looking
  261  * for other devices there.  The array 'found' is a 2-D table of
  262  * bits; a one in the (sec, chan) position of the table means we found
  263  * a device on that SEC at that channel number (SEC device number
  264  * between 0 and 95).
  265  *
  266  * For the moment, let's just "know" how to index this,
  267  * as I don't know where the macros that manipulate such
  268  * a table should live.
  269  */
  270 
  271 probe_sec_devices()
  272 {
  273         register struct ctlr_toc        *toc;
  274         register struct sec_conf        *sec;
  275         register struct sec_driver      *secd;
  276         register struct sec_dev         *sd;
  277         register struct sec_desc        *sec_desc;
  278         register int i;
  279         struct  sec_cib *cibs[MAXNUMSEC];
  280         u_char  vec;
  281         u_int   found[MAXNUMSEC*3];
  282         int secno, chan;
  283         extern  int     mono_P_slic;
  284         extern  struct  sec_cib *cbdcib, *todcib, *wdtcib;
  285 
  286         toc = PHYSTOKV(&va_CD_LOC->c_toc[SLB_SCSIBOARD], struct ctlr_toc *);
  287 
  288         for (secno = 0; secno < MAXNUMSEC; ++secno)
  289                 for (chan = 0; chan < 3; ++chan)
  290                         found[secno*3 + chan] = 0;
  291 
  292         /*
  293          * Run through the sec_conf array and do the probes.
  294          * We call the boot procedure even if no existing HW is found.
  295          *
  296          * for each configured SEC driver, for each device ...
  297          */
  298 
  299         for (sec = sec_conf; sec->sec_driver; ++sec) {
  300                 secd = sec->sec_driver;
  301                 for (sd = sec->sec_dev, i = 0;  i < sec->sec_nent;  i++, sd++) {
  302 
  303                         /*
  304                          * If it has an interrupt procedure, allocate a vector
  305                          * in the appropriate bin.  Must allocate even if
  306                          * probe ==> not here, to preserve order of devices.
  307                          */
  308                         if (secd->sed_cflags & SED_HASINTR)
  309                                 vec = ivecall(sd->sd_bin);
  310 
  311                         /*
  312                          * If it's there, fill out configure fields in `sd'.
  313                          */
  314                         if ((sec_desc = SEC_probe(secd, sd, found)) == 0)
  315                                 continue;
  316                         found[(sec_desc-SEC_desc)*3 + (sd->sd_chan >> 5)] |= 1 << (sd->sd_chan & 0x1F);
  317                         sd->sd_desc = sec_desc;
  318                         sd->sd_alive = 1;
  319                         if (secd->sed_cflags & SED_MONOP) {
  320                                 mono_P_slic = va_slic->sl_procid;
  321                         }
  322                         if (secd->sed_cflags & SED_HASINTR) {
  323                                 sd->sd_vector = vec;
  324                                 ivecinit(sd->sd_bin, vec, secd->sed_intr);
  325                                 if (secd->sed_cflags & SED_MONOP)
  326                                         sd->sd_destslic = mono_P_slic;
  327                                 else
  328                                         sd->sd_destslic = SL_GROUP|TMPOS_GROUP;
  329                         }
  330 
  331                         /*
  332                          * Allocate the request and done queues.
  333                          * The program pointers themselves are filled
  334                          * in later by the driver (at boot time).
  335                          * The pointer to the cib queue is filled in
  336                          * by SEC_init_channels, when the contiguous
  337                          * cib channel array is allocated.
  338                          */
  339                         SEC_allocate_progqs(sd);
  340                         assert(sd->sd_requestq != 0);
  341                         assert(sd->sd_doneq != 0);
  342 
  343                         /*
  344                          * Tell the world it's alive.
  345                          */
  346                         printf("%s%d found at SEC%d", secd->sed_name, i, sec_desc-SEC_desc);
  347                         if (secd->sed_cflags & SED_IS_SCSI) {
  348                                 printf(" target adapter %d unit %d", sd->sd_target, sd->sd_unit);
  349                         }
  350                         if (secd->sed_cflags & SED_HASINTR) {
  351                                 printf(" bin %d vec %d", sd->sd_bin, sd->sd_vector);
  352                         }
  353                         printf(" input q %d output q %d",
  354                                 sd->sd_req_size, sd->sd_doneq_size);
  355 #ifdef DEBUG
  356                         if (sec_debug)
  357                                 printf(" dest slic 0x%x",
  358                                         sd->sd_destslic);
  359 #endif
  360                         printf(".\n");
  361                 }
  362         }
  363 
  364         /*
  365          * Allocate a garbage buffer for raw io.
  366          * Only one is needed for *all* SCED controllers.
  367          * Must not cross a 64kbyte physical boundry because of
  368          * SEC DMA hardware limitation.
  369          */
  370 
  371         callocrnd(DEV_BSIZE);
  372         SECgarbuf = (u_char *)calloc(DEV_BSIZE*sizeof(u_char));
  373 
  374         /*
  375          * Allocate the SEC controller queues/cibs.
  376          */
  377 
  378         for (i = 0; i < toc->ct_count; ++i) {
  379                 if (!SEC_EXISTS(i))
  380                         continue;
  381                 cibs[i] = SEC_alloc_channels(i, &SEC_desc[i], sec_conf);
  382                 /*
  383                  * If console SCED board, save away pointers to the cib's
  384                  * for the TOD clock, Watchdog timer, and console board device.
  385                  */
  386                 if (SEC_desc[i].sec_is_cons) {
  387                         cbdcib = &cibs[i][SDEV_SCSIBOARD];
  388                         todcib = &cibs[i][SDEV_TOD];
  389                         wdtcib = &cibs[i][SDEV_WATCHDOG];
  390                 }
  391         }
  392 
  393         /*
  394          * Probes done, "boot" the drivers.
  395          * This must be done before the SEC is initialized, as the boot
  396          * routine may need to ask/tell the device something, and interrupts
  397          * aren't available yet.
  398          */
  399 
  400         for (sec = sec_conf; sec->sec_driver; ++sec) {
  401                 secd = sec->sec_driver;
  402                 if (secd->sed_cflags & SED_HASBOOT)
  403                         (*secd->sed_boot)(sec->sec_nent, sec->sec_dev);
  404         }
  405 
  406         /*
  407          * Inform the SCSI/Ether controller of the queues/cib/etc.
  408          * And initialize SEC error reporting vectors.
  409          *
  410          * This relies on ivecall() returning consecutive vectors.
  411          */
  412 
  413         SEC_errbase = ivecpeek(SEC_ERROR_BIN);
  414         for (i = 0; i < toc->ct_count; ++i) {
  415                 vec = ivecall(SEC_ERROR_BIN);
  416                 ivecinit(SEC_ERROR_BIN, vec, SEC_error);
  417                 if (!SEC_EXISTS(i))
  418                         continue;               /* deconf'd */
  419                 SEC_init_channels(i, &SEC_desc[i], sec_conf, cibs[i],
  420                         SEC_ERROR_BIN, vec);
  421                 if (SEC_desc[i].sec_is_cons)
  422                         conscsi_yet = 1;
  423         }
  424 }
  425 
  426 /*
  427  * SEC_probe()
  428  *      Probe for a device on a scsi/ether controller.
  429  *
  430  * Handles wild-card SEC specification, finding a SEC with the device
  431  * if it exists.  But we won't look where a device has already been found.
  432  *
  433  * Returns pointer to SEC descriptor that device lives on or zero if
  434  * device not found.
  435  */
  436 
  437 struct sec_desc *
  438 SEC_probe(secd, sd, found)
  439         struct sec_driver *secd;
  440         register struct sec_dev *sd;
  441         u_int found[MAXNUMSEC*3];
  442 {
  443         register int SEC_idx;
  444         register struct sec_desc *sec;
  445         register int target, unit;
  446         int secbits, targstart, targend, targincr, unitmin, unitmax;
  447         int proberes;
  448         struct sec_probe sp, sp0;
  449 
  450         /*
  451          * SEC is either wild-carded or must exist in the configuration.
  452          */
  453 
  454         if (sd->sd_sec_idx >= 0 && !SEC_EXISTS(sd->sd_sec_idx))
  455                 return ((struct sec_desc *)0);
  456 
  457         /*
  458          * If no probe procedure, then assume it exists if the
  459          * desired SEC exists.  Note:  SEC_EXISTS is false for
  460          * wildcard SEC index.
  461          */
  462 
  463         if ((secd->sed_cflags & SED_HASPROBE) == 0) {
  464                 if (WILDCARD(sd)) {
  465                         printf("illegal config: %s device can't be probed for wildcards.\n",
  466                                 secd->sed_name);
  467                         return ((struct sec_desc *)0);
  468                 }
  469                 if (SEC_EXISTS(sd->sd_sec_idx))
  470                         return (&SEC_desc[sd->sd_sec_idx]);
  471                 else
  472                         return ((struct sec_desc *)0);
  473         }
  474 
  475         /*
  476          * It has a probe procedure, so we have to try to find it.
  477          * For SCSI/Ether controller devices, this means
  478          * we may have to look at the target adapter and unit,
  479          * as well as the controller.
  480          * The loops themselves (though nested to a depth of 4 if
  481          * you count the one that calls this) shouldn't really be
  482          * a speed problem.  We set up loop ranges outside the loop
  483          * to speed up the autoconf of those things already specified.
  484          */
  485 
  486         if (sd->sd_target >= 0) {
  487                 targstart = targend = sd->sd_target;
  488         } else if (!CCS_present) {
  489                 targstart = 7; targend = 0; targincr = -1;
  490         } else {
  491                 targstart = 0; targend = 7; targincr = 1;
  492         }
  493         if (sd->sd_unit >= 0) {
  494                 unitmin = unitmax = sd->sd_unit;
  495         } else {
  496                 unitmin = 0; unitmax = 7;
  497         }
  498         for (SEC_idx = 0, secbits = SECvec; secbits != 0; ++SEC_idx, secbits >>= 1) {
  499                 if (!SEC_EXISTS(SEC_idx))
  500                         continue;
  501 
  502                 if (sd->sd_sec_idx >= 0 && sd->sd_sec_idx != SEC_idx)
  503                         continue;
  504 
  505                 sec = &SEC_desc[SEC_idx];
  506                 sp.secp_desc = sec;
  507                 sp.secp_flags = sd->sd_flags;
  508                 sp.secp_puq = sec->sec_powerup;
  509 
  510                 if ((secd->sed_cflags & SED_IS_SCSI) == 0) {
  511                         /*
  512                          * The device is not a SCSI bus device, and
  513                          * it matches this SCSI/Ether controller.
  514                          * If no other device has been found here, probe it.
  515                          */
  516                         if (sd->sd_unit < 0) {
  517                                 printf("SEC_probe: invalid config: non-scsi device has unit wildcard\n");
  518                                 continue;
  519                         }
  520                         sp.secp_chan = secd->sed_base_chan + sd->sd_unit;
  521                         sp.secp_target = 0;
  522                         if (found[SEC_idx*3 + (sp.secp_chan >> 5)] & (1 << (sp.secp_chan & 0x1F)))
  523                                 continue;
  524 
  525                         if ((*secd->sed_probe)(&sp)) {
  526                                 sd->sd_sec_idx = SEC_idx;
  527                                 sd->sd_target = 0;
  528                                 sd->sd_chan = sp.secp_chan;
  529                                 sd->sd_alive = 1;
  530                                 return (sec);
  531                         }
  532                 } else {
  533                         /*
  534                          * It's a SCSI bus device.  If this is our first time
  535                          * here, probe the guy at the distinguished target
  536                          * location to see if it is an embedded SCSI disk.
  537                          */
  538                         if ((strcmp(secd->sed_name, "sd") == 0)
  539                           && (sd->sd_target < 0)
  540                           && (CCS_magic_target != sec->sec_target_no)
  541                           && (probescsi_yet == 0)) {
  542                                 probescsi_yet++;
  543                                 sp0 = sp;
  544                                 sp0.secp_target = CCS_magic_target;
  545                                 sp0.secp_unit = 0;
  546                                 sp0.secp_chan = secd->sed_base_chan
  547                                                         + CCS_magic_target*8;
  548 
  549                                 /*
  550                                  * if the guy exists and is an embedded
  551                                  * SCSI drive, prepare to do all scans
  552                                  * of SCSI targets from low to high
  553                                  */
  554 
  555                                 proberes = (*secd->sed_probe)(&sp0);
  556                                 if ((proberes & SECP_FOUND) == SECP_FOUND 
  557                                     && CCS_present) {
  558                                         targstart = 0; targend = 7;
  559                                         targincr = 1;
  560                                 }
  561                         }
  562 
  563                         /*
  564                          * For wildcarding, etc. we have to look at
  565                          * all target adapters and unit numbers.
  566                          * But for non-wildcarded entries, targmin, etc
  567                          * are set up just to look at the right target/unit.
  568                          * Search target adapters in reverse numeric order
  569                          * if the drive at target 0 is not an embedded SCSI,
  570                          * in numeric order otherwise.
  571                          */
  572                         for (target = targstart; target != targend + targincr;
  573                                                     target += targincr) {
  574                                 if (target == sec->sec_target_no)
  575                                         continue;
  576 
  577                                 /*
  578                                  * loop short-circuit:  no way our goal
  579                                  * can be resolved here;
  580                                  * no need to scan further.
  581                                  */
  582                                 if (SECnoprobe[SEC_idx] & (1 << target))
  583                                         continue;
  584 
  585                                 for (unit = unitmin; unit <= unitmax; ++unit) {
  586 
  587                                         /*
  588                                          * Somewhere along the line, this
  589                                          * (SEC_idx, target, unit) matches the
  590                                          * one we are trying to configure.
  591                                          * Probe for it.
  592                                          */
  593 
  594                                         sp.secp_target = target;
  595                                         sp.secp_unit = unit;
  596                                         sp.secp_chan = secd->sed_base_chan + target*8 + unit;
  597                                         if (found[SEC_idx*3 + (sp.secp_chan >> 5)] & (1 << (sp.secp_chan & 0x1F)))
  598                                                 continue;
  599 
  600                                         proberes = (*secd->sed_probe)(&sp);
  601 
  602                                         if ((proberes & SECP_ONELUN)
  603                                                                 == SECP_ONELUN)
  604                                                 SECnoprobe[SEC_idx] |=
  605                                                         1 << target;
  606 
  607                                         if ((proberes & SECP_FOUND) 
  608                                                                 == SECP_FOUND) {
  609                                                 sd->sd_sec_idx = SEC_idx;
  610                                                 sd->sd_target = target;
  611                                                 sd->sd_unit = unit;
  612                                                 sd->sd_chan = sp.secp_chan;
  613                                                 sd->sd_alive = 1;
  614                                                 return (sec);
  615                                         }
  616 
  617                                         /*
  618                                          * no need to scan for
  619                                          * more units or ever look at this
  620                                          * target again.
  621                                          */
  622                                         if (proberes & SECP_NOTARGET) {
  623 
  624                                                 /*
  625                                                  * NOTARGET may come up
  626                                                  * erroneously true on valid
  627                                                  * targets with invalid units.
  628                                                  */
  629                                                 if (unit == 0) {
  630                                                         SECnoprobe[SEC_idx] |=
  631                                                                 1 << target;
  632                                                 }
  633                                                 break;
  634                                         }
  635 
  636                                         if (proberes == SECP_NOTFOUND)
  637                                                 continue;
  638                                 }
  639                         }
  640                 }
  641         }
  642 
  643         /*
  644          * Ran through the existing SEC's, targets, etc. and didn't find it;
  645          */
  646 
  647         return ((struct sec_desc *)0);
  648 }
  649 
  650 
  651 /*
  652  * Allocate program queues for SEC devices.
  653  */
  654 
  655 SEC_allocate_progqs(sd)
  656         register struct sec_dev *sd;
  657 {
  658         register int nbytes;
  659 
  660         /*
  661          * Allocate the request queue, and the programs.
  662          */
  663         nbytes = (int)(&((struct sec_progq *)0)->pq_un.pq_progs[sd->sd_req_size]);
  664         if (nbytes <= 0) {
  665                 sd->sd_requestq = (struct sec_progq *)0;
  666         } else {
  667                 sd->sd_requestq = (struct sec_progq *) calloc(nbytes);
  668         }
  669 
  670         if (sd->sd_chan != SDEV_ETHERREAD) {
  671                 /*
  672                  * Non-ether-read output queue.
  673                  * These all look alike from device to device.
  674                  * We just allocate the output queue, as the programs
  675                  * will be filled in by firmware as the programs complete.
  676                  */
  677                 nbytes = (int)(&((struct sec_progq *)0)->pq_un.pq_progs[sd->sd_doneq_size]);
  678                 if (nbytes <= 0) {
  679                         sd->sd_doneq = (struct sec_progq *)0;
  680                 } else {
  681                         sd->sd_doneq = (struct sec_progq *)calloc(nbytes);
  682                 }
  683         } else {
  684                 /*
  685                  * Ether read output (done) queue looks different.
  686                  */
  687                 nbytes = (int)(&((struct sec_eprogq *)0)->epq_status[sd->sd_doneq_size]);
  688                 if (nbytes <= 0) {
  689                         sd->sd_doneq = (struct sec_progq *)0;
  690                 } else {
  691                         sd->sd_doneq = (struct sec_progq *)calloc(nbytes);
  692                 }
  693         }
  694 }
  695 
  696 /*
  697  * SEC_fill_progq - fill a program queue with device programs.
  698  *
  699  * This may be called by the device driver from its boot procedure
  700  * to fill in the array of drive program pointers allocated by
  701  * the autoconfig code.
  702  */
  703 
  704 SEC_fill_progq(progq, n, width)
  705         register struct sec_progq *progq;
  706 {
  707         register int i;
  708         caddr_t base = calloc(n*width);
  709 
  710         for (i = 0; i < n; ++i) {
  711                 progq->pq_un.pq_progs[i] =
  712                     (struct sec_dev_prog *)
  713                         KVTOPHYS(base + i*width, struct sec_dev_prog *);
  714 #ifdef DEBUG
  715                 if (sec_debug > 2 || (sec_debug > 0 && i == 0))
  716                         printf("0x%x->pq_un.pq_progs[%d] = 0x%x\n",
  717                                         progq, i, progq->pq_un.pq_progs[i]);
  718 #endif DEBUG
  719         }
  720         progq->pq_head = progq->pq_tail = 0;
  721 }
  722 
  723 /*
  724  * SEC_alloc_channels()
  725  *      Initialize the channels for a single SEC controller.
  726  */
  727 
  728 struct sec_cib *
  729 SEC_alloc_channels(SEC_idx, desc, conf)
  730         int SEC_idx;
  731         register struct sec_desc *desc;
  732         struct sec_conf *conf;
  733 {
  734         struct sec_driver *driver;
  735         register struct sec_dev *dev;
  736         struct sec_cib *cibs;
  737         int i, chan;
  738 
  739         assert(desc - SEC_desc == SEC_idx);
  740         assert(desc->sec_powerup != 0);
  741         cibs = (struct sec_cib *) calloc(SDEV_NUM_DEVICES*sizeof(struct sec_cib));
  742 #ifdef DEBUG
  743         if (sec_debug > 1)
  744                 printf("SEC_alloc_channels: cibs @ 0x%x\n", cibs);
  745 #endif DEBUG
  746 
  747         for (; conf->sec_driver; ++conf) {
  748                 driver = conf->sec_driver;
  749                 for (i = 0; i < conf->sec_nent; ++i) {
  750                         dev = &conf->sec_dev[i];
  751                         if (!dev->sd_alive)
  752                                 continue;
  753 
  754                         if (dev->sd_sec_idx != SEC_idx)
  755                                 continue;
  756 
  757                         /*
  758                          * Found a device on this SEC controller.
  759                          * Add its entry to the data to be initialized.
  760                          */
  761                         if (driver->sed_cflags & SED_IS_SCSI) {
  762                                 chan = driver->sed_base_chan + 8*dev->sd_target + dev->sd_unit;
  763                         } else {
  764                                 chan = driver->sed_base_chan + dev->sd_unit;
  765                         }
  766                         dev->sd_cib = &cibs[chan];
  767                         assert(dev->sd_cib != 0);
  768                         assert(dev->sd_requestq != 0);
  769                         assert(dev->sd_doneq != 0);
  770                         assert(dev->sd_bin != 0);
  771                 }
  772         }
  773 
  774 #ifdef DEBUG
  775         if (sec_debug > 1)
  776                 printf("done\n");
  777 #endif DEBUG
  778         return (cibs);
  779 }
  780 
  781 
  782 /*
  783  * SEC_init_channels
  784  *
  785  * Issue the INIT command to the specified SEC controller
  786  * after collecting all the relevant data for each channel.
  787  */
  788 
  789 #define DELAY_TIME      50000
  790 
  791 SEC_init_channels(SEC_idx, desc, conf, cibs, errbin, errvec)
  792         int SEC_idx;
  793         register struct sec_desc *desc;
  794         struct sec_conf *conf;
  795         struct sec_cib *cibs;
  796         u_char errbin;
  797         u_char errvec;
  798 {
  799         struct sec_init_chan_data data;
  800         struct sec_driver *driver;
  801         register struct sec_chan_descr *cp;
  802         register struct sec_dev *dev;
  803         int i, chan, delay;
  804 
  805         assert(desc - SEC_desc == SEC_idx);
  806         assert(KVTOPHYS(&data, int) < 4*1024*1024);
  807         assert(desc->sec_powerup != 0);
  808 
  809         data.sic_status = 0;
  810         data.sic_cib = KVTOPHYS(cibs, struct sec_cib *);
  811         for (i = 0; i < SDEV_NUM_DEVICES; ++i) {
  812                 data.sic_chans[i].scd_requestq = 0;
  813                 data.sic_chans[i].scd_doneq = 0;
  814                 data.sic_chans[i].scd_bin = 0;
  815                 data.sic_chans[i].scd_vector = 0;
  816                 data.sic_chans[i].scd_destslic = 0;
  817         }
  818 #ifdef DEBUG
  819         if (sec_debug > 1)
  820                 printf("SEC_init_channels: cibs @ 0x%x, data @ 0x%x\n", data.sic_cib, &data);
  821 #endif DEBUG
  822 
  823         for (; conf->sec_driver; ++conf) {
  824                 driver = conf->sec_driver;
  825                 for (i = 0; i < conf->sec_nent; ++i) {
  826                         dev = &conf->sec_dev[i];
  827                         if (!dev->sd_alive)
  828                                 continue;
  829 
  830                         if (dev->sd_sec_idx != SEC_idx)
  831                                 continue;
  832 
  833                         /*
  834                          * Found a device on this SEC controller.
  835                          * Add its entry to the data to be initialized.
  836                          */
  837                         if (driver->sed_cflags & SED_IS_SCSI) {
  838                                 chan = driver->sed_base_chan + 8*dev->sd_target + dev->sd_unit;
  839                         } else {
  840                                 chan = driver->sed_base_chan + dev->sd_unit;
  841                         }
  842                         cp = &data.sic_chans[chan];
  843                         if (cp ->scd_requestq != (struct sec_progq *)0) {
  844                                 printf("%s%d: ioconf.c error, already initialized: target %d unit %d\n",
  845                                         driver->sed_name, i, dev->sd_target, dev->sd_unit);
  846                                 continue;
  847                         }
  848                         assert(dev->sd_cib != 0);
  849                         assert(dev->sd_requestq != 0);
  850                         assert(dev->sd_doneq != 0);
  851                         assert(dev->sd_bin != 0);
  852                         cp->scd_requestq =
  853                             KVTOPHYS(dev->sd_requestq, struct sec_progq *);
  854                 /*      cp->scd_requestq->pq_head = cp->scd_requestq->pq_tail = dev->sd_req_size; */
  855                         dev->sd_requestq->pq_head = dev->sd_req_size;
  856                         dev->sd_requestq->pq_tail = dev->sd_req_size;
  857 
  858                         cp->scd_doneq =
  859                             KVTOPHYS(dev->sd_doneq, struct sec_progq *);
  860                 /*      cp->scd_doneq->pq_head = cp->scd_doneq->pq_tail = dev->sd_doneq_size; */
  861                         dev->sd_doneq->pq_head = dev->sd_doneq_size;
  862                         dev->sd_doneq->pq_tail = dev->sd_doneq_size;
  863 
  864                         cp->scd_bin = dev->sd_bin;
  865                         cp->scd_vector = dev->sd_vector;
  866                         cp->scd_destslic = dev->sd_destslic;
  867                         assert(cp->scd_requestq != 0);
  868                         assert(cp->scd_doneq != 0);
  869                         assert(cp->scd_bin != 0);
  870 #ifdef DEBUG
  871                         if (sec_debug > 1)
  872                                 printf("  add 0x%x: dev %s%d: unit %d base %d chan %d cib 0x%x rq 0x%x dq 0x%x bin %d vector 0x%x destslic 0x%x\n",
  873                                         cp, driver->sed_name, i, dev->sd_unit,
  874                                         driver->sed_base_chan, chan,
  875                                         &data.sic_cib[chan], cp->scd_requestq,
  876                                         cp->scd_doneq, cp->scd_bin,
  877                                         cp->scd_vector, cp->scd_destslic);
  878 #endif DEBUG
  879                 }
  880         }
  881 
  882         /*
  883          * Initialize TOD interrupts from console SCED.
  884          */
  885         if (desc->sec_is_cons) {
  886                 data.sic_chans[SDEV_TOD].scd_bin = TODCLKBIN;
  887                 data.sic_chans[SDEV_TOD].scd_vector = TODCLKVEC;
  888 #ifdef  MACH
  889                 data.sic_chans[SDEV_TOD].scd_destslic = mono_P_slic;
  890 #else   MACH
  891                 data.sic_chans[SDEV_TOD].scd_destslic = SL_GROUP|TMPOS_GROUP;
  892 #endif  MACH
  893         }
  894 
  895         /*
  896          * Initialize this SEC's error bin, vector. Also, tell SEC
  897          * where to place the copy of its access error register for
  898          * the kernel.
  899          */
  900         data.sic_chans[SDEV_SCSIBOARD].scd_bin = errbin;
  901         data.sic_chans[SDEV_SCSIBOARD].scd_vector = errvec;
  902 #ifdef  MACH
  903         data.sic_chans[SDEV_SCSIBOARD].scd_destslic = mono_P_slic;
  904 #else   MACH
  905         data.sic_chans[SDEV_SCSIBOARD].scd_destslic = SL_GROUP|TMPOS_GROUP;
  906 #endif  MACH
  907         data.sic_chans[SDEV_SCSIBOARD].scd_doneq =
  908             KVTOPHYS(&SEC_accerr[errvec-SEC_errbase], struct sec_progq *);
  909 
  910         /*
  911          * Initialize the channels.
  912          */
  913         desc->sec_powerup->pu_cib.cib_inst = SINST_INIT;
  914         desc->sec_powerup->pu_cib.cib_status = KVTOPHYS(&data, int *);
  915 #ifdef DEBUG
  916         if (sec_debug>1) {
  917                 printf("Before SINST_INIT: cib 0x%x, cib_status 0x%x\nchans:\n",
  918                                 &desc->sec_powerup->pu_cib,
  919                                 desc->sec_powerup->pu_cib.cib_status);
  920                 for (i = 0; i < SDEV_NUM_DEVICES; ++i) {
  921                         if (data.sic_chans[i].scd_requestq == (struct sec_progq *)0)
  922                                 continue;
  923                         cp = &data.sic_chans[i];
  924                         printf("   %d (0x%x): reqq 0x%x doneq 0x%x bin %d vector %d\n",
  925                                 i, cp, cp->scd_requestq, cp->scd_doneq,
  926                                 cp->scd_bin, cp->scd_vector);
  927                 }
  928                 printf("mIntr(%d, 7, 0): ", desc->sec_slicaddr);
  929         }
  930 #endif DEBUG
  931         mIntr(desc->sec_slicaddr, 7, 0);
  932         delay = calc_delay((unsigned int)DELAY_TIME);
  933         while ((data.sic_status & SINST_INSDONE) == 0) {
  934                 if (delay-- <= 0) {
  935                         printf("SEC_init_channels: no response after %d peeks\n",
  936                                         calc_delay((unsigned int)DELAY_TIME));
  937                         break;
  938                 }
  939         }
  940 
  941         data.sic_status &= ~SINST_INSDONE;
  942 #ifdef DEBUG
  943         if (sec_debug > 1)
  944                 printf("init_chan: status %d\n", data.sic_status);
  945         if (data.sic_status != 0) {
  946                 printf("can't initialize SCSI/Ether controller %d: status %d\n",
  947                                 i, data.sic_status);
  948         }
  949 #endif DEBUG
  950         /*
  951          * These are no longer valid.
  952          */
  953         desc->sec_powerup = (struct sec_powerup *)0;
  954 #ifdef DEBUG
  955         if (sec_debug>1)
  956                 printf("done\n");
  957 #endif DEBUG
  958 }
  959 
  960 /*
  961  * SEC_error()
  962  *      Error interrupt from SEC board(s).
  963  *
  964  * SEC received an access error. Report and panic.
  965  * This is a SPLHI interrupt routine.
  966  */
  967 
  968 int
  969 SEC_error(vector)
  970         u_char  vector;
  971 {
  972         int offset;
  973 
  974         offset = vector - SEC_errbase;
  975         printf("SEC%d received Access Error\n", offset);
  976         access_error(SEC_accerr[offset]);
  977         panic("SEC Access Error");
  978 }
  979 
  980 /* 
  981  * The following are run-time support routines used by device drivers.
  982  */
  983 #ifdef  MACH_KERNEL
  984 /*
  985  * buf_iat()
  986  *      Takes an io_req_t ('buf') and a struct iat * to
  987  *      set up an indirect address table for the SED.
  988  *
  989  * Returns nothing.
  990  * Does *NO* locking.
  991  *
  992  * Implementation assumes that the number of iat slots pointed to
  993  * by the iat parameter has enough entries to handle
  994  * (ior->io_count + (IATBYTES-1))/IATBYTES iat slots.
  995  *
  996  * All data is in the kernel map.
  997  *
  998  * Assumes NBPG >= IATBYTES.
  999  */
 1000 
 1001 /*ARGSUSED*/
 1002 buf_iat(bp, iat, niat)
 1003         struct buf      *bp;            /* io_req_t */
 1004         register struct sec_iat *iat;   /* iat descriptor */
 1005         int             niat;           /* Max iats to fill */
 1006 {
 1007         register int    bcount;
 1008         int             junkbytes;
 1009         vm_offset_t     virt_addr;
 1010         vm_offset_t     phys_addr;
 1011         register pt_entry_t *pte;
 1012         int             pgoffset;
 1013         int             iatoffset;
 1014 
 1015         bcount = bp->b_bcount;
 1016         junkbytes = 0;
 1017 
 1018         /*
 1019          * Look into alignment, since we can start on an arbitrary
 1020          * boundary.  Once the offset into the page is found and mapped,
 1021          * the iats are filled in IATBYTE chunks until the count is zero.
 1022          */
 1023 
 1024         virt_addr = (vm_offset_t)bp->b_un.b_addr;
 1025 
 1026         junkbytes = bcount % DEV_BSIZE;
 1027         pgoffset = virt_addr & (I386_PGBYTES - 1);
 1028         iatoffset = pgoffset & (IATBYTES-1);
 1029 
 1030         pte = pmap_pte(kernel_pmap, virt_addr);
 1031         phys_addr = pte_to_pa(*pte) + pgoffset;
 1032 
 1033         iat->iat_data = (u_char *) phys_addr;
 1034         iat->iat_count = MIN(IATBYTES-iatoffset, bcount);
 1035         bcount -= iat->iat_count;
 1036         phys_addr += iat->iat_count;
 1037 
 1038         ++pte;
 1039         ++iat;
 1040 
 1041         for (; bcount > 0; phys_addr += IATBYTES, bcount -= IATBYTES, iat++)
 1042         {
 1043             if ((phys_addr & (I386_PGBYTES-1)) == 0) {
 1044                 phys_addr = pte_to_pa(*pte);
 1045                 pte++;
 1046             }
 1047             iat->iat_count = MIN(bcount, IATBYTES);
 1048             iat->iat_data = (u_char *)phys_addr;
 1049         }
 1050 
 1051         /*
 1052          * On raw transfers, round up to a DEV_BSIZE (512) byte transfer
 1053          * because the interface is block (DEV_BSIZE) oriented.
 1054          */
 1055         if (junkbytes) {
 1056             iat->iat_count = DEV_BSIZE - junkbytes;
 1057             iat->iat_data = SECgarbuf;
 1058         }
 1059 }
 1060 
 1061 /*
 1062  * bufiat_sz()
 1063  *      Takes a "bp" (struct buf *) and returns the number of
 1064  *      indirect address tables needed for this io operation.
 1065  *
 1066  * Returns count of iats required.
 1067  *
 1068  * Does *no* locking.
 1069  *
 1070  * Assumes NBPG >= IATBYTES.
 1071  */
 1072 
 1073 buf_iatsz(bp)
 1074         register struct buf     *bp;                    /* buffer header */
 1075 {
 1076 
 1077         /*
 1078          * Raw can start on any byte boundary so will add an
 1079          * extra iat to map an additional page when it is
 1080          * needed.
 1081          *
 1082          * IATVARIANCE is used to tell the device drivers the 
 1083          * number of iats used for data alignment so that the
 1084          * the drivers can calculate the maximum transfer count
 1085          * based on an iat count.
 1086          *
 1087          * Add an additional iat for garbage collection of the
 1088          * last block.
 1089          */
 1090 
 1091         return (howmany(bp->b_bcount, IATBYTES) + IATVARIANCE + 1);
 1092 }
 1093 
 1094 #else   /* MACH_KERNEL */
 1095 
 1096 #ifdef  MACH
 1097 
 1098 /*
 1099  * buf_iat()
 1100  *      Takes a "bp" (struct buf *) and iat (struct iat *) to
 1101  *      setup an indirect address table for the SED.
 1102  *
 1103  * Returns returns nothing.
 1104  * Does *no* locking.
 1105  * Panics if bad pte found; "can't" happen.
 1106  *
 1107  * Implementation assumes that the number of iat slots
 1108  * pointed to by the iat parameter has enough entries to
 1109  * handle (bp->b_bcount+(IATBYTES-1))/IATBYTES iat slots.
 1110  *
 1111  * B_RAWIO, B_PTEIO, B_PTBIO cases must flush TLB to avoid stale mappings
 1112  * thru Usrptmap[], since this is callable from interrupt procedures.
 1113  *
 1114  * Also assumes NBPG >= IATBYTES, and IATBYTES divides CLBYTES.
 1115  */
 1116 
 1117 /*ARGSUSED*/
 1118 buf_iat(bp, iat, niat)
 1119         struct  buf     *bp;                    /* buffer header */
 1120         register struct sec_iat *iat;           /* iat descriptor */
 1121         int             niat;                   /* Max iat's to spray */
 1122 {
 1123         register unsigned paddr = 0;
 1124         register int    bcount = bp->b_bcount;
 1125         struct  pte     *pte;
 1126         int             junkbytes = 0;
 1127         unsigned        pgoffset;
 1128         unsigned        iatoffset;
 1129 
 1130 #ifdef  DEBUG
 1131         assert(iat != 0);
 1132         assert(bcount > 0);
 1133         assert(niat > 0);
 1134 #endif  DEBUG
 1135 
 1136         /*
 1137          * Source/target pte's are found differently based on type
 1138          * of IO operation.
 1139          */
 1140 
 1141         if (bp->b_flags & B_PHYS) {
 1142                 /*
 1143                  * In this case, must look into alignment of physical
 1144                  * memory, since we can start on arbitrary boundary.
 1145                  * Once the offset into the page is found and mapped,
 1146                  * the iat's are sprayed in IATBYTE chunks until b_bcount 
 1147                  * is zero.
 1148                  */
 1149 
 1150                 junkbytes = bcount % DEV_BSIZE;
 1151                 pte = (struct pte *) pmap_pte(vm_map_pmap(bp->b_proc->task->map),
 1152                                         (vm_offset_t)bp->b_un.b_addr | VA_USER);
 1153                 pgoffset = (int)bp->b_un.b_addr & (NBPG-1);
 1154                 iatoffset = pgoffset & (IATBYTES-1);
 1155                 paddr = PTETOPHYS(*pte) + pgoffset;
 1156                 iat->iat_data = (u_char *) paddr;
 1157                 iat->iat_count = MIN(IATBYTES-iatoffset, bcount);
 1158                 bcount -= iat->iat_count;
 1159                 paddr += iat->iat_count;
 1160 #ifdef  DEBUG
 1161                 --niat;
 1162                 if (bcount > 0)
 1163                         assert((paddr&(IATBYTES-1)) == 0);
 1164                 if (sec_debug)
 1165                         printf("iat = 0x%x %d\n", iat->iat_data,iat->iat_count);
 1166 #endif  DEBUG
 1167                 ++pte;
 1168                 ++iat;
 1169         } else {
 1170 
 1171                 /*
 1172                  * Filesys/buffer-cache IO.  These are always cluster aligned
 1173                  * both physically and virtually.  b_bcount is a multiple of 
 1174                  * DEV_BSIZE.
 1175                  */
 1176 
 1177                 pte = &Sysmap[btop(bp->b_un.b_addr)];
 1178 #ifdef  DEBUG
 1179                 if (((int)bp->b_un.b_addr & (IATBYTES-1)) != 0) {
 1180                         printf("bp=0x%x, addr=0x%x\n", bp, bp->b_un.b_addr);
 1181                         panic("buf_iat: bad FS IO");
 1182                 }
 1183                 if (bp->b_bcount <= 0 || bp->b_bcount > MAXBSIZE) {
 1184                         printf("bp=0x%x, bcount=%d\n", bp, bp->b_bcount);
 1185                         panic("buf_iat: bad FS count");
 1186                 }
 1187 #endif  DEBUG
 1188         }
 1189 
 1190         /*
 1191          * Check count, and set up the iat's.
 1192          */
 1193 
 1194 #ifdef  DEBUG
 1195         assert(howmany(bcount);
 1196 #endif  DEBUG
 1197 
 1198         for (; bcount > 0; paddr += IATBYTES, bcount -= IATBYTES, iat++) {
 1199                 if ((paddr & (NBPG-1)) == 0) {
 1200 #ifdef  DEBUG
 1201                         assert(PTEPF(*pte) != 0);
 1202 #endif  DEBUG
 1203                         paddr = PTETOPHYS(*pte);
 1204                         ++pte;
 1205                 }
 1206                 iat->iat_count = MIN(bcount, IATBYTES);
 1207                 iat->iat_data = (u_char *) paddr;
 1208 #ifdef  DEBUG
 1209                 if (sec_debug)
 1210                         printf("iat = 0x%x %d\n", iat->iat_data,iat->iat_count);
 1211                 assert(iat->iat_count > 0);
 1212 #endif  DEBUG
 1213         }
 1214 
 1215         /*
 1216          * On raw xfers, round up to a DEV_BSIZE (512) byte transfer because
 1217          * interface is block (DEV_BSIZE) oriented.
 1218          */
 1219 
 1220         if (junkbytes) {
 1221                 iat->iat_count = DEV_BSIZE - junkbytes;
 1222                 iat->iat_data = SECgarbuf;
 1223 #ifdef DEBUG
 1224                 if (sec_debug > 1)
 1225                         printf("buf_iat: %d garbage bytes from bcount = %d\n",
 1226                                         iat->iat_count, bp->b_bcount); 
 1227 #endif DEBUG
 1228         }
 1229 }
 1230 
 1231 /*
 1232  * bufiat_sz()
 1233  *      Takes a "bp" (struct buf *) and returns the number of
 1234  *      indirect address tables needed for this io operation.
 1235  *
 1236  * Returns count of iats required.
 1237  *
 1238  * Does *no* locking.
 1239  *
 1240  * Assumes NBPG >= IATBYTES.
 1241  */
 1242 
 1243 buf_iatsz(bp)
 1244         register struct buf     *bp;                    /* buffer header */
 1245 {
 1246 
 1247         if (bp->b_flags & B_PHYS) {
 1248                 /*
 1249                  * Raw can start on any byte boundary so will add an
 1250                  * extra iat to map an additional page when it is
 1251                  * needed.
 1252                  *
 1253                  * IATVARIANCE is used to tell the device drivers the 
 1254                  * number of iat's used for data alignment so that the
 1255                  * the drivers can calculate the maximum transfer count
 1256                  * based on an iat count.
 1257                  *
 1258                  * Add an additional iat for garbage collection of the
 1259                  * last block.
 1260                  */
 1261 
 1262                 return (howmany(bp->b_bcount, IATBYTES) + IATVARIANCE +1);
 1263         } else {
 1264 
 1265                 /*
 1266                  * Pte-based IO -- already know pte of 1st page, which
 1267                  * is cluster aligned, and b_count is a multiple of CLBYTES.
 1268                  *
 1269                  * Page-table based IO is page-aligned and b_bcount is
 1270                  * a multiple of NBPG.
 1271                  *
 1272                  * Filesys/buffer-cache IO.  These always start cluster aligned
 1273                  * both physically and virtually. 
 1274                  */
 1275                 return (howmany(bp->b_bcount, IATBYTES));
 1276         }
 1277 
 1278 }
 1279 #else   MACH
 1280 
 1281 #if     NBPG >= IATBYTES                        /* eg, SGS */
 1282 
 1283 /*
 1284  * buf_iat()
 1285  *      Takes a "bp" (struct buf *) and iat (struct iat *) to
 1286  *      setup an indirect address table for the SED.
 1287  *
 1288  * Returns returns nothing.
 1289  * Does *no* locking.
 1290  * Panics if bad pte found; "can't" happen.
 1291  *
 1292  * Implementation assumes that the number of iat slots
 1293  * pointed to by the iat parameter has enough entries to
 1294  * handle (bp->b_bcount+(IATBYTES-1))/IATBYTES iat slots.
 1295  *
 1296  * B_RAWIO, B_PTEIO, B_PTBIO cases must flush TLB to avoid stale mappings
 1297  * thru Usrptmap[], since this is callable from interrupt procedures.
 1298  *
 1299  * Also assumes NBPG >= IATBYTES, and IATBYTES divides CLBYTES.
 1300  */
 1301 
 1302 /*ARGSUSED*/
 1303 buf_iat(bp, iat, niat)
 1304         struct  buf     *bp;                    /* buffer header */
 1305         register struct sec_iat *iat;           /* iat descriptor */
 1306         int             niat;                   /* Max iat's to spray */
 1307 {
 1308         register unsigned paddr = 0;
 1309         register int    bcount = bp->b_bcount;
 1310         struct  pte     *pte;
 1311         int             junkbytes = 0;
 1312         unsigned        pgoffset;
 1313         unsigned        iatoffset;
 1314         struct pte      *vtopte();
 1315 
 1316 #ifdef  DEBUG
 1317         assert(iat != 0);
 1318         assert(bcount > 0);
 1319         assert(niat > 0);
 1320 #endif  DEBUG
 1321 
 1322         /*
 1323          * Source/target pte's are found differently based on type
 1324          * of IO operation.
 1325          */
 1326 
 1327         switch(bp->b_iotype) {
 1328         case B_RAWIO:                                   /* RAW IO */
 1329                 /*
 1330                  * In this case, must look into alignment of physical
 1331                  * memory, since we can start on arbitrary boundary.
 1332                  * Once the offset into the page is found and mapped,
 1333                  * the iat's are sprayed in IATBYTE chunks until b_bcount 
 1334                  * is zero.
 1335                  */
 1336 
 1337                 flush_tlb();
 1338                 junkbytes = bcount % DEV_BSIZE;
 1339                 pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr));
 1340                 pgoffset = (int)bp->b_un.b_addr & (NBPG-1);
 1341                 iatoffset = pgoffset & (IATBYTES-1);
 1342                 paddr = PTETOPHYS(*pte) + pgoffset;
 1343                 iat->iat_data = (u_char *) paddr;
 1344                 iat->iat_count = MIN(IATBYTES-iatoffset, bcount);
 1345                 bcount -= iat->iat_count;
 1346                 paddr += iat->iat_count;
 1347 #ifdef  DEBUG
 1348                 --niat;
 1349                 if (bcount > 0)
 1350                         assert((paddr&(IATBYTES-1)) == 0);
 1351                 if (sec_debug)
 1352                         printf("iat = 0x%x %d\n", iat->iat_data,iat->iat_count);
 1353 #endif  DEBUG
 1354                 ++pte;
 1355                 ++iat;
 1356                 break;
 1357 
 1358         case B_FILIO:                                   /* file-sys IO */
 1359                 /*
 1360                  * Filesys/buffer-cache IO.  These are always cluster aligned
 1361                  * both physically and virtually.  b_bcount is a multiple of 
 1362                  * DEV_BSIZE.
 1363                  */
 1364 
 1365                 pte = &Sysmap[btop(bp->b_un.b_addr)];
 1366 #ifdef  DEBUG
 1367                 if (((int)bp->b_un.b_addr & (IATBYTES-1)) != 0) {
 1368                         printf("bp=0x%x, addr=0x%x\n", bp, bp->b_un.b_addr);
 1369                         panic("buf_iat: bad FS IO");
 1370                 }
 1371                 if (bp->b_bcount <= 0 || bp->b_bcount > MAXBSIZE) {
 1372                         printf("bp=0x%x, bcount=%d\n", bp, bp->b_bcount);
 1373                         panic("buf_iat: bad FS count");
 1374                 }
 1375 #endif  DEBUG
 1376                 break;
 1377 
 1378         case B_PTBIO:                                   /* Page-Table IO */
 1379                 /*
 1380                  * Page-Table IO: like B_PTEIO, but can start/end with
 1381                  * non-cluster aligned memory (but is always HW page
 1382                  * aligned).  Count is multiple of NBPG.
 1383                  *
 1384                  * Since NBPG >= IATBYTES, this case is identical to
 1385                  * B_PTEIO, so...
 1386                  */
 1387 
 1388         case B_PTEIO:                                   /* swap/page IO */
 1389                 /*
 1390                  * Pte-based IO -- already know pte of 1st page, which
 1391                  * is cluster aligned, and b_count is a multiple of CLBYTES.
 1392                  */
 1393 
 1394                 flush_tlb();
 1395                 pte = bp->b_un.b_pte;
 1396                 break;
 1397 
 1398         default:
 1399                 panic("buf_iat: bad b_iotype");
 1400                 /*NOTREACHED*/
 1401         }
 1402 
 1403         /*
 1404          * Check count, and set up the iat's.
 1405          */
 1406 
 1407 #ifdef  DEBUG
 1408         assert(howmany(bcount);
 1409 #endif  DEBUG
 1410 
 1411         for (; bcount > 0; paddr += IATBYTES, bcount -= IATBYTES, iat++) {
 1412                 if ((paddr & (NBPG-1)) == 0) {
 1413 #ifdef  DEBUG
 1414                         assert(PTEPF(*pte) != 0);
 1415 #endif  DEBUG
 1416                         paddr = PTETOPHYS(*pte);
 1417                         ++pte;
 1418                 }
 1419                 iat->iat_count = MIN(bcount, IATBYTES);
 1420                 iat->iat_data = (u_char *) paddr;
 1421 #ifdef  DEBUG
 1422                 if (sec_debug)
 1423                         printf("iat = 0x%x %d\n", iat->iat_data,iat->iat_count);
 1424                 assert(iat->iat_count > 0);
 1425 #endif  DEBUG
 1426         }
 1427 
 1428         /*
 1429          * On raw xfers, round up to a DEV_BSIZE (512) byte transfer because
 1430          * interface is block (DEV_BSIZE) oriented.
 1431          */
 1432 
 1433         if (junkbytes) {
 1434                 iat->iat_count = DEV_BSIZE - junkbytes;
 1435                 iat->iat_data = SECgarbuf;
 1436 #ifdef DEBUG
 1437                 if (sec_debug > 1)
 1438                         printf("buf_iat: %d garbage bytes from bcount = %d\n",
 1439                                         iat->iat_count, bp->b_bcount); 
 1440 #endif DEBUG
 1441         }
 1442 }
 1443 
 1444 /*
 1445  * bufiat_sz()
 1446  *      Takes a "bp" (struct buf *) and returns the number of
 1447  *      indirect address tables needed for this io operation.
 1448  *
 1449  * Returns count of iats required.
 1450  *
 1451  * Does *no* locking.
 1452  *
 1453  * Assumes NBPG >= IATBYTES.
 1454  */
 1455 
 1456 buf_iatsz(bp)
 1457         register struct buf     *bp;                    /* buffer header */
 1458 {
 1459 
 1460         switch(bp->b_iotype) {
 1461         case B_RAWIO:                                   /* RAW IO */
 1462                 /*
 1463                  * Raw can start on any byte boundary so will add an
 1464                  * extra iat to map an additional page when it is
 1465                  * needed.
 1466                  *
 1467                  * IATVARIANCE is used to tell the device drivers the 
 1468                  * number of iat's used for data alignment so that the
 1469                  * the drivers can calculate the maximum transfer count
 1470                  * based on an iat count.
 1471                  *
 1472                  * Add an additional iat for garbage collection of the
 1473                  * last block.
 1474                  */
 1475 
 1476                 return (howmany(bp->b_bcount, IATBYTES) + IATVARIANCE +1);
 1477 
 1478         case B_PTEIO:                                   /* swap/page IO */
 1479         case B_PTBIO:                                   /* Page-Table IO */
 1480         case B_FILIO:                                   /* file-sys IO */
 1481                 /*
 1482                  * Pte-based IO -- already know pte of 1st page, which
 1483                  * is cluster aligned, and b_count is a multiple of CLBYTES.
 1484                  *
 1485                  * Page-table based IO is page-aligned and b_bcount is
 1486                  * a multiple of NBPG.
 1487                  *
 1488                  * Filesys/buffer-cache IO.  These always start cluster aligned
 1489                  * both physically and virtually. 
 1490                  */
 1491                 return (howmany(bp->b_bcount, IATBYTES));
 1492 
 1493         default:
 1494                 panic("buf_iatsz: bad b_iotype");
 1495                 /*NOTREACHED*/
 1496         }
 1497 }
 1498 
 1499 #else   NBPG < IATBYTES                         /* eg, FGS */
 1500 
 1501 /*
 1502  * PTESEDOFF returns offset of memory pointed at by pte.
 1503  */
 1504 
 1505 #define PTESEDOFF(pte) \
 1506                 ((unsigned)((*(int*)(&(pte))) & ((~(NBPG-1))&(IATBYTES-1))))
 1507 
 1508 /*
 1509  * buf_iat()
 1510  *      Takes a "bp" (struct buf *) and iat (struct iat *) to
 1511  *      setup an indirect address table for the SED.
 1512  *
 1513  * Returns returns nothing.
 1514  * Does *no* locking.
 1515  * Panics if bad pte found; "can't" happen.
 1516  *
 1517  * Implementation assumes that the number of iat slots
 1518  * pointed to by the iat parameter has enough entries to
 1519  * handle (bp->b_bcount+(CLBYTES-1))/CLBYTES iat slots.
 1520  * Also assumes NBPG<=IATBYTES<=CLBYTES, and IATBYTES divides CLBYTES.
 1521  */
 1522 
 1523 buf_iat(bp, iat, niat)
 1524         register struct buf     *bp;            /* buffer header */
 1525         register struct sec_iat *iat;           /* iat descriptor */
 1526         int             niat;                   /* Max iat's to spray */
 1527 {
 1528         register struct pte *pte;
 1529         register int    count;
 1530         register int    bcount;
 1531         int             offset;
 1532         struct pte      *vtopte();
 1533         int             iatbytes = 0;
 1534         extern          u_char  *SECgarbuf;
 1535 
 1536 #ifdef  DEBUG
 1537         assert(iat != 0);
 1538         assert(bp->b_bcount > 0);
 1539         assert(niat > 0);
 1540 #endif  DEBUG
 1541 
 1542         /*
 1543          * Source/target pte's are found differently based on type
 1544          * of IO operation.
 1545          */
 1546 
 1547         switch(bp->b_iotype) {
 1548         case B_RAWIO:                                   /* RAW IO */
 1549                 /*
 1550                  * In this case, must look into alignment of physical
 1551                  * memory, since we can start on arbitrary boundary.
 1552                  * Once the offset into the page is found and mapped,
 1553                  * the iat's are sprayed in IATBYTE chunks until b_bcount 
 1554                  * is zero.
 1555                  */
 1556 
 1557                 flush_tlb();
 1558                 pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr));
 1559                 offset = PTESEDOFF(*pte) + ((int)bp->b_un.b_addr & (NBPG-1));
 1560                 pte -= btop(offset);
 1561                 iat->iat_data = (u_char *)PTETOPHYS(*pte) + offset;
 1562                 iat->iat_count = MIN(IATBYTES-offset, bp->b_bcount);
 1563                 bcount = bp->b_bcount - iat->iat_count;
 1564                 count = (bcount + (IATBYTES-1)) / IATBYTES;
 1565                 iat++;
 1566                 niat--;
 1567                 pte += IATSIZE;
 1568                 iatbytes = bp->b_bcount % DEV_BSIZE;
 1569                 break;
 1570 
 1571         case B_FILIO:                                   /* file-sys IO */
 1572                 /*
 1573                  * Filesys/buffer-cache IO.  These are always cluster aligned
 1574                  * both physically and virtually.  b_bcount is a multiple of 
 1575                  * DEVBSIZE (512, currently).
 1576                  */
 1577 
 1578                 pte = &Sysmap[btop(bp->b_un.b_addr)];
 1579                 bcount = bp->b_bcount;
 1580                 count = (bcount + IATBYTES-1) / IATBYTES;
 1581 #ifdef  DEBUG
 1582                 if (((int)bp->b_un.b_addr & (IATBYTES-1)) != 0) {
 1583                         printf("bp=0x%x, addr=0x%x\n", bp, bp->b_un.b_addr);
 1584                         panic("buf_iat: bad FS IO");
 1585                 }
 1586                 if (bp->b_bcount <= 0 || bp->b_bcount > MAXBSIZE) {
 1587                         printf("bp=0x%x, bcount=%d\n", bp, bp->b_bcount);
 1588                         panic("buf_iat: bad FS count");
 1589                 }
 1590 #endif  DEBUG
 1591                 break;
 1592 
 1593         case B_PTEIO:                                   /* swap/page IO */
 1594                 /*
 1595                  * Pte-based IO -- already know pte of 1st page, which
 1596                  * is cluster aligned, and b_count is a multiple of CLBYTES.
 1597                  * Since IATBYTES <= CLBYTES, and IATBYTES divides CLBYTES,
 1598                  * can just divide IATBYTES.
 1599                  *
 1600                  * One special case here is read/write of Uarea during
 1601                  * swap -- swap code passes in b_bcount = UPAGES*NBPG
 1602                  * and b_iotype == B_PTEIO.  Thus, insure CLSIZE divides
 1603                  * UPAGES.
 1604                  */
 1605 
 1606 #               if UPAGES % CLSIZE != 0
 1607                         ERROR -- code assumes UPAGES is multiple of CLSIZE
 1608 #               endif
 1609 
 1610                 flush_tlb();
 1611                 pte = bp->b_un.b_pte;
 1612                 bcount = bp->b_bcount;
 1613                 count = bcount / IATBYTES;
 1614                 break;
 1615 
 1616         case B_PTBIO:                                   /* Page-Table IO */
 1617                 /*
 1618                  * Page-Table IO: like B_PTEIO, but can start/end with
 1619                  * non-cluster aligned memory (but is always HW page
 1620                  * aligned).  Count is multiple of NBPG.  Case mostly
 1621                  * borrowed from B_RAWIO.
 1622                  *
 1623                  * Separate case for greater efficiency in B_PTEIO.
 1624                  */
 1625 
 1626                 flush_tlb();
 1627                 pte = bp->b_un.b_pte;
 1628                 offset = PTESEDOFF(*pte);
 1629                 pte -= btop(offset);
 1630                 iat->iat_data = (u_char *)PTETOPHYS(*pte) + offset;
 1631                 iat->iat_count = MIN(IATBYTES-offset, bp->b_bcount);
 1632                 bcount = bp->b_bcount - iat->iat_count;
 1633                 count = (bcount + (IATBYTES-1)) / IATBYTES;
 1634                 iat++;
 1635                 niat--;
 1636                 pte += IATSIZE;
 1637                 break;
 1638 
 1639         default:
 1640                 panic("buf_iat: bad b_iotype");
 1641                 /*NOTREACHED*/
 1642         }
 1643 
 1644         /*
 1645          * Check count, and set up the iat's.
 1646          */
 1647 
 1648         assert(count <= niat);
 1649 
 1650         for (; count--; pte += (IATBYTES/NBPG), bcount -= IATBYTES, iat++) {
 1651                 iat->iat_count = MIN(bcount, IATBYTES);
 1652                 iat->iat_data = (u_char *)PTETOPHYS(*pte);
 1653 #ifdef  DEBUG
 1654                 if (sec_debug)
 1655                         printf("iat = 0x%x %d\n", PTETOPHYS(*pte), iat->iat_count);
 1656                 assert(PTEPF(*pte) != 0);
 1657                 assert((PTETOPHYS(*pte) & (IATBYTES-1)) == 0);
 1658                 assert(iat->iat_count > 0);
 1659 #endif  DEBUG
 1660         }
 1661 
 1662         /*
 1663          * On raw xfers, round up to a DEV_BSIZE (512) byte transfer because
 1664          * interface is block (DEV_BSIZE) oriented.
 1665          */
 1666         if (iatbytes>0) {
 1667                 iat->iat_count = DEV_BSIZE - iatbytes;
 1668                 iat->iat_data = SECgarbuf;
 1669 #ifdef DEBUG
 1670                 if (sec_debug>1)
 1671                         printf("collecting garbage bytes of %d from a bcount of %d\n",
 1672                                         iat->iat_count, bp->b_bcount); 
 1673 #endif DEBUG
 1674         }
 1675 }
 1676 
 1677 /*
 1678  * bufiat_sz()
 1679  *      Takes a "bp" (struct buf *) to
 1680  *      determine the number of indirect address tables needed for
 1681  *      this io operation.
 1682  *
 1683  * Returns count of iats required.
 1684  * Does *no* locking.
 1685  *
 1686  * Guesstimate number of iat's needed for this xfer.
 1687  * Assumes NBPG<=IATBYTES<=CLBYTES
 1688  */
 1689 
 1690 buf_iatsz(bp)
 1691         register struct buf     *bp;                    /* buffer header */
 1692 {
 1693 
 1694         switch(bp->b_iotype) {
 1695         case B_RAWIO:                                   /* RAW IO */
 1696         case B_PTBIO:                                   /* Page-Table IO */
 1697                 /*
 1698                  * Raw can start on any byte boundary so will add an
 1699                  * extra iat to map an additional page when it is
 1700                  * needed.  Page-Table IO similar (can start in middle
 1701                  * of page), but more constrained.
 1702                  *
 1703                  * IATVARIANCE is used to tell the device drivers the 
 1704                  * number of iat's used for data alignment so that the
 1705                  * the drivers can calculate the maximum transfer count
 1706                  * based on an iat count.
 1707                  *
 1708                  * Add an additional iat for garbage collection of the last block.
 1709                  */
 1710 
 1711                 return (howmany(bp->b_bcount, IATBYTES) + IATVARIANCE +1);
 1712 
 1713         case B_PTEIO:                                   /* swap/page IO */
 1714         case B_FILIO:                                   /* file-sys IO */
 1715                 /*
 1716                  * Pte-based IO -- already know pte of 1st page, which
 1717                  * is cluster aligned, and b_count is a multiple of CLBYTES.
 1718                  *
 1719                  * Filesys/buffer-cache IO.  These always start cluster aligned
 1720                  * both physically and virtually. 
 1721                  */
 1722                 return (howmany(bp->b_bcount, IATBYTES));
 1723 
 1724         default:
 1725                 panic("buf_iatsz: bad b_iotype");
 1726                 /*NOTREACHED*/
 1727         }
 1728 }
 1729 
 1730 #endif  NBPG >= IATBYTES
 1731 
 1732 #endif  MACH
 1733 #endif  /* MACH_KERNEL */
 1734 
 1735 /*
 1736  * SEC_startio - start an operation by sending a command to the
 1737  *              sec board via slic.
 1738  *
 1739  * This procedure may be used until the init command is sent
 1740  * to turn on sec interrupts, which occurs after the boot procedure
 1741  * routines for all device drivers have been called.
 1742  *
 1743  * Calls mIntr() to do the actual slic fussing to send the message.
 1744  *
 1745  * NOTE: It's critical that the status pointer live below 0x400000
 1746  * because the sec can't talk above that address, hence all status
 1747  * variable must *not* live on kernel stack.
 1748  */
 1749 
 1750 SEC_startio(cmd, statptr, bin, mesg, q, slicid)
 1751         register
 1752         volatile int    *statptr;
 1753         int             cmd;
 1754         unsigned char   bin;
 1755         unsigned char   mesg;
 1756         unsigned char   slicid;
 1757         struct  sec_cib *q;
 1758 {
 1759         register int    spin;
 1760 
 1761         *statptr = 0;
 1762         q->cib_inst = cmd;
 1763         q->cib_status = KVTOPHYS(statptr, volatile int *);
 1764 
 1765         mIntr(slicid, bin, mesg);
 1766 
 1767         spin = calc_delay(10 * DELAY_TIME);
 1768         while ((*statptr & SINST_INSDONE) == 0) {
 1769                 if (spin-- <= 0) {
 1770                         printf("SEC_startio: timeout\n");
 1771                         break;
 1772                 }
 1773         }
 1774 }
 1775 
 1776 /*
 1777  * sec_startio - start an operation by sending a command to the
 1778  *              sec board via slic.
 1779  *
 1780  * This procedure is used once interrupts have been enabled
 1781  * in the kernel.
 1782  *
 1783  * Calls mIntr() to do the actual slic fussing to send the message.  Use
 1784  * bin 3, since this helps avoid SLIC-bus saturation/lockup (since SCED
 1785  * interrupts Dynix mostly on bins 4-7, using bin 3 to interrupt SCED gives
 1786  * SCED -> Dynix priority over Dynix -> SCED, thus SCED won't deadlock
 1787  * against Dynix).  Initialization-time mIntr()'s can use other bins since
 1788  * SLIC-bus is not busy at that time.
 1789  *
 1790  * NOTE: It's critical that the status pointer live below 0x400000
 1791  * because the sec can't talk above that address, hence all status
 1792  * variable must *not* live on kernel stack.
 1793  */
 1794 
 1795 sec_startio(cmd, statptr, sd)
 1796         int             cmd;
 1797         register
 1798         volatile int    *statptr;
 1799         register struct sec_dev *sd;
 1800 {
 1801         register int    spin;
 1802 
 1803         *statptr = 0;
 1804         sd->sd_cib->cib_inst = cmd;
 1805         sd->sd_cib->cib_status = KVTOPHYS(statptr, int *);
 1806 
 1807         /*
 1808          * Must insure that the interrupt gets sent, so don't allow
 1809          * interrupts on this processor while sending the interrupt.
 1810          */
 1811 
 1812 #ifdef  ns32000
 1813         { spl_t spl = splhi();
 1814         mIntr(sd->sd_desc->sec_slicaddr, 3, sd->sd_chan);
 1815         splx(spl);
 1816         }
 1817 #endif  ns32000
 1818 
 1819 #ifdef  i386
 1820         DISABLE();
 1821         mIntr(sd->sd_desc->sec_slicaddr, 3, sd->sd_chan);
 1822         ENABLE();
 1823 #endif  i386
 1824 
 1825         spin = calc_delay(10 * DELAY_TIME);
 1826         while ((*statptr & SINST_INSDONE) == 0) {
 1827                 if (spin-- <= 0) {
 1828                         printf("sec_startio: timeout\n");
 1829                         break;
 1830                 }
 1831         }
 1832 }
 1833 
 1834 /* 
 1835  * u_char *                     <= IATIFIED PTR!
 1836  * SEC_rqinit(rqbuf, rqbufsz)
 1837  *      u_char *rqbuf;
 1838  *
 1839  * SEC_rqinit - init a request sense iat chain to
 1840  *      allow the SEC dma hardware to transfer complete
 1841  *      request sense data buffers which are *not* 8 byte
 1842  *      aligned. This procedure returns an SEC iat pointer
 1843  *      that is used to point at a request sense buffer
 1844  *      (ie. device_prog.dp_datap = rqbuf can be replaced with
 1845  *      device_prog.dp_datap = returned pointer). Max size is 255.
 1846  *
 1847  *      NOTE: the larger the buffer size the more memory this uses! 
 1848  *      Memory used =
 1849  *              sz<8    16 bytes.
 1850  *              sz<24   16+((sz-8)*8)           ; max 144 bytes
 1851  *              sz>24   144+((sz-24)/2)*8+8     ; max 1072 bytes (for 255 buf)
 1852  *
 1853  *      This hardware limititation is by-passed by
 1854  *      creating a chain of iat's that point to the
 1855  *      (passed in) buffer pointer in the following
 1856  *      structure respectively:
 1857  *      #iat's_used     length  bytes covered
 1858  *              1       4       0-3     (standard)
 1859  *              1       4       4-7     (extended)
 1860  *              16      1       8-23    (additional)
 1861  *              sz-24/2 2       24-sz   (additional)
 1862  *      
 1863  *      Note: this must be a generic buffer to handle
 1864  *      target adapter interchange since the number of
 1865  *      returned bytes from the target adapter will vary 
 1866  *      based on vendor, error type and buffer size.
 1867  *      Maximum buffer size allowed is 255.
 1868  *      Assumes calloc gets buffer from an address <4Mbyte.
 1869  *      For target adapters that transfer greater than 24 bytes
 1870  *      it's possible to loose the last byte on an odd transfer.
 1871  *      Returns type char * to please lint with straight replacement
 1872  *      in existing drivers. Enforces a minimum of eight bytes to
 1873  *      ease the iat fill out process.
 1874  *
 1875  *      This conforms to ansi X3T9.2/82-2 revision 14 specification.
 1876  *
 1877  */
 1878 
 1879 u_char  *
 1880 SEC_rqinit(rqbuf, rqbufsize)
 1881         register u_char *rqbuf;
 1882         register int    rqbufsize;
 1883 {
 1884         register u_char *ret_iatptr;
 1885         register struct sec_iat *iat;           /* iat descriptor */
 1886         register int    count;
 1887         int             iat_count;
 1888 #ifdef DEBUG
 1889         int             dcnt;
 1890         u_char          *drqbuf = rqbuf;
 1891 #endif DEBUG
 1892 
 1893         /*
 1894          * Calculate the iat chain size.
 1895          */
 1896 
 1897         rqbufsize = MAX(rqbufsize, 8);          /* enforce minimum of eight */
 1898         count = rqbufsize-8;
 1899         iat_count = 2;                          /* first two */
 1900         if (count>0) {
 1901                 iat_count += (count-16 > 0) ? 16 : count;       /* bytes 8-23 */
 1902                 count  -= 16;
 1903         }
 1904         if (count>0) {
 1905                 iat_count += count/2 + count%2; /* bytes 24-rqbufsize */
 1906                 count   = 0;                    /* for sanity */
 1907         }
 1908         assert(count<=0);
 1909 #ifdef DEBUG
 1910         if (sec_debug>1)
 1911                 printf("SEC_rqinit: iat's needed=%d\n", iat_count);
 1912         dcnt = iat_count;                       /* debug */
 1913 #endif DEBUG
 1914         
 1915         /*
 1916          * Allocate space for the iat's,
 1917          * and save the callers reference pointer.
 1918          */
 1919 
 1920         iat = (struct sec_iat *)calloc(iat_count*sizeof(struct sec_iat));
 1921         ret_iatptr = (u_char *)SEC_IATIFY(KVTOPHYS(iat,struct sec_iat *));
 1922 
 1923         /*
 1924          * Fill out iat chain.
 1925          */
 1926 
 1927         count = 0;
 1928         for (; count<2; count++, iat++, rqbuf = (u_char *)((int)rqbuf+4)) {
 1929                 iat->iat_count = 4;
 1930                 iat->iat_data = KVTOPHYS(rqbuf, u_char *);
 1931         }
 1932         iat_count -=2;
 1933 
 1934         /*
 1935          * Bytes 8-23.
 1936          */
 1937 
 1938         count = 0;
 1939         for (; count<16 && iat_count>0; count++, iat++, iat_count--, rqbuf++) {
 1940                 iat->iat_count = 1;
 1941                 iat->iat_data = KVTOPHYS(rqbuf, u_char *);
 1942         }
 1943 
 1944         /*
 1945          * Bytes 24-rqbufsize.
 1946          */
 1947 
 1948         for (; iat_count>0; iat++, iat_count--, rqbuf++, rqbuf++) {
 1949                 iat->iat_count = 2;
 1950                 iat->iat_data = KVTOPHYS(rqbuf, u_char *);
 1951         }
 1952 
 1953         /*
 1954          * Adjust the last iat if the count is odd, the data ptr is ok.
 1955          */
 1956 
 1957         if (rqbufsize&1) {
 1958                 iat--;
 1959                 iat->iat_count = 1;
 1960         }
 1961 
 1962 #ifdef DEBUG
 1963         if (sec_debug>1) {
 1964                 iat = PHYSTOKV((u_int)ret_iatptr & ~SEC_IAT_FLAG,
 1965                                 struct sec_iat *);
 1966                 for (; dcnt; dcnt--, iat++)
 1967                         printf("buf 0x%x iat 0x%x count %d retiat 0x%x\n",
 1968                                 drqbuf, iat->iat_data, iat->iat_count, ret_iatptr);
 1969         }
 1970 #endif DEBUG
 1971                         
 1972         return (ret_iatptr);
 1973 }
 1974 
 1975 /*
 1976  * sec_map()
 1977  *      Null memory mapping function.  
 1978  *
 1979  * Sec configuration doesn't need to map any address space; all data
 1980  * and interface memory is calloc()'d.
 1981  */
 1982 
 1983 sec_map() {}

Cache object: a7a21c6dac4f66402b646780aa0f13fd


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