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