disklabel support
authorMike Hibler <hibler@ucbvax.Berkeley.EDU>
Mon, 28 Dec 1992 01:32:37 +0000 (17:32 -0800)
committerMike Hibler <hibler@ucbvax.Berkeley.EDU>
Mon, 28 Dec 1992 01:32:37 +0000 (17:32 -0800)
SCCS-vsn: sys/hp300/dev/rd.c 7.18
SCCS-vsn: sys/hp300/dev/rdreg.h 7.4
SCCS-vsn: sys/hp300/dev/sd.c 7.17

usr/src/sys/hp300/dev/rd.c
usr/src/sys/hp300/dev/rdreg.h
usr/src/sys/hp300/dev/sd.c

index 9bb47d9..8315d80 100644 (file)
@@ -9,9 +9,9 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- * from: Utah $Hdr: rd.c 1.38 90/10/12$
+ * from: Utah $Hdr: rd.c 1.44 92/12/26$
  *
  *
- *     @(#)rd.c        7.17 (Berkeley) %G%
+ *     @(#)rd.c        7.18 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
 
 #include <sys/param.h>
 #include <sys/systm.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/errno.h>
+#include <sys/buf.h>
+#include <sys/stat.h>
 #include <sys/dkstat.h>
 #include <sys/disklabel.h>
 #include <sys/dkstat.h>
 #include <sys/disklabel.h>
-#include <sys/buf.h>
-#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
 
 #include <hp/dev/device.h>
 #include <hp300/dev/rdreg.h>
 
 #include <hp/dev/device.h>
 #include <hp300/dev/rdreg.h>
+#include <hp300/dev/rdvar.h>
+#ifdef USELEDS
+#include <hp300/hp300/led.h>
+#endif
 
 #include <vm/vm_param.h>
 #include <vm/lock.h>
 
 #include <vm/vm_param.h>
 #include <vm/lock.h>
 #include <vm/pmap.h>
 
 int    rdinit(), rdstart(), rdgo(), rdintr();
 #include <vm/pmap.h>
 
 int    rdinit(), rdstart(), rdgo(), rdintr();
+void   rdstrategy();
 struct driver rddriver = {
        rdinit, "rd", rdstart, rdgo, rdintr,
 };
 
 struct driver rddriver = {
        rdinit, "rd", rdstart, rdgo, rdintr,
 };
 
-struct rd_softc {
-       struct  hp_device *sc_hd;
-       int     sc_flags;
-       short   sc_type;
-       short   sc_punit;
-       char    *sc_addr;
-       int     sc_resid;
-       u_int   sc_wpms;
-       struct  rdinfo *sc_info;
-       struct  devqueue sc_dq;
-       struct  rd_iocmd sc_ioc;
-       struct  rd_rscmd sc_rsc;
-       struct  rd_stat sc_stat;
-       struct  rd_ssmcmd sc_ssmc;
-       struct  rd_srcmd sc_src;
-       struct  rd_clearcmd sc_clear;
-} rd_softc[NRD];
-
-/* sc_flags values */
-#define        RDF_ALIVE       0x1
-#define        RDF_SEEK        0x2
-#define RDF_SWAIT      0x4
-
-struct size {
-       daddr_t nblocks;
-       int     cyloff;
-};
+struct rd_softc rd_softc[NRD];
+struct buf rdtab[NRD];
+int    rderrthresh = RDRETRY-1;        /* when to start reporting errors */
 
 #ifdef DEBUG
 
 #ifdef DEBUG
-int rddebug = 0x80;
-#define RDB_FOLLOW     0x01
-#define RDB_STATUS     0x02
-#define RDB_IDENT      0x04
-#define RDB_IO         0x08
-#define RDB_ASYNC      0x10
-#define RDB_ERROR      0x80
-#define RDB_DUMP       0x80000000
-
-struct rdstats {
-       long    rdretries;
-       long    rdresets;
-       long    rdtimeouts;
-       long    rdpolltries;
-       long    rdpollwaits;
-} rdstats[NRD];
-
 /* error message tables */
 char *err_reject[] = {
        0, 0,
 /* error message tables */
 char *err_reject[] = {
        0, 0,
@@ -153,244 +118,43 @@ char *err_info[] = {
        "maintenance track overflow",   /* 0x0004 */
        0, 0
 };
        "maintenance track overflow",   /* 0x0004 */
        0, 0
 };
+
+struct rdstats rdstats[NRD];
+int    rddebug = 0x80;
+#define RDB_FOLLOW     0x01
+#define RDB_STATUS     0x02
+#define RDB_IDENT      0x04
+#define RDB_IO         0x08
+#define RDB_ASYNC      0x10
+#define RDB_ERROR      0x80
 #endif
 
 /*
 #endif
 
 /*
- * CS/80 partitions.  We reserve the first cylinder for a LIF
- * style boot directory (the 8k allowed in the BSD filesystem
- * is just way too small).  This boot area is outside of all but
- * the C partition.  This implies that you cannot use the C 
- * partition on a bootable disk since the filesystem would overlay
- * the boot area.  You must use the A partition.
- *
- * These maps support four basic layouts:
- *
- *     A/B/G:   This is the "traditional" setup for a bootable disk.
- *              A is the root partition, B the swap, and G a user partition.
- *     A/D/H:   This is a setup for bootable systems requiring more swap
- *              (e.g. those who use HPCL).  It has A as the root, D as a
- *              larger swap, and H as a smaller user partition.
- *     A/D/E/F: Similar to A/D/H with E and F breaking H into two partitions.
- *              E could be used for /usr and F for users.
- *     C:       This gives a single, non-bootable, large user filesystem.
- *              Good for second drives on a machine (e.g. /usr/src).
- */
-struct size rd7945A_sizes[8] = {
-       RDSZ(15904),    1,              /* A=cyl 1 thru 142 */
-       RDSZ(20160),    143,            /* B=cyl 143 thru 322 */
-       RDSZ(108416),   0,              /* C=cyl 0 thru 967 */
-       RDSZ(40320),    143,            /* D=cyl 143 thru 502 */
-       RDSZ(0),        0,              /* E=<undefined> */
-       RDSZ(0),        0,              /* F=<undefined> */
-       RDSZ(72240),    323,            /* G=cyl 323 thru 967 */
-       RDSZ(52080),    503,            /* H=cyl 503 thru 967 */
-}, rd9134D_sizes[8] = {
-       RDSZ(15936),    1,              /* A=cyl 1 thru 166 */
-       RDSZ(13056),    167,            /* B=cyl 167 thru 302 */
-       RDSZ(29088),    0,              /* C=cyl 0 thru 302 */
-       RDSZ(0),        0,              /* D=<undefined> */
-       RDSZ(0),        0,              /* E=<undefined> */
-       RDSZ(0),        0,              /* F=<undefined> */
-       RDSZ(0),        0,              /* G=<undefined> */
-       RDSZ(0),        0,              /* H=<undefined> */
-}, rd9122S_sizes[8] = {
-       RDSZ(0),        0,              /* A=<undefined> */
-       RDSZ(0),        0,              /* B=<undefined> */
-       RDSZ(1232),     0,              /* C=cyl 0 thru 76 */
-       RDSZ(0),        0,              /* D=<undefined> */
-       RDSZ(0),        0,              /* E=<undefined> */
-       RDSZ(0),        0,              /* F=<undefined> */
-       RDSZ(0),        0,              /* G=<undefined> */
-       RDSZ(0),        0,              /* H=<undefined> */
-}, rd7912P_sizes[8] = {
-       RDSZ(15904),    0,              /* A=cyl 1 thru 71 */
-       RDSZ(22400),    72,             /* B=cyl 72 thru 171 */
-       RDSZ(128128),   0,              /* C=cyl 0 thru 571 */
-       RDSZ(42560),    72,             /* D=cyl 72 thru 261 */
-       RDSZ(0),        292,            /* E=<undefined> */
-       RDSZ(0),        542,            /* F=<undefined> */
-       RDSZ(89600),    172,            /* G=cyl 221 thru 571 */
-       RDSZ(69440),    262,            /* H=cyl 262 thru 571 */
-}, rd7914P_sizes[8] = {
-       RDSZ(15904),    1,              /* A=cyl 1 thru 71 */
-       RDSZ(40320),    72,             /* B=cyl 72 thru 251 */
-       RDSZ(258048),   0,              /* C=cyl 0 thru 1151 */
-       RDSZ(64960),    72,             /* D=cyl 72 thru 361 */
-       RDSZ(98560),    362,            /* E=cyl 362 thru 801 */
-       RDSZ(78400),    802,            /* F=cyl 802 thru 1151 */
-       RDSZ(201600),   252,            /* G=cyl 221 thru 1151 */
-       RDSZ(176960),   362,            /* H=cyl 362 thru 1151 */
-}, rd7933H_sizes[8] = {
-       RDSZ(16146),    1,              /* A=cyl 1 thru 27 */
-       RDSZ(66976),    28,             /* B=cyl 28 thru 139 */
-       RDSZ(789958),   0,              /* C=cyl 0 thru 1320 */
-       RDSZ(16146),    140,            /* D=cyl 140 thru 166 */
-       RDSZ(165646),   167,            /* E=cyl 167 thru 443 */
-       RDSZ(165646),   444,            /* F=cyl 444 thru 720 */
-       RDSZ(706238),   140,            /* G=cyl 140 thru 1320 */
-       RDSZ(358800),   721,            /* H=cyl 721 thru 1320 */
-}, rd9134L_sizes[8] = {
-       RDSZ(15920),    1,              /* A=cyl 1 thru 199 */
-       RDSZ(20000),    200,            /* B=cyl 200 thru 449 */
-       RDSZ(77840),    0,              /* C=cyl 0 thru 972 */
-       RDSZ(32000),    200,            /* D=cyl 200 thru 599 */
-       RDSZ(0),        0,              /* E=<undefined> */
-       RDSZ(0),        0,              /* F=<undefined> */
-       RDSZ(41840),    450,            /* G=cyl 450 thru 972 */
-       RDSZ(29840),    600,            /* H=cyl 600 thru 972 */
-}, rd7957A_sizes[8] = {
-       RDSZ(16016),    1,              /* A=cyl 1 thru 104 */
-       RDSZ(24640),    105,            /* B=cyl 105 thru 264 */
-       RDSZ(159544),   0,              /* C=cyl 0 thru 1035 */
-       RDSZ(42350),    105,            /* D=cyl 105 thru 379 */
-       RDSZ(54824),    380,            /* E=cyl 380 thru 735 */
-       RDSZ(46200),    736,            /* F=cyl 736 thru 1035 */
-       RDSZ(118734),   265,            /* G=cyl 265 thru 1035 */
-       RDSZ(101024),   380,            /* H=cyl 380 thru 1035 */
-}, rd7958A_sizes[8] = {
-       RDSZ(16128),    1,              /* A=cyl 1 thru 64 */
-       RDSZ(32256),    65,             /* B=cyl 65 thru 192 */
-       RDSZ(255276),   0,              /* C=cyl 0 thru 1012 */
-       RDSZ(48384),    65,             /* D=cyl 65 thru 256 */
-       RDSZ(100800),   257,            /* E=cyl 257 thru 656 */
-       RDSZ(89712),    657,            /* F=cyl 657 thru 1012 */
-       RDSZ(206640),   193,            /* G=cyl 193 thru 1012 */
-       RDSZ(190512),   257,            /* H=cyl 257 thru 1012 */
-}, rd7957B_sizes[8] = {
-       RDSZ(16002),    1,              /* A=cyl 1 thru 127 */
-       RDSZ(32760),    128,            /* B=cyl 128 thru 387 */
-       RDSZ(159894),   0,              /* C=cyl 0 thru 1268 */
-       RDSZ(49140),    128,            /* D=cyl 128 thru 517 */
-       RDSZ(50400),    518,            /* E=cyl 518 thru 917 */
-       RDSZ(44226),    918,            /* F=cyl 918 thru 1268 */
-       RDSZ(111006),   388,            /* G=cyl 388 thru 1268 */
-       RDSZ(94626),    518,            /* H=cyl 518 thru 1268 */
-}, rd7958B_sizes[8] = {
-       RDSZ(16254),    1,              /* A=cyl 1 thru 43 */
-       RDSZ(32886),    44,             /* B=cyl 44 thru 130 */
-       RDSZ(297108),   0,              /* C=cyl 0 thru 785 */
-       RDSZ(49140),    44,             /* D=cyl 44 thru 173 */
-       RDSZ(121716),   174,            /* E=cyl 174 thru 495 */
-       RDSZ(109620),   496,            /* F=cyl 496 thru 785 */
-       RDSZ(247590),   131,            /* G=cyl 131 thru 785 */
-       RDSZ(231336),   174,            /* H=cyl 174 thru 785 */
-}, rd7959B_sizes[8] = {
-       RDSZ(16254),    1,              /* A=cyl 1 thru 43 */
-       RDSZ(49140),    44,             /* B=cyl 44 thru 173 */
-       RDSZ(594216),   0,              /* C=cyl 0 thru 1571 */
-       RDSZ(65772),    44,             /* D=cyl 44 thru 217 */
-       RDSZ(303912),   218,            /* E=cyl 218 thru 1021 */
-       RDSZ(207900),   1022,           /* F=cyl 1022 thru 1571 */
-       RDSZ(528444),   174,            /* G=cyl 174 thru 1571 */
-       RDSZ(511812),   218,            /* H=cyl 218 thru 1571 */
-}, rd2200A_sizes[8] = {
-       RDSZ(16272),    1,              /* A=cyl 1 thru 36 */
-       RDSZ(49720),    37,             /* B=cyl 37 thru 146 */
-       RDSZ(654948),   0,              /* C=cyl 0 thru 1448 */
-       RDSZ(65992),    37,             /* D=cyl 37 thru 182 */
-       RDSZ(304648),   183,            /* E=cyl 183 thru 856 */
-       RDSZ(267584),   857,            /* F=cyl 857 thru 1448 */
-       RDSZ(588504),   147,            /* G=cyl 147 thru 1448 */
-       RDSZ(572232),   183,            /* H=cyl 183 thru 1448 */
-}, rd2203A_sizes[8] = {
-       /* modelled after the 7937; i.e. bogus */
-       RDSZ(16272),    1,              /* A=cyl 1 thru 18 */
-       RDSZ(67800),    19,             /* B=cyl 19 thru 93 */
-       RDSZ(1309896),  0,              /* C=cyl 0 thru 1448 */
-       RDSZ(16272),    94,             /* D=cyl 19 thru 111 */
-       RDSZ(305552),   112,            /* E=cyl 112 thru 449 */
-       RDSZ(305552),   450,            /* F=cyl 450 thru 787 */
-       RDSZ(1224920),  94,             /* G=cyl 94 thru 1448 */
-       RDSZ(597544),   788,            /* H=cyl 788 thru 1448 */
-
-#if DEV_BSIZE == 512
-/*
- * These values would not work for 1k,
- * since the number of cylinders would be different.
+ * Misc. HW description, indexed by sc_type.
+ * Nothing really critical here, could do without it.
  */
  */
-}, rd7936H_sizes[8] = {
-       RDSZ(16359),    1,              /* A=cyl 1 thru 19 */
-       RDSZ(67158),    20,             /* B=cyl 20 thru 97 */
-       RDSZ(600978),   0,              /* C=cyl 0 thru 697 */
-       RDSZ(16359),    98,             /* D=cyl 98 thru 116 */
-       RDSZ(120540),   117,            /* E=cyl 117 thru 256 */
-       RDSZ(120540),   256,            /* F=cyl 256 thru 396 */
-       RDSZ(516600),   98,             /* G=cyl 98 thru 697 */
-       RDSZ(259161),   397,            /* H=cyl 397 thru 697 */
-}, rd7937H_sizes[8] = {
-       RDSZ(15990),    1,              /* A=cyl 1 thru 10 */
-       RDSZ(67158),    11,             /* B=cyl 11 thru 52 */
-       RDSZ(1116102),  0,              /* C=cyl 0 thru 697 */
-       RDSZ(124722),   53,             /* D=cyl 53 thru 130 */
-       RDSZ(163098),   131,            /* E=cyl 131 thru 232 */
-       RDSZ(287820),   233,            /* F=cyl 233 thru 412 */
-       RDSZ(1031355),  53,             /* G=cyl 53 thru 697 */
-       RDSZ(455715),   413,            /* H=cyl 413 thru 697 */
-#endif
-};
-
-struct rdinfo {
-       int     nbpt;           /* DEV_BSIZE blocks per track */
-       int     ntpc;           /* tracks per cylinder */
-       int     nbpc;           /* blocks per cylinder */
-       struct  size *sizes;    /* default partition info (if no disklabel) */
-       short   hwid;           /* 2 byte HW id */
-       short   maxunum;        /* maximum allowed unit number */
-       char    *desc;          /* drive type description */
-};
-
-struct rdinfo rdinfo[] = {
-       NRD7945ABPT,    NRD7945ATRK,    NRD7945ABPT * NRD7945ATRK,
-       rd7945A_sizes,  RD7946AID,      0,      "7945A",
-       NRD9134DBPT,    NRD9134DTRK,    NRD9134DBPT * NRD9134DTRK,
-       rd9134D_sizes,  RD9134DID,      1,      "9134D",
-       NRD9122SBPT,    NRD9122STRK,    NRD9122SBPT * NRD9122STRK,
-       rd9122S_sizes,  RD9134LID,      1,      "9122S",
-       NRD7912PBPT,    NRD7912PTRK,    NRD7912PBPT * NRD7912PTRK,
-       rd7912P_sizes,  RD7912PID,      0,      "7912P",
-       NRD7914PBPT,    NRD7914PTRK,    NRD7914PBPT * NRD7914PTRK,
-       rd7914P_sizes,  RD7914PID,      0,      "7914P",
-       NRD7958ABPT,    NRD7958ATRK,    NRD7958ABPT * NRD7958ATRK,
-       rd7958A_sizes,  RD7958AID,      0,      "7958A",
-       NRD7957ABPT,    NRD7957ATRK,    NRD7957ABPT * NRD7957ATRK,
-       rd7957A_sizes,  RD7957AID,      0,      "7957A",
-       NRD7933HBPT,    NRD7933HTRK,    NRD7933HBPT * NRD7933HTRK,
-       rd7933H_sizes,  RD7933HID,      0,      "7933H",
-       NRD9134LBPT,    NRD9134LTRK,    NRD9134LBPT * NRD9134LTRK,
-       rd9134L_sizes,  RD9134LID,      1,      "9134L",
-       NRD7936HBPT,    NRD7936HTRK,    NRD7936HBPT * NRD7936HTRK,
-       rd7936H_sizes,  RD7936HID,      0,      "7936H",
-       NRD7937HBPT,    NRD7937HTRK,    NRD7937HBPT * NRD7937HTRK,
-       rd7937H_sizes,  RD7937HID,      0,      "7937H",
-       NRD7914PBPT,    NRD7914PTRK,    NRD7914PBPT * NRD7914PTRK,
-       rd7914P_sizes,  RD7914CTID,     0,      "7914CT",
-       NRD7945ABPT,    NRD7945ATRK,    NRD7945ABPT * NRD7945ATRK,
-       rd7945A_sizes,  RD7946AID,      0,      "7946A",
-       NRD9122SBPT,    NRD9122STRK,    NRD9122SBPT * NRD9122STRK,
-       rd9122S_sizes,  RD9134LID,      1,      "9122D",
-       NRD7957BBPT,    NRD7957BTRK,    NRD7957BBPT * NRD7957BTRK,
-       rd7957B_sizes,  RD7957BID,      0,      "7957B",
-       NRD7958BBPT,    NRD7958BTRK,    NRD7958BBPT * NRD7958BTRK,
-       rd7958B_sizes,  RD7958BID,      0,      "7958B",
-       NRD7959BBPT,    NRD7959BTRK,    NRD7959BBPT * NRD7959BTRK,
-       rd7959B_sizes,  RD7959BID,      0,      "7959B",
-       NRD2200ABPT,    NRD2200ATRK,    NRD2200ABPT * NRD2200ATRK,
-       rd2200A_sizes,  RD2200AID,      0,      "2200A",
-       NRD2203ABPT,    NRD2203ATRK,    NRD2203ABPT * NRD2203ATRK,
-       rd2203A_sizes,  RD2203AID,      0,      "2203A",
+struct rdidentinfo rdidentinfo[] = {
+       { RD7946AID,    0,      "7945A",         108416 },
+       { RD9134DID,    1,      "9134D",          29088 },
+       { RD9134LID,    1,      "9122S",           1232 },
+       { RD7912PID,    0,      "7912P",         128128 },
+       { RD7914PID,    0,      "7914P",         258048 },
+       { RD7958AID,    0,      "7958A",         255276 },
+       { RD7957AID,    0,      "7957A",         159544 },
+       { RD7933HID,    0,      "7933H",         789958 },
+       { RD9134LID,    1,      "9134L",          77840 },
+       { RD7936HID,    0,      "7936H",         600978 },
+       { RD7937HID,    0,      "7937H",        1116102 },
+       { RD7914CTID,   0,      "7914CT",        258048 },
+       { RD7946AID,    0,      "7946A",         108416 },
+       { RD9134LID,    1,      "9122D",           1232 },
+       { RD7957BID,    0,      "7957B",         159894 },
+       { RD7958BID,    0,      "7958B",         297108 },
+       { RD7959BID,    0,      "7959B",         594216 },
+       { RD2200AID,    0,      "2200A",         654948 },
+       { RD2203AID,    0,      "2203A",        1309896 }
 };
 };
-int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]);
-
-struct buf rdtab[NRD];
-
-#define        rdunit(x)       (minor(x) >> 3)
-#define rdpart(x)      (minor(x) & 0x7)
-#define        rdpunit(x)      ((x) & 7)
-#define        b_cylin         b_resid
-#define        RDRETRY         5
-#define RDWAITC                1       /* min time for timeout in seconds */
-
-int rderrthresh = RDRETRY-1;   /* when to start reporting errors */
+int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]);
 
 rdinit(hd)
        register struct hp_device *hd;
 
 rdinit(hd)
        register struct hp_device *hd;
