cleanup
[unix-history] / usr / src / sys / hp300 / dev / sd.c
CommitLineData
60f56dfc
KM
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson of Lawrence Berkeley Laboratory.
7 *
8 * %sccs.include.redist.c%
9 *
029e208f 10 * @(#)sd.c 7.2 (Berkeley) %G%
60f56dfc
KM
11 */
12
13/*
14 * SCSI CCS (Command Command Set) disk driver.
15 */
16#include "sd.h"
17#if NSD > 0
18
19#ifndef lint
20static char rcsid[] = "$Header: sd.c,v 1.5 90/01/10 16:06:12 mike Locked $";
21#endif
22
23#include "param.h"
24#include "systm.h"
25#include "buf.h"
26#include "errno.h"
27#include "dkstat.h"
28#include "disklabel.h"
29#include "device.h"
30#include "malloc.h"
31#include "scsireg.h"
32
33#include "user.h"
34#include "proc.h"
35#include "uio.h"
36
37extern int scsi_test_unit_rdy();
38extern int scsi_request_sense();
39extern int scsi_inquiry();
40extern int scsi_read_capacity();
41extern int scsi_tt_write();
42extern int scsireq();
43extern int scsiustart();
44extern int scsigo();
45extern void scsifree();
46extern void scsireset();
47
48extern void printf();
49extern void bcopy();
50extern void disksort();
51extern int splbio();
52extern void splx();
53extern void biodone();
54extern int physio();
55extern void TBIS();
56
57int sdinit();
58void sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
59
60struct driver sddriver = {
61 sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr,
62};
63
64struct size {
65 u_long strtblk;
66 u_long endblk;
67 int nblocks;
68};
69
70struct sdinfo {
71 struct size part[8];
72};
73
74/*
75 * since the SCSI standard tends to hide the disk structure, we define
76 * partitions in terms of DEV_BSIZE blocks. The default partition table
77 * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg
78 * root and 32 meg of swap. The rest of the space on the drive goes in
79 * the G partition. As usual, the C partition covers the entire disk
80 * (including the boot area).
81 */
82struct sdinfo sddefaultpart = {
83 1024, 17408, 16384 , /* A */
84 17408, 82944, 65536 , /* B */
85 0, 0, 0 , /* C */
86 17408, 115712, 98304 , /* D */
87 115712, 218112, 102400 , /* E */
88 218112, 0, 0 , /* F */
89 82944, 0, 0 , /* G */
90 115712, 0, 0 , /* H */
91};
92
93struct sd_softc {
94 struct hp_device *sc_hd;
95 struct devqueue sc_dq;
96 int sc_format_pid; /* process using "format" mode */
97 short sc_flags;
98 short sc_type; /* drive type */
99 short sc_punit; /* physical unit (scsi lun) */
100 u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */
101 u_int sc_blks; /* number of blocks on device */
102 int sc_blksize; /* device block size in bytes */
103 u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */
104 struct sdinfo sc_info; /* drive partition table & label info */
105} sd_softc[NSD];
106
107/* sc_flags values */
108#define SDF_ALIVE 0x1
109
110#ifdef DEBUG
111int sddebug = 1;
112#define SDB_ERROR 0x01
113#define SDB_PARTIAL 0x02
114#endif
115
116struct sdstats {
117 long sdresets;
118 long sdtransfers;
119 long sdpartials;
120} sdstats[NSD];
121
122struct buf sdtab[NSD];
123struct buf sdbuf[NSD];
124struct scsi_fmt_cdb sdcmd[NSD];
125struct scsi_fmt_sense sdsense[NSD];
126
127static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
128static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
129
130#define sdunit(x) ((minor(x) >> 3) & 0x7)
131#define sdpart(x) (minor(x) & 0x7)
132#define sdpunit(x) ((x) & 7)
133#define b_cylin b_resid
134#define SDRETRY 2
135
136/*
137 * Table of scsi commands users are allowed to access via "format"
138 * mode. 0 means not legal. 1 means "immediate" (doesn't need dma).
139 * -1 means needs dma and/or wait for intr.
140 */
141static char legal_cmds[256] = {
142/***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */
143/*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144/*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
145/*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
147/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
148/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
149/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
150/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
151/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
152/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
153/*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
154/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
156/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
157/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
158/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
159};
160
161static struct scsi_inquiry inqbuf;
162static struct scsi_fmt_cdb inq = {
163 6,
164 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
165};
166
167static u_char capbuf[8];
168struct scsi_fmt_cdb cap = {
169 10,
170 CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
171};
172
173static int
174sdident(sc, hd)
175 struct sd_softc *sc;
176 struct hp_device *hd;
177{
178 int unit;
179 register int ctlr, slave;
180 register int i;
181 register int tries = 10;
182
183 ctlr = hd->hp_ctlr;
184 slave = hd->hp_slave;
185 unit = sc->sc_punit;
186
187 /*
188 * See if unit exists and is a disk then read block size & nblocks.
189 */
190 while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
191 if (i == -1 || --tries < 0)
192 /* doesn't exist or not a CCS device */
193 return (-1);
194 if (i == STS_CHECKCOND) {
195 u_char sensebuf[128];
196 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
197
198 scsi_request_sense(ctlr, slave, unit, sensebuf,
199 sizeof(sensebuf));
200 if (sp->class == 7 && sp->key == 6)
201 /* drive doing an RTZ -- give it a while */
202 DELAY(1000000);
203 }
204 DELAY(1000);
205 }
206 if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
207 sizeof(inqbuf), B_READ) ||
208 scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
209 sizeof(capbuf), B_READ))
210 /* doesn't exist or not a CCS device */
211 return (-1);
212
213 switch (inqbuf.type) {
214 case 0: /* disk */
215 case 4: /* WORM */
216 case 5: /* CD-ROM */
217 case 7: /* Magneto-optical */
218 break;
219 default: /* not a disk */
220 return (-1);
221 }
222 sc->sc_blks = *(u_int *)&capbuf[0];
223 sc->sc_blksize = *(int *)&capbuf[4];
224
225 if (inqbuf.version != 1)
226 printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit,
227 inqbuf.type, inqbuf.qual, inqbuf.version);
228 else {
229 char idstr[32];
230
231 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
232 for (i = 27; i > 23; --i)
233 if (idstr[i] != ' ')
234 break;
235 idstr[i+1] = 0;
236 for (i = 23; i > 7; --i)
237 if (idstr[i] != ' ')
238 break;
239 idstr[i+1] = 0;
240 for (i = 7; i >= 0; --i)
241 if (idstr[i] != ' ')
242 break;
243 idstr[i+1] = 0;
244 printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
245 &idstr[24]);
246 }
247 printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
248 if (sc->sc_blksize != DEV_BSIZE) {
249 if (sc->sc_blksize < DEV_BSIZE) {
250 printf("sd%d: need %d byte blocks - drive ignored\n",
251 unit, DEV_BSIZE);
252 return (-1);
253 }
254 for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
255 ++sc->sc_bshift;
256 sc->sc_blks <<= sc->sc_bshift;
257 }
258 sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */
259 return(inqbuf.type);
260}
261
262int
263sdinit(hd)
264 register struct hp_device *hd;
265{
266 register struct sd_softc *sc = &sd_softc[hd->hp_unit];
267
268 sc->sc_hd = hd;
269 sc->sc_punit = sdpunit(hd->hp_flags);
270 sc->sc_type = sdident(sc, hd);
271 if (sc->sc_type < 0)
272 return(0);
273 sc->sc_dq.dq_ctlr = hd->hp_ctlr;
274 sc->sc_dq.dq_unit = hd->hp_unit;
275 sc->sc_dq.dq_slave = hd->hp_slave;
276 sc->sc_dq.dq_driver = &sddriver;
277
278 /*
279 * If we don't have a disk label, build a default partition
280 * table with 'standard' size root & swap and everything else
281 * in the G partition.
282 */
283 sc->sc_info = sddefaultpart;
284 /* C gets everything */
285 sc->sc_info.part[2].nblocks = sc->sc_blks;
286 sc->sc_info.part[2].endblk = sc->sc_blks;
287 /* G gets from end of B to end of disk */
288 sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk;
289 sc->sc_info.part[6].endblk = sc->sc_blks;
290 /*
291 * We also define the D, E and F paritions as an alternative to
292 * B and G. D is 48Mb, starts after A and is intended for swapping.
293 * E is 50Mb, starts after D and is intended for /usr. F starts
294 * after E and is what ever is left.
295 */
296 if (sc->sc_blks >= sc->sc_info.part[4].endblk) {
297 sc->sc_info.part[5].nblocks =
298 sc->sc_blks - sc->sc_info.part[4].endblk;
299 sc->sc_info.part[5].endblk = sc->sc_blks;
300 } else {
301 sc->sc_info.part[5].strtblk = 0;
302 sc->sc_info.part[3] = sc->sc_info.part[5];
303 sc->sc_info.part[4] = sc->sc_info.part[5];
304 }
305 /*
306 * H is a single partition alternative to E and F.
307 */
308 if (sc->sc_blks >= sc->sc_info.part[3].endblk) {
309 sc->sc_info.part[7].nblocks =
310 sc->sc_blks - sc->sc_info.part[3].endblk;
311 sc->sc_info.part[7].endblk = sc->sc_blks;
312 } else {
313 sc->sc_info.part[7].strtblk = 0;
314 }
315
316 sc->sc_flags = SDF_ALIVE;
317 return(1);
318}
319
320void
321sdreset(sc, hd)
322 register struct sd_softc *sc;
323 register struct hp_device *hd;
324{
325 sdstats[hd->hp_unit].sdresets++;
326}
327
328int
329sdopen(dev, flags)
330 dev_t dev;
331 int flags;
332{
333 register int unit = sdunit(dev);
334 register struct sd_softc *sc = &sd_softc[unit];
335
336 if (unit >= NSD)
337 return(ENXIO);
338 if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(u.u_cred, &u.u_acflag))
339 return(ENXIO);
340
341 if (sc->sc_hd->hp_dk >= 0)
342 dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
343 return(0);
344}
345
346/*
347 * This routine is called for partial block transfers and non-aligned
348 * transfers (the latter only being possible on devices with a block size
349 * larger than DEV_BSIZE). The operation is performed in three steps
350 * using a locally allocated buffer:
351 * 1. transfer any initial partial block
352 * 2. transfer full blocks
353 * 3. transfer any final partial block
354 */
355static void
356sdlblkstrat(bp, bsize)
357 register struct buf *bp;
358 register int bsize;
359{
360 register struct buf *cbp = (struct buf *)malloc(sizeof(struct buf),
361 M_DEVBUF, M_WAITOK);
362 caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
363 register int bn, resid;
364 register caddr_t addr;
365
366 bzero((caddr_t)cbp, sizeof(*cbp));
367 cbp->b_proc = u.u_procp;
368 cbp->b_dev = bp->b_dev;
369 bn = bp->b_blkno;
370 resid = bp->b_bcount;
371 addr = bp->b_un.b_addr;
372#ifdef DEBUG
373 if (sddebug & SDB_PARTIAL)
374 printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
375 bp, bp->b_flags, bn, resid, addr);
376#endif
377
378 while (resid > 0) {
379 register int boff = dbtob(bn) & (bsize - 1);
380 register int count;
381
382 if (boff || resid < bsize) {
383 sdstats[sdunit(bp->b_dev)].sdpartials++;
384 count = MIN(resid, bsize - boff);
385 cbp->b_flags = B_BUSY | B_PHYS | B_READ;
386 cbp->b_blkno = bn - btodb(boff);
387 cbp->b_un.b_addr = cbuf;
388 cbp->b_bcount = bsize;
389#ifdef DEBUG
390 if (sddebug & SDB_PARTIAL)
391 printf(" readahead: bn %x cnt %x off %x addr %x\n",
392 cbp->b_blkno, count, boff, addr);
393#endif
394 sdstrategy(cbp);
395 biowait(cbp);
396 if (cbp->b_flags & B_ERROR) {
397 bp->b_flags |= B_ERROR;
398 bp->b_error = cbp->b_error;
399 break;
400 }
401 if (bp->b_flags & B_READ) {
402 bcopy(&cbuf[boff], addr, count);
403 goto done;
404 }
405 bcopy(addr, &cbuf[boff], count);
406#ifdef DEBUG
407 if (sddebug & SDB_PARTIAL)
408 printf(" writeback: bn %x cnt %x off %x addr %x\n",
409 cbp->b_blkno, count, boff, addr);
410#endif
411 } else {
412 count = resid & ~(bsize - 1);
413 cbp->b_blkno = bn;
414 cbp->b_un.b_addr = addr;
415 cbp->b_bcount = count;
416#ifdef DEBUG
417 if (sddebug & SDB_PARTIAL)
418 printf(" fulltrans: bn %x cnt %x addr %x\n",
419 cbp->b_blkno, count, addr);
420#endif
421 }
422 cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ);
423 sdstrategy(cbp);
424 biowait(cbp);
425 if (cbp->b_flags & B_ERROR) {
426 bp->b_flags |= B_ERROR;
427 bp->b_error = cbp->b_error;
428 break;
429 }
430done:
431 bn += btodb(count);
432 resid -= count;
433 addr += count;
434#ifdef DEBUG
435 if (sddebug & SDB_PARTIAL)
436 printf(" done: bn %x resid %x addr %x\n",
437 bn, resid, addr);
438#endif
439 }
440 free(cbuf, M_DEVBUF);
441 free(cbp, M_DEVBUF);
442}
443
444void
445sdstrategy(bp)
446 register struct buf *bp;
447{
448 register int part = sdpart(bp->b_dev);
449 register int unit = sdunit(bp->b_dev);
450 register int bn, sz;
451 register struct sd_softc *sc = &sd_softc[unit];
452 register struct buf *dp = &sdtab[unit];
453 register int s;
454
455 if (sc->sc_format_pid) {
456 if (sc->sc_format_pid != u.u_procp->p_pid) {
457 bp->b_error = EPERM;
458 goto bad;
459 }
460 bp->b_cylin = 0;
461 } else {
462 bn = bp->b_blkno;
463 sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT;
464 if (bn < 0 || bn + sz > sc->sc_info.part[part].nblocks) {
465 if (bn == sc->sc_info.part[part].nblocks) {
466 bp->b_resid = bp->b_bcount;
467 goto done;
468 }
469 bp->b_error = EINVAL;
470 goto bad;
471 }
472 /*
473 * Non-aligned or partial-block transfers handled specially.
474 */
475 s = sc->sc_blksize - 1;
476 if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
477 sdlblkstrat(bp, sc->sc_blksize);
478 goto done;
479 }
480 bp->b_cylin = (bn + sc->sc_info.part[part].strtblk) >>
481 sc->sc_bshift;
482 }
483 s = splbio();
484 disksort(dp, bp);
485 if (dp->b_active == 0) {
486 dp->b_active = 1;
487 sdustart(unit);
488 }
489 splx(s);
490 return;
491bad:
492 bp->b_flags |= B_ERROR;
493done:
494 iodone(bp);
495}
496
497void
498sdustart(unit)
499 register int unit;
500{
501 if (scsireq(&sd_softc[unit].sc_dq))
502 sdstart(unit);
503}
504
505static void
506sderror(unit, sc, hp, stat)
507 int unit, stat;
508 register struct sd_softc *sc;
509 register struct hp_device *hp;
510{
511 sdsense[unit].status = stat;
512 if (stat & STS_CHECKCOND) {
513 struct scsi_xsense *sp;
514
515 scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
516 sc->sc_punit, sdsense[unit].sense,
517 sizeof(sdsense[unit].sense));
518 sp = (struct scsi_xsense *)sdsense[unit].sense;
519 printf("sd%d: scsi sense class %d, code %d", unit,
520 sp->class, sp->code);
521 if (sp->class == 7) {
522 printf(", key %d", sp->key);
523 if (sp->valid)
524 printf(", blk %d", *(int *)&sp->info1);
525 }
526 printf("\n");
527 }
528}
529
530static void
531sdfinish(unit, sc, bp)
532 int unit;
533 register struct sd_softc *sc;
534 register struct buf *bp;
535{
536 sdtab[unit].b_errcnt = 0;
537 sdtab[unit].b_actf = bp->b_actf;
538 bp->b_resid = 0;
539 iodone(bp);
540 scsifree(&sc->sc_dq);
541 if (sdtab[unit].b_actf)
542 sdustart(unit);
543 else
544 sdtab[unit].b_active = 0;
545}
546
547void
548sdstart(unit)
549 register int unit;
550{
551 register struct sd_softc *sc = &sd_softc[unit];
552 register struct hp_device *hp = sc->sc_hd;
553
554 /*
555 * we have the SCSI bus -- in format mode, we may or may not need dma
556 * so check now.
557 */
558 if (sc->sc_format_pid && legal_cmds[sdcmd[unit].cdb[0]] > 0) {
559 register struct buf *bp = sdtab[unit].b_actf;
560 register int sts;
561
562 sts = scsi_immed_command(hp->hp_ctlr, hp->hp_slave,
563 sc->sc_punit, &sdcmd[unit],
564 bp->b_un.b_addr, bp->b_bcount,
565 bp->b_flags & B_READ);
566 sdsense[unit].status = sts;
567 if (sts & 0xfe) {
568 sderror(unit, sc, hp, sts);
569 bp->b_flags |= B_ERROR;
570 bp->b_error = EIO;
571 }
572 sdfinish(unit, sc, bp);
573
574 } else if (scsiustart(hp->hp_ctlr))
575 sdgo(unit);
576}
577
578void
579sdgo(unit)
580 register int unit;
581{
582 register struct sd_softc *sc = &sd_softc[unit];
583 register struct hp_device *hp = sc->sc_hd;
584 register struct buf *bp = sdtab[unit].b_actf;
585 register int pad;
586 register struct scsi_fmt_cdb *cmd;
587
588 if (sc->sc_format_pid) {
589 cmd = &sdcmd[unit];
590 pad = 0;
591 } else {
592 cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
593 *(int *)(&cmd->cdb[2]) = bp->b_cylin;
594 pad = howmany(bp->b_bcount, sc->sc_blksize);
595 *(u_short *)(&cmd->cdb[7]) = pad;
596 pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0;
597#ifdef DEBUG
598 if (pad)
599 printf("sd%d: partial block xfer -- %x bytes\n",
600 unit, bp->b_bcount);
601#endif
602 sdstats[unit].sdtransfers++;
603 }
604 if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) {
605 if (hp->hp_dk >= 0) {
606 dk_busy |= 1 << hp->hp_dk;
607 ++dk_seek[hp->hp_dk];
608 ++dk_xfer[hp->hp_dk];
609 dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
610 }
611 return;
612 }
613#ifdef DEBUG
614 if (sddebug & SDB_ERROR)
615 printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n",
616 unit, bp->b_flags & B_READ? "read" : "write",
617 bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
618 sdtab[unit].b_errcnt);
619#endif
620 bp->b_flags |= B_ERROR;
621 bp->b_error = EIO;
622 sdfinish(unit, sc, bp);
623}
624
625void
626sdintr(unit, stat)
627 register int unit;
628 int stat;
629{
630 register struct sd_softc *sc = &sd_softc[unit];
631 register struct buf *bp = sdtab[unit].b_actf;
632 register struct hp_device *hp = sc->sc_hd;
633
634 if (bp == NULL) {
635 printf("sd%d: bp == NULL\n", unit);
636 return;
637 }
638 if (hp->hp_dk >= 0)
639 dk_busy &=~ (1 << hp->hp_dk);
640 if (stat) {
641#ifdef DEBUG
642 if (sddebug & SDB_ERROR)
643 printf("sd%d: sdintr: bad scsi status 0x%x\n",
644 unit, stat);
645#endif
646 sderror(unit, sc, hp, stat);
647 bp->b_flags |= B_ERROR;
648 bp->b_error = EIO;
649 }
650 sdfinish(unit, sc, bp);
651}
652
653int
654sdread(dev, uio)
655 dev_t dev;
656 struct uio *uio;
657{
658 register int unit = sdunit(dev);
659 register int pid;
660
661 if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid)
662 return (EPERM);
663
664 return(physio(sdstrategy, &sdbuf[unit], dev, B_READ, minphys, uio));
665}
666
667int
668sdwrite(dev, uio)
669 dev_t dev;
670 struct uio *uio;
671{
672 register int unit = sdunit(dev);
673 register int pid;
674
675 if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid)
676 return (EPERM);
677
678 return(physio(sdstrategy, &sdbuf[unit], dev, B_WRITE, minphys, uio));
679}
680
681int
682sdioctl(dev, cmd, data, flag)
683 dev_t dev;
684 int cmd;
685 caddr_t data;
686 int flag;
687{
688 register int unit = sdunit(dev);
689 register struct sd_softc *sc = &sd_softc[unit];
690
691 switch (cmd) {
692 default:
693 return (EINVAL);
694
695 case SDIOCSFORMAT:
696 /* take this device into or out of "format" mode */
697 if (suser(u.u_cred, &u.u_acflag))
698 return(EPERM);
699
700 if (*(int *)data) {
701 if (sc->sc_format_pid)
702 return (EPERM);
703 sc->sc_format_pid = u.u_procp->p_pid;
704 } else
705 sc->sc_format_pid = 0;
706 return (0);
707
708 case SDIOCGFORMAT:
709 /* find out who has the device in format mode */
710 *(int *)data = sc->sc_format_pid;
711 return (0);
712
713 case SDIOCSCSICOMMAND:
714 /*
715 * Save what user gave us as SCSI cdb to use with next
716 * read or write to the char device.
717 */
718 if (sc->sc_format_pid != u.u_procp->p_pid)
719 return (EPERM);
720 if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
721 return (EINVAL);
722 bcopy(data, (caddr_t)&sdcmd[unit], sizeof(sdcmd[0]));
723 return (0);
724
725 case SDIOCSENSE:
726 /*
727 * return the SCSI sense data saved after the last
728 * operation that completed with "check condition" status.
729 */
730 bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0]));
731 return (0);
732
733 }
734 /*NOTREACHED*/
735}
736
737int
738sdsize(dev)
739 dev_t dev;
740{
741 register int unit = sdunit(dev);
742 register struct sd_softc *sc = &sd_softc[unit];
743
744 if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
745 return(-1);
746
747 return(sc->sc_info.part[sdpart(dev)].nblocks);
748}
749
750#include "machine/pte.h"
751#include "machine/vmparam.h"
029e208f 752#include "../sys/vmmac.h"
60f56dfc
KM
753
754/*
755 * Non-interrupt driven, non-dma dump routine.
756 */
757int
758sddump(dev)
759 dev_t dev;
760{
761 int part = sdpart(dev);
762 int unit = sdunit(dev);
763 register struct sd_softc *sc = &sd_softc[unit];
764 register struct hp_device *hp = sc->sc_hd;
765 register daddr_t baddr;
766 register int maddr;
767 register int pages, i;
768 int stat;
769 extern int lowram;
770
771 /*
772 * Hmm... all vax drivers dump maxfree pages which is physmem minus
773 * the message buffer. Is there a reason for not dumping the
774 * message buffer? Savecore expects to read 'dumpsize' pages of
775 * dump, where dumpsys() sets dumpsize to physmem!
776 */
777 pages = physmem;
778
779 /* is drive ok? */
780 if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
781 return (ENXIO);
782 /* dump parameters in range? */
783 if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks)
784 return (EINVAL);
785 if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks)
786 pages = dtoc(sc->sc_info.part[part].nblocks - dumplo);
787 maddr = lowram;
788 baddr = dumplo + sc->sc_info.part[part].strtblk;
789 /* scsi bus idle? */
790 if (!scsireq(&sc->sc_dq)) {
791 scsireset(hp->hp_ctlr);
792 sdreset(sc, sc->sc_hd);
793 printf("[ drive %d reset ] ", unit);
794 }
795 for (i = 0; i < pages; i++) {
796#define NPGMB (1024*1024/NBPG)
797 /* print out how many Mbs we have dumped */
798 if (i && (i % NPGMB) == 0)
799 printf("%d ", i / NPGMB);
800#undef NPBMG
801 mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V);
802 stat = scsi_tt_write(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,
803 vmmap, NBPG, baddr, sc->sc_bshift);
804 if (stat) {
805 printf("sddump: scsi write error 0x%x\n", stat);
806 return (EIO);
807 }
808 maddr += NBPG;
809 baddr += ctod(1);
810 }
811 return (0);
812}
813#endif