1 /*
2 * Copyright (c) 1992 OMRON Corporation.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * OMRON Corporation.
8 *
9 * %sccs.include.redist.c%
10 *
11 * @(#)sd.c 8.1 (Berkeley) 06/10/93
12 */
13
14 /*
15 * sd.c -- SCSI DISK device driver
16 * by A.Fujita, FEB-26-1992
17 */
18
19
20 /*
21 * SCSI CCS (Command Command Set) disk driver.
22 */
23 #define NSD 2
24
25 #include <sys/param.h>
26 #include <sys/disklabel.h>
27 #include <luna68k/dev/scsireg.h>
28 #include <luna68k/stand/saio.h>
29 #include <luna68k/stand/device.h>
30
31
32 int sdinit(), sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
33
34 struct driver sddriver = {
35 sdinit, "sd", sdstart, sdgo, sdintr,
36 };
37
38 struct disklabel sdlabel[NSD];
39
40 struct sd_softc {
41 struct hp_device *sc_hd;
42 struct devqueue sc_dq;
43 int sc_format_pid; /* process using "format" mode */
44 short sc_flags;
45 short sc_type; /* drive type */
46 short sc_punit; /* physical unit (scsi lun) */
47 u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */
48 u_int sc_blks; /* number of blocks on device */
49 int sc_blksize; /* device block size in bytes */
50 u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */
51 } sd_softc[NSD];
52
53 /* sc_flags values */
54 #define SDF_ALIVE 0x1
55
56 #define sdunit(x) ((minor(x) >> 3) & 0x7)
57 #define sdpart(x) (minor(x) & 0x7)
58 #define sdpunit(x) ((x) & 7)
59
60 static struct scsi_inquiry inqbuf;
61 static struct scsi_fmt_cdb inq = {
62 6,
63 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
64 };
65
66 static u_long capbuf[2];
67 struct scsi_fmt_cdb cap = {
68 10,
69 CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
70 };
71
72 int
sdident(sc,hd)73 sdident(sc, hd)
74 struct sd_softc *sc;
75 struct hp_device *hd;
76 {
77 char idstr[32];
78 int unit;
79 register int ctlr, slave;
80 register int i;
81 register int tries = 10;
82
83 ctlr = hd->hp_ctlr;
84 slave = hd->hp_slave;
85 unit = sc->sc_punit;
86
87 /*
88 * See if unit exists and is a disk then read block size & nblocks.
89 */
90 while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
91 if (i < 0 || --tries < 0)
92 return (-1);
93 if (i == STS_CHECKCOND) {
94 u_char sensebuf[8];
95 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
96
97 scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
98 if (sp->class == 7 && sp->key == 6)
99 /* drive doing an RTZ -- give it a while */
100 DELAY(1000000);
101 }
102 DELAY(1000);
103 }
104 if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
105 sizeof(inqbuf)) ||
106 scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
107 sizeof(capbuf)))
108 /* doesn't exist or not a CCS device */
109 return (-1);
110
111 switch (inqbuf.type) {
112 case 0: /* disk */
113 case 4: /* WORM */
114 case 5: /* CD-ROM */
115 case 7: /* Magneto-optical */
116 break;
117 default: /* not a disk */
118 return (-1);
119 }
120 sc->sc_blks = capbuf[0];
121 sc->sc_blksize = capbuf[1];
122
123 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
124 for (i = 27; i > 23; --i)
125 if (idstr[i] != ' ')
126 break;
127 idstr[i+1] = 0;
128 for (i = 23; i > 7; --i)
129 if (idstr[i] != ' ')
130 break;
131 idstr[i+1] = 0;
132 for (i = 7; i >= 0; --i)
133 if (idstr[i] != ' ')
134 break;
135 idstr[i+1] = 0;
136 printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
137 &idstr[24]);
138
139 printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
140 if (sc->sc_blksize != DEV_BSIZE) {
141 if (sc->sc_blksize < DEV_BSIZE) {
142 printf("sd%d: need %d byte blocks - drive ignored\n",
143 unit, DEV_BSIZE);
144 return (-1);
145 }
146 for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
147 ++sc->sc_bshift;
148 sc->sc_blks <<= sc->sc_bshift;
149 }
150 sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */
151 return(inqbuf.type);
152 }
153
154 int
sdinit(hd)155 sdinit(hd)
156 register struct hp_device *hd;
157 {
158 register struct sd_softc *sc = &sd_softc[hd->hp_unit];
159 register struct disklabel *lp;
160 char *msg, *readdisklabel();
161
162 #ifdef DEBUG
163 printf("sdinit: hd->hp_unit = %d\n", hd->hp_unit);
164 printf("sdinit: hd->hp_ctlr = %d, hd->hp_slave = %d\n",
165 hd->hp_ctlr, hd->hp_slave);
166 #endif
167 sc->sc_hd = hd;
168 sc->sc_punit = sdpunit(hd->hp_flags);
169 sc->sc_type = sdident(sc, hd);
170 if (sc->sc_type < 0)
171 return(0);
172
173 /*
174 * Use the default sizes until we've read the label,
175 * or longer if there isn't one there.
176 */
177 lp = &sdlabel[hd->hp_unit];
178
179 if (lp->d_secpercyl == 0) {
180 lp->d_secsize = DEV_BSIZE;
181 lp->d_nsectors = 32;
182 lp->d_ntracks = 20;
183 lp->d_secpercyl = 32*20;
184 lp->d_npartitions = 1;
185 lp->d_partitions[0].p_offset = 0;
186 lp->d_partitions[0].p_size = LABELSECTOR + 1;
187 }
188
189 /*
190 * read disklabel
191 */
192 if (msg = readdisklabel(hd->hp_slave, sdstrategy, lp)) {
193 if (msg != NULL)
194 printf("sd%d: %s\n", hd->hp_unit, msg);
195 }
196
197 sc->sc_flags = SDF_ALIVE;
198 return(1);
199 }
200
201 int
sdopen(io)202 sdopen(io)
203 struct iob *io;
204 {
205 register int unit = io->i_unit;
206 register struct disklabel *lp;
207
208 if (unit < 0 || unit >= NSD)
209 return(-1);
210
211 lp = &sdlabel[unit];
212 io->i_boff = lp->d_partitions[io->i_boff].p_offset;
213 }
214
215 static struct scsi_fmt_cdb cdb_read = {
216 10,
217 CMD_READ_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0
218 };
219
220 static struct scsi_fmt_cdb cdb_write = {
221 6,
222 CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0
223 };
224
225 int
sdstrategy(io,func)226 sdstrategy(io, func)
227 register struct iob *io;
228 register int func;
229 {
230 int unit = io->i_unit;
231 struct sd_softc *sc = &sd_softc[unit];
232 struct scsi_fmt_cdb *cdb;
233 daddr_t blk = io->i_bn >> sc->sc_bshift;
234 u_int nblk = io->i_cc >> sc->sc_bshift;
235 int stat, ctlr, slave, i;
236
237 if (unit < 0 || unit >= NSD)
238 return(-1);
239
240 ctlr = sc->sc_hd->hp_ctlr;
241 slave = sc->sc_hd->hp_slave;
242
243 if (func == READ)
244 cdb = &cdb_read;
245 else
246 cdb = &cdb_write;
247
248 cdb->cdb[2] = (blk & 0xff000000) >> 24;
249 cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
250 cdb->cdb[4] = (blk & 0x0000ff00) >> 8;
251 cdb->cdb[5] = (blk & 0x000000ff);
252
253 cdb->cdb[7] = ((nblk >> DEV_BSHIFT) & 0xff00) >> 8;
254 cdb->cdb[8] = ((nblk >> DEV_BSHIFT) & 0x00ff);
255
256 #ifdef DEBUG
257 printf("sdstrategy: io->i_unit = %d\n", io->i_unit);
258 printf("sdstrategy: blk = %d (0x%x), nblk = %d (0x%x)\n", blk, blk, nblk, nblk);
259 for (i = 0; i < 10; i++)
260 printf("sdstrategy: cdb[%d] = 0x%x\n", i, cdb->cdb[i]);
261 printf("sdstrategy: ctlr = %d, slave = %d\n", ctlr, slave);
262 #endif
263 stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, io->i_ma, io->i_cc);
264
265 return(io->i_cc);
266 }
267
268 int
sdustart()269 sdustart()
270 {
271 }
272
273 int
sdstart()274 sdstart()
275 {
276 }
277
278 int
sdgo()279 sdgo()
280 {
281 }
282
283 int
sdintr()284 sdintr()
285 {
286 }
287
288 int
sdread(dev,blk,nblk,buff,len)289 sdread(dev, blk, nblk, buff, len)
290 dev_t dev;
291 u_int blk;
292 u_int nblk;
293 u_char *buff;
294 u_int len;
295 {
296 register int unit = sdunit(dev);
297 register int part = sdpart(dev);
298 struct sd_softc *sc = &sd_softc[unit];
299 struct scsi_fmt_cdb *cdb;
300 int stat, ctlr, slave;
301
302 ctlr = sc->sc_hd->hp_ctlr;
303 slave = sc->sc_hd->hp_slave;
304
305 cdb = &cdb_read;
306
307 cdb->cdb[2] = (blk & 0xff000000) >> 24;
308 cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
309 cdb->cdb[4] = (blk & 0x0000ff00) >> 8;
310 cdb->cdb[5] = (blk & 0x000000ff);
311
312 cdb->cdb[7] = (nblk & 0xff00) >> 8;
313 cdb->cdb[8] = (nblk & 0x00ff);
314
315 stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, buff, len);
316
317 if (stat == 0)
318 return(1);
319 else
320 return(0);
321 }
322
323 int
sdioctl(dev,data)324 sdioctl(dev, data)
325 dev_t dev;
326 u_long data[];
327 {
328 register int unit = sdunit(dev);
329 register int part = sdpart(dev);
330 register struct disklabel *lp;
331
332 if (unit < 0 || unit >= NSD)
333 return(0);
334
335 if (part < 0 || part >= MAXPARTITIONS)
336 return(0);
337
338 lp = &sdlabel[unit];
339 data[0] = lp->d_partitions[part].p_offset;
340 data[1] = lp->d_partitions[part].p_size;
341
342 return(1);
343 }
344