@@ -406,7 +170,6 @@ rdinit(hd)
        rs->sc_dq.dq_unit = hd->hp_unit;
        rs->sc_dq.dq_slave = hd->hp_slave;
        rs->sc_dq.dq_driver = &rddriver;
        rs->sc_dq.dq_unit = hd->hp_unit;
        rs->sc_dq.dq_slave = hd->hp_slave;
        rs->sc_dq.dq_driver = &rddriver;
-       rs->sc_info = &rdinfo[rs->sc_type];
        rs->sc_flags = RDF_ALIVE;
 #ifdef DEBUG
        /* always report errors */
        rs->sc_flags = RDF_ALIVE;
 #ifdef DEBUG
        /* always report errors */
@@ -444,10 +207,10 @@ rdident(rs, hd)
 #endif
        if ((id & 0x200) == 0)
                return(-1);
 #endif
        if ((id & 0x200) == 0)
                return(-1);
-       for (i = 0; i < nrdinfo; i++)
-               if (id == rdinfo[i].hwid)
+       for (i = 0; i < numrdidentinfo; i++)
+               if (id == rdidentinfo[i].ri_hwid)
                        break;
                        break;
-       if (i == nrdinfo || unit > rdinfo[i].maxunum)
+       if (i == numrdidentinfo || unit > rdidentinfo[i].ri_maxunum)
                return(-1);
        id = i;
 
                return(-1);
        id = i;
 
