~ubuntu-branches/ubuntu/utopic/cdrdao/utopic

« back to all changes in this revision

Viewing changes to scsilib/libscg/scsi-qnx.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Suffield
  • Date: 2004-06-24 22:33:16 UTC
  • Revision ID: james.westby@ubuntu.com-20040624223316-534onzugaeeyq61j
Tags: upstream-1.1.9
ImportĀ upstreamĀ versionĀ 1.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* @(#)scsi-qnx.c       1.3 04/01/15 Copyright 1998-2003 J. Schilling */
 
2
#ifndef lint
 
3
static  char __sccsid[] =
 
4
        "@(#)scsi-qnx.c 1.3 04/01/15 Copyright 1998-2003 J. Schilling";
 
5
#endif
 
6
/*
 
7
 *      Interface for QNX (Neutrino generic SCSI implementation).
 
8
 *      First version adopted from the OSF-1 version by
 
9
 *      Kevin Chiles <kchiles@qnx.com>
 
10
 *
 
11
 *      Warning: you may change this source, but if you do that
 
12
 *      you need to change the _scg_version and _scg_auth* string below.
 
13
 *      You may not return "schily" for an SCG_AUTHOR request anymore.
 
14
 *      Choose your name instead of "schily" and make clear that the version
 
15
 *      string is related to a modified source.
 
16
 *
 
17
 *      Copyright (c) 1998-2003 J. Schilling
 
18
 */
 
19
/*
 
20
 * This program is free software; you can redistribute it and/or modify
 
21
 * it under the terms of the GNU General Public License as published by
 
22
 * the Free Software Foundation; either version 2, or (at your option)
 
23
 * any later version.
 
24
 *
 
25
 * This program is distributed in the hope that it will be useful,
 
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
28
 * GNU General Public License for more details.
 
29
 *
 
30
 * You should have received a copy of the GNU General Public License along with
 
31
 * this program; see the file COPYING.  If not, write to the Free Software
 
32
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
33
 */
 
34
 
 
35
#include <sys/mman.h>
 
36
#include <sys/types.h>
 
37
#include <sys/dcmd_cam.h>
 
38
#include <sys/cam_device.h>
 
39
 
 
40
/*
 
41
 *      Warning: you may change this source, but if you do that
 
42
 *      you need to change the _scg_version and _scg_auth* string below.
 
43
 *      You may not return "schily" for an SCG_AUTHOR request anymore.
 
44
 *      Choose your name instead of "schily" and make clear that the version
 
45
 *      string is related to a modified source.
 
46
 */
 
47
LOCAL   char    _scg_trans_version[] = "scsi-qnx.c-1.3";        /* The version for this transport*/
 
48
 
 
49
#define MAX_SCG         16      /* Max # of SCSI controllers */
 
50
#define MAX_TGT         16
 
51
#define MAX_LUN         8
 
52
 
 
53
struct scg_local {
 
54
        int             fd;
 
55
};
 
56
 
 
57
#define scglocal(p)     ((struct scg_local *)((p)->local))
 
58
#define QNX_CAM_MAX_DMA (32*1024)
 
59
 
 
60
#ifndef AUTO_SENSE_LEN
 
61
#       define  AUTO_SENSE_LEN  32      /* SCG_MAX_SENSE */
 
62
#endif
 
63
 
 
64
/*
 
65
 * Return version information for the low level SCSI transport code.
 
66
 * This has been introduced to make it easier to trace down problems
 
67
 * in applications.
 
68
 */
 
69
LOCAL char *
 
70
scgo_version(scgp, what)
 
71
        SCSI    *scgp;
 
72
        int     what;
 
73
{
 
74
        if (scgp != (SCSI *)0) {
 
75
                switch (what) {
 
76
 
 
77
                case SCG_VERSION:
 
78
                        return (_scg_trans_version);
 
79
                /*
 
80
                 * If you changed this source, you are not allowed to
 
81
                 * return "schily" for the SCG_AUTHOR request.
 
82
                 */
 
83
                case SCG_AUTHOR:
 
84
                        return ("Initial Version adopted from OSF-1 by QNX-people");
 
85
                        return (_scg_auth_schily);
 
86
                case SCG_SCCS_ID:
 
87
                        return (__sccsid);
 
88
                }
 
89
        }
 
90
        return ((char *)0);
 
91
}
 
92
 
 
93
LOCAL int
 
94
scgo_help(scgp, f)
 
95
        SCSI    *scgp;
 
96
        FILE    *f;
 
97
{
 
98
        __scg_help(f, "CAM", "Generic transport independent SCSI (Common Access Method)",
 
99
                "", "bus,target,lun", "1,2,0", TRUE, FALSE);
 
100
        return (0);
 
101
}
 
102
 
 
103
LOCAL int
 
104
scgo_open(scgp, device)
 
105
        SCSI    *scgp;
 
106
        char    *device;
 
107
{
 
108
        int fd;
 
109
 
 
110
        if (device == NULL || *device == '\0') {
 
111
                errno = EINVAL;
 
112
                if (scgp->errstr)
 
113
                        js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 
114
                                "'devname' must be specified on this OS");
 
115
                return (-1);
 
116
        }
 
117
 
 
118
        if (scgp->local == NULL) {
 
119
                scgp->local = malloc(sizeof (struct scg_local));
 
120
                if (scgp->local == NULL)
 
121
                        return (0);
 
122
                scglocal(scgp)->fd = -1;
 
123
        }
 
124
 
 
125
        if (scglocal(scgp)->fd != -1)   /* multiple open? */
 
126
                return (1);
 
127
 
 
128
        if ((scglocal(scgp)->fd = open(device, O_RDONLY, 0)) < 0) {
 
129
                if (scgp->errstr)
 
130
                        js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 
131
                                "Cannot open '%s'", device);
 
132
                return (-1);
 
133
        }
 
