1 /* @(#)scsi-syllable.c 1.2 12/12/02 Copyright 1998-2012 J. Schilling, 2005 Kristian Van Der Vliet */
2 #ifndef lint
3 static char sccsid[] =
4 "@(#)scsi-syllable.c 1.2 12/12/02 Copyright 1998-2012 J. Schilling, 2005 Kristian Van Der Vliet";
5 #endif
6 /*
7 * Interface for the Syllable "SCSI" implementation.
8 *
9 * Current versions of Syllable do not implement a complete SCSI layer,
10 * but the ATAPI portion of the ATA driver has a simple interface that
11 * can be used to send raw ATAPI packets to the device.
12 *
13 * This drives can be seen only as a first hack. As it does not support
14 * SCSI bus scanning, there is not yet support for the auto-target
15 * feature os higher level applications.
16 *
17 * Warning: you may change this source, but if you do that
18 * you need to change the _scg_version and _scg_auth* string below.
19 * You may not return "schily" for an SCG_AUTHOR request anymore.
20 * Choose your name instead of "schily" and make clear that the version
21 * string is related to a modified source.
22 *
23 * Copyright (c) 1998-2012 J. Schilling
24 */
25 /*
26 * The contents of this file are subject to the terms of the
27 * Common Development and Distribution License, Version 1.0 only
28 * (the "License"). You may not use this file except in compliance
29 * with the License.
30 *
31 * See the file CDDL.Schily.txt in this distribution for details.
32 * A copy of the CDDL is also available via the Internet at
33 * http://www.opensource.org/licenses/cddl1.txt
34 *
35 * The following exceptions apply:
36 * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
37 * combining Covered Software with other code if all other code is governed by
38 * the terms of a license that is OSI approved (see www.opensource.org) and
39 * you may distribute the Larger Work as a single product. In such a case,
40 * You must make sure the requirements of this License are fulfilled for
41 * the Covered Software."
42 *
43 * When distributing Covered Code, include this CDDL HEADER in each
44 * file and include the License file CDDL.Schily.txt from this distribution.
45 */
46
47 /*
48 * Warning: you may change this source, but if you do that
49 * you need to change the _scg_version and _scg_auth* string below.
50 * You may not return "schily" for an SCG_AUTHOR request anymore.
51 * Choose your name instead of "schily" and make clear that the version
52 * string is related to a modified source.
53 */
54 LOCAL char _scg_trans_version[] = "scsi-syllable.c-1.2"; /* The version for this transport */
55
56 #include <schily/stdlib.h>
57 #include <schily/stdio.h>
58 #include <schily/string.h>
59 #include <schily/unistd.h>
60 #include <schily/stat.h>
61 #ifdef __PYRO__ /* Pyro */
62 #include <pyro/types.h>
63 #include <pyro/cdrom.h>
64 #else /* Syllable and AtheOS */
65 #include <atheos/types.h>
66 #include <atheos/cdrom.h>
67 #endif
68
69 #define MAX_SCG 16 /* Max # of SCSI controllers */
70
71 struct scg_local {
72 int fd;
73 };
74
75 #define scglocal(p) ((struct scg_local *)((p)->local))
76
77 /*
78 * Return version information for the low level SCSI transport code.
79 * This has been introduced to make it easier to trace down problems
80 * in applications.
81 */
82 LOCAL char *
scgo_version(scgp,what)83 scgo_version(scgp, what)
84 SCSI *scgp;
85 int what;
86 {
87 if (scgp != (SCSI *)0) {
88 switch (what) {
89
90 case SCG_VERSION:
91 return (_scg_trans_version);
92 case SCG_AUTHOR:
93 return ("vanders");
94 case SCG_SCCS_ID:
95 return (__sccsid);
96 }
97 }
98 return ((char *)0);
99 }
100
101 LOCAL int
scgo_help(scgp,f)102 scgo_help(scgp, f)
103 SCSI *scgp;
104 FILE *f;
105 {
106 __scg_help(f, "ATA", "ATA Packet SCSI transport",
107 "ATAPI:", "device", "/dev/disk/ata/cdc/raw", FALSE, TRUE);
108 return (0);
109 }
110
111 LOCAL int
scgo_open(scgp,device)112 scgo_open(scgp, device)
113 SCSI *scgp;
114 char *device;
115 {
116 int fd;
117
118 if (device == NULL || *device == '\0') {
119 errno = EINVAL;
120 if (scgp->errstr)
121 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
122 "'devname' must be specified on this OS");
123 return (-1);
124 }
125
126 if (scgp->local == NULL) {
127 scgp->local = malloc(sizeof (struct scg_local));
128 if (scgp->local == NULL)
129 return (0);
130 scglocal(scgp)->fd = -1;
131 }
132
133 if (scglocal(scgp)->fd != -1) /* multiple open? */
134 return (1);
135
136 if ((scglocal(scgp)->fd = open(device, O_RDONLY, 0)) < 0) {
137 if (scgp->errstr)
138 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
139 "Cannot open '%s'", device);
140 return (-1);
141 }
142
143 scg_settarget(scgp, 0, 0, 0);
144
145 return (1);
146 }
147
148 LOCAL int
scgo_close(scgp)149 scgo_close(scgp)
150 SCSI *scgp;
151 {
152 if (scgp->local == NULL)
153 return (-1);
154
155 if (scglocal(scgp)->fd >= 0)
156 close(scglocal(scgp)->fd);
157 scglocal(scgp)->fd = -1;
158 return (0);
159 }
160
161 LOCAL long
scgo_maxdma(scgp,amt)162 scgo_maxdma(scgp, amt)
163 SCSI *scgp;
164 long amt;
165 {
166 return (256*1024);
167 }
168
169 LOCAL void *
scgo_getbuf(scgp,amt)170 scgo_getbuf(scgp, amt)
171 SCSI *scgp;
172 long amt;
173 {
174 if (scgp->debug > 0) {
175 js_fprintf((FILE *)scgp->errfile,
176 "scgo_getbuf: %ld bytes\n", amt);
177 }
178 scgp->bufbase = malloc((size_t)(amt));
179 return (scgp->bufbase);
180 }
181
182 LOCAL void
scgo_freebuf(scgp)183 scgo_freebuf(scgp)
184 SCSI *scgp;
185 {
186 if (scgp->bufbase)
187 free(scgp->bufbase);
188 scgp->bufbase = NULL;
189 }
190
191 LOCAL int
scgo_numbus(scgp)192 scgo_numbus(scgp)
193 SCSI *scgp;
194 {
195 return (MAX_SCG);
196 }
197
198 LOCAL BOOL
scgo_havebus(scgp,busno)199 scgo_havebus(scgp, busno)
200 SCSI *scgp;
201 int busno;
202 {
203 return (TRUE);
204 }
205
206 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)207 scgo_fileno(scgp, busno, tgt, tlun)
208 SCSI *scgp;
209 int busno;
210 int tgt;
211 int tlun;
212 {
213 if (scgp->local == NULL)
214 return (-1);
215
216 return ((busno < 0 || busno >= MAX_SCG) ? -1 : scglocal(scgp)->fd);
217 }
218
219 LOCAL int
scgo_initiator_id(scgp)220 scgo_initiator_id(scgp)
221 SCSI *scgp;
222 {
223 return (-1);
224 }
225
226 LOCAL int
scgo_isatapi(scgp)227 scgo_isatapi(scgp)
228 SCSI *scgp;
229 {
230 return (TRUE);
231 }
232
233 LOCAL int
scgo_reset(scgp,what)234 scgo_reset(scgp, what)
235 SCSI *scgp;
236 int what;
237 {
238 errno = EINVAL;
239 return (-1);
240 }
241
242 LOCAL int
scgo_send(scgp)243 scgo_send(scgp)
244 SCSI *scgp;
245 {
246 struct scg_cmd *sp = scgp->scmd;
247 int ret;
248 cdrom_packet_cmd_s cmd;
249
250 if (scgp->fd < 0) {
251 sp->error = SCG_FATAL;
252 return (-1);
253 }
254
255 /*
256 * As long as we only support ATAPI, we limit the SCSI CDB size to 12.
257 */
258 if (sp->cdb_len > 12) {
259 if (scgp->debug > 0)
260 error("sp->cdb_len > 12!\n");
261 sp->error = SCG_FATAL;
262 sp->ux_errno = EIO;
263 return (0);
264 }
265
266 /* initialize */
267 fillbytes((caddr_t) & cmd, sizeof (cmd), '\0');
268 fillbytes((caddr_t) & sp->u_sense.cmd_sense,
269 sizeof (sp->u_sense.cmd_sense), '\0');
270
271 memcpy(cmd.nCommand, &(sp->cdb), sp->cdb_len);
272 cmd.nCommandLength = sp->cdb_len;
273 cmd.pnData = (uint8 *)sp->addr;
274 cmd.nDataLength = sp->size;
275 cmd.pnSense = (uint8 *)sp->u_sense.cmd_sense;
276 cmd.nSenseLength = sp->sense_len;
277 cmd.nFlags = 0;
278
279 if (sp->size > 0) {
280 if (sp->flags & SCG_RECV_DATA)
281 cmd.nDirection = READ;
282 else
283 cmd.nDirection = WRITE;
284 } else {
285 cmd.nDirection = NO_DATA;
286 }
287
288 if (scgp->debug > 0) {
289 error("SEND(%d): cmd %02x, cdb = %d, data = %d, sense = %d\n",
290 scgp->fd, cmd.nCommand[0], cmd.nCommandLength,
291 cmd.nDataLength, cmd.nSenseLength);
292 }
293 ret = ioctl(scgp->fd, CD_PACKET_COMMAND, &cmd, sizeof (cmd));
294 if (ret < 0)
295 sp->ux_errno = geterrno();
296
297 if (ret < 0 && scgp->debug > 4) {
298 js_fprintf((FILE *) scgp->errfile,
299 "ioctl(CD_PACKET_COMMAND) ret: %d\n", ret);
300 }
301
302 if (ret < 0 && cmd.nError) {
303 sp->u_scb.cmd_scb[0] = ST_CHK_COND;
304 if (scgp->debug > 0)
305 error("result: scsi %02x\n", cmd.nError);
306
307 switch (cmd.nError) {
308
309 case SC_UNIT_ATTENTION:
310 case SC_NOT_READY:
311 sp->error = SCG_RETRYABLE; /* may be BUS_BUSY */
312 sp->u_scb.cmd_scb[0] |= ST_BUSY;
313 break;
314 case SC_ILLEGAL_REQUEST:
315 break;
316 default:
317 break;
318 }
319 } else {
320 sp->u_scb.cmd_scb[0] = 0x00;
321 }
322
323 return (0);
324 }
325