@@ -496,7 +259,7 @@ rdident(rs, hd)
         * 2. 9122S and 9134D both return same HW id
         * 3. 9122D and 9134L both return same HW id
         */
         * 2. 9122S and 9134D both return same HW id
         * 3. 9122D and 9134L both return same HW id
         */
-       switch (rdinfo[id].hwid) {
+       switch (rdidentinfo[id].ri_hwid) {
        case RD7946AID:
                if (bcmp(name, "079450", 6) == 0)
                        id = RD7945A;
        case RD7946AID:
                if (bcmp(name, "079450", 6) == 0)
                        id = RD7945A;
@@ -518,7 +281,7 @@ rdident(rs, hd)
                        id = RD9134D;
                break;
        }
                        id = RD9134D;
                break;
        }
-       printf("rd%d: %s\n", lunit, rdinfo[id].desc);
+       printf("rd%d: %s\n", lunit, rdidentinfo[id].ri_desc);
        return(id);
 }
 
        return(id);
 }
 
@@ -557,6 +320,52 @@ rdreset(rs, hd)
 #endif
 }
 
 #endif
 }
 
+/*
+ * Read or constuct a disklabel
+ */
+int
+rdgetinfo(dev)
+       dev_t dev;
+{
+       int unit = rdunit(dev);
+       register struct rd_softc *rs = &rd_softc[unit];
+       register struct disklabel *lp = &rs->sc_info.ri_label;
+       register struct partition *pi;
+       char *msg, *readdisklabel();
+
+       /*
+        * Set some default values to use while reading the label
+        * or to use if there isn't a label.
+        */
+       bzero((caddr_t)lp, sizeof *lp);
+       lp->d_type = DTYPE_HPIB;
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_nsectors = 32;
+       lp->d_ntracks = 20;
+       lp->d_secpercyl = 32*20;
+       lp->d_npartitions = 3;
+       lp->d_partitions[2].p_offset = 0;
+       lp->d_partitions[2].p_size = LABELSECTOR+1;
+
+       /*
+        * Now try to read the disklabel
+        */
+       msg = readdisklabel(rdlabdev(dev), rdstrategy, lp);
+       if (msg == NULL)
+               return(0);
+
+       pi = lp->d_partitions;
+       printf("rd%d: WARNING: %s, ", unit, msg);
+#ifdef COMPAT_NOLABEL
+       printf("using old default partitioning\n");
+       rdmakedisklabel(unit, lp);
+#else
+       printf("defining `c' partition as entire disk\n");
+       pi[2].p_size = rdidentinfo[rs->sc_type].ri_nblocks;
+#endif
+       return(0);
+}
+
 int
 rdopen(dev, flags, mode, p)
        dev_t dev;
 int
 rdopen(dev, flags, mode, p)
        dev_t dev;
@@ -565,25 +374,93 @@ rdopen(dev, flags, mode, p)
 {
        register int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
 {
        register int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
+       int error, mask;
 
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return(ENXIO);
 
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return(ENXIO);
+
+       /*
+        * Wait for any pending opens/closes to complete
+        */
+       while (rs->sc_flags & (RDF_OPENING|RDF_CLOSING))
+               sleep((caddr_t)rs, PRIBIO);
+
+       /*
+        * On first open, get label and partition info.
+        * We may block reading the label, so be careful
+        * to stop any other opens.
+        */
+       if (rs->sc_info.ri_open == 0) {
+               rs->sc_flags |= RDF_OPENING;
+               error = rdgetinfo(dev);
+               rs->sc_flags &= ~RDF_OPENING;
+               wakeup((caddr_t)rs);
+               if (error)
+                       return(error);
+       }
        if (rs->sc_hd->hp_dk >= 0) {
                /* guess at xfer rate based on 3600 rpm (60 rps) */
                if (rs->sc_wpms == 0)
        if (rs->sc_hd->hp_dk >= 0) {
                /* guess at xfer rate based on 3600 rpm (60 rps) */
                if (rs->sc_wpms == 0)
-                       rs->sc_wpms = 60 * rs->sc_info->nbpt * DEV_BSIZE / 2;
+                       rs->sc_wpms = 60 * rs->sc_info.ri_label.d_nsectors
+                               * DEV_BSIZE / 2;
                dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
        }
                dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
        }
+
+       mask = 1 << rdpart(dev);
+       if (mode == S_IFCHR)
+               rs->sc_info.ri_copen |= mask;
+       else
+               rs->sc_info.ri_bopen |= mask;
+       rs->sc_info.ri_open |= mask;
        return(0);
 }
 
        return(0);
 }
 