134
 
 
135
        scg_settarget(scgp, 0, 0, 0);
 
136
 
 
137
        return (1);
 
138
}
 
139
 
 
140
LOCAL int
 
141
scgo_close(scgp)
 
142
        SCSI    *scgp;
 
143
{
 
144
        if (scgp->local == NULL)
 
145
                return (-1);
 
146
 
 
147
        if (scglocal(scgp)->fd >= 0)
 
148
                close(scglocal(scgp)->fd);
 
149
        scglocal(scgp)->fd = -1;
 
150
        return (0);
 
151
}
 
152
 
 
153
LOCAL long
 
154
scgo_maxdma(scgp, amt)
 
155
        SCSI    *scgp;
 
156
        long    amt;
 
157
{
 
158
        long maxdma = QNX_CAM_MAX_DMA;
 
159
 
 
160
        return (maxdma);
 
161
}
 
162
 
 
163
LOCAL void *
 
164
scgo_getbuf(scgp, amt)
 
165
        SCSI    *scgp;
 
166
        long    amt;
 
167
{
 
168
        void    *addr;
 
169
 
 
170
        if (scgp->debug > 0) {
 
171
                js_fprintf((FILE *)scgp->errfile, "scgo_getbuf: %ld bytes\n", amt);
 
172
        }
 
173
 
 
174
        if ((addr = mmap(NULL, amt, PROT_READ | PROT_WRITE | PROT_NOCACHE,
 
175
                                                MAP_ANON | MAP_PHYS | MAP_NOX64K, NOFD, 0)) == MAP_FAILED) {
 
176
                return (NULL);
 
177
        }
 
178
 
 
179
        scgp->bufbase = addr;
 
180
        return (addr);
 
181
}
 
182
 
 
183
LOCAL void
 
184
scgo_freebuf(scgp)
 
185
        SCSI    *scgp;
 
186
{
 
187
        if (scgp->bufbase)
 
188
                munmap(scgp->bufbase, QNX_CAM_MAX_DMA);
 
189
        scgp->bufbase = NULL;
 
190
}
 
191
 
 
192
LOCAL BOOL
 
193
scgo_havebus(scgp, busno)
 
194
        SCSI    *scgp;
 
195
        int     busno;
 
196
{
 
197
        return (FALSE);
 
198
}
 
199
 
 
200
 
 
201
LOCAL int
 
202
scgo_fileno(scgp, busno, tgt, tlun)
 
203
        SCSI    *scgp;
 
204
        int     busno;
 
205
        int     tgt;
 
206
        int     tlun;
 
207
{
 
208
        if (scgp->local == NULL)
 
209
                return (-1);
 
210
 
 
211
        return ((busno < 0 || busno >= MAX_SCG) ? -1 : scglocal(scgp)->fd);
 
212
}
 
213
 
 
214
LOCAL int
 
215
scgo_initiator_id(scgp)
 
216
        SCSI    *scgp;
 
217
{
 
218
        return (-1);
 
219
}
 
220
 
 
221
LOCAL int
 
222
scgo_isatapi(scgp)
 
223
        SCSI    *scgp;
 
224
{
 
225
        cam_devinfo_t   cinfo;
 
226
 
 
227
        if (devctl(scgp->fd, DCMD_CAM_DEVINFO, &cinfo, sizeof (cinfo), NULL) != EOK) {
 
228
                return (TRUE);          /* default to ATAPI */
 
229
        }
 
230
        return ((cinfo.flags & DEV_ATAPI) ? TRUE : FALSE);
 
231
}
 
