Merge branch 'master' into 'master'
[brasero.git] / libbrasero-media / scsi-cam.c
blobd9370f2474ba5798858a06b64c0ab51e21b5f8c8
1 /***************************************************************************
2 * scsi-cam.c
4 * Saturday February 16, 2008
5 * Copyright 2008 Joe Marcus Clarke
6 * <marcus@FreeBSD.org>
7 ****************************************************************************/
9 /*
10 * Copyright (C) Joe Marcus Clarke 2008 <marcus@FreeBSD.org>
12 * Libbrasero-media is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * The Libbrasero-media authors hereby grant permission for non-GPL compatible
18 * GStreamer plugins to be used and distributed together with GStreamer
19 * and Libbrasero-media. This permission is above and beyond the permissions granted
20 * by the GPL license by which Libbrasero-media is covered. If you modify this code
21 * you may extend this exception to your version of the code, but you are not
22 * obligated to do so. If you do not wish to do so, delete this exception
23 * statement from your version.
25 * Libbrasero-media 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 Library General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to:
32 * The Free Software Foundation, Inc.,
33 * 51 Franklin Street, Fifth Floor
34 * Boston, MA 02110-1301, USA.
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
41 #include <errno.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <string.h>
48 #include <sys/ioctl.h>
50 #include <glib.h>
52 #include "brasero-media-private.h"
53 #include "scsi-command.h"
54 #include "scsi-utils.h"
55 #include "scsi-error.h"
56 #include "scsi-sense-data.h"
58 /* FreeBSD's SCSI CAM interface */
60 #include <camlib.h>
61 #include <cam/scsi/scsi_message.h>
63 struct _BraseroDeviceHandle {
64 struct cam_device *cam;
65 int fd;
68 struct _BraseroScsiCmd {
69 uchar cmd [BRASERO_SCSI_CMD_MAX_LEN];
70 BraseroDeviceHandle *handle;
72 const BraseroScsiCmdInfo *info;
74 typedef struct _BraseroScsiCmd BraseroScsiCmd;
76 #define BRASERO_SCSI_CMD_OPCODE_OFF 0
77 #define BRASERO_SCSI_CMD_SET_OPCODE(command) (command->cmd [BRASERO_SCSI_CMD_OPCODE_OFF] = command->info->opcode)
79 #define OPEN_FLAGS O_RDONLY /*|O_EXCL */|O_NONBLOCK
81 BraseroScsiResult
82 brasero_scsi_command_issue_sync (gpointer command,
83 gpointer buffer,
84 int size,
85 BraseroScsiErrCode *error)
87 int timeout;
88 BraseroScsiCmd *cmd;
89 union ccb cam_ccb;
90 int direction = -1;
92 timeout = 10;
94 memset (&cam_ccb, 0, sizeof(cam_ccb));
95 cmd = command;
97 cam_ccb.ccb_h.path_id = cmd->handle->cam->path_id;
98 cam_ccb.ccb_h.target_id = cmd->handle->cam->target_id;
99 cam_ccb.ccb_h.target_lun = cmd->handle->cam->target_lun;
101 if (cmd->info->direction & BRASERO_SCSI_READ)
102 direction = CAM_DIR_IN;
103 else if (cmd->info->direction & BRASERO_SCSI_WRITE)
104 direction = CAM_DIR_OUT;
106 g_assert (direction > -1);
108 cam_fill_csio(&cam_ccb.csio,
110 NULL,
111 direction,
112 MSG_SIMPLE_Q_TAG,
113 buffer,
114 size,
115 sizeof(cam_ccb.csio.sense_data),
116 cmd->info->size,
117 timeout * 1000);
119 memcpy (cam_ccb.csio.cdb_io.cdb_bytes, cmd->cmd,
120 BRASERO_SCSI_CMD_MAX_LEN);
122 if (cam_send_ccb (cmd->handle->cam, &cam_ccb) == -1) {
123 BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_ERRNO);
124 return BRASERO_SCSI_FAILURE;
127 if ((cam_ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
128 BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_ERRNO);
129 return BRASERO_SCSI_FAILURE;
132 return BRASERO_SCSI_OK;
135 gpointer
136 brasero_scsi_command_new (const BraseroScsiCmdInfo *info,
137 BraseroDeviceHandle *handle)
139 BraseroScsiCmd *cmd;
141 /* make sure we can set the flags of the descriptor */
143 /* allocate the command */
144 cmd = g_new0 (BraseroScsiCmd, 1);
145 cmd->info = info;
146 cmd->handle = handle;
148 BRASERO_SCSI_CMD_SET_OPCODE (cmd);
149 return cmd;
152 BraseroScsiResult
153 brasero_scsi_command_free (gpointer cmd)
155 g_free (cmd);
156 return BRASERO_SCSI_OK;
160 * This is to open a device
163 BraseroDeviceHandle *
164 brasero_device_handle_open (const gchar *path,
165 gboolean exclusive,
166 BraseroScsiErrCode *code)
168 int fd;
169 int flags = OPEN_FLAGS;
170 BraseroDeviceHandle *handle;
171 struct cam_device *cam;
173 g_assert (path != NULL);
175 /* if (exclusive)
176 flags |= O_EXCL;*/
178 /* cam_open_device() fails unless we use O_RDWR */
179 cam = cam_open_device (path, O_RDWR);
180 fd = open (path, flags);
181 if (cam && fd > -1) {
182 handle = g_new0 (BraseroDeviceHandle, 1);
183 handle->cam = cam;
184 handle->fd = fd;
186 else {
187 int serrno;
189 if (code) {
190 if (errno == EAGAIN
191 || errno == EWOULDBLOCK
192 || errno == EBUSY)
193 *code = BRASERO_SCSI_NOT_READY;
194 else
195 *code = BRASERO_SCSI_ERRNO;
198 serrno = errno;
200 if (fd > -1)
201 close (fd);
202 if (cam)
203 cam_close_device (cam);
205 errno = serrno;
207 return NULL;
210 return handle;
213 void
214 brasero_device_handle_close (BraseroDeviceHandle *handle)
216 g_assert (handle != NULL);
218 if (handle->cam)
219 cam_close_device (handle->cam);
221 close (handle->fd);
223 g_free (handle);
226 char *
227 brasero_device_get_bus_target_lun (const gchar *device)
229 struct cam_device *cam_dev;
230 char *addr;
232 cam_dev = cam_open_device (device, O_RDWR);
234 if (cam_dev == NULL) {
235 BRASERO_MEDIA_LOG ("CAM: Failed to open %s: %s", device, g_strerror (errno));
236 return NULL;
239 addr = g_strdup_printf ("%i,%i,%i", cam_dev->path_id, cam_dev->target_id, cam_dev->target_lun);
241 cam_close_device (cam_dev);
242 return addr;