+int
+rdclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       int unit = rdunit(dev);
+       register struct rd_softc *rs = &rd_softc[unit];
+       register struct rdinfo *ri = &rs->sc_info;
+       int mask, s;
+
+       mask = 1 << rdpart(dev);
+       if (mode == S_IFCHR)
+               ri->ri_copen &= ~mask;
+       else
+               ri->ri_bopen &= ~mask;
+       ri->ri_open = ri->ri_bopen | ri->ri_copen;
+       /*
+        * On last close, we wait for all activity to cease since
+        * the label/parition info will become invalid.  Since we
+        * might sleep, we must block any opens while we are here.
+        * Note we don't have to about other closes since we know
+        * we are the last one.
+        */
+       if (ri->ri_open == 0) {
+               rs->sc_flags |= RDF_CLOSING;
+               s = splbio();
+               while (rdtab[unit].b_active) {
+                       rs->sc_flags |= RDF_WANTED;
+                       sleep((caddr_t)&rdtab[unit], PRIBIO);
+               }
+               splx(s);
+               rs->sc_flags &= ~(RDF_CLOSING|RDF_WLABEL);
+               wakeup((caddr_t)rs);
+       }
+       return(0);
+}
+
+void
 rdstrategy(bp)
        register struct buf *bp;
 {
 rdstrategy(bp)
        register struct buf *bp;
 {
-       register int unit = rdunit(bp->b_dev);
+       int unit = rdunit(bp->b_dev);
        register struct rd_softc *rs = &rd_softc[unit];
        register struct rd_softc *rs = &rd_softc[unit];
-       register struct size *pinfo = &rs->sc_info->sizes[rdpart(bp->b_dev)];
        register struct buf *dp = &rdtab[unit];
        register struct buf *dp = &rdtab[unit];
+       register struct partition *pinfo;
        register daddr_t bn;
        register int sz, s;
 
        register daddr_t bn;
        register int sz, s;
 
@@ -595,20 +472,31 @@ rdstrategy(bp)
 #endif
        bn = bp->b_blkno;
        sz = howmany(bp->b_bcount, DEV_BSIZE);
 #endif
        bn = bp->b_blkno;
        sz = howmany(bp->b_bcount, DEV_BSIZE);
-       if (bn < 0 || bn + sz > pinfo->nblocks) {
-               sz = pinfo->nblocks - bn;
+       pinfo = &rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)];
+       if (bn < 0 || bn + sz > pinfo->p_size) {
+               sz = pinfo->p_size - bn;
                if (sz == 0) {
                        bp->b_resid = bp->b_bcount;
                        goto done;
                }
                if (sz < 0) {
                        bp->b_error = EINVAL;
                if (sz == 0) {
                        bp->b_resid = bp->b_bcount;
                        goto done;
                }
                if (sz < 0) {
                        bp->b_error = EINVAL;
-                       bp->b_flags |= B_ERROR;
-                       goto done;
+                       goto bad;
                }
                bp->b_bcount = dbtob(sz);
        }
                }
                bp->b_bcount = dbtob(sz);
        }
-       bp->b_cylin = bn / rs->sc_info->nbpc + pinfo->cyloff;
+       /*
+        * Check for write to write protected label
+        */
+       if (bn + pinfo->p_offset <= LABELSECTOR &&
+#if LABELSECTOR != 0
+           bn + pinfo->p_offset + sz > LABELSECTOR &&
+#endif
+           !(bp->b_flags & B_READ) && !(rs->sc_flags & RDF_WLABEL)) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
+       bp->b_cylin = bn + pinfo->p_offset;
        s = splbio();
        disksort(dp, bp);
        if (dp->b_active == 0) {
        s = splbio();
        disksort(dp, bp);
        if (dp->b_active == 0) {
@@ -617,6 +505,8 @@ rdstrategy(bp)
        }
        splx(s);
        return;
        }
        splx(s);
        return;
+bad:
+       bp->b_flags |= B_ERROR;
 done:
        biodone(bp);
 }
 done:
        biodone(bp);
 }
@@ -646,6 +536,29 @@ rdustart(unit)
                rdstart(unit);
 }
 
                rdstart(unit);
 }
 
+struct buf *
+rdfinish(unit, rs, bp)
+       int unit;
+       register struct rd_softc *rs;
+       register struct buf *bp;
+{
+       register struct buf *dp = &rdtab[unit];
+
+       dp->b_errcnt = 0;
+       dp->b_actf = bp->b_actf;
+       bp->b_resid = 0;
+       biodone(bp);
+       hpibfree(&rs->sc_dq);
+       if (dp->b_actf)
+               return(dp->b_actf);
+       dp->b_active = 0;
+       if (rs->sc_flags & RDF_WANTED) {
+               rs->sc_flags &= ~RDF_WANTED;
+               wakeup((caddr_t)dp);
+       }
+       return(NULL);
+}
+
 rdstart(unit)
        register int unit;
 {
 rdstart(unit)
        register int unit;
 {
@@ -666,8 +579,7 @@ again:
        rs->sc_ioc.c_volume = C_SVOL(0);
        rs->sc_ioc.c_saddr = C_SADDR;
        rs->sc_ioc.c_hiaddr = 0;
        rs->sc_ioc.c_volume = C_SVOL(0);
        rs->sc_ioc.c_saddr = C_SADDR;
        rs->sc_ioc.c_hiaddr = 0;
-       rs->sc_ioc.c_addr = RDBTOS(bp->b_blkno + rs->sc_info->nbpc *
-               rs->sc_info->sizes[part].cyloff);
+       rs->sc_ioc.c_addr = RDBTOS(bp->b_cylin);
        rs->sc_ioc.c_nop2 = C_NOP;
        rs->sc_ioc.c_slen = C_SLEN;
        rs->sc_ioc.c_len = rs->sc_resid;
        rs->sc_ioc.c_nop2 = C_NOP;
        rs->sc_ioc.c_slen = C_SLEN;
        rs->sc_ioc.c_len = rs->sc_resid;
@@ -711,22 +623,15 @@ again:
        printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",
               unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
               bp->b_blkno, rs->sc_resid);
        printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",
               unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
               bp->b_blkno, rs->sc_resid);
-       rdtab[unit].b_errcnt = 0;
-       rdtab[unit].b_actf = bp->b_actf;
        bp->b_flags |= B_ERROR;
        bp->b_error = EIO;
        bp->b_flags |= B_ERROR;
        bp->b_error = EIO;
-       bp->b_resid = 0;
-       biodone(bp);
-       hpibfree(&rs->sc_dq);
-       bp = rdtab[unit].b_actf;
-       if (bp == NULL) {
-               rdtab[unit].b_active = 0;
-               return;
+       bp = rdfinish(unit, rs, bp);
+       if (bp) {
+               rs->sc_addr = bp->b_un.b_addr;
+               rs->sc_resid = bp->b_bcount;
+               if (hpibreq(&rs->sc_dq))
+                       goto again;
        }
        }
-       rs->sc_addr = bp->b_un.b_addr;
-       rs->sc_resid = bp->b_bcount;
-       if (hpibreq(&rs->sc_dq))
-               goto again;
 }
 
 rdgo(unit)
 }
 
 rdgo(unit)
@@ -741,6 +646,10 @@ rdgo(unit)
                dk_xfer[hp->hp_dk]++;
                dk_wds[hp->hp_dk] += rs->sc_resid >> 6;
        }
                dk_xfer[hp->hp_dk]++;
                dk_wds[hp->hp_dk] += rs->sc_resid >> 6;
        }
+#ifdef USELEDS
+       if (inledcontrol == 0)
+               ledcontrol(0, 0, LED_DISK);
+#endif
        hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,
               rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);
 }
        hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,
               rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);
 }
@@ -805,15 +714,8 @@ rdintr(unit)
                bp->b_flags |= B_ERROR;
                bp->b_error = EIO;
        }
                bp->b_flags |= B_ERROR;
                bp->b_error = EIO;
        }
-       rdtab[unit].b_errcnt = 0;
-       rdtab[unit].b_actf = bp->b_actf;
-       bp->b_resid = 0;
-       biodone(bp);
-       hpibfree(&rs->sc_dq);
-       if (rdtab[unit].b_actf)
+       if (rdfinish(unit, rs, bp))
                rdustart(unit);
                rdustart(unit);
-       else
-               rdtab[unit].b_active = 0;
 }
 
 rdstatus(rs)
 }
 
 rdstatus(rs)
@@ -920,8 +822,7 @@ rderror(unit)
         * we just use b_blkno.
         */
        bp = rdtab[unit].b_actf;
         * we just use b_blkno.
         */
        bp = rdtab[unit].b_actf;
