1 1.45 andvar /* $NetBSD: rd.c,v 1.45 2023/02/12 16:04:57 andvar Exp $ */ 2 1.1 gmcgarry 3 1.1 gmcgarry /*- 4 1.1 gmcgarry * Copyright (c) 1996-2003 The NetBSD Foundation, Inc. 5 1.1 gmcgarry * All rights reserved. 6 1.1 gmcgarry * 7 1.1 gmcgarry * This code is derived from software contributed to The NetBSD Foundation 8 1.1 gmcgarry * by Jason R. Thorpe. 9 1.1 gmcgarry * 10 1.1 gmcgarry * Redistribution and use in source and binary forms, with or without 11 1.1 gmcgarry * modification, are permitted provided that the following conditions 12 1.1 gmcgarry * are met: 13 1.1 gmcgarry * 1. Redistributions of source code must retain the above copyright 14 1.1 gmcgarry * notice, this list of conditions and the following disclaimer. 15 1.1 gmcgarry * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 gmcgarry * notice, this list of conditions and the following disclaimer in the 17 1.1 gmcgarry * documentation and/or other materials provided with the distribution. 18 1.1 gmcgarry * 19 1.1 gmcgarry * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 gmcgarry * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 gmcgarry * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 gmcgarry * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 gmcgarry * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 gmcgarry * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 gmcgarry * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 gmcgarry * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 gmcgarry * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 gmcgarry * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 gmcgarry * POSSIBILITY OF SUCH DAMAGE. 30 1.1 gmcgarry */ 31 1.1 gmcgarry 32 1.1 gmcgarry /* 33 1.28 rmind * Copyright (c) 1988 University of Utah. 34 1.1 gmcgarry * Copyright (c) 1982, 1990, 1993 35 1.1 gmcgarry * The Regents of the University of California. All rights reserved. 36 1.1 gmcgarry * 37 1.1 gmcgarry * This code is derived from software contributed to Berkeley by 38 1.1 gmcgarry * the Systems Programming Group of the University of Utah Computer 39 1.1 gmcgarry * Science Department. 40 1.1 gmcgarry * 41 1.1 gmcgarry * Redistribution and use in source and binary forms, with or without 42 1.1 gmcgarry * modification, are permitted provided that the following conditions 43 1.1 gmcgarry * are met: 44 1.1 gmcgarry * 1. Redistributions of source code must retain the above copyright 45 1.1 gmcgarry * notice, this list of conditions and the following disclaimer. 46 1.1 gmcgarry * 2. Redistributions in binary form must reproduce the above copyright 47 1.1 gmcgarry * notice, this list of conditions and the following disclaimer in the 48 1.1 gmcgarry * documentation and/or other materials provided with the distribution. 49 1.2 agc * 3. Neither the name of the University nor the names of its contributors 50 1.2 agc * may be used to endorse or promote products derived from this software 51 1.2 agc * without specific prior written permission. 52 1.2 agc * 53 1.2 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 1.2 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 1.2 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 1.2 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 1.2 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 1.2 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 1.2 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.2 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.2 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.2 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.2 agc * SUCH DAMAGE. 64 1.2 agc * 65 1.2 agc * from: Utah $Hdr: rd.c 1.44 92/12/26$ 66 1.2 agc * 67 1.2 agc * @(#)rd.c 8.2 (Berkeley) 5/19/94 68 1.2 agc */ 69 1.2 agc 70 1.2 agc /* 71 1.1 gmcgarry * CS80/SS80 disk driver 72 1.1 gmcgarry */ 73 1.1 gmcgarry 74 1.1 gmcgarry #include <sys/cdefs.h> 75 1.45 andvar __KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.45 2023/02/12 16:04:57 andvar Exp $"); 76 1.1 gmcgarry 77 1.1 gmcgarry #include <sys/param.h> 78 1.1 gmcgarry #include <sys/systm.h> 79 1.1 gmcgarry #include <sys/buf.h> 80 1.4 yamt #include <sys/bufq.h> 81 1.1 gmcgarry #include <sys/callout.h> 82 1.1 gmcgarry #include <sys/conf.h> 83 1.1 gmcgarry #include <sys/device.h> 84 1.1 gmcgarry #include <sys/disk.h> 85 1.1 gmcgarry #include <sys/disklabel.h> 86 1.1 gmcgarry #include <sys/endian.h> 87 1.1 gmcgarry #include <sys/fcntl.h> 88 1.1 gmcgarry #include <sys/ioctl.h> 89 1.1 gmcgarry #include <sys/proc.h> 90 1.1 gmcgarry #include <sys/stat.h> 91 1.1 gmcgarry 92 1.40 riastrad #include <sys/rndsource.h> 93 1.1 gmcgarry 94 1.1 gmcgarry #include <dev/gpib/gpibvar.h> 95 1.1 gmcgarry #include <dev/gpib/cs80busvar.h> 96 1.1 gmcgarry 97 1.1 gmcgarry #include <dev/gpib/rdreg.h> 98 1.1 gmcgarry 99 1.42 riastrad #include "ioconf.h" 100 1.42 riastrad 101 1.1 gmcgarry #ifdef DEBUG 102 1.1 gmcgarry int rddebug = 0xff; 103 1.1 gmcgarry #define RDB_FOLLOW 0x01 104 1.1 gmcgarry #define RDB_STATUS 0x02 105 1.1 gmcgarry #define RDB_IDENT 0x04 106 1.1 gmcgarry #define RDB_IO 0x08 107 1.1 gmcgarry #define RDB_ASYNC 0x10 108 1.1 gmcgarry #define RDB_ERROR 0x80 109 1.1 gmcgarry #define DPRINTF(mask, str) if (rddebug & (mask)) printf str 110 1.1 gmcgarry #else 111 1.1 gmcgarry #define DPRINTF(mask, str) /* nothing */ 112 1.1 gmcgarry #endif 113 1.1 gmcgarry 114 1.1 gmcgarry struct rd_softc { 115 1.31 chs device_t sc_dev; 116 1.1 gmcgarry gpib_chipset_tag_t sc_ic; 117 1.1 gmcgarry gpib_handle_t sc_hdl; 118 1.1 gmcgarry 119 1.1 gmcgarry struct disk sc_dk; 120 1.1 gmcgarry 121 1.1 gmcgarry int sc_slave; /* GPIB slave */ 122 1.1 gmcgarry int sc_punit; /* physical unit on slave */ 123 1.1 gmcgarry 124 1.1 gmcgarry int sc_flags; 125 1.1 gmcgarry #define RDF_ALIVE 0x01 126 1.1 gmcgarry #define RDF_SEEK 0x02 127 1.1 gmcgarry #define RDF_SWAIT 0x04 128 1.1 gmcgarry #define RDF_OPENING 0x08 129 1.1 gmcgarry #define RDF_CLOSING 0x10 130 1.1 gmcgarry #define RDF_WANTED 0x20 131 1.1 gmcgarry #define RDF_WLABEL 0x40 132 1.1 gmcgarry 133 1.1 gmcgarry u_int16_t sc_type; 134 1.1 gmcgarry u_int8_t *sc_addr; 135 1.1 gmcgarry int sc_resid; 136 1.1 gmcgarry struct rd_iocmd sc_ioc; 137 1.6 yamt struct bufq_state *sc_tab; 138 1.1 gmcgarry int sc_active; 139 1.1 gmcgarry int sc_errcnt; 140 1.1 gmcgarry 141 1.1 gmcgarry struct callout sc_restart_ch; 142 1.1 gmcgarry 143 1.29 tls krndsource_t rnd_source; 144 1.1 gmcgarry }; 145 1.1 gmcgarry 146 1.1 gmcgarry #define RDUNIT(dev) DISKUNIT(dev) 147 1.1 gmcgarry #define RDPART(dev) DISKPART(dev) 148 1.1 gmcgarry #define RDMAKEDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 149 1.1 gmcgarry #define RDLABELDEV(dev) (RDMAKEDEV(major(dev), RDUNIT(dev), RAW_PART)) 150 1.1 gmcgarry 151 1.1 gmcgarry #define RDRETRY 5 152 1.1 gmcgarry #define RDWAITC 1 /* min time for timeout in seconds */ 153 1.1 gmcgarry 154 1.1 gmcgarry int rderrthresh = RDRETRY-1; /* when to start reporting errors */ 155 1.1 gmcgarry 156 1.1 gmcgarry /* 157 1.1 gmcgarry * Misc. HW description, indexed by sc_type. 158 1.1 gmcgarry * Used for mapping 256-byte sectors for 512-byte sectors 159 1.1 gmcgarry */ 160 1.1 gmcgarry const struct rdidentinfo { 161 1.1 gmcgarry u_int16_t ri_hwid; /* 2 byte HW id */ 162 1.1 gmcgarry u_int16_t ri_maxunum; /* maximum allowed unit number */ 163 1.14 cube const char *ri_desc; /* drive type description */ 164 1.1 gmcgarry int ri_nbpt; /* DEV_BSIZE blocks per track */ 165 1.1 gmcgarry int ri_ntpc; /* tracks per cylinder */ 166 1.1 gmcgarry int ri_ncyl; /* cylinders per unit */ 167 1.1 gmcgarry int ri_nblocks; /* DEV_BSIZE blocks on disk */ 168 1.1 gmcgarry } rdidentinfo[] = { 169 1.1 gmcgarry { RD7946AID, 0, "7945A", NRD7945ABPT, 170 1.1 gmcgarry NRD7945ATRK, 968, 108416 }, 171 1.1 gmcgarry 172 1.1 gmcgarry { RD9134DID, 1, "9134D", NRD9134DBPT, 173 1.1 gmcgarry NRD9134DTRK, 303, 29088 }, 174 1.1 gmcgarry 175 1.1 gmcgarry { RD9134LID, 1, "9122S", NRD9122SBPT, 176 1.1 gmcgarry NRD9122STRK, 77, 1232 }, 177 1.1 gmcgarry 178 1.1 gmcgarry { RD7912PID, 0, "7912P", NRD7912PBPT, 179 1.1 gmcgarry NRD7912PTRK, 572, 128128 }, 180 1.1 gmcgarry 181 1.1 gmcgarry { RD7914PID, 0, "7914P", NRD7914PBPT, 182 1.1 gmcgarry NRD7914PTRK, 1152, 258048 }, 183 1.1 gmcgarry 184 1.1 gmcgarry { RD7958AID, 0, "7958A", NRD7958ABPT, 185 1.1 gmcgarry NRD7958ATRK, 1013, 255276 }, 186 1.1 gmcgarry 187 1.1 gmcgarry { RD7957AID, 0, "7957A", NRD7957ABPT, 188 1.1 gmcgarry NRD7957ATRK, 1036, 159544 }, 189 1.1 gmcgarry 190 1.1 gmcgarry { RD7933HID, 0, "7933H", NRD7933HBPT, 191 1.1 gmcgarry NRD7933HTRK, 1321, 789958 }, 192 1.1 gmcgarry 193 1.1 gmcgarry { RD9134LID, 1, "9134L", NRD9134LBPT, 194 1.1 gmcgarry NRD9134LTRK, 973, 77840 }, 195 1.1 gmcgarry 196 1.1 gmcgarry { RD7936HID, 0, "7936H", NRD7936HBPT, 197 1.1 gmcgarry NRD7936HTRK, 698, 600978 }, 198 1.1 gmcgarry 199 1.1 gmcgarry { RD7937HID, 0, "7937H", NRD7937HBPT, 200 1.1 gmcgarry NRD7937HTRK, 698, 1116102 }, 201 1.1 gmcgarry 202 1.1 gmcgarry { RD7914CTID, 0, "7914CT", NRD7914PBPT, 203 1.1 gmcgarry NRD7914PTRK, 1152, 258048 }, 204 1.1 gmcgarry 205 1.1 gmcgarry { RD7946AID, 0, "7946A", NRD7945ABPT, 206 1.1 gmcgarry NRD7945ATRK, 968, 108416 }, 207 1.1 gmcgarry 208 1.1 gmcgarry { RD9134LID, 1, "9122D", NRD9122SBPT, 209 1.1 gmcgarry NRD9122STRK, 77, 1232 }, 210 1.1 gmcgarry 211 1.1 gmcgarry { RD7957BID, 0, "7957B", NRD7957BBPT, 212 1.1 gmcgarry NRD7957BTRK, 1269, 159894 }, 213 1.1 gmcgarry 214 1.1 gmcgarry { RD7958BID, 0, "7958B", NRD7958BBPT, 215 1.1 gmcgarry NRD7958BTRK, 786, 297108 }, 216 1.1 gmcgarry 217 1.1 gmcgarry { RD7959BID, 0, "7959B", NRD7959BBPT, 218 1.1 gmcgarry NRD7959BTRK, 1572, 594216 }, 219 1.1 gmcgarry 220 1.1 gmcgarry { RD2200AID, 0, "2200A", NRD2200ABPT, 221 1.1 gmcgarry NRD2200ATRK, 1449, 654948 }, 222 1.1 gmcgarry 223 1.1 gmcgarry { RD2203AID, 0, "2203A", NRD2203ABPT, 224 1.1 gmcgarry NRD2203ATRK, 1449, 1309896 } 225 1.1 gmcgarry }; 226 1.1 gmcgarry int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]); 227 1.1 gmcgarry 228 1.1 gmcgarry int rdlookup(int, int, int); 229 1.1 gmcgarry int rdgetinfo(struct rd_softc *); 230 1.1 gmcgarry void rdrestart(void *); 231 1.1 gmcgarry struct buf *rdfinish(struct rd_softc *, struct buf *); 232 1.1 gmcgarry 233 1.1 gmcgarry void rdgetcompatlabel(struct rd_softc *, struct disklabel *); 234 1.1 gmcgarry void rdgetdefaultlabel(struct rd_softc *, struct disklabel *); 235 1.1 gmcgarry void rdrestart(void *); 236 1.1 gmcgarry void rdustart(struct rd_softc *); 237 1.1 gmcgarry struct buf *rdfinish(struct rd_softc *, struct buf *); 238 1.1 gmcgarry void rdcallback(void *, int); 239 1.1 gmcgarry void rdstart(struct rd_softc *); 240 1.1 gmcgarry void rdintr(struct rd_softc *); 241 1.1 gmcgarry int rderror(struct rd_softc *); 242 1.1 gmcgarry 243 1.26 cegger int rdmatch(device_t, cfdata_t, void *); 244 1.26 cegger void rdattach(device_t, device_t, void *); 245 1.1 gmcgarry 246 1.31 chs CFATTACH_DECL_NEW(rd, sizeof(struct rd_softc), 247 1.1 gmcgarry rdmatch, rdattach, NULL, NULL); 248 1.1 gmcgarry 249 1.1 gmcgarry 250 1.1 gmcgarry dev_type_open(rdopen); 251 1.1 gmcgarry dev_type_close(rdclose); 252 1.1 gmcgarry dev_type_read(rdread); 253 1.1 gmcgarry dev_type_write(rdwrite); 254 1.1 gmcgarry dev_type_ioctl(rdioctl); 255 1.1 gmcgarry dev_type_strategy(rdstrategy); 256 1.1 gmcgarry dev_type_dump(rddump); 257 1.1 gmcgarry dev_type_size(rdsize); 258 1.1 gmcgarry 259 1.1 gmcgarry const struct bdevsw rd_bdevsw = { 260 1.32 dholland .d_open = rdopen, 261 1.32 dholland .d_close = rdclose, 262 1.32 dholland .d_strategy = rdstrategy, 263 1.32 dholland .d_ioctl = rdioctl, 264 1.32 dholland .d_dump = rddump, 265 1.32 dholland .d_psize = rdsize, 266 1.34 dholland .d_discard = nodiscard, 267 1.32 dholland .d_flag = D_DISK 268 1.1 gmcgarry }; 269 1.1 gmcgarry 270 1.1 gmcgarry const struct cdevsw rd_cdevsw = { 271 1.32 dholland .d_open = rdopen, 272 1.32 dholland .d_close = rdclose, 273 1.32 dholland .d_read = rdread, 274 1.32 dholland .d_write = rdwrite, 275 1.32 dholland .d_ioctl = rdioctl, 276 1.32 dholland .d_stop = nostop, 277 1.32 dholland .d_tty = notty, 278 1.32 dholland .d_poll = nopoll, 279 1.32 dholland .d_mmap = nommap, 280 1.32 dholland .d_kqfilter = nokqfilter, 281 1.35 dholland .d_discard = nodiscard, 282 1.32 dholland .d_flag = D_DISK 283 1.1 gmcgarry }; 284 1.1 gmcgarry 285 1.1 gmcgarry int 286 1.23 dsl rdlookup(int id, int slave, int punit) 287 1.1 gmcgarry { 288 1.1 gmcgarry int i; 289 1.1 gmcgarry 290 1.1 gmcgarry for (i = 0; i < numrdidentinfo; i++) { 291 1.1 gmcgarry if (rdidentinfo[i].ri_hwid == id) 292 1.1 gmcgarry break; 293 1.1 gmcgarry } 294 1.1 gmcgarry if (i == numrdidentinfo || punit > rdidentinfo[i].ri_maxunum) 295 1.1 gmcgarry return (-1); 296 1.1 gmcgarry return (i); 297 1.1 gmcgarry } 298 1.1 gmcgarry 299 1.1 gmcgarry int 300 1.26 cegger rdmatch(device_t parent, cfdata_t match, void *aux) 301 1.1 gmcgarry { 302 1.1 gmcgarry struct cs80bus_attach_args *ca = aux; 303 1.1 gmcgarry 304 1.1 gmcgarry if (rdlookup(ca->ca_id, ca->ca_slave, ca->ca_punit) < 0) 305 1.1 gmcgarry return (0); 306 1.1 gmcgarry return (1); 307 1.1 gmcgarry } 308 1.1 gmcgarry 309 1.1 gmcgarry void 310 1.26 cegger rdattach(device_t parent, device_t self, void *aux) 311 1.1 gmcgarry { 312 1.11 thorpej struct rd_softc *sc = device_private(self); 313 1.1 gmcgarry struct cs80bus_attach_args *ca = aux; 314 1.1 gmcgarry struct cs80_description csd; 315 1.1 gmcgarry char name[7]; 316 1.1 gmcgarry int type, i, n; 317 1.1 gmcgarry 318 1.31 chs sc->sc_dev = self; 319 1.1 gmcgarry sc->sc_ic = ca->ca_ic; 320 1.1 gmcgarry sc->sc_slave = ca->ca_slave; 321 1.1 gmcgarry sc->sc_punit = ca->ca_punit; 322 1.1 gmcgarry 323 1.1 gmcgarry if ((type = rdlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0) 324 1.1 gmcgarry return; 325 1.1 gmcgarry 326 1.1 gmcgarry if (cs80reset(parent, sc->sc_slave, sc->sc_punit)) { 327 1.19 cegger aprint_normal("\n"); 328 1.31 chs aprint_error_dev(sc->sc_dev, "can't reset device\n"); 329 1.1 gmcgarry return; 330 1.1 gmcgarry } 331 1.1 gmcgarry 332 1.1 gmcgarry if (cs80describe(parent, sc->sc_slave, sc->sc_punit, &csd)) { 333 1.19 cegger aprint_normal("\n"); 334 1.41 msaitoh aprint_error_dev(sc->sc_dev, 335 1.41 msaitoh "didn't respond to describe command\n"); 336 1.1 gmcgarry return; 337 1.1 gmcgarry } 338 1.5 perry memset(name, 0, sizeof(name)); 339 1.1 gmcgarry for (i=0, n=0; i<3; i++) { 340 1.1 gmcgarry name[n++] = (csd.d_name[i] >> 4) + '0'; 341 1.1 gmcgarry name[n++] = (csd.d_name[i] & 0x0f) + '0'; 342 1.1 gmcgarry } 343 1.1 gmcgarry 344 1.1 gmcgarry #ifdef DEBUG 345 1.1 gmcgarry if (rddebug & RDB_IDENT) { 346 1.1 gmcgarry printf("\n%s: name: ('%s')\n", 347 1.31 chs device_xname(sc->sc_dev), name); 348 1.1 gmcgarry printf(" iuw %x, maxxfr %d, ctype %d\n", 349 1.1 gmcgarry csd.d_iuw, csd.d_cmaxxfr, csd.d_ctype); 350 1.1 gmcgarry printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n", 351 1.1 gmcgarry csd.d_utype, csd.d_sectsize, 352 1.1 gmcgarry csd.d_blkbuf, csd.d_burstsize, csd.d_blocktime); 353 1.1 gmcgarry printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n", 354 1.1 gmcgarry csd.d_uavexfr, csd.d_retry, csd.d_access, 355 1.1 gmcgarry csd.d_maxint, csd.d_fvbyte, csd.d_rvbyte); 356 1.1 gmcgarry printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n", 357 1.1 gmcgarry csd.d_maxcylhead >> 8, csd.d_maxcylhead & 0xff, 358 1.1 gmcgarry csd.d_maxsect, csd.d_maxvsectl, csd.d_interleave); 359 1.31 chs printf("%s", device_xname(sc->sc_dev)); 360 1.1 gmcgarry } 361 1.1 gmcgarry #endif 362 1.1 gmcgarry 363 1.1 gmcgarry /* 364 1.45 andvar * Take care of a couple of anomalies: 365 1.1 gmcgarry * 1. 7945A and 7946A both return same HW id 366 1.1 gmcgarry * 2. 9122S and 9134D both return same HW id 367 1.1 gmcgarry * 3. 9122D and 9134L both return same HW id 368 1.1 gmcgarry */ 369 1.1 gmcgarry switch (ca->ca_id) { 370 1.1 gmcgarry case RD7946AID: 371 1.1 gmcgarry if (memcmp(name, "079450", 6) == 0) 372 1.1 gmcgarry type = RD7945A; 373 1.1 gmcgarry else 374 1.1 gmcgarry type = RD7946A; 375 1.1 gmcgarry break; 376 1.1 gmcgarry 377 1.1 gmcgarry case RD9134LID: 378 1.1 gmcgarry if (memcmp(name, "091340", 6) == 0) 379 1.1 gmcgarry type = RD9134L; 380 1.1 gmcgarry else 381 1.1 gmcgarry type = RD9122D; 382 1.1 gmcgarry break; 383 1.1 gmcgarry 384 1.1 gmcgarry case RD9134DID: 385 1.1 gmcgarry if (memcmp(name, "091220", 6) == 0) 386 1.1 gmcgarry type = RD9122S; 387 1.1 gmcgarry else 388 1.1 gmcgarry type = RD9134D; 389 1.1 gmcgarry break; 390 1.1 gmcgarry } 391 1.1 gmcgarry 392 1.1 gmcgarry sc->sc_type = type; 393 1.1 gmcgarry 394 1.1 gmcgarry /* 395 1.1 gmcgarry * XXX We use DEV_BSIZE instead of the sector size value pulled 396 1.1 gmcgarry * XXX off the driver because all of this code assumes 512 byte 397 1.1 gmcgarry * XXX blocks. ICK! 398 1.1 gmcgarry */ 399 1.1 gmcgarry printf(": %s\n", rdidentinfo[type].ri_desc); 400 1.1 gmcgarry printf("%s: %d cylinders, %d heads, %d blocks, %d bytes/block\n", 401 1.31 chs device_xname(sc->sc_dev), rdidentinfo[type].ri_ncyl, 402 1.1 gmcgarry rdidentinfo[type].ri_ntpc, rdidentinfo[type].ri_nblocks, 403 1.1 gmcgarry DEV_BSIZE); 404 1.1 gmcgarry 405 1.6 yamt bufq_alloc(&sc->sc_tab, "fcfs", 0); 406 1.1 gmcgarry 407 1.1 gmcgarry /* 408 1.1 gmcgarry * Initialize and attach the disk structure. 409 1.1 gmcgarry */ 410 1.1 gmcgarry memset(&sc->sc_dk, 0, sizeof(sc->sc_dk)); 411 1.31 chs disk_init(&sc->sc_dk, device_xname(sc->sc_dev), NULL); 412 1.1 gmcgarry disk_attach(&sc->sc_dk); 413 1.1 gmcgarry 414 1.16 ad callout_init(&sc->sc_restart_ch, 0); 415 1.1 gmcgarry 416 1.1 gmcgarry if (gpibregister(sc->sc_ic, sc->sc_slave, rdcallback, sc, 417 1.1 gmcgarry &sc->sc_hdl)) { 418 1.31 chs aprint_error_dev(sc->sc_dev, "can't register callback\n"); 419 1.1 gmcgarry return; 420 1.1 gmcgarry } 421 1.1 gmcgarry 422 1.1 gmcgarry sc->sc_flags = RDF_ALIVE; 423 1.1 gmcgarry #ifdef DEBUG 424 1.1 gmcgarry /* always report errors */ 425 1.1 gmcgarry if (rddebug & RDB_ERROR) 426 1.1 gmcgarry rderrthresh = 0; 427 1.1 gmcgarry #endif 428 1.1 gmcgarry /* 429 1.1 gmcgarry * attach the device into the random source list 430 1.1 gmcgarry */ 431 1.31 chs rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 432 1.36 tls RND_TYPE_DISK, RND_FLAG_DEFAULT); 433 1.1 gmcgarry } 434 1.1 gmcgarry 435 1.1 gmcgarry /* 436 1.8 wiz * Read or construct a disklabel 437 1.1 gmcgarry */ 438 1.1 gmcgarry int 439 1.23 dsl rdgetinfo(struct rd_softc *sc) 440 1.1 gmcgarry { 441 1.1 gmcgarry struct disklabel *lp = sc->sc_dk.dk_label; 442 1.1 gmcgarry struct partition *pi; 443 1.1 gmcgarry const char *msg; 444 1.1 gmcgarry 445 1.1 gmcgarry memset(sc->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); 446 1.1 gmcgarry 447 1.1 gmcgarry rdgetdefaultlabel(sc, lp); 448 1.1 gmcgarry 449 1.1 gmcgarry /* 450 1.1 gmcgarry * Call the generic disklabel extraction routine 451 1.1 gmcgarry */ 452 1.31 chs msg = readdisklabel(RDMAKEDEV(0, device_unit(sc->sc_dev), RAW_PART), 453 1.1 gmcgarry rdstrategy, lp, NULL); 454 1.1 gmcgarry if (msg == NULL) 455 1.1 gmcgarry return (0); 456 1.1 gmcgarry 457 1.1 gmcgarry pi = lp->d_partitions; 458 1.31 chs printf("%s: WARNING: %s\n", device_xname(sc->sc_dev), msg); 459 1.3 thorpej 460 1.1 gmcgarry pi[RAW_PART].p_size = rdidentinfo[sc->sc_type].ri_nblocks; 461 1.1 gmcgarry lp->d_npartitions = RAW_PART+1; 462 1.1 gmcgarry pi[0].p_size = 0; 463 1.3 thorpej 464 1.1 gmcgarry return (0); 465 1.1 gmcgarry } 466 1.1 gmcgarry 467 1.1 gmcgarry int 468 1.21 cegger rdopen(dev_t dev, int flags, int mode, struct lwp *l) 469 1.1 gmcgarry { 470 1.1 gmcgarry struct rd_softc *sc; 471 1.1 gmcgarry int error, mask, part; 472 1.1 gmcgarry 473 1.21 cegger sc = device_lookup_private(&rd_cd, RDUNIT(dev)); 474 1.1 gmcgarry if (sc == NULL || (sc->sc_flags & RDF_ALIVE) ==0) 475 1.1 gmcgarry return (ENXIO); 476 1.1 gmcgarry 477 1.1 gmcgarry /* 478 1.1 gmcgarry * Wait for any pending opens/closes to complete 479 1.1 gmcgarry */ 480 1.1 gmcgarry while (sc->sc_flags & (RDF_OPENING | RDF_CLOSING)) 481 1.1 gmcgarry (void) tsleep(sc, PRIBIO, "rdopen", 0); 482 1.1 gmcgarry 483 1.1 gmcgarry /* 484 1.1 gmcgarry * On first open, get label and partition info. 485 1.1 gmcgarry * We may block reading the label, so be careful 486 1.1 gmcgarry * to stop any other opens. 487 1.1 gmcgarry */ 488 1.1 gmcgarry if (sc->sc_dk.dk_openmask == 0) { 489 1.1 gmcgarry sc->sc_flags |= RDF_OPENING; 490 1.1 gmcgarry error = rdgetinfo(sc); 491 1.1 gmcgarry sc->sc_flags &= ~RDF_OPENING; 492 1.15 christos wakeup((void *)sc); 493 1.1 gmcgarry if (error) 494 1.1 gmcgarry return (error); 495 1.1 gmcgarry } 496 1.1 gmcgarry 497 1.1 gmcgarry part = RDPART(dev); 498 1.1 gmcgarry mask = 1 << part; 499 1.1 gmcgarry 500 1.1 gmcgarry /* Check that the partition exists. */ 501 1.1 gmcgarry if (part != RAW_PART && (part > sc->sc_dk.dk_label->d_npartitions || 502 1.1 gmcgarry sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) 503 1.1 gmcgarry return (ENXIO); 504 1.1 gmcgarry 505 1.1 gmcgarry /* Ensure only one open at a time. */ 506 1.1 gmcgarry switch (mode) { 507 1.1 gmcgarry case S_IFCHR: 508 1.1 gmcgarry sc->sc_dk.dk_copenmask |= mask; 509 1.1 gmcgarry break; 510 1.1 gmcgarry case S_IFBLK: 511 1.1 gmcgarry sc->sc_dk.dk_bopenmask |= mask; 512 1.1 gmcgarry break; 513 1.1 gmcgarry } 514 1.1 gmcgarry sc->sc_dk.dk_openmask = 515 1.1 gmcgarry sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; 516 1.1 gmcgarry 517 1.1 gmcgarry return (0); 518 1.1 gmcgarry } 519 1.1 gmcgarry 520 1.1 gmcgarry int 521 1.21 cegger rdclose(dev_t dev, int flag, int mode, struct lwp *l) 522 1.1 gmcgarry { 523 1.1 gmcgarry struct rd_softc *sc; 524 1.1 gmcgarry struct disk *dk; 525 1.1 gmcgarry int mask, s; 526 1.1 gmcgarry 527 1.21 cegger sc = device_lookup_private(&rd_cd, RDUNIT(dev)); 528 1.1 gmcgarry if (sc == NULL) 529 1.1 gmcgarry return (ENXIO); 530 1.1 gmcgarry 531 1.1 gmcgarry dk = &sc->sc_dk; 532 1.1 gmcgarry 533 1.1 gmcgarry mask = 1 << RDPART(dev); 534 1.1 gmcgarry if (mode == S_IFCHR) 535 1.1 gmcgarry dk->dk_copenmask &= ~mask; 536 1.1 gmcgarry else 537 1.1 gmcgarry dk->dk_bopenmask &= ~mask; 538 1.1 gmcgarry dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; 539 1.1 gmcgarry /* 540 1.1 gmcgarry * On last close, we wait for all activity to cease since 541 1.43 msaitoh * the label/partition info will become invalid. Since we 542 1.1 gmcgarry * might sleep, we must block any opens while we are here. 543 1.1 gmcgarry * Note we don't have to about other closes since we know 544 1.1 gmcgarry * we are the last one. 545 1.1 gmcgarry */ 546 1.1 gmcgarry if (dk->dk_openmask == 0) { 547 1.1 gmcgarry sc->sc_flags |= RDF_CLOSING; 548 1.1 gmcgarry s = splbio(); 549 1.1 gmcgarry while (sc->sc_active) { 550 1.1 gmcgarry sc->sc_flags |= RDF_WANTED; 551 1.1 gmcgarry (void) tsleep(&sc->sc_tab, PRIBIO, "rdclose", 0); 552 1.1 gmcgarry } 553 1.1 gmcgarry splx(s); 554 1.1 gmcgarry sc->sc_flags &= ~(RDF_CLOSING | RDF_WLABEL); 555 1.15 christos wakeup((void *)sc); 556 1.1 gmcgarry } 557 1.1 gmcgarry return (0); 558 1.1 gmcgarry } 559 1.1 gmcgarry 560 1.1 gmcgarry void 561 1.21 cegger rdstrategy(struct buf *bp) 562 1.1 gmcgarry { 563 1.1 gmcgarry struct rd_softc *sc; 564 1.1 gmcgarry struct partition *pinfo; 565 1.1 gmcgarry daddr_t bn; 566 1.1 gmcgarry int sz, s; 567 1.1 gmcgarry int offset; 568 1.1 gmcgarry 569 1.21 cegger sc = device_lookup_private(&rd_cd, RDUNIT(bp->b_dev)); 570 1.1 gmcgarry 571 1.1 gmcgarry DPRINTF(RDB_FOLLOW, 572 1.27 tsutsui ("rdstrategy(%p): dev %" PRIx64 ", bn %" PRId64 ", bcount %d, %c\n", 573 1.1 gmcgarry bp, bp->b_dev, bp->b_blkno, bp->b_bcount, 574 1.1 gmcgarry (bp->b_flags & B_READ) ? 'R' : 'W')); 575 1.1 gmcgarry 576 1.1 gmcgarry bn = bp->b_blkno; 577 1.1 gmcgarry sz = howmany(bp->b_bcount, DEV_BSIZE); 578 1.1 gmcgarry pinfo = &sc->sc_dk.dk_label->d_partitions[RDPART(bp->b_dev)]; 579 1.1 gmcgarry 580 1.1 gmcgarry /* Don't perform partition translation on RAW_PART. */ 581 1.1 gmcgarry offset = (RDPART(bp->b_dev) == RAW_PART) ? 0 : pinfo->p_offset; 582 1.1 gmcgarry 583 1.1 gmcgarry if (RDPART(bp->b_dev) != RAW_PART) { 584 1.1 gmcgarry /* 585 1.1 gmcgarry * XXX This block of code belongs in 586 1.1 gmcgarry * XXX bounds_check_with_label() 587 1.1 gmcgarry */ 588 1.1 gmcgarry 589 1.1 gmcgarry if (bn < 0 || bn + sz > pinfo->p_size) { 590 1.1 gmcgarry sz = pinfo->p_size - bn; 591 1.1 gmcgarry if (sz == 0) { 592 1.1 gmcgarry bp->b_resid = bp->b_bcount; 593 1.1 gmcgarry goto done; 594 1.1 gmcgarry } 595 1.1 gmcgarry if (sz < 0) { 596 1.1 gmcgarry bp->b_error = EINVAL; 597 1.17 ad goto done; 598 1.1 gmcgarry } 599 1.1 gmcgarry bp->b_bcount = dbtob(sz); 600 1.1 gmcgarry } 601 1.1 gmcgarry /* 602 1.1 gmcgarry * Check for write to write protected label 603 1.1 gmcgarry */ 604 1.1 gmcgarry if (bn + offset <= LABELSECTOR && 605 1.1 gmcgarry #if LABELSECTOR != 0 606 1.1 gmcgarry bn + offset + sz > LABELSECTOR && 607 1.1 gmcgarry #endif 608 1.1 gmcgarry !(bp->b_flags & B_READ) && !(sc->sc_flags & RDF_WLABEL)) { 609 1.1 gmcgarry bp->b_error = EROFS; 610 1.17 ad goto done; 611 1.1 gmcgarry } 612 1.1 gmcgarry } 613 1.1 gmcgarry bp->b_rawblkno = bn + offset; 614 1.1 gmcgarry s = splbio(); 615 1.22 yamt bufq_put(sc->sc_tab, bp); 616 1.1 gmcgarry if (sc->sc_active == 0) { 617 1.1 gmcgarry sc->sc_active = 1; 618 1.1 gmcgarry rdustart(sc); 619 1.1 gmcgarry } 620 1.1 gmcgarry splx(s); 621 1.1 gmcgarry return; 622 1.1 gmcgarry done: 623 1.1 gmcgarry biodone(bp); 624 1.1 gmcgarry } 625 1.1 gmcgarry 626 1.1 gmcgarry /* 627 1.1 gmcgarry * Called from timeout() when handling maintenance releases 628 1.1 gmcgarry * callout from timeouts 629 1.1 gmcgarry */ 630 1.1 gmcgarry void 631 1.23 dsl rdrestart(void *arg) 632 1.1 gmcgarry { 633 1.1 gmcgarry int s = splbio(); 634 1.1 gmcgarry rdustart((struct rd_softc *)arg); 635 1.1 gmcgarry splx(s); 636 1.1 gmcgarry } 637 1.1 gmcgarry 638 1.1 gmcgarry 639 1.1 gmcgarry /* called by rdstrategy() to start a block transfer */ 640 1.1 gmcgarry /* called by rdrestart() when handingly timeouts */ 641 1.1 gmcgarry /* called by rdintr() */ 642 1.1 gmcgarry void 643 1.23 dsl rdustart(struct rd_softc *sc) 644 1.1 gmcgarry { 645 1.1 gmcgarry struct buf *bp; 646 1.1 gmcgarry 647 1.22 yamt bp = bufq_peek(sc->sc_tab); 648 1.1 gmcgarry sc->sc_addr = bp->b_data; 649 1.1 gmcgarry sc->sc_resid = bp->b_bcount; 650 1.1 gmcgarry if (gpibrequest(sc->sc_ic, sc->sc_hdl)) 651 1.1 gmcgarry rdstart(sc); 652 1.1 gmcgarry } 653 1.1 gmcgarry 654 1.1 gmcgarry struct buf * 655 1.23 dsl rdfinish(struct rd_softc *sc, struct buf *bp) 656 1.1 gmcgarry { 657 1.1 gmcgarry 658 1.1 gmcgarry sc->sc_errcnt = 0; 659 1.22 yamt (void)bufq_get(sc->sc_tab); 660 1.1 gmcgarry bp->b_resid = 0; 661 1.1 gmcgarry biodone(bp); 662 1.1 gmcgarry gpibrelease(sc->sc_ic, sc->sc_hdl); 663 1.22 yamt if ((bp = bufq_peek(sc->sc_tab)) != NULL) 664 1.1 gmcgarry return (bp); 665 1.1 gmcgarry sc->sc_active = 0; 666 1.1 gmcgarry if (sc->sc_flags & RDF_WANTED) { 667 1.1 gmcgarry sc->sc_flags &= ~RDF_WANTED; 668 1.15 christos wakeup((void *)&sc->sc_tab); 669 1.1 gmcgarry } 670 1.1 gmcgarry return (NULL); 671 1.1 gmcgarry } 672 1.1 gmcgarry 673 1.1 gmcgarry void 674 1.23 dsl rdcallback(void *v, int action) 675 1.1 gmcgarry { 676 1.1 gmcgarry struct rd_softc *sc = v; 677 1.1 gmcgarry 678 1.1 gmcgarry DPRINTF(RDB_FOLLOW, ("rdcallback: v=%p, action=%d\n", v, action)); 679 1.1 gmcgarry 680 1.1 gmcgarry switch (action) { 681 1.1 gmcgarry case GPIBCBF_START: 682 1.1 gmcgarry rdstart(sc); 683 1.1 gmcgarry break; 684 1.1 gmcgarry case GPIBCBF_INTR: 685 1.1 gmcgarry rdintr(sc); 686 1.1 gmcgarry break; 687 1.1 gmcgarry #ifdef DEBUG 688 1.1 gmcgarry default: 689 1.1 gmcgarry DPRINTF(RDB_ERROR, ("rdcallback: unknown action %d\n", 690 1.1 gmcgarry action)); 691 1.1 gmcgarry break; 692 1.1 gmcgarry #endif 693 1.1 gmcgarry } 694 1.1 gmcgarry } 695 1.1 gmcgarry 696 1.1 gmcgarry 697 1.1 gmcgarry /* called from rdustart() to start a transfer */ 698 1.1 gmcgarry /* called from gpib interface as the initiator */ 699 1.1 gmcgarry void 700 1.23 dsl rdstart(struct rd_softc *sc) 701 1.1 gmcgarry { 702 1.22 yamt struct buf *bp = bufq_peek(sc->sc_tab); 703 1.33 christos int slave, punit; 704 1.1 gmcgarry 705 1.1 gmcgarry slave = sc->sc_slave; 706 1.1 gmcgarry punit = sc->sc_punit; 707 1.1 gmcgarry 708 1.1 gmcgarry DPRINTF(RDB_FOLLOW, ("rdstart(%s): bp %p, %c\n", 709 1.31 chs device_xname(sc->sc_dev), bp, (bp->b_flags & B_READ) ? 'R' : 'W')); 710 1.1 gmcgarry 711 1.1 gmcgarry again: 712 1.1 gmcgarry 713 1.1 gmcgarry sc->sc_flags |= RDF_SEEK; 714 1.1 gmcgarry sc->sc_ioc.c_unit = CS80CMD_SUNIT(punit); 715 1.1 gmcgarry sc->sc_ioc.c_volume = CS80CMD_SVOL(0); 716 1.1 gmcgarry sc->sc_ioc.c_saddr = CS80CMD_SADDR; 717 1.1 gmcgarry sc->sc_ioc.c_hiaddr = htobe16(0); 718 1.1 gmcgarry sc->sc_ioc.c_addr = htobe32(RDBTOS(bp->b_rawblkno)); 719 1.1 gmcgarry sc->sc_ioc.c_nop2 = CS80CMD_NOP; 720 1.1 gmcgarry sc->sc_ioc.c_slen = CS80CMD_SLEN; 721 1.1 gmcgarry sc->sc_ioc.c_len = htobe32(sc->sc_resid); 722 1.1 gmcgarry sc->sc_ioc.c_cmd = bp->b_flags & B_READ ? CS80CMD_READ : CS80CMD_WRITE; 723 1.1 gmcgarry 724 1.1 gmcgarry if (gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_ioc.c_unit, 725 1.1 gmcgarry sizeof(sc->sc_ioc)-1) == sizeof(sc->sc_ioc)-1) { 726 1.1 gmcgarry /* Instrumentation. */ 727 1.1 gmcgarry disk_busy(&sc->sc_dk); 728 1.12 blymn iostat_seek(sc->sc_dk.dk_stats); 729 1.1 gmcgarry gpibawait(sc->sc_ic); 730 1.1 gmcgarry return; 731 1.1 gmcgarry } 732 1.1 gmcgarry /* 733 1.1 gmcgarry * Experience has shown that the gpibwait in this gpibsend will 734 1.1 gmcgarry * occasionally timeout. It appears to occur mostly on old 7914 735 1.1 gmcgarry * drives with full maintenance tracks. We should probably 736 1.1 gmcgarry * integrate this with the backoff code in rderror. 737 1.1 gmcgarry */ 738 1.1 gmcgarry 739 1.1 gmcgarry DPRINTF(RDB_ERROR, 740 1.1 gmcgarry ("rdstart: cmd %x adr %ul blk %" PRId64 " len %d ecnt %d\n", 741 1.1 gmcgarry sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, bp->b_blkno, sc->sc_resid, 742 1.1 gmcgarry sc->sc_errcnt)); 743 1.1 gmcgarry 744 1.1 gmcgarry sc->sc_flags &= ~RDF_SEEK; 745 1.31 chs cs80reset(device_parent(sc->sc_dev), slave, punit); 746 1.1 gmcgarry if (sc->sc_errcnt++ < RDRETRY) 747 1.1 gmcgarry goto again; 748 1.1 gmcgarry printf("%s: rdstart err: cmd 0x%x sect %uld blk %" PRId64 " len %d\n", 749 1.31 chs device_xname(sc->sc_dev), sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, 750 1.1 gmcgarry bp->b_blkno, sc->sc_resid); 751 1.1 gmcgarry bp->b_error = EIO; 752 1.1 gmcgarry bp = rdfinish(sc, bp); 753 1.1 gmcgarry if (bp) { 754 1.1 gmcgarry sc->sc_addr = bp->b_data; 755 1.1 gmcgarry sc->sc_resid = bp->b_bcount; 756 1.1 gmcgarry if (gpibrequest(sc->sc_ic, sc->sc_hdl)) 757 1.1 gmcgarry goto again; 758 1.1 gmcgarry } 759 1.1 gmcgarry } 760 1.1 gmcgarry 761 1.1 gmcgarry void 762 1.23 dsl rdintr(struct rd_softc *sc) 763 1.1 gmcgarry { 764 1.1 gmcgarry struct buf *bp; 765 1.1 gmcgarry u_int8_t stat = 13; /* in case gpibrecv fails */ 766 1.1 gmcgarry int rv, dir, restart, slave; 767 1.1 gmcgarry 768 1.1 gmcgarry slave = sc->sc_slave; 769 1.22 yamt bp = bufq_peek(sc->sc_tab); 770 1.1 gmcgarry 771 1.1 gmcgarry DPRINTF(RDB_FOLLOW, ("rdintr(%s): bp %p, %c, flags %x\n", 772 1.31 chs device_xname(sc->sc_dev), bp, (bp->b_flags & B_READ) ? 'R' : 'W', 773 1.1 gmcgarry sc->sc_flags)); 774 1.1 gmcgarry 775 1.1 gmcgarry disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid), 776 1.1 gmcgarry (bp->b_flags & B_READ)); 777 1.1 gmcgarry 778 1.1 gmcgarry if (sc->sc_flags & RDF_SEEK) { 779 1.1 gmcgarry sc->sc_flags &= ~RDF_SEEK; 780 1.1 gmcgarry dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE); 781 1.1 gmcgarry gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr, 782 1.1 gmcgarry sc->sc_resid, dir, dir == GPIB_READ); 783 1.1 gmcgarry disk_busy(&sc->sc_dk); 784 1.1 gmcgarry return; 785 1.1 gmcgarry } 786 1.1 gmcgarry if ((sc->sc_flags & RDF_SWAIT) == 0) { 787 1.1 gmcgarry if (gpibpptest(sc->sc_ic, slave) == 0) { 788 1.1 gmcgarry /* Instrumentation. */ 789 1.1 gmcgarry disk_busy(&sc->sc_dk); 790 1.1 gmcgarry sc->sc_flags |= RDF_SWAIT; 791 1.1 gmcgarry gpibawait(sc->sc_ic); 792 1.1 gmcgarry return; 793 1.1 gmcgarry } 794 1.1 gmcgarry } else 795 1.1 gmcgarry sc->sc_flags &= ~RDF_SWAIT; 796 1.1 gmcgarry rv = gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 797 1.1 gmcgarry if (rv != 1 || stat) { 798 1.1 gmcgarry DPRINTF(RDB_ERROR, 799 1.1 gmcgarry ("rdintr: receive failed (rv=%d) or bad stat %d\n", rv, 800 1.1 gmcgarry stat)); 801 1.1 gmcgarry restart = rderror(sc); 802 1.1 gmcgarry if (sc->sc_errcnt++ < RDRETRY) { 803 1.1 gmcgarry if (restart) 804 1.1 gmcgarry rdstart(sc); 805 1.1 gmcgarry return; 806 1.1 gmcgarry } 807 1.1 gmcgarry bp->b_error = EIO; 808 1.1 gmcgarry } 809 1.1 gmcgarry if (rdfinish(sc, bp) != NULL) 810 1.1 gmcgarry rdustart(sc); 811 1.1 gmcgarry rnd_add_uint32(&sc->rnd_source, bp->b_blkno); 812 1.1 gmcgarry } 813 1.1 gmcgarry 814 1.1 gmcgarry /* 815 1.1 gmcgarry * Deal with errors. 816 1.1 gmcgarry * Returns 1 if request should be restarted, 817 1.1 gmcgarry * 0 if we should just quietly give up. 818 1.1 gmcgarry */ 819 1.1 gmcgarry int 820 1.23 dsl rderror(struct rd_softc *sc) 821 1.1 gmcgarry { 822 1.1 gmcgarry struct cs80_stat css; 823 1.1 gmcgarry struct buf *bp; 824 1.1 gmcgarry daddr_t hwbn, pbn; 825 1.1 gmcgarry 826 1.1 gmcgarry DPRINTF(RDB_FOLLOW, ("rderror: sc=%p\n", sc)); 827 1.1 gmcgarry 828 1.31 chs if (cs80status(device_parent(sc->sc_dev), sc->sc_slave, 829 1.1 gmcgarry sc->sc_punit, &css)) { 830 1.31 chs cs80reset(device_parent(sc->sc_dev), sc->sc_slave, 831 1.9 thorpej sc->sc_punit); 832 1.1 gmcgarry return (1); 833 1.1 gmcgarry } 834 1.1 gmcgarry #ifdef DEBUG 835 1.1 gmcgarry if (rddebug & RDB_ERROR) { /* status info */ 836 1.1 gmcgarry printf("\n volume: %d, unit: %d\n", 837 1.1 gmcgarry (css.c_vu>>4)&0xF, css.c_vu&0xF); 838 1.1 gmcgarry printf(" reject 0x%x\n", css.c_ref); 839 1.1 gmcgarry printf(" fault 0x%x\n", css.c_fef); 840 1.1 gmcgarry printf(" access 0x%x\n", css.c_aef); 841 1.1 gmcgarry printf(" info 0x%x\n", css.c_ief); 842 1.1 gmcgarry printf(" block, P1-P10: "); 843 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&css.c_raw[0]); 844 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&css.c_raw[4]); 845 1.1 gmcgarry printf("0x%x\n", *(u_int16_t *)&css.c_raw[8]); 846 1.1 gmcgarry } 847 1.1 gmcgarry #endif 848 1.1 gmcgarry if (css.c_fef & FEF_REXMT) 849 1.1 gmcgarry return (1); 850 1.1 gmcgarry if (css.c_fef & FEF_PF) { 851 1.31 chs cs80reset(device_parent(sc->sc_dev), sc->sc_slave, 852 1.9 thorpej sc->sc_punit); 853 1.1 gmcgarry return (1); 854 1.1 gmcgarry } 855 1.1 gmcgarry /* 856 1.1 gmcgarry * Unit requests release for internal maintenance. 857 1.45 andvar * We just delay awhile and try again later. Use exponentially 858 1.1 gmcgarry * increasing backoff ala ethernet drivers since we don't really 859 1.1 gmcgarry * know how long the maintenance will take. With RDWAITC and 860 1.1 gmcgarry * RDRETRY as defined, the range is 1 to 32 seconds. 861 1.1 gmcgarry */ 862 1.1 gmcgarry if (css.c_fef & FEF_IMR) { 863 1.1 gmcgarry extern int hz; 864 1.1 gmcgarry int rdtimo = RDWAITC << sc->sc_errcnt; 865 1.1 gmcgarry DPRINTF(RDB_STATUS, 866 1.1 gmcgarry ("%s: internal maintenance, %d-second timeout\n", 867 1.31 chs device_xname(sc->sc_dev), rdtimo)); 868 1.1 gmcgarry gpibrelease(sc->sc_ic, sc->sc_hdl); 869 1.1 gmcgarry callout_reset(&sc->sc_restart_ch, rdtimo * hz, rdrestart, sc); 870 1.1 gmcgarry return (0); 871 1.1 gmcgarry } 872 1.1 gmcgarry /* 873 1.1 gmcgarry * Only report error if we have reached the error reporting 874 1.44 andvar * threshold. By default, this will only report after the 875 1.1 gmcgarry * retry limit has been exceeded. 876 1.1 gmcgarry */ 877 1.1 gmcgarry if (sc->sc_errcnt < rderrthresh) 878 1.1 gmcgarry return (1); 879 1.1 gmcgarry 880 1.1 gmcgarry /* 881 1.1 gmcgarry * First conjure up the block number at which the error occurred. 882 1.1 gmcgarry */ 883 1.22 yamt bp = bufq_peek(sc->sc_tab); 884 1.1 gmcgarry pbn = sc->sc_dk.dk_label->d_partitions[RDPART(bp->b_dev)].p_offset; 885 1.1 gmcgarry if ((css.c_fef & FEF_CU) || (css.c_fef & FEF_DR) || 886 1.1 gmcgarry (css.c_ief & IEF_RRMASK)) { 887 1.1 gmcgarry /* 888 1.1 gmcgarry * Not all errors report a block number, just use b_blkno. 889 1.1 gmcgarry */ 890 1.1 gmcgarry hwbn = RDBTOS(pbn + bp->b_blkno); 891 1.1 gmcgarry pbn = bp->b_blkno; 892 1.1 gmcgarry } else { 893 1.1 gmcgarry hwbn = css.c_blk; 894 1.1 gmcgarry pbn = RDSTOB(hwbn) - pbn; 895 1.1 gmcgarry } 896 1.1 gmcgarry #ifdef DEBUG 897 1.1 gmcgarry if (rddebug & RDB_ERROR) { /* status info */ 898 1.1 gmcgarry printf("\n volume: %d, unit: %d\n", 899 1.1 gmcgarry (css.c_vu>>4)&0xF, css.c_vu&0xF); 900 1.1 gmcgarry printf(" reject 0x%x\n", css.c_ref); 901 1.1 gmcgarry printf(" fault 0x%x\n", css.c_fef); 902 1.1 gmcgarry printf(" access 0x%x\n", css.c_aef); 903 1.1 gmcgarry printf(" info 0x%x\n", css.c_ief); 904 1.1 gmcgarry printf(" block, P1-P10: "); 905 1.1 gmcgarry printf(" block: %" PRId64 ", P1-P10: ", hwbn); 906 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&css.c_raw[0]); 907 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&css.c_raw[4]); 908 1.1 gmcgarry printf("0x%x\n", *(u_int16_t *)&css.c_raw[8]); 909 1.1 gmcgarry } 910 1.1 gmcgarry #endif 911 1.1 gmcgarry #ifdef DEBUG 912 1.1 gmcgarry if (rddebug & RDB_ERROR) { /* command */ 913 1.1 gmcgarry printf(" ioc: "); 914 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&sc->sc_ioc.c_pad); 915 1.1 gmcgarry printf("0x%x", *(u_int16_t *)&sc->sc_ioc.c_hiaddr); 916 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&sc->sc_ioc.c_addr); 917 1.1 gmcgarry printf("0x%x", *(u_int16_t *)&sc->sc_ioc.c_nop2); 918 1.1 gmcgarry printf("0x%x", *(u_int32_t *)&sc->sc_ioc.c_len); 919 1.1 gmcgarry printf("0x%x\n", *(u_int16_t *)&sc->sc_ioc.c_cmd); 920 1.1 gmcgarry return (1); 921 1.1 gmcgarry } 922 1.1 gmcgarry #endif 923 1.1 gmcgarry /* 924 1.1 gmcgarry * Now output a generic message suitable for badsect. 925 1.1 gmcgarry * Note that we don't use harderr because it just prints 926 1.1 gmcgarry * out b_blkno which is just the beginning block number 927 1.1 gmcgarry * of the transfer, not necessary where the error occurred. 928 1.1 gmcgarry */ 929 1.1 gmcgarry printf("%s%c: hard error, sector number %" PRId64 "\n", 930 1.31 chs device_xname(sc->sc_dev), 'a'+RDPART(bp->b_dev), pbn); 931 1.1 gmcgarry /* 932 1.1 gmcgarry * Now report the status as returned by the hardware with 933 1.1 gmcgarry * attempt at interpretation. 934 1.1 gmcgarry */ 935 1.31 chs printf("%s %s error:", device_xname(sc->sc_dev), 936 1.1 gmcgarry (bp->b_flags & B_READ) ? "read" : "write"); 937 1.1 gmcgarry printf(" unit %d, volume %d R0x%x F0x%x A0x%x I0x%x\n", 938 1.1 gmcgarry css.c_vu&0xF, (css.c_vu>>4)&0xF, 939 1.1 gmcgarry css.c_ref, css.c_fef, css.c_aef, css.c_ief); 940 1.1 gmcgarry printf("P1-P10: "); 941 1.1 gmcgarry printf("0x%x ", *(u_int32_t *)&css.c_raw[0]); 942 1.1 gmcgarry printf("0x%x ", *(u_int32_t *)&css.c_raw[4]); 943 1.1 gmcgarry printf("0x%x\n", *(u_int16_t *)&css.c_raw[8]); 944 1.1 gmcgarry 945 1.1 gmcgarry return (1); 946 1.1 gmcgarry } 947 1.1 gmcgarry 948 1.1 gmcgarry int 949 1.23 dsl rdread(dev_t dev, struct uio *uio, int flags) 950 1.1 gmcgarry { 951 1.1 gmcgarry 952 1.1 gmcgarry return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio)); 953 1.1 gmcgarry } 954 1.1 gmcgarry 955 1.1 gmcgarry int 956 1.23 dsl rdwrite(dev_t dev, struct uio *uio, int flags) 957 1.1 gmcgarry { 958 1.1 gmcgarry 959 1.1 gmcgarry return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio)); 960 1.1 gmcgarry } 961 1.1 gmcgarry 962 1.1 gmcgarry int 963 1.21 cegger rdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 964 1.1 gmcgarry { 965 1.1 gmcgarry struct rd_softc *sc; 966 1.1 gmcgarry struct disklabel *lp; 967 1.1 gmcgarry int error, flags; 968 1.1 gmcgarry 969 1.21 cegger sc = device_lookup_private(&rd_cd, RDUNIT(dev)); 970 1.1 gmcgarry if (sc == NULL) 971 1.1 gmcgarry return (ENXIO); 972 1.1 gmcgarry lp = sc->sc_dk.dk_label; 973 1.1 gmcgarry 974 1.1 gmcgarry DPRINTF(RDB_FOLLOW, ("rdioctl: sc=%p\n", sc)); 975 1.1 gmcgarry 976 1.38 christos error = disk_ioctl(&sc->sc_dk, dev, cmd, data, flag, l); 977 1.37 christos if (error != EPASSTHROUGH) 978 1.37 christos return error; 979 1.37 christos 980 1.1 gmcgarry switch (cmd) { 981 1.1 gmcgarry case DIOCWLABEL: 982 1.1 gmcgarry if ((flag & FWRITE) == 0) 983 1.1 gmcgarry return (EBADF); 984 1.1 gmcgarry if (*(int *)data) 985 1.1 gmcgarry sc->sc_flags |= RDF_WLABEL; 986 1.1 gmcgarry else 987 1.1 gmcgarry sc->sc_flags &= ~RDF_WLABEL; 988 1.1 gmcgarry return (0); 989 1.1 gmcgarry 990 1.1 gmcgarry case DIOCSDINFO: 991 1.1 gmcgarry if ((flag & FWRITE) == 0) 992 1.1 gmcgarry return (EBADF); 993 1.1 gmcgarry return (setdisklabel(lp, (struct disklabel *)data, 994 1.1 gmcgarry (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dk.dk_openmask, 995 1.1 gmcgarry (struct cpu_disklabel *)0)); 996 1.1 gmcgarry 997 1.1 gmcgarry case DIOCWDINFO: 998 1.1 gmcgarry if ((flag & FWRITE) == 0) 999 1.1 gmcgarry return (EBADF); 1000 1.1 gmcgarry error = setdisklabel(lp, (struct disklabel *)data, 1001 1.1 gmcgarry (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dk.dk_openmask, 1002 1.1 gmcgarry (struct cpu_disklabel *)0); 1003 1.1 gmcgarry if (error) 1004 1.1 gmcgarry return (error); 1005 1.1 gmcgarry flags = sc->sc_flags; 1006 1.1 gmcgarry sc->sc_flags = RDF_ALIVE | RDF_WLABEL; 1007 1.1 gmcgarry error = writedisklabel(RDLABELDEV(dev), rdstrategy, lp, 1008 1.1 gmcgarry (struct cpu_disklabel *)0); 1009 1.1 gmcgarry sc->sc_flags = flags; 1010 1.1 gmcgarry return (error); 1011 1.1 gmcgarry 1012 1.1 gmcgarry case DIOCGDEFLABEL: 1013 1.1 gmcgarry rdgetdefaultlabel(sc, (struct disklabel *)data); 1014 1.1 gmcgarry return (0); 1015 1.1 gmcgarry } 1016 1.1 gmcgarry return (EINVAL); 1017 1.1 gmcgarry } 1018 1.1 gmcgarry 1019 1.1 gmcgarry void 1020 1.23 dsl rdgetdefaultlabel(struct rd_softc *sc, struct disklabel *lp) 1021 1.1 gmcgarry { 1022 1.1 gmcgarry int type = sc->sc_type; 1023 1.1 gmcgarry 1024 1.15 christos memset((void *)lp, 0, sizeof(struct disklabel)); 1025 1.1 gmcgarry 1026 1.39 christos lp->d_type = DKTYPE_HPIB /* DKTYPE_GPIB */; 1027 1.1 gmcgarry lp->d_secsize = DEV_BSIZE; 1028 1.1 gmcgarry lp->d_nsectors = rdidentinfo[type].ri_nbpt; 1029 1.1 gmcgarry lp->d_ntracks = rdidentinfo[type].ri_ntpc; 1030 1.1 gmcgarry lp->d_ncylinders = rdidentinfo[type].ri_ncyl; 1031 1.1 gmcgarry lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1032 1.1 gmcgarry lp->d_secperunit = lp->d_ncylinders * lp->d_secpercyl; 1033 1.1 gmcgarry 1034 1.1 gmcgarry strncpy(lp->d_typename, rdidentinfo[type].ri_desc, 16); 1035 1.1 gmcgarry strncpy(lp->d_packname, "fictitious", 16); 1036 1.1 gmcgarry lp->d_rpm = 3000; 1037 1.1 gmcgarry lp->d_interleave = 1; 1038 1.1 gmcgarry lp->d_flags = 0; 1039 1.1 gmcgarry 1040 1.1 gmcgarry lp->d_partitions[RAW_PART].p_offset = 0; 1041 1.1 gmcgarry lp->d_partitions[RAW_PART].p_size = 1042 1.1 gmcgarry lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); 1043 1.1 gmcgarry lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 1044 1.1 gmcgarry lp->d_npartitions = RAW_PART + 1; 1045 1.1 gmcgarry 1046 1.1 gmcgarry lp->d_magic = DISKMAGIC; 1047 1.1 gmcgarry lp->d_magic2 = DISKMAGIC; 1048 1.1 gmcgarry lp->d_checksum = dkcksum(lp); 1049 1.1 gmcgarry } 1050 1.1 gmcgarry 1051 1.1 gmcgarry int 1052 1.21 cegger rdsize(dev_t dev) 1053 1.1 gmcgarry { 1054 1.1 gmcgarry struct rd_softc *sc; 1055 1.1 gmcgarry int psize, didopen = 0; 1056 1.1 gmcgarry 1057 1.21 cegger sc = device_lookup_private(&rd_cd, RDUNIT(dev)); 1058 1.1 gmcgarry if (sc == NULL || (sc->sc_flags & RDF_ALIVE) == 0) 1059 1.1 gmcgarry return (-1); 1060 1.1 gmcgarry 1061 1.1 gmcgarry /* 1062 1.1 gmcgarry * We get called very early on (via swapconf) 1063 1.1 gmcgarry * without the device being open so we may need 1064 1.1 gmcgarry * to handle it here. 1065 1.1 gmcgarry */ 1066 1.1 gmcgarry if (sc->sc_dk.dk_openmask == 0) { 1067 1.1 gmcgarry if (rdopen(dev, FREAD | FWRITE, S_IFBLK, NULL)) 1068 1.1 gmcgarry return (-1); 1069 1.1 gmcgarry didopen = 1; 1070 1.1 gmcgarry } 1071 1.1 gmcgarry psize = sc->sc_dk.dk_label->d_partitions[RDPART(dev)].p_size * 1072 1.1 gmcgarry (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE); 1073 1.1 gmcgarry if (didopen) 1074 1.1 gmcgarry (void) rdclose(dev, FREAD | FWRITE, S_IFBLK, NULL); 1075 1.1 gmcgarry return (psize); 1076 1.1 gmcgarry } 1077 1.1 gmcgarry 1078 1.1 gmcgarry 1079 1.1 gmcgarry static int rddoingadump; /* simple mutex */ 1080 1.1 gmcgarry 1081 1.1 gmcgarry /* 1082 1.1 gmcgarry * Non-interrupt driven, non-dma dump routine. 1083 1.1 gmcgarry */ 1084 1.1 gmcgarry int 1085 1.21 cegger rddump(dev_t dev, daddr_t blkno, void *va, size_t size) 1086 1.1 gmcgarry { 1087 1.1 gmcgarry struct rd_softc *sc; 1088 1.1 gmcgarry int sectorsize; /* size of a disk sector */ 1089 1.1 gmcgarry int nsects; /* number of sectors in partition */ 1090 1.1 gmcgarry int sectoff; /* sector offset of partition */ 1091 1.1 gmcgarry int totwrt; /* total number of sectors left to write */ 1092 1.1 gmcgarry int nwrt; /* current number of sectors to write */ 1093 1.1 gmcgarry int slave; 1094 1.1 gmcgarry struct disklabel *lp; 1095 1.1 gmcgarry u_int8_t stat; 1096 1.1 gmcgarry 1097 1.1 gmcgarry /* Check for recursive dump; if so, punt. */ 1098 1.1 gmcgarry if (rddoingadump) 1099 1.1 gmcgarry return (EFAULT); 1100 1.1 gmcgarry rddoingadump = 1; 1101 1.1 gmcgarry 1102 1.21 cegger sc = device_lookup_private(&rd_cd, RDUNIT(dev)); 1103 1.1 gmcgarry if (sc == NULL || (sc->sc_flags & RDF_ALIVE) == 0) 1104 1.1 gmcgarry return (ENXIO); 1105 1.1 gmcgarry 1106 1.1 gmcgarry DPRINTF(RDB_FOLLOW, ("rddump: sc=%p\n", sc)); 1107 1.1 gmcgarry 1108 1.1 gmcgarry slave = sc->sc_slave; 1109 1.1 gmcgarry 1110 1.1 gmcgarry /* 1111 1.1 gmcgarry * Convert to disk sectors. Request must be a multiple of size. 1112 1.1 gmcgarry */ 1113 1.1 gmcgarry lp = sc->sc_dk.dk_label; 1114 1.1 gmcgarry sectorsize = lp->d_secsize; 1115 1.1 gmcgarry if ((size % sectorsize) != 0) 1116 1.1 gmcgarry return (EFAULT); 1117 1.1 gmcgarry totwrt = size / sectorsize; 1118 1.1 gmcgarry blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */ 1119 1.1 gmcgarry 1120 1.1 gmcgarry nsects = lp->d_partitions[RDPART(dev)].p_size; 1121 1.1 gmcgarry sectoff = lp->d_partitions[RDPART(dev)].p_offset; 1122 1.1 gmcgarry 1123 1.1 gmcgarry /* Check transfer bounds against partition size. */ 1124 1.1 gmcgarry if ((blkno < 0) || (blkno + totwrt) > nsects) 1125 1.1 gmcgarry return (EINVAL); 1126 1.1 gmcgarry 1127 1.1 gmcgarry /* Offset block number to start of partition. */ 1128 1.1 gmcgarry blkno += sectoff; 1129 1.1 gmcgarry 1130 1.1 gmcgarry while (totwrt > 0) { 1131 1.1 gmcgarry nwrt = totwrt; /* XXX */ 1132 1.1 gmcgarry #ifndef RD_DUMP_NOT_TRUSTED 1133 1.1 gmcgarry /* 1134 1.1 gmcgarry * Fill out and send GPIB command. 1135 1.1 gmcgarry */ 1136 1.1 gmcgarry sc->sc_ioc.c_unit = CS80CMD_SUNIT(sc->sc_punit); 1137 1.1 gmcgarry sc->sc_ioc.c_volume = CS80CMD_SVOL(0); 1138 1.1 gmcgarry sc->sc_ioc.c_saddr = CS80CMD_SADDR; 1139 1.1 gmcgarry sc->sc_ioc.c_hiaddr = 0; 1140 1.1 gmcgarry sc->sc_ioc.c_addr = RDBTOS(blkno); 1141 1.1 gmcgarry sc->sc_ioc.c_nop2 = CS80CMD_NOP; 1142 1.1 gmcgarry sc->sc_ioc.c_slen = CS80CMD_SLEN; 1143 1.1 gmcgarry sc->sc_ioc.c_len = nwrt * sectorsize; 1144 1.1 gmcgarry sc->sc_ioc.c_cmd = CS80CMD_WRITE; 1145 1.1 gmcgarry (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, 1146 1.1 gmcgarry &sc->sc_ioc.c_unit, sizeof(sc->sc_ioc)-3); 1147 1.1 gmcgarry if (gpibswait(sc->sc_ic, slave)) 1148 1.1 gmcgarry return (EIO); 1149 1.1 gmcgarry /* 1150 1.1 gmcgarry * Send the data. 1151 1.1 gmcgarry */ 1152 1.1 gmcgarry (void) gpibsend(sc->sc_ic, slave, CS80CMD_EXEC, va, 1153 1.1 gmcgarry nwrt * sectorsize); 1154 1.1 gmcgarry (void) gpibswait(sc->sc_ic, slave); 1155 1.1 gmcgarry (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 1156 1.1 gmcgarry if (stat) 1157 1.1 gmcgarry return (EIO); 1158 1.1 gmcgarry #else /* RD_DUMP_NOT_TRUSTED */ 1159 1.1 gmcgarry /* Let's just talk about this first... */ 1160 1.31 chs printf("%s: dump addr %p, blk %d\n", device_xname(sc->sc_dev), 1161 1.1 gmcgarry va, blkno); 1162 1.1 gmcgarry delay(500 * 1000); /* half a second */ 1163 1.1 gmcgarry #endif /* RD_DUMP_NOT_TRUSTED */ 1164 1.1 gmcgarry 1165 1.1 gmcgarry /* update block count */ 1166 1.1 gmcgarry totwrt -= nwrt; 1167 1.1 gmcgarry blkno += nwrt; 1168 1.27 tsutsui va = (char *)va + sectorsize * nwrt; 1169 1.1 gmcgarry } 1170 1.1 gmcgarry rddoingadump = 0; 1171 1.1 gmcgarry return (0); 1172 1.1 gmcgarry } 1173