232
 
 
233
LOCAL int
 
234
scgo_reset(scgp, what)
 
235
        SCSI    *scgp;
 
236
        int     what;
 
237
{
 
238
        errno = EINVAL;
 
239
        return (-1);
 
240
}
 
241
 
 
242
LOCAL int
 
243
scgo_send(scgp)
 
244
        SCSI            *scgp;
 
245
{
 
246
        int             i;
 
247
        struct scg_cmd  *sp;
 
248
        int             icnt;
 
249
        iov_t           iov[3];
 
250
        CAM_PASS_THRU   cpt;
 
251
 
 
252
        icnt    = 1;
 
253
        sp      = scgp->scmd;
 
254
        if (scgp->fd < 0) {
 
255
                sp->error = SCG_FATAL;
 
256
                return (0);
 
257
        }
 
258
 
 
259
        memset(&cpt, 0, sizeof (cpt));
 
260
 
 
261
        sp->sense_count = 0;
 
262
        sp->ux_errno    = 0;
 
263
        sp->error       = SCG_NO_ERROR;
 
264
        cpt.cam_timeout = sp->timeout;
 
265
        cpt.cam_cdb_len = sp->cdb_len;
 
266
        memcpy(cpt.cam_cdb, sp->cdb.cmd_cdb, sp->cdb_len);
 
267
 
 
268
        if (sp->sense_len != -1) {
 
269
                cpt.cam_sense_len       = sp->sense_len;
 
270
                cpt.cam_sense_ptr       = sizeof (cpt); /* XXX Offset from start of struct to data ??? */
 
271
                icnt++;
 
272
        } else {
 
273
                cpt.cam_flags |= CAM_DIS_AUTOSENSE;
 
274
        }
 
275
 
 
276
        if (cpt.cam_dxfer_len = sp->size) {
 
277
                icnt++;
 
278
                cpt.cam_data_ptr        = (paddr_t)sizeof (cpt) + cpt.cam_sense_len;
 
279
                if (sp->flags & SCG_RECV_DATA) {
 
280
                        cpt.cam_flags |= CAM_DIR_IN;
 
281
                } else {
 
282
                        cpt.cam_flags |= CAM_DIR_OUT;
 
283
                }
 
284
        } else {
 
285
                cpt.cam_flags |= CAM_DIR_NONE;
 
286
        }
 
287
 
 
288
        SETIOV(&iov[0], &cpt, sizeof (cpt));
 
289
        SETIOV(&iov[1], sp->u_sense.cmd_sense, cpt.cam_sense_len);
 
290
        SETIOV(&iov[2], sp->addr, sp->size);
 
291
        if (devctlv(scglocal(scgp)->fd, DCMD_CAM_PASS_THRU, icnt, icnt, iov, iov, NULL)) {
 
292
                sp->ux_errno = geterrno();
 
293
                sp->error = SCG_FATAL;
 
294
                if (scgp->debug > 0) {
 
295
                        errmsg("cam_io failed\n");
 
296
                }
 
297
                return (0);
 
298
        }
 
299
 
 
300
        sp->resid               = cpt.cam_resid;
 
301
        sp->u_scb.cmd_scb[0]    = cpt.cam_scsi_status;
 
302
 
 
303
        switch (cpt.cam_status & CAM_STATUS_MASK) {
 
304
                case CAM_REQ_CMP:
 
305
                        break;
 
306
 
 
307
                case CAM_SEL_TIMEOUT:
 
308
                        sp->error       = SCG_FATAL;
 
309
                        sp->ux_errno    = EIO;
 
310
                        break;
 
311
 
 
312
                case CAM_CMD_TIMEOUT:
 
313
                        sp->error       = SCG_TIMEOUT;
 
314
                        sp->ux_errno    = EIO;
 
315
                        break;
 
316
 
 
317
                default:
 
318
                        sp->error       = SCG_RETRYABLE;
 
319
                        sp->ux_errno    = EIO;
 
320
                        break;
 
321
        }
 
322
 
 
323
        if (cpt.cam_status & CAM_AUTOSNS_VALID) {
 
324
                sp->sense_count = min(cpt.cam_sense_len - cpt.cam_sense_resid,
 
325
                                                        SCG_MAX_SENSE);
 
326
                sp->sense_count = min(sp->sense_count, sp->sense_len);
 
327
                if (sp->sense_len < 0)
 
328
                        sp->sense_count = 0;
 
329
        }
 
330
 
 
331
        return (0);
 
332
}