-       pbn = rs->sc_info->nbpc *
-               rs->sc_info->sizes[rdpart(bp->b_dev)].cyloff;
+       pbn = rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)].p_offset;
        if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
            (sp->c_ief & IEF_RRMASK)) {
                hwbn = RDBTOS(pbn + bp->b_blkno);
        if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
            (sp->c_ief & IEF_RRMASK)) {
                hwbn = RDBTOS(pbn + bp->b_blkno);
@@ -984,7 +885,6 @@ rdread(dev, uio, flags)
        struct uio *uio;
        int flags;
 {
        struct uio *uio;
        int flags;
 {
-       register int unit = rdunit(dev);
 
        return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
 }
 
        return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
 }
@@ -995,7 +895,6 @@ rdwrite(dev, uio, flags)
        struct uio *uio;
        int flags;
 {
        struct uio *uio;
        int flags;
 {
-       register int unit = rdunit(dev);
 
        return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
 }
 
        return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
 }
@@ -1008,6 +907,52 @@ rdioctl(dev, cmd, data, flag, p)
        int flag;
        struct proc *p;
 {
        int flag;
        struct proc *p;
 {
+       int unit = rdunit(dev);
+       register struct rd_softc *sc = &rd_softc[unit];
+       register struct disklabel *lp = &sc->sc_info.ri_label;
+       int error, flags;
+
+       switch (cmd) {
+       case DIOCGDINFO:
+               *(struct disklabel *)data = *lp;
+               return (0);
+
+       case DIOCGPART:
+               ((struct partinfo *)data)->disklab = lp;
+               ((struct partinfo *)data)->part =
+                       &lp->d_partitions[rdpart(dev)];
+               return (0);
+
+        case DIOCWLABEL:
+                if ((flag & FWRITE) == 0)
+                        return (EBADF);
+               if (*(int *)data)
+                       sc->sc_flags |= RDF_WLABEL;
+               else
+                       sc->sc_flags &= ~RDF_WLABEL;
+               return (0);
+
+        case DIOCSDINFO:
+                if ((flag & FWRITE) == 0)
+                        return (EBADF);
+               return (setdisklabel(lp, (struct disklabel *)data,
+                                    (sc->sc_flags & RDF_WLABEL) ? 0
+                                    : sc->sc_info.ri_open));
+
+        case DIOCWDINFO:
+               if ((flag & FWRITE) == 0)
+                       return (EBADF);
+               error = setdisklabel(lp, (struct disklabel *)data,
+                                    (sc->sc_flags & RDF_WLABEL) ? 0
+                                    : sc->sc_info.ri_open);
+               if (error)
+                       return (error);
+               flags = sc->sc_flags;
+               sc->sc_flags = RDF_ALIVE | RDF_WLABEL;
+               error = writedisklabel(rdlabdev(dev), rdstrategy, lp);
+               sc->sc_flags = flags;
+               return (error);
+       }
        return(EINVAL);
 }
 
        return(EINVAL);
 }
 
@@ -1017,10 +962,25 @@ rdsize(dev)
 {
        register int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
 {
        register int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
+       int psize, didopen = 0;
 
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return(-1);
 
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return(-1);
-       return(rs->sc_info->sizes[rdpart(dev)].nblocks);
+
+       /*
+        * We get called very early on (via swapconf)
+        * without the device being open so we may need
+        * to handle it here.
+        */
+       if (rs->sc_info.ri_open == 0) {
+               if (rdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))
+                       return(-1);
+               didopen = 1;
+       }
+       psize = rs->sc_info.ri_label.d_partitions[rdpart(dev)].p_size;
+       if (didopen)
+               (void) rdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);
+       return (psize);
 }
 
 #ifdef DEBUG
 }
 
 #ifdef DEBUG
@@ -1054,6 +1014,7 @@ rddump(dev)
        int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
        register struct hp_device *hp = rs->sc_hd;
        int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
        register struct hp_device *hp = rs->sc_hd;
+       register struct partition *pinfo;
        register daddr_t baddr;
        register int maddr, pages, i;
        char stat;
        register daddr_t baddr;
        register int maddr, pages, i;
        char stat;
@@ -1063,46 +1024,31 @@ rddump(dev)
        pmapdebug = 0;
 #endif
 
        pmapdebug = 0;
 #endif
 
-       pages = dumpsize;
-#ifdef DEBUG
-       if (rddebug & RDB_DUMP)
-               printf("rddump(%x): u %d p %d dumplo %d ram %x pmem %d\n",
-                      dev, unit, part, dumplo, lowram, ctod(pages));
-#endif
        /* is drive ok? */
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return (ENXIO);
        /* is drive ok? */
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return (ENXIO);
+       pinfo = &rs->sc_info.ri_label.d_partitions[part];
+       /* dump parameters in range? */
+       if (dumplo < 0 || dumplo >= pinfo->p_size ||
+           pinfo->p_fstype != FS_SWAP)
+               return (EINVAL);
+       pages = dumpsize;
+       if (dumplo + ctod(pages) > pinfo->p_size)
+               pages = dtoc(pinfo->p_size - dumplo);
+       maddr = lowram;
+       baddr = dumplo + pinfo->p_offset;
        /* HPIB idle? */
        if (!hpibreq(&rs->sc_dq)) {
        /* HPIB idle? */
        if (!hpibreq(&rs->sc_dq)) {
-#ifdef DEBUG
-               /* is this a safe thing to do?? */
                hpibreset(hp->hp_ctlr);
                rdreset(rs, rs->sc_hd);
                printf("[ drive %d reset ] ", unit);
                hpibreset(hp->hp_ctlr);
                rdreset(rs, rs->sc_hd);
                printf("[ drive %d reset ] ", unit);
-#else
-               return (EFAULT);
-#endif
        }
        }
-       /* dump parameters in range? */
-       if (dumplo < 0 || dumplo >= rs->sc_info->sizes[part].nblocks)
-               return (EINVAL);
-       if (dumplo + ctod(pages) > rs->sc_info->sizes[part].nblocks)
-               pages = dtoc(rs->sc_info->sizes[part].nblocks - dumplo);
-       maddr = lowram;
-       baddr = dumplo + rs->sc_info->nbpc * rs->sc_info->sizes[part].cyloff;
-#ifdef DEBUG
-       if (rddebug & RDB_DUMP)
-               printf("rddump: dumping %d pages from %x to disk block %d\n",
-                      pages, maddr, baddr);
-#endif
        for (i = 0; i < pages; i++) {
        for (i = 0; i < pages; i++) {
-#ifdef DEBUG
 #define NPGMB  (1024*1024/NBPG)
                /* print out how many Mbs we have dumped */
                if (i && (i % NPGMB) == 0)
                        printf("%d ", i / NPGMB);
 #undef NPBMG
 #define NPGMB  (1024*1024/NBPG)
                /* print out how many Mbs we have dumped */
                if (i && (i % NPGMB) == 0)
                        printf("%d ", i / NPGMB);
 #undef NPBMG
-#endif
                rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
                rs->sc_ioc.c_volume = C_SVOL(0);
                rs->sc_ioc.c_saddr = C_SADDR;
                rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
                rs->sc_ioc.c_volume = C_SVOL(0);
                rs->sc_ioc.c_saddr = C_SADDR;
@@ -1114,31 +1060,15 @@ rddump(dev)
                rs->sc_ioc.c_cmd = C_WRITE;
                hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,
                         &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
                rs->sc_ioc.c_cmd = C_WRITE;
                hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,
                         &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
-               if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
-#ifdef DEBUG
-                       if (rddebug & RDB_DUMP)
-                               printf("rddump: IOC wait timeout\n");
-#endif
+               if (hpibswait(hp->hp_ctlr, hp->hp_slave))
                        return (EIO);
                        return (EIO);
-               }
                pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,
                    VM_PROT_READ, TRUE);
                hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
                pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,
                    VM_PROT_READ, TRUE);
                hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
-               if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
-#ifdef DEBUG
-                       if (rddebug & RDB_DUMP)
-                               printf("rddump: write wait timeout\n");
-#endif
-               }
+               (void) hpibswait(hp->hp_ctlr, hp->hp_slave);
                hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
                hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
-               if (stat) {
-#ifdef DEBUG
-                       if (rddebug & RDB_DUMP)
-                               printf("rddump: write failed, status %x\n",
-                                      stat);
-#endif
+               if (stat)
                        return (EIO);
                        return (EIO);
-               }
                maddr += NBPG;
                baddr += ctod(1);
        }
                maddr += NBPG;
                baddr += ctod(1);
        }
index 6bdc1dc..d555301 100644 (file)
@@ -11,7 +11,7 @@
  *
  * from: Utah $Hdr: rdreg.h 1.2 90/10/12$
  *
  *
  * from: Utah $Hdr: rdreg.h 1.2 90/10/12$
  *
