home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / dev / rd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  33.1 KB  |  1,184 lines

  1. /*
  2.  * Copyright (c) 1988 University of Utah.
  3.  * Copyright (c) 1982, 1990 The Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * the Systems Programming Group of the University of Utah Computer
  8.  * Science Department.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  *
  38.  * from: Utah $Hdr: rd.c 1.38 90/10/12$
  39.  *
  40.  *    @(#)rd.c    7.9 (Berkeley) 5/7/91
  41.  */
  42.  
  43. /*
  44.  * CS80/SS80 disk driver
  45.  */
  46. #include "rd.h"
  47. #if NRD > 0
  48.  
  49. #include "sys/param.h"
  50. #include "sys/systm.h"
  51. #include "sys/errno.h"
  52. #include "sys/dkstat.h"
  53. #include "sys/disklabel.h"
  54. #include "sys/buf.h"
  55. #include "sys/uio.h"
  56.  
  57. #include "device.h"
  58. #include "rdreg.h"
  59.  
  60. #include "vm/vm_param.h"
  61. #include "vm/lock.h"
  62. #include "vm/vm_statistics.h"
  63. #include "vm/pmap.h"
  64. #include "vm/vm_prot.h"
  65.  
  66. int    rdinit(), rdstart(), rdgo(), rdintr();
  67. struct    driver rddriver = {
  68.     rdinit, "rd", rdstart, rdgo, rdintr,
  69. };
  70.  
  71. struct    rd_softc {
  72.     struct    hp_device *sc_hd;
  73.     int    sc_flags;
  74.     short    sc_type;
  75.     short    sc_punit;
  76.     char    *sc_addr;
  77.     int    sc_resid;
  78.     u_int    sc_wpms;
  79.     struct    rdinfo *sc_info;
  80.     struct    devqueue sc_dq;
  81.     struct    rd_iocmd sc_ioc;
  82.     struct    rd_rscmd sc_rsc;
  83.     struct    rd_stat sc_stat;
  84.     struct    rd_ssmcmd sc_ssmc;
  85.     struct    rd_srcmd sc_src;
  86.     struct    rd_clearcmd sc_clear;
  87. } rd_softc[NRD];
  88.  
  89. /* sc_flags values */
  90. #define    RDF_ALIVE    0x1
  91. #define    RDF_SEEK    0x2
  92. #define RDF_SWAIT    0x4
  93.  
  94. struct    size {
  95.     daddr_t    nblocks;
  96.     int    cyloff;
  97. };
  98.  
  99. #ifdef DEBUG
  100. int rddebug = 0x80;
  101. #define RDB_FOLLOW    0x01
  102. #define RDB_STATUS    0x02
  103. #define RDB_IDENT    0x04
  104. #define RDB_IO        0x08
  105. #define RDB_ASYNC    0x10
  106. #define RDB_ERROR    0x80
  107. #define RDB_DUMP    0x80000000
  108.  
  109. struct rdstats {
  110.     long    rdretries;
  111.     long    rdresets;
  112.     long    rdtimeouts;
  113.     long    rdpolltries;
  114.     long    rdpollwaits;
  115. } rdstats[NRD];
  116.  
  117. /* error message tables */
  118. char *err_reject[] = {
  119.     0, 0,
  120.     "channel parity error",        /* 0x2000 */
  121.     0, 0,
  122.     "illegal opcode",        /* 0x0400 */
  123.     "module addressing",        /* 0x0200 */
  124.     "address bounds",        /* 0x0100 */
  125.     "parameter bounds",        /* 0x0080 */
  126.     "illegal parameter",        /* 0x0040 */
  127.     "message sequence",        /* 0x0020 */
  128.     0,
  129.     "message length",        /* 0x0008 */
  130.     0, 0, 0
  131. };
  132.  
  133. char *err_fault[] = {
  134.     0,
  135.     "cross unit",            /* 0x4000 */
  136.     0,
  137.     "controller fault",        /* 0x1000 */
  138.     0, 0,
  139.     "unit fault",            /* 0x0200 */
  140.     0,
  141.     "diagnostic result",        /* 0x0080 */
  142.     0,
  143.     "operator release request",    /* 0x0020 */
  144.     "diagnostic release request",    /* 0x0010 */
  145.     "internal maintenance release request",    /* 0x0008 */
  146.     0,
  147.     "power fail",            /* 0x0002 */
  148.     "retransmit"            /* 0x0001 */
  149. };
  150.  
  151. char *err_access[] = {
  152.     "illegal parallel operation",    /* 0x8000 */
  153.     "uninitialized media",        /* 0x4000 */
  154.     "no spares available",        /* 0x2000 */
  155.     "not ready",            /* 0x1000 */
  156.     "write protect",        /* 0x0800 */
  157.     "no data found",        /* 0x0400 */
  158.     0, 0,
  159.     "unrecoverable data overflow",    /* 0x0080 */
  160.     "unrecoverable data",        /* 0x0040 */
  161.     0,
  162.     "end of file",            /* 0x0010 */
  163.     "end of volume",        /* 0x0008 */
  164.     0, 0, 0
  165. };
  166.  
  167. char *err_info[] = {
  168.     "operator release request",    /* 0x8000 */
  169.     "diagnostic release request",    /* 0x4000 */
  170.     "internal maintenance release request",    /* 0x2000 */
  171.     "media wear",            /* 0x1000 */
  172.     "latency induced",        /* 0x0800 */
  173.     0, 0,
  174.     "auto sparing invoked",        /* 0x0100 */
  175.     0,
  176.     "recoverable data overflow",    /* 0x0040 */
  177.     "marginal data",        /* 0x0020 */
  178.     "recoverable data",        /* 0x0010 */
  179.     0,
  180.     "maintenance track overflow",    /* 0x0004 */
  181.     0, 0
  182. };
  183. #endif
  184.  
  185. /*
  186.  * CS/80 partitions.  We reserve the first cylinder for a LIF
  187.  * style boot directory (the 8k allowed in the BSD filesystem
  188.  * is just way too small).  This boot area is outside of all but
  189.  * the C partition.  This implies that you cannot use the C 
  190.  * partition on a bootable disk since the filesystem would overlay
  191.  * the boot area.  You must use the A partition.
  192.  *
  193.  * These maps support four basic layouts:
  194.  *
  195.  *    A/B/G:   This is the "traditional" setup for a bootable disk.
  196.  *             A is the root partition, B the swap, and G a user partition.
  197.  *    A/D/H:   This is a setup for bootable systems requiring more swap
  198.  *         (e.g. those who use HPCL).  It has A as the root, D as a
  199.  *         larger swap, and H as a smaller user partition.
  200.  *    A/D/E/F: Similar to A/D/H with E and F breaking H into two partitions.
  201.  *         E could be used for /usr and F for users.
  202.  *    C:       This gives a single, non-bootable, large user filesystem.
  203.  *             Good for second drives on a machine (e.g. /usr/src).
  204.  */
  205. struct size rd7945A_sizes[8] = {
  206.     RDSZ(15904),    1,        /* A=cyl 1 thru 142 */
  207.     RDSZ(20160),    143,        /* B=cyl 143 thru 322 */
  208.     RDSZ(108416),    0,        /* C=cyl 0 thru 967 */
  209.     RDSZ(40320),    143,        /* D=cyl 143 thru 502 */
  210.     RDSZ(0),    0,        /* E=<undefined> */
  211.     RDSZ(0),    0,        /* F=<undefined> */
  212.     RDSZ(72240),    323,        /* G=cyl 323 thru 967 */
  213.     RDSZ(52080),    503,        /* H=cyl 503 thru 967 */
  214. }, rd9134D_sizes[8] = {
  215.     RDSZ(15936),    1,        /* A=cyl 1 thru 166 */
  216.     RDSZ(13056),    167,        /* B=cyl 167 thru 302 */
  217.     RDSZ(29088),    0,        /* C=cyl 0 thru 302 */
  218.     RDSZ(0),    0,        /* D=<undefined> */
  219.     RDSZ(0),    0,        /* E=<undefined> */
  220.     RDSZ(0),    0,        /* F=<undefined> */
  221.     RDSZ(0),    0,        /* G=<undefined> */
  222.     RDSZ(0),    0,        /* H=<undefined> */
  223. }, rd9122S_sizes[8] = {
  224.     RDSZ(0),    0,        /* A=<undefined> */
  225.     RDSZ(0),    0,        /* B=<undefined> */
  226.     RDSZ(1232),    0,        /* C=cyl 0 thru 76 */
  227.     RDSZ(0),    0,        /* D=<undefined> */
  228.     RDSZ(0),    0,        /* E=<undefined> */
  229.     RDSZ(0),    0,        /* F=<undefined> */
  230.     RDSZ(0),    0,        /* G=<undefined> */
  231.     RDSZ(0),    0,        /* H=<undefined> */
  232. }, rd7912P_sizes[8] = {
  233.     RDSZ(15904),    0,        /* A=cyl 1 thru 71 */
  234.     RDSZ(22400),    72,        /* B=cyl 72 thru 171 */
  235.     RDSZ(128128),    0,        /* C=cyl 0 thru 571 */
  236.     RDSZ(42560),    72,        /* D=cyl 72 thru 261 */
  237.     RDSZ(0),    292,        /* E=<undefined> */
  238.     RDSZ(0),    542,        /* F=<undefined> */
  239.     RDSZ(89600),    172,        /* G=cyl 221 thru 571 */
  240.     RDSZ(69440),    262,        /* H=cyl 262 thru 571 */
  241. }, rd7914P_sizes[8] = {
  242.     RDSZ(15904),    1,        /* A=cyl 1 thru 71 */
  243.     RDSZ(40320),    72,        /* B=cyl 72 thru 251 */
  244.     RDSZ(258048),    0,        /* C=cyl 0 thru 1151 */
  245.     RDSZ(64960),    72,        /* D=cyl 72 thru 361 */
  246.     RDSZ(98560),    362,        /* E=cyl 362 thru 801 */
  247.     RDSZ(78400),    802,        /* F=cyl 802 thru 1151 */
  248.     RDSZ(201600),    252,        /* G=cyl 221 thru 1151 */
  249.     RDSZ(176960),    362,        /* H=cyl 362 thru 1151 */
  250. }, rd7933H_sizes[8] = {
  251.     RDSZ(16146),    1,        /* A=cyl 1 thru 27 */
  252.     RDSZ(66976),    28,        /* B=cyl 28 thru 139 */
  253.     RDSZ(789958),    0,        /* C=cyl 0 thru 1320 */
  254.     RDSZ(16146),    140,        /* D=cyl 140 thru 166 */
  255.     RDSZ(165646),    167,        /* E=cyl 167 thru 443 */
  256.     RDSZ(165646),    444,        /* F=cyl 444 thru 720 */
  257.     RDSZ(706238),    140,        /* G=cyl 140 thru 1320 */
  258.     RDSZ(358800),    721,        /* H=cyl 721 thru 1320 */
  259. }, rd9134L_sizes[8] = {
  260.     RDSZ(15920),    1,        /* A=cyl 1 thru 199 */
  261.     RDSZ(20000),    200,        /* B=cyl 200 thru 449 */
  262.     RDSZ(77840),    0,        /* C=cyl 0 thru 972 */
  263.     RDSZ(32000),    200,        /* D=cyl 200 thru 599 */
  264.     RDSZ(0),    0,        /* E=<undefined> */
  265.     RDSZ(0),    0,        /* F=<undefined> */
  266.     RDSZ(41840),    450,        /* G=cyl 450 thru 972 */
  267.     RDSZ(29840),    600,        /* H=cyl 600 thru 972 */
  268. }, rd7957A_sizes[8] = {
  269.     RDSZ(16016),    1,        /* A=cyl 1 thru 104 */
  270.     RDSZ(24640),    105,        /* B=cyl 105 thru 264 */
  271.     RDSZ(159544),    0,        /* C=cyl 0 thru 1035 */
  272.     RDSZ(42350),    105,        /* D=cyl 105 thru 379 */
  273.     RDSZ(54824),    380,        /* E=cyl 380 thru 735 */
  274.     RDSZ(46200),    736,        /* F=cyl 736 thru 1035 */
  275.     RDSZ(118734),    265,        /* G=cyl 265 thru 1035 */
  276.     RDSZ(101024),    380,        /* H=cyl 380 thru 1035 */
  277. }, rd7958A_sizes[8] = {
  278.     RDSZ(16128),    1,        /* A=cyl 1 thru 64 */
  279.     RDSZ(32256),    65,        /* B=cyl 65 thru 192 */
  280.     RDSZ(255276),    0,        /* C=cyl 0 thru 1012 */
  281.     RDSZ(48384),    65,        /* D=cyl 65 thru 256 */
  282.     RDSZ(100800),    257,        /* E=cyl 257 thru 656 */
  283.     RDSZ(89712),    657,        /* F=cyl 657 thru 1012 */
  284.     RDSZ(206640),    193,        /* G=cyl 193 thru 1012 */
  285.     RDSZ(190512),    257,        /* H=cyl 257 thru 1012 */
  286. }, rd7957B_sizes[8] = {
  287.     RDSZ(16002),    1,        /* A=cyl 1 thru 127 */
  288.     RDSZ(32760),    128,        /* B=cyl 128 thru 387 */
  289.     RDSZ(159894),    0,        /* C=cyl 0 thru 1268 */
  290.     RDSZ(49140),    128,        /* D=cyl 128 thru 517 */
  291.     RDSZ(50400),    518,        /* E=cyl 518 thru 917 */
  292.     RDSZ(44226),    918,        /* F=cyl 918 thru 1268 */
  293.     RDSZ(111006),    388,        /* G=cyl 388 thru 1268 */
  294.     RDSZ(94626),    518,        /* H=cyl 518 thru 1268 */
  295. }, rd7958B_sizes[8] = {
  296.     RDSZ(16254),    1,        /* A=cyl 1 thru 43 */
  297.     RDSZ(32886),    44,        /* B=cyl 44 thru 130 */
  298.     RDSZ(297108),    0,        /* C=cyl 0 thru 785 */
  299.     RDSZ(49140),    44,        /* D=cyl 44 thru 173 */
  300.     RDSZ(121716),    174,        /* E=cyl 174 thru 495 */
  301.     RDSZ(109620),    496,        /* F=cyl 496 thru 785 */
  302.     RDSZ(247590),    131,        /* G=cyl 131 thru 785 */
  303.     RDSZ(231336),    174,        /* H=cyl 174 thru 785 */
  304. }, rd7959B_sizes[8] = {
  305.     RDSZ(16254),    1,        /* A=cyl 1 thru 43 */
  306.     RDSZ(49140),    44,        /* B=cyl 44 thru 173 */
  307.     RDSZ(594216),    0,        /* C=cyl 0 thru 1571 */
  308.     RDSZ(65772),    44,        /* D=cyl 44 thru 217 */
  309.     RDSZ(303912),    218,        /* E=cyl 218 thru 1021 */
  310.     RDSZ(207900),    1022,        /* F=cyl 1022 thru 1571 */
  311.     RDSZ(528444),    174,        /* G=cyl 174 thru 1571 */
  312.     RDSZ(511812),    218,        /* H=cyl 218 thru 1571 */
  313. }, rd2200A_sizes[8] = {
  314.     RDSZ(16272),    1,        /* A=cyl 1 thru 36 */
  315.     RDSZ(49720),    37,        /* B=cyl 37 thru 146 */
  316.     RDSZ(654948),    0,        /* C=cyl 0 thru 1448 */
  317.     RDSZ(65992),    37,        /* D=cyl 37 thru 182 */
  318.     RDSZ(304648),    183,        /* E=cyl 183 thru 856 */
  319.     RDSZ(267584),    857,        /* F=cyl 857 thru 1448 */
  320.     RDSZ(588504),    147,        /* G=cyl 147 thru 1448 */
  321.     RDSZ(572232),    183,        /* H=cyl 183 thru 1448 */
  322. }, rd2203A_sizes[8] = {
  323.     /* modelled after the 7937; i.e. bogus */
  324.     RDSZ(16272),    1,        /* A=cyl 1 thru 18 */
  325.     RDSZ(67800),    19,        /* B=cyl 19 thru 93 */
  326.     RDSZ(1309896),    0,        /* C=cyl 0 thru 1448 */
  327.     RDSZ(16272),    94,        /* D=cyl 19 thru 111 */
  328.     RDSZ(305552),    112,        /* E=cyl 112 thru 449 */
  329.     RDSZ(305552),    450,        /* F=cyl 450 thru 787 */
  330.     RDSZ(1224920),    94,        /* G=cyl 94 thru 1448 */
  331.     RDSZ(597544),    788,        /* H=cyl 788 thru 1448 */
  332.  
  333. #if DEV_BSIZE == 512
  334. /*
  335.  * These values would not work for 1k,
  336.  * since the number of cylinders would be different.
  337.  */
  338. }, rd7936H_sizes[8] = {
  339.     RDSZ(16359),    1,        /* A=cyl 1 thru 19 */
  340.     RDSZ(67158),    20,        /* B=cyl 20 thru 97 */
  341.     RDSZ(600978),    0,        /* C=cyl 0 thru 697 */
  342.     RDSZ(16359),    98,        /* D=cyl 98 thru 116 */
  343.     RDSZ(120540),    117,        /* E=cyl 117 thru 256 */
  344.     RDSZ(120540),    256,        /* F=cyl 256 thru 396 */
  345.     RDSZ(516600),    98,        /* G=cyl 98 thru 697 */
  346.     RDSZ(259161),    397,        /* H=cyl 397 thru 697 */
  347. }, rd7937H_sizes[8] = {
  348. #ifdef UTAH
  349.     RDSZ(15990),    1,        /* A=cyl 1 thru 10 */
  350.     RDSZ(67158),    11,        /* B=cyl 11 thru 52 */
  351.     RDSZ(1116102),    0,        /* C=cyl 0 thru 697 */
  352.     RDSZ(124722),    53,        /* D=cyl 53 thru 130 */
  353.     RDSZ(163098),    131,        /* E=cyl 131 thru 232 */
  354.     RDSZ(287820),    233,        /* F=cyl 233 thru 412 */
  355.     RDSZ(1031355),    53,        /* G=cyl 53 thru 697 */
  356.     RDSZ(455715),    413,        /* H=cyl 413 thru 697 */
  357. #else
  358.     RDSZ(15990),    1,        /* A=cyl 1 thru 10 */
  359.     RDSZ(67158),    11,        /* B=cyl 11 thru 52 */
  360.     RDSZ(1116102),    0,        /* C=cyl 0 thru 697 */
  361.     RDSZ(15990),    53,        /* D=cyl 53 thru 62 */
  362.     RDSZ(246246),    63,        /* E=cyl 63 thru 216 */
  363.     RDSZ(246246),    217,        /* F=cyl 217 thru 370 */
  364.     RDSZ(1031355),    53,        /* G=cyl 53 thru 697 */
  365.     RDSZ(522873),    371,        /* H=cyl 371 thru 697 */
  366. #endif
  367. #endif
  368. };
  369.  
  370. struct    rdinfo {
  371.     int    nbpt;        /* DEV_BSIZE blocks per track */
  372.     int    ntpc;        /* tracks per cylinder */
  373.     int    nbpc;        /* blocks per cylinder */
  374.     struct    size *sizes;    /* default partition info (if no disklabel) */
  375.     short    hwid;        /* 2 byte HW id */
  376.     short    maxunum;    /* maximum allowed unit number */
  377.     char    *desc;        /* drive type description */
  378. };
  379.  
  380. struct rdinfo rdinfo[] = {
  381.     NRD7945ABPT,    NRD7945ATRK,    NRD7945ABPT * NRD7945ATRK,
  382.     rd7945A_sizes,    RD7946AID,    0,    "7945A",
  383.     NRD9134DBPT,    NRD9134DTRK,    NRD9134DBPT * NRD9134DTRK,
  384.     rd9134D_sizes,    RD9134DID,    1,    "9134D",
  385.     NRD9122SBPT,    NRD9122STRK,    NRD9122SBPT * NRD9122STRK,
  386.     rd9122S_sizes,    RD9134LID,    1,    "9122S",
  387.     NRD7912PBPT,    NRD7912PTRK,    NRD7912PBPT * NRD7912PTRK,
  388.     rd7912P_sizes,    RD7912PID,    0,    "7912P",
  389.     NRD7914PBPT,    NRD7914PTRK,    NRD7914PBPT * NRD7914PTRK,
  390.     rd7914P_sizes,    RD7914PID,    0,    "7914P",
  391.     NRD7958ABPT,    NRD7958ATRK,    NRD7958ABPT * NRD7958ATRK,
  392.     rd7958A_sizes,    RD7958AID,    0,    "7958A",
  393.     NRD7957ABPT,    NRD7957ATRK,    NRD7957ABPT * NRD7957ATRK,
  394.     rd7957A_sizes,    RD7957AID,    0,    "7957A",
  395.     NRD7933HBPT,    NRD7933HTRK,    NRD7933HBPT * NRD7933HTRK,
  396.     rd7933H_sizes,    RD7933HID,    0,    "7933H",
  397.     NRD9134LBPT,    NRD9134LTRK,    NRD9134LBPT * NRD9134LTRK,
  398.     rd9134L_sizes,    RD9134LID,    1,    "9134L",
  399.     NRD7936HBPT,    NRD7936HTRK,    NRD7936HBPT * NRD7936HTRK,
  400.     rd7936H_sizes,    RD7936HID,    0,    "7936H",
  401.     NRD7937HBPT,    NRD7937HTRK,    NRD7937HBPT * NRD7937HTRK,
  402.     rd7937H_sizes,    RD7937HID,    0,    "7937H",
  403.     NRD7914PBPT,    NRD7914PTRK,    NRD7914PBPT * NRD7914PTRK,
  404.     rd7914P_sizes,    RD7914CTID,    0,    "7914CT",
  405.     NRD7945ABPT,    NRD7945ATRK,    NRD7945ABPT * NRD7945ATRK,
  406.     rd7945A_sizes,    RD7946AID,    0,    "7946A",
  407.     NRD9122SBPT,    NRD9122STRK,    NRD9122SBPT * NRD9122STRK,
  408.     rd9122S_sizes,    RD9134LID,    1,    "9122D",
  409.     NRD7957BBPT,    NRD7957BTRK,    NRD7957BBPT * NRD7957BTRK,
  410.     rd7957B_sizes,    RD7957BID,    0,    "7957B",
  411.     NRD7958BBPT,    NRD7958BTRK,    NRD7958BBPT * NRD7958BTRK,
  412.     rd7958B_sizes,    RD7958BID,    0,    "7958B",
  413.     NRD7959BBPT,    NRD7959BTRK,    NRD7959BBPT * NRD7959BTRK,
  414.     rd7959B_sizes,    RD7959BID,    0,    "7959B",
  415.     NRD2200ABPT,    NRD2200ATRK,    NRD2200ABPT * NRD2200ATRK,
  416.     rd2200A_sizes,    RD2200AID,    0,    "2200A",
  417.     NRD2203ABPT,    NRD2203ATRK,    NRD2203ABPT * NRD2203ATRK,
  418.     rd2203A_sizes,    RD2203AID,    0,    "2203A",
  419. };
  420. int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]);
  421.  
  422. struct    buf rdtab[NRD];
  423.  
  424. #define    rdunit(x)    (minor(x) >> 3)
  425. #define rdpart(x)    (minor(x) & 0x7)
  426. #define    rdpunit(x)    ((x) & 7)
  427. #define    b_cylin        b_resid
  428. #define    RDRETRY        5
  429. #define RDWAITC        1    /* min time for timeout in seconds */
  430.  
  431. int rderrthresh = RDRETRY-1;    /* when to start reporting errors */
  432.  
  433. rdinit(hd)
  434.     register struct hp_device *hd;
  435. {
  436.     register struct rd_softc *rs = &rd_softc[hd->hp_unit];
  437.  
  438.     rs->sc_hd = hd;
  439.     rs->sc_punit = rdpunit(hd->hp_flags);
  440.     rs->sc_type = rdident(rs, hd);
  441.     if (rs->sc_type < 0)
  442.         return(0);
  443.     rs->sc_dq.dq_ctlr = hd->hp_ctlr;
  444.     rs->sc_dq.dq_unit = hd->hp_unit;
  445.     rs->sc_dq.dq_slave = hd->hp_slave;
  446.     rs->sc_dq.dq_driver = &rddriver;
  447.     rs->sc_info = &rdinfo[rs->sc_type];
  448.     rs->sc_flags = RDF_ALIVE;
  449. #ifdef DEBUG
  450.     /* always report errors */
  451.     if (rddebug & RDB_ERROR)
  452.         rderrthresh = 0;
  453. #endif
  454.     return(1);
  455. }
  456.  
  457. rdident(rs, hd)
  458.     struct rd_softc *rs;
  459.     struct hp_device *hd;
  460. {
  461.     struct rd_describe desc;
  462.     u_char stat, cmd[3];
  463.     int unit, lunit;
  464.     char name[7];
  465.     register int ctlr, slave, id, i;
  466.  
  467.     ctlr = hd->hp_ctlr;
  468.     slave = hd->hp_slave;
  469.     unit = rs->sc_punit;
  470.     lunit = hd->hp_unit;
  471.  
  472.     /*
  473.      * Grab device id and make sure:
  474.      * 1. It is a CS80 device.
  475.      * 2. It is one of the types we support.
  476.      * 3. If it is a 7946, we are accessing the disk unit (0)
  477.      */
  478.     id = hpibid(ctlr, slave);
  479. #ifdef DEBUG
  480.     if (rddebug & RDB_IDENT)
  481.         printf("hpibid(%d, %d) -> %x\n", ctlr, slave, id);
  482. #endif
  483.     if ((id & 0x200) == 0)
  484.         return(-1);
  485.     for (i = 0; i < nrdinfo; i++)
  486.         if (id == rdinfo[i].hwid)
  487.             break;
  488.     if (i == nrdinfo || unit > rdinfo[i].maxunum)
  489.         return(-1);
  490.     id = i;
  491.  
  492.     /*
  493.      * Reset drive and collect device description.
  494.      * Don't really use the description info right now but
  495.      * might come in handy in the future (for disk labels).
  496.      */
  497.     rdreset(rs, hd);
  498.     cmd[0] = C_SUNIT(unit);
  499.     cmd[1] = C_SVOL(0);
  500.     cmd[2] = C_DESC;
  501.     hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));
  502.     hpibrecv(ctlr, slave, C_EXEC, &desc, 37);
  503.     hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
  504.     bzero(name, sizeof(name));
  505.     if (!stat) {
  506.         register int n = desc.d_name;
  507.         for (i = 5; i >= 0; i--) {
  508.             name[i] = (n & 0xf) + '0';
  509.             n >>= 4;
  510.         }
  511.         /* use drive characteristics to calculate xfer rate */
  512.         rs->sc_wpms = 1000000 * (desc.d_sectsize/2) / desc.d_blocktime;
  513.     }
  514. #ifdef DEBUG
  515.     if (rddebug & RDB_IDENT) {
  516.         printf("rd%d: name: %x ('%s')\n",
  517.                lunit, desc.d_name, name);
  518.         printf("  iuw %x, maxxfr %d, ctype %d\n",
  519.                desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);
  520.         printf("  utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
  521.                desc.d_utype, desc.d_sectsize,
  522.                desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);
  523.         printf("  avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
  524.                desc.d_uavexfr, desc.d_retry, desc.d_access,
  525.                desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);
  526.         printf("  maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
  527.                desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,
  528.                desc.d_maxvsectl, desc.d_interleave);
  529.     }
  530. #endif
  531.     /*
  532.      * Take care of a couple of anomolies:
  533.      * 1. 7945A and 7946A both return same HW id
  534.      * 2. 9122S and 9134D both return same HW id
  535.      * 3. 9122D and 9134L both return same HW id
  536.      */
  537.     switch (rdinfo[id].hwid) {
  538.     case RD7946AID:
  539.         if (bcmp(name, "079450", 6) == 0)
  540.             id = RD7945A;
  541.         else
  542.             id = RD7946A;
  543.         break;
  544.  
  545.     case RD9134LID:
  546.         if (bcmp(name, "091340", 6) == 0)
  547.             id = RD9134L;
  548.         else
  549.             id = RD9122D;
  550.         break;
  551.  
  552.     case RD9134DID:
  553.         if (bcmp(name, "091220", 6) == 0)
  554.             id = RD9122S;
  555.         else
  556.             id = RD9134D;
  557.         break;
  558.     }
  559.     printf("rd%d: %s\n", lunit, rdinfo[id].desc);
  560.     return(id);
  561. }
  562.  
  563. rdreset(rs, hd)
  564.     register struct rd_softc *rs;
  565.     register struct hp_device *hd;
  566. {
  567.     u_char stat;
  568.  
  569.     rs->sc_clear.c_unit = C_SUNIT(rs->sc_punit);
  570.     rs->sc_clear.c_cmd = C_CLEAR;
  571.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &rs->sc_clear,
  572.         sizeof(rs->sc_clear));
  573.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  574.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  575.     rs->sc_src.c_unit = C_SUNIT(RDCTLR);
  576.     rs->sc_src.c_nop = C_NOP;
  577.     rs->sc_src.c_cmd = C_SREL;
  578.     rs->sc_src.c_param = C_REL;
  579.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_src,
  580.         sizeof(rs->sc_src));
  581.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  582.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  583.     rs->sc_ssmc.c_unit = C_SUNIT(rs->sc_punit);
  584.     rs->sc_ssmc.c_cmd = C_SSM;
  585.     rs->sc_ssmc.c_refm = REF_MASK;
  586.     rs->sc_ssmc.c_fefm = FEF_MASK;
  587.     rs->sc_ssmc.c_aefm = AEF_MASK;
  588.     rs->sc_ssmc.c_iefm = IEF_MASK;
  589.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_ssmc,
  590.         sizeof(rs->sc_ssmc));
  591.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  592.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  593. #ifdef DEBUG
  594.     rdstats[hd->hp_unit].rdresets++;
  595. #endif
  596. }
  597.  
  598. int
  599. rdopen(dev, flags, mode, p)
  600.     dev_t dev;
  601.     int flags, mode;
  602.     struct proc *p;
  603. {
  604.     register int unit = rdunit(dev);
  605.     register struct rd_softc *rs = &rd_softc[unit];
  606.  
  607.     if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
  608.         return(ENXIO);
  609.     if (rs->sc_hd->hp_dk >= 0) {
  610.         /* guess at xfer rate based on 3600 rpm (60 rps) */
  611.         if (rs->sc_wpms == 0)
  612.             rs->sc_wpms = 60 * rs->sc_info->nbpt * DEV_BSIZE / 2;
  613.         dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
  614.     }
  615.     return(0);
  616. }
  617.  
  618. rdstrategy(bp)
  619.     register struct buf *bp;
  620. {
  621.     register int unit = rdunit(bp->b_dev);
  622.     register struct rd_softc *rs = &rd_softc[unit];
  623.     register struct size *pinfo = &rs->sc_info->sizes[rdpart(bp->b_dev)];
  624.     register struct buf *dp = &rdtab[unit];
  625.     register daddr_t bn;
  626.     register int sz, s;
  627.  
  628. #ifdef DEBUG
  629.     if (rddebug & RDB_FOLLOW)
  630.         printf("rdstrategy(%x): dev %x, bn %x, bcount %x, %c\n",
  631.                bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
  632.                (bp->b_flags & B_READ) ? 'R' : 'W');
  633. #endif
  634.     bn = bp->b_blkno;
  635.     sz = howmany(bp->b_bcount, DEV_BSIZE);
  636.     if (bn < 0 || bn + sz > pinfo->nblocks) {
  637.         sz = pinfo->nblocks - bn;
  638.         if (sz == 0) {
  639.             bp->b_resid = bp->b_bcount;
  640.             goto done;
  641.         }
  642.         if (sz < 0) {
  643.             bp->b_error = EINVAL;
  644.             bp->b_flags |= B_ERROR;
  645.             goto done;
  646.         }
  647.         bp->b_bcount = dbtob(sz);
  648.     }
  649.     bp->b_cylin = bn / rs->sc_info->nbpc + pinfo->cyloff;
  650.     s = splbio();
  651.     disksort(dp, bp);
  652.     if (dp->b_active == 0) {
  653.         dp->b_active = 1;
  654.         rdustart(unit);
  655.     }
  656.     splx(s);
  657.     return;
  658. done:
  659.     biodone(bp);
  660. }
  661.  
  662. /*
  663.  * Called from timeout() when handling maintenance releases
  664.  */
  665. rdrestart(unit)
  666.     int unit;
  667. {
  668.     int s = splbio();
  669.     rdustart(unit);
  670.     splx(s);
  671. }
  672.  
  673. rdustart(unit)
  674.     register int unit;
  675. {
  676.     register struct buf *bp;
  677.     register struct rd_softc *rs = &rd_softc[unit];
  678.  
  679.     bp = rdtab[unit].b_actf;
  680.     rs->sc_addr = bp->b_un.b_addr;
  681.     rs->sc_resid = bp->b_bcount;
  682.     if (hpibreq(&rs->sc_dq))
  683.         rdstart(unit);
  684. }
  685.  
  686. rdstart(unit)
  687.     register int unit;
  688. {
  689.     register struct rd_softc *rs = &rd_softc[unit];
  690.     register struct buf *bp = rdtab[unit].b_actf;
  691.     register struct hp_device *hp = rs->sc_hd;
  692.     register int part;
  693.  
  694. again:
  695. #ifdef DEBUG
  696.     if (rddebug & RDB_FOLLOW)
  697.         printf("rdstart(%d): bp %x, %c\n", unit, bp,
  698.                (bp->b_flags & B_READ) ? 'R' : 'W');
  699. #endif
  700.     part = rdpart(bp->b_dev);
  701.     rs->sc_flags |= RDF_SEEK;
  702.     rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
  703.     rs->sc_ioc.c_volume = C_SVOL(0);
  704.     rs->sc_ioc.c_saddr = C_SADDR;
  705.     rs->sc_ioc.c_hiaddr = 0;
  706.     rs->sc_ioc.c_addr = RDBTOS(bp->b_blkno + rs->sc_info->nbpc *
  707.         rs->sc_info->sizes[part].cyloff);
  708.     rs->sc_ioc.c_nop2 = C_NOP;
  709.     rs->sc_ioc.c_slen = C_SLEN;
  710.     rs->sc_ioc.c_len = rs->sc_resid;
  711.     rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
  712. #ifdef DEBUG
  713.     if (rddebug & RDB_IO)
  714.         printf("rdstart: hpibsend(%x, %x, %x, %x, %x)\n",
  715.                hp->hp_ctlr, hp->hp_slave, C_CMD,
  716.                &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
  717. #endif
  718.     if (hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, &rs->sc_ioc.c_unit,
  719.              sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
  720.         if (hp->hp_dk >= 0) {
  721.             dk_busy |= 1 << hp->hp_dk;
  722.             dk_seek[hp->hp_dk]++;
  723.         }
  724. #ifdef DEBUG
  725.         if (rddebug & RDB_IO)
  726.             printf("rdstart: hpibawait(%x)\n", hp->hp_ctlr);
  727. #endif
  728.         hpibawait(hp->hp_ctlr);
  729.         return;
  730.     }
  731.     /*
  732.      * Experience has shown that the hpibwait in this hpibsend will
  733.      * occasionally timeout.  It appears to occur mostly on old 7914
  734.      * drives with full maintenance tracks.  We should probably
  735.      * integrate this with the backoff code in rderror.
  736.      */
  737. #ifdef DEBUG
  738.     if (rddebug & RDB_ERROR)
  739.         printf("rd%d: rdstart: cmd %x adr %d blk %d len %d ecnt %d\n",
  740.                unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
  741.                bp->b_blkno, rs->sc_resid, rdtab[unit].b_errcnt);
  742.     rdstats[unit].rdretries++;
  743. #endif
  744.     rs->sc_flags &= ~RDF_SEEK;
  745.     rdreset(rs, hp);
  746.     if (rdtab[unit].b_errcnt++ < RDRETRY)
  747.         goto again;
  748.     printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",
  749.            unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
  750.            bp->b_blkno, rs->sc_resid);
  751.     rdtab[unit].b_errcnt = 0;
  752.     rdtab[unit].b_actf = bp->b_actf;
  753.     bp->b_flags |= B_ERROR;
  754.     bp->b_error = EIO;
  755.     bp->b_resid = 0;
  756.     biodone(bp);
  757.     hpibfree(&rs->sc_dq);
  758.     bp = rdtab[unit].b_actf;
  759.     if (bp == NULL) {
  760.         rdtab[unit].b_active = 0;
  761.         return;
  762.     }
  763.     rs->sc_addr = bp->b_un.b_addr;
  764.     rs->sc_resid = bp->b_bcount;
  765.     if (hpibreq(&rs->sc_dq))
  766.         goto again;
  767. }
  768.  
  769. rdgo(unit)
  770.     register int unit;
  771. {
  772.     register struct rd_softc *rs = &rd_softc[unit];
  773.     register struct hp_device *hp = rs->sc_hd;
  774.     struct buf *bp = rdtab[unit].b_actf;
  775.  
  776.     if (hp->hp_dk >= 0) {
  777.         dk_busy |= 1 << hp->hp_dk;
  778.         dk_xfer[hp->hp_dk]++;
  779.         dk_wds[hp->hp_dk] += rs->sc_resid >> 6;
  780.     }
  781.     hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,
  782.            rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);
  783. }
  784.  
  785. rdintr(unit)
  786.     register int unit;
  787. {
  788.     register struct rd_softc *rs = &rd_softc[unit];
  789.     register struct buf *bp = rdtab[unit].b_actf;
  790.     register struct hp_device *hp = rs->sc_hd;
  791.     u_char stat = 13;    /* in case hpibrecv fails */
  792.     int rv, restart;
  793.     
  794. #ifdef DEBUG
  795.     if (rddebug & RDB_FOLLOW)
  796.         printf("rdintr(%d): bp %x, %c, flags %x\n", unit, bp,
  797.                (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);
  798.     if (bp == NULL) {
  799.         printf("rd%d: bp == NULL\n", unit);
  800.         return;
  801.     }
  802. #endif
  803.     if (hp->hp_dk >= 0)
  804.         dk_busy &= ~(1 << hp->hp_dk);
  805.     if (rs->sc_flags & RDF_SEEK) {
  806.         rs->sc_flags &= ~RDF_SEEK;
  807.         if (hpibustart(hp->hp_ctlr))
  808.             rdgo(unit);
  809.         return;
  810.     }
  811.     if ((rs->sc_flags & RDF_SWAIT) == 0) {
  812. #ifdef DEBUG
  813.         rdstats[unit].rdpolltries++;
  814. #endif
  815.         if (hpibpptest(hp->hp_ctlr, hp->hp_slave) == 0) {
  816. #ifdef DEBUG
  817.             rdstats[unit].rdpollwaits++;
  818. #endif
  819.             if (hp->hp_dk >= 0)
  820.                 dk_busy |= 1 << hp->hp_dk;
  821.             rs->sc_flags |= RDF_SWAIT;
  822.             hpibawait(hp->hp_ctlr);
  823.             return;
  824.         }
  825.     } else
  826.         rs->sc_flags &= ~RDF_SWAIT;
  827.     rv = hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
  828.     if (rv != 1 || stat) {
  829. #ifdef DEBUG
  830.         if (rddebug & RDB_ERROR)
  831.             printf("rdintr: recv failed or bad stat %d\n", stat);
  832. #endif
  833.         restart = rderror(unit);
  834. #ifdef DEBUG
  835.         rdstats[unit].rdretries++;
  836. #endif
  837.         if (rdtab[unit].b_errcnt++ < RDRETRY) {
  838.             if (restart)
  839.                 rdstart(unit);
  840.             return;
  841.         }
  842.         bp->b_flags |= B_ERROR;
  843.         bp->b_error = EIO;
  844.     }
  845.     rdtab[unit].b_errcnt = 0;
  846.     rdtab[unit].b_actf = bp->b_actf;
  847.     bp->b_resid = 0;
  848.     biodone(bp);
  849.     hpibfree(&rs->sc_dq);
  850.     if (rdtab[unit].b_actf)
  851.         rdustart(unit);
  852.     else
  853.         rdtab[unit].b_active = 0;
  854. }
  855.  
  856. rdstatus(rs)
  857.     register struct rd_softc *rs;
  858. {
  859.     register int c, s;
  860.     u_char stat;
  861.     int rv;
  862.  
  863.     c = rs->sc_hd->hp_ctlr;
  864.     s = rs->sc_hd->hp_slave;
  865.     rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);
  866.     rs->sc_rsc.c_sram = C_SRAM;
  867.     rs->sc_rsc.c_ram = C_RAM;
  868.     rs->sc_rsc.c_cmd = C_STATUS;
  869.     bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));
  870.     rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));
  871.     if (rv != sizeof(rs->sc_rsc)) {
  872. #ifdef DEBUG
  873.         if (rddebug & RDB_STATUS)
  874.             printf("rdstatus: send C_CMD failed %d != %d\n",
  875.                    rv, sizeof(rs->sc_rsc));
  876. #endif
  877.         return(1);
  878.     }
  879.     rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));
  880.     if (rv != sizeof(rs->sc_stat)) {
  881. #ifdef DEBUG
  882.         if (rddebug & RDB_STATUS)
  883.             printf("rdstatus: send C_EXEC failed %d != %d\n",
  884.                    rv, sizeof(rs->sc_stat));
  885. #endif
  886.         return(1);
  887.     }
  888.     rv = hpibrecv(c, s, C_QSTAT, &stat, 1);
  889.     if (rv != 1 || stat) {
  890. #ifdef DEBUG
  891.         if (rddebug & RDB_STATUS)
  892.             printf("rdstatus: recv failed %d or bad stat %d\n",
  893.                    rv, stat);
  894. #endif
  895.         return(1);
  896.     }
  897.     return(0);
  898. }
  899.  
  900. /*
  901.  * Deal with errors.
  902.  * Returns 1 if request should be restarted,
  903.  * 0 if we should just quietly give up.
  904.  */
  905. rderror(unit)
  906.     int unit;
  907. {
  908.     struct rd_softc *rs = &rd_softc[unit];
  909.     register struct rd_stat *sp;
  910.     struct buf *bp;
  911.     daddr_t hwbn, pbn;
  912.  
  913.     if (rdstatus(rs)) {
  914. #ifdef DEBUG
  915.         printf("rd%d: couldn't get status\n", unit);
  916. #endif
  917.         rdreset(rs, rs->sc_hd);
  918.         return(1);
  919.     }
  920.     sp = &rs->sc_stat;
  921.     if (sp->c_fef & FEF_REXMT)
  922.         return(1);
  923.     if (sp->c_fef & FEF_PF) {
  924.         rdreset(rs, rs->sc_hd);
  925.         return(1);
  926.     }
  927.     /*
  928.      * Unit requests release for internal maintenance.
  929.      * We just delay awhile and try again later.  Use expontially
  930.      * increasing backoff ala ethernet drivers since we don't really
  931.      * know how long the maintenance will take.  With RDWAITC and
  932.      * RDRETRY as defined, the range is 1 to 32 seconds.
  933.      */
  934.     if (sp->c_fef & FEF_IMR) {
  935.         extern int hz;
  936.         int rdtimo = RDWAITC << rdtab[unit].b_errcnt;
  937. #ifdef DEBUG
  938.         printf("rd%d: internal maintenance, %d second timeout\n",
  939.                unit, rdtimo);
  940.         rdstats[unit].rdtimeouts++;
  941. #endif
  942.         hpibfree(&rs->sc_dq);
  943.         timeout(rdrestart, unit, rdtimo*hz);
  944.         return(0);
  945.     }
  946.     /*
  947.      * Only report error if we have reached the error reporting
  948.      * threshhold.  By default, this will only report after the
  949.      * retry limit has been exceeded.
  950.      */
  951.     if (rdtab[unit].b_errcnt < rderrthresh)
  952.         return(1);
  953.  
  954.     /*
  955.      * First conjure up the block number at which the error occured.
  956.      * Note that not all errors report a block number, in that case
  957.      * we just use b_blkno.
  958.       */
  959.     bp = rdtab[unit].b_actf;
  960.     pbn = rs->sc_info->nbpc *
  961.         rs->sc_info->sizes[rdpart(bp->b_dev)].cyloff;
  962.     if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
  963.         (sp->c_ief & IEF_RRMASK)) {
  964.         hwbn = RDBTOS(pbn + bp->b_blkno);
  965.         pbn = bp->b_blkno;
  966.     } else {
  967.         hwbn = sp->c_blk;
  968.         pbn = RDSTOB(hwbn) - pbn;
  969.     }
  970.     /*
  971.      * Now output a generic message suitable for badsect.
  972.      * Note that we don't use harderr cuz it just prints
  973.      * out b_blkno which is just the beginning block number
  974.      * of the transfer, not necessary where the error occured.
  975.      */
  976.     printf("rd%d%c: hard error sn%d\n",
  977.            rdunit(bp->b_dev), 'a'+rdpart(bp->b_dev), pbn);
  978.     /*
  979.      * Now report the status as returned by the hardware with
  980.      * attempt at interpretation (unless debugging).
  981.      */
  982.     printf("rd%d %s error:",
  983.            unit, (bp->b_flags & B_READ) ? "read" : "write");
  984. #ifdef DEBUG
  985.     if (rddebug & RDB_ERROR) {
  986.         /* status info */
  987.         printf("\n    volume: %d, unit: %d\n",
  988.                (sp->c_vu>>4)&0xF, sp->c_vu&0xF);
  989.         rdprinterr("reject", sp->c_ref, err_reject);
  990.         rdprinterr("fault", sp->c_fef, err_fault);
  991.         rdprinterr("access", sp->c_aef, err_access);
  992.         rdprinterr("info", sp->c_ief, err_info);
  993.         printf("    block: %d, P1-P10: ", hwbn);
  994.         printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
  995.         printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
  996.         printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
  997.         /* command */
  998.         printf("    ioc: ");
  999.         printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_pad, 8));
  1000.         printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_hiaddr, 4));
  1001.         printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_addr, 8));
  1002.         printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_nop2, 4));
  1003.         printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_len, 8));
  1004.         printf("%s\n", hexstr(*(u_short *)&rs->sc_ioc.c_cmd, 4));
  1005.         return(1);
  1006.     }
  1007. #endif
  1008.     printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n",
  1009.            (sp->c_vu>>4)&0xF, sp->c_vu&0xF,
  1010.            sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);
  1011.     printf("P1-P10: ");
  1012.     printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
  1013.     printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
  1014.     printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
  1015.     return(1);
  1016. }
  1017.  
  1018. int
  1019. rdread(dev, uio, flags)
  1020.     dev_t dev;
  1021.     struct uio *uio;
  1022.     int flags;
  1023. {
  1024.     register int unit = rdunit(dev);
  1025.  
  1026.     return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
  1027. }
  1028.  
  1029. int
  1030. rdwrite(dev, uio, flags)
  1031.     dev_t dev;
  1032.     struct uio *uio;
  1033.     int flags;
  1034. {
  1035.     register int unit = rdunit(dev);
  1036.  
  1037.     return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
  1038. }
  1039.  
  1040. int
  1041. rdioctl(dev, cmd, data, flag, p)
  1042.     dev_t dev;
  1043.     int cmd;
  1044.     caddr_t data;
  1045.     int flag;
  1046.     struct proc *p;
  1047. {
  1048.     return(EINVAL);
  1049. }
  1050.  
  1051. int
  1052. rdsize(dev)
  1053.     dev_t dev;
  1054. {
  1055.     register int unit = rdunit(dev);
  1056.     register struct rd_softc *rs = &rd_softc[unit];
  1057.  
  1058.     if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
  1059.         return(-1);
  1060.     return(rs->sc_info->sizes[rdpart(dev)].nblocks);
  1061. }
  1062.  
  1063. #ifdef DEBUG
  1064. rdprinterr(str, err, tab)
  1065.     char *str;
  1066.     short err;
  1067.     char *tab[];
  1068. {
  1069.     register int i;
  1070.     int printed;
  1071.  
  1072.     if (err == 0)
  1073.         return;
  1074.     printf("    %s error field:", str, err);
  1075.     printed = 0;
  1076.     for (i = 0; i < 16; i++)
  1077.         if (err & (0x8000 >> i))
  1078.             printf("%s%s", printed++ ? " + " : " ", tab[i]);
  1079.     printf("\n");
  1080. }
  1081. #endif
  1082.  
  1083. /*
  1084.  * Non-interrupt driven, non-dma dump routine.
  1085.  */
  1086. int
  1087. rddump(dev)
  1088.     dev_t dev;
  1089. {
  1090.     int part = rdpart(dev);
  1091.     int unit = rdunit(dev);
  1092.     register struct rd_softc *rs = &rd_softc[unit];
  1093.     register struct hp_device *hp = rs->sc_hd;
  1094.     register daddr_t baddr;
  1095.     register int maddr, pages, i;
  1096.     char stat;
  1097.     extern int lowram, dumpsize;
  1098. #ifdef DEBUG
  1099.     extern int pmapdebug;
  1100.     pmapdebug = 0;
  1101. #endif
  1102.  
  1103.     pages = dumpsize;
  1104. #ifdef DEBUG
  1105.     if (rddebug & RDB_DUMP)
  1106.         printf("rddump(%x): u %d p %d dumplo %d ram %x pmem %d\n",
  1107.                dev, unit, part, dumplo, lowram, ctod(pages));
  1108. #endif
  1109.     /* is drive ok? */
  1110.     if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
  1111.         return (ENXIO);
  1112.     /* HPIB idle? */
  1113.     if (!hpibreq(&rs->sc_dq)) {
  1114. #ifdef DEBUG
  1115.         /* is this a safe thing to do?? */
  1116.         hpibreset(hp->hp_ctlr);
  1117.         rdreset(rs, rs->sc_hd);
  1118.         printf("[ drive %d reset ] ", unit);
  1119. #else
  1120.         return (EFAULT);
  1121. #endif
  1122.     }
  1123.     /* dump parameters in range? */
  1124.     if (dumplo < 0 || dumplo >= rs->sc_info->sizes[part].nblocks)
  1125.         return (EINVAL);
  1126.     if (dumplo + ctod(pages) > rs->sc_info->sizes[part].nblocks)
  1127.         pages = dtoc(rs->sc_info->sizes[part].nblocks - dumplo);
  1128.     maddr = lowram;
  1129.     baddr = dumplo + rs->sc_info->nbpc * rs->sc_info->sizes[part].cyloff;
  1130. #ifdef DEBUG
  1131.     if (rddebug & RDB_DUMP)
  1132.         printf("rddump: dumping %d pages from %x to disk block %d\n",
  1133.                pages, maddr, baddr);
  1134. #endif
  1135.     for (i = 0; i < pages; i++) {
  1136. #ifdef DEBUG
  1137. #define NPGMB    (1024*1024/NBPG)
  1138.         /* print out how many Mbs we have dumped */
  1139.         if (i && (i % NPGMB) == 0)
  1140.             printf("%d ", i / NPGMB);
  1141. #undef NPBMG
  1142. #endif
  1143.         rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
  1144.         rs->sc_ioc.c_volume = C_SVOL(0);
  1145.         rs->sc_ioc.c_saddr = C_SADDR;
  1146.         rs->sc_ioc.c_hiaddr = 0;
  1147.         rs->sc_ioc.c_addr = RDBTOS(baddr);
  1148.         rs->sc_ioc.c_nop2 = C_NOP;
  1149.         rs->sc_ioc.c_slen = C_SLEN;
  1150.         rs->sc_ioc.c_len = NBPG;
  1151.         rs->sc_ioc.c_cmd = C_WRITE;
  1152.         hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,
  1153.              &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
  1154.         if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
  1155. #ifdef DEBUG
  1156.             if (rddebug & RDB_DUMP)
  1157.                 printf("rddump: IOC wait timeout\n");
  1158. #endif
  1159.             return (EIO);
  1160.         }
  1161.         pmap_enter(pmap_kernel(), vmmap, maddr, VM_PROT_READ, TRUE);
  1162.         hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
  1163.         if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
  1164. #ifdef DEBUG
  1165.             if (rddebug & RDB_DUMP)
  1166.                 printf("rddump: write wait timeout\n");
  1167. #endif
  1168.         }
  1169.         hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
  1170.         if (stat) {
  1171. #ifdef DEBUG
  1172.             if (rddebug & RDB_DUMP)
  1173.                 printf("rddump: write failed, status %x\n",
  1174.                        stat);
  1175. #endif
  1176.             return (EIO);
  1177.         }
  1178.         maddr += NBPG;
  1179.         baddr += ctod(1);
  1180.     }
  1181.     return (0);
  1182. }
  1183. #endif
  1184.