1 /* @(#)scsilog.c	1.25 10/12/19 Copyright 1998-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)scsilog.c	1.25 10/12/19 Copyright 1998-2010 J. Schilling";
6 #endif
7 /*
8  *	SCSI log page handling
9  *
10  *	Copyright (c) 1998-2010 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/mconfig.h>
27 
28 #include <schily/stdio.h>
29 #include <schily/standard.h>
30 #include <schily/utypes.h>
31 #include <schily/btorder.h>
32 #include <schily/schily.h>
33 #include <schily/nlsdefs.h>
34 
35 #include <scg/scgcmd.h>
36 #include <scg/scsidefs.h>
37 #include <scg/scsireg.h>
38 #include <scg/scsitransp.h>
39 
40 #include "scsilog.h"
41 
42 extern	int	lverbose;
43 
44 EXPORT	int	log_sense		__PR((SCSI *scgp, caddr_t bp, int cnt, int page, int pc, int pp));
45 EXPORT	BOOL	has_log_page		__PR((SCSI *scgp, int page, int pc));
46 EXPORT	int	get_log			__PR((SCSI *scgp, caddr_t bp, int *lenp, int page, int pc, int pp));
47 EXPORT	void	print_logpages		__PR((SCSI *scgp));
48 
49 /*
50  * Currently not implemented: PPC, SP
51  */
52 EXPORT int
log_sense(scgp,bp,cnt,page,pc,pp)53 log_sense(scgp, bp, cnt, page, pc, pp)
54 	SCSI	*scgp;
55 	caddr_t	bp;
56 	int	cnt;
57 	int	page;	/* Page code */
58 	int	pc;	/* Page control */
59 	int	pp;	/* Parameter Pointer */
60 {
61 	register struct	scg_cmd	*scmd = scgp->scmd;
62 
63 	fillbytes(bp, cnt, '\0');
64 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
65 	scmd->addr = bp;
66 	scmd->size = cnt;
67 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
68 	scmd->cdb_len = SC_G1_CDBLEN;
69 	scmd->sense_len = CCS_SENSE_LEN;
70 	scmd->cdb.g1_cdb.cmd = 0x4D;
71 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
72 	scmd->cdb.g1_cdb.addr[0] = (pc << 6) | (page & 0x3f);
73 	i_to_2_byte(&scmd->cdb.cmd_cdb[5], pp);
74 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
75 
76 	scgp->cmdname = "log sense";
77 
78 	if (scg_cmd(scgp) < 0)
79 		return (-1);
80 	if (scgp->verbose)
81 		scg_prbytes(_("Log sense Data   :"), (Uchar *)bp, cnt - scg_getresid(scgp));
82 	return (0);
83 }
84 
85 EXPORT BOOL
has_log_page(scgp,page,pc)86 has_log_page(scgp, page, pc)
87 	SCSI	*scgp;
88 	int	page;
89 	int	pc;
90 {
91 	Uchar	log[0x3F + sizeof (scsi_log_hdr)];
92 	int	len;
93 	int	i;
94 	struct scsi_logpage_0 *sp = (struct scsi_logpage_0 *)log;
95 
96 	scgp->silent++;
97 	if (log_sense(scgp, (caddr_t)log, sizeof (scsi_log_hdr), 0, pc, 0) < 0) {
98 		scgp->silent--;
99 		return (FALSE);
100 	}
101 
102 	len = a_to_u_2_byte(sp->hdr.p_len);
103 
104 	if (log_sense(scgp, (caddr_t)log, len + sizeof (scsi_log_hdr), 0, pc, 0) < 0) {
105 		scgp->silent--;
106 		return (FALSE);
107 	}
108 	scgp->silent--;
109 
110 	len -= scg_getresid(scgp);
111 
112 	for (i = 0; i < len; i++) {
113 		if (page == sp->p_code[i])
114 			return (TRUE);
115 	}
116 	return (FALSE);
117 }
118 
119 EXPORT int
get_log(scgp,bp,lenp,page,pc,pp)120 get_log(scgp, bp, lenp, page, pc, pp)
121 	SCSI	*scgp;
122 	caddr_t	bp;
123 	int	*lenp;
124 	int	page;
125 	int	pc;
126 	int	pp;
127 {
128 	Uchar		log[sizeof (scsi_log_hdr)];
129 	scsi_log_hdr	*hp = (scsi_log_hdr *)log;
130 	int		maxlen = *lenp;
131 	int		len;
132 
133 	if (log_sense(scgp, (caddr_t)log, sizeof (scsi_log_hdr), page, pc, pp) < 0)
134 		return (-1);
135 	len = a_to_u_2_byte(hp->p_len);
136 	*lenp = len + sizeof (scsi_log_hdr);
137 	if ((len + (int)sizeof (scsi_log_hdr)) > maxlen)
138 		len = maxlen - sizeof (scsi_log_hdr);
139 
140 	if (log_sense(scgp, bp, len + sizeof (scsi_log_hdr), page, pc, pp) < 0)
141 		return (-1);
142 	return (0);
143 }
144 
145 EXPORT void
print_logpages(scgp)146 print_logpages(scgp)
147 	SCSI	*scgp;
148 {
149 	Uchar	log[0x3F + sizeof (scsi_log_hdr)];
150 	int	len;
151 	int	i;
152 	struct scsi_logpage_0 *sp = (struct scsi_logpage_0 *)log;
153 
154 	scgp->silent++;
155 	if (log_sense(scgp, (caddr_t)log, sizeof (scsi_log_hdr), 0, LOG_CUMUL, 0) < 0) {
156 		scgp->silent--;
157 		return;
158 	}
159 
160 	len = a_to_u_2_byte(sp->hdr.p_len);
161 
162 	if (log_sense(scgp, (caddr_t)log, len + sizeof (scsi_log_hdr), 0, LOG_CUMUL,  0) < 0) {
163 		scgp->silent--;
164 		return;
165 	}
166 	scgp->silent--;
167 
168 	len -= scg_getresid(scgp);
169 
170 	printf(_("Supported log pages:"));
171 
172 	for (i = 0; i < len; i++) {
173 		printf(" %X", sp->p_code[i]);
174 	}
175 	printf("\n");
176 }
177