- *     @(#)rdreg.h     7.3 (Berkeley) %G%
+ *     @(#)rdreg.h     7.4 (Berkeley) %G%
  */
 
 struct rd_iocmd {
  */
 
 struct rd_iocmd {
@@ -103,25 +103,6 @@ struct rd_describe {
                d_interleave:8; /* volume: current interleave */
  };
 
                d_interleave:8; /* volume: current interleave */
  };
 
-/* indicies into rdinfo -- order is arbitrary */
-#define        RD7945A         0
-#define        RD9134D         1
-#define        RD9122S         2
-#define        RD7912P         3
-#define        RD7914P         4
-#define        RD7958A         5
-#define RD7957A                6
-#define        RD7933H         7
-#define        RD9134L         8
-#define        RD7936H         9
-#define        RD7937H         10
-#define RD7914CT       11
-#define RD7946A                12
-#define RD9122D                13
-#define RD7957B                14
-#define RD7958B                15
-#define RD7959B                16
-
 /* HW ids */
 #define        RD7946AID       0x220   /* also 7945A */
 #define        RD9134DID       0x221   /* also 9122S */
 /* HW ids */
 #define        RD7946AID       0x220   /* also 7945A */
 #define        RD9134DID       0x221   /* also 9122S */
@@ -140,19 +121,38 @@ struct rd_describe {
 #define RD2200AID      0x22F
 #define RD2203AID      0x230   /* yet another guess */
 
 #define RD2200AID      0x22F
 #define RD2203AID      0x230   /* yet another guess */
 
-#define        NRD7945ABPT     (32 >> (DEV_BSHIFT-8))
+/* SW ids -- indicies into rdidentinfo, order is arbitrary */
+#define        RD7945A         0
+#define        RD9134D         1
+#define        RD9122S         2
+#define        RD7912P         3
+#define        RD7914P         4
+#define        RD7958A         5
+#define RD7957A                6
+#define        RD7933H         7
+#define        RD9134L         8
+#define        RD7936H         9
+#define        RD7937H         10
+#define RD7914CT       11
+#define RD7946A                12
+#define RD9122D                13
+#define RD7957B                14
+#define RD7958B                15
+#define RD7959B                16
+
+#define        NRD7945ABPT     16
 #define        NRD7945ATRK     7
 #define        NRD7945ATRK     7
-#define        NRD9134DBPT     (32 >> (DEV_BSHIFT-8))
+#define        NRD9134DBPT     16
 #define        NRD9134DTRK     6
 #define        NRD9134DTRK     6
-#define        NRD9122SBPT     (16 >> (DEV_BSHIFT-8))
+#define        NRD9122SBPT     8
 #define        NRD9122STRK     2
 #define        NRD9122STRK     2
-#define        NRD7912PBPT     (64 >> (DEV_BSHIFT-8))
+#define        NRD7912PBPT     32
 #define        NRD7912PTRK     7
 #define        NRD7912PTRK     7
-#define        NRD7914PBPT     (64 >> (DEV_BSHIFT-8))
+#define        NRD7914PBPT     32
 #define        NRD7914PTRK     7
 #define        NRD7914PTRK     7
-#define        NRD7933HBPT     (92 >> (DEV_BSHIFT-8))
+#define        NRD7933HBPT     46
 #define        NRD7933HTRK     13
 #define        NRD7933HTRK     13
-#define        NRD9134LBPT     (32 >> (DEV_BSHIFT-8))
+#define        NRD9134LBPT     16
 #define        NRD9134LTRK     5
 
 /*
 #define        NRD9134LTRK     5
 
 /*
@@ -179,42 +179,24 @@ struct rd_describe {
  * 2200A:      113 x  8 x 1449         113 x  2 x 1449         113 x  4 x 1449
  * 2203A:      113 x 16 x 1449         113 x  4 x 1449         113 x  8 x 1449
  */
  * 2200A:      113 x  8 x 1449         113 x  2 x 1449         113 x  4 x 1449
  * 2203A:      113 x 16 x 1449         113 x  4 x 1449         113 x  8 x 1449
  */
-#if DEV_BSIZE == 512
-#      define  NRD7936HBPT     123
-#      define  NRD7936HTRK     7
-#      define  NRD7937HBPT     123
-#      define  NRD7937HTRK     13
-#      define  NRD7957ABPT     22
-#      define  NRD7957ATRK     7
-#      define  NRD7958ABPT     36
-#      define  NRD7958ATRK     7
-#      define  NRD7957BBPT     18
-#      define  NRD7957BTRK     7
-#      define  NRD7958BBPT     42
-#      define  NRD7958BTRK     9
-#      define  NRD7959BBPT     42
-#      define  NRD7959BTRK     9
-#      define  NRD2200ABPT     113
-#      define  NRD2200ATRK     4
-#      define  NRD2203ABPT     113
-#      define  NRD2203ATRK     8
-#endif
-#if DEV_BSIZE == 1024
-#      define  NRD7957ABPT     11
-#      define  NRD7957ATRK     7
-#      define  NRD7958ABPT     21
-#      define  NRD7958ATRK     6
-#      define  NRD7957BBPT     9
-#      define  NRD7957BTRK     7
-#      define  NRD7958BBPT     21
-#      define  NRD7958BTRK     9
-#      define  NRD7959BBPT     21
-#      define  NRD7959BTRK     9
-#      define  NRD2200ABPT     113
-#      define  NRD2200ATRK     2
-#      define  NRD2203ABPT     113
-#      define  NRD2203ATRK     4
-#endif
+#define        NRD7936HBPT     123
+#define        NRD7936HTRK     7
+#define        NRD7937HBPT     123
+#define        NRD7937HTRK     13
+#define        NRD7957ABPT     22
+#define        NRD7957ATRK     7
+#define        NRD7958ABPT     36
+#define        NRD7958ATRK     7
+#define        NRD7957BBPT     18
+#define        NRD7957BTRK     7
+#define        NRD7958BBPT     42
+#define        NRD7958BTRK     9
+#define        NRD7959BBPT     42
+#define        NRD7959BTRK     9
+#define        NRD2200ABPT     113
+#define        NRD2200ATRK     4
+#define        NRD2203ABPT     113
+#define        NRD2203ATRK     8
 
 /* controller "unit" number */
 #define        RDCTLR          15
 
 /* controller "unit" number */
 #define        RDCTLR          15
index 693203e..98dca14 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)sd.c        7.16 (Berkeley) %G%
+ *     @(#)sd.c        7.17 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
 #if NSD > 0
 
 #ifndef lint
 #if NSD > 0
 
 #ifndef lint
-static char rcsid[] = "$Header: /usr/src/sys/hp300/dev/RCS/sd.c,v 1.2 92/04/10 20:48:35 mike Exp $";
+static char rcsid[] = "$Header: /usr/src/sys/hp300/dev/RCS/sd.c,v 1.4 92/12/26 13:26:40 mike Exp $";
 #endif
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/buf.h>
 #endif
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/buf.h>
+#include <sys/stat.h>
 #include <sys/dkstat.h>
 #include <sys/disklabel.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/ioctl.h>
 #include <sys/dkstat.h>
 #include <sys/disklabel.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/ioctl.h>
+#include <sys/fcntl.h>
 
 #include <hp/dev/device.h>
 #include <hp300/dev/scsireg.h>
 
 #include <hp/dev/device.h>
 #include <hp300/dev/scsireg.h>
+#include <hp300/dev/sdvar.h>
+#ifdef USELEDS
+#include <hp300/hp300/led.h>
+#endif
 
 #include <vm/vm_param.h>
 #include <vm/lock.h>
 
 #include <vm/vm_param.h>
 #include <vm/lock.h>
@@ -61,66 +67,14 @@ struct      driver sddriver = {
        sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr,
 };
 
        sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr,
 };
 
-struct size {
-       u_long  strtblk;
-       u_long  endblk;
-       int     nblocks;
-};
-
-struct sdinfo {
-       struct  size part[8];
-};
-
-/*
- * since the SCSI standard tends to hide the disk structure, we define
- * partitions in terms of DEV_BSIZE blocks.  The default partition table
- * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg
- * root and 32 meg of swap.  The rest of the space on the drive goes in
- * the G partition.  As usual, the C partition covers the entire disk
- * (including the boot area).
- */
-struct sdinfo sddefaultpart = {
-            1024,   17408,   16384   , /* A */
-           17408,   82944,   65536   , /* B */
-               0,       0,       0   , /* C */
-           17408,  115712,   98304   , /* D */
-          115712,  218112,  102400   , /* E */
-          218112,       0,       0   , /* F */
-           82944,       0,       0   , /* G */
-          115712,       0,       0   , /* H */
-};
-
-struct sd_softc {
-       struct  hp_device *sc_hd;
-       struct  devqueue sc_dq;
-       int     sc_format_pid;  /* process using "format" mode */
-       short   sc_flags;
-       short   sc_type;        /* drive type */
-       short   sc_punit;       /* physical unit (scsi lun) */
-       u_short sc_bshift;      /* convert device blocks to DEV_BSIZE blks */
-       u_int   sc_blks;        /* number of blocks on device */
-       int     sc_blksize;     /* device block size in bytes */
-       u_int   sc_wpms;        /* average xfer rate in 16 bit wds/sec. */
-       struct  sdinfo sc_info; /* drive partition table & label info */
-} sd_softc[NSD];
-
-/* sc_flags values */
-#define        SDF_ALIVE       0x1
-#define SDF_WANTED     0x2
-#define SDF_RMEDIA     0x4
-
 #ifdef DEBUG
 int sddebug = 1;
 #define SDB_ERROR      0x01
 #define SDB_PARTIAL    0x02
 #endif
 
 #ifdef DEBUG
 int sddebug = 1;
 #define SDB_ERROR      0x01
 #define SDB_PARTIAL    0x02
 #endif
 
-struct sdstats {
-       long    sdresets;
-       long    sdtransfers;
-       long    sdpartials;
-} sdstats[NSD];
-
+struct sd_softc sd_softc[NSD];
+struct sdstats sdstats[NSD];
 struct buf sdtab[NSD];
 struct scsi_fmt_cdb sdcmd[NSD];
 struct scsi_fmt_sense sdsense[NSD];
 struct buf sdtab[NSD];
 struct scsi_fmt_cdb sdcmd[NSD];
 struct scsi_fmt_sense sdsense[NSD];
@@ -128,13 +82,6 @@ struct      scsi_fmt_sense sdsense[NSD];
 static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
 static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
 
 static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
 static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
 
-#define        sdunit(x)       (minor(x) >> 3)
-#define sdpart(x)      (minor(x) & 0x7)
-#define        sdpunit(x)      ((x) & 7)
-#define        b_cylin         b_resid
-
-#define        SDRETRY         2
-
 /*
  * Table of scsi commands users are allowed to access via "format"
  * mode.  0 means not legal.  1 means "immediate" (doesn't need dma).
 /*
  * Table of scsi commands users are allowed to access via "format"
  * mode.  0 means not legal.  1 means "immediate" (doesn't need dma).
@@ -241,10 +188,9 @@ sdident(sc, hd)
        /*
         * Get a usable id string
         */
        /*
         * Get a usable id string
         */
-       if (inqbuf.version != 1) {
-               bcopy("UNKNOWN", &idstr[0], 8);
-               bcopy("DRIVE TYPE", &idstr[8], 11);
-       } else {
+       switch (inqbuf.version) {
+       case 1:
+       case 2:
                bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
                for (i = 27; i > 23; --i)
                        if (idstr[i] != ' ')
                bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
                for (i = 27; i > 23; --i)
                        if (idstr[i] != ' ')
@@ -258,6 +204,10 @@ sdident(sc, hd)
                        if (idstr[i] != ' ')
                                break;
                idstr[i+1] = 0;
                        if (idstr[i] != ' ')
                                break;
                idstr[i+1] = 0;
+               break;
+       default:
+               bcopy("UNKNOWN", &idstr[0], 8);
+               bcopy("DRIVE TYPE", &idstr[8], 11);
        }
        i = scsi_immed_command(ctlr, slave, unit, &cap,
                               (u_char *)&capbuf, sizeof(capbuf), B_READ);
        }
        i = scsi_immed_command(ctlr, slave, unit, &cap,
                               (u_char *)&capbuf, sizeof(capbuf), B_READ);
@@ -276,12 +226,19 @@ sdident(sc, hd)
        /* return value of read capacity is last valid block number */
        sc->sc_blks++;
 
        /* return value of read capacity is last valid block number */
        sc->sc_blks++;
 
-       if (inqbuf.version != 1)
-               printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit,
-                       inqbuf.type, inqbuf.qual, inqbuf.version);
-       else
+       switch (inqbuf.version) {
+       case 1:
+       case 2:
                printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
                        &idstr[24]);
                printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
                        &idstr[24]);
+               if (inqbuf.version == 2)
+                       printf(" (SCSI-2)");
+               break;
+       default:
+               printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit,
+                      inqbuf.type, inqbuf.qual, inqbuf.version);
+               break;
+       }
        printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
        if (inqbuf.qual & 0x80)
                sc->sc_flags |= SDF_RMEDIA;
        printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
        if (inqbuf.qual & 0x80)
                sc->sc_flags |= SDF_RMEDIA;
