1 /* @(#)scsi-hpux.c	1.34 09/10/09 Copyright 1997 J. Schilling */
2 #ifndef lint
3 static	char __sccsid[] =
4 	"@(#)scsi-hpux.c	1.34 09/10/09 Copyright 1997 J. Schilling";
5 #endif
6 /*
7  *	Interface for the HP-UX generic SCSI implementation.
8  *
9  *	Warning: you may change this source, but if you do that
10  *	you need to change the _scg_version and _scg_auth* string below.
11  *	You may not return "schily" for an SCG_AUTHOR request anymore.
12  *	Choose your name instead of "schily" and make clear that the version
13  *	string is related to a modified source.
14  *
15  *	Copyright (c) 1997 J. Schilling
16  */
17 /*
18  * The contents of this file are subject to the terms of the
19  * Common Development and Distribution License, Version 1.0 only
20  * (the "License").  You may not use this file except in compliance
21  * with the License.
22  *
23  * See the file CDDL.Schily.txt in this distribution for details.
24  * A copy of the CDDL is also available via the Internet at
25  * http://www.opensource.org/licenses/cddl1.txt
26  *
27  * The following exceptions apply:
28  * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
29  * combining Covered Software with other code if all other code is governed by
30  * the terms of a license that is OSI approved (see www.opensource.org) and
31  * you may distribute the Larger Work as a single product. In such a case,
32  * You must make sure the requirements of this License are fulfilled for
33  * the Covered Software."
34  *
35  * When distributing Covered Code, include this CDDL HEADER in each
36  * file and include the License file CDDL.Schily.txt from this distribution.
37  */
38 
39 #undef	sense
40 #include <sys/scsi.h>
41 
42 /*
43  *	Warning: you may change this source, but if you do that
44  *	you need to change the _scg_version and _scg_auth* string below.
45  *	You may not return "schily" for an SCG_AUTHOR request anymore.
46  *	Choose your name instead of "schily" and make clear that the version
47  *	string is related to a modified source.
48  */
49 LOCAL	char	_scg_trans_version[] = "scsi-hpux.c-1.34";	/* The version for this transport*/
50 
51 #define	MAX_SCG		16	/* Max # of SCSI controllers */
52 #define	MAX_TGT		16
53 #define	MAX_LUN		8
54 
55 struct scg_local {
56 	short	scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
57 };
58 #define	scglocal(p)	((struct scg_local *)((p)->local))
59 
60 #ifdef	SCSI_MAXPHYS
61 #define	MAX_DMA_HP	SCSI_MAXPHYS
62 #else
63 #define	MAX_DMA_HP	(63*1024)	/* Check if this is not too big */
64 #endif
65 
66 
67 /*
68  * Return version information for the low level SCSI transport code.
69  * This has been introduced to make it easier to trace down problems
70  * in applications.
71  */
72 LOCAL char *
scgo_version(scgp,what)73 scgo_version(scgp, what)
74 	SCSI	*scgp;
75 	int	what;
76 {
77 	if (scgp != (SCSI *)0) {
78 		switch (what) {
79 
80 		case SCG_VERSION:
81 			return (_scg_trans_version);
82 		/*
83 		 * If you changed this source, you are not allowed to
84 		 * return "schily" for the SCG_AUTHOR request.
85 		 */
86 		case SCG_AUTHOR:
87 			return (_scg_auth_schily);
88 		case SCG_SCCS_ID:
89 			return (__sccsid);
90 		}
91 	}
92 	return ((char *)0);
93 }
94 
95 LOCAL int
scgo_help(scgp,f)96 scgo_help(scgp, f)
97 	SCSI	*scgp;
98 	FILE	*f;
99 {
100 	__scg_help(f, "SIOC", "Generic SCSI",
101 		"", "bus,target,lun", "1,2,0", TRUE, FALSE);
102 	return (0);
103 }
104 
105 LOCAL int
scgo_open(scgp,device)106 scgo_open(scgp, device)
107 	SCSI	*scgp;
108 	char	*device;
109 {
110 		int	busno	= scg_scsibus(scgp);
111 		int	tgt	= scg_target(scgp);
112 		int	tlun	= scg_lun(scgp);
113 	register int	f;
114 	register int	b;
115 	register int	t;
116 	register int	l;
117 	register int	nopen = 0;
118 	char		devname[64];
119 
120 	if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
121 		errno = EINVAL;
122 		if (scgp->errstr)
123 			js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
124 				"Illegal value for busno, target or lun '%d,%d,%d'",
125 				busno, tgt, tlun);
126 		return (-1);
127 	}
128 
129 	if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
130 		errno = EINVAL;
131 		if (scgp->errstr)
132 			js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
133 				"Open by 'devname' not supported on this OS");
134 		return (-1);
135 	}
136 
137 	if (scgp->local == NULL) {
138 		scgp->local = malloc(sizeof (struct scg_local));
139 		if (scgp->local == NULL)
140 			return (0);
141 
142 		for (b = 0; b < MAX_SCG; b++) {
143 			for (t = 0; t < MAX_TGT; t++) {
144 				for (l = 0; l < MAX_LUN; l++)
145 					scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
146 			}
147 		}
148 	}
149 
150 	if (busno >= 0 && tgt >= 0 && tlun >= 0) {
151 
152 		js_snprintf(devname, sizeof (devname),
153 				"/dev/rscsi/c%xt%xl%x", busno, tgt, tlun);
154 		f = open(devname, O_RDWR);
155 		if (f < 0)
156 			return (-1);
157 		scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
158 		return (1);
159 	} else {
160 		for (b = 0; b < MAX_SCG; b++) {
161 			for (t = 0; t < MAX_TGT; t++) {
162 /*				for (l = 0; l < MAX_LUN; l++) {*/
163 				for (l = 0; l < 1; l++) {
164 					js_snprintf(devname, sizeof (devname),
165 							"/dev/rscsi/c%xt%xl%x", b, t, l);
166 /*error("name: '%s'\n", devname);*/
167 					f = open(devname, O_RDWR);
168 					if (f >= 0) {
169 						scglocal(scgp)->scgfiles[b][t][l] = (short)f;
170 						nopen++;
171 					} else if (scgp->debug > 0) {
172 						errmsg("open '%s'\n", devname);
173 					}
174 				}
175 			}
176 		}
177 	}
178 	return (nopen);
179 }
180 
181 LOCAL int
scgo_close(scgp)182 scgo_close(scgp)
183 	SCSI	*scgp;
184 {
185 	register int	f;
186 	register int	b;
187 	register int	t;
188 	register int	l;
189 
190 	if (scgp->local == NULL)
191 		return (-1);
192 
193 	for (b = 0; b < MAX_SCG; b++) {
194 		for (t = 0; t < MAX_TGT; t++) {
195 			for (l = 0; l < MAX_LUN; l++) {
196 				f = scglocal(scgp)->scgfiles[b][t][l];
197 				if (f >= 0)
198 					close(f);
199 				scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
200 			}
201 		}
202 	}
203 	return (0);
204 }
205 
206 LOCAL long
scgo_maxdma(scgp,amt)207 scgo_maxdma(scgp, amt)
208 	SCSI	*scgp;
209 	long	amt;
210 {
211 	return	(MAX_DMA_HP);
212 }
213 
214 LOCAL void *
scgo_getbuf(scgp,amt)215 scgo_getbuf(scgp, amt)
216 	SCSI	*scgp;
217 	long	amt;
218 {
219 	if (scgp->debug > 0) {
220 		js_fprintf((FILE *)scgp->errfile,
221 			"scgo_getbuf: %ld bytes\n", amt);
222 	}
223 	scgp->bufbase = valloc((size_t)(amt));
224 	return (scgp->bufbase);
225 }
226 
227 LOCAL void
scgo_freebuf(scgp)228 scgo_freebuf(scgp)
229 	SCSI	*scgp;
230 {
231 	if (scgp->bufbase)
232 		free(scgp->bufbase);
233 	scgp->bufbase = NULL;
234 }
235 
236 LOCAL int
scgo_numbus(scgp)237 scgo_numbus(scgp)
238 	SCSI	*scgp;
239 {
240 	return (MAX_SCG);
241 }
242 
243 LOCAL BOOL
scgo_havebus(scgp,busno)244 scgo_havebus(scgp, busno)
245 	SCSI	*scgp;
246 	int	busno;
247 {
248 	register int	t;
249 	register int	l;
250 
251 	if (busno < 0 || busno >= MAX_SCG)
252 		return (FALSE);
253 
254 	if (scgp->local == NULL)
255 		return (FALSE);
256 
257 	for (t = 0; t < MAX_TGT; t++) {
258 		for (l = 0; l < MAX_LUN; l++)
259 			if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
260 				return (TRUE);
261 	}
262 	return (FALSE);
263 }
264 
265 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)266 scgo_fileno(scgp, busno, tgt, tlun)
267 	SCSI	*scgp;
268 	int	busno;
269 	int	tgt;
270 	int	tlun;
271 {
272 	if (busno < 0 || busno >= MAX_SCG ||
273 	    tgt < 0 || tgt >= MAX_TGT ||
274 	    tlun < 0 || tlun >= MAX_LUN)
275 		return (-1);
276 
277 	if (scgp->local == NULL)
278 		return (-1);
279 
280 	return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
281 }
282 
283 LOCAL int
scgo_initiator_id(scgp)284 scgo_initiator_id(scgp)
285 	SCSI	*scgp;
286 {
287 	return (-1);
288 }
289 
290 LOCAL int
scgo_isatapi(scgp)291 scgo_isatapi(scgp)
292 	SCSI	*scgp;
293 {
294 	return (FALSE);
295 }
296 
297 LOCAL int
scgo_reset(scgp,what)298 scgo_reset(scgp, what)
299 	SCSI	*scgp;
300 	int	what;
301 {
302 	if (what == SCG_RESET_NOP)
303 		return (0);
304 	if (what != SCG_RESET_BUS) {
305 		errno = EINVAL;
306 		return (-1);
307 	}
308 	return (ioctl(scgp->fd, SIOC_RESET_BUS, 0));
309 }
310 
311 LOCAL int
scgo_send(scgp)312 scgo_send(scgp)
313 	SCSI		*scgp;
314 {
315 	struct scg_cmd	*sp = scgp->scmd;
316 	int		ret;
317 	int		flags;
318 	struct sctl_io	sctl_io;
319 
320 	if ((scgp->fd < 0) || (sp->cdb_len > sizeof (sctl_io.cdb))) {
321 		sp->error = SCG_FATAL;
322 		return (0);
323 	}
324 
325 	fillbytes((caddr_t)&sctl_io, sizeof (sctl_io), '\0');
326 
327 	flags = 0;
328 /*	flags = SCTL_INIT_WDTR|SCTL_INIT_SDTR;*/
329 	if (sp->flags & SCG_RECV_DATA)
330 		flags |= SCTL_READ;
331 	if ((sp->flags & SCG_DISRE_ENA) == 0)
332 		flags |= SCTL_NO_ATN;
333 
334 	sctl_io.flags		= flags;
335 
336 	movebytes(&sp->cdb, sctl_io.cdb, sp->cdb_len);
337 	sctl_io.cdb_length	= sp->cdb_len;
338 
339 	sctl_io.data_length	= sp->size;
340 	sctl_io.data		= sp->addr;
341 
342 	if (sp->timeout == 0)
343 		sctl_io.max_msecs = 0;
344 	else
345 		sctl_io.max_msecs = (sp->timeout * 1000) + 500;
346 
347 	errno		= 0;
348 	sp->error	= SCG_NO_ERROR;
349 	sp->sense_count	= 0;
350 	sp->u_scb.cmd_scb[0] = 0;
351 	sp->resid	= 0;
352 
353 	ret = ioctl(scgp->fd, SIOC_IO, &sctl_io);
354 	if (ret < 0) {
355 		sp->error = SCG_FATAL;
356 		sp->ux_errno = errno;
357 		return (ret);
358 	}
359 if (scgp->debug > 0)
360 error("cdb_status: %X, size: %d xfer: %d senselen: %d sensexfer: %d\n",
361 sctl_io.cdb_status, sctl_io.data_length, sctl_io.data_xfer, sp->sense_len, sctl_io.sense_xfer);
362 
363 	if (sctl_io.cdb_status == 0 || sctl_io.cdb_status == 0x02)
364 		sp->resid = sp->size - sctl_io.data_xfer;
365 
366 	if (sctl_io.cdb_status & SCTL_SELECT_TIMEOUT ||
367 			sctl_io.cdb_status & SCTL_INVALID_REQUEST) {
368 		sp->error = SCG_FATAL;
369 #ifdef	SCTL_POWERFAIL
370 	} else if (sctl_io.cdb_status & SCTL_POWERFAIL) {	/* Cannot select ATA */
371 		sp->error = SCG_FATAL;
372 #endif
373 	} else if (sctl_io.cdb_status & SCTL_INCOMPLETE) {
374 		sp->error = SCG_TIMEOUT;
375 	} else if (sctl_io.cdb_status > 0xFF) {
376 		errmsgno(EX_BAD, "SCSI problems: cdb_status: %X\n", sctl_io.cdb_status);
377 
378 	} else if ((sctl_io.cdb_status & 0xFF) != 0) {
379 /*		sp->error = SCG_RETRYABLE;*/
380 		sp->ux_errno = EIO;
381 
382 		sp->u_scb.cmd_scb[0] = sctl_io.cdb_status & 0xFF;
383 
384 		sp->sense_count = sctl_io.sense_xfer;
385 		if (sp->sense_count > SCG_MAX_SENSE)
386 			sp->sense_count = SCG_MAX_SENSE;
387 
388 		if (sctl_io.sense_status != S_GOOD) {
389 			sp->sense_count = 0;
390 		} else {
391 			movebytes(sctl_io.sense, sp->u_sense.cmd_sense, sp->sense_count);
392 		}
393 
394 	}
395 	return (ret);
396 }
397 #define	sense	u_sense.Sense
398