1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
/*
$Id: freebsd.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This file contains FreeBSD-specific code and implements low-level
control of the CD drive. Culled initially I think from xine's or
mplayer's FreeBSD code with lots of modifications.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <cdio/sector.h>
#include "cdio_assert.h"
#include "cdio_private.h"
/*!
For ioctl access /dev/acd0c is preferred over /dev/cd0c.
For cam access /dev/cd0c is preferred. DEFAULT_CDIO_DEVICE and
DEFAULT_FREEBSD_AM should be consistent.
*/
#ifndef DEFAULT_CDIO_DEVICE
#define DEFAULT_CDIO_DEVICE "/dev/cd0c"
#endif
#ifndef DEFUALT_FREEBSD_AM
#define DEFAULT_FREEBSD_AM _AM_CAM
#endif
#include <string.h>
#ifdef HAVE_FREEBSD_CDROM
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_SYS_CDIO_H
# include <sys/cdio.h>
#endif
#ifndef CDIOCREADAUDIO
struct ioc_read_audio
{
u_char address_format;
union msf_lba address;
int nframes;
u_char* buffer;
};
#define CDIOCREADAUDIO _IOWR('c',31,struct ioc_read_audio)
#endif
#include <sys/cdrio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* for __FreeBSD_version */
#if __FreeBSD_kernel_version < 500000
#define DEVICE_POSTFIX "c"
#else
#define DEVICE_POSTFIX ""
#endif
#define HAVE_FREEBSD_CAM
#ifdef HAVE_FREEBSD_CAM
#include <camlib.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
#include <errno.h>
#define ERRCODE(s) ((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13]))
#define EMEDIUMTYPE EINVAL
#define ENOMEDIUM ENODEV
#define CREAM_ON_ERRNO(s) do { \
switch ((s)[12]) \
{ case 0x04: errno=EAGAIN; break; \
case 0x20: errno=ENODEV; break; \
case 0x21: if ((s)[13]==0) errno=ENOSPC; \
else errno=EINVAL; \
break; \
case 0x30: errno=EMEDIUMTYPE; break; \
case 0x3A: errno=ENOMEDIUM; break; \
} \
} while(0)
#endif /*HAVE_FREEBSD_CAM*/
#include <cdio/util.h>
#define TOTAL_TRACKS ( p_env->tochdr.ending_track \
- p_env->tochdr.starting_track + 1)
#define FIRST_TRACK_NUM (p_env->tochdr.starting_track)
typedef enum {
_AM_NONE,
_AM_IOCTL,
_AM_CAM
} access_mode_t;
typedef struct {
/* Things common to all drivers like this.
This must be first. */
generic_img_private_t gen;
#ifdef HAVE_FREEBSD_CAM
char *device;
struct cam_device *cam;
union ccb ccb;
#endif
access_mode_t access_mode;
bool b_ioctl_init;
bool b_cam_init;
/* Track information */
struct ioc_toc_header tochdr;
/* Entry info for each track. Add 1 for leadout. */
struct ioc_read_toc_single_entry tocent[CDIO_CD_MAX_TRACKS+1];
} _img_private_t;
bool cdio_is_cdrom_freebsd_ioctl(char *drive, char *mnttype);
track_format_t get_track_format_freebsd_ioctl(const _img_private_t *env,
track_t i_track);
bool get_track_green_freebsd_ioctl(const _img_private_t *env,
track_t i_track);
int eject_media_freebsd_ioctl (_img_private_t *env);
int eject_media_freebsd_cam (_img_private_t *env);
void get_drive_cap_freebsd_cam (const _img_private_t *p_env,
cdio_drive_read_cap_t *p_read_cap,
cdio_drive_write_cap_t *p_write_cap,
cdio_drive_misc_cap_t *p_misc_cap);
char *get_mcn_freebsd_ioctl (const _img_private_t *p_env);
void free_freebsd_cam (void *obj);
/*!
Using the ioctl method, r nblocks of audio sectors from cd device
into data starting from lsn. Returns 0 if no error.
*/
int read_audio_sectors_freebsd_ioctl (_img_private_t *env, void *data,
lsn_t lsn, unsigned int nblocks);
/*!
Using the CAM method, reads nblocks of mode2 sectors from
cd device using into data starting from lsn. Returns 0 if no
error.
*/
int read_mode2_sector_freebsd_cam (_img_private_t *env, void *data,
lsn_t lsn, bool b_form2);
/*!
Using the ioctl method, reads nblocks of mode2 sectors from
cd device using into data starting from lsn. Returns 0 if no
error.
*/
int read_mode2_sector_freebsd_ioctl (_img_private_t *env, void *data,
lsn_t lsn, bool b_form2);
/*!
Using the CAM method, reads nblocks of mode2 form2 sectors from
cd device using into data starting from lsn. Returns 0 if no
error.
Note: if you want form1 sectors, the caller has to pick out the
appropriate piece.
*/
int read_mode2_sectors_freebsd_cam (_img_private_t *env, void *buf,
lsn_t lsn, unsigned int nblocks);
bool read_toc_freebsd_ioctl (_img_private_t *env);
/*!
Run a SCSI MMC command.
p_user_data internal CD structure.
i_timeout time in milliseconds we will wait for the command
to complete. If this value is -1, use the default
time-out value.
i_cdb Size of p_cdb
p_cdb CDB bytes.
e_direction direction the transfer is to go.
i_buf Size of buffer
p_buf Buffer for data, both sending and receiving
Return 0 if no error.
*/
int run_scsi_cmd_freebsd_cam( const void *p_user_data,
unsigned int i_timeout_ms,
unsigned int i_cdb,
const scsi_mmc_cdb_t *p_cdb,
scsi_mmc_direction_t e_direction,
unsigned int i_buf,
/*in/out*/ void *p_buf );
/*!
Return the size of the CD in logical block address (LBA) units.
*/
uint32_t stat_size_freebsd_cam (_img_private_t *env);
uint32_t stat_size_freebsd_ioctl (_img_private_t *env);
bool init_freebsd_cam (_img_private_t *env);
void free_freebsd_cam (void *user_data);
#endif /*HAVE_FREEBSD_CDROM*/
|