@@ -320,44 +277,6 @@ sdinit(hd)
        sc->sc_dq.dq_slave = hd->hp_slave;
        sc->sc_dq.dq_driver = &sddriver;
 
        sc->sc_dq.dq_slave = hd->hp_slave;
        sc->sc_dq.dq_driver = &sddriver;
 
-       /*
-        * If we don't have a disk label, build a default partition
-        * table with 'standard' size root & swap and everything else
-        * in the G partition.
-        */
-       sc->sc_info = sddefaultpart;
-       /* C gets everything */
-       sc->sc_info.part[2].nblocks = sc->sc_blks;
-       sc->sc_info.part[2].endblk = sc->sc_blks;
-       /* G gets from end of B to end of disk */
-       sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk;
-       sc->sc_info.part[6].endblk = sc->sc_blks;
-       /*
-        * We also define the D, E and F paritions as an alternative to
-        * B and G.  D is 48Mb, starts after A and is intended for swapping.
-        * E is 50Mb, starts after D and is intended for /usr. F starts
-        * after E and is what ever is left.
-        */
-       if (sc->sc_blks >= sc->sc_info.part[4].endblk) {
-               sc->sc_info.part[5].nblocks =
-                       sc->sc_blks - sc->sc_info.part[4].endblk;
-               sc->sc_info.part[5].endblk = sc->sc_blks;
-       } else {
-               sc->sc_info.part[5].strtblk = 0;
-               sc->sc_info.part[3] = sc->sc_info.part[5];
-               sc->sc_info.part[4] = sc->sc_info.part[5];
-       }
-       /*
-        * H is a single partition alternative to E and F.
-        */
-       if (sc->sc_blks >= sc->sc_info.part[3].endblk) {
-               sc->sc_info.part[7].nblocks =
-                       sc->sc_blks - sc->sc_info.part[3].endblk;
-               sc->sc_info.part[7].endblk = sc->sc_blks;
-       } else {
-               sc->sc_info.part[7].strtblk = 0;
-       }
-
        sc->sc_flags |= SDF_ALIVE;
        return(1);
 }
        sc->sc_flags |= SDF_ALIVE;
        return(1);
 }
@@ -370,6 +289,56 @@ sdreset(sc, hd)
        sdstats[hd->hp_unit].sdresets++;
 }
 
        sdstats[hd->hp_unit].sdresets++;
 }
 
+/*
+ * Read or constuct a disklabel
+ */
+int
+sdgetinfo(dev)
+       dev_t dev;
+{
+       int unit = sdunit(dev);
+       register struct sd_softc *sc = &sd_softc[unit];
+       register struct disklabel *lp = &sc->sc_info.si_label;
+       register struct partition *pi;
+       char *msg, *readdisklabel();
+
+       /*
+        * Set some default values to use while reading the label
+        * or to use if there isn't a label.
+        */
+       bzero((caddr_t)lp, sizeof *lp);
+       lp->d_type = DTYPE_SCSI;
+       lp->d_secsize = DEV_BSIZE;
+       lp->d_nsectors = 32;
+       lp->d_ntracks = 20;
+       lp->d_secpercyl = 32*20;
+       lp->d_npartitions = 3;
+       lp->d_partitions[2].p_offset = 0;
+       /* XXX ensure size is at least one device block */
+       lp->d_partitions[2].p_size =
+               roundup(LABELSECTOR+1, btodb(sc->sc_blksize));
+
+       /*
+        * Now try to read the disklabel
+        */
+       msg = readdisklabel(sdlabdev(dev), sdstrategy, lp);
+       if (msg == NULL)
+               return(0);
+       if (bcmp(msg, "I/O", 3) == 0) /* XXX */
+               return(EIO);
+
+       pi = lp->d_partitions;
+       printf("sd%d: WARNING: %s, ", unit, msg);
+#ifdef COMPAT_NOLABEL
+       printf("using old default partitioning\n");
+       sdmakedisklabel(unit, lp);
+#else
+       printf("defining `c' partition as entire disk\n");
+       pi[2].p_size = sc->sc_blks;
+#endif
+       return(0);
+}
+
 int
 sdopen(dev, flags, mode, p)
        dev_t dev;
 int
 sdopen(dev, flags, mode, p)
        dev_t dev;
@@ -378,14 +347,42 @@ sdopen(dev, flags, mode, p)
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
+       int mask, error;
 
        if (unit >= NSD)
                return(ENXIO);
        if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
                return(ENXIO);
 
        if (unit >= NSD)
                return(ENXIO);
        if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
                return(ENXIO);
+       if (sc->sc_flags & SDF_ERROR)
+               return(EIO);
 
 
+       /*
+        * Wait for any pending opens/closes to complete
+        */
+       while (sc->sc_flags & (SDF_OPENING|SDF_CLOSING))
+               sleep((caddr_t)sc, PRIBIO);
+       /*
+        * On first open, get label and partition info.
+        * We may block reading the label, so be careful
+        * to stop any other opens.
+        */
+       if (sc->sc_info.si_open == 0) {
+               sc->sc_flags |= SDF_OPENING;
+               error = sdgetinfo(dev);
+               sc->sc_flags &= ~SDF_OPENING;
+               wakeup((caddr_t)sc);
+               if (error)
+                       return(error);
+       }
        if (sc->sc_hd->hp_dk >= 0)
                dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
        if (sc->sc_hd->hp_dk >= 0)
                dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
+
+       mask = 1 << sdpart(dev);
+       if (mode == S_IFCHR)
+               sc->sc_info.si_copen |= mask;
+       else
+               sc->sc_info.si_bopen |= mask;
+       sc->sc_info.si_open |= mask;
        return(0);
 }
 
        return(0);
 }
 
@@ -397,20 +394,35 @@ sdclose(dev, flag, mode, p)
 {
        int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
 {
        int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
-       int s;
+       register struct sdinfo *si = &sc->sc_info;
+       int mask, s;
 
 
+       mask = 1 << sdpart(dev);
+       if (mode == S_IFCHR)
+               si->si_copen &= ~mask;
+       else
+               si->si_bopen &= ~mask;
+       si->si_open = si->si_bopen | si->si_copen;
        /*
        /*
-        * XXX we should really do this for all drives.
+        * On last close, we wait for all activity to cease since
+        * the label/parition info will become invalid.  Since we
+        * might sleep, we must block any opens while we are here.
+        * Note we don't have to about other closes since we know
+        * we are the last one.
         */
         */
-       if (sc->sc_flags & SDF_RMEDIA) {
+       if (si->si_open == 0) {
+               sc->sc_flags |= SDF_CLOSING;
                s = splbio();
                while (sdtab[unit].b_active) {
                        sc->sc_flags |= SDF_WANTED;
                        sleep((caddr_t)&sdtab[unit], PRIBIO);
                }
                splx(s);
                s = splbio();
                while (sdtab[unit].b_active) {
                        sc->sc_flags |= SDF_WANTED;
                        sleep((caddr_t)&sdtab[unit], PRIBIO);
                }
                splx(s);
+               sc->sc_flags &= ~(SDF_CLOSING|SDF_WLABEL|SDF_ERROR);
+               wakeup((caddr_t)sc);
        }
        sc->sc_format_pid = 0;
        }
        sc->sc_format_pid = 0;
+       return(0);
 }
 
 /*
 }
 
 /*
@@ -515,36 +527,50 @@ void
 sdstrategy(bp)
        register struct buf *bp;
 {
 sdstrategy(bp)
        register struct buf *bp;
 {
-       register int unit = sdunit(bp->b_dev);
+       int unit = sdunit(bp->b_dev);
        register struct sd_softc *sc = &sd_softc[unit];
        register struct sd_softc *sc = &sd_softc[unit];
-       register struct size *pinfo = &sc->sc_info.part[sdpart(bp->b_dev)];
        register struct buf *dp = &sdtab[unit];
        register struct buf *dp = &sdtab[unit];
+       register struct partition *pinfo;
        register daddr_t bn;
        register int sz, s;
 
        register daddr_t bn;
        register int sz, s;
 
+       if (sc->sc_flags & SDF_ERROR) {
+               bp->b_error = EIO;
+               goto bad;
+       }
        if (sc->sc_format_pid) {
                if (sc->sc_format_pid != curproc->p_pid) {      /* XXX */
                        bp->b_error = EPERM;
        if (sc->sc_format_pid) {
                if (sc->sc_format_pid != curproc->p_pid) {      /* XXX */
                        bp->b_error = EPERM;
-                       bp->b_flags |= B_ERROR;
-                       goto done;
+                       goto bad;
                }
                bp->b_cylin = 0;
        } else {
                bn = bp->b_blkno;
                sz = howmany(bp->b_bcount, DEV_BSIZE);
                }
                bp->b_cylin = 0;
        } else {
                bn = bp->b_blkno;
                sz = howmany(bp->b_bcount, DEV_BSIZE);
-               if (bn < 0 || bn + sz > pinfo->nblocks) {
-                       sz = pinfo->nblocks - bn;
+               pinfo = &sc->sc_info.si_label.d_partitions[sdpart(bp->b_dev)];
+               if (bn < 0 || bn + sz > pinfo->p_size) {
+                       sz = pinfo->p_size - bn;
                        if (sz == 0) {
                                bp->b_resid = bp->b_bcount;
                                goto done;
                        }
                        if (sz < 0) {
                                bp->b_error = EINVAL;
                        if (sz == 0) {
                                bp->b_resid = bp->b_bcount;
                                goto done;
                        }
                        if (sz < 0) {
                                bp->b_error = EINVAL;
-                               bp->b_flags |= B_ERROR;
-                               goto done;
+                               goto bad;
                        }
                        bp->b_bcount = dbtob(sz);
                }
                        }
                        bp->b_bcount = dbtob(sz);
                }
+               /*
+                * Check for write to write protected label
+                */
+               if (bn + pinfo->p_offset <= LABELSECTOR &&
+#if LABELSECTOR != 0
+                   bn + pinfo->p_offset + sz > LABELSECTOR &&
+#endif
+                   !(bp->b_flags & B_READ) && !(sc->sc_flags & SDF_WLABEL)) {
+                       bp->b_error = EROFS;
+                       goto bad;
+               }
                /*
                 * Non-aligned or partial-block transfers handled specially.
                 */
                /*
                 * Non-aligned or partial-block transfers handled specially.
                 */
@@ -553,7 +579,7 @@ sdstrategy(bp)
                        sdlblkstrat(bp, sc->sc_blksize);
                        goto done;
                }
                        sdlblkstrat(bp, sc->sc_blksize);
                        goto done;
                }
