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