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