-               bp->b_cylin = (bn + pinfo->strtblk) >> sc->sc_bshift;
+               bp->b_cylin = (bn + pinfo->p_offset) >> sc->sc_bshift;
        }
        s = splbio();
        disksort(dp, bp);
        }
        s = splbio();
        disksort(dp, bp);
@@ -563,6 +589,8 @@ sdstrategy(bp)
        }
        splx(s);
        return;
        }
        splx(s);
        return;
+bad:
+       bp->b_flags |= B_ERROR;
 done:
        biodone(bp);
 }
 done:
        biodone(bp);
 }
@@ -612,6 +640,23 @@ sderror(unit, sc, hp, stat)
                        case 1:
                                cond = 0;
                                break;
                        case 1:
                                cond = 0;
                                break;
+                       /* possible media change */
+                       case 6:
+                               /*
+                                * For removable media, if we are doing the
+                                * first open (i.e. reading the label) go
+                                * ahead and retry, otherwise someone has
+                                * changed the media out from under us and
+                                * we should abort any further operations
+                                * until a close is done.
+                                */
+                               if (sc->sc_flags & SDF_RMEDIA) {
+                                       if (sc->sc_flags & SDF_OPENING)
+                                               cond = -1;
+                                       else
+                                               sc->sc_flags |= SDF_ERROR;
+                               }
+                               break;
                        }
                }
                printf("\n");
                        }
                }
                printf("\n");
@@ -684,6 +729,15 @@ sdgo(unit)
        register int pad;
        register struct scsi_fmt_cdb *cmd;
 
        register int pad;
        register struct scsi_fmt_cdb *cmd;
 
+       /*
+        * Drive is in an error state, abort all operations
+        */
+       if (sc->sc_flags & SDF_ERROR) {
+               bp->b_flags |= B_ERROR;
+               bp->b_error = EIO;
+               sdfinish(unit, sc, bp);
+               return;
+       }
        if (sc->sc_format_pid) {
                cmd = &sdcmd[unit];
                pad = 0;
        if (sc->sc_format_pid) {
                cmd = &sdcmd[unit];
                pad = 0;
@@ -700,6 +754,10 @@ sdgo(unit)
 #endif
                sdstats[unit].sdtransfers++;
        }
 #endif
                sdstats[unit].sdtransfers++;
        }
+#ifdef USELEDS
+       if (inledcontrol == 0)
+               ledcontrol(0, 0, LED_DISK);
+#endif
        if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) {
                if (hp->hp_dk >= 0) {
                        dk_busy |= 1 << hp->hp_dk;
        if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) {
                if (hp->hp_dk >= 0) {
                        dk_busy |= 1 << hp->hp_dk;
@@ -801,13 +859,56 @@ sdioctl(dev, cmd, data, flag, p)
        int flag;
        struct proc *p;
 {
        int flag;
        struct proc *p;
 {
-       register int unit = sdunit(dev);
+       int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
        register struct sd_softc *sc = &sd_softc[unit];
+       register struct disklabel *lp = &sc->sc_info.si_label;
+       int error, flags;
 
        switch (cmd) {
        default:
                return (EINVAL);
 
 
        switch (cmd) {
        default:
                return (EINVAL);
 
+       case DIOCGDINFO:
+               *(struct disklabel *)data = *lp;
+               return (0);
+
+       case DIOCGPART:
+               ((struct partinfo *)data)->disklab = lp;
+               ((struct partinfo *)data)->part =
+                       &lp->d_partitions[sdpart(dev)];
+               return (0);
+
+        case DIOCWLABEL:
+                if ((flag & FWRITE) == 0)
+                        return (EBADF);
+               if (*(int *)data)
+                       sc->sc_flags |= SDF_WLABEL;
+               else
+                       sc->sc_flags &= ~SDF_WLABEL;
+               return (0);
+
+        case DIOCSDINFO:
+                if ((flag & FWRITE) == 0)
+                        return (EBADF);
+               error = setdisklabel(lp, (struct disklabel *)data,
+                                    (sc->sc_flags & SDF_WLABEL) ? 0
+                                    : sc->sc_info.si_open);
+               return (error);
+
+        case DIOCWDINFO:
+               if ((flag & FWRITE) == 0)
+                       return (EBADF);
+               error = setdisklabel(lp, (struct disklabel *)data,
+                                    (sc->sc_flags & SDF_WLABEL) ? 0
+                                    : sc->sc_info.si_open);
+               if (error)
+                       return (error);
+               flags = sc->sc_flags;
+               sc->sc_flags = SDF_ALIVE | SDF_WLABEL;
+               error = writedisklabel(sdlabdev(dev), sdstrategy, lp);
+               sc->sc_flags = flags;
+               return (error);
+
        case SDIOCSFORMAT:
                /* take this device into or out of "format" mode */
                if (suser(p->p_ucred, &p->p_acflag))
        case SDIOCSFORMAT:
                /* take this device into or out of "format" mode */
                if (suser(p->p_ucred, &p->p_acflag))
@@ -856,11 +957,25 @@ sdsize(dev)
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
+       int psize, didopen = 0;
 
        if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
                return(-1);
 
 
        if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
                return(-1);
 
-       return(sc->sc_info.part[sdpart(dev)].nblocks);
+       /*
+        * We get called very early on (via swapconf)
+        * without the device being open so we may need
+        * to handle it here.
+        */
+       if (sc->sc_info.si_open == 0) {
+               if (sdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))
+                       return(-1);
+               didopen = 1;
+       }
+       psize = sc->sc_info.si_label.d_partitions[sdpart(dev)].p_size;
+       if (didopen)
+               (void) sdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);
+       return (psize);
 }
 
 /*
 }
 
 /*
@@ -874,30 +989,26 @@ sddump(dev)
        int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
        register struct hp_device *hp = sc->sc_hd;
        int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
        register struct hp_device *hp = sc->sc_hd;
+       register struct partition *pinfo;
        register daddr_t baddr;
        register int maddr;
        register int pages, i;
        int stat;
        extern int lowram;
 
        register daddr_t baddr;
        register int maddr;
        register int pages, i;
        int stat;
        extern int lowram;
 
-       /*
-        * Hmm... all vax drivers dump maxfree pages which is physmem minus
-        * the message buffer.  Is there a reason for not dumping the
-        * message buffer?  Savecore expects to read 'dumpsize' pages of
-        * dump, where dumpsys() sets dumpsize to physmem!
-        */
-       pages = physmem;
-
        /* is drive ok? */
        if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
                return (ENXIO);
        /* is drive ok? */
        if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
                return (ENXIO);
+       pinfo = &sc->sc_info.si_label.d_partitions[part];
        /* dump parameters in range? */
        /* dump parameters in range? */
-       if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks)
+       if (dumplo < 0 || dumplo >= pinfo->p_size ||
+           pinfo->p_fstype != FS_SWAP)
                return (EINVAL);
                return (EINVAL);
-       if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks)
-               pages = dtoc(sc->sc_info.part[part].nblocks - dumplo);
+       pages = physmem;
+       if (dumplo + ctod(pages) > pinfo->p_size)
+               pages = dtoc(pinfo->p_size - dumplo);
        maddr = lowram;
        maddr = lowram;
-       baddr = dumplo + sc->sc_info.part[part].strtblk;
+       baddr = dumplo + pinfo->p_offset;
        /* scsi bus idle? */
        if (!scsireq(&sc->sc_dq)) {
                scsireset(hp->hp_ctlr);
        /* scsi bus idle? */
        if (!scsireq(&sc->sc_dq)) {
                scsireset(hp->hp_ctlr);