| @@ -1,1340 +1,1340 @@ | | | @@ -1,1340 +1,1340 @@ |
1 | /* $NetBSD: rd.c,v 1.90 2011/02/08 20:20:13 rmind Exp $ */ | | 1 | /* $NetBSD: rd.c,v 1.91 2011/07/28 03:42:20 uebayasi Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe. | | 8 | * by Jason R. Thorpe. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1988 University of Utah. | | 33 | * Copyright (c) 1988 University of Utah. |
34 | * Copyright (c) 1982, 1990, 1993 | | 34 | * Copyright (c) 1982, 1990, 1993 |
35 | * The Regents of the University of California. All rights reserved. | | 35 | * The Regents of the University of California. All rights reserved. |
36 | * | | 36 | * |
37 | * This code is derived from software contributed to Berkeley by | | 37 | * This code is derived from software contributed to Berkeley by |
38 | * the Systems Programming Group of the University of Utah Computer | | 38 | * the Systems Programming Group of the University of Utah Computer |
39 | * Science Department. | | 39 | * Science Department. |
40 | * | | 40 | * |
41 | * Redistribution and use in source and binary forms, with or without | | 41 | * Redistribution and use in source and binary forms, with or without |
42 | * modification, are permitted provided that the following conditions | | 42 | * modification, are permitted provided that the following conditions |
43 | * are met: | | 43 | * are met: |
44 | * 1. Redistributions of source code must retain the above copyright | | 44 | * 1. Redistributions of source code must retain the above copyright |
45 | * notice, this list of conditions and the following disclaimer. | | 45 | * notice, this list of conditions and the following disclaimer. |
46 | * 2. Redistributions in binary form must reproduce the above copyright | | 46 | * 2. Redistributions in binary form must reproduce the above copyright |
47 | * notice, this list of conditions and the following disclaimer in the | | 47 | * notice, this list of conditions and the following disclaimer in the |
48 | * documentation and/or other materials provided with the distribution. | | 48 | * documentation and/or other materials provided with the distribution. |
49 | * 3. Neither the name of the University nor the names of its contributors | | 49 | * 3. Neither the name of the University nor the names of its contributors |
50 | * may be used to endorse or promote products derived from this software | | 50 | * may be used to endorse or promote products derived from this software |
51 | * without specific prior written permission. | | 51 | * without specific prior written permission. |
52 | * | | 52 | * |
53 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 53 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
54 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 54 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
63 | * SUCH DAMAGE. | | 63 | * SUCH DAMAGE. |
64 | * | | 64 | * |
65 | * from: Utah $Hdr: rd.c 1.44 92/12/26$ | | 65 | * from: Utah $Hdr: rd.c 1.44 92/12/26$ |
66 | * | | 66 | * |
67 | * @(#)rd.c 8.2 (Berkeley) 5/19/94 | | 67 | * @(#)rd.c 8.2 (Berkeley) 5/19/94 |
68 | */ | | 68 | */ |
69 | | | 69 | |
70 | /* | | 70 | /* |
71 | * CS80/SS80 disk driver | | 71 | * CS80/SS80 disk driver |
72 | */ | | 72 | */ |
73 | | | 73 | |
74 | #include <sys/cdefs.h> | | 74 | #include <sys/cdefs.h> |
75 | __KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.90 2011/02/08 20:20:13 rmind Exp $"); | | 75 | __KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.91 2011/07/28 03:42:20 uebayasi Exp $"); |
76 | | | 76 | |
77 | #include "opt_useleds.h" | | 77 | #include "opt_useleds.h" |
78 | #include "rnd.h" | | 78 | #include "rnd.h" |
79 | | | 79 | |
80 | #include <sys/param.h> | | 80 | #include <sys/param.h> |
81 | #include <sys/systm.h> | | 81 | #include <sys/systm.h> |
82 | #include <sys/buf.h> | | 82 | #include <sys/buf.h> |
83 | #include <sys/bufq.h> | | 83 | #include <sys/bufq.h> |
84 | #include <sys/conf.h> | | 84 | #include <sys/conf.h> |
85 | #include <sys/device.h> | | 85 | #include <sys/device.h> |
86 | #include <sys/disk.h> | | 86 | #include <sys/disk.h> |
87 | #include <sys/disklabel.h> | | 87 | #include <sys/disklabel.h> |
88 | #include <sys/fcntl.h> | | 88 | #include <sys/fcntl.h> |
89 | #include <sys/ioctl.h> | | 89 | #include <sys/ioctl.h> |
90 | #include <sys/proc.h> | | 90 | #include <sys/proc.h> |
91 | #include <sys/stat.h> | | 91 | #include <sys/stat.h> |
92 | | | 92 | |
93 | #if NRND > 0 | | 93 | #if NRND > 0 |
94 | #include <sys/rnd.h> | | 94 | #include <sys/rnd.h> |
95 | #endif | | 95 | #endif |
96 | | | 96 | |
97 | #include <hp300/dev/hpibvar.h> | | 97 | #include <hp300/dev/hpibvar.h> |
98 | | | 98 | |
99 | #include <hp300/dev/rdreg.h> | | 99 | #include <hp300/dev/rdreg.h> |
100 | #include <hp300/dev/rdvar.h> | | 100 | #include <hp300/dev/rdvar.h> |
101 | | | 101 | |
102 | #ifdef USELEDS | | 102 | #ifdef USELEDS |
103 | #include <hp300/hp300/leds.h> | | 103 | #include <hp300/hp300/leds.h> |
104 | #endif | | 104 | #endif |
105 | | | 105 | |
106 | #include "ioconf.h" | | 106 | #include "ioconf.h" |
107 | | | 107 | |
108 | int rderrthresh = RDRETRY-1; /* when to start reporting errors */ | | 108 | int rderrthresh = RDRETRY-1; /* when to start reporting errors */ |
109 | | | 109 | |
110 | #ifdef DEBUG | | 110 | #ifdef DEBUG |
111 | /* error message tables */ | | 111 | /* error message tables */ |
112 | static const char *err_reject[] = { | | 112 | static const char *err_reject[] = { |
113 | 0, 0, | | 113 | 0, 0, |
114 | "channel parity error", /* 0x2000 */ | | 114 | "channel parity error", /* 0x2000 */ |
115 | 0, 0, | | 115 | 0, 0, |
116 | "illegal opcode", /* 0x0400 */ | | 116 | "illegal opcode", /* 0x0400 */ |
117 | "module addressing", /* 0x0200 */ | | 117 | "module addressing", /* 0x0200 */ |
118 | "address bounds", /* 0x0100 */ | | 118 | "address bounds", /* 0x0100 */ |
119 | "parameter bounds", /* 0x0080 */ | | 119 | "parameter bounds", /* 0x0080 */ |
120 | "illegal parameter", /* 0x0040 */ | | 120 | "illegal parameter", /* 0x0040 */ |
121 | "message sequence", /* 0x0020 */ | | 121 | "message sequence", /* 0x0020 */ |
122 | 0, | | 122 | 0, |
123 | "message length", /* 0x0008 */ | | 123 | "message length", /* 0x0008 */ |
124 | 0, 0, 0 | | 124 | 0, 0, 0 |
125 | }; | | 125 | }; |
126 | | | 126 | |
127 | static const char *err_fault[] = { | | 127 | static const char *err_fault[] = { |
128 | 0, | | 128 | 0, |
129 | "cross unit", /* 0x4000 */ | | 129 | "cross unit", /* 0x4000 */ |
130 | 0, | | 130 | 0, |
131 | "controller fault", /* 0x1000 */ | | 131 | "controller fault", /* 0x1000 */ |
132 | 0, 0, | | 132 | 0, 0, |
133 | "unit fault", /* 0x0200 */ | | 133 | "unit fault", /* 0x0200 */ |
134 | 0, | | 134 | 0, |
135 | "diagnostic result", /* 0x0080 */ | | 135 | "diagnostic result", /* 0x0080 */ |
136 | 0, | | 136 | 0, |
137 | "operator release request", /* 0x0020 */ | | 137 | "operator release request", /* 0x0020 */ |
138 | "diagnostic release request", /* 0x0010 */ | | 138 | "diagnostic release request", /* 0x0010 */ |
139 | "internal maintenance release request", /* 0x0008 */ | | 139 | "internal maintenance release request", /* 0x0008 */ |
140 | 0, | | 140 | 0, |
141 | "power fail", /* 0x0002 */ | | 141 | "power fail", /* 0x0002 */ |
142 | "retransmit" /* 0x0001 */ | | 142 | "retransmit" /* 0x0001 */ |
143 | }; | | 143 | }; |
144 | | | 144 | |
145 | static const char *err_access[] = { | | 145 | static const char *err_access[] = { |
146 | "illegal parallel operation", /* 0x8000 */ | | 146 | "illegal parallel operation", /* 0x8000 */ |
147 | "uninitialized media", /* 0x4000 */ | | 147 | "uninitialized media", /* 0x4000 */ |
148 | "no spares available", /* 0x2000 */ | | 148 | "no spares available", /* 0x2000 */ |
149 | "not ready", /* 0x1000 */ | | 149 | "not ready", /* 0x1000 */ |
150 | "write protect", /* 0x0800 */ | | 150 | "write protect", /* 0x0800 */ |
151 | "no data found", /* 0x0400 */ | | 151 | "no data found", /* 0x0400 */ |
152 | 0, 0, | | 152 | 0, 0, |
153 | "unrecoverable data overflow", /* 0x0080 */ | | 153 | "unrecoverable data overflow", /* 0x0080 */ |
154 | "unrecoverable data", /* 0x0040 */ | | 154 | "unrecoverable data", /* 0x0040 */ |
155 | 0, | | 155 | 0, |
156 | "end of file", /* 0x0010 */ | | 156 | "end of file", /* 0x0010 */ |
157 | "end of volume", /* 0x0008 */ | | 157 | "end of volume", /* 0x0008 */ |
158 | 0, 0, 0 | | 158 | 0, 0, 0 |
159 | }; | | 159 | }; |
160 | | | 160 | |
161 | static const char *err_info[] = { | | 161 | static const char *err_info[] = { |
162 | "operator release request", /* 0x8000 */ | | 162 | "operator release request", /* 0x8000 */ |
163 | "diagnostic release request", /* 0x4000 */ | | 163 | "diagnostic release request", /* 0x4000 */ |
164 | "internal maintenance release request", /* 0x2000 */ | | 164 | "internal maintenance release request", /* 0x2000 */ |
165 | "media wear", /* 0x1000 */ | | 165 | "media wear", /* 0x1000 */ |
166 | "latency induced", /* 0x0800 */ | | 166 | "latency induced", /* 0x0800 */ |
167 | 0, 0, | | 167 | 0, 0, |
168 | "auto sparing invoked", /* 0x0100 */ | | 168 | "auto sparing invoked", /* 0x0100 */ |
169 | 0, | | 169 | 0, |
170 | "recoverable data overflow", /* 0x0040 */ | | 170 | "recoverable data overflow", /* 0x0040 */ |
171 | "marginal data", /* 0x0020 */ | | 171 | "marginal data", /* 0x0020 */ |
172 | "recoverable data", /* 0x0010 */ | | 172 | "recoverable data", /* 0x0010 */ |
173 | 0, | | 173 | 0, |
174 | "maintenance track overflow", /* 0x0004 */ | | 174 | "maintenance track overflow", /* 0x0004 */ |
175 | 0, 0 | | 175 | 0, 0 |
176 | }; | | 176 | }; |
177 | | | 177 | |
178 | int rddebug = 0x80; | | 178 | int rddebug = 0x80; |
179 | #define RDB_FOLLOW 0x01 | | 179 | #define RDB_FOLLOW 0x01 |
180 | #define RDB_STATUS 0x02 | | 180 | #define RDB_STATUS 0x02 |
181 | #define RDB_IDENT 0x04 | | 181 | #define RDB_IDENT 0x04 |
182 | #define RDB_IO 0x08 | | 182 | #define RDB_IO 0x08 |
183 | #define RDB_ASYNC 0x10 | | 183 | #define RDB_ASYNC 0x10 |
184 | #define RDB_ERROR 0x80 | | 184 | #define RDB_ERROR 0x80 |
185 | #endif | | 185 | #endif |
186 | | | 186 | |
187 | /* | | 187 | /* |
188 | * Misc. HW description, indexed by sc_type. | | 188 | * Misc. HW description, indexed by sc_type. |
189 | * Nothing really critical here, could do without it. | | 189 | * Nothing really critical here, could do without it. |
190 | */ | | 190 | */ |
191 | static const struct rdidentinfo rdidentinfo[] = { | | 191 | static const struct rdidentinfo rdidentinfo[] = { |
192 | { RD7946AID, 0, "7945A", NRD7945ABPT, | | 192 | { RD7946AID, 0, "7945A", NRD7945ABPT, |
193 | NRD7945ATRK, 968, 108416 }, | | 193 | NRD7945ATRK, 968, 108416 }, |
194 | | | 194 | |
195 | { RD9134DID, 1, "9134D", NRD9134DBPT, | | 195 | { RD9134DID, 1, "9134D", NRD9134DBPT, |
196 | NRD9134DTRK, 303, 29088 }, | | 196 | NRD9134DTRK, 303, 29088 }, |
197 | | | 197 | |
198 | { RD9134LID, 1, "9122S", NRD9122SBPT, | | 198 | { RD9134LID, 1, "9122S", NRD9122SBPT, |
199 | NRD9122STRK, 77, 1232 }, | | 199 | NRD9122STRK, 77, 1232 }, |
200 | | | 200 | |
201 | { RD7912PID, 0, "7912P", NRD7912PBPT, | | 201 | { RD7912PID, 0, "7912P", NRD7912PBPT, |
202 | NRD7912PTRK, 572, 128128 }, | | 202 | NRD7912PTRK, 572, 128128 }, |
203 | | | 203 | |
204 | { RD7914PID, 0, "7914P", NRD7914PBPT, | | 204 | { RD7914PID, 0, "7914P", NRD7914PBPT, |
205 | NRD7914PTRK, 1152, 258048 }, | | 205 | NRD7914PTRK, 1152, 258048 }, |
206 | | | 206 | |
207 | { RD7958AID, 0, "7958A", NRD7958ABPT, | | 207 | { RD7958AID, 0, "7958A", NRD7958ABPT, |
208 | NRD7958ATRK, 1013, 255276 }, | | 208 | NRD7958ATRK, 1013, 255276 }, |
209 | | | 209 | |
210 | { RD7957AID, 0, "7957A", NRD7957ABPT, | | 210 | { RD7957AID, 0, "7957A", NRD7957ABPT, |
211 | NRD7957ATRK, 1036, 159544 }, | | 211 | NRD7957ATRK, 1036, 159544 }, |
212 | | | 212 | |
213 | { RD7933HID, 0, "7933H", NRD7933HBPT, | | 213 | { RD7933HID, 0, "7933H", NRD7933HBPT, |
214 | NRD7933HTRK, 1321, 789958 }, | | 214 | NRD7933HTRK, 1321, 789958 }, |
215 | | | 215 | |
216 | { RD9134LID, 1, "9134L", NRD9134LBPT, | | 216 | { RD9134LID, 1, "9134L", NRD9134LBPT, |
217 | NRD9134LTRK, 973, 77840 }, | | 217 | NRD9134LTRK, 973, 77840 }, |
218 | | | 218 | |
219 | { RD7936HID, 0, "7936H", NRD7936HBPT, | | 219 | { RD7936HID, 0, "7936H", NRD7936HBPT, |
220 | NRD7936HTRK, 698, 600978 }, | | 220 | NRD7936HTRK, 698, 600978 }, |
221 | | | 221 | |
222 | { RD7937HID, 0, "7937H", NRD7937HBPT, | | 222 | { RD7937HID, 0, "7937H", NRD7937HBPT, |
223 | NRD7937HTRK, 698, 1116102 }, | | 223 | NRD7937HTRK, 698, 1116102 }, |
224 | | | 224 | |
225 | { RD7914CTID, 0, "7914CT", NRD7914PBPT, | | 225 | { RD7914CTID, 0, "7914CT", NRD7914PBPT, |
226 | NRD7914PTRK, 1152, 258048 }, | | 226 | NRD7914PTRK, 1152, 258048 }, |
227 | | | 227 | |
228 | { RD7946AID, 0, "7946A", NRD7945ABPT, | | 228 | { RD7946AID, 0, "7946A", NRD7945ABPT, |
229 | NRD7945ATRK, 968, 108416 }, | | 229 | NRD7945ATRK, 968, 108416 }, |
230 | | | 230 | |
231 | { RD9134LID, 1, "9122D", NRD9122SBPT, | | 231 | { RD9134LID, 1, "9122D", NRD9122SBPT, |
232 | NRD9122STRK, 77, 1232 }, | | 232 | NRD9122STRK, 77, 1232 }, |
233 | | | 233 | |
234 | { RD7957BID, 0, "7957B", NRD7957BBPT, | | 234 | { RD7957BID, 0, "7957B", NRD7957BBPT, |
235 | NRD7957BTRK, 1269, 159894 }, | | 235 | NRD7957BTRK, 1269, 159894 }, |
236 | | | 236 | |
237 | { RD7958BID, 0, "7958B", NRD7958BBPT, | | 237 | { RD7958BID, 0, "7958B", NRD7958BBPT, |
238 | NRD7958BTRK, 786, 297108 }, | | 238 | NRD7958BTRK, 786, 297108 }, |
239 | | | 239 | |
240 | { RD7959BID, 0, "7959B", NRD7959BBPT, | | 240 | { RD7959BID, 0, "7959B", NRD7959BBPT, |
241 | NRD7959BTRK, 1572, 594216 }, | | 241 | NRD7959BTRK, 1572, 594216 }, |
242 | | | 242 | |
243 | { RD2200AID, 0, "2200A", NRD2200ABPT, | | 243 | { RD2200AID, 0, "2200A", NRD2200ABPT, |
244 | NRD2200ATRK, 1449, 654948 }, | | 244 | NRD2200ATRK, 1449, 654948 }, |
245 | | | 245 | |
246 | { RD2203AID, 0, "2203A", NRD2203ABPT, | | 246 | { RD2203AID, 0, "2203A", NRD2203ABPT, |
247 | NRD2203ATRK, 1449, 1309896 } | | 247 | NRD2203ATRK, 1449, 1309896 } |
248 | }; | | 248 | }; |
249 | static const int numrdidentinfo = __arraycount(rdidentinfo); | | 249 | static const int numrdidentinfo = __arraycount(rdidentinfo); |
250 | | | 250 | |
251 | static int rdident(struct device *, struct rd_softc *, | | 251 | static int rdident(struct device *, struct rd_softc *, |
252 | struct hpibbus_attach_args *); | | 252 | struct hpibbus_attach_args *); |
253 | static void rdreset(struct rd_softc *); | | 253 | static void rdreset(struct rd_softc *); |
254 | static void rdustart(struct rd_softc *); | | 254 | static void rdustart(struct rd_softc *); |
255 | static int rdgetinfo(dev_t); | | 255 | static int rdgetinfo(dev_t); |
256 | static void rdrestart(void *); | | 256 | static void rdrestart(void *); |
257 | static struct buf *rdfinish(struct rd_softc *, struct buf *); | | 257 | static struct buf *rdfinish(struct rd_softc *, struct buf *); |
258 | | | 258 | |
259 | static void rdgetdefaultlabel(struct rd_softc *, struct disklabel *); | | 259 | static void rdgetdefaultlabel(struct rd_softc *, struct disklabel *); |
260 | static void rdrestart(void *); | | 260 | static void rdrestart(void *); |
261 | static void rdustart(struct rd_softc *); | | 261 | static void rdustart(struct rd_softc *); |
262 | static struct buf *rdfinish(struct rd_softc *, struct buf *); | | 262 | static struct buf *rdfinish(struct rd_softc *, struct buf *); |
263 | static void rdstart(void *); | | 263 | static void rdstart(void *); |
264 | static void rdgo(void *); | | 264 | static void rdgo(void *); |
265 | static void rdintr(void *); | | 265 | static void rdintr(void *); |
266 | static int rdstatus(struct rd_softc *); | | 266 | static int rdstatus(struct rd_softc *); |
267 | static int rderror(int); | | 267 | static int rderror(int); |
268 | #ifdef DEBUG | | 268 | #ifdef DEBUG |
269 | static void rdprinterr(const char *, short, const char **); | | 269 | static void rdprinterr(const char *, short, const char **); |
270 | #endif | | 270 | #endif |
271 | | | 271 | |
272 | static int rdmatch(device_t, cfdata_t, void *); | | 272 | static int rdmatch(device_t, cfdata_t, void *); |
273 | static void rdattach(device_t, device_t, void *); | | 273 | static void rdattach(device_t, device_t, void *); |
274 | | | 274 | |
275 | CFATTACH_DECL_NEW(rd, sizeof(struct rd_softc), | | 275 | CFATTACH_DECL_NEW(rd, sizeof(struct rd_softc), |
276 | rdmatch, rdattach, NULL, NULL); | | 276 | rdmatch, rdattach, NULL, NULL); |
277 | | | 277 | |
278 | static dev_type_open(rdopen); | | 278 | static dev_type_open(rdopen); |
279 | static dev_type_close(rdclose); | | 279 | static dev_type_close(rdclose); |
280 | static dev_type_read(rdread); | | 280 | static dev_type_read(rdread); |
281 | static dev_type_write(rdwrite); | | 281 | static dev_type_write(rdwrite); |
282 | static dev_type_ioctl(rdioctl); | | 282 | static dev_type_ioctl(rdioctl); |
283 | static dev_type_strategy(rdstrategy); | | 283 | static dev_type_strategy(rdstrategy); |
284 | static dev_type_dump(rddump); | | 284 | static dev_type_dump(rddump); |
285 | static dev_type_size(rdsize); | | 285 | static dev_type_size(rdsize); |
286 | | | 286 | |
287 | const struct bdevsw rd_bdevsw = { | | 287 | const struct bdevsw rd_bdevsw = { |
288 | rdopen, rdclose, rdstrategy, rdioctl, rddump, rdsize, D_DISK | | 288 | rdopen, rdclose, rdstrategy, rdioctl, rddump, rdsize, D_DISK |
289 | }; | | 289 | }; |
290 | | | 290 | |
291 | const struct cdevsw rd_cdevsw = { | | 291 | const struct cdevsw rd_cdevsw = { |
292 | rdopen, rdclose, rdread, rdwrite, rdioctl, | | 292 | rdopen, rdclose, rdread, rdwrite, rdioctl, |
293 | nostop, notty, nopoll, nommap, nokqfilter, D_DISK | | 293 | nostop, notty, nopoll, nommap, nokqfilter, D_DISK |
294 | }; | | 294 | }; |
295 | | | 295 | |
296 | static int | | 296 | static int |
297 | rdmatch(device_t parent, cfdata_t cf, void *aux) | | 297 | rdmatch(device_t parent, cfdata_t cf, void *aux) |
298 | { | | 298 | { |
299 | struct hpibbus_attach_args *ha = aux; | | 299 | struct hpibbus_attach_args *ha = aux; |
300 | | | 300 | |
301 | /* | | 301 | /* |
302 | * Set punit if operator specified one in the kernel | | 302 | * Set punit if operator specified one in the kernel |
303 | * configuration file. | | 303 | * configuration file. |
304 | */ | | 304 | */ |
305 | if (cf->hpibbuscf_punit != HPIBBUSCF_PUNIT_DEFAULT && | | 305 | if (cf->hpibbuscf_punit != HPIBBUSCF_PUNIT_DEFAULT && |
306 | cf->hpibbuscf_punit < HPIB_NPUNITS) | | 306 | cf->hpibbuscf_punit < HPIB_NPUNITS) |
307 | ha->ha_punit = cf->hpibbuscf_punit; | | 307 | ha->ha_punit = cf->hpibbuscf_punit; |
308 | | | 308 | |
309 | if (rdident(parent, NULL, ha) == 0) { | | 309 | if (rdident(parent, NULL, ha) == 0) { |
310 | /* | | 310 | /* |
311 | * XXX Some aging HP-IB drives are slow to | | 311 | * XXX Some aging HP-IB drives are slow to |
312 | * XXX respond; give them a chance to catch | | 312 | * XXX respond; give them a chance to catch |
313 | * XXX up and probe them again. | | 313 | * XXX up and probe them again. |
314 | */ | | 314 | */ |
315 | delay(10000); | | 315 | delay(10000); |
316 | ha->ha_id = hpibid(device_unit(parent), ha->ha_slave); | | 316 | ha->ha_id = hpibid(device_unit(parent), ha->ha_slave); |
317 | return rdident(parent, NULL, ha); | | 317 | return rdident(parent, NULL, ha); |
318 | } | | 318 | } |
319 | return 1; | | 319 | return 1; |
320 | } | | 320 | } |
321 | | | 321 | |
322 | static void | | 322 | static void |
323 | rdattach(device_t parent, device_t self, void *aux) | | 323 | rdattach(device_t parent, device_t self, void *aux) |
324 | { | | 324 | { |
325 | struct rd_softc *sc = device_private(self); | | 325 | struct rd_softc *sc = device_private(self); |
326 | struct hpibbus_attach_args *ha = aux; | | 326 | struct hpibbus_attach_args *ha = aux; |
327 | | | 327 | |
328 | sc->sc_dev = self; | | 328 | sc->sc_dev = self; |
329 | bufq_alloc(&sc->sc_tab, "disksort", BUFQ_SORT_RAWBLOCK); | | 329 | bufq_alloc(&sc->sc_tab, "disksort", BUFQ_SORT_RAWBLOCK); |
330 | | | 330 | |
331 | if (rdident(parent, sc, ha) == 0) { | | 331 | if (rdident(parent, sc, ha) == 0) { |
332 | aprint_error(": didn't respond to describe command!\n"); | | 332 | aprint_error(": didn't respond to describe command!\n"); |
333 | return; | | 333 | return; |
334 | } | | 334 | } |
335 | | | 335 | |
336 | /* | | 336 | /* |
337 | * Initialize and attach the disk structure. | | 337 | * Initialize and attach the disk structure. |
338 | */ | | 338 | */ |
339 | memset(&sc->sc_dkdev, 0, sizeof(sc->sc_dkdev)); | | 339 | memset(&sc->sc_dkdev, 0, sizeof(sc->sc_dkdev)); |
340 | disk_init(&sc->sc_dkdev, device_xname(sc->sc_dev), NULL); | | 340 | disk_init(&sc->sc_dkdev, device_xname(sc->sc_dev), NULL); |
341 | disk_attach(&sc->sc_dkdev); | | 341 | disk_attach(&sc->sc_dkdev); |
342 | | | 342 | |
343 | sc->sc_slave = ha->ha_slave; | | 343 | sc->sc_slave = ha->ha_slave; |
344 | sc->sc_punit = ha->ha_punit; | | 344 | sc->sc_punit = ha->ha_punit; |
345 | | | 345 | |
346 | callout_init(&sc->sc_restart_ch, 0); | | 346 | callout_init(&sc->sc_restart_ch, 0); |
347 | | | 347 | |
348 | /* Initialize the hpib job queue entry */ | | 348 | /* Initialize the hpib job queue entry */ |
349 | sc->sc_hq.hq_softc = sc; | | 349 | sc->sc_hq.hq_softc = sc; |
350 | sc->sc_hq.hq_slave = sc->sc_slave; | | 350 | sc->sc_hq.hq_slave = sc->sc_slave; |
351 | sc->sc_hq.hq_start = rdstart; | | 351 | sc->sc_hq.hq_start = rdstart; |
352 | sc->sc_hq.hq_go = rdgo; | | 352 | sc->sc_hq.hq_go = rdgo; |
353 | sc->sc_hq.hq_intr = rdintr; | | 353 | sc->sc_hq.hq_intr = rdintr; |
354 | | | 354 | |
355 | sc->sc_flags = RDF_ALIVE; | | 355 | sc->sc_flags = RDF_ALIVE; |
356 | #ifdef DEBUG | | 356 | #ifdef DEBUG |
357 | /* always report errors */ | | 357 | /* always report errors */ |
358 | if (rddebug & RDB_ERROR) | | 358 | if (rddebug & RDB_ERROR) |
359 | rderrthresh = 0; | | 359 | rderrthresh = 0; |
360 | #endif | | 360 | #endif |
361 | #if NRND > 0 | | 361 | #if NRND > 0 |
362 | /* | | 362 | /* |
363 | * attach the device into the random source list | | 363 | * attach the device into the random source list |
364 | */ | | 364 | */ |
365 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | | 365 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), |
366 | RND_TYPE_DISK, 0); | | 366 | RND_TYPE_DISK, 0); |
367 | #endif | | 367 | #endif |
368 | } | | 368 | } |
369 | | | 369 | |
370 | static int | | 370 | static int |
371 | rdident(device_t parent, struct rd_softc *sc, struct hpibbus_attach_args *ha) | | 371 | rdident(device_t parent, struct rd_softc *sc, struct hpibbus_attach_args *ha) |
372 | { | | 372 | { |
373 | struct rd_describe *desc = sc != NULL ? &sc->sc_rddesc : NULL; | | 373 | struct rd_describe *desc = sc != NULL ? &sc->sc_rddesc : NULL; |
374 | u_char stat, cmd[3]; | | 374 | u_char stat, cmd[3]; |
375 | char name[7]; | | 375 | char name[7]; |
376 | int i, id, n, ctlr, slave; | | 376 | int i, id, n, ctlr, slave; |
377 | | | 377 | |
378 | ctlr = device_unit(parent); | | 378 | ctlr = device_unit(parent); |
379 | slave = ha->ha_slave; | | 379 | slave = ha->ha_slave; |
380 | | | 380 | |
381 | /* Verify that we have a CS80 device. */ | | 381 | /* Verify that we have a CS80 device. */ |
382 | if ((ha->ha_id & 0x200) == 0) | | 382 | if ((ha->ha_id & 0x200) == 0) |
383 | return 0; | | 383 | return 0; |
384 | | | 384 | |
385 | /* Is it one of the disks we support? */ | | 385 | /* Is it one of the disks we support? */ |
386 | for (id = 0; id < numrdidentinfo; id++) | | 386 | for (id = 0; id < numrdidentinfo; id++) |
387 | if (ha->ha_id == rdidentinfo[id].ri_hwid) | | 387 | if (ha->ha_id == rdidentinfo[id].ri_hwid) |
388 | break; | | 388 | break; |
389 | if (id == numrdidentinfo || ha->ha_punit > rdidentinfo[id].ri_maxunum) | | 389 | if (id == numrdidentinfo || ha->ha_punit > rdidentinfo[id].ri_maxunum) |
390 | return 0; | | 390 | return 0; |
391 | | | 391 | |
392 | /* | | 392 | /* |
393 | * If we're just probing for the device, that's all the | | 393 | * If we're just probing for the device, that's all the |
394 | * work we need to do. | | 394 | * work we need to do. |
395 | */ | | 395 | */ |
396 | if (sc == NULL) | | 396 | if (sc == NULL) |
397 | return 1; | | 397 | return 1; |
398 | | | 398 | |
399 | /* | | 399 | /* |
400 | * Reset device and collect description | | 400 | * Reset device and collect description |
401 | */ | | 401 | */ |
402 | rdreset(sc); | | 402 | rdreset(sc); |
403 | cmd[0] = C_SUNIT(ha->ha_punit); | | 403 | cmd[0] = C_SUNIT(ha->ha_punit); |
404 | cmd[1] = C_SVOL(0); | | 404 | cmd[1] = C_SVOL(0); |
405 | cmd[2] = C_DESC; | | 405 | cmd[2] = C_DESC; |
406 | hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd)); | | 406 | hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd)); |
407 | hpibrecv(ctlr, slave, C_EXEC, desc, 37); | | 407 | hpibrecv(ctlr, slave, C_EXEC, desc, 37); |
408 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); | | 408 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); |
409 | memset(name, 0, sizeof(name)); | | 409 | memset(name, 0, sizeof(name)); |
410 | if (stat == 0) { | | 410 | if (stat == 0) { |
411 | n = desc->d_name; | | 411 | n = desc->d_name; |
412 | for (i = 5; i >= 0; i--) { | | 412 | for (i = 5; i >= 0; i--) { |
413 | name[i] = (n & 0xf) + '0'; | | 413 | name[i] = (n & 0xf) + '0'; |
414 | n >>= 4; | | 414 | n >>= 4; |
415 | } | | 415 | } |
416 | } | | 416 | } |
417 | | | 417 | |
418 | #ifdef DEBUG | | 418 | #ifdef DEBUG |
419 | if (rddebug & RDB_IDENT) { | | 419 | if (rddebug & RDB_IDENT) { |
420 | aprint_debug("\n"); | | 420 | aprint_debug("\n"); |
421 | aprint_debug_dev(sc->sc_dev, "name: %x ('%s')\n", | | 421 | aprint_debug_dev(sc->sc_dev, "name: %x ('%s')\n", |
422 | desc->d_name, name); | | 422 | desc->d_name, name); |
423 | aprint_debug(" iuw %x, maxxfr %d, ctype %d\n", | | 423 | aprint_debug(" iuw %x, maxxfr %d, ctype %d\n", |
424 | desc->d_iuw, desc->d_cmaxxfr, desc->d_ctype); | | 424 | desc->d_iuw, desc->d_cmaxxfr, desc->d_ctype); |
425 | aprint_debug(" utype %d, bps %d, blkbuf %d, burst %d," | | 425 | aprint_debug(" utype %d, bps %d, blkbuf %d, burst %d," |
426 | " blktime %d\n", | | 426 | " blktime %d\n", |
427 | desc->d_utype, desc->d_sectsize, | | 427 | desc->d_utype, desc->d_sectsize, |
428 | desc->d_blkbuf, desc->d_burstsize, desc->d_blocktime); | | 428 | desc->d_blkbuf, desc->d_burstsize, desc->d_blocktime); |
429 | aprint_debug(" avxfr %d, ort %d, atp %d, maxint %d, fv %x" | | 429 | aprint_debug(" avxfr %d, ort %d, atp %d, maxint %d, fv %x" |
430 | ", rv %x\n", | | 430 | ", rv %x\n", |
431 | desc->d_uavexfr, desc->d_retry, desc->d_access, | | 431 | desc->d_uavexfr, desc->d_retry, desc->d_access, |
432 | desc->d_maxint, desc->d_fvbyte, desc->d_rvbyte); | | 432 | desc->d_maxint, desc->d_fvbyte, desc->d_rvbyte); |
433 | aprint_debug(" maxcyl/head/sect %d/%d/%d, maxvsect %d," | | 433 | aprint_debug(" maxcyl/head/sect %d/%d/%d, maxvsect %d," |
434 | " inter %d\n", | | 434 | " inter %d\n", |
435 | desc->d_maxcyl, desc->d_maxhead, desc->d_maxsect, | | 435 | desc->d_maxcyl, desc->d_maxhead, desc->d_maxsect, |
436 | desc->d_maxvsectl, desc->d_interleave); | | 436 | desc->d_maxvsectl, desc->d_interleave); |
437 | aprint_normal("%s", device_xname(sc->sc_dev)); | | 437 | aprint_normal("%s", device_xname(sc->sc_dev)); |
438 | } | | 438 | } |
439 | #endif | | 439 | #endif |
440 | | | 440 | |
441 | /* | | 441 | /* |
442 | * Take care of a couple of anomolies: | | 442 | * Take care of a couple of anomolies: |
443 | * 1. 7945A and 7946A both return same HW id | | 443 | * 1. 7945A and 7946A both return same HW id |
444 | * 2. 9122S and 9134D both return same HW id | | 444 | * 2. 9122S and 9134D both return same HW id |
445 | * 3. 9122D and 9134L both return same HW id | | 445 | * 3. 9122D and 9134L both return same HW id |
446 | */ | | 446 | */ |
447 | switch (ha->ha_id) { | | 447 | switch (ha->ha_id) { |
448 | case RD7946AID: | | 448 | case RD7946AID: |
449 | if (memcmp(name, "079450", 6) == 0) | | 449 | if (memcmp(name, "079450", 6) == 0) |
450 | id = RD7945A; | | 450 | id = RD7945A; |
451 | else | | 451 | else |
452 | id = RD7946A; | | 452 | id = RD7946A; |
453 | break; | | 453 | break; |
454 | | | 454 | |
455 | case RD9134LID: | | 455 | case RD9134LID: |
456 | if (memcmp(name, "091340", 6) == 0) | | 456 | if (memcmp(name, "091340", 6) == 0) |
457 | id = RD9134L; | | 457 | id = RD9134L; |
458 | else | | 458 | else |
459 | id = RD9122D; | | 459 | id = RD9122D; |
460 | break; | | 460 | break; |
461 | | | 461 | |
462 | case RD9134DID: | | 462 | case RD9134DID: |
463 | if (memcmp(name, "091220", 6) == 0) | | 463 | if (memcmp(name, "091220", 6) == 0) |
464 | id = RD9122S; | | 464 | id = RD9122S; |
465 | else | | 465 | else |
466 | id = RD9134D; | | 466 | id = RD9134D; |
467 | break; | | 467 | break; |
468 | } | | 468 | } |
469 | | | 469 | |
470 | sc->sc_type = id; | | 470 | sc->sc_type = id; |
471 | | | 471 | |
472 | /* | | 472 | /* |
473 | * XXX We use DEV_BSIZE instead of the sector size value pulled | | 473 | * XXX We use DEV_BSIZE instead of the sector size value pulled |
474 | * XXX off the driver because all of this code assumes 512 byte | | 474 | * XXX off the driver because all of this code assumes 512 byte |
475 | * XXX blocks. ICK! | | 475 | * XXX blocks. ICK! |
476 | */ | | 476 | */ |
477 | aprint_normal(": %s\n", rdidentinfo[id].ri_desc); | | 477 | aprint_normal(": %s\n", rdidentinfo[id].ri_desc); |
478 | aprint_normal_dev(sc->sc_dev, "%d cylinders, %d heads, %d blocks," | | 478 | aprint_normal_dev(sc->sc_dev, "%d cylinders, %d heads, %d blocks," |
479 | " %d bytes/block\n", | | 479 | " %d bytes/block\n", |
480 | rdidentinfo[id].ri_ncyl, | | 480 | rdidentinfo[id].ri_ncyl, |
481 | rdidentinfo[id].ri_ntpc, rdidentinfo[id].ri_nblocks, | | 481 | rdidentinfo[id].ri_ntpc, rdidentinfo[id].ri_nblocks, |
482 | DEV_BSIZE); | | 482 | DEV_BSIZE); |
483 | | | 483 | |
484 | return 1; | | 484 | return 1; |
485 | } | | 485 | } |
486 | | | 486 | |
487 | static void | | 487 | static void |
488 | rdreset(struct rd_softc *sc) | | 488 | rdreset(struct rd_softc *sc) |
489 | { | | 489 | { |
490 | int ctlr = device_unit(device_parent(sc->sc_dev)); | | 490 | int ctlr = device_unit(device_parent(sc->sc_dev)); |
491 | int slave = sc->sc_slave; | | 491 | int slave = sc->sc_slave; |
492 | u_char stat; | | 492 | u_char stat; |
493 | | | 493 | |
494 | sc->sc_clear.c_unit = C_SUNIT(sc->sc_punit); | | 494 | sc->sc_clear.c_unit = C_SUNIT(sc->sc_punit); |
495 | sc->sc_clear.c_cmd = C_CLEAR; | | 495 | sc->sc_clear.c_cmd = C_CLEAR; |
496 | hpibsend(ctlr, slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear)); | | 496 | hpibsend(ctlr, slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear)); |
497 | hpibswait(ctlr, slave); | | 497 | hpibswait(ctlr, slave); |
498 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); | | 498 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); |
499 | | | 499 | |
500 | sc->sc_src.c_unit = C_SUNIT(RDCTLR); | | 500 | sc->sc_src.c_unit = C_SUNIT(RDCTLR); |
501 | sc->sc_src.c_nop = C_NOP; | | 501 | sc->sc_src.c_nop = C_NOP; |
502 | sc->sc_src.c_cmd = C_SREL; | | 502 | sc->sc_src.c_cmd = C_SREL; |
503 | sc->sc_src.c_param = C_REL; | | 503 | sc->sc_src.c_param = C_REL; |
504 | hpibsend(ctlr, slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src)); | | 504 | hpibsend(ctlr, slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src)); |
505 | hpibswait(ctlr, slave); | | 505 | hpibswait(ctlr, slave); |
506 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); | | 506 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); |
507 | | | 507 | |
508 | sc->sc_ssmc.c_unit = C_SUNIT(sc->sc_punit); | | 508 | sc->sc_ssmc.c_unit = C_SUNIT(sc->sc_punit); |
509 | sc->sc_ssmc.c_cmd = C_SSM; | | 509 | sc->sc_ssmc.c_cmd = C_SSM; |
510 | sc->sc_ssmc.c_refm = REF_MASK; | | 510 | sc->sc_ssmc.c_refm = REF_MASK; |
511 | sc->sc_ssmc.c_fefm = FEF_MASK; | | 511 | sc->sc_ssmc.c_fefm = FEF_MASK; |
512 | sc->sc_ssmc.c_aefm = AEF_MASK; | | 512 | sc->sc_ssmc.c_aefm = AEF_MASK; |
513 | sc->sc_ssmc.c_iefm = IEF_MASK; | | 513 | sc->sc_ssmc.c_iefm = IEF_MASK; |
514 | hpibsend(ctlr, slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc)); | | 514 | hpibsend(ctlr, slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc)); |
515 | hpibswait(ctlr, slave); | | 515 | hpibswait(ctlr, slave); |
516 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); | | 516 | hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); |
517 | #ifdef DEBUG | | 517 | #ifdef DEBUG |
518 | sc->sc_stats.rdresets++; | | 518 | sc->sc_stats.rdresets++; |
519 | #endif | | 519 | #endif |
520 | } | | 520 | } |
521 | | | 521 | |
522 | /* | | 522 | /* |
523 | * Read or construct a disklabel | | 523 | * Read or construct a disklabel |
524 | */ | | 524 | */ |
525 | static int | | 525 | static int |
526 | rdgetinfo(dev_t dev) | | 526 | rdgetinfo(dev_t dev) |
527 | { | | 527 | { |
528 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(dev)); | | 528 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(dev)); |
529 | struct disklabel *lp = sc->sc_dkdev.dk_label; | | 529 | struct disklabel *lp = sc->sc_dkdev.dk_label; |
530 | struct partition *pi; | | 530 | struct partition *pi; |
531 | const char *msg; | | 531 | const char *msg; |
532 | | | 532 | |
533 | /* | | 533 | /* |
534 | * Set some default values to use while reading the label | | 534 | * Set some default values to use while reading the label |
535 | * or to use if there isn't a label. | | 535 | * or to use if there isn't a label. |
536 | */ | | 536 | */ |
537 | memset((void *)lp, 0, sizeof *lp); | | 537 | memset((void *)lp, 0, sizeof *lp); |
538 | rdgetdefaultlabel(sc, lp); | | 538 | rdgetdefaultlabel(sc, lp); |
539 | | | 539 | |
540 | /* | | 540 | /* |
541 | * Now try to read the disklabel | | 541 | * Now try to read the disklabel |
542 | */ | | 542 | */ |
543 | msg = readdisklabel(rdlabdev(dev), rdstrategy, lp, NULL); | | 543 | msg = readdisklabel(rdlabdev(dev), rdstrategy, lp, NULL); |
544 | if (msg == NULL) | | 544 | if (msg == NULL) |
545 | return 0; | | 545 | return 0; |
546 | | | 546 | |
547 | pi = lp->d_partitions; | | 547 | pi = lp->d_partitions; |
548 | printf("%s: WARNING: %s\n", device_xname(sc->sc_dev), msg); | | 548 | printf("%s: WARNING: %s\n", device_xname(sc->sc_dev), msg); |
549 | | | 549 | |
550 | pi[2].p_size = rdidentinfo[sc->sc_type].ri_nblocks; | | 550 | pi[2].p_size = rdidentinfo[sc->sc_type].ri_nblocks; |
551 | /* XXX reset other info since readdisklabel screws with it */ | | 551 | /* XXX reset other info since readdisklabel screws with it */ |
552 | lp->d_npartitions = 3; | | 552 | lp->d_npartitions = 3; |
553 | pi[0].p_size = 0; | | 553 | pi[0].p_size = 0; |
554 | | | 554 | |
555 | return 0; | | 555 | return 0; |
556 | } | | 556 | } |
557 | | | 557 | |
558 | static int | | 558 | static int |
559 | rdopen(dev_t dev, int flags, int mode, struct lwp *l) | | 559 | rdopen(dev_t dev, int flags, int mode, struct lwp *l) |
560 | { | | 560 | { |
561 | struct rd_softc *sc; | | 561 | struct rd_softc *sc; |
562 | int error, mask, part; | | 562 | int error, mask, part; |
563 | | | 563 | |
564 | sc = device_lookup_private(&rd_cd, rdunit(dev)); | | 564 | sc = device_lookup_private(&rd_cd, rdunit(dev)); |
565 | if (sc == NULL) | | 565 | if (sc == NULL) |
566 | return ENXIO; | | 566 | return ENXIO; |
567 | | | 567 | |
568 | if ((sc->sc_flags & RDF_ALIVE) == 0) | | 568 | if ((sc->sc_flags & RDF_ALIVE) == 0) |
569 | return ENXIO; | | 569 | return ENXIO; |
570 | | | 570 | |
571 | /* | | 571 | /* |
572 | * Wait for any pending opens/closes to complete | | 572 | * Wait for any pending opens/closes to complete |
573 | */ | | 573 | */ |
574 | while (sc->sc_flags & (RDF_OPENING|RDF_CLOSING)) | | 574 | while (sc->sc_flags & (RDF_OPENING|RDF_CLOSING)) |
575 | (void) tsleep(sc, PRIBIO, "rdopen", 0); | | 575 | (void) tsleep(sc, PRIBIO, "rdopen", 0); |
576 | | | 576 | |
577 | /* | | 577 | /* |
578 | * On first open, get label and partition info. | | 578 | * On first open, get label and partition info. |
579 | * We may block reading the label, so be careful | | 579 | * We may block reading the label, so be careful |
580 | * to stop any other opens. | | 580 | * to stop any other opens. |
581 | */ | | 581 | */ |
582 | if (sc->sc_dkdev.dk_openmask == 0) { | | 582 | if (sc->sc_dkdev.dk_openmask == 0) { |
583 | sc->sc_flags |= RDF_OPENING; | | 583 | sc->sc_flags |= RDF_OPENING; |
584 | error = rdgetinfo(dev); | | 584 | error = rdgetinfo(dev); |
585 | sc->sc_flags &= ~RDF_OPENING; | | 585 | sc->sc_flags &= ~RDF_OPENING; |
586 | wakeup((void *)sc); | | 586 | wakeup((void *)sc); |
587 | if (error) | | 587 | if (error) |
588 | return error; | | 588 | return error; |
589 | } | | 589 | } |
590 | | | 590 | |
591 | part = rdpart(dev); | | 591 | part = rdpart(dev); |
592 | mask = 1 << part; | | 592 | mask = 1 << part; |
593 | | | 593 | |
594 | /* Check that the partition exists. */ | | 594 | /* Check that the partition exists. */ |
595 | if (part != RAW_PART && | | 595 | if (part != RAW_PART && |
596 | (part > sc->sc_dkdev.dk_label->d_npartitions || | | 596 | (part > sc->sc_dkdev.dk_label->d_npartitions || |
597 | sc->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) | | 597 | sc->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) |
598 | return ENXIO; | | 598 | return ENXIO; |
599 | | | 599 | |
600 | /* Ensure only one open at a time. */ | | 600 | /* Ensure only one open at a time. */ |
601 | switch (mode) { | | 601 | switch (mode) { |
602 | case S_IFCHR: | | 602 | case S_IFCHR: |
603 | sc->sc_dkdev.dk_copenmask |= mask; | | 603 | sc->sc_dkdev.dk_copenmask |= mask; |
604 | break; | | 604 | break; |
605 | case S_IFBLK: | | 605 | case S_IFBLK: |
606 | sc->sc_dkdev.dk_bopenmask |= mask; | | 606 | sc->sc_dkdev.dk_bopenmask |= mask; |
607 | break; | | 607 | break; |
608 | } | | 608 | } |
609 | sc->sc_dkdev.dk_openmask = | | 609 | sc->sc_dkdev.dk_openmask = |
610 | sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask; | | 610 | sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask; |
611 | | | 611 | |
612 | return 0; | | 612 | return 0; |
613 | } | | 613 | } |
614 | | | 614 | |
615 | static int | | 615 | static int |
616 | rdclose(dev_t dev, int flag, int mode, struct lwp *l) | | 616 | rdclose(dev_t dev, int flag, int mode, struct lwp *l) |
617 | { | | 617 | { |
618 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(dev)); | | 618 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(dev)); |
619 | struct disk *dk = &sc->sc_dkdev; | | 619 | struct disk *dk = &sc->sc_dkdev; |
620 | int mask, s; | | 620 | int mask, s; |
621 | | | 621 | |
622 | mask = 1 << rdpart(dev); | | 622 | mask = 1 << rdpart(dev); |
623 | if (mode == S_IFCHR) | | 623 | if (mode == S_IFCHR) |
624 | dk->dk_copenmask &= ~mask; | | 624 | dk->dk_copenmask &= ~mask; |
625 | else | | 625 | else |
626 | dk->dk_bopenmask &= ~mask; | | 626 | dk->dk_bopenmask &= ~mask; |
627 | dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; | | 627 | dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; |
628 | /* | | 628 | /* |
629 | * On last close, we wait for all activity to cease since | | 629 | * On last close, we wait for all activity to cease since |
630 | * the label/parition info will become invalid. Since we | | 630 | * the label/parition info will become invalid. Since we |
631 | * might sleep, we must block any opens while we are here. | | 631 | * might sleep, we must block any opens while we are here. |
632 | * Note we don't have to about other closes since we know | | 632 | * Note we don't have to about other closes since we know |
633 | * we are the last one. | | 633 | * we are the last one. |
634 | */ | | 634 | */ |
635 | if (dk->dk_openmask == 0) { | | 635 | if (dk->dk_openmask == 0) { |
636 | sc->sc_flags |= RDF_CLOSING; | | 636 | sc->sc_flags |= RDF_CLOSING; |
637 | s = splbio(); | | 637 | s = splbio(); |
638 | while (sc->sc_active) { | | 638 | while (sc->sc_active) { |
639 | sc->sc_flags |= RDF_WANTED; | | 639 | sc->sc_flags |= RDF_WANTED; |
640 | (void) tsleep(&sc->sc_tab, PRIBIO, "rdclose", 0); | | 640 | (void) tsleep(&sc->sc_tab, PRIBIO, "rdclose", 0); |
641 | } | | 641 | } |
642 | splx(s); | | 642 | splx(s); |
643 | sc->sc_flags &= ~(RDF_CLOSING|RDF_WLABEL); | | 643 | sc->sc_flags &= ~(RDF_CLOSING|RDF_WLABEL); |
644 | wakeup((void *)sc); | | 644 | wakeup((void *)sc); |
645 | } | | 645 | } |
646 | return 0; | | 646 | return 0; |
647 | } | | 647 | } |
648 | | | 648 | |
649 | static void | | 649 | static void |
650 | rdstrategy(struct buf *bp) | | 650 | rdstrategy(struct buf *bp) |
651 | { | | 651 | { |
652 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(bp->b_dev)); | | 652 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(bp->b_dev)); |
653 | struct partition *pinfo; | | 653 | struct partition *pinfo; |
654 | daddr_t bn; | | 654 | daddr_t bn; |
655 | int sz, s; | | 655 | int sz, s; |
656 | int offset; | | 656 | int offset; |
657 | | | 657 | |
658 | #ifdef DEBUG | | 658 | #ifdef DEBUG |
659 | if (rddebug & RDB_FOLLOW) | | 659 | if (rddebug & RDB_FOLLOW) |
660 | printf("rdstrategy(%p): dev %x, bn %llx, bcount %x, %c\n", | | 660 | printf("rdstrategy(%p): dev %"PRIx64", bn %llx, bcount %x, %c\n", |
661 | bp, bp->b_dev, bp->b_blkno, bp->b_bcount, | | 661 | bp, bp->b_dev, bp->b_blkno, bp->b_bcount, |
662 | (bp->b_flags & B_READ) ? 'R' : 'W'); | | 662 | (bp->b_flags & B_READ) ? 'R' : 'W'); |
663 | #endif | | 663 | #endif |
664 | bn = bp->b_blkno; | | 664 | bn = bp->b_blkno; |
665 | sz = howmany(bp->b_bcount, DEV_BSIZE); | | 665 | sz = howmany(bp->b_bcount, DEV_BSIZE); |
666 | pinfo = &sc->sc_dkdev.dk_label->d_partitions[rdpart(bp->b_dev)]; | | 666 | pinfo = &sc->sc_dkdev.dk_label->d_partitions[rdpart(bp->b_dev)]; |
667 | | | 667 | |
668 | /* Don't perform partition translation on RAW_PART. */ | | 668 | /* Don't perform partition translation on RAW_PART. */ |
669 | offset = (rdpart(bp->b_dev) == RAW_PART) ? 0 : pinfo->p_offset; | | 669 | offset = (rdpart(bp->b_dev) == RAW_PART) ? 0 : pinfo->p_offset; |
670 | | | 670 | |
671 | if (rdpart(bp->b_dev) != RAW_PART) { | | 671 | if (rdpart(bp->b_dev) != RAW_PART) { |
672 | /* | | 672 | /* |
673 | * XXX This block of code belongs in | | 673 | * XXX This block of code belongs in |
674 | * XXX bounds_check_with_label() | | 674 | * XXX bounds_check_with_label() |
675 | */ | | 675 | */ |
676 | | | 676 | |
677 | if (bn < 0 || bn + sz > pinfo->p_size) { | | 677 | if (bn < 0 || bn + sz > pinfo->p_size) { |
678 | sz = pinfo->p_size - bn; | | 678 | sz = pinfo->p_size - bn; |
679 | if (sz == 0) { | | 679 | if (sz == 0) { |
680 | bp->b_resid = bp->b_bcount; | | 680 | bp->b_resid = bp->b_bcount; |
681 | goto done; | | 681 | goto done; |
682 | } | | 682 | } |
683 | if (sz < 0) { | | 683 | if (sz < 0) { |
684 | bp->b_error = EINVAL; | | 684 | bp->b_error = EINVAL; |
685 | goto done; | | 685 | goto done; |
686 | } | | 686 | } |
687 | bp->b_bcount = dbtob(sz); | | 687 | bp->b_bcount = dbtob(sz); |
688 | } | | 688 | } |
689 | /* | | 689 | /* |
690 | * Check for write to write protected label | | 690 | * Check for write to write protected label |
691 | */ | | 691 | */ |
692 | if (bn + offset <= LABELSECTOR && | | 692 | if (bn + offset <= LABELSECTOR && |
693 | #if LABELSECTOR != 0 | | 693 | #if LABELSECTOR != 0 |
694 | bn + offset + sz > LABELSECTOR && | | 694 | bn + offset + sz > LABELSECTOR && |
695 | #endif | | 695 | #endif |
696 | !(bp->b_flags & B_READ) && !(sc->sc_flags & RDF_WLABEL)) { | | 696 | !(bp->b_flags & B_READ) && !(sc->sc_flags & RDF_WLABEL)) { |
697 | bp->b_error = EROFS; | | 697 | bp->b_error = EROFS; |
698 | goto done; | | 698 | goto done; |
699 | } | | 699 | } |
700 | } | | 700 | } |
701 | bp->b_rawblkno = bn + offset; | | 701 | bp->b_rawblkno = bn + offset; |
702 | s = splbio(); | | 702 | s = splbio(); |
703 | bufq_put(sc->sc_tab, bp); | | 703 | bufq_put(sc->sc_tab, bp); |
704 | if (sc->sc_active == 0) { | | 704 | if (sc->sc_active == 0) { |
705 | sc->sc_active = 1; | | 705 | sc->sc_active = 1; |
706 | rdustart(sc); | | 706 | rdustart(sc); |
707 | } | | 707 | } |
708 | splx(s); | | 708 | splx(s); |
709 | return; | | 709 | return; |
710 | done: | | 710 | done: |
711 | biodone(bp); | | 711 | biodone(bp); |
712 | } | | 712 | } |
713 | | | 713 | |
714 | /* | | 714 | /* |
715 | * Called from timeout() when handling maintenance releases | | 715 | * Called from timeout() when handling maintenance releases |
716 | */ | | 716 | */ |
717 | static void | | 717 | static void |
718 | rdrestart(void *arg) | | 718 | rdrestart(void *arg) |
719 | { | | 719 | { |
720 | int s = splbio(); | | 720 | int s = splbio(); |
721 | rdustart((struct rd_softc *)arg); | | 721 | rdustart((struct rd_softc *)arg); |
722 | splx(s); | | 722 | splx(s); |
723 | } | | 723 | } |
724 | | | 724 | |
725 | static void | | 725 | static void |
726 | rdustart(struct rd_softc *sc) | | 726 | rdustart(struct rd_softc *sc) |
727 | { | | 727 | { |
728 | struct buf *bp; | | 728 | struct buf *bp; |
729 | | | 729 | |
730 | bp = bufq_peek(sc->sc_tab); | | 730 | bp = bufq_peek(sc->sc_tab); |
731 | sc->sc_addr = bp->b_data; | | 731 | sc->sc_addr = bp->b_data; |
732 | sc->sc_resid = bp->b_bcount; | | 732 | sc->sc_resid = bp->b_bcount; |
733 | if (hpibreq(device_parent(sc->sc_dev), &sc->sc_hq)) | | 733 | if (hpibreq(device_parent(sc->sc_dev), &sc->sc_hq)) |
734 | rdstart(sc); | | 734 | rdstart(sc); |
735 | } | | 735 | } |
736 | | | 736 | |
737 | static struct buf * | | 737 | static struct buf * |
738 | rdfinish(struct rd_softc *sc, struct buf *bp) | | 738 | rdfinish(struct rd_softc *sc, struct buf *bp) |
739 | { | | 739 | { |
740 | | | 740 | |
741 | sc->sc_errcnt = 0; | | 741 | sc->sc_errcnt = 0; |
742 | (void)bufq_get(sc->sc_tab); | | 742 | (void)bufq_get(sc->sc_tab); |
743 | bp->b_resid = 0; | | 743 | bp->b_resid = 0; |
744 | biodone(bp); | | 744 | biodone(bp); |
745 | hpibfree(device_parent(sc->sc_dev), &sc->sc_hq); | | 745 | hpibfree(device_parent(sc->sc_dev), &sc->sc_hq); |
746 | if ((bp = bufq_peek(sc->sc_tab)) != NULL) | | 746 | if ((bp = bufq_peek(sc->sc_tab)) != NULL) |
747 | return bp; | | 747 | return bp; |
748 | sc->sc_active = 0; | | 748 | sc->sc_active = 0; |
749 | if (sc->sc_flags & RDF_WANTED) { | | 749 | if (sc->sc_flags & RDF_WANTED) { |
750 | sc->sc_flags &= ~RDF_WANTED; | | 750 | sc->sc_flags &= ~RDF_WANTED; |
751 | wakeup((void *)&sc->sc_tab); | | 751 | wakeup((void *)&sc->sc_tab); |
752 | } | | 752 | } |
753 | return NULL; | | 753 | return NULL; |
754 | } | | 754 | } |
755 | | | 755 | |
756 | static void | | 756 | static void |
757 | rdstart(void *arg) | | 757 | rdstart(void *arg) |
758 | { | | 758 | { |
759 | struct rd_softc *sc = arg; | | 759 | struct rd_softc *sc = arg; |
760 | struct buf *bp = bufq_peek(sc->sc_tab); | | 760 | struct buf *bp = bufq_peek(sc->sc_tab); |
761 | int part, ctlr, slave; | | 761 | int part, ctlr, slave; |
762 | | | 762 | |
763 | ctlr = device_unit(device_parent(sc->sc_dev)); | | 763 | ctlr = device_unit(device_parent(sc->sc_dev)); |
764 | slave = sc->sc_slave; | | 764 | slave = sc->sc_slave; |
765 | | | 765 | |
766 | again: | | 766 | again: |
767 | #ifdef DEBUG | | 767 | #ifdef DEBUG |
768 | if (rddebug & RDB_FOLLOW) | | 768 | if (rddebug & RDB_FOLLOW) |
769 | printf("rdstart(%s): bp %p, %c\n", device_xname(sc->sc_dev), bp, | | 769 | printf("rdstart(%s): bp %p, %c\n", device_xname(sc->sc_dev), bp, |
770 | (bp->b_flags & B_READ) ? 'R' : 'W'); | | 770 | (bp->b_flags & B_READ) ? 'R' : 'W'); |
771 | #endif | | 771 | #endif |
772 | part = rdpart(bp->b_dev); | | 772 | part = rdpart(bp->b_dev); |
773 | sc->sc_flags |= RDF_SEEK; | | 773 | sc->sc_flags |= RDF_SEEK; |
774 | sc->sc_ioc.c_unit = C_SUNIT(sc->sc_punit); | | 774 | sc->sc_ioc.c_unit = C_SUNIT(sc->sc_punit); |
775 | sc->sc_ioc.c_volume = C_SVOL(0); | | 775 | sc->sc_ioc.c_volume = C_SVOL(0); |
776 | sc->sc_ioc.c_saddr = C_SADDR; | | 776 | sc->sc_ioc.c_saddr = C_SADDR; |
777 | sc->sc_ioc.c_hiaddr = 0; | | 777 | sc->sc_ioc.c_hiaddr = 0; |
778 | sc->sc_ioc.c_addr = RDBTOS(bp->b_rawblkno); | | 778 | sc->sc_ioc.c_addr = RDBTOS(bp->b_rawblkno); |
779 | sc->sc_ioc.c_nop2 = C_NOP; | | 779 | sc->sc_ioc.c_nop2 = C_NOP; |
780 | sc->sc_ioc.c_slen = C_SLEN; | | 780 | sc->sc_ioc.c_slen = C_SLEN; |
781 | sc->sc_ioc.c_len = sc->sc_resid; | | 781 | sc->sc_ioc.c_len = sc->sc_resid; |
782 | sc->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE; | | 782 | sc->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE; |
783 | #ifdef DEBUG | | 783 | #ifdef DEBUG |
784 | if (rddebug & RDB_IO) | | 784 | if (rddebug & RDB_IO) |
785 | printf("rdstart: hpibsend(%x, %x, %x, %p, %x)\n", | | 785 | printf("rdstart: hpibsend(%x, %x, %x, %p, %x)\n", |
786 | ctlr, slave, C_CMD, | | 786 | ctlr, slave, C_CMD, |
787 | &sc->sc_ioc.c_unit, sizeof(sc->sc_ioc) - 2); | | 787 | &sc->sc_ioc.c_unit, sizeof(sc->sc_ioc) - 2); |
788 | #endif | | 788 | #endif |
789 | if (hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc.c_unit, | | 789 | if (hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc.c_unit, |
790 | sizeof(sc->sc_ioc) - 2) == sizeof(sc->sc_ioc) - 2) { | | 790 | sizeof(sc->sc_ioc) - 2) == sizeof(sc->sc_ioc) - 2) { |
791 | | | 791 | |
792 | /* Instrumentation. */ | | 792 | /* Instrumentation. */ |
793 | disk_busy(&sc->sc_dkdev); | | 793 | disk_busy(&sc->sc_dkdev); |
794 | iostat_seek(sc->sc_dkdev.dk_stats); | | 794 | iostat_seek(sc->sc_dkdev.dk_stats); |
795 | | | 795 | |
796 | #ifdef DEBUG | | 796 | #ifdef DEBUG |
797 | if (rddebug & RDB_IO) | | 797 | if (rddebug & RDB_IO) |
798 | printf("rdstart: hpibawait(%x)\n", ctlr); | | 798 | printf("rdstart: hpibawait(%x)\n", ctlr); |
799 | #endif | | 799 | #endif |
800 | hpibawait(ctlr); | | 800 | hpibawait(ctlr); |
801 | return; | | 801 | return; |
802 | } | | 802 | } |
803 | /* | | 803 | /* |
804 | * Experience has shown that the hpibwait in this hpibsend will | | 804 | * Experience has shown that the hpibwait in this hpibsend will |
805 | * occasionally timeout. It appears to occur mostly on old 7914 | | 805 | * occasionally timeout. It appears to occur mostly on old 7914 |
806 | * drives with full maintenance tracks. We should probably | | 806 | * drives with full maintenance tracks. We should probably |
807 | * integrate this with the backoff code in rderror. | | 807 | * integrate this with the backoff code in rderror. |
808 | */ | | 808 | */ |
809 | #ifdef DEBUG | | 809 | #ifdef DEBUG |
810 | if (rddebug & RDB_ERROR) | | 810 | if (rddebug & RDB_ERROR) |
811 | printf("%s: rdstart: cmd %x adr %lx blk %lld len %d ecnt %d\n", | | 811 | printf("%s: rdstart: cmd %x adr %lx blk %lld len %d ecnt %d\n", |
812 | device_xname(sc->sc_dev), | | 812 | device_xname(sc->sc_dev), |
813 | sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, | | 813 | sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, |
814 | bp->b_blkno, sc->sc_resid, sc->sc_errcnt); | | 814 | bp->b_blkno, sc->sc_resid, sc->sc_errcnt); |
815 | sc->sc_stats.rdretries++; | | 815 | sc->sc_stats.rdretries++; |
816 | #endif | | 816 | #endif |
817 | sc->sc_flags &= ~RDF_SEEK; | | 817 | sc->sc_flags &= ~RDF_SEEK; |
818 | rdreset(sc); | | 818 | rdreset(sc); |
819 | if (sc->sc_errcnt++ < RDRETRY) | | 819 | if (sc->sc_errcnt++ < RDRETRY) |
820 | goto again; | | 820 | goto again; |
821 | printf("%s: rdstart err: cmd 0x%x sect %ld blk %" PRId64 " len %d\n", | | 821 | printf("%s: rdstart err: cmd 0x%x sect %ld blk %" PRId64 " len %d\n", |
822 | device_xname(sc->sc_dev), sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, | | 822 | device_xname(sc->sc_dev), sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, |
823 | bp->b_blkno, sc->sc_resid); | | 823 | bp->b_blkno, sc->sc_resid); |
824 | bp->b_error = EIO; | | 824 | bp->b_error = EIO; |
825 | bp = rdfinish(sc, bp); | | 825 | bp = rdfinish(sc, bp); |
826 | if (bp) { | | 826 | if (bp) { |
827 | sc->sc_addr = bp->b_data; | | 827 | sc->sc_addr = bp->b_data; |
828 | sc->sc_resid = bp->b_bcount; | | 828 | sc->sc_resid = bp->b_bcount; |
829 | if (hpibreq(device_parent(sc->sc_dev), &sc->sc_hq)) | | 829 | if (hpibreq(device_parent(sc->sc_dev), &sc->sc_hq)) |
830 | goto again; | | 830 | goto again; |
831 | } | | 831 | } |
832 | } | | 832 | } |
833 | | | 833 | |
834 | static void | | 834 | static void |
835 | rdgo(void *arg) | | 835 | rdgo(void *arg) |
836 | { | | 836 | { |
837 | struct rd_softc *sc = arg; | | 837 | struct rd_softc *sc = arg; |
838 | struct buf *bp = bufq_peek(sc->sc_tab); | | 838 | struct buf *bp = bufq_peek(sc->sc_tab); |
839 | int rw, ctlr, slave; | | 839 | int rw, ctlr, slave; |
840 | | | 840 | |
841 | ctlr = device_unit(device_parent(sc->sc_dev)); | | 841 | ctlr = device_unit(device_parent(sc->sc_dev)); |
842 | slave = sc->sc_slave; | | 842 | slave = sc->sc_slave; |
843 | | | 843 | |
844 | rw = bp->b_flags & B_READ; | | 844 | rw = bp->b_flags & B_READ; |
845 | | | 845 | |
846 | /* Instrumentation. */ | | 846 | /* Instrumentation. */ |
847 | disk_busy(&sc->sc_dkdev); | | 847 | disk_busy(&sc->sc_dkdev); |
848 | | | 848 | |
849 | #ifdef USELEDS | | 849 | #ifdef USELEDS |
850 | ledcontrol(0, 0, LED_DISK); | | 850 | ledcontrol(0, 0, LED_DISK); |
851 | #endif | | 851 | #endif |
852 | hpibgo(ctlr, slave, C_EXEC, sc->sc_addr, sc->sc_resid, rw, rw != 0); | | 852 | hpibgo(ctlr, slave, C_EXEC, sc->sc_addr, sc->sc_resid, rw, rw != 0); |
853 | } | | 853 | } |
854 | | | 854 | |
855 | /* ARGSUSED */ | | 855 | /* ARGSUSED */ |
856 | static void | | 856 | static void |
857 | rdintr(void *arg) | | 857 | rdintr(void *arg) |
858 | { | | 858 | { |
859 | struct rd_softc *sc = arg; | | 859 | struct rd_softc *sc = arg; |
860 | int unit = device_unit(sc->sc_dev); | | 860 | int unit = device_unit(sc->sc_dev); |
861 | struct buf *bp = bufq_peek(sc->sc_tab); | | 861 | struct buf *bp = bufq_peek(sc->sc_tab); |
862 | u_char stat = 13; /* in case hpibrecv fails */ | | 862 | u_char stat = 13; /* in case hpibrecv fails */ |
863 | int rv, restart, ctlr, slave; | | 863 | int rv, restart, ctlr, slave; |
864 | | | 864 | |
865 | ctlr = device_unit(device_parent(sc->sc_dev)); | | 865 | ctlr = device_unit(device_parent(sc->sc_dev)); |
866 | slave = sc->sc_slave; | | 866 | slave = sc->sc_slave; |
867 | | | 867 | |
868 | #ifdef DEBUG | | 868 | #ifdef DEBUG |
869 | if (rddebug & RDB_FOLLOW) | | 869 | if (rddebug & RDB_FOLLOW) |
870 | printf("rdintr(%d): bp %p, %c, flags %x\n", unit, bp, | | 870 | printf("rdintr(%d): bp %p, %c, flags %x\n", unit, bp, |
871 | (bp->b_flags & B_READ) ? 'R' : 'W', sc->sc_flags); | | 871 | (bp->b_flags & B_READ) ? 'R' : 'W', sc->sc_flags); |
872 | if (bp == NULL) { | | 872 | if (bp == NULL) { |
873 | printf("%s: bp == NULL\n", device_xname(sc->sc_dev)); | | 873 | printf("%s: bp == NULL\n", device_xname(sc->sc_dev)); |
874 | return; | | 874 | return; |
875 | } | | 875 | } |
876 | #endif | | 876 | #endif |
877 | disk_unbusy(&sc->sc_dkdev, (bp->b_bcount - bp->b_resid), | | 877 | disk_unbusy(&sc->sc_dkdev, (bp->b_bcount - bp->b_resid), |
878 | (bp->b_flags & B_READ)); | | 878 | (bp->b_flags & B_READ)); |
879 | | | 879 | |
880 | if (sc->sc_flags & RDF_SEEK) { | | 880 | if (sc->sc_flags & RDF_SEEK) { |
881 | sc->sc_flags &= ~RDF_SEEK; | | 881 | sc->sc_flags &= ~RDF_SEEK; |
882 | if (hpibustart(ctlr)) | | 882 | if (hpibustart(ctlr)) |
883 | rdgo(sc); | | 883 | rdgo(sc); |
884 | return; | | 884 | return; |
885 | } | | 885 | } |
886 | if ((sc->sc_flags & RDF_SWAIT) == 0) { | | 886 | if ((sc->sc_flags & RDF_SWAIT) == 0) { |
887 | #ifdef DEBUG | | 887 | #ifdef DEBUG |
888 | sc->sc_stats.rdpolltries++; | | 888 | sc->sc_stats.rdpolltries++; |
889 | #endif | | 889 | #endif |
890 | if (hpibpptest(ctlr, slave) == 0) { | | 890 | if (hpibpptest(ctlr, slave) == 0) { |
891 | #ifdef DEBUG | | 891 | #ifdef DEBUG |
892 | sc->sc_stats.rdpollwaits++; | | 892 | sc->sc_stats.rdpollwaits++; |
893 | #endif | | 893 | #endif |
894 | | | 894 | |
895 | /* Instrumentation. */ | | 895 | /* Instrumentation. */ |
896 | disk_busy(&sc->sc_dkdev); | | 896 | disk_busy(&sc->sc_dkdev); |
897 | sc->sc_flags |= RDF_SWAIT; | | 897 | sc->sc_flags |= RDF_SWAIT; |
898 | hpibawait(ctlr); | | 898 | hpibawait(ctlr); |
899 | return; | | 899 | return; |
900 | } | | 900 | } |
901 | } else | | 901 | } else |
902 | sc->sc_flags &= ~RDF_SWAIT; | | 902 | sc->sc_flags &= ~RDF_SWAIT; |
903 | rv = hpibrecv(ctlr, slave, C_QSTAT, &stat, 1); | | 903 | rv = hpibrecv(ctlr, slave, C_QSTAT, &stat, 1); |
904 | if (rv != 1 || stat) { | | 904 | if (rv != 1 || stat) { |
905 | #ifdef DEBUG | | 905 | #ifdef DEBUG |
906 | if (rddebug & RDB_ERROR) | | 906 | if (rddebug & RDB_ERROR) |
907 | printf("rdintr: recv failed or bad stat %d\n", stat); | | 907 | printf("rdintr: recv failed or bad stat %d\n", stat); |
908 | #endif | | 908 | #endif |
909 | restart = rderror(unit); | | 909 | restart = rderror(unit); |
910 | #ifdef DEBUG | | 910 | #ifdef DEBUG |
911 | sc->sc_stats.rdretries++; | | 911 | sc->sc_stats.rdretries++; |
912 | #endif | | 912 | #endif |
913 | if (sc->sc_errcnt++ < RDRETRY) { | | 913 | if (sc->sc_errcnt++ < RDRETRY) { |
914 | if (restart) | | 914 | if (restart) |
915 | rdstart(sc); | | 915 | rdstart(sc); |
916 | return; | | 916 | return; |
917 | } | | 917 | } |
918 | bp->b_error = EIO; | | 918 | bp->b_error = EIO; |
919 | } | | 919 | } |
920 | if (rdfinish(sc, bp)) | | 920 | if (rdfinish(sc, bp)) |
921 | rdustart(sc); | | 921 | rdustart(sc); |
922 | #if NRND > 0 | | 922 | #if NRND > 0 |
923 | rnd_add_uint32(&sc->rnd_source, bp->b_blkno); | | 923 | rnd_add_uint32(&sc->rnd_source, bp->b_blkno); |
924 | #endif | | 924 | #endif |
925 | } | | 925 | } |
926 | | | 926 | |
927 | static int | | 927 | static int |
928 | rdstatus(struct rd_softc *sc) | | 928 | rdstatus(struct rd_softc *sc) |
929 | { | | 929 | { |
930 | int c, s; | | 930 | int c, s; |
931 | u_char stat; | | 931 | u_char stat; |
932 | int rv; | | 932 | int rv; |
933 | | | 933 | |
934 | c = device_unit(device_parent(sc->sc_dev)); | | 934 | c = device_unit(device_parent(sc->sc_dev)); |
935 | s = sc->sc_slave; | | 935 | s = sc->sc_slave; |
936 | sc->sc_rsc.c_unit = C_SUNIT(sc->sc_punit); | | 936 | sc->sc_rsc.c_unit = C_SUNIT(sc->sc_punit); |
937 | sc->sc_rsc.c_sram = C_SRAM; | | 937 | sc->sc_rsc.c_sram = C_SRAM; |
938 | sc->sc_rsc.c_ram = C_RAM; | | 938 | sc->sc_rsc.c_ram = C_RAM; |
939 | sc->sc_rsc.c_cmd = C_STATUS; | | 939 | sc->sc_rsc.c_cmd = C_STATUS; |
940 | memset((void *)&sc->sc_stat, 0, sizeof(sc->sc_stat)); | | 940 | memset((void *)&sc->sc_stat, 0, sizeof(sc->sc_stat)); |
941 | rv = hpibsend(c, s, C_CMD, &sc->sc_rsc, sizeof(sc->sc_rsc)); | | 941 | rv = hpibsend(c, s, C_CMD, &sc->sc_rsc, sizeof(sc->sc_rsc)); |
942 | if (rv != sizeof(sc->sc_rsc)) { | | 942 | if (rv != sizeof(sc->sc_rsc)) { |
943 | #ifdef DEBUG | | 943 | #ifdef DEBUG |
944 | if (rddebug & RDB_STATUS) | | 944 | if (rddebug & RDB_STATUS) |
945 | printf("rdstatus: send C_CMD failed %d != %d\n", | | 945 | printf("rdstatus: send C_CMD failed %d != %d\n", |
946 | rv, sizeof(sc->sc_rsc)); | | 946 | rv, sizeof(sc->sc_rsc)); |
947 | #endif | | 947 | #endif |
948 | return 1; | | 948 | return 1; |
949 | } | | 949 | } |
950 | rv = hpibrecv(c, s, C_EXEC, &sc->sc_stat, sizeof(sc->sc_stat)); | | 950 | rv = hpibrecv(c, s, C_EXEC, &sc->sc_stat, sizeof(sc->sc_stat)); |
951 | if (rv != sizeof(sc->sc_stat)) { | | 951 | if (rv != sizeof(sc->sc_stat)) { |
952 | #ifdef DEBUG | | 952 | #ifdef DEBUG |
953 | if (rddebug & RDB_STATUS) | | 953 | if (rddebug & RDB_STATUS) |
954 | printf("rdstatus: send C_EXEC failed %d != %d\n", | | 954 | printf("rdstatus: send C_EXEC failed %d != %d\n", |
955 | rv, sizeof(sc->sc_stat)); | | 955 | rv, sizeof(sc->sc_stat)); |
956 | #endif | | 956 | #endif |
957 | return 1; | | 957 | return 1; |
958 | } | | 958 | } |
959 | rv = hpibrecv(c, s, C_QSTAT, &stat, 1); | | 959 | rv = hpibrecv(c, s, C_QSTAT, &stat, 1); |
960 | if (rv != 1 || stat) { | | 960 | if (rv != 1 || stat) { |
961 | #ifdef DEBUG | | 961 | #ifdef DEBUG |
962 | if (rddebug & RDB_STATUS) | | 962 | if (rddebug & RDB_STATUS) |
963 | printf("rdstatus: recv failed %d or bad stat %d\n", | | 963 | printf("rdstatus: recv failed %d or bad stat %d\n", |
964 | rv, stat); | | 964 | rv, stat); |
965 | #endif | | 965 | #endif |
966 | return 1; | | 966 | return 1; |
967 | } | | 967 | } |
968 | return 0; | | 968 | return 0; |
969 | } | | 969 | } |
970 | | | 970 | |
971 | /* | | 971 | /* |
972 | * Deal with errors. | | 972 | * Deal with errors. |
973 | * Returns 1 if request should be restarted, | | 973 | * Returns 1 if request should be restarted, |
974 | * 0 if we should just quietly give up. | | 974 | * 0 if we should just quietly give up. |
975 | */ | | 975 | */ |
976 | static int | | 976 | static int |
977 | rderror(int unit) | | 977 | rderror(int unit) |
978 | { | | 978 | { |
979 | struct rd_softc *sc = device_lookup_private(&rd_cd,unit); | | 979 | struct rd_softc *sc = device_lookup_private(&rd_cd,unit); |
980 | struct rd_stat *sp; | | 980 | struct rd_stat *sp; |
981 | struct buf *bp; | | 981 | struct buf *bp; |
982 | daddr_t hwbn, pbn; | | 982 | daddr_t hwbn, pbn; |
983 | char *hexstr(int, int); /* XXX */ | | 983 | char *hexstr(int, int); /* XXX */ |
984 | | | 984 | |
985 | if (rdstatus(sc)) { | | 985 | if (rdstatus(sc)) { |
986 | #ifdef DEBUG | | 986 | #ifdef DEBUG |
987 | printf("%s: couldn't get status\n", device_xname(sc->sc_dev)); | | 987 | printf("%s: couldn't get status\n", device_xname(sc->sc_dev)); |
988 | #endif | | 988 | #endif |
989 | rdreset(sc); | | 989 | rdreset(sc); |
990 | return 1; | | 990 | return 1; |
991 | } | | 991 | } |
992 | sp = &sc->sc_stat; | | 992 | sp = &sc->sc_stat; |
993 | if (sp->c_fef & FEF_REXMT) | | 993 | if (sp->c_fef & FEF_REXMT) |
994 | return 1; | | 994 | return 1; |
995 | if (sp->c_fef & FEF_PF) { | | 995 | if (sp->c_fef & FEF_PF) { |
996 | rdreset(sc); | | 996 | rdreset(sc); |
997 | return 1; | | 997 | return 1; |
998 | } | | 998 | } |
999 | /* | | 999 | /* |
1000 | * Unit requests release for internal maintenance. | | 1000 | * Unit requests release for internal maintenance. |
1001 | * We just delay awhile and try again later. Use expontially | | 1001 | * We just delay awhile and try again later. Use expontially |
1002 | * increasing backoff ala ethernet drivers since we don't really | | 1002 | * increasing backoff ala ethernet drivers since we don't really |
1003 | * know how long the maintenance will take. With RDWAITC and | | 1003 | * know how long the maintenance will take. With RDWAITC and |
1004 | * RDRETRY as defined, the range is 1 to 32 seconds. | | 1004 | * RDRETRY as defined, the range is 1 to 32 seconds. |
1005 | */ | | 1005 | */ |
1006 | if (sp->c_fef & FEF_IMR) { | | 1006 | if (sp->c_fef & FEF_IMR) { |
1007 | extern int hz; | | 1007 | extern int hz; |
1008 | int rdtimo = RDWAITC << sc->sc_errcnt; | | 1008 | int rdtimo = RDWAITC << sc->sc_errcnt; |
1009 | #ifdef DEBUG | | 1009 | #ifdef DEBUG |
1010 | printf("%s: internal maintenance, %d second timeout\n", | | 1010 | printf("%s: internal maintenance, %d second timeout\n", |
1011 | device_xname(sc->sc_dev), rdtimo); | | 1011 | device_xname(sc->sc_dev), rdtimo); |
1012 | sc->sc_stats.rdtimeouts++; | | 1012 | sc->sc_stats.rdtimeouts++; |
1013 | #endif | | 1013 | #endif |
1014 | hpibfree(device_parent(sc->sc_dev), &sc->sc_hq); | | 1014 | hpibfree(device_parent(sc->sc_dev), &sc->sc_hq); |
1015 | callout_reset(&sc->sc_restart_ch, rdtimo * hz, rdrestart, sc); | | 1015 | callout_reset(&sc->sc_restart_ch, rdtimo * hz, rdrestart, sc); |
1016 | return 0; | | 1016 | return 0; |
1017 | } | | 1017 | } |
1018 | /* | | 1018 | /* |
1019 | * Only report error if we have reached the error reporting | | 1019 | * Only report error if we have reached the error reporting |
1020 | * threshhold. By default, this will only report after the | | 1020 | * threshhold. By default, this will only report after the |
1021 | * retry limit has been exceeded. | | 1021 | * retry limit has been exceeded. |
1022 | */ | | 1022 | */ |
1023 | if (sc->sc_errcnt < rderrthresh) | | 1023 | if (sc->sc_errcnt < rderrthresh) |
1024 | return 1; | | 1024 | return 1; |
1025 | | | 1025 | |
1026 | /* | | 1026 | /* |
1027 | * First conjure up the block number at which the error occurred. | | 1027 | * First conjure up the block number at which the error occurred. |
1028 | * Note that not all errors report a block number, in that case | | 1028 | * Note that not all errors report a block number, in that case |
1029 | * we just use b_blkno. | | 1029 | * we just use b_blkno. |
1030 | */ | | 1030 | */ |
1031 | bp = bufq_peek(sc->sc_tab); | | 1031 | bp = bufq_peek(sc->sc_tab); |
1032 | pbn = sc->sc_dkdev.dk_label->d_partitions[rdpart(bp->b_dev)].p_offset; | | 1032 | pbn = sc->sc_dkdev.dk_label->d_partitions[rdpart(bp->b_dev)].p_offset; |
1033 | if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) || | | 1033 | if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) || |
1034 | (sp->c_ief & IEF_RRMASK)) { | | 1034 | (sp->c_ief & IEF_RRMASK)) { |
1035 | hwbn = RDBTOS(pbn + bp->b_blkno); | | 1035 | hwbn = RDBTOS(pbn + bp->b_blkno); |
1036 | pbn = bp->b_blkno; | | 1036 | pbn = bp->b_blkno; |
1037 | } else { | | 1037 | } else { |
1038 | hwbn = sp->c_blk; | | 1038 | hwbn = sp->c_blk; |
1039 | pbn = RDSTOB(hwbn) - pbn; | | 1039 | pbn = RDSTOB(hwbn) - pbn; |
1040 | } | | 1040 | } |
1041 | /* | | 1041 | /* |
1042 | * Now output a generic message suitable for badsect. | | 1042 | * Now output a generic message suitable for badsect. |
1043 | * Note that we don't use harderr cuz it just prints | | 1043 | * Note that we don't use harderr cuz it just prints |
1044 | * out b_blkno which is just the beginning block number | | 1044 | * out b_blkno which is just the beginning block number |
1045 | * of the transfer, not necessary where the error occurred. | | 1045 | * of the transfer, not necessary where the error occurred. |
1046 | */ | | 1046 | */ |
1047 | printf("%s%c: hard error sn%" PRId64 "\n", device_xname(sc->sc_dev), | | 1047 | printf("%s%c: hard error sn%" PRId64 "\n", device_xname(sc->sc_dev), |
1048 | 'a'+rdpart(bp->b_dev), pbn); | | 1048 | 'a'+rdpart(bp->b_dev), pbn); |
1049 | /* | | 1049 | /* |
1050 | * Now report the status as returned by the hardware with | | 1050 | * Now report the status as returned by the hardware with |
1051 | * attempt at interpretation (unless debugging). | | 1051 | * attempt at interpretation (unless debugging). |
1052 | */ | | 1052 | */ |
1053 | printf("%s %s error:", device_xname(sc->sc_dev), | | 1053 | printf("%s %s error:", device_xname(sc->sc_dev), |
1054 | (bp->b_flags & B_READ) ? "read" : "write"); | | 1054 | (bp->b_flags & B_READ) ? "read" : "write"); |
1055 | #ifdef DEBUG | | 1055 | #ifdef DEBUG |
1056 | if (rddebug & RDB_ERROR) { | | 1056 | if (rddebug & RDB_ERROR) { |
1057 | /* status info */ | | 1057 | /* status info */ |
1058 | printf("\n volume: %d, unit: %d\n", | | 1058 | printf("\n volume: %d, unit: %d\n", |
1059 | (sp->c_vu>>4)&0xF, sp->c_vu&0xF); | | 1059 | (sp->c_vu>>4)&0xF, sp->c_vu&0xF); |
1060 | rdprinterr("reject", sp->c_ref, err_reject); | | 1060 | rdprinterr("reject", sp->c_ref, err_reject); |
1061 | rdprinterr("fault", sp->c_fef, err_fault); | | 1061 | rdprinterr("fault", sp->c_fef, err_fault); |
1062 | rdprinterr("access", sp->c_aef, err_access); | | 1062 | rdprinterr("access", sp->c_aef, err_access); |
1063 | rdprinterr("info", sp->c_ief, err_info); | | 1063 | rdprinterr("info", sp->c_ief, err_info); |
1064 | printf(" block: %lld, P1-P10: ", hwbn); | | 1064 | printf(" block: %lld, P1-P10: ", hwbn); |
1065 | printf("0x%x", *(u_int *)&sp->c_raw[0]); | | 1065 | printf("0x%x", *(u_int *)&sp->c_raw[0]); |
1066 | printf("0x%x", *(u_int *)&sp->c_raw[4]); | | 1066 | printf("0x%x", *(u_int *)&sp->c_raw[4]); |
1067 | printf("0x%x\n", *(u_short *)&sp->c_raw[8]); | | 1067 | printf("0x%x\n", *(u_short *)&sp->c_raw[8]); |
1068 | /* command */ | | 1068 | /* command */ |
1069 | printf(" ioc: "); | | 1069 | printf(" ioc: "); |
1070 | printf("0x%x", *(u_int *)&sc->sc_ioc.c_pad); | | 1070 | printf("0x%x", *(u_int *)&sc->sc_ioc.c_pad); |
1071 | printf("0x%x", *(u_short *)&sc->sc_ioc.c_hiaddr); | | 1071 | printf("0x%x", *(u_short *)&sc->sc_ioc.c_hiaddr); |
1072 | printf("0x%x", *(u_int *)&sc->sc_ioc.c_addr); | | 1072 | printf("0x%x", *(u_int *)&sc->sc_ioc.c_addr); |
1073 | printf("0x%x", *(u_short *)&sc->sc_ioc.c_nop2); | | 1073 | printf("0x%x", *(u_short *)&sc->sc_ioc.c_nop2); |
1074 | printf("0x%x", *(u_int *)&sc->sc_ioc.c_len); | | 1074 | printf("0x%x", *(u_int *)&sc->sc_ioc.c_len); |
1075 | printf("0x%x\n", *(u_short *)&sc->sc_ioc.c_cmd); | | 1075 | printf("0x%x\n", *(u_short *)&sc->sc_ioc.c_cmd); |
1076 | return 1; | | 1076 | return 1; |
1077 | } | | 1077 | } |
1078 | #endif | | 1078 | #endif |
1079 | printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n", | | 1079 | printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n", |
1080 | (sp->c_vu>>4)&0xF, sp->c_vu&0xF, | | 1080 | (sp->c_vu>>4)&0xF, sp->c_vu&0xF, |
1081 | sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief); | | 1081 | sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief); |
1082 | printf("P1-P10: "); | | 1082 | printf("P1-P10: "); |
1083 | printf("0x%x", *(u_int *)&sp->c_raw[0]); | | 1083 | printf("0x%x", *(u_int *)&sp->c_raw[0]); |
1084 | printf("0x%x", *(u_int *)&sp->c_raw[4]); | | 1084 | printf("0x%x", *(u_int *)&sp->c_raw[4]); |
1085 | printf("0x%x\n", *(u_short *)&sp->c_raw[8]); | | 1085 | printf("0x%x\n", *(u_short *)&sp->c_raw[8]); |
1086 | return 1; | | 1086 | return 1; |
1087 | } | | 1087 | } |
1088 | | | 1088 | |
1089 | static int | | 1089 | static int |
1090 | rdread(dev_t dev, struct uio *uio, int flags) | | 1090 | rdread(dev_t dev, struct uio *uio, int flags) |
1091 | { | | 1091 | { |
1092 | | | 1092 | |
1093 | return physio(rdstrategy, NULL, dev, B_READ, minphys, uio); | | 1093 | return physio(rdstrategy, NULL, dev, B_READ, minphys, uio); |
1094 | } | | 1094 | } |
1095 | | | 1095 | |
1096 | static int | | 1096 | static int |
1097 | rdwrite(dev_t dev, struct uio *uio, int flags) | | 1097 | rdwrite(dev_t dev, struct uio *uio, int flags) |
1098 | { | | 1098 | { |
1099 | | | 1099 | |
1100 | return physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio); | | 1100 | return physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio); |
1101 | } | | 1101 | } |
1102 | | | 1102 | |
1103 | static int | | 1103 | static int |
1104 | rdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) | | 1104 | rdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) |
1105 | { | | 1105 | { |
1106 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(dev)); | | 1106 | struct rd_softc *sc = device_lookup_private(&rd_cd, rdunit(dev)); |
1107 | struct disklabel *lp = sc->sc_dkdev.dk_label; | | 1107 | struct disklabel *lp = sc->sc_dkdev.dk_label; |
1108 | int error, flags; | | 1108 | int error, flags; |
1109 | | | 1109 | |
1110 | switch (cmd) { | | 1110 | switch (cmd) { |
1111 | case DIOCGDINFO: | | 1111 | case DIOCGDINFO: |
1112 | *(struct disklabel *)data = *lp; | | 1112 | *(struct disklabel *)data = *lp; |
1113 | return 0; | | 1113 | return 0; |
1114 | | | 1114 | |
1115 | case DIOCGPART: | | 1115 | case DIOCGPART: |
1116 | ((struct partinfo *)data)->disklab = lp; | | 1116 | ((struct partinfo *)data)->disklab = lp; |
1117 | ((struct partinfo *)data)->part = | | 1117 | ((struct partinfo *)data)->part = |
1118 | &lp->d_partitions[rdpart(dev)]; | | 1118 | &lp->d_partitions[rdpart(dev)]; |
1119 | return 0; | | 1119 | return 0; |
1120 | | | 1120 | |
1121 | case DIOCWLABEL: | | 1121 | case DIOCWLABEL: |
1122 | if ((flag & FWRITE) == 0) | | 1122 | if ((flag & FWRITE) == 0) |
1123 | return EBADF; | | 1123 | return EBADF; |
1124 | if (*(int *)data) | | 1124 | if (*(int *)data) |
1125 | sc->sc_flags |= RDF_WLABEL; | | 1125 | sc->sc_flags |= RDF_WLABEL; |
1126 | else | | 1126 | else |
1127 | sc->sc_flags &= ~RDF_WLABEL; | | 1127 | sc->sc_flags &= ~RDF_WLABEL; |
1128 | return 0; | | 1128 | return 0; |
1129 | | | 1129 | |
1130 | case DIOCSDINFO: | | 1130 | case DIOCSDINFO: |
1131 | if ((flag & FWRITE) == 0) | | 1131 | if ((flag & FWRITE) == 0) |
1132 | return EBADF; | | 1132 | return EBADF; |
1133 | return setdisklabel(lp, (struct disklabel *)data, | | 1133 | return setdisklabel(lp, (struct disklabel *)data, |
1134 | (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dkdev.dk_openmask, | | 1134 | (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dkdev.dk_openmask, |
1135 | NULL); | | 1135 | NULL); |
1136 | | | 1136 | |
1137 | case DIOCWDINFO: | | 1137 | case DIOCWDINFO: |
1138 | if ((flag & FWRITE) == 0) | | 1138 | if ((flag & FWRITE) == 0) |
1139 | return EBADF; | | 1139 | return EBADF; |
1140 | error = setdisklabel(lp, (struct disklabel *)data, | | 1140 | error = setdisklabel(lp, (struct disklabel *)data, |
1141 | (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dkdev.dk_openmask, | | 1141 | (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dkdev.dk_openmask, |
1142 | NULL); | | 1142 | NULL); |
1143 | if (error) | | 1143 | if (error) |
1144 | return error; | | 1144 | return error; |
1145 | flags = sc->sc_flags; | | 1145 | flags = sc->sc_flags; |
1146 | sc->sc_flags = RDF_ALIVE | RDF_WLABEL; | | 1146 | sc->sc_flags = RDF_ALIVE | RDF_WLABEL; |
1147 | error = writedisklabel(rdlabdev(dev), rdstrategy, lp, NULL); | | 1147 | error = writedisklabel(rdlabdev(dev), rdstrategy, lp, NULL); |
1148 | sc->sc_flags = flags; | | 1148 | sc->sc_flags = flags; |
1149 | return error; | | 1149 | return error; |
1150 | | | 1150 | |
1151 | case DIOCGDEFLABEL: | | 1151 | case DIOCGDEFLABEL: |
1152 | rdgetdefaultlabel(sc, (struct disklabel *)data); | | 1152 | rdgetdefaultlabel(sc, (struct disklabel *)data); |
1153 | return 0; | | 1153 | return 0; |
1154 | } | | 1154 | } |
1155 | return EINVAL; | | 1155 | return EINVAL; |
1156 | } | | 1156 | } |
1157 | | | 1157 | |
1158 | static void | | 1158 | static void |
1159 | rdgetdefaultlabel(struct rd_softc *sc, struct disklabel *lp) | | 1159 | rdgetdefaultlabel(struct rd_softc *sc, struct disklabel *lp) |
1160 | { | | 1160 | { |
1161 | int type = sc->sc_type; | | 1161 | int type = sc->sc_type; |
1162 | | | 1162 | |
1163 | memset((void *)lp, 0, sizeof(struct disklabel)); | | 1163 | memset((void *)lp, 0, sizeof(struct disklabel)); |
1164 | | | 1164 | |
1165 | lp->d_type = DTYPE_HPIB; | | 1165 | lp->d_type = DTYPE_HPIB; |
1166 | lp->d_secsize = DEV_BSIZE; | | 1166 | lp->d_secsize = DEV_BSIZE; |
1167 | lp->d_nsectors = rdidentinfo[type].ri_nbpt; | | 1167 | lp->d_nsectors = rdidentinfo[type].ri_nbpt; |
1168 | lp->d_ntracks = rdidentinfo[type].ri_ntpc; | | 1168 | lp->d_ntracks = rdidentinfo[type].ri_ntpc; |
1169 | lp->d_ncylinders = rdidentinfo[type].ri_ncyl; | | 1169 | lp->d_ncylinders = rdidentinfo[type].ri_ncyl; |
1170 | lp->d_secperunit = rdidentinfo[type].ri_nblocks; | | 1170 | lp->d_secperunit = rdidentinfo[type].ri_nblocks; |
1171 | lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; | | 1171 | lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; |
1172 | | | 1172 | |
1173 | strlcpy(lp->d_typename, rdidentinfo[type].ri_desc, | | 1173 | strlcpy(lp->d_typename, rdidentinfo[type].ri_desc, |
1174 | sizeof(lp->d_typename)); | | 1174 | sizeof(lp->d_typename)); |
1175 | strlcpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); | | 1175 | strlcpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); |
1176 | lp->d_rpm = 3000; | | 1176 | lp->d_rpm = 3000; |
1177 | lp->d_interleave = 1; | | 1177 | lp->d_interleave = 1; |
1178 | lp->d_flags = 0; | | 1178 | lp->d_flags = 0; |
1179 | | | 1179 | |
1180 | lp->d_partitions[RAW_PART].p_offset = 0; | | 1180 | lp->d_partitions[RAW_PART].p_offset = 0; |
1181 | lp->d_partitions[RAW_PART].p_size = | | 1181 | lp->d_partitions[RAW_PART].p_size = |
1182 | lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); | | 1182 | lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); |
1183 | lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; | | 1183 | lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; |
1184 | lp->d_npartitions = RAW_PART + 1; | | 1184 | lp->d_npartitions = RAW_PART + 1; |
1185 | | | 1185 | |
1186 | lp->d_magic = DISKMAGIC; | | 1186 | lp->d_magic = DISKMAGIC; |
1187 | lp->d_magic2 = DISKMAGIC; | | 1187 | lp->d_magic2 = DISKMAGIC; |
1188 | lp->d_checksum = dkcksum(lp); | | 1188 | lp->d_checksum = dkcksum(lp); |
1189 | } | | 1189 | } |
1190 | | | 1190 | |
1191 | int | | 1191 | int |
1192 | rdsize(dev_t dev) | | 1192 | rdsize(dev_t dev) |
1193 | { | | 1193 | { |
1194 | struct rd_softc *sc; | | 1194 | struct rd_softc *sc; |
1195 | int psize, didopen = 0; | | 1195 | int psize, didopen = 0; |
1196 | | | 1196 | |
1197 | sc = device_lookup_private(&rd_cd, rdunit(dev)); | | 1197 | sc = device_lookup_private(&rd_cd, rdunit(dev)); |
1198 | if (sc == NULL) | | 1198 | if (sc == NULL) |
1199 | return ENXIO; | | 1199 | return ENXIO; |
1200 | | | 1200 | |
1201 | if ((sc->sc_flags & RDF_ALIVE) == 0) | | 1201 | if ((sc->sc_flags & RDF_ALIVE) == 0) |
1202 | return ENXIO; | | 1202 | return ENXIO; |
1203 | | | 1203 | |
1204 | /* | | 1204 | /* |
1205 | * We get called very early on (via swapconf) | | 1205 | * We get called very early on (via swapconf) |
1206 | * without the device being open so we may need | | 1206 | * without the device being open so we may need |
1207 | * to handle it here. | | 1207 | * to handle it here. |
1208 | */ | | 1208 | */ |
1209 | if (sc->sc_dkdev.dk_openmask == 0) { | | 1209 | if (sc->sc_dkdev.dk_openmask == 0) { |
1210 | if (rdopen(dev, FREAD|FWRITE, S_IFBLK, NULL)) | | 1210 | if (rdopen(dev, FREAD|FWRITE, S_IFBLK, NULL)) |
1211 | return -1; | | 1211 | return -1; |
1212 | didopen = 1; | | 1212 | didopen = 1; |
1213 | } | | 1213 | } |
1214 | psize = sc->sc_dkdev.dk_label->d_partitions[rdpart(dev)].p_size * | | 1214 | psize = sc->sc_dkdev.dk_label->d_partitions[rdpart(dev)].p_size * |
1215 | (sc->sc_dkdev.dk_label->d_secsize / DEV_BSIZE); | | 1215 | (sc->sc_dkdev.dk_label->d_secsize / DEV_BSIZE); |
1216 | if (didopen) | | 1216 | if (didopen) |
1217 | (void)rdclose(dev, FREAD|FWRITE, S_IFBLK, NULL); | | 1217 | (void)rdclose(dev, FREAD|FWRITE, S_IFBLK, NULL); |
1218 | return psize; | | 1218 | return psize; |
1219 | } | | 1219 | } |
1220 | | | 1220 | |
1221 | #ifdef DEBUG | | 1221 | #ifdef DEBUG |
1222 | static void | | 1222 | static void |
1223 | rdprinterr(const char *str, short err, const char **tab) | | 1223 | rdprinterr(const char *str, short err, const char **tab) |
1224 | { | | 1224 | { |
1225 | int i; | | 1225 | int i; |
1226 | int printed; | | 1226 | int printed; |
1227 | | | 1227 | |
1228 | if (err == 0) | | 1228 | if (err == 0) |
1229 | return; | | 1229 | return; |
1230 | printf(" %s error %d field:", str, err); | | 1230 | printf(" %s error %d field:", str, err); |
1231 | printed = 0; | | 1231 | printed = 0; |
1232 | for (i = 0; i < 16; i++) | | 1232 | for (i = 0; i < 16; i++) |
1233 | if (err & (0x8000 >> i)) | | 1233 | if (err & (0x8000 >> i)) |
1234 | printf("%s%s", printed++ ? " + " : " ", tab[i]); | | 1234 | printf("%s%s", printed++ ? " + " : " ", tab[i]); |
1235 | printf("\n"); | | 1235 | printf("\n"); |
1236 | } | | 1236 | } |
1237 | #endif | | 1237 | #endif |
1238 | | | 1238 | |
1239 | static int rddoingadump; /* simple mutex */ | | 1239 | static int rddoingadump; /* simple mutex */ |
1240 | | | 1240 | |
1241 | /* | | 1241 | /* |
1242 | * Non-interrupt driven, non-DMA dump routine. | | 1242 | * Non-interrupt driven, non-DMA dump routine. |
1243 | */ | | 1243 | */ |
1244 | static int | | 1244 | static int |
1245 | rddump(dev_t dev, daddr_t blkno, void *va, size_t size) | | 1245 | rddump(dev_t dev, daddr_t blkno, void *va, size_t size) |
1246 | { | | 1246 | { |
1247 | int sectorsize; /* size of a disk sector */ | | 1247 | int sectorsize; /* size of a disk sector */ |
1248 | int nsects; /* number of sectors in partition */ | | 1248 | int nsects; /* number of sectors in partition */ |
1249 | int sectoff; /* sector offset of partition */ | | 1249 | int sectoff; /* sector offset of partition */ |
1250 | int totwrt; /* total number of sectors left to write */ | | 1250 | int totwrt; /* total number of sectors left to write */ |
1251 | int nwrt; /* current number of sectors to write */ | | 1251 | int nwrt; /* current number of sectors to write */ |
1252 | int unit, part; | | 1252 | int unit, part; |
1253 | int ctlr, slave; | | 1253 | int ctlr, slave; |
1254 | struct rd_softc *sc; | | 1254 | struct rd_softc *sc; |
1255 | struct disklabel *lp; | | 1255 | struct disklabel *lp; |
1256 | char stat; | | 1256 | char stat; |
1257 | | | 1257 | |
1258 | /* Check for recursive dump; if so, punt. */ | | 1258 | /* Check for recursive dump; if so, punt. */ |
1259 | if (rddoingadump) | | 1259 | if (rddoingadump) |
1260 | return EFAULT; | | 1260 | return EFAULT; |
1261 | rddoingadump = 1; | | 1261 | rddoingadump = 1; |
1262 | | | 1262 | |
1263 | /* Decompose unit and partition. */ | | 1263 | /* Decompose unit and partition. */ |
1264 | unit = rdunit(dev); | | 1264 | unit = rdunit(dev); |
1265 | part = rdpart(dev); | | 1265 | part = rdpart(dev); |
1266 | | | 1266 | |
1267 | /* Make sure dump device is ok. */ | | 1267 | /* Make sure dump device is ok. */ |
1268 | sc = device_lookup_private(&rd_cd, rdunit(dev)); | | 1268 | sc = device_lookup_private(&rd_cd, rdunit(dev)); |
1269 | if (sc == NULL) | | 1269 | if (sc == NULL) |
1270 | return ENXIO; | | 1270 | return ENXIO; |
1271 | | | 1271 | |
1272 | if ((sc->sc_flags & RDF_ALIVE) == 0) | | 1272 | if ((sc->sc_flags & RDF_ALIVE) == 0) |
1273 | return ENXIO; | | 1273 | return ENXIO; |
1274 | | | 1274 | |
1275 | ctlr = device_unit(device_parent(sc->sc_dev)); | | 1275 | ctlr = device_unit(device_parent(sc->sc_dev)); |
1276 | slave = sc->sc_slave; | | 1276 | slave = sc->sc_slave; |
1277 | | | 1277 | |
1278 | /* | | 1278 | /* |
1279 | * Convert to disk sectors. Request must be a multiple of size. | | 1279 | * Convert to disk sectors. Request must be a multiple of size. |
1280 | */ | | 1280 | */ |
1281 | lp = sc->sc_dkdev.dk_label; | | 1281 | lp = sc->sc_dkdev.dk_label; |
1282 | sectorsize = lp->d_secsize; | | 1282 | sectorsize = lp->d_secsize; |
1283 | if ((size % sectorsize) != 0) | | 1283 | if ((size % sectorsize) != 0) |
1284 | return EFAULT; | | 1284 | return EFAULT; |
1285 | totwrt = size / sectorsize; | | 1285 | totwrt = size / sectorsize; |
1286 | blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */ | | 1286 | blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */ |
1287 | | | 1287 | |
1288 | nsects = lp->d_partitions[part].p_size; | | 1288 | nsects = lp->d_partitions[part].p_size; |
1289 | sectoff = lp->d_partitions[part].p_offset; | | 1289 | sectoff = lp->d_partitions[part].p_offset; |
1290 | | | 1290 | |
1291 | /* Check transfer bounds against partition size. */ | | 1291 | /* Check transfer bounds against partition size. */ |
1292 | if ((blkno < 0) || (blkno + totwrt) > nsects) | | 1292 | if ((blkno < 0) || (blkno + totwrt) > nsects) |
1293 | return EINVAL; | | 1293 | return EINVAL; |
1294 | | | 1294 | |
1295 | /* Offset block number to start of partition. */ | | 1295 | /* Offset block number to start of partition. */ |
1296 | blkno += sectoff; | | 1296 | blkno += sectoff; |
1297 | | | 1297 | |
1298 | while (totwrt > 0) { | | 1298 | while (totwrt > 0) { |
1299 | nwrt = totwrt; /* XXX */ | | 1299 | nwrt = totwrt; /* XXX */ |
1300 | #ifndef RD_DUMP_NOT_TRUSTED | | 1300 | #ifndef RD_DUMP_NOT_TRUSTED |
1301 | /* | | 1301 | /* |
1302 | * Fill out and send HPIB command. | | 1302 | * Fill out and send HPIB command. |
1303 | */ | | 1303 | */ |
1304 | sc->sc_ioc.c_unit = C_SUNIT(sc->sc_punit); | | 1304 | sc->sc_ioc.c_unit = C_SUNIT(sc->sc_punit); |
1305 | sc->sc_ioc.c_volume = C_SVOL(0); | | 1305 | sc->sc_ioc.c_volume = C_SVOL(0); |
1306 | sc->sc_ioc.c_saddr = C_SADDR; | | 1306 | sc->sc_ioc.c_saddr = C_SADDR; |
1307 | sc->sc_ioc.c_hiaddr = 0; | | 1307 | sc->sc_ioc.c_hiaddr = 0; |
1308 | sc->sc_ioc.c_addr = RDBTOS(blkno); | | 1308 | sc->sc_ioc.c_addr = RDBTOS(blkno); |
1309 | sc->sc_ioc.c_nop2 = C_NOP; | | 1309 | sc->sc_ioc.c_nop2 = C_NOP; |
1310 | sc->sc_ioc.c_slen = C_SLEN; | | 1310 | sc->sc_ioc.c_slen = C_SLEN; |
1311 | sc->sc_ioc.c_len = nwrt * sectorsize; | | 1311 | sc->sc_ioc.c_len = nwrt * sectorsize; |
1312 | sc->sc_ioc.c_cmd = C_WRITE; | | 1312 | sc->sc_ioc.c_cmd = C_WRITE; |
1313 | hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc.c_unit, | | 1313 | hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc.c_unit, |
1314 | sizeof(sc->sc_ioc) - 2); | | 1314 | sizeof(sc->sc_ioc) - 2); |
1315 | if (hpibswait(ctlr, slave)) | | 1315 | if (hpibswait(ctlr, slave)) |
1316 | return EIO; | | 1316 | return EIO; |
1317 | | | 1317 | |
1318 | /* | | 1318 | /* |
1319 | * Send the data. | | 1319 | * Send the data. |
1320 | */ | | 1320 | */ |
1321 | hpibsend(ctlr, slave, C_EXEC, va, nwrt * sectorsize); | | 1321 | hpibsend(ctlr, slave, C_EXEC, va, nwrt * sectorsize); |
1322 | (void) hpibswait(ctlr, slave); | | 1322 | (void) hpibswait(ctlr, slave); |
1323 | hpibrecv(ctlr, slave, C_QSTAT, &stat, 1); | | 1323 | hpibrecv(ctlr, slave, C_QSTAT, &stat, 1); |
1324 | if (stat) | | 1324 | if (stat) |
1325 | return EIO; | | 1325 | return EIO; |
1326 | #else /* RD_DUMP_NOT_TRUSTED */ | | 1326 | #else /* RD_DUMP_NOT_TRUSTED */ |
1327 | /* Let's just talk about this first... */ | | 1327 | /* Let's just talk about this first... */ |
1328 | printf("%s: dump addr %p, blk %d\n", device_xname(sc->sc_dev), | | 1328 | printf("%s: dump addr %p, blk %d\n", device_xname(sc->sc_dev), |
1329 | va, blkno); | | 1329 | va, blkno); |
1330 | delay(500 * 1000); /* half a second */ | | 1330 | delay(500 * 1000); /* half a second */ |
1331 | #endif /* RD_DUMP_NOT_TRUSTED */ | | 1331 | #endif /* RD_DUMP_NOT_TRUSTED */ |
1332 | | | 1332 | |
1333 | /* update block count */ | | 1333 | /* update block count */ |
1334 | totwrt -= nwrt; | | 1334 | totwrt -= nwrt; |
1335 | blkno += nwrt; | | 1335 | blkno += nwrt; |
1336 | va = (char *)va + sectorsize * nwrt; | | 1336 | va = (char *)va + sectorsize * nwrt; |
1337 | } | | 1337 | } |
1338 | rddoingadump = 0; | | 1338 | rddoingadump = 0; |
1339 | return 0; | | 1339 | return 0; |
1340 | } | | 1340 | } |