/[debburn]/cdrkit/trunk/libusal/scsi-next.c
ViewVC logotype

Contents of /cdrkit/trunk/libusal/scsi-next.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 462 - (show annotations) (download)
Sat Nov 25 00:20:20 2006 UTC (6 years, 5 months ago) by blade
File MIME type: text/plain
File size: 11034 byte(s)
Cleanup with lots of libschily/* libc reinventions
1 /*
2 * This file has been modified for the cdrkit suite.
3 *
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
6 *
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
10 *
11 */
12
13 /* @(#)scsi-next.c 1.32 04/01/15 Copyright 1997 J. Schilling */
14 #ifndef lint
15 static char __sccsid[] =
16 "@(#)scsi-next.c 1.32 04/01/15 Copyright 1997 J. Schilling";
17 #endif
18 /*
19 * Interface for the NeXT Step generic SCSI implementation.
20 *
21 * This is a hack, that tries to emulate the functionality
22 * of the usal driver.
23 *
24 * Warning: you may change this source, but if you do that
25 * you need to change the _usal_version and _usal_auth* string below.
26 * You may not return "schily" for an SCG_AUTHOR request anymore.
27 * Choose your name instead of "schily" and make clear that the version
28 * string is related to a modified source.
29 *
30 * Copyright (c) 1997 J. Schilling
31 */
32 /*
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License version 2
35 * as published by the Free Software Foundation.
36 *
37 * This program is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 * GNU General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License along with
43 * this program; see the file COPYING. If not, write to the Free Software
44 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
45 */
46
47 #include <bsd/dev/scsireg.h>
48
49 /*
50 * Warning: you may change this source, but if you do that
51 * you need to change the _usal_version and _usal_auth* string below.
52 * You may not return "schily" for an SCG_AUTHOR request anymore.
53 * Choose your name instead of "schily" and make clear that the version
54 * string is related to a modified source.
55 */
56 static char _usal_trans_version[] = "scsi-next.c-1.32"; /* The version for this transport*/
57
58 #define MAX_SCG 16 /* Max # of SCSI controllers */
59 #define MAX_TGT 16
60 #define MAX_LUN 8
61
62 struct usal_local {
63 short usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
64 int usalfile;
65 int max_scsibus;
66 int cur_scsibus;
67 int cur_target;
68 int cur_lun;
69 };
70 #define usallocal(p) ((struct usal_local *)((p)->local))
71
72 /*#define MAX_DMA_NEXT (32*1024)*/
73 #define MAX_DMA_NEXT (64*1024) /* Check if this is not too big */
74
75
76 static BOOL usal_setup(SCSI *usalp, int busno, int tgt, int tlun, BOOL ex);
77
78 /*
79 * Return version information for the low level SCSI transport code.
80 * This has been introduced to make it easier to trace down problems
81 * in applications.
82 */
83 static char *
84 usalo_version(SCSI *usalp, int what)
85 {
86 if (usalp != (SCSI *)0) {
87 switch (what) {
88
89 case SCG_VERSION:
90 return (_usal_trans_version);
91 /*
92 * If you changed this source, you are not allowed to
93 * return "schily" for the SCG_AUTHOR request.
94 */
95 case SCG_AUTHOR:
96 return (_usal_auth_cdrkit);
97 case SCG_SCCS_ID:
98 return (__sccsid);
99 }
100 }
101 return ((char *)0);
102 }
103
104 static int
105 usalo_help(SCSI *usalp, FILE *f)
106 {
107 __usal_help(f, "SGIOCREQ", "Generic SCSI",
108 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
109 return (0);
110 }
111
112 static int
113 usalo_open(SCSI *usalp, char *device)
114 {
115 int busno = usal_scsibus(usalp);
116 int tgt = usal_target(usalp);
117 int tlun = usal_lun(usalp);
118 register int f;
119 register int i;
120 char devname[64];
121
122 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
123 errno = EINVAL;
124 if (usalp->errstr)
125 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
126 "Illegal value for busno, target or lun '%d,%d,%d'",
127 busno, tgt, tlun);
128 return (-1);
129 }
130
131 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
132 errno = EINVAL;
133 if (usalp->errstr)
134 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
135 "Open by 'devname' not supported on this OS");
136 return (-1);
137 }
138
139 if (usalp->local == NULL) {
140 usalp->local = malloc(sizeof (struct usal_local));
141 if (usalp->local == NULL)
142 return (0);
143
144 usallocal(usalp)->usalfile = -1;
145 usallocal(usalp)->max_scsibus = -1;
146 usallocal(usalp)->cur_scsibus = -1;
147 usallocal(usalp)->cur_target = -1;
148 usallocal(usalp)->cur_lun = -1;
149 }
150
151 for (i = 0; i < 4; i++) {
152 snprintf(devname, sizeof (devname), "/dev/sg%d", i);
153 f = open(devname, O_RDWR);
154 if (usalp->debug > 0)
155 errmsg("open(devname: '%s') : %d\n", devname, f);
156 if (f < 0)
157 continue;
158 usallocal(usalp)->usalfile = f;
159 break;
160
161 }
162 if (f >= 0) {
163 if (usallocal(usalp)->max_scsibus < 0) {
164 for (i = 0; i < MAX_SCG; i++) {
165 if (!SCGO_HAVEBUS(usalp, i))
166 break;
167 }
168 usallocal(usalp)->max_scsibus = i;
169 }
170 if (usalp->debug > 0) {
171 fprintf((FILE *)usalp->errfile,
172 "maxbus: %d\n", usallocal(usalp)->max_scsibus);
173 }
174 if (usallocal(usalp)->max_scsibus <= 0) {
175 usallocal(usalp)->max_scsibus = 1;
176 usallocal(usalp)->cur_scsibus = 0;
177 }
178
179 ioctl(f, SGIOCENAS);
180 if (busno > 0 && tgt > 0 && tlun > 0)
181 usal_setup(usalp, busno, tgt, tlun, TRUE);
182 return (1);
183 }
184 if (usalp->errstr)
185 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
186 "Cannot open '/dev/sg*'");
187 return (0);
188 }
189
190 static int
191 usalo_close(SCSI *usalp)
192 {
193 if (usalp->local == NULL)
194 return (-1);
195
196 if (usallocal(usalp)->usalfile >= 0)
197 close(usallocal(usalp)->usalfile);
198 usallocal(usalp)->usalfile = -1;
199 return (0);
200 }
201
202 static BOOL
203 usal_setup(SCSI *usalp, int busno, int tgt, int tlun, BOOL ex)
204 {
205 scsi_adr_t sadr;
206
207 sadr.sa_target = tgt;
208 sadr.sa_lun = tlun;
209
210 if (usalp->debug > 0) {
211 fprintf((FILE *)usalp->errfile,
212 "usal_setup curbus %d -> %d\n", usallocal(usalp)->cur_scsibus, busno);
213 }
214
215 if (usalp->debug > 0 && ((usallocal(usalp)->cur_scsibus < 0 || usallocal(usalp)->cur_scsibus != busno)))
216 fprintf((FILE *)usalp->errfile, "setting SCSI bus to: %d\n", busno);
217 if ((usallocal(usalp)->cur_scsibus < 0 || usallocal(usalp)->cur_scsibus != busno) &&
218 ioctl(usallocal(usalp)->usalfile, SGIOCCNTR, &busno) < 0) {
219
220 usallocal(usalp)->cur_scsibus = -1; /* Driver is in undefined state */
221 if (ex)
222 /* comerr("Cannot set SCSI bus\n");*/
223 errmsg("Cannot set SCSI bus\n");
224 return (FALSE);
225 }
226 usallocal(usalp)->cur_scsibus = busno;
227
228 if (usalp->debug > 0) {
229 fprintf((FILE *)usalp->errfile,
230 "setting target/lun to: %d/%d\n", tgt, tlun);
231 }
232 if (ioctl(usallocal(usalp)->usalfile, SGIOCSTL, &sadr) < 0) {
233 if (ex)
234 comerr("Cannot set SCSI address\n");
235 return (FALSE);
236 }
237 usallocal(usalp)->cur_scsibus = busno;
238 usallocal(usalp)->cur_target = tgt;
239 usallocal(usalp)->cur_lun = tlun;
240 return (TRUE);
241 }
242
243 static long
244 usalo_maxdma(SCSI *usalp, long amt)
245 {
246 long maxdma = MAX_DMA_NEXT;
247 #ifdef SGIOCMAXDMA
248 int m;
249
250 if (ioctl(usallocal(usalp)->usalfile, SGIOCMAXDMA, &m) >= 0) {
251 maxdma = m;
252 if (usalp->debug > 0) {
253 fprintf((FILE *)usalp->errfile,
254 "maxdma: %d\n", maxdma);
255 }
256 }
257 #endif
258 return (maxdma);
259 }
260 #ifdef XXX
261 #define SGIOCENAS _IO('s', 2) /* enable autosense */
262 #define SGIOCDAS _IO('s', 3) /* disable autosense */
263 #define SGIOCRST _IO('s', 4) /* reset SCSI bus */
264 #define SGIOCCNTR _IOW('s', 6, int) /* select controller */
265 #define SGIOCGAS _IOR('s', 7, int) /* get autosense */
266 #define SGIOCMAXDMA _IOR('s', 8, int) /* max DMA size */
267 #define SGIOCNUMTARGS _IOR('s', 9, int) /* # of targets/bus */
268 #endif
269
270 static void *
271 usalo_getbuf(SCSI *usalp, long amt)
272 {
273 if (usalp->debug > 0) {
274 fprintf((FILE *)usalp->errfile,
275 "usalo_getbuf: %ld bytes\n", amt);
276 }
277 usalp->bufbase = valloc((size_t)(amt));
278 return (usalp->bufbase);
279 }
280
281 static void
282 usalo_freebuf(SCSI *usalp)
283 {
284 if (usalp->bufbase)
285 free(usalp->bufbase);
286 usalp->bufbase = NULL;
287 }
288
289 static BOOL
290 usalo_havebus(SCSI *usalp, int busno)
291 {
292 if (busno < 0 || busno >= MAX_SCG)
293 return (FALSE);
294
295 if (usalp->local == NULL)
296 return (FALSE);
297
298 if (usallocal(usalp)->max_scsibus > 0 && busno >= usallocal(usalp)->max_scsibus)
299 return (FALSE);
300
301 return (usal_setup(usalp, busno, 0, 0, FALSE));
302 }
303
304 static int
305 usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
306 {
307 if (busno < 0 || busno >= MAX_SCG ||
308 tgt < 0 || tgt >= MAX_TGT ||
309 tlun < 0 || tlun >= MAX_LUN)
310 return (-1);
311 if (usallocal(usalp)->max_scsibus > 0 && busno >= usallocal(usalp)->max_scsibus)
312 return (-1);
313
314 if (usalp->local == NULL)
315 return (-1);
316
317 if ((busno != usallocal(usalp)->cur_scsibus) || (tgt != usallocal(usalp)->cur_target) || (tlun != usallocal(usalp)->cur_lun)) {
318 if (!usal_setup(usalp, busno, tgt, tlun, FALSE))
319 return (-1);
320 }
321 return (usallocal(usalp)->usalfile);
322 }
323
324 static int
325 usalo_initiator_id(SCSI *usalp)
326 {
327 return (-1);
328 }
329
330 static int
331 usalo_isatapi(SCSI *usalp)
332 {
333 return (FALSE);
334 }
335
336 static int
337 usalo_reset(SCSI *usalp, int what)
338 {
339 if (what == SCG_RESET_NOP)
340 return (0);
341 if (what != SCG_RESET_BUS) {
342 errno = EINVAL;
343 return (-1);
344 }
345 return (ioctl(usalp->fd, SGIOCRST, 0));
346 }
347
348 static int
349 usalo_send(SCSI *usalp)
350 {
351 struct usal_cmd *sp = usalp->scmd;
352 struct scsi_req req;
353 register long *lp1;
354 register long *lp2;
355 int ret = 0;
356
357 if (usalp->fd < 0 || (sp->cdb_len > sizeof (req.sr_cdb))) {
358 sp->error = SCG_FATAL;
359 sp->ux_errno = EIO;
360 return (0);
361 }
362 fillbytes(&req, sizeof (req), '\0');
363 movebytes(sp->cdb.cmd_cdb, &req.sr_cdb, sp->cdb_len);
364 if (sp->size) {
365 req.sr_dma_dir = SR_DMA_WR;
366 if (sp->flags & SCG_RECV_DATA)
367 req.sr_dma_dir = SR_DMA_RD;
368 }
369 req.sr_addr = sp->addr;
370 req.sr_dma_max = sp->size;
371 req.sr_ioto = sp->timeout;
372 if (ioctl(usalp->fd, SGIOCREQ, (void *)&req) < 0) {
373 ret = -1;
374 sp->ux_errno = geterrno();
375 if (sp->ux_errno != ENOTTY)
376 ret = 0;
377 } else {
378 sp->ux_errno = 0;
379 }
380 if (usalp->debug > 0) {
381 fprintf((FILE *)usalp->errfile, "dma_dir: %X\n", req.sr_dma_dir);
382 fprintf((FILE *)usalp->errfile, "dma_addr: %X\n", req.sr_addr);
383 fprintf((FILE *)usalp->errfile, "io_time: %d\n", req.sr_ioto);
384 fprintf((FILE *)usalp->errfile, "io_status: %d\n", req.sr_io_status);
385 fprintf((FILE *)usalp->errfile, "scsi_status: %X\n", req.sr_scsi_status);
386 fprintf((FILE *)usalp->errfile, "dma_xfer: %d\n", req.sr_dma_xfr);
387 }
388 sp->u_scb.cmd_scb[0] = req.sr_scsi_status;
389 sp->sense_count = sizeof (esense_reply_t);
390 if (sp->sense_count > sp->sense_len)
391 sp->sense_count = sp->sense_len;
392 if (sp->sense_count > SCG_MAX_SENSE)
393 sp->sense_count = SCG_MAX_SENSE;
394 if (sp->sense_count < 0)
395 sp->sense_count = 0;
396 movebytes(&req.sr_esense, sp->u_sense.cmd_sense, sp->sense_count);
397 sp->resid = sp->size - req.sr_dma_xfr;
398
399 switch (req.sr_io_status) {
400
401 case SR_IOST_GOOD: sp->error = SCG_NO_ERROR; break;
402
403 case SR_IOST_CHKSNV: sp->sense_count = 0;
404 case SR_IOST_CHKSV: sp->error = SCG_RETRYABLE;
405 break;
406
407 case SR_IOST_SELTO:
408 case SR_IOST_DMAOR:
409 sp->error = SCG_FATAL; break;
410
411 case SR_IOST_IOTO: sp->error = SCG_TIMEOUT; break;
412
413 case SR_IOST_PERM:
414 case SR_IOST_NOPEN:
415 sp->error = SCG_FATAL;
416 ret = (-1);
417 break;
418
419 default: sp->error = SCG_RETRYABLE; break;
420
421 }
422 return (ret);
423 }

  ViewVC Help
Powered by ViewVC 1.1.5