sd.c revision 1.116.2.3 1 1.116.2.3 thorpej /* $NetBSD: sd.c,v 1.116.2.3 1997/09/22 06:33:42 thorpej Exp $ */
2 1.116.2.2 thorpej
3 1.116.2.2 thorpej /*
4 1.116.2.2 thorpej * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved.
5 1.116.2.2 thorpej *
6 1.116.2.2 thorpej * Redistribution and use in source and binary forms, with or without
7 1.116.2.2 thorpej * modification, are permitted provided that the following conditions
8 1.116.2.2 thorpej * are met:
9 1.116.2.2 thorpej * 1. Redistributions of source code must retain the above copyright
10 1.116.2.2 thorpej * notice, this list of conditions and the following disclaimer.
11 1.116.2.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright
12 1.116.2.2 thorpej * notice, this list of conditions and the following disclaimer in the
13 1.116.2.2 thorpej * documentation and/or other materials provided with the distribution.
14 1.116.2.2 thorpej * 3. All advertising materials mentioning features or use of this software
15 1.116.2.2 thorpej * must display the following acknowledgement:
16 1.116.2.2 thorpej * This product includes software developed by Charles M. Hannum.
17 1.116.2.2 thorpej * 4. The name of the author may not be used to endorse or promote products
18 1.116.2.2 thorpej * derived from this software without specific prior written permission.
19 1.116.2.2 thorpej *
20 1.116.2.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 1.116.2.2 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 1.116.2.2 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 1.116.2.2 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 1.116.2.2 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 1.116.2.2 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 1.116.2.2 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 1.116.2.2 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 1.116.2.2 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 1.116.2.2 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 1.116.2.2 thorpej */
31 1.116.2.2 thorpej
32 1.116.2.2 thorpej /*
33 1.116.2.2 thorpej * Originally written by Julian Elischer (julian (at) dialix.oz.au)
34 1.116.2.2 thorpej * for TRW Financial Systems for use under the MACH(2.5) operating system.
35 1.116.2.2 thorpej *
36 1.116.2.2 thorpej * TRW Financial Systems, in accordance with their agreement with Carnegie
37 1.116.2.2 thorpej * Mellon University, makes this software available to CMU to distribute
38 1.116.2.2 thorpej * or use in any manner that they see fit as long as this message is kept with
39 1.116.2.2 thorpej * the software. For this reason TFS also grants any other persons or
40 1.116.2.2 thorpej * organisations permission to use or modify this software.
41 1.116.2.2 thorpej *
42 1.116.2.2 thorpej * TFS supplies this software to be publicly redistributed
43 1.116.2.2 thorpej * on the understanding that TFS is not responsible for the correct
44 1.116.2.2 thorpej * functioning of this software in any circumstances.
45 1.116.2.2 thorpej *
46 1.116.2.2 thorpej * Ported to run under 386BSD by Julian Elischer (julian (at) dialix.oz.au) Sept 1992
47 1.116.2.2 thorpej */
48 1.116.2.2 thorpej
49 1.116.2.2 thorpej #include <sys/types.h>
50 1.116.2.2 thorpej #include <sys/param.h>
51 1.116.2.2 thorpej #include <sys/systm.h>
52 1.116.2.2 thorpej #include <sys/kernel.h>
53 1.116.2.2 thorpej #include <sys/file.h>
54 1.116.2.2 thorpej #include <sys/stat.h>
55 1.116.2.2 thorpej #include <sys/ioctl.h>
56 1.116.2.2 thorpej #include <sys/buf.h>
57 1.116.2.2 thorpej #include <sys/uio.h>
58 1.116.2.2 thorpej #include <sys/malloc.h>
59 1.116.2.2 thorpej #include <sys/errno.h>
60 1.116.2.2 thorpej #include <sys/device.h>
61 1.116.2.2 thorpej #include <sys/disklabel.h>
62 1.116.2.2 thorpej #include <sys/disk.h>
63 1.116.2.2 thorpej #include <sys/proc.h>
64 1.116.2.2 thorpej #include <sys/conf.h>
65 1.116.2.2 thorpej
66 1.116.2.2 thorpej #include <dev/scsipi/scsi_all.h>
67 1.116.2.2 thorpej #include <dev/scsipi/scsipi_all.h>
68 1.116.2.2 thorpej #include <dev/scsipi/scsi_all.h>
69 1.116.2.2 thorpej #include <dev/scsipi/scsi_disk.h>
70 1.116.2.2 thorpej #include <dev/scsipi/scsipi_disk.h>
71 1.116.2.2 thorpej #include <dev/scsipi/scsiconf.h>
72 1.116.2.2 thorpej
73 1.116.2.3 thorpej #ifndef SDOUTSTANDING
74 1.116.2.2 thorpej #define SDOUTSTANDING 4
75 1.116.2.3 thorpej #endif
76 1.116.2.2 thorpej #define SDRETRIES 4
77 1.116.2.2 thorpej
78 1.116.2.2 thorpej #define SDUNIT(dev) DISKUNIT(dev)
79 1.116.2.2 thorpej #define SDPART(dev) DISKPART(dev)
80 1.116.2.2 thorpej #define MAKESDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
81 1.116.2.2 thorpej
82 1.116.2.2 thorpej #define SDLABELDEV(dev) (MAKESDDEV(major(dev), SDUNIT(dev), RAW_PART))
83 1.116.2.2 thorpej
84 1.116.2.2 thorpej struct sd_softc {
85 1.116.2.2 thorpej struct device sc_dev;
86 1.116.2.2 thorpej struct disk sc_dk;
87 1.116.2.2 thorpej
88 1.116.2.2 thorpej int flags;
89 1.116.2.2 thorpej #define SDF_LOCKED 0x01
90 1.116.2.2 thorpej #define SDF_WANTED 0x02
91 1.116.2.2 thorpej #define SDF_WLABEL 0x04 /* label is writable */
92 1.116.2.2 thorpej #define SDF_LABELLING 0x08 /* writing label */
93 1.116.2.2 thorpej #define SDF_ANCIENT 0x10 /* disk is ancient; for minphys */
94 1.116.2.2 thorpej struct scsipi_link *sc_link; /* contains our targ, lun, etc. */
95 1.116.2.2 thorpej struct disk_parms {
96 1.116.2.2 thorpej u_char heads; /* number of heads */
97 1.116.2.2 thorpej u_short cyls; /* number of cylinders */
98 1.116.2.2 thorpej u_char sectors; /* number of sectors/track */
99 1.116.2.2 thorpej int blksize; /* number of bytes/sector */
100 1.116.2.2 thorpej u_long disksize; /* total number sectors */
101 1.116.2.2 thorpej } params;
102 1.116.2.2 thorpej struct buf buf_queue;
103 1.116.2.2 thorpej u_int8_t type;
104 1.116.2.2 thorpej };
105 1.116.2.2 thorpej
106 1.116.2.2 thorpej struct scsi_mode_sense_data {
107 1.116.2.2 thorpej struct scsi_mode_header header;
108 1.116.2.2 thorpej struct scsi_blk_desc blk_desc;
109 1.116.2.2 thorpej union scsi_disk_pages pages;
110 1.116.2.2 thorpej };
111 1.116.2.2 thorpej
112 1.116.2.2 thorpej #ifdef __BROKEN_INDIRECT_CONFIG
113 1.116.2.2 thorpej int sdmatch __P((struct device *, void *, void *));
114 1.116.2.2 thorpej #else
115 1.116.2.2 thorpej int sdmatch __P((struct device *, struct cfdata *, void *));
116 1.116.2.2 thorpej #endif
117 1.116.2.2 thorpej void sdattach __P((struct device *, struct device *, void *));
118 1.116.2.2 thorpej int sdlock __P((struct sd_softc *));
119 1.116.2.2 thorpej void sdunlock __P((struct sd_softc *));
120 1.116.2.2 thorpej void sdminphys __P((struct buf *));
121 1.116.2.2 thorpej void sdgetdisklabel __P((struct sd_softc *));
122 1.116.2.2 thorpej void sdstart __P((void *));
123 1.116.2.2 thorpej void sddone __P((struct scsipi_xfer *));
124 1.116.2.2 thorpej int sd_reassign_blocks __P((struct sd_softc *, u_long));
125 1.116.2.2 thorpej int sd_get_optparms __P((struct sd_softc *, int, struct disk_parms *));
126 1.116.2.2 thorpej int sd_get_parms __P((struct sd_softc *, int));
127 1.116.2.2 thorpej static int sd_mode_sense __P((struct sd_softc *, struct scsi_mode_sense_data *,
128 1.116.2.2 thorpej int, int));
129 1.116.2.2 thorpej
130 1.116.2.2 thorpej struct cfattach sd_ca = {
131 1.116.2.2 thorpej sizeof(struct sd_softc), sdmatch, sdattach
132 1.116.2.2 thorpej };
133 1.116.2.2 thorpej
134 1.116.2.2 thorpej struct cfdriver sd_cd = {
135 1.116.2.2 thorpej NULL, "sd", DV_DISK
136 1.116.2.2 thorpej };
137 1.116.2.2 thorpej
138 1.116.2.2 thorpej struct dkdriver sddkdriver = { sdstrategy };
139 1.116.2.2 thorpej
140 1.116.2.2 thorpej struct scsipi_device sd_switch = {
141 1.116.2.2 thorpej NULL, /* Use default error handler */
142 1.116.2.2 thorpej sdstart, /* have a queue, served by this */
143 1.116.2.2 thorpej NULL, /* have no async handler */
144 1.116.2.2 thorpej sddone, /* deal with stats at interrupt time */
145 1.116.2.2 thorpej };
146 1.116.2.2 thorpej
147 1.116.2.2 thorpej struct scsipi_inquiry_pattern sd_patterns[] = {
148 1.116.2.2 thorpej {T_DIRECT, T_FIXED,
149 1.116.2.2 thorpej "", "", ""},
150 1.116.2.2 thorpej {T_DIRECT, T_REMOV,
151 1.116.2.2 thorpej "", "", ""},
152 1.116.2.2 thorpej {T_OPTICAL, T_FIXED,
153 1.116.2.2 thorpej "", "", ""},
154 1.116.2.2 thorpej {T_OPTICAL, T_REMOV,
155 1.116.2.2 thorpej "", "", ""},
156 1.116.2.2 thorpej };
157 1.116.2.2 thorpej
158 1.116.2.2 thorpej int
159 1.116.2.2 thorpej sdmatch(parent, match, aux)
160 1.116.2.2 thorpej struct device *parent;
161 1.116.2.2 thorpej #ifdef __BROKEN_INDIRECT_CONFIG
162 1.116.2.2 thorpej void *match;
163 1.116.2.2 thorpej #else
164 1.116.2.2 thorpej struct cfdata *match;
165 1.116.2.2 thorpej #endif
166 1.116.2.2 thorpej void *aux;
167 1.116.2.2 thorpej {
168 1.116.2.2 thorpej struct scsipibus_attach_args *sa = aux;
169 1.116.2.2 thorpej int priority;
170 1.116.2.2 thorpej
171 1.116.2.2 thorpej (void)scsipi_inqmatch(&sa->sa_inqbuf,
172 1.116.2.2 thorpej (caddr_t)sd_patterns, sizeof(sd_patterns)/sizeof(sd_patterns[0]),
173 1.116.2.2 thorpej sizeof(sd_patterns[0]), &priority);
174 1.116.2.2 thorpej return (priority);
175 1.116.2.2 thorpej }
176 1.116.2.2 thorpej
177 1.116.2.2 thorpej /*
178 1.116.2.2 thorpej * The routine called by the low level scsi routine when it discovers
179 1.116.2.2 thorpej * a device suitable for this driver.
180 1.116.2.2 thorpej */
181 1.116.2.2 thorpej void
182 1.116.2.2 thorpej sdattach(parent, self, aux)
183 1.116.2.2 thorpej struct device *parent, *self;
184 1.116.2.2 thorpej void *aux;
185 1.116.2.2 thorpej {
186 1.116.2.2 thorpej int error;
187 1.116.2.2 thorpej struct sd_softc *sd = (void *)self;
188 1.116.2.2 thorpej struct disk_parms *dp = &sd->params;
189 1.116.2.2 thorpej struct scsipibus_attach_args *sa = aux;
190 1.116.2.2 thorpej struct scsipi_link *sc_link = sa->sa_sc_link;
191 1.116.2.2 thorpej
192 1.116.2.2 thorpej SC_DEBUG(sc_link, SDEV_DB2, ("sdattach: "));
193 1.116.2.2 thorpej
194 1.116.2.2 thorpej /*
195 1.116.2.2 thorpej * Store information needed to contact our base driver
196 1.116.2.2 thorpej */
197 1.116.2.2 thorpej sd->sc_link = sc_link;
198 1.116.2.2 thorpej sd->type = (sa->sa_inqbuf.type & SID_TYPE);
199 1.116.2.2 thorpej sc_link->device = &sd_switch;
200 1.116.2.2 thorpej sc_link->device_softc = sd;
201 1.116.2.2 thorpej if (sc_link->openings > SDOUTSTANDING)
202 1.116.2.2 thorpej sc_link->openings = SDOUTSTANDING;
203 1.116.2.2 thorpej
204 1.116.2.2 thorpej /*
205 1.116.2.2 thorpej * Initialize and attach the disk structure.
206 1.116.2.2 thorpej */
207 1.116.2.2 thorpej sd->sc_dk.dk_driver = &sddkdriver;
208 1.116.2.2 thorpej sd->sc_dk.dk_name = sd->sc_dev.dv_xname;
209 1.116.2.2 thorpej disk_attach(&sd->sc_dk);
210 1.116.2.2 thorpej
211 1.116.2.2 thorpej #if !defined(i386)
212 1.116.2.2 thorpej dk_establish(&sd->sc_dk, &sd->sc_dev); /* XXX */
213 1.116.2.2 thorpej #endif
214 1.116.2.2 thorpej
215 1.116.2.2 thorpej /*
216 1.116.2.2 thorpej * Note if this device is ancient. This is used in sdminphys().
217 1.116.2.2 thorpej */
218 1.116.2.2 thorpej if ((sa->scsipi_info.scsi_version & SID_ANSII) == 0)
219 1.116.2.2 thorpej sd->flags |= SDF_ANCIENT;
220 1.116.2.2 thorpej
221 1.116.2.2 thorpej /*
222 1.116.2.2 thorpej * Use the subdriver to request information regarding
223 1.116.2.2 thorpej * the drive. We cannot use interrupts yet, so the
224 1.116.2.2 thorpej * request must specify this.
225 1.116.2.2 thorpej */
226 1.116.2.2 thorpej printf("\n");
227 1.116.2.2 thorpej printf("%s: ", sd->sc_dev.dv_xname);
228 1.116.2.2 thorpej
229 1.116.2.2 thorpej if ((sd->sc_link->quirks & SDEV_NOSTARTUNIT) == 0) {
230 1.116.2.2 thorpej error = scsipi_start(sd->sc_link, SSS_START,
231 1.116.2.2 thorpej SCSI_AUTOCONF | SCSI_IGNORE_ILLEGAL_REQUEST |
232 1.116.2.2 thorpej SCSI_IGNORE_MEDIA_CHANGE | SCSI_SILENT);
233 1.116.2.2 thorpej } else
234 1.116.2.2 thorpej error = 0;
235 1.116.2.2 thorpej
236 1.116.2.2 thorpej if (error || sd_get_parms(sd, SCSI_AUTOCONF) != 0)
237 1.116.2.2 thorpej printf("drive offline\n");
238 1.116.2.2 thorpej else
239 1.116.2.2 thorpej printf("%ldMB, %d cyl, %d head, %d sec, %d bytes/sect x %ld sectors\n",
240 1.116.2.2 thorpej dp->disksize / (1048576 / dp->blksize), dp->cyls,
241 1.116.2.2 thorpej dp->heads, dp->sectors, dp->blksize, dp->disksize);
242 1.116.2.2 thorpej }
243 1.116.2.2 thorpej
244 1.116.2.2 thorpej /*
245 1.116.2.2 thorpej * Wait interruptibly for an exclusive lock.
246 1.116.2.2 thorpej *
247 1.116.2.2 thorpej * XXX
248 1.116.2.2 thorpej * Several drivers do this; it should be abstracted and made MP-safe.
249 1.116.2.2 thorpej */
250 1.116.2.2 thorpej int
251 1.116.2.2 thorpej sdlock(sd)
252 1.116.2.2 thorpej struct sd_softc *sd;
253 1.116.2.2 thorpej {
254 1.116.2.2 thorpej int error;
255 1.116.2.2 thorpej
256 1.116.2.2 thorpej while ((sd->flags & SDF_LOCKED) != 0) {
257 1.116.2.2 thorpej sd->flags |= SDF_WANTED;
258 1.116.2.2 thorpej if ((error = tsleep(sd, PRIBIO | PCATCH, "sdlck", 0)) != 0)
259 1.116.2.2 thorpej return error;
260 1.116.2.2 thorpej }
261 1.116.2.2 thorpej sd->flags |= SDF_LOCKED;
262 1.116.2.2 thorpej return 0;
263 1.116.2.2 thorpej }
264 1.116.2.2 thorpej
265 1.116.2.2 thorpej /*
266 1.116.2.2 thorpej * Unlock and wake up any waiters.
267 1.116.2.2 thorpej */
268 1.116.2.2 thorpej void
269 1.116.2.2 thorpej sdunlock(sd)
270 1.116.2.2 thorpej struct sd_softc *sd;
271 1.116.2.2 thorpej {
272 1.116.2.2 thorpej
273 1.116.2.2 thorpej sd->flags &= ~SDF_LOCKED;
274 1.116.2.2 thorpej if ((sd->flags & SDF_WANTED) != 0) {
275 1.116.2.2 thorpej sd->flags &= ~SDF_WANTED;
276 1.116.2.2 thorpej wakeup(sd);
277 1.116.2.2 thorpej }
278 1.116.2.2 thorpej }
279 1.116.2.2 thorpej
280 1.116.2.2 thorpej /*
281 1.116.2.2 thorpej * open the device. Make sure the partition info is a up-to-date as can be.
282 1.116.2.2 thorpej */
283 1.116.2.2 thorpej int
284 1.116.2.2 thorpej sdopen(dev, flag, fmt, p)
285 1.116.2.2 thorpej dev_t dev;
286 1.116.2.2 thorpej int flag, fmt;
287 1.116.2.2 thorpej struct proc *p;
288 1.116.2.2 thorpej {
289 1.116.2.2 thorpej struct sd_softc *sd;
290 1.116.2.2 thorpej struct scsipi_link *sc_link;
291 1.116.2.2 thorpej int unit, part;
292 1.116.2.2 thorpej int error;
293 1.116.2.2 thorpej
294 1.116.2.2 thorpej unit = SDUNIT(dev);
295 1.116.2.2 thorpej if (unit >= sd_cd.cd_ndevs)
296 1.116.2.2 thorpej return ENXIO;
297 1.116.2.2 thorpej sd = sd_cd.cd_devs[unit];
298 1.116.2.2 thorpej if (sd == NULL)
299 1.116.2.2 thorpej return ENXIO;
300 1.116.2.2 thorpej
301 1.116.2.2 thorpej sc_link = sd->sc_link;
302 1.116.2.2 thorpej
303 1.116.2.2 thorpej SC_DEBUG(sc_link, SDEV_DB1,
304 1.116.2.2 thorpej ("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
305 1.116.2.2 thorpej sd_cd.cd_ndevs, SDPART(dev)));
306 1.116.2.2 thorpej
307 1.116.2.2 thorpej if ((error = sdlock(sd)) != 0)
308 1.116.2.2 thorpej return error;
309 1.116.2.2 thorpej
310 1.116.2.2 thorpej if (sd->sc_dk.dk_openmask != 0) {
311 1.116.2.2 thorpej /*
312 1.116.2.2 thorpej * If any partition is open, but the disk has been invalidated,
313 1.116.2.2 thorpej * disallow further opens.
314 1.116.2.2 thorpej */
315 1.116.2.2 thorpej if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
316 1.116.2.2 thorpej error = EIO;
317 1.116.2.2 thorpej goto bad3;
318 1.116.2.2 thorpej }
319 1.116.2.2 thorpej } else {
320 1.116.2.2 thorpej /* Check that it is still responding and ok. */
321 1.116.2.2 thorpej error = scsipi_test_unit_ready(sc_link,
322 1.116.2.2 thorpej SCSI_IGNORE_ILLEGAL_REQUEST |
323 1.116.2.2 thorpej SCSI_IGNORE_MEDIA_CHANGE |
324 1.116.2.2 thorpej SCSI_IGNORE_NOT_READY);
325 1.116.2.2 thorpej if (error)
326 1.116.2.2 thorpej goto bad3;
327 1.116.2.2 thorpej
328 1.116.2.2 thorpej /* Start the pack spinning if necessary. */
329 1.116.2.2 thorpej if ((sc_link->quirks & SDEV_NOSTARTUNIT) == 0) {
330 1.116.2.2 thorpej error = scsipi_start(sc_link, SSS_START,
331 1.116.2.2 thorpej SCSI_IGNORE_ILLEGAL_REQUEST |
332 1.116.2.2 thorpej SCSI_IGNORE_MEDIA_CHANGE |
333 1.116.2.2 thorpej SCSI_SILENT);
334 1.116.2.2 thorpej if (error)
335 1.116.2.2 thorpej goto bad3;
336 1.116.2.2 thorpej }
337 1.116.2.2 thorpej
338 1.116.2.2 thorpej sc_link->flags |= SDEV_OPEN;
339 1.116.2.2 thorpej
340 1.116.2.2 thorpej /* Lock the pack in. */
341 1.116.2.2 thorpej error = scsipi_prevent(sc_link, PR_PREVENT,
342 1.116.2.2 thorpej SCSI_IGNORE_ILLEGAL_REQUEST |
343 1.116.2.2 thorpej SCSI_IGNORE_MEDIA_CHANGE);
344 1.116.2.2 thorpej if (error)
345 1.116.2.2 thorpej goto bad;
346 1.116.2.2 thorpej
347 1.116.2.2 thorpej if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
348 1.116.2.2 thorpej sc_link->flags |= SDEV_MEDIA_LOADED;
349 1.116.2.2 thorpej
350 1.116.2.2 thorpej /* Load the physical device parameters. */
351 1.116.2.2 thorpej if (sd_get_parms(sd, 0) != 0) {
352 1.116.2.2 thorpej error = ENXIO;
353 1.116.2.2 thorpej goto bad2;
354 1.116.2.2 thorpej }
355 1.116.2.2 thorpej SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
356 1.116.2.2 thorpej
357 1.116.2.2 thorpej /* Load the partition info if not already loaded. */
358 1.116.2.2 thorpej sdgetdisklabel(sd);
359 1.116.2.2 thorpej SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel loaded "));
360 1.116.2.2 thorpej }
361 1.116.2.2 thorpej }
362 1.116.2.2 thorpej
363 1.116.2.2 thorpej part = SDPART(dev);
364 1.116.2.2 thorpej
365 1.116.2.2 thorpej /* Check that the partition exists. */
366 1.116.2.2 thorpej if (part != RAW_PART &&
367 1.116.2.2 thorpej (part >= sd->sc_dk.dk_label->d_npartitions ||
368 1.116.2.2 thorpej sd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
369 1.116.2.2 thorpej error = ENXIO;
370 1.116.2.2 thorpej goto bad;
371 1.116.2.2 thorpej }
372 1.116.2.2 thorpej
373 1.116.2.2 thorpej /* Insure only one open at a time. */
374 1.116.2.2 thorpej switch (fmt) {
375 1.116.2.2 thorpej case S_IFCHR:
376 1.116.2.2 thorpej sd->sc_dk.dk_copenmask |= (1 << part);
377 1.116.2.2 thorpej break;
378 1.116.2.2 thorpej case S_IFBLK:
379 1.116.2.2 thorpej sd->sc_dk.dk_bopenmask |= (1 << part);
380 1.116.2.2 thorpej break;
381 1.116.2.2 thorpej }
382 1.116.2.2 thorpej sd->sc_dk.dk_openmask = sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
383 1.116.2.2 thorpej
384 1.116.2.2 thorpej SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
385 1.116.2.2 thorpej sdunlock(sd);
386 1.116.2.2 thorpej return 0;
387 1.116.2.2 thorpej
388 1.116.2.2 thorpej bad2:
389 1.116.2.2 thorpej sc_link->flags &= ~SDEV_MEDIA_LOADED;
390 1.116.2.2 thorpej
391 1.116.2.2 thorpej bad:
392 1.116.2.2 thorpej if (sd->sc_dk.dk_openmask == 0) {
393 1.116.2.2 thorpej scsipi_prevent(sc_link, PR_ALLOW,
394 1.116.2.2 thorpej SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE);
395 1.116.2.2 thorpej sc_link->flags &= ~SDEV_OPEN;
396 1.116.2.2 thorpej }
397 1.116.2.2 thorpej
398 1.116.2.2 thorpej bad3:
399 1.116.2.2 thorpej sdunlock(sd);
400 1.116.2.2 thorpej return error;
401 1.116.2.2 thorpej }
402 1.116.2.2 thorpej
403 1.116.2.2 thorpej /*
404 1.116.2.2 thorpej * close the device.. only called if we are the LAST occurence of an open
405 1.116.2.2 thorpej * device. Convenient now but usually a pain.
406 1.116.2.2 thorpej */
407 1.116.2.2 thorpej int
408 1.116.2.2 thorpej sdclose(dev, flag, fmt, p)
409 1.116.2.2 thorpej dev_t dev;
410 1.116.2.2 thorpej int flag, fmt;
411 1.116.2.2 thorpej struct proc *p;
412 1.116.2.2 thorpej {
413 1.116.2.2 thorpej struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(dev)];
414 1.116.2.2 thorpej int part = SDPART(dev);
415 1.116.2.2 thorpej int error;
416 1.116.2.2 thorpej
417 1.116.2.2 thorpej if ((error = sdlock(sd)) != 0)
418 1.116.2.2 thorpej return error;
419 1.116.2.2 thorpej
420 1.116.2.2 thorpej switch (fmt) {
421 1.116.2.2 thorpej case S_IFCHR:
422 1.116.2.2 thorpej sd->sc_dk.dk_copenmask &= ~(1 << part);
423 1.116.2.2 thorpej break;
424 1.116.2.2 thorpej case S_IFBLK:
425 1.116.2.2 thorpej sd->sc_dk.dk_bopenmask &= ~(1 << part);
426 1.116.2.2 thorpej break;
427 1.116.2.2 thorpej }
428 1.116.2.2 thorpej sd->sc_dk.dk_openmask = sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
429 1.116.2.2 thorpej
430 1.116.2.2 thorpej if (sd->sc_dk.dk_openmask == 0) {
431 1.116.2.2 thorpej /* XXXX Must wait for I/O to complete! */
432 1.116.2.2 thorpej
433 1.116.2.2 thorpej scsipi_prevent(sd->sc_link, PR_ALLOW,
434 1.116.2.2 thorpej SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
435 1.116.2.2 thorpej sd->sc_link->flags &= ~(SDEV_OPEN|SDEV_MEDIA_LOADED);
436 1.116.2.2 thorpej }
437 1.116.2.2 thorpej
438 1.116.2.2 thorpej sdunlock(sd);
439 1.116.2.2 thorpej return 0;
440 1.116.2.2 thorpej }
441 1.116.2.2 thorpej
442 1.116.2.2 thorpej /*
443 1.116.2.2 thorpej * Actually translate the requested transfer into one the physical driver
444 1.116.2.2 thorpej * can understand. The transfer is described by a buf and will include
445 1.116.2.2 thorpej * only one physical transfer.
446 1.116.2.2 thorpej */
447 1.116.2.2 thorpej void
448 1.116.2.2 thorpej sdstrategy(bp)
449 1.116.2.2 thorpej struct buf *bp;
450 1.116.2.2 thorpej {
451 1.116.2.2 thorpej struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(bp->b_dev)];
452 1.116.2.2 thorpej int s;
453 1.116.2.2 thorpej
454 1.116.2.2 thorpej SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy "));
455 1.116.2.2 thorpej SC_DEBUG(sd->sc_link, SDEV_DB1,
456 1.116.2.2 thorpej ("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
457 1.116.2.2 thorpej /*
458 1.116.2.2 thorpej * The transfer must be a whole number of blocks.
459 1.116.2.2 thorpej */
460 1.116.2.2 thorpej if ((bp->b_bcount % sd->sc_dk.dk_label->d_secsize) != 0) {
461 1.116.2.2 thorpej bp->b_error = EINVAL;
462 1.116.2.2 thorpej goto bad;
463 1.116.2.2 thorpej }
464 1.116.2.2 thorpej /*
465 1.116.2.2 thorpej * If the device has been made invalid, error out
466 1.116.2.2 thorpej */
467 1.116.2.2 thorpej if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
468 1.116.2.2 thorpej bp->b_error = EIO;
469 1.116.2.2 thorpej goto bad;
470 1.116.2.2 thorpej }
471 1.116.2.2 thorpej /*
472 1.116.2.2 thorpej * If it's a null transfer, return immediatly
473 1.116.2.2 thorpej */
474 1.116.2.2 thorpej if (bp->b_bcount == 0)
475 1.116.2.2 thorpej goto done;
476 1.116.2.2 thorpej
477 1.116.2.2 thorpej /*
478 1.116.2.2 thorpej * Do bounds checking, adjust transfer. if error, process.
479 1.116.2.2 thorpej * If end of partition, just return.
480 1.116.2.2 thorpej */
481 1.116.2.2 thorpej if (SDPART(bp->b_dev) != RAW_PART &&
482 1.116.2.2 thorpej bounds_check_with_label(bp, sd->sc_dk.dk_label,
483 1.116.2.2 thorpej (sd->flags & (SDF_WLABEL|SDF_LABELLING)) != 0) <= 0)
484 1.116.2.2 thorpej goto done;
485 1.116.2.2 thorpej
486 1.116.2.2 thorpej s = splbio();
487 1.116.2.2 thorpej
488 1.116.2.2 thorpej /*
489 1.116.2.2 thorpej * Place it in the queue of disk activities for this disk
490 1.116.2.2 thorpej */
491 1.116.2.2 thorpej disksort(&sd->buf_queue, bp);
492 1.116.2.2 thorpej
493 1.116.2.2 thorpej /*
494 1.116.2.2 thorpej * Tell the device to get going on the transfer if it's
495 1.116.2.2 thorpej * not doing anything, otherwise just wait for completion
496 1.116.2.2 thorpej */
497 1.116.2.2 thorpej sdstart(sd);
498 1.116.2.2 thorpej
499 1.116.2.2 thorpej splx(s);
500 1.116.2.2 thorpej return;
501 1.116.2.2 thorpej
502 1.116.2.2 thorpej bad:
503 1.116.2.2 thorpej bp->b_flags |= B_ERROR;
504 1.116.2.2 thorpej done:
505 1.116.2.2 thorpej /*
506 1.116.2.2 thorpej * Correctly set the buf to indicate a completed xfer
507 1.116.2.2 thorpej */
508 1.116.2.2 thorpej bp->b_resid = bp->b_bcount;
509 1.116.2.2 thorpej biodone(bp);
510 1.116.2.2 thorpej }
511 1.116.2.2 thorpej
512 1.116.2.2 thorpej /*
513 1.116.2.2 thorpej * sdstart looks to see if there is a buf waiting for the device
514 1.116.2.2 thorpej * and that the device is not already busy. If both are true,
515 1.116.2.2 thorpej * It dequeues the buf and creates a scsi command to perform the
516 1.116.2.2 thorpej * transfer in the buf. The transfer request will call scsipi_done
517 1.116.2.2 thorpej * on completion, which will in turn call this routine again
518 1.116.2.2 thorpej * so that the next queued transfer is performed.
519 1.116.2.2 thorpej * The bufs are queued by the strategy routine (sdstrategy)
520 1.116.2.2 thorpej *
521 1.116.2.2 thorpej * This routine is also called after other non-queued requests
522 1.116.2.2 thorpej * have been made of the scsi driver, to ensure that the queue
523 1.116.2.2 thorpej * continues to be drained.
524 1.116.2.2 thorpej *
525 1.116.2.2 thorpej * must be called at the correct (highish) spl level
526 1.116.2.2 thorpej * sdstart() is called at splbio from sdstrategy and scsipi_done
527 1.116.2.2 thorpej */
528 1.116.2.2 thorpej void
529 1.116.2.2 thorpej sdstart(v)
530 1.116.2.2 thorpej register void *v;
531 1.116.2.2 thorpej {
532 1.116.2.2 thorpej register struct sd_softc *sd = v;
533 1.116.2.2 thorpej register struct scsipi_link *sc_link = sd->sc_link;
534 1.116.2.2 thorpej struct buf *bp = 0;
535 1.116.2.2 thorpej struct buf *dp;
536 1.116.2.2 thorpej struct scsipi_rw_big cmd_big;
537 1.116.2.2 thorpej struct scsi_rw cmd_small;
538 1.116.2.2 thorpej struct scsipi_generic *cmdp;
539 1.116.2.2 thorpej int blkno, nblks, cmdlen, error;
540 1.116.2.2 thorpej struct partition *p;
541 1.116.2.2 thorpej
542 1.116.2.2 thorpej SC_DEBUG(sc_link, SDEV_DB2, ("sdstart "));
543 1.116.2.2 thorpej /*
544 1.116.2.2 thorpej * Check if the device has room for another command
545 1.116.2.2 thorpej */
546 1.116.2.2 thorpej while (sc_link->openings > 0) {
547 1.116.2.2 thorpej /*
548 1.116.2.2 thorpej * there is excess capacity, but a special waits
549 1.116.2.2 thorpej * It'll need the adapter as soon as we clear out of the
550 1.116.2.2 thorpej * way and let it run (user level wait).
551 1.116.2.2 thorpej */
552 1.116.2.2 thorpej if (sc_link->flags & SDEV_WAITING) {
553 1.116.2.2 thorpej sc_link->flags &= ~SDEV_WAITING;
554 1.116.2.2 thorpej wakeup((caddr_t)sc_link);
555 1.116.2.2 thorpej return;
556 1.116.2.2 thorpej }
557 1.116.2.2 thorpej
558 1.116.2.2 thorpej /*
559 1.116.2.2 thorpej * See if there is a buf with work for us to do..
560 1.116.2.2 thorpej */
561 1.116.2.2 thorpej dp = &sd->buf_queue;
562 1.116.2.2 thorpej if ((bp = dp->b_actf) == NULL) /* yes, an assign */
563 1.116.2.2 thorpej return;
564 1.116.2.2 thorpej dp->b_actf = bp->b_actf;
565 1.116.2.2 thorpej
566 1.116.2.2 thorpej /*
567 1.116.2.2 thorpej * If the device has become invalid, abort all the
568 1.116.2.2 thorpej * reads and writes until all files have been closed and
569 1.116.2.2 thorpej * re-opened
570 1.116.2.2 thorpej */
571 1.116.2.2 thorpej if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
572 1.116.2.2 thorpej bp->b_error = EIO;
573 1.116.2.2 thorpej bp->b_flags |= B_ERROR;
574 1.116.2.2 thorpej bp->b_resid = bp->b_bcount;
575 1.116.2.2 thorpej biodone(bp);
576 1.116.2.2 thorpej continue;
577 1.116.2.2 thorpej }
578 1.116.2.2 thorpej
579 1.116.2.2 thorpej /*
580 1.116.2.2 thorpej * We have a buf, now we should make a command
581 1.116.2.2 thorpej *
582 1.116.2.2 thorpej * First, translate the block to absolute and put it in terms
583 1.116.2.2 thorpej * of the logical blocksize of the device.
584 1.116.2.2 thorpej */
585 1.116.2.2 thorpej blkno =
586 1.116.2.2 thorpej bp->b_blkno / (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
587 1.116.2.2 thorpej if (SDPART(bp->b_dev) != RAW_PART) {
588 1.116.2.2 thorpej p = &sd->sc_dk.dk_label->d_partitions[SDPART(bp->b_dev)];
589 1.116.2.2 thorpej blkno += p->p_offset;
590 1.116.2.2 thorpej }
591 1.116.2.2 thorpej nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label->d_secsize);
592 1.116.2.2 thorpej
593 1.116.2.2 thorpej /*
594 1.116.2.2 thorpej * Fill out the scsi command. If the transfer will
595 1.116.2.2 thorpej * fit in a "small" cdb, use it.
596 1.116.2.2 thorpej */
597 1.116.2.2 thorpej if (((blkno & 0x1fffff) == blkno) &&
598 1.116.2.2 thorpej ((nblks & 0xff) == nblks)) {
599 1.116.2.2 thorpej /*
600 1.116.2.2 thorpej * We can fit in a small cdb.
601 1.116.2.2 thorpej */
602 1.116.2.2 thorpej bzero(&cmd_small, sizeof(cmd_small));
603 1.116.2.2 thorpej cmd_small.opcode = (bp->b_flags & B_READ) ?
604 1.116.2.2 thorpej SCSI_READ_COMMAND : SCSI_WRITE_COMMAND;
605 1.116.2.2 thorpej _lto3b(blkno, cmd_small.addr);
606 1.116.2.2 thorpej cmd_small.length = nblks & 0xff;
607 1.116.2.2 thorpej cmdlen = sizeof(cmd_small);
608 1.116.2.2 thorpej cmdp = (struct scsipi_generic *)&cmd_small;
609 1.116.2.2 thorpej } else {
610 1.116.2.2 thorpej /*
611 1.116.2.2 thorpej * Need a large cdb.
612 1.116.2.2 thorpej */
613 1.116.2.2 thorpej bzero(&cmd_big, sizeof(cmd_big));
614 1.116.2.2 thorpej cmd_big.opcode = (bp->b_flags & B_READ) ?
615 1.116.2.2 thorpej READ_BIG : WRITE_BIG;
616 1.116.2.2 thorpej _lto4b(blkno, cmd_big.addr);
617 1.116.2.2 thorpej _lto2b(nblks, cmd_big.length);
618 1.116.2.2 thorpej cmdlen = sizeof(cmd_big);
619 1.116.2.2 thorpej cmdp = (struct scsipi_generic *)&cmd_big;
620 1.116.2.2 thorpej }
621 1.116.2.2 thorpej
622 1.116.2.2 thorpej /* Instrumentation. */
623 1.116.2.2 thorpej disk_busy(&sd->sc_dk);
624 1.116.2.2 thorpej
625 1.116.2.2 thorpej /*
626 1.116.2.2 thorpej * Call the routine that chats with the adapter.
627 1.116.2.2 thorpej * Note: we cannot sleep as we may be an interrupt
628 1.116.2.2 thorpej */
629 1.116.2.2 thorpej error = sc_link->scsipi_cmd(sc_link, cmdp, cmdlen,
630 1.116.2.2 thorpej (u_char *)bp->b_data, bp->b_bcount,
631 1.116.2.2 thorpej SDRETRIES, 60000, bp, SCSI_NOSLEEP |
632 1.116.2.2 thorpej ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT));
633 1.116.2.2 thorpej if (error)
634 1.116.2.2 thorpej printf("%s: not queued, error %d\n",
635 1.116.2.2 thorpej sd->sc_dev.dv_xname, error);
636 1.116.2.2 thorpej }
637 1.116.2.2 thorpej }
638 1.116.2.2 thorpej
639 1.116.2.2 thorpej void
640 1.116.2.2 thorpej sddone(xs)
641 1.116.2.2 thorpej struct scsipi_xfer *xs;
642 1.116.2.2 thorpej {
643 1.116.2.2 thorpej struct sd_softc *sd = xs->sc_link->device_softc;
644 1.116.2.2 thorpej
645 1.116.2.2 thorpej if (xs->bp != NULL)
646 1.116.2.2 thorpej disk_unbusy(&sd->sc_dk, xs->bp->b_bcount - xs->bp->b_resid);
647 1.116.2.2 thorpej }
648 1.116.2.2 thorpej
649 1.116.2.2 thorpej void
650 1.116.2.2 thorpej sdminphys(bp)
651 1.116.2.2 thorpej struct buf *bp;
652 1.116.2.2 thorpej {
653 1.116.2.2 thorpej struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(bp->b_dev)];
654 1.116.2.2 thorpej long max;
655 1.116.2.2 thorpej
656 1.116.2.2 thorpej /*
657 1.116.2.2 thorpej * If the device is ancient, we want to make sure that
658 1.116.2.2 thorpej * the transfer fits into a 6-byte cdb.
659 1.116.2.2 thorpej *
660 1.116.2.2 thorpej * XXX Note that the SCSI-I spec says that 256-block transfers
661 1.116.2.2 thorpej * are allowed in a 6-byte read/write, and are specified
662 1.116.2.2 thorpej * by settng the "length" to 0. However, we're conservative
663 1.116.2.2 thorpej * here, allowing only 255-block transfers in case an
664 1.116.2.2 thorpej * ancient device gets confused by length == 0. A length of 0
665 1.116.2.2 thorpej * in a 10-byte read/write actually means 0 blocks.
666 1.116.2.2 thorpej */
667 1.116.2.2 thorpej if (sd->flags & SDF_ANCIENT) {
668 1.116.2.2 thorpej max = sd->sc_dk.dk_label->d_secsize * 0xff;
669 1.116.2.2 thorpej
670 1.116.2.2 thorpej if (bp->b_bcount > max)
671 1.116.2.2 thorpej bp->b_bcount = max;
672 1.116.2.2 thorpej }
673 1.116.2.2 thorpej
674 1.116.2.2 thorpej (*sd->sc_link->adapter->scsipi_minphys)(bp);
675 1.116.2.2 thorpej }
676 1.116.2.2 thorpej
677 1.116.2.2 thorpej int
678 1.116.2.2 thorpej sdread(dev, uio, ioflag)
679 1.116.2.2 thorpej dev_t dev;
680 1.116.2.2 thorpej struct uio *uio;
681 1.116.2.2 thorpej int ioflag;
682 1.116.2.2 thorpej {
683 1.116.2.2 thorpej
684 1.116.2.2 thorpej return (physio(sdstrategy, NULL, dev, B_READ, sdminphys, uio));
685 1.116.2.2 thorpej }
686 1.116.2.2 thorpej
687 1.116.2.2 thorpej int
688 1.116.2.2 thorpej sdwrite(dev, uio, ioflag)
689 1.116.2.2 thorpej dev_t dev;
690 1.116.2.2 thorpej struct uio *uio;
691 1.116.2.2 thorpej int ioflag;
692 1.116.2.2 thorpej {
693 1.116.2.2 thorpej
694 1.116.2.2 thorpej return (physio(sdstrategy, NULL, dev, B_WRITE, sdminphys, uio));
695 1.116.2.2 thorpej }
696 1.116.2.2 thorpej
697 1.116.2.2 thorpej /*
698 1.116.2.2 thorpej * Perform special action on behalf of the user
699 1.116.2.2 thorpej * Knows about the internals of this device
700 1.116.2.2 thorpej */
701 1.116.2.2 thorpej int
702 1.116.2.2 thorpej sdioctl(dev, cmd, addr, flag, p)
703 1.116.2.2 thorpej dev_t dev;
704 1.116.2.2 thorpej u_long cmd;
705 1.116.2.2 thorpej caddr_t addr;
706 1.116.2.2 thorpej int flag;
707 1.116.2.2 thorpej struct proc *p;
708 1.116.2.2 thorpej {
709 1.116.2.2 thorpej struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(dev)];
710 1.116.2.2 thorpej int error;
711 1.116.2.2 thorpej
712 1.116.2.2 thorpej SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdioctl 0x%lx ", cmd));
713 1.116.2.2 thorpej
714 1.116.2.2 thorpej /*
715 1.116.2.2 thorpej * If the device is not valid.. abandon ship
716 1.116.2.2 thorpej */
717 1.116.2.2 thorpej if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0)
718 1.116.2.2 thorpej return EIO;
719 1.116.2.2 thorpej
720 1.116.2.2 thorpej switch (cmd) {
721 1.116.2.2 thorpej case DIOCGDINFO:
722 1.116.2.2 thorpej *(struct disklabel *)addr = *(sd->sc_dk.dk_label);
723 1.116.2.2 thorpej return 0;
724 1.116.2.2 thorpej
725 1.116.2.2 thorpej case DIOCGPART:
726 1.116.2.2 thorpej ((struct partinfo *)addr)->disklab = sd->sc_dk.dk_label;
727 1.116.2.2 thorpej ((struct partinfo *)addr)->part =
728 1.116.2.2 thorpej &sd->sc_dk.dk_label->d_partitions[SDPART(dev)];
729 1.116.2.2 thorpej return 0;
730 1.116.2.2 thorpej
731 1.116.2.2 thorpej case DIOCWDINFO:
732 1.116.2.2 thorpej case DIOCSDINFO:
733 1.116.2.2 thorpej if ((flag & FWRITE) == 0)
734 1.116.2.2 thorpej return EBADF;
735 1.116.2.2 thorpej
736 1.116.2.2 thorpej if ((error = sdlock(sd)) != 0)
737 1.116.2.2 thorpej return error;
738 1.116.2.2 thorpej sd->flags |= SDF_LABELLING;
739 1.116.2.2 thorpej
740 1.116.2.2 thorpej error = setdisklabel(sd->sc_dk.dk_label,
741 1.116.2.2 thorpej (struct disklabel *)addr, /*sd->sc_dk.dk_openmask : */0,
742 1.116.2.2 thorpej sd->sc_dk.dk_cpulabel);
743 1.116.2.2 thorpej if (error == 0) {
744 1.116.2.2 thorpej if (cmd == DIOCWDINFO)
745 1.116.2.2 thorpej error = writedisklabel(SDLABELDEV(dev),
746 1.116.2.2 thorpej sdstrategy, sd->sc_dk.dk_label,
747 1.116.2.2 thorpej sd->sc_dk.dk_cpulabel);
748 1.116.2.2 thorpej }
749 1.116.2.2 thorpej
750 1.116.2.2 thorpej sd->flags &= ~SDF_LABELLING;
751 1.116.2.2 thorpej sdunlock(sd);
752 1.116.2.2 thorpej return error;
753 1.116.2.2 thorpej
754 1.116.2.2 thorpej case DIOCWLABEL:
755 1.116.2.2 thorpej if ((flag & FWRITE) == 0)
756 1.116.2.2 thorpej return EBADF;
757 1.116.2.2 thorpej if (*(int *)addr)
758 1.116.2.2 thorpej sd->flags |= SDF_WLABEL;
759 1.116.2.2 thorpej else
760 1.116.2.2 thorpej sd->flags &= ~SDF_WLABEL;
761 1.116.2.2 thorpej return 0;
762 1.116.2.2 thorpej
763 1.116.2.2 thorpej case DIOCLOCK:
764 1.116.2.2 thorpej return scsipi_prevent(sd->sc_link,
765 1.116.2.2 thorpej (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0);
766 1.116.2.2 thorpej
767 1.116.2.2 thorpej case DIOCEJECT:
768 1.116.2.2 thorpej return ((sd->sc_link->flags & SDEV_REMOVABLE) == 0 ? ENOTTY :
769 1.116.2.2 thorpej scsipi_start(sd->sc_link, SSS_STOP|SSS_LOEJ, 0));
770 1.116.2.2 thorpej
771 1.116.2.2 thorpej default:
772 1.116.2.2 thorpej if (SDPART(dev) != RAW_PART)
773 1.116.2.2 thorpej return ENOTTY;
774 1.116.2.2 thorpej return scsipi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p);
775 1.116.2.2 thorpej }
776 1.116.2.2 thorpej
777 1.116.2.2 thorpej #ifdef DIAGNOSTIC
778 1.116.2.2 thorpej panic("sdioctl: impossible");
779 1.116.2.2 thorpej #endif
780 1.116.2.2 thorpej }
781 1.116.2.2 thorpej
782 1.116.2.2 thorpej /*
783 1.116.2.2 thorpej * Load the label information on the named device
784 1.116.2.2 thorpej */
785 1.116.2.2 thorpej void
786 1.116.2.2 thorpej sdgetdisklabel(sd)
787 1.116.2.2 thorpej struct sd_softc *sd;
788 1.116.2.2 thorpej {
789 1.116.2.2 thorpej struct disklabel *lp = sd->sc_dk.dk_label;
790 1.116.2.2 thorpej char *errstring;
791 1.116.2.2 thorpej
792 1.116.2.2 thorpej bzero(lp, sizeof(struct disklabel));
793 1.116.2.2 thorpej bzero(sd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
794 1.116.2.2 thorpej
795 1.116.2.2 thorpej lp->d_secsize = sd->params.blksize;
796 1.116.2.2 thorpej lp->d_ntracks = sd->params.heads;
797 1.116.2.2 thorpej lp->d_nsectors = sd->params.sectors;
798 1.116.2.2 thorpej lp->d_ncylinders = sd->params.cyls;
799 1.116.2.2 thorpej lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
800 1.116.2.2 thorpej if (lp->d_secpercyl == 0) {
801 1.116.2.2 thorpej lp->d_secpercyl = 100;
802 1.116.2.2 thorpej /* as long as it's not 0 - readdisklabel divides by it (?) */
803 1.116.2.2 thorpej }
804 1.116.2.2 thorpej
805 1.116.2.2 thorpej if (sd->type == T_OPTICAL)
806 1.116.2.2 thorpej strncpy(lp->d_typename, "SCSI optical", 16);
807 1.116.2.2 thorpej else
808 1.116.2.2 thorpej strncpy(lp->d_typename, "SCSI disk", 16);
809 1.116.2.2 thorpej lp->d_type = DTYPE_SCSI;
810 1.116.2.2 thorpej strncpy(lp->d_packname, "fictitious", 16);
811 1.116.2.2 thorpej lp->d_secperunit = sd->params.disksize;
812 1.116.2.2 thorpej lp->d_rpm = 3600;
813 1.116.2.2 thorpej lp->d_interleave = 1;
814 1.116.2.2 thorpej lp->d_flags = 0;
815 1.116.2.2 thorpej
816 1.116.2.2 thorpej lp->d_partitions[RAW_PART].p_offset = 0;
817 1.116.2.2 thorpej lp->d_partitions[RAW_PART].p_size =
818 1.116.2.2 thorpej lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
819 1.116.2.2 thorpej lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
820 1.116.2.2 thorpej lp->d_npartitions = RAW_PART + 1;
821 1.116.2.2 thorpej
822 1.116.2.2 thorpej lp->d_magic = DISKMAGIC;
823 1.116.2.2 thorpej lp->d_magic2 = DISKMAGIC;
824 1.116.2.2 thorpej lp->d_checksum = dkcksum(lp);
825 1.116.2.2 thorpej
826 1.116.2.2 thorpej /*
827 1.116.2.2 thorpej * Call the generic disklabel extraction routine
828 1.116.2.2 thorpej */
829 1.116.2.2 thorpej errstring = readdisklabel(MAKESDDEV(0, sd->sc_dev.dv_unit, RAW_PART),
830 1.116.2.2 thorpej sdstrategy, lp, sd->sc_dk.dk_cpulabel);
831 1.116.2.2 thorpej if (errstring) {
832 1.116.2.2 thorpej printf("%s: %s\n", sd->sc_dev.dv_xname, errstring);
833 1.116.2.2 thorpej return;
834 1.116.2.2 thorpej }
835 1.116.2.2 thorpej }
836 1.116.2.2 thorpej
837 1.116.2.2 thorpej /*
838 1.116.2.2 thorpej * Tell the device to map out a defective block
839 1.116.2.2 thorpej */
840 1.116.2.2 thorpej int
841 1.116.2.2 thorpej sd_reassign_blocks(sd, blkno)
842 1.116.2.2 thorpej struct sd_softc *sd;
843 1.116.2.2 thorpej u_long blkno;
844 1.116.2.2 thorpej {
845 1.116.2.2 thorpej struct scsi_reassign_blocks scsipi_cmd;
846 1.116.2.2 thorpej struct scsi_reassign_blocks_data rbdata;
847 1.116.2.2 thorpej
848 1.116.2.2 thorpej bzero(&scsipi_cmd, sizeof(scsipi_cmd));
849 1.116.2.2 thorpej bzero(&rbdata, sizeof(rbdata));
850 1.116.2.2 thorpej scsipi_cmd.opcode = SCSI_REASSIGN_BLOCKS;
851 1.116.2.2 thorpej
852 1.116.2.2 thorpej _lto2b(sizeof(rbdata.defect_descriptor[0]), rbdata.length);
853 1.116.2.2 thorpej _lto4b(blkno, rbdata.defect_descriptor[0].dlbaddr);
854 1.116.2.2 thorpej
855 1.116.2.2 thorpej return sd->sc_link->scsipi_cmd(sd->sc_link,
856 1.116.2.2 thorpej (struct scsipi_generic *)&scsipi_cmd,
857 1.116.2.2 thorpej sizeof(scsipi_cmd), (u_char *)&rbdata, sizeof(rbdata), SDRETRIES,
858 1.116.2.2 thorpej 5000, NULL, SCSI_DATA_OUT);
859 1.116.2.2 thorpej }
860 1.116.2.2 thorpej
861 1.116.2.2 thorpej
862 1.116.2.2 thorpej
863 1.116.2.2 thorpej static int
864 1.116.2.2 thorpej sd_mode_sense(sd, scsipi_sense, page, flags)
865 1.116.2.2 thorpej struct sd_softc *sd;
866 1.116.2.2 thorpej struct scsi_mode_sense_data *scsipi_sense;
867 1.116.2.2 thorpej int page, flags;
868 1.116.2.2 thorpej {
869 1.116.2.2 thorpej struct scsi_mode_sense scsipi_cmd;
870 1.116.2.2 thorpej
871 1.116.2.2 thorpej /*
872 1.116.2.2 thorpej * Make sure the sense buffer is clean before we do
873 1.116.2.2 thorpej * the mode sense, so that checks for bogus values of
874 1.116.2.2 thorpej * 0 will work in case the mode sense fails.
875 1.116.2.2 thorpej */
876 1.116.2.2 thorpej bzero(scsipi_sense, sizeof(*scsipi_sense));
877 1.116.2.2 thorpej
878 1.116.2.2 thorpej bzero(&scsipi_cmd, sizeof(scsipi_cmd));
879 1.116.2.2 thorpej scsipi_cmd.opcode = SCSI_MODE_SENSE;
880 1.116.2.2 thorpej scsipi_cmd.page = page;
881 1.116.2.2 thorpej scsipi_cmd.length = 0x20;
882 1.116.2.2 thorpej /*
883 1.116.2.2 thorpej * If the command worked, use the results to fill out
884 1.116.2.2 thorpej * the parameter structure
885 1.116.2.2 thorpej */
886 1.116.2.2 thorpej return sd->sc_link->scsipi_cmd(sd->sc_link,
887 1.116.2.2 thorpej (struct scsipi_generic *)&scsipi_cmd,
888 1.116.2.2 thorpej sizeof(scsipi_cmd), (u_char *)scsipi_sense, sizeof(*scsipi_sense),
889 1.116.2.2 thorpej SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN | SCSI_SILENT);
890 1.116.2.2 thorpej }
891 1.116.2.2 thorpej
892 1.116.2.2 thorpej int
893 1.116.2.2 thorpej sd_get_optparms(sd, flags, dp)
894 1.116.2.2 thorpej struct sd_softc *sd;
895 1.116.2.2 thorpej int flags;
896 1.116.2.2 thorpej struct disk_parms *dp;
897 1.116.2.2 thorpej {
898 1.116.2.2 thorpej struct scsi_mode_sense scsipi_cmd;
899 1.116.2.2 thorpej struct scsi_mode_sense_data {
900 1.116.2.2 thorpej struct scsi_mode_header header;
901 1.116.2.2 thorpej struct scsi_blk_desc blk_desc;
902 1.116.2.2 thorpej union scsi_disk_pages pages;
903 1.116.2.2 thorpej } scsipi_sense;
904 1.116.2.2 thorpej u_long sectors;
905 1.116.2.2 thorpej int error;
906 1.116.2.2 thorpej
907 1.116.2.2 thorpej dp->blksize = 512;
908 1.116.2.2 thorpej if ((sectors = scsipi_size(sd->sc_link, flags)) == 0)
909 1.116.2.2 thorpej return 1;
910 1.116.2.2 thorpej
911 1.116.2.2 thorpej /* XXX
912 1.116.2.2 thorpej * It is better to get the following params from the
913 1.116.2.2 thorpej * mode sense page 6 only (optical device parameter page).
914 1.116.2.2 thorpej * However, there are stupid optical devices which does NOT
915 1.116.2.2 thorpej * support the page 6. Ghaa....
916 1.116.2.2 thorpej */
917 1.116.2.2 thorpej bzero(&scsipi_cmd, sizeof(scsipi_cmd));
918 1.116.2.2 thorpej scsipi_cmd.opcode = SCSI_MODE_SENSE;
919 1.116.2.2 thorpej scsipi_cmd.page = 0x3f; /* all pages */
920 1.116.2.2 thorpej scsipi_cmd.length = sizeof(struct scsi_mode_header) +
921 1.116.2.2 thorpej sizeof(struct scsi_blk_desc);
922 1.116.2.2 thorpej
923 1.116.2.2 thorpej if ((error = sd->sc_link->scsipi_cmd(sd->sc_link,
924 1.116.2.2 thorpej (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
925 1.116.2.2 thorpej (u_char *)&scsipi_sense, sizeof(scsipi_sense), SDRETRIES,
926 1.116.2.2 thorpej 6000, NULL, flags | SCSI_DATA_IN)) != 0)
927 1.116.2.2 thorpej return error;
928 1.116.2.2 thorpej
929 1.116.2.2 thorpej dp->blksize = _3btol(scsipi_sense.blk_desc.blklen);
930 1.116.2.2 thorpej if (dp->blksize == 0)
931 1.116.2.2 thorpej dp->blksize = 512;
932 1.116.2.2 thorpej
933 1.116.2.2 thorpej /*
934 1.116.2.2 thorpej * Create a pseudo-geometry.
935 1.116.2.2 thorpej */
936 1.116.2.2 thorpej dp->heads = 64;
937 1.116.2.2 thorpej dp->sectors = 32;
938 1.116.2.2 thorpej dp->cyls = sectors / (dp->heads * dp->sectors);
939 1.116.2.2 thorpej dp->disksize = sectors;
940 1.116.2.2 thorpej
941 1.116.2.2 thorpej return 0;
942 1.116.2.2 thorpej }
943 1.116.2.2 thorpej
944 1.116.2.2 thorpej /*
945 1.116.2.2 thorpej * Get the scsi driver to send a full inquiry to the * device and use the
946 1.116.2.2 thorpej * results to fill out the disk parameter structure.
947 1.116.2.2 thorpej */
948 1.116.2.2 thorpej int
949 1.116.2.2 thorpej sd_get_parms(sd, flags)
950 1.116.2.2 thorpej struct sd_softc *sd;
951 1.116.2.2 thorpej int flags;
952 1.116.2.2 thorpej {
953 1.116.2.2 thorpej struct disk_parms *dp = &sd->params;
954 1.116.2.2 thorpej struct scsi_mode_sense_data scsipi_sense;
955 1.116.2.2 thorpej u_long sectors;
956 1.116.2.2 thorpej int page;
957 1.116.2.2 thorpej int error;
958 1.116.2.2 thorpej
959 1.116.2.2 thorpej if (sd->type == T_OPTICAL) {
960 1.116.2.2 thorpej if ((error = sd_get_optparms(sd, flags, dp)) != 0)
961 1.116.2.2 thorpej sd->sc_link->flags &= ~SDEV_MEDIA_LOADED;
962 1.116.2.2 thorpej return error;
963 1.116.2.2 thorpej }
964 1.116.2.2 thorpej
965 1.116.2.2 thorpej if ((error = sd_mode_sense(sd, &scsipi_sense, page = 4, flags)) == 0) {
966 1.116.2.2 thorpej SC_DEBUG(sd->sc_link, SDEV_DB3,
967 1.116.2.2 thorpej ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
968 1.116.2.2 thorpej _3btol(scsipi_sense.pages.rigid_geometry.ncyl),
969 1.116.2.2 thorpej scsipi_sense.pages.rigid_geometry.nheads,
970 1.116.2.2 thorpej _2btol(scsipi_sense.pages.rigid_geometry.st_cyl_wp),
971 1.116.2.2 thorpej _2btol(scsipi_sense.pages.rigid_geometry.st_cyl_rwc),
972 1.116.2.2 thorpej _2btol(scsipi_sense.pages.rigid_geometry.land_zone)));
973 1.116.2.2 thorpej
974 1.116.2.2 thorpej /*
975 1.116.2.2 thorpej * KLUDGE!! (for zone recorded disks)
976 1.116.2.2 thorpej * give a number of sectors so that sec * trks * cyls
977 1.116.2.2 thorpej * is <= disk_size
978 1.116.2.2 thorpej * can lead to wasted space! THINK ABOUT THIS !
979 1.116.2.2 thorpej */
980 1.116.2.2 thorpej dp->heads = scsipi_sense.pages.rigid_geometry.nheads;
981 1.116.2.2 thorpej dp->cyls = _3btol(scsipi_sense.pages.rigid_geometry.ncyl);
982 1.116.2.2 thorpej dp->blksize = _3btol(scsipi_sense.blk_desc.blklen);
983 1.116.2.2 thorpej
984 1.116.2.2 thorpej if (dp->heads == 0 || dp->cyls == 0)
985 1.116.2.2 thorpej goto fake_it;
986 1.116.2.2 thorpej
987 1.116.2.2 thorpej if (dp->blksize == 0)
988 1.116.2.2 thorpej dp->blksize = 512;
989 1.116.2.2 thorpej
990 1.116.2.2 thorpej sectors = scsipi_size(sd->sc_link, flags);
991 1.116.2.2 thorpej dp->disksize = sectors;
992 1.116.2.2 thorpej sectors /= (dp->heads * dp->cyls);
993 1.116.2.2 thorpej dp->sectors = sectors; /* XXX dubious on SCSI */
994 1.116.2.2 thorpej
995 1.116.2.2 thorpej return 0;
996 1.116.2.2 thorpej }
997 1.116.2.2 thorpej
998 1.116.2.2 thorpej if ((error = sd_mode_sense(sd, &scsipi_sense, page = 5, flags)) == 0) {
999 1.116.2.2 thorpej dp->heads = scsipi_sense.pages.flex_geometry.nheads;
1000 1.116.2.2 thorpej dp->cyls = _2btol(scsipi_sense.pages.flex_geometry.ncyl);
1001 1.116.2.2 thorpej dp->blksize = _3btol(scsipi_sense.blk_desc.blklen);
1002 1.116.2.2 thorpej dp->sectors = scsipi_sense.pages.flex_geometry.ph_sec_tr;
1003 1.116.2.2 thorpej dp->disksize = dp->heads * dp->cyls * dp->sectors;
1004 1.116.2.2 thorpej if (dp->disksize == 0)
1005 1.116.2.2 thorpej goto fake_it;
1006 1.116.2.2 thorpej
1007 1.116.2.2 thorpej if (dp->blksize == 0)
1008 1.116.2.2 thorpej dp->blksize = 512;
1009 1.116.2.2 thorpej
1010 1.116.2.2 thorpej return 0;
1011 1.116.2.2 thorpej }
1012 1.116.2.2 thorpej
1013 1.116.2.2 thorpej fake_it:
1014 1.116.2.2 thorpej if ((sd->sc_link->quirks & SDEV_NOMODESENSE) == 0) {
1015 1.116.2.2 thorpej if (error == 0)
1016 1.116.2.2 thorpej printf("%s: mode sense (%d) returned nonsense",
1017 1.116.2.2 thorpej sd->sc_dev.dv_xname, page);
1018 1.116.2.2 thorpej else
1019 1.116.2.2 thorpej printf("%s: could not mode sense (4/5)",
1020 1.116.2.2 thorpej sd->sc_dev.dv_xname);
1021 1.116.2.2 thorpej printf("; using fictitious geometry\n");
1022 1.116.2.2 thorpej }
1023 1.116.2.2 thorpej /*
1024 1.116.2.2 thorpej * use adaptec standard fictitious geometry
1025 1.116.2.2 thorpej * this depends on which controller (e.g. 1542C is
1026 1.116.2.2 thorpej * different. but we have to put SOMETHING here..)
1027 1.116.2.2 thorpej */
1028 1.116.2.2 thorpej sectors = scsipi_size(sd->sc_link, flags);
1029 1.116.2.2 thorpej dp->heads = 64;
1030 1.116.2.2 thorpej dp->sectors = 32;
1031 1.116.2.2 thorpej dp->cyls = sectors / (64 * 32);
1032 1.116.2.2 thorpej dp->blksize = 512;
1033 1.116.2.2 thorpej dp->disksize = sectors;
1034 1.116.2.2 thorpej return 0;
1035 1.116.2.2 thorpej }
1036 1.116.2.2 thorpej
1037 1.116.2.2 thorpej int
1038 1.116.2.2 thorpej sdsize(dev)
1039 1.116.2.2 thorpej dev_t dev;
1040 1.116.2.2 thorpej {
1041 1.116.2.2 thorpej struct sd_softc *sd;
1042 1.116.2.2 thorpej int part, unit, omask;
1043 1.116.2.2 thorpej int size;
1044 1.116.2.2 thorpej
1045 1.116.2.2 thorpej unit = SDUNIT(dev);
1046 1.116.2.2 thorpej if (unit >= sd_cd.cd_ndevs)
1047 1.116.2.2 thorpej return (-1);
1048 1.116.2.2 thorpej sd = sd_cd.cd_devs[unit];
1049 1.116.2.2 thorpej if (sd == NULL)
1050 1.116.2.2 thorpej return (-1);
1051 1.116.2.2 thorpej
1052 1.116.2.2 thorpej part = SDPART(dev);
1053 1.116.2.2 thorpej omask = sd->sc_dk.dk_openmask & (1 << part);
1054 1.116.2.2 thorpej
1055 1.116.2.2 thorpej if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0)
1056 1.116.2.2 thorpej return (-1);
1057 1.116.2.2 thorpej if (sd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
1058 1.116.2.2 thorpej size = -1;
1059 1.116.2.2 thorpej else
1060 1.116.2.2 thorpej size = sd->sc_dk.dk_label->d_partitions[part].p_size *
1061 1.116.2.2 thorpej (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
1062 1.116.2.2 thorpej if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0)
1063 1.116.2.2 thorpej return (-1);
1064 1.116.2.2 thorpej return (size);
1065 1.116.2.2 thorpej }
1066 1.116.2.2 thorpej
1067 1.116.2.2 thorpej #ifndef __BDEVSW_DUMP_OLD_TYPE
1068 1.116.2.2 thorpej /* #define SD_DUMP_NOT_TRUSTED if you just want to watch */
1069 1.116.2.2 thorpej static struct scsipi_xfer sx;
1070 1.116.2.2 thorpej static int sddoingadump;
1071 1.116.2.2 thorpej
1072 1.116.2.2 thorpej /*
1073 1.116.2.2 thorpej * dump all of physical memory into the partition specified, starting
1074 1.116.2.2 thorpej * at offset 'dumplo' into the partition.
1075 1.116.2.2 thorpej */
1076 1.116.2.2 thorpej int
1077 1.116.2.2 thorpej sddump(dev, blkno, va, size)
1078 1.116.2.2 thorpej dev_t dev;
1079 1.116.2.2 thorpej daddr_t blkno;
1080 1.116.2.2 thorpej caddr_t va;
1081 1.116.2.2 thorpej size_t size;
1082 1.116.2.2 thorpej {
1083 1.116.2.2 thorpej struct sd_softc *sd; /* disk unit to do the I/O */
1084 1.116.2.2 thorpej struct disklabel *lp; /* disk's disklabel */
1085 1.116.2.2 thorpej int unit, part;
1086 1.116.2.2 thorpej int sectorsize; /* size of a disk sector */
1087 1.116.2.2 thorpej int nsects; /* number of sectors in partition */
1088 1.116.2.2 thorpej int sectoff; /* sector offset of partition */
1089 1.116.2.2 thorpej int totwrt; /* total number of sectors left to write */
1090 1.116.2.2 thorpej int nwrt; /* current number of sectors to write */
1091 1.116.2.2 thorpej struct scsipi_rw_big cmd; /* write command */
1092 1.116.2.2 thorpej struct scsipi_xfer *xs; /* ... convenience */
1093 1.116.2.2 thorpej int retval;
1094 1.116.2.2 thorpej
1095 1.116.2.2 thorpej /* Check if recursive dump; if so, punt. */
1096 1.116.2.2 thorpej if (sddoingadump)
1097 1.116.2.2 thorpej return EFAULT;
1098 1.116.2.2 thorpej
1099 1.116.2.2 thorpej /* Mark as active early. */
1100 1.116.2.2 thorpej sddoingadump = 1;
1101 1.116.2.2 thorpej
1102 1.116.2.2 thorpej unit = SDUNIT(dev); /* Decompose unit & partition. */
1103 1.116.2.2 thorpej part = SDPART(dev);
1104 1.116.2.2 thorpej
1105 1.116.2.2 thorpej /* Check for acceptable drive number. */
1106 1.116.2.2 thorpej if (unit >= sd_cd.cd_ndevs || (sd = sd_cd.cd_devs[unit]) == NULL)
1107 1.116.2.2 thorpej return ENXIO;
1108 1.116.2.2 thorpej
1109 1.116.2.2 thorpej /*
1110 1.116.2.2 thorpej * XXX Can't do this check, since the media might have been
1111 1.116.2.2 thorpej * XXX marked `invalid' by successful unmounting of all
1112 1.116.2.2 thorpej * XXX filesystems.
1113 1.116.2.2 thorpej */
1114 1.116.2.2 thorpej #if 0
1115 1.116.2.2 thorpej /* Make sure it was initialized. */
1116 1.116.2.2 thorpej if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
1117 1.116.2.2 thorpej return ENXIO;
1118 1.116.2.2 thorpej #endif
1119 1.116.2.2 thorpej
1120 1.116.2.2 thorpej /* Convert to disk sectors. Request must be a multiple of size. */
1121 1.116.2.2 thorpej lp = sd->sc_dk.dk_label;
1122 1.116.2.2 thorpej sectorsize = lp->d_secsize;
1123 1.116.2.2 thorpej if ((size % sectorsize) != 0)
1124 1.116.2.2 thorpej return EFAULT;
1125 1.116.2.2 thorpej totwrt = size / sectorsize;
1126 1.116.2.2 thorpej blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */
1127 1.116.2.2 thorpej
1128 1.116.2.2 thorpej nsects = lp->d_partitions[part].p_size;
1129 1.116.2.2 thorpej sectoff = lp->d_partitions[part].p_offset;
1130 1.116.2.2 thorpej
1131 1.116.2.2 thorpej /* Check transfer bounds against partition size. */
1132 1.116.2.2 thorpej if ((blkno < 0) || ((blkno + totwrt) > nsects))
1133 1.116.2.2 thorpej return EINVAL;
1134 1.116.2.2 thorpej
1135 1.116.2.2 thorpej /* Offset block number to start of partition. */
1136 1.116.2.2 thorpej blkno += sectoff;
1137 1.116.2.2 thorpej
1138 1.116.2.2 thorpej xs = &sx;
1139 1.116.2.2 thorpej
1140 1.116.2.2 thorpej while (totwrt > 0) {
1141 1.116.2.2 thorpej nwrt = totwrt; /* XXX */
1142 1.116.2.2 thorpej #ifndef SD_DUMP_NOT_TRUSTED
1143 1.116.2.2 thorpej /*
1144 1.116.2.2 thorpej * Fill out the scsi command
1145 1.116.2.2 thorpej */
1146 1.116.2.2 thorpej bzero(&cmd, sizeof(cmd));
1147 1.116.2.2 thorpej cmd.opcode = WRITE_BIG;
1148 1.116.2.2 thorpej _lto4b(blkno, cmd.addr);
1149 1.116.2.2 thorpej _lto2b(nwrt, cmd.length);
1150 1.116.2.2 thorpej /*
1151 1.116.2.2 thorpej * Fill out the scsipi_xfer structure
1152 1.116.2.2 thorpej * Note: we cannot sleep as we may be an interrupt
1153 1.116.2.2 thorpej * don't use sc_link->scsipi_cmd() as it may want
1154 1.116.2.2 thorpej * to wait for an xs.
1155 1.116.2.2 thorpej */
1156 1.116.2.2 thorpej bzero(xs, sizeof(sx));
1157 1.116.2.2 thorpej xs->flags |= SCSI_AUTOCONF | INUSE | SCSI_DATA_OUT;
1158 1.116.2.2 thorpej xs->sc_link = sd->sc_link;
1159 1.116.2.2 thorpej xs->retries = SDRETRIES;
1160 1.116.2.2 thorpej xs->timeout = 10000; /* 10000 millisecs for a disk ! */
1161 1.116.2.2 thorpej xs->cmd = (struct scsipi_generic *)&cmd;
1162 1.116.2.2 thorpej xs->cmdlen = sizeof(cmd);
1163 1.116.2.2 thorpej xs->resid = nwrt * sectorsize;
1164 1.116.2.2 thorpej xs->error = XS_NOERROR;
1165 1.116.2.2 thorpej xs->bp = 0;
1166 1.116.2.2 thorpej xs->data = va;
1167 1.116.2.2 thorpej xs->datalen = nwrt * sectorsize;
1168 1.116.2.2 thorpej
1169 1.116.2.2 thorpej /*
1170 1.116.2.2 thorpej * Pass all this info to the scsi driver.
1171 1.116.2.2 thorpej */
1172 1.116.2.2 thorpej retval = (*(sd->sc_link->adapter->scsipi_cmd)) (xs);
1173 1.116.2.2 thorpej if (retval != COMPLETE)
1174 1.116.2.2 thorpej return ENXIO;
1175 1.116.2.2 thorpej #else /* SD_DUMP_NOT_TRUSTED */
1176 1.116.2.2 thorpej /* Let's just talk about this first... */
1177 1.116.2.2 thorpej printf("sd%d: dump addr 0x%x, blk %d\n", unit, va, blkno);
1178 1.116.2.2 thorpej delay(500 * 1000); /* half a second */
1179 1.116.2.2 thorpej #endif /* SD_DUMP_NOT_TRUSTED */
1180 1.116.2.2 thorpej
1181 1.116.2.2 thorpej /* update block count */
1182 1.116.2.2 thorpej totwrt -= nwrt;
1183 1.116.2.2 thorpej blkno += nwrt;
1184 1.116.2.2 thorpej va += sectorsize * nwrt;
1185 1.116.2.2 thorpej }
1186 1.116.2.2 thorpej sddoingadump = 0;
1187 1.116.2.2 thorpej return 0;
1188 1.116.2.2 thorpej }
1189 1.116.2.2 thorpej #else /* __BDEVSW_DUMP_NEW_TYPE */
1190 1.116.2.2 thorpej int
1191 1.116.2.2 thorpej sddump(dev, blkno, va, size)
1192 1.116.2.2 thorpej dev_t dev;
1193 1.116.2.2 thorpej daddr_t blkno;
1194 1.116.2.2 thorpej caddr_t va;
1195 1.116.2.2 thorpej size_t size;
1196 1.116.2.2 thorpej {
1197 1.116.2.2 thorpej
1198 1.116.2.2 thorpej /* Not implemented. */
1199 1.116.2.2 thorpej return ENXIO;
1200 1.116.2.2 thorpej }
1201 1.116.2.2 thorpej #endif /* __BDEVSW_DUMP_NEW_TYPE */
1202