1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Van Jacobson of Lawrence Berkeley Laboratory and the Systems 8 * Programming Group of the University of Utah Computer Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: sd.c 1.9 92/12/21$ 13 * 14 * @(#)sd.c 7.9 (Berkeley) 05/24/93 15 */ 16 17 /* 18 * SCSI CCS disk driver 19 */ 20 21 #include <sys/param.h> 22 #include <sys/disklabel.h> 23 #include <stand.att/saio.h> 24 #include <hp300/stand/samachdep.h> 25 26 #include <hp300/dev/scsireg.h> 27 28 struct disklabel sdlabel; 29 30 struct sdminilabel { 31 u_short npart; 32 u_long offset[MAXPARTITIONS]; 33 }; 34 35 struct sd_softc { 36 char sc_retry; 37 char sc_alive; 38 short sc_blkshift; 39 struct sdminilabel sc_pinfo; 40 } sd_softc[NSCSI][NSD]; 41 42 #define SDRETRY 2 43 44 sdinit(ctlr, unit) 45 int ctlr, unit; 46 { 47 register struct sd_softc *ss = &sd_softc[ctlr][unit]; 48 u_char stat; 49 int capbuf[2]; 50 51 stat = scsi_test_unit_rdy(ctlr, unit); 52 if (stat) { 53 /* drive may be doing RTZ - wait a bit */ 54 if (stat == STS_CHECKCOND) { 55 DELAY(1000000); 56 stat = scsi_test_unit_rdy(ctlr, unit); 57 } 58 if (stat) { 59 printf("sd(%d,%d,0,0): init failed (stat=%x)\n", 60 ctlr, unit, stat); 61 return (0); 62 } 63 } 64 /* 65 * try to get the drive block size. 66 */ 67 capbuf[0] = 0; 68 capbuf[1] = 0; 69 stat = scsi_read_capacity(ctlr, unit, 70 (u_char *)capbuf, sizeof(capbuf)); 71 if (stat == 0) { 72 if (capbuf[1] > DEV_BSIZE) 73 for (; capbuf[1] > DEV_BSIZE; capbuf[1] >>= 1) 74 ++ss->sc_blkshift; 75 } 76 ss->sc_alive = 1; 77 return (1); 78 } 79 80 sdreset(ctlr, unit) 81 int ctlr, unit; 82 { 83 } 84 85 #ifdef COMPAT_NOLABEL 86 struct sdminilabel defaultpinfo = { 87 8, 88 { 1024, 17408, 0, 17408, 115712, 218112, 82944, 115712 } 89 }; 90 #endif 91 92 sdgetinfo(io) 93 register struct iob *io; 94 { 95 struct sd_softc *ss = &sd_softc[io->i_adapt][io->i_ctlr]; 96 register struct sdminilabel *pi = &ss->sc_pinfo; 97 register struct disklabel *lp = &sdlabel; 98 char *msg, *readdisklabel(); 99 int sdstrategy(), i; 100 101 bzero((caddr_t)lp, sizeof *lp); 102 lp->d_secsize = (DEV_BSIZE << ss->sc_blkshift); 103 msg = readdisklabel(io, sdstrategy, lp); 104 if (msg) { 105 printf("sd(%d,%d,%d,%d): WARNING: %s, ", 106 io->i_adapt, io->i_ctlr, io->i_unit, io->i_part, msg); 107 #ifdef COMPAT_NOLABEL 108 printf("using old default partitioning\n"); 109 *pi = defaultpinfo; 110 #else 111 printf("defining `c' partition as entire disk\n"); 112 pi->npart = 3; 113 pi->offset[0] = pi->offset[1] = -1; 114 pi->offset[2] = 0; 115 #endif 116 } else { 117 pi->npart = lp->d_npartitions; 118 for (i = 0; i < pi->npart; i++) 119 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 120 -1 : lp->d_partitions[i].p_offset; 121 } 122 return(1); 123 } 124 125 sdopen(io) 126 struct iob *io; 127 { 128 register struct sd_softc *ss; 129 int ctlr, unit, part; 130 131 devconvert(io); 132 133 ctlr = io->i_adapt; 134 if (ctlr >= NSCSI || scsialive(ctlr) == 0) 135 return (EADAPT); 136 unit = io->i_ctlr; 137 if (unit >= NSD) 138 return (ECTLR); 139 ss = &sd_softc[ctlr][unit]; 140 if (ss->sc_alive == 0) { 141 if (sdinit(ctlr, unit) == 0) 142 return (ENXIO); 143 if (sdgetinfo(io) == 0) 144 return (ERDLAB); 145 } 146 part = io->i_part; 147 if (part >= ss->sc_pinfo.npart || ss->sc_pinfo.offset[part] == -1) 148 return (EPART); 149 io->i_boff = ss->sc_pinfo.offset[part]; 150 return (0); 151 } 152 153 sdstrategy(io, func) 154 register struct iob *io; 155 int func; 156 { 157 register int ctlr = io->i_adapt; 158 register int unit = io->i_ctlr; 159 register struct sd_softc *ss = &sd_softc[ctlr][unit]; 160 daddr_t blk = io->i_bn >> ss->sc_blkshift; 161 u_int nblk = io->i_cc >> ss->sc_blkshift; 162 char stat; 163 164 if (io->i_cc == 0) 165 return(0); 166 167 ss->sc_retry = 0; 168 retry: 169 if (func == F_READ) 170 stat = scsi_tt_read(ctlr, unit, io->i_ma, io->i_cc, blk, nblk); 171 else 172 stat = scsi_tt_write(ctlr, unit, io->i_ma, io->i_cc, blk, nblk); 173 if (stat) { 174 printf("sd(%d,%d,%d,%d): block=%x, error=0x%x\n", 175 ctlr, unit, io->i_unit, io->i_part, blk, stat); 176 if (++ss->sc_retry > SDRETRY) 177 return(-1); 178 goto retry; 179 } 180 return(io->i_cc); 181 } 182