|
|
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: *
36: * @(#)sd.c 7.8 (Berkeley) 6/9/91
37: */
38:
39: /*
40: * SCSI CCS (Command Command Set) disk driver.
41: */
42: #include "sd.h"
43: #if NSD > 0
44:
45: #ifndef lint
46: static char rcsid[] = "/b/source/CVS/src/sys/arch/amiga/dev/sd.c,v 1.1.1.1 1993/07/05 19:19:47 mw Exp";
47: #endif
48:
49: #include "sys/param.h"
50: #include "sys/systm.h"
51: #include "sys/buf.h"
52: #include "sys/dkstat.h"
53: #include "sys/disklabel.h"
54: #include "sys/malloc.h"
55: #include "sys/proc.h"
56: #include "sys/reboot.h"
57: #include "sys/file.h"
58:
59: #include "device.h"
60: #include "scsireg.h"
61: #include "vm/vm_param.h"
62: #include "vm/lock.h"
63: #include "vm/vm_statistics.h"
64: #include "vm/pmap.h"
65: #include "vm/vm_prot.h"
66:
67: #include "rdb.h"
68:
69: struct sd_softc;
70:
71: extern int sdinit (register struct amiga_device *ad);
72: extern void sdreset (register struct sd_softc *sc, register struct amiga_device *ad);
73: extern int sdopen (dev_t dev, int flags, int mode, struct proc *p);
74: extern void sdstrategy (register struct buf *bp);
75: extern void sdustart (register int unit);
76: extern void sdstart (register int unit);
77: extern void sdgo (register int unit);
78: extern void sdintr (register int unit, int stat);
79: extern int sdioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
80: extern int sdsize (dev_t dev);
81: extern int sddump (dev_t dev);
82: static int sdident (struct sd_softc *sc, struct amiga_device *ad);
83: static void sdlblkstrat (register struct buf *bp, register int bsize);
84: static int sderror (int unit, register struct sd_softc *sc, register struct amiga_device *am, int stat);
85: static void sdfinish (int unit, register struct sd_softc *sc, register struct buf *bp);
86:
87: extern void disksort();
88: extern int physio();
89: extern void TBIS();
90:
91: int sdinit();
92: void sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
93:
94: struct driver sddriver = {
95: sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr, 0,
96: };
97:
98: #if 0
99: struct size {
100: u_long strtblk;
101: u_long endblk;
102: int nblocks;
103: };
104:
105: struct sdinfo {
106: u_int cylinders; /* number of driver cylinders RDB value */
107: u_int sectors; /* sectors per track RDB value */
108: u_int heads; /* number of drive heads RDB value */
109: u_int cylblocks; /* available number of blocks per cyl RDB value */
110: struct size part[8];
111: };
112:
113: /*
114: * since the SCSI standard tends to hide the disk structure, we define
115: * partitions in terms of DEV_BSIZE blocks. The default partition table
116: * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg
117: * root and 32 meg of swap. The rest of the space on the drive goes in
118: * the G partition. As usual, the C partition covers the entire disk
119: * (including the boot area).
120: */
121: struct sdinfo sddefaultpart = {
122: 1024, 17408, 16384 , /* A */
123: 17408, 82944, 65536 , /* B */
124: 0, 0, 0 , /* C */
125: 17408, 115712, 98304 , /* D */
126: 115712, 218112, 102400 , /* E */
127: 218112, 0, 0 , /* F */
128: 82944, 0, 0 , /* G */
129: 115712, 0, 0 , /* H */
130: };
131: #endif
132:
133: struct sd_softc {
134: struct amiga_device *sc_ad;
135: struct devqueue sc_dq;
136: int sc_format_pid; /* process using "format" mode */
137: short sc_flags;
138: short sc_type; /* drive type */
139: short sc_punit; /* physical unit (scsi lun) */
140: u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */
141: u_int sc_blks; /* number of blocks on device */
142: int sc_blksize; /* device block size in bytes */
143: u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */
144: char sc_idstr[32]; /* XXX */
145: struct disklabel sc_label; /* drive partition table & label info */
146: int sc_have_label;
147: int sc_write_label;
148: } sd_softc[NSD];
149:
150: /* sc_flags values */
151: #define SDF_ALIVE 0x1
152:
153: #ifdef DEBUG
154: int sddebug = 0;
155: #define SDB_ERROR 0x01
156: #define SDB_PARTIAL 0x02
157: /*#define QUASEL*/
158: #endif
159:
160: #ifdef QUASEL
161: #define QPRINTF(a) printf a
162: #else
163: #define QPRINTF(a)
164: #endif
165:
166: struct sdstats {
167: long sdresets;
168: long sdtransfers;
169: long sdpartials;
170: } sdstats[NSD];
171:
172: struct buf sdtab[NSD];
173: struct scsi_fmt_cdb sdcmd[NSD];
174: struct scsi_fmt_sense sdsense[NSD];
175:
176: static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
177: static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
178:
179: #define sdunit(x) (minor(x) >> 3)
180: #define sdpart(x) (minor(x) & 0x7)
181: #define sdpunit(x) ((x) & 7)
182: #define b_cylin b_resid
183:
184: #define SDRETRY 2
185:
186: /*
187: * Table of scsi commands users are allowed to access via "format"
188: * mode. 0 means not legal. 1 means "immediate" (doesn't need dma).
189: * -1 means needs dma and/or wait for intr.
190: */
191: static char legal_cmds[256] = {
192: /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */
193: /*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
194: /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
195: /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
196: /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
197: /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
198: /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199: /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200: /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201: /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202: /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203: /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204: /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205: /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
206: /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207: /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208: /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
209: };
210:
211: static struct scsi_inquiry inqbuf;
212: static struct scsi_fmt_cdb inq = {
213: 6,
214: CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
215: };
216:
217: static u_char capbuf[8];
218: struct scsi_fmt_cdb cap = {
219: 10,
220: CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
221: };
222:
223: static int
224: sdident(sc, ad)
225: struct sd_softc *sc;
226: struct amiga_device *ad;
227: {
228: int unit;
229: register int ctlr, slave;
230: register int i;
231: register int tries = 10;
232: int ismo = 0;
233:
234: ctlr = ad->amiga_ctlr;
235: slave = ad->amiga_slave;
236: unit = sc->sc_punit;
237: scsi_delay(-1);
238:
239: /*
240: * See if unit exists and is a disk then read block size & nblocks.
241: */
242: while ((i = scsi_test_unit_rdy(slave)) != 0) {
243: retry_TUR:
244: if (i == -1 || --tries < 0) {
245: if (ismo)
246: break;
247: /* doesn't exist or not a CCS device */
248: goto failed;
249: }
250: if (i == STS_CHECKCOND) {
251: u_char sensebuf[128];
252: struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
253:
254: i = scsi_request_sense(slave, sensebuf, sizeof(sensebuf));
255: if (sp->class == 7)
256: switch (sp->key) {
257: /* not ready -- might be MO with no media */
258: case 2:
259: if (sp->len == 12 &&
260: sensebuf[12] == 10) /* XXX */
261: ismo = 1;
262: break;
263: /* drive doing an RTZ -- give it a while */
264: case 6:
265: DELAY(1000000);
266: break;
267: default:
268: break;
269: }
270: }
271: DELAY(1000);
272: }
273: /*
274: * Find out about device
275: */
276: if (i = scsi_immed_command(slave, &inq, (u_char *)&inqbuf, sizeof(inqbuf), B_READ))
277: {
278: if (i == STS_CHECKCOND)
279: goto retry_TUR;
280: goto failed;
281: }
282: switch (inqbuf.type) {
283: case 0: /* disk */
284: case 4: /* WORM */
285: case 5: /* CD-ROM */
286: case 7: /* Magneto-optical */
287: break;
288: default: /* not a disk */
289: if (sddebug)
290: printf ("Unit %d unknown scsi-type: %d\n", slave, inqbuf.type);
291: goto failed;
292: }
293: /*
294: * Get a usable id string
295: */
296: if (inqbuf.version < 1) {
297: bcopy("UNKNOWN", &sc->sc_idstr[0], 8);
298: bcopy("DRIVE TYPE", &sc->sc_idstr[8], 11);
299: } else {
300: bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)sc->sc_idstr, 28);
301: for (i = 27; i > 23; --i)
302: if (sc->sc_idstr[i] != ' ')
303: break;
304: sc->sc_idstr[i+1] = 0;
305: for (i = 23; i > 7; --i)
306: if (sc->sc_idstr[i] != ' ')
307: break;
308: sc->sc_idstr[i+1] = 0;
309: for (i = 7; i >= 0; --i)
310: if (sc->sc_idstr[i] != ' ')
311: break;
312: sc->sc_idstr[i+1] = 0;
313: }
314: i = scsi_immed_command(slave, &cap, (u_char *)&capbuf, sizeof(capbuf), B_READ);
315: if (i) {
316: if (i != STS_CHECKCOND ||
317: bcmp(&sc->sc_idstr[0], "HP", 3) ||
318: bcmp(&sc->sc_idstr[8], "S6300.650A", 11))
319: goto failed;
320: /* XXX unformatted or non-existant MO media; fake it */
321: sc->sc_blks = 318664;
322: sc->sc_blksize = 1024;
323: } else {
324: sc->sc_blks = *(u_int *)&capbuf[0];
325: sc->sc_blksize = *(int *)&capbuf[4];
326: }
327: /* return value of read capacity is last valid block number */
328: sc->sc_blks++;
329:
330: if (inqbuf.version < 1)
331: printf("sd%d: type 0x%x, qual 0x%x, ver %d", ad->amiga_unit,
332: inqbuf.type, inqbuf.qual, inqbuf.version);
333: else
334: printf("sd%d: %s %s rev %s", ad->amiga_unit, sc->sc_idstr, &sc->sc_idstr[8],
335: &sc->sc_idstr[24]);
336: printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
337: if (sc->sc_blksize != DEV_BSIZE) {
338: if (sc->sc_blksize < DEV_BSIZE) {
339: printf("sd%d: need %d byte blocks - drive ignored\n",
340: unit, DEV_BSIZE);
341: goto failed;
342: }
343: for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
344: ++sc->sc_bshift;
345: sc->sc_blks <<= sc->sc_bshift;
346: }
347: sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */
348: scsi_delay(0);
349: return(inqbuf.type);
350: failed:
351: scsi_delay(0);
352: return(-1);
353: }
354:
355: int
356: sdinit(ad)
357: register struct amiga_device *ad;
358: {
359: register struct sd_softc *sc = &sd_softc[ad->amiga_unit];
360: static u_int block [DEV_BSIZE / 4];
361: struct RigidDiskBlock *rdb = (struct RigidDiskBlock *) block;
362: struct PartitionBlock *pb = (struct PartitionBlock *) block;
363: int bnum, npbnum, num_bsd_part = 0;
364: struct disklabel *dl;
365:
366: sc->sc_ad = ad;
367: sc->sc_punit = sdpunit(ad->amiga_flags);
368: sc->sc_type = sdident(sc, ad);
369: if (sc->sc_type < 0)
370: return(0);
371: sc->sc_dq.dq_ctlr = ad->amiga_ctlr;
372: sc->sc_dq.dq_unit = ad->amiga_unit;
373: sc->sc_dq.dq_slave = ad->amiga_slave;
374: sc->sc_dq.dq_driver = &sddriver;
375:
376: /* read RDB and partition blocks to find out about which partitions
377: are ok to be scribbled upon by BSD. This is quite Amiga specific. */
378:
379: for (bnum = 0; bnum < RDB_LOCATION_LIMIT; bnum++)
380: {
381: if (scsi_tt_read (ad->amiga_slave, block, DEV_BSIZE, bnum, sc->sc_bshift))
382: /* read error on block */
383: return 0;
384:
385: if (rdb->rdb_ID == IDNAME_RIGIDDISK)
386: break;
387: }
388: if (bnum == RDB_LOCATION_LIMIT)
389: /* no RDB on this disk */
390: return 0;
391:
392: /* fill in as much as we can of the disklabel */
393: dl = &sc->sc_label;
394: bzero (dl, sizeof (*dl));
395: dl->d_magic = DISKMAGIC;
396: dl->d_type = DTYPE_SCSI;
397:
398: strncpy (dl->d_typename, sc->sc_idstr, sizeof (dl->d_typename) - 1);
399: strcpy (dl->d_packname, "some pack");
400:
401: /* now for more serious information.. */
402: dl->d_secsize = rdb->rdb_BlockBytes;
403: dl->d_nsectors = rdb->rdb_Sectors;
404: dl->d_ntracks = rdb->rdb_Heads;
405: dl->d_ncylinders = rdb->rdb_Cylinders;
406: dl->d_secpercyl = rdb->rdb_CylBlocks;
407: dl->d_secperunit = (rdb->rdb_CylBlocks
408: * (rdb->rdb_HiCylinder - rdb->rdb_LoCylinder));
409:
410: /* makes sense? */
411: dl->d_acylinders = rdb->rdb_Cylinders - (rdb->rdb_HiCylinder - rdb->rdb_LoCylinder);
412:
413: dl->d_magic2 = DISKMAGIC;
414:
415: /* ok, go thru the partition blocks, and check for BSD ID's */
416:
417: for (npbnum = rdb->rdb_PartitionList; npbnum; )
418: {
419: u_int start_block, end_block, nblocks;
420: u_int reserved;
421: int part;
422:
423: if (scsi_tt_read (ad->amiga_slave, block, DEV_BSIZE, npbnum, sc->sc_bshift))
424: break;
425:
426: if (pb->pb_ID != IDNAME_PARTITION)
427: break;
428:
429: /* remember those values, they're destroyed when reading the first
430: partition block */
431: npbnum = pb->pb_Next;
432: start_block = pb->pb_Environment[DE_LOWCYL] * dl->d_secpercyl;
433: reserved = pb->pb_Environment[DE_RESERVEDBLKS];
434: end_block = pb->pb_Environment[DE_UPPERCYL] * dl->d_secpercyl;
435:
436: part = -1;
437: switch (pb->pb_Environment[DE_DOSTYPE])
438: {
439: case DOSTYPE_BSD_ROOT:
440: if (! dl->d_partitions[0].p_size)
441: {
442: extern u_long bootdev;
443:
444: part = 0;
445:
446: /* Since we don't boot BSD with a standalone-kernel, but
447: with a simple boot-loader from AmigaDOS, we fake a
448: bootdev by assigning the just computed values of the
449: root partition. */
450:
451: /* 4: sd major
452: 0: adaptor number
453: 0: controller number
454: ad->amiga_unit: scsi-unit
455: part: partition (A) */
456:
457: bootdev = MAKEBOOTDEV (4, 0, 0, ad->amiga_unit, part);
458: }
459: break;
460:
461: case DOSTYPE_BSD_SWAP:
462: if (! dl->d_partitions[1].p_size)
463: part = 1;
464: break;
465:
466: case DOSTYPE_BSD_D:
467: if (! dl->d_partitions[3].p_size)
468: part = 3;
469: break;
470:
471: case DOSTYPE_BSD_E:
472: if (! dl->d_partitions[4].p_size)
473: part = 4;
474: break;
475:
476: case DOSTYPE_BSD_F:
477: if (! dl->d_partitions[5].p_size)
478: part = 5;
479: break;
480:
481: case DOSTYPE_BSD_G:
482: if (! dl->d_partitions[6].p_size)
483: part = 6;
484: break;
485:
486: case DOSTYPE_BSD_H:
487: if (! dl->d_partitions[7].p_size)
488: part = 7;
489: break;
490: }
491:
492: if (part >= 0)
493: {
494: num_bsd_part++;
495:
496: dl->d_partitions[part].p_offset = start_block + reserved;
497: dl->d_partitions[part].p_size = end_block - start_block - reserved;
498:
499: /* for now, have this static.. XXX */
500: dl->d_partitions[part].p_fsize = 1024;
501: dl->d_partitions[part].p_fstype = part == 1 ? FS_SWAP : FS_BSDFFS;
502: dl->d_partitions[part].p_frag = 8;
503: dl->d_partitions[part].p_cpg = 0; /* XXX */
504:
505: if (sddebug)
506: printf ("%c @%d - %d = %d\n", part + 'A',
507: start_block, end_block, end_block - start_block - reserved);
508: }
509: }
510:
511: dl->d_npartitions = num_bsd_part;
512: if (sddebug)
513: printf ("total %d BSD-partitions.\n", num_bsd_part);
514:
515: /* C gets everything */
516: dl->d_partitions[2].p_size = sc->sc_blks;
517:
518: dl->d_checksum = 0;
519: dl->d_checksum = dkcksum (dl);
520:
521: sc->sc_have_label = 1;
522: sc->sc_write_label = 0;
523:
524: sc->sc_flags = SDF_ALIVE;
525: return(1);
526: }
527:
528: void
529: sdreset(sc, ad)
530: register struct sd_softc *sc;
531: register struct amiga_device *ad;
532: {
533: sdstats[ad->amiga_unit].sdresets++;
534: }
535:
536: int
537: sdopen(dev, flags, mode, p)
538: dev_t dev;
539: int flags, mode;
540: struct proc *p;
541: {
542: register int unit = sdunit(dev);
543: register struct sd_softc *sc = &sd_softc[unit];
544:
545: if (unit >= NSD)
546: return(ENXIO);
547: if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
548: return(ENXIO);
549:
550: if (sc->sc_ad->amiga_dk >= 0)
551: dk_wpms[sc->sc_ad->amiga_dk] = sc->sc_wpms;
552: return(0);
553: }
554:
555: /*
556: * This routine is called for partial block transfers and non-aligned
557: * transfers (the latter only being possible on devices with a block size
558: * larger than DEV_BSIZE). The operation is performed in three steps
559: * using a locally allocated buffer:
560: * 1. transfer any initial partial block
561: * 2. transfer full blocks
562: * 3. transfer any final partial block
563: */
564: static void
565: sdlblkstrat(bp, bsize)
566: register struct buf *bp;
567: register int bsize;
568: {
569: register struct buf *cbp = (struct buf *)malloc(sizeof(struct buf),
570: M_DEVBUF, M_WAITOK);
571: caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
572: register int bn, resid;
573: register caddr_t addr;
574:
575: bzero((caddr_t)cbp, sizeof(*cbp));
576: cbp->b_proc = curproc; /* XXX */
577: cbp->b_dev = bp->b_dev;
578: bn = bp->b_blkno;
579: resid = bp->b_bcount;
580: addr = bp->b_un.b_addr;
581: #ifdef DEBUG
582: if (sddebug & SDB_PARTIAL)
583: printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
584: bp, bp->b_flags, bn, resid, addr);
585: #endif
586:
587: while (resid > 0) {
588: register int boff = dbtob(bn) & (bsize - 1);
589: register int count;
590:
591: if (boff || resid < bsize) {
592: sdstats[sdunit(bp->b_dev)].sdpartials++;
593: count = MIN(resid, bsize - boff);
594: cbp->b_flags = B_BUSY | B_PHYS | B_READ;
595: cbp->b_blkno = bn - btodb(boff);
596: cbp->b_un.b_addr = cbuf;
597: cbp->b_bcount = bsize;
598: #ifdef DEBUG
599: if (sddebug & SDB_PARTIAL)
600: printf(" readahead: bn %x cnt %x off %x addr %x\n",
601: cbp->b_blkno, count, boff, addr);
602: #endif
603: sdstrategy(cbp);
604: biowait(cbp);
605: if (cbp->b_flags & B_ERROR) {
606: bp->b_flags |= B_ERROR;
607: bp->b_error = cbp->b_error;
608: break;
609: }
610: if (bp->b_flags & B_READ) {
611: bcopy(&cbuf[boff], addr, count);
612: goto done;
613: }
614: bcopy(addr, &cbuf[boff], count);
615: #ifdef DEBUG
616: if (sddebug & SDB_PARTIAL)
617: printf(" writeback: bn %x cnt %x off %x addr %x\n",
618: cbp->b_blkno, count, boff, addr);
619: #endif
620: } else {
621: count = resid & ~(bsize - 1);
622: cbp->b_blkno = bn;
623: cbp->b_un.b_addr = addr;
624: cbp->b_bcount = count;
625: #ifdef DEBUG
626: if (sddebug & SDB_PARTIAL)
627: printf(" fulltrans: bn %x cnt %x addr %x\n",
628: cbp->b_blkno, count, addr);
629: #endif
630: }
631: cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ);
632: sdstrategy(cbp);
633: biowait(cbp);
634: if (cbp->b_flags & B_ERROR) {
635: bp->b_flags |= B_ERROR;
636: bp->b_error = cbp->b_error;
637: break;
638: }
639: done:
640: bn += btodb(count);
641: resid -= count;
642: addr += count;
643: #ifdef DEBUG
644: if (sddebug & SDB_PARTIAL)
645: printf(" done: bn %x resid %x addr %x\n",
646: bn, resid, addr);
647: #endif
648: }
649: free(cbuf, M_DEVBUF);
650: free(cbp, M_DEVBUF);
651: }
652:
653: void
654: sdstrategy(bp)
655: register struct buf *bp;
656: {
657: register int unit = sdunit(bp->b_dev);
658: register struct sd_softc *sc = &sd_softc[unit];
659: register struct partition *pinfo = &sc->sc_label.d_partitions[sdpart(bp->b_dev)];
660: register struct buf *dp = &sdtab[unit];
661: register daddr_t bn;
662: register int sz, s;
663:
664: QPRINTF (("sdstrat: unit=%d [s=%d,l=%d], [b=%d,l=%d]\n", unit,
665: pinfo->p_offset, pinfo->p_size, bp->b_blkno, bp->b_bcount));
666:
667: if (sc->sc_format_pid) {
668: if (sc->sc_format_pid != curproc->p_pid) { /* XXX */
669: bp->b_error = EPERM;
670: bp->b_flags |= B_ERROR;
671: goto done;
672: }
673: bp->b_cylin = 0;
674: } else {
675: bn = bp->b_blkno;
676: sz = howmany(bp->b_bcount, DEV_BSIZE);
677: if (bn < 0 || bn + sz > pinfo->p_size) {
678: sz = pinfo->p_size - bn;
679: if (sz == 0) {
680: bp->b_resid = bp->b_bcount;
681: goto done;
682: }
683: if (sz < 0) {
684: bp->b_error = EINVAL;
685: bp->b_flags |= B_ERROR;
686: goto done;
687: }
688: bp->b_bcount = dbtob(sz);
689: }
690: /*
691: * Non-aligned or partial-block transfers handled specially.
692: */
693: s = sc->sc_blksize - 1;
694: if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
695: sdlblkstrat(bp, sc->sc_blksize);
696: goto done;
697: }
698: bp->b_cylin = (bn + pinfo->p_offset) >> sc->sc_bshift;
699: }
700: s = splbio();
701: disksort(dp, bp);
702: if (dp->b_active == 0) {
703: dp->b_active = 1;
704: sdustart(unit);
705: }
706: splx(s);
707: return;
708: done:
709: biodone(bp);
710: }
711:
712: void
713: sdustart(unit)
714: register int unit;
715: {
716: if (scsireq(&sd_softc[unit].sc_dq))
717: sdstart(unit);
718: }
719:
720: /*
721: * Return:
722: * 0 if not really an error
723: * <0 if we should do a retry
724: * >0 if a fatal error
725: */
726: static int
727: sderror(unit, sc, am, stat)
728: int unit, stat;
729: register struct sd_softc *sc;
730: register struct amiga_device *am;
731: {
732: int cond = 1;
733:
734: sdsense[unit].status = stat;
735: if (stat & STS_CHECKCOND) {
736: struct scsi_xsense *sp;
737:
738: scsi_request_sense(am->amiga_slave,
739: sdsense[unit].sense,
740: sizeof(sdsense[unit].sense));
741: sp = (struct scsi_xsense *)sdsense[unit].sense;
742: printf("sd%d: scsi sense class %d, code %d", unit,
743: sp->class, sp->code);
744: if (sp->class == 7) {
745: printf(", key %d", sp->key);
746: if (sp->valid)
747: printf(", blk %d", *(int *)&sp->info1);
748: switch (sp->key) {
749: /* no sense, try again */
750: case 0:
751: cond = -1;
752: break;
753: /* recovered error, not a problem */
754: case 1:
755: cond = 0;
756: break;
757: }
758: }
759: printf("\n");
760: }
761: return(cond);
762: }
763:
764: static void
765: sdfinish(unit, sc, bp)
766: int unit;
767: register struct sd_softc *sc;
768: register struct buf *bp;
769: {
770: sdtab[unit].b_errcnt = 0;
771: sdtab[unit].b_actf = bp->b_actf;
772: bp->b_resid = 0;
773: biodone(bp);
774: scsifree(&sc->sc_dq);
775: if (sdtab[unit].b_actf)
776: sdustart(unit);
777: else
778: sdtab[unit].b_active = 0;
779: }
780:
781: void
782: sdstart(unit)
783: register int unit;
784: {
785: register struct sd_softc *sc = &sd_softc[unit];
786: register struct amiga_device *am = sc->sc_ad;
787:
788: /*
789: * we have the SCSI bus -- in format mode, we may or may not need dma
790: * so check now.
791: */
792: if (sc->sc_format_pid && legal_cmds[sdcmd[unit].cdb[0]] > 0) {
793: register struct buf *bp = sdtab[unit].b_actf;
794: register int sts;
795:
796: sts = scsi_immed_command(am->amiga_slave,
797: &sdcmd[unit],
798: bp->b_un.b_addr, bp->b_bcount,
799: bp->b_flags & B_READ);
800: sdsense[unit].status = sts;
801: if (sts & 0xfe) {
802: (void) sderror(unit, sc, am, sts);
803: bp->b_flags |= B_ERROR;
804: bp->b_error = EIO;
805: }
806: sdfinish(unit, sc, bp);
807:
808: } else if (scsiustart(am->amiga_ctlr))
809: sdgo(unit);
810: }
811:
812: void
813: sdgo(unit)
814: register int unit;
815: {
816: register struct sd_softc *sc = &sd_softc[unit];
817: register struct amiga_device *am = sc->sc_ad;
818: register struct buf *bp = sdtab[unit].b_actf;
819: register int pad;
820: register struct scsi_fmt_cdb *cmd;
821:
822: /* XXX ? */
823: if (! bp)
824: return;
825:
826: if (sc->sc_format_pid) {
827: cmd = &sdcmd[unit];
828: pad = 0;
829: } else {
830: cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
831: *(int *)(&cmd->cdb[2]) = bp->b_cylin;
832: pad = howmany(bp->b_bcount, sc->sc_blksize);
833: *(u_short *)(&cmd->cdb[7]) = pad;
834: QPRINTF(("sdgo[%d, %d]: %s @%d >%d\n",
835: am->amiga_ctlr, am->amiga_slave,
836: bp->b_flags & B_READ ? "R" : "W",
837: bp->b_cylin, pad));
838: pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0;
839: #ifdef DEBUG
840: if (pad)
841: printf("sd%d: partial block xfer -- %x bytes\n",
842: unit, bp->b_bcount);
843: #endif
844: sdstats[unit].sdtransfers++;
845: }
846: if (scsigo(am->amiga_ctlr, am->amiga_slave, bp, cmd, pad) == 0) {
847: if (am->amiga_dk >= 0) {
848: dk_busy |= 1 << am->amiga_dk;
849: ++dk_seek[am->amiga_dk];
850: ++dk_xfer[am->amiga_dk];
851: dk_wds[am->amiga_dk] += bp->b_bcount >> 6;
852: }
853: return;
854: }
855: #ifdef DEBUG
856: if (sddebug & SDB_ERROR)
857: printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n",
858: unit, bp->b_flags & B_READ? "read" : "write",
859: bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
860: sdtab[unit].b_errcnt);
861: #endif
862: bp->b_flags |= B_ERROR;
863: bp->b_error = EIO;
864: sdfinish(unit, sc, bp);
865: }
866:
867: void
868: sdintr(unit, stat)
869: register int unit;
870: int stat;
871: {
872: register struct sd_softc *sc = &sd_softc[unit];
873: register struct buf *bp = sdtab[unit].b_actf;
874: register struct amiga_device *am = sc->sc_ad;
875: int cond;
876:
877: if (bp == NULL) {
878: printf("sd%d: bp == NULL\n", unit);
879: return;
880: }
881: if (am->amiga_dk >= 0)
882: dk_busy &=~ (1 << am->amiga_dk);
883: if (stat) {
884: #ifdef DEBUG
885: if (sddebug & SDB_ERROR)
886: printf("sd%d: sdintr: bad scsi status 0x%x\n",
887: unit, stat);
888: #endif
889: cond = sderror(unit, sc, am, stat);
890: if (cond) {
891: if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
892: #ifdef DEBUG
893: if (sddebug & SDB_ERROR)
894: printf("sd%d: retry #%d\n",
895: unit, sdtab[unit].b_errcnt);
896: #endif
897: sdstart(unit);
898: return;
899: }
900: bp->b_flags |= B_ERROR;
901: bp->b_error = EIO;
902: }
903: }
904: sdfinish(unit, sc, bp);
905: }
906:
907: #if 1
908: u_int
909: sdminphys (bp)
910: struct buf *bp;
911: {
912: register int unit = sdunit(bp->b_dev);
913: register struct sd_softc *sc = &sd_softc[unit];
914: register struct partition *pinfo = &sc->sc_label.d_partitions[sdpart(bp->b_dev)];
915: register daddr_t bn;
916: register int sz, s;
917:
918: /* first restrict by max amount of physio possible */
919: bp->b_bcount = min(MAXPHYS, bp->b_bcount);
920:
921: /* then restrict by partition size (code replicated from sdstrategy).
922: Should minphys() really fiddle around with b_resid and b_flags ??? XXXX */
923:
924: bn = bp->b_blkno;
925: sz = howmany(bp->b_bcount, DEV_BSIZE);
926: if (bn < 0 || bn + sz > pinfo->p_size)
927: {
928: sz = pinfo->p_size - bn;
929: if (sz == 0)
930: {
931: bp->b_resid = bp->b_bcount;
932: goto done;
933: }
934: if (sz < 0)
935: {
936: bp->b_error = EINVAL;
937: bp->b_flags |= B_ERROR;
938: goto done;
939: }
940: bp->b_bcount = dbtob(sz);
941: }
942:
943: return bp->b_bcount;
944: done:
945: return 0;
946: }
947:
948:
949: int
950: sdread(dev, uio, flags)
951: dev_t dev;
952: struct uio *uio;
953: int flags;
954: {
955: register int unit = sdunit(dev);
956: register int pid;
957:
958: if ((pid = sd_softc[unit].sc_format_pid) &&
959: pid != uio->uio_procp->p_pid)
960: return (EPERM);
961:
962: return (physio(sdstrategy, NULL, dev, B_READ, sdminphys, uio));
963: }
964:
965: int
966: sdwrite(dev, uio, flags)
967: dev_t dev;
968: struct uio *uio;
969: int flags;
970: {
971: register int unit = sdunit(dev);
972: register int pid;
973:
974: if ((pid = sd_softc[unit].sc_format_pid) &&
975: pid != uio->uio_procp->p_pid)
976: return (EPERM);
977:
978: return (physio(sdstrategy, NULL, dev, B_WRITE, sdminphys, uio));
979: }
980: #endif
981:
982: int
983: sdioctl(dev, cmd, data, flag, p)
984: dev_t dev;
985: int cmd;
986: caddr_t data;
987: int flag;
988: struct proc *p;
989: {
990: register int unit = sdunit(dev);
991: register struct sd_softc *sc = &sd_softc[unit];
992: struct disklabel *dl;
993: int error;
994:
995: switch (cmd) {
996: default:
997: return (EINVAL);
998:
999: case DIOCGDINFO:
1000: *(struct disklabel *)data = sc->sc_label;
1001: return 0;
1002:
1003: case DIOCSDINFO:
1004: if ((flag & FWRITE) == 0)
1005: return EBADF;
1006:
1007: dl = (struct disklabel *)data;
1008: if (error = setdisklabel(&sc->sc_label, dl, 0, 0));
1009: return error;
1010: sc->sc_have_label = 1;
1011: return 0;
1012:
1013: case DIOCWLABEL:
1014: if ((flag & FWRITE) == 0)
1015: return EBADF;
1016:
1017: sc->sc_write_label = *(int *)data;
1018: return 0;
1019:
1020: case DIOCWDINFO:
1021: if ((flag & FWRITE) == 0)
1022: return EBADF;
1023:
1024: dl = (struct disklabel *)data;
1025:
1026: if (error = setdisklabel (&sc->sc_label, dl, 0, 0))
1027: return error;
1028:
1029: sc->sc_have_label = 1;
1030:
1031: #if 0
1032: old_wlabel = as->wlabel;
1033: as->wlabel = 1;
1034: error = writedisklabel(dev, asstrategy, &as->label,
1035: as->dospart);
1036: as->wlabel = old_wlabel;
1037: #endif
1038: return EINVAL;
1039:
1040: case SDIOCSFORMAT:
1041: /* take this device into or out of "format" mode */
1042: if (suser(p->p_ucred, &p->p_acflag))
1043: return(EPERM);
1044:
1045: if (*(int *)data) {
1046: if (sc->sc_format_pid)
1047: return (EPERM);
1048: sc->sc_format_pid = p->p_pid;
1049: } else
1050: sc->sc_format_pid = 0;
1051: return (0);
1052:
1053: case SDIOCGFORMAT:
1054: /* find out who has the device in format mode */
1055: *(int *)data = sc->sc_format_pid;
1056: return (0);
1057:
1058: case SDIOCSCSICOMMAND:
1059: /*
1060: * Save what user gave us as SCSI cdb to use with next
1061: * read or write to the char device.
1062: */
1063: if (sc->sc_format_pid != p->p_pid)
1064: return (EPERM);
1065: if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
1066: return (EINVAL);
1067: bcopy(data, (caddr_t)&sdcmd[unit], sizeof(sdcmd[0]));
1068: return (0);
1069:
1070: case SDIOCSENSE:
1071: /*
1072: * return the SCSI sense data saved after the last
1073: * operation that completed with "check condition" status.
1074: */
1075: bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0]));
1076: return (0);
1077:
1078: }
1079: /*NOTREACHED*/
1080: }
1081:
1082: int
1083: sdsize(dev)
1084: dev_t dev;
1085: {
1086: register int unit = sdunit(dev);
1087: register struct sd_softc *sc = &sd_softc[unit];
1088:
1089: if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
1090: return(-1);
1091: return(sc->sc_label.d_partitions[sdpart(dev)].p_size);
1092: }
1093:
1094: /*
1095: * Non-interrupt driven, non-dma dump routine.
1096: */
1097: int
1098: sddump(dev)
1099: dev_t dev;
1100: {
1101: int part = sdpart(dev);
1102: int unit = sdunit(dev);
1103: register struct sd_softc *sc = &sd_softc[unit];
1104: register struct amiga_device *am = sc->sc_ad;
1105: register daddr_t baddr;
1106: register int maddr;
1107: register int pages, i;
1108: int stat;
1109: extern int lowram;
1110:
1111: /*
1112: * Hmm... all vax drivers dump maxfree pages which is physmem minus
1113: * the message buffer. Is there a reason for not dumping the
1114: * message buffer? Savecore expects to read 'dumpsize' pages of
1115: * dump, where dumpsys() sets dumpsize to physmem!
1116: */
1117: pages = physmem;
1118:
1119: /* is drive ok? */
1120: if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
1121: return (ENXIO);
1122: /* dump parameters in range? */
1123: if (dumplo < 0 || dumplo >= sc->sc_label.d_partitions[part].p_size)
1124: return (EINVAL);
1125: if (dumplo + ctod(pages) > sc->sc_label.d_partitions[part].p_size)
1126: pages = dtoc(sc->sc_label.d_partitions[part].p_size - dumplo);
1127: maddr = lowram;
1128: baddr = dumplo + sc->sc_label.d_partitions[part].p_offset;
1129: /* scsi bus idle? */
1130: if (!scsireq(&sc->sc_dq)) {
1131: scsireset(/*am->amiga_ctlr*/);
1132: sdreset(sc, sc->sc_ad);
1133: printf("[ drive %d reset ] ", unit);
1134: }
1135: for (i = 0; i < pages; i++) {
1136: #define NPGMB (1024*1024/NBPG)
1137: /* print out how many Mbs we have dumped */
1138: if (i && (i % NPGMB) == 0)
1139: printf("%d ", i / NPGMB);
1140: #undef NPBMG
1141: pmap_enter(pmap_kernel(), vmmap, maddr, VM_PROT_READ, TRUE);
1142: stat = scsi_tt_write(am->amiga_slave,
1143: vmmap, NBPG, baddr, sc->sc_bshift);
1144: if (stat) {
1145: printf("sddump: scsi write error 0x%x\n", stat);
1146: return (EIO);
1147: }
1148: maddr += NBPG;
1149: baddr += ctod(1);
1150: }
1151: return (0);
1152: }
1153: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.