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