~ubuntu-branches/ubuntu/edgy/libcdio/edgy-updates

« back to all changes in this revision

Viewing changes to lib/_cdio_sunos.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-11-15 16:53:23 UTC
  • mfrom: (3.1.1 etch)
  • Revision ID: james.westby@ubuntu.com-20051115165323-peroku75syl2j36u
Tags: 0.76-1ubuntu1
* Sync to new Debian version, manually apply Ubuntu patches:
  - debian/control: Remove dpkg-awk build dependency.
  - debian/rules: hardcode $LIBCDEV. This keeps the diff small (compared to
    the original patch of changing every ${libcdev} occurence).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    $Id: _cdio_sunos.c,v 1.79 2004/11/18 01:56:09 rocky Exp $
3
 
 
4
 
    Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
5
 
    Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
6
 
 
7
 
    This program is free software; you can redistribute it and/or modify
8
 
    it under the terms of the GNU General Public License as published by
9
 
    the Free Software Foundation; either version 2 of the License, or
10
 
    (at your option) any later version.
11
 
 
12
 
    This program is distributed in the hope that it will be useful,
13
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
    GNU General Public License for more details.
16
 
 
17
 
    You should have received a copy of the GNU General Public License
18
 
    along with this program; if not, write to the Free Software
19
 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 
*/
21
 
 
22
 
#ifdef HAVE_CONFIG_H
23
 
# include "config.h"
24
 
#endif
25
 
 
26
 
#ifdef HAVE_STRING_H
27
 
#include <string.h>
28
 
#endif
29
 
 
30
 
#include <cdio/logging.h>
31
 
#include <cdio/sector.h>
32
 
#include <cdio/util.h>
33
 
#include <cdio/scsi_mmc.h>
34
 
#include "cdio_assert.h"
35
 
#include "cdio_private.h"
36
 
 
37
 
#define DEFAULT_CDIO_DEVICE "/vol/dev/aliases/cdrom0"
38
 
 
39
 
#ifdef HAVE_SOLARIS_CDROM
40
 
 
41
 
static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.79 2004/11/18 01:56:09 rocky Exp $";
42
 
 
43
 
#ifdef HAVE_GLOB_H
44
 
#include <glob.h>
45
 
#endif
46
 
 
47
 
#include <stdio.h>
48
 
#include <stdlib.h>
49
 
#include <errno.h>
50
 
#include <unistd.h>
51
 
#include <fcntl.h>
52
 
 
53
 
#ifdef HAVE_SYS_CDIO_H
54
 
# include <sys/cdio.h> /* CDIOCALLOW etc... */
55
 
#else 
56
 
#error "You need <sys/cdio.h> to have CDROM support"
57
 
#endif
58
 
 
59
 
#include <sys/dkio.h>
60
 
#include <sys/scsi/generic/commands.h>
61
 
#include <sys/scsi/impl/uscsi.h>
62
 
 
63
 
#include <sys/stat.h>
64
 
#include <sys/types.h>
65
 
#include <sys/ioctl.h>
66
 
#include "cdtext_private.h"
67
 
 
68
 
/* not defined in dkio.h yet */
69
 
#define DK_DVDRW 0x13
70
 
 
71
 
/* reader */
72
 
 
73
 
typedef  enum {
74
 
    _AM_NONE,
75
 
    _AM_SUN_CTRL_ATAPI,
76
 
    _AM_SUN_CTRL_SCSI
77
 
#if FINISHED
78
 
    _AM_READ_CD,
79
 
    _AM_READ_10
80
 
#endif
81
 
} access_mode_t;
82
 
 
83
 
 
84
 
typedef struct {
85
 
  /* Things common to all drivers like this. 
86
 
     This must be first. */
87
 
  generic_img_private_t gen; 
88
 
  
89
 
  access_mode_t access_mode;
90
 
 
91
 
  /* Some of the more OS specific things. */
92
 
  /* Entry info for each track, add 1 for leadout. */
93
 
  struct cdrom_tocentry  tocent[CDIO_CD_MAX_TRACKS+1]; 
94
 
 
95
 
  /* Track information */
96
 
  struct cdrom_tochdr    tochdr;
97
 
} _img_private_t;
98
 
 
99
 
static track_format_t get_track_format_solaris(void *p_user_data, 
100
 
                                               track_t i_track);
101
 
 
102
 
static access_mode_t 
103
 
str_to_access_mode_sunos(const char *psz_access_mode) 
104
 
{
105
 
  const access_mode_t default_access_mode = _AM_SUN_CTRL_SCSI;
106
 
 
107
 
  if (NULL==psz_access_mode) return default_access_mode;
108
 
  
109
 
  if (!strcmp(psz_access_mode, "ATAPI"))
110
 
    return _AM_SUN_CTRL_SCSI; /* force ATAPI to be SCSI */
111
 
  else if (!strcmp(psz_access_mode, "SCSI"))
112
 
    return _AM_SUN_CTRL_SCSI;
113
 
  else {
114
 
    cdio_warn ("unknown access type: %s. Default SCSI used.", 
115
 
               psz_access_mode);
116
 
    return default_access_mode;
117
 
  }
118
 
}
119
 
 
120
 
 
121
 
/*!
122
 
  Initialize CD device.
123
 
 */
124
 
static bool
125
 
init_solaris (_img_private_t *p_env)
126
 
{
127
 
 
128
 
  if (!cdio_generic_init(p_env)) return false;
129
 
  
130
 
  p_env->access_mode = _AM_SUN_CTRL_SCSI;    
131
 
 
132
 
  return true;
133
 
}
134
 
 
135
 
/*!
136
 
  Run a SCSI MMC command. 
137
 
 
138
 
  p_user_data   internal CD structure.
139
 
  i_timeout_ms   time in milliseconds we will wait for the command
140
 
                to complete. 
141
 
  i_cdb         Size of p_cdb
142
 
  p_cdb         CDB bytes. 
143
 
  e_direction   direction the transfer is to go.
144
 
  i_buf         Size of buffer
145
 
  p_buf         Buffer for data, both sending and receiving
146
 
 
147
 
  Return 0 if no error.
148
 
 */
149
 
static int
150
 
run_scsi_cmd_solaris( const void *p_user_data, unsigned int i_timeout_ms,
151
 
                      unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, 
152
 
                      scsi_mmc_direction_t e_direction, 
153
 
                      unsigned int i_buf, /*in/out*/ void *p_buf )
154
 
{
155
 
  const _img_private_t *p_env = p_user_data;
156
 
  struct uscsi_cmd cgc;
157
 
 
158
 
  memset (&cgc, 0, sizeof (struct uscsi_cmd));
159
 
  cgc.uscsi_cdb = (caddr_t) p_cdb;
160
 
 
161
 
  cgc.uscsi_flags = SCSI_MMC_DATA_READ == e_direction ? 
162
 
    USCSI_READ : USCSI_WRITE;
163
 
 
164
 
  cgc.uscsi_timeout = msecs2secs(i_timeout_ms);
165
 
  cgc.uscsi_bufaddr = p_buf;   
166
 
  cgc.uscsi_buflen  = i_buf;
167
 
  cgc.uscsi_cdblen  = i_cdb;
168
 
  
169
 
  return ioctl(p_env->gen.fd, USCSICMD, &cgc);
170
 
}
171
 
 
172
 
/*!
173
 
   Reads audio sectors from CD device into data starting from lsn.
174
 
   Returns 0 if no error. 
175
 
 
176
 
   May have to check size of nblocks. There may be a limit that
177
 
   can be read in one go, e.g. 25 blocks.
178
 
*/
179
 
 
180
 
static int
181
 
_read_audio_sectors_solaris (void *p_user_data, void *data, lsn_t lsn, 
182
 
                          unsigned int nblocks)
183
 
{
184
 
  struct cdrom_msf solaris_msf;
185
 
  msf_t _msf;
186
 
  struct cdrom_cdda cdda;
187
 
 
188
 
  _img_private_t *p_env = p_user_data;
189
 
 
190
 
  cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
191
 
  solaris_msf.cdmsf_min0   = cdio_from_bcd8(_msf.m);
192
 
  solaris_msf.cdmsf_sec0   = cdio_from_bcd8(_msf.s);
193
 
  solaris_msf.cdmsf_frame0 = cdio_from_bcd8(_msf.f);
194
 
  
195
 
  if (p_env->gen.ioctls_debugged == 75)
196
 
    cdio_debug ("only displaying every 75th ioctl from now on");
197
 
  
198
 
  if (p_env->gen.ioctls_debugged == 30 * 75)
199
 
    cdio_debug ("only displaying every 30*75th ioctl from now on");
200
 
  
201
 
  if (p_env->gen.ioctls_debugged < 75 
202
 
      || (p_env->gen.ioctls_debugged < (30 * 75)  
203
 
          && p_env->gen.ioctls_debugged % 75 == 0)
204
 
      || p_env->gen.ioctls_debugged % (30 * 75) == 0)
205
 
    cdio_debug ("reading %d", lsn);
206
 
  
207
 
  p_env->gen.ioctls_debugged++;
208
 
  
209
 
  cdda.cdda_addr    = lsn;
210
 
  cdda.cdda_length  = nblocks;
211
 
  cdda.cdda_data    = (caddr_t) data;
212
 
  cdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
213
 
  
214
 
  if (ioctl (p_env->gen.fd, CDROMCDDA, &cdda) == -1) {
215
 
    perror ("ioctl(..,CDROMCDDA,..)");
216
 
        return 1;
217
 
        /* exit (EXIT_FAILURE); */
218
 
  }
219
 
  
220
 
  return 0;
221
 
}
222
 
 
223
 
/*!
224
 
   Reads a single mode1 sector from cd device into data starting
225
 
   from lsn. Returns 0 if no error. 
226
 
 */
227
 
static int
228
 
_read_mode1_sector_solaris (void *env, void *data, lsn_t lsn, 
229
 
                            bool b_form2)
230
 
{
231
 
 
232
 
#if FIXED
233
 
  do something here. 
234
 
#else
235
 
  return cdio_generic_read_form1_sector(env, data, lsn);
236
 
#endif
237
 
}
238
 
 
239
 
/*!
240
 
   Reads nblocks of mode2 sectors from cd device into data starting
241
 
   from lsn.
242
 
   Returns 0 if no error. 
243
 
 */
244
 
static int
245
 
_read_mode1_sectors_solaris (void *p_user_data, void *p_data, lsn_t lsn, 
246
 
                             bool b_form2, unsigned int nblocks)
247
 
{
248
 
  _img_private_t *p_env = p_user_data;
249
 
  unsigned int i;
250
 
  int retval;
251
 
  unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
252
 
 
253
 
  for (i = 0; i < nblocks; i++) {
254
 
    if ( (retval = _read_mode1_sector_solaris (p_env, 
255
 
                                            ((char *)p_data) + (blocksize * i),
256
 
                                               lsn + i, b_form2)) )
257
 
      return retval;
258
 
  }
259
 
  return 0;
260
 
}
261
 
 
262
 
/*!
263
 
   Reads a single mode2 sector from cd device into data starting from lsn.
264
 
   Returns 0 if no error. 
265
 
 */
266
 
static int
267
 
_read_mode2_sector_solaris (void *p_user_data, void *p_data, lsn_t lsn, 
268
 
                            bool b_form2)
269
 
{
270
 
  char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
271
 
  struct cdrom_msf solaris_msf;
272
 
  msf_t _msf;
273
 
  int offset = 0;
274
 
  struct cdrom_cdxa cd_read;
275
 
 
276
 
  _img_private_t *p_env = p_user_data;
277
 
 
278
 
  cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
279
 
  solaris_msf.cdmsf_min0   = cdio_from_bcd8(_msf.m);
280
 
  solaris_msf.cdmsf_sec0   = cdio_from_bcd8(_msf.s);
281
 
  solaris_msf.cdmsf_frame0 = cdio_from_bcd8(_msf.f);
282
 
  
283
 
  if (p_env->gen.ioctls_debugged == 75)
284
 
    cdio_debug ("only displaying every 75th ioctl from now on");
285
 
  
286
 
  if (p_env->gen.ioctls_debugged == 30 * 75)
287
 
    cdio_debug ("only displaying every 30*75th ioctl from now on");
288
 
  
289
 
  if (p_env->gen.ioctls_debugged < 75 
290
 
      || (p_env->gen.ioctls_debugged < (30 * 75)  
291
 
          && p_env->gen.ioctls_debugged % 75 == 0)
292
 
      || p_env->gen.ioctls_debugged % (30 * 75) == 0)
293
 
    cdio_debug ("reading %2.2d:%2.2d:%2.2d",
294
 
                solaris_msf.cdmsf_min0, solaris_msf.cdmsf_sec0, 
295
 
                solaris_msf.cdmsf_frame0);
296
 
  
297
 
  p_env->gen.ioctls_debugged++;
298
 
  
299
 
  /* Using CDROMXA ioctl will actually use the same uscsi command
300
 
   * as ATAPI, except we don't need to be root
301
 
   */      
302
 
  offset = CDIO_CD_XA_SYNC_HEADER;
303
 
  cd_read.cdxa_addr = lsn;
304
 
  cd_read.cdxa_data = buf;
305
 
  cd_read.cdxa_length = 1;
306
 
  cd_read.cdxa_format = CDROM_XA_SECTOR_DATA;
307
 
  if (ioctl (p_env->gen.fd, CDROMCDXA, &cd_read) == -1) {
308
 
    perror ("ioctl(..,CDROMCDXA,..)");
309
 
    return 1;
310
 
    /* exit (EXIT_FAILURE); */
311
 
  }
312
 
  
313
 
  if (b_form2)
314
 
    memcpy (p_data, buf + (offset-CDIO_CD_SUBHEADER_SIZE), M2RAW_SECTOR_SIZE);
315
 
  else
316
 
    memcpy (((char *)p_data), buf + offset, CDIO_CD_FRAMESIZE);
317
 
  
318
 
  return 0;
319
 
}
320
 
 
321
 
/*!
322
 
   Reads nblocks of mode2 sectors from cd device into data starting
323
 
   from lsn.
324
 
   Returns 0 if no error. 
325
 
 */
326
 
static int
327
 
_read_mode2_sectors_solaris (void *p_user_data, void *data, lsn_t lsn, 
328
 
                             bool b_form2, unsigned int nblocks)
329
 
{
330
 
  _img_private_t *env = p_user_data;
331
 
  unsigned int i;
332
 
  int retval;
333
 
  unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
334
 
 
335
 
  for (i = 0; i < nblocks; i++) {
336
 
    if ( (retval = _read_mode2_sector_solaris (env, 
337
 
                                            ((char *)data) + (blocksize * i),
338
 
                                               lsn + i, b_form2)) )
339
 
      return retval;
340
 
  }
341
 
  return 0;
342
 
}
343
 
 
344
 
 
345
 
/*!
346
 
   Return the size of the CD in logical block address (LBA) units.
347
 
 */
348
 
static uint32_t 
349
 
_cdio_stat_size (void *p_user_data)
350
 
{
351
 
  _img_private_t *env = p_user_data;
352
 
 
353
 
  struct cdrom_tocentry tocent;
354
 
  uint32_t size;
355
 
 
356
 
  tocent.cdte_track  = CDIO_CDROM_LEADOUT_TRACK;
357
 
  tocent.cdte_format = CDIO_CDROM_LBA;
358
 
  if (ioctl (env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
359
 
    {
360
 
      perror ("ioctl(CDROMREADTOCENTRY)");
361
 
      exit (EXIT_FAILURE);
362
 
    }
363
 
 
364
 
  size = tocent.cdte_addr.lba;
365
 
 
366
 
  return size;
367
 
}
368
 
 
369
 
/*!
370
 
  Set the arg "key" with "value" in the source device.
371
 
  Currently "source" and "access-mode" are valid keys.
372
 
  "source" sets the source device in I/O operations 
373
 
  "access-mode" sets the the method of CD access 
374
 
 
375
 
  0 is returned if no error was found, and nonzero if there as an error.
376
 
*/
377
 
static int
378
 
_set_arg_solaris (void *p_user_data, const char key[], const char value[])
379
 
{
380
 
  _img_private_t *env = p_user_data;
381
 
 
382
 
  if (!strcmp (key, "source"))
383
 
    {
384
 
      if (!value)
385
 
        return -2;
386
 
 
387
 
      free (env->gen.source_name);
388
 
      
389
 
      env->gen.source_name = strdup (value);
390
 
    }
391
 
  else if (!strcmp (key, "access-mode"))
392
 
    {
393
 
      env->access_mode = str_to_access_mode_sunos(key);
394
 
    }
395
 
  else 
396
 
    return -1;
397
 
 
398
 
  return 0;
399
 
}
400
 
 
401
 
/*! 
402
 
  Read and cache the CD's Track Table of Contents and track info.
403
 
  Return true if successful or false if an error.
404
 
*/
405
 
static bool
406
 
read_toc_solaris (void *p_user_data) 
407
 
{
408
 
  _img_private_t *p_env = p_user_data;
409
 
  int i;
410
 
 
411
 
  /* read TOC header */
412
 
  if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) {
413
 
    cdio_warn("%s: %s\n", 
414
 
            "error in ioctl CDROMREADTOCHDR", strerror(errno));
415
 
    return false;
416
 
  }
417
 
 
418
 
  p_env->gen.i_first_track = p_env->tochdr.cdth_trk0;
419
 
  p_env->gen.i_tracks      = p_env->tochdr.cdth_trk1;
420
 
  
421
 
  /* read individual tracks */
422
 
  for (i=p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) {
423
 
    p_env->tocent[i-1].cdte_track = i;
424
 
    p_env->tocent[i-1].cdte_format = CDIO_CDROM_MSF;
425
 
    if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[i-1]) == -1 ) {
426
 
      cdio_warn("%s %d: %s\n",
427
 
              "error in ioctl CDROMREADTOCENTRY for track", 
428
 
              i, strerror(errno));
429
 
      return false;
430
 
    }
431
 
  }
432
 
 
433
 
  /* read the lead-out track */
434
 
  p_env->tocent[p_env->tochdr.cdth_trk1].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
435
 
  p_env->tocent[p_env->tochdr.cdth_trk1].cdte_format = CDIO_CDROM_MSF;
436
 
 
437
 
  if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, 
438
 
            &p_env->tocent[p_env->tochdr.cdth_trk1]) == -1 ) {
439
 
    cdio_warn("%s: %s\n", 
440
 
             "error in ioctl CDROMREADTOCENTRY for lead-out",
441
 
            strerror(errno));
442
 
    return false;
443
 
  }
444
 
 
445
 
  p_env->gen.toc_init = true;
446
 
  return true;
447
 
}
448
 
 
449
 
/*!
450
 
  Eject media in CD drive. If successful, as a side effect we 
451
 
  also free obj.
452
 
 */
453
 
static int 
454
 
eject_media_solaris (void *p_user_data) {
455
 
 
456
 
  _img_private_t *env = p_user_data;
457
 
  int ret;
458
 
 
459
 
  close(env->gen.fd);
460
 
  env->gen.fd = -1;
461
 
  if (env->gen.fd > -1) {
462
 
    if ((ret = ioctl(env->gen.fd, CDROMEJECT)) != 0) {
463
 
      cdio_generic_free((void *) env);
464
 
      cdio_warn ("CDROMEJECT failed: %s\n", strerror(errno));
465
 
      return 1;
466
 
    } else {
467
 
      return 0;
468
 
    }
469
 
  }
470
 
  return 2;
471
 
}
472
 
 
473
 
 
474
 
static void *
475
 
_cdio_malloc_and_zero(size_t size) {
476
 
  void *ptr;
477
 
 
478
 
  if( !size ) size++;
479
 
    
480
 
  if((ptr = malloc(size)) == NULL) {
481
 
    cdio_warn("malloc() failed: %s", strerror(errno));
482
 
    return NULL;
483
 
  }
484
 
 
485
 
  memset(ptr, 0, size);
486
 
  return ptr;
487
 
}
488
 
 
489
 
/*!
490
 
  Return the value associated with the key "arg".
491
 
*/
492
 
static const char *
493
 
get_arg_solaris (void *p_user_data, const char key[])
494
 
{
495
 
  _img_private_t *env = p_user_data;
496
 
 
497
 
  if (!strcmp (key, "source")) {
498
 
    return env->gen.source_name;
499
 
  } else if (!strcmp (key, "access-mode")) {
500
 
    switch (env->access_mode) {
501
 
    case _AM_SUN_CTRL_ATAPI:
502
 
      return "ATAPI";
503
 
    case _AM_SUN_CTRL_SCSI:
504
 
      return "SCSI";
505
 
    case _AM_NONE:
506
 
      return "no access method";
507
 
    }
508
 
  } 
509
 
  return NULL;
510
 
}
511
 
 
512
 
/*!
513
 
  Return a string containing the default CD device if none is specified.
514
 
 */
515
 
char *
516
 
cdio_get_default_device_solaris(void)
517
 
{
518
 
  char *volume_device;
519
 
  char *volume_name;
520
 
  char *volume_action;
521
 
  char *device;
522
 
  struct stat stb;
523
 
 
524
 
  if ((volume_device = getenv("VOLUME_DEVICE")) != NULL &&
525
 
      (volume_name   = getenv("VOLUME_NAME"))   != NULL &&
526
 
      (volume_action = getenv("VOLUME_ACTION")) != NULL &&
527
 
      strcmp(volume_action, "insert") == 0) {
528
 
 
529
 
    device = _cdio_malloc_and_zero(strlen(volume_device) 
530
 
                                  + strlen(volume_name) + 2);
531
 
    if (device == NULL)
532
 
      return strdup(DEFAULT_CDIO_DEVICE);
533
 
    sprintf(device, "%s/%s", volume_device, volume_name);
534
 
    if (stat(device, &stb) != 0 || !S_ISCHR(stb.st_mode)) {
535
 
      free(device);
536
 
      return strdup(DEFAULT_CDIO_DEVICE);
537
 
    }
538
 
    return device;
539
 
  }
540
 
  /* Check if it could be a Solaris media*/
541
 
  if((stat(DEFAULT_CDIO_DEVICE, &stb) == 0) && S_ISDIR(stb.st_mode)) {
542
 
    device = _cdio_malloc_and_zero(strlen(DEFAULT_CDIO_DEVICE) + 4);
543
 
    sprintf(device, "%s/s0", DEFAULT_CDIO_DEVICE);
544
 
    return device;
545
 
  }
546
 
  return strdup(DEFAULT_CDIO_DEVICE);
547
 
}
548
 
 
549
 
/*! 
550
 
  Get disc type associated with cd object.
551
 
*/
552
 
 
553
 
static discmode_t
554
 
get_discmode_solaris (void *p_user_data)
555
 
{
556
 
  _img_private_t *p_env = p_user_data;
557
 
  track_t i_track;
558
 
  discmode_t discmode=CDIO_DISC_MODE_NO_INFO;
559
 
  struct dk_minfo media;
560
 
  int ret;
561
 
 
562
 
  /* Get the media info */
563
 
  if((ret = ioctl(p_env->gen.fd, DKIOCGMEDIAINFO, &media)) != 0) {
564
 
     cdio_warn ("DKIOCGMEDIAINFO failed: %s\n", strerror(errno));
565
 
         return CDIO_DISC_MODE_NO_INFO;
566
 
  }
567
 
  switch(media.dki_media_type) {
568
 
  case DK_CDROM:
569
 
  case DK_CDR:
570
 
  case DK_CDRW:
571
 
  /* Do cdrom detection */
572
 
  break;
573
 
  case DK_DVDROM:       return CDIO_DISC_MODE_DVD_ROM;
574
 
  case DK_DVDR:         discmode = CDIO_DISC_MODE_DVD_R;
575
 
  break;
576
 
  case DK_DVDRAM:       discmode = CDIO_DISC_MODE_DVD_RAM;
577
 
  break;
578
 
  case DK_DVDRW:
579
 
  case DK_DVDRW+1:      discmode = CDIO_DISC_MODE_DVD_RW;
580
 
  break;
581
 
  default: /* no valid match */
582
 
  return CDIO_DISC_MODE_NO_INFO; 
583
 
  }
584
 
 
585
 
  if((discmode == CDIO_DISC_MODE_DVD_RAM || 
586
 
      discmode == CDIO_DISC_MODE_DVD_RW ||
587
 
      discmode == CDIO_DISC_MODE_DVD_R)) {
588
 
    /* Fallback to uscsi if we can */
589
 
    if(geteuid() == 0)
590
 
      return get_discmode_solaris(p_user_data);
591
 
    return discmode;
592
 
  }
593
 
 
594
 
  if (!p_env->gen.toc_init) 
595
 
    read_toc_solaris (p_env);
596
 
 
597
 
  if (!p_env->gen.toc_init) 
598
 
    return CDIO_DISC_MODE_NO_INFO;
599
 
 
600
 
  for (i_track = p_env->gen.i_first_track; 
601
 
       i_track < p_env->gen.i_first_track + p_env->tochdr.cdth_trk1 ; 
602
 
       i_track ++) {
603
 
    track_format_t track_fmt=get_track_format_solaris(p_env, i_track);
604
 
 
605
 
    switch(track_fmt) {
606
 
    case TRACK_FORMAT_AUDIO:
607
 
      switch(discmode) {
608
 
        case CDIO_DISC_MODE_NO_INFO:
609
 
          discmode = CDIO_DISC_MODE_CD_DA;
610
 
          break;
611
 
        case CDIO_DISC_MODE_CD_DA:
612
 
        case CDIO_DISC_MODE_CD_MIXED: 
613
 
        case CDIO_DISC_MODE_ERROR: 
614
 
          /* No change*/
615
 
          break;
616
 
      default:
617
 
          discmode = CDIO_DISC_MODE_CD_MIXED;
618
 
      }
619
 
      break;
620
 
    case TRACK_FORMAT_XA:
621
 
      switch(discmode) {
622
 
        case CDIO_DISC_MODE_NO_INFO:
623
 
          discmode = CDIO_DISC_MODE_CD_XA;
624
 
          break;
625
 
        case CDIO_DISC_MODE_CD_XA:
626
 
        case CDIO_DISC_MODE_CD_MIXED: 
627
 
        case CDIO_DISC_MODE_ERROR: 
628
 
          /* No change*/
629
 
          break;
630
 
      default:
631
 
        discmode = CDIO_DISC_MODE_CD_MIXED;
632
 
      }
633
 
      break;
634
 
    case TRACK_FORMAT_DATA:
635
 
      switch(discmode) {
636
 
        case CDIO_DISC_MODE_NO_INFO:
637
 
          discmode = CDIO_DISC_MODE_CD_DATA;
638
 
          break;
639
 
        case CDIO_DISC_MODE_CD_DATA:
640
 
        case CDIO_DISC_MODE_CD_MIXED: 
641
 
        case CDIO_DISC_MODE_ERROR: 
642
 
          /* No change*/
643
 
          break;
644
 
      default:
645
 
        discmode = CDIO_DISC_MODE_CD_MIXED;
646
 
      }
647
 
      break;
648
 
    case TRACK_FORMAT_ERROR:
649
 
    default:
650
 
      discmode = CDIO_DISC_MODE_ERROR;
651
 
    }
652
 
  }
653
 
  return discmode;
654
 
}
655
 
 
656
 
/*!  
657
 
  Get format of track. 
658
 
*/
659
 
static track_format_t
660
 
get_track_format_solaris(void *p_user_data, track_t i_track) 
661
 
{
662
 
  _img_private_t *p_env = p_user_data;
663
 
  
664
 
  if ( !p_env ) return TRACK_FORMAT_ERROR;
665
 
  if (!p_env->gen.init) init_solaris(p_env);
666
 
  if (!p_env->gen.toc_init) read_toc_solaris (p_user_data) ;
667
 
 
668
 
  if ( (i_track > p_env->gen.i_tracks+p_env->gen.i_first_track) 
669
 
       || i_track < p_env->gen.i_first_track)
670
 
    return TRACK_FORMAT_ERROR;
671
 
 
672
 
  i_track -= p_env->gen.i_first_track;
673
 
 
674
 
  /* This is pretty much copied from the "badly broken" cdrom_count_tracks
675
 
     in linux/cdrom.c.
676
 
   */
677
 
  if (p_env->tocent[i_track].cdte_ctrl & CDROM_DATA_TRACK) {
678
 
    if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK)
679
 
      return TRACK_FORMAT_CDI;
680
 
    else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK) 
681
 
      return TRACK_FORMAT_XA;
682
 
    else
683
 
      return TRACK_FORMAT_DATA;
684
 
  } else
685
 
    return TRACK_FORMAT_AUDIO;
686
 
  
687
 
}
688
 
 
689
 
/*!
690
 
  Return true if we have XA data (green, mode2 form1) or
691
 
  XA data (green, mode2 form2). That is track begins:
692
 
  sync - header - subheader
693
 
  12     4      -  8
694
 
 
695
 
  FIXME: there's gotta be a better design for this and get_track_format?
696
 
*/
697
 
static bool
698
 
_cdio_get_track_green(void *p_user_data, track_t i_track) 
699
 
{
700
 
  _img_private_t *p_env = p_user_data;
701
 
  
702
 
  if ( !p_env ) return false;
703
 
  if (!p_env->gen.init) init_solaris(p_env);
704
 
  if (!p_env->gen.toc_init) read_toc_solaris (p_env) ;
705
 
 
706
 
  if (i_track >= p_env->gen.i_tracks+p_env->gen.i_first_track 
707
 
      || i_track < p_env->gen.i_first_track)
708
 
    return false;
709
 
 
710
 
  i_track -= p_env->gen.i_first_track;
711
 
 
712
 
  /* FIXME: Dunno if this is the right way, but it's what 
713
 
     I was using in cd-info for a while.
714
 
   */
715
 
  return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0);
716
 
}
717
 
 
718
 
/*!  
719
 
  Return the starting MSF (minutes/secs/frames) for track number
720
 
  track_num in obj.  Track numbers usually start at something 
721
 
  greater than 0, usually 1.
722
 
 
723
 
  The "leadout" track is specified either by
724
 
  using track_num LEADOUT_TRACK or the total tracks+1.
725
 
  False is returned if there is no entry.
726
 
*/
727
 
static bool
728
 
_cdio_get_track_msf(void *p_user_data, track_t i_track, msf_t *msf)
729
 
{
730
 
  _img_private_t *p_env = p_user_data;
731
 
 
732
 
  if (NULL == msf) return false;
733
 
 
734
 
  if (!p_env->gen.init) init_solaris(p_env);
735
 
  if (!p_env->gen.toc_init) read_toc_solaris (p_env) ;
736
 
 
737
 
  if (i_track == CDIO_CDROM_LEADOUT_TRACK) 
738
 
    i_track = p_env->gen.i_tracks + p_env->gen.i_first_track;
739
 
 
740
 
  if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track) 
741
 
      || i_track < p_env->gen.i_first_track) {
742
 
    return false;
743
 
  } else {
744
 
    struct cdrom_tocentry *msf0 = &p_env->tocent[i_track-1];
745
 
    msf->m = cdio_to_bcd8(msf0->cdte_addr.msf.minute);
746
 
    msf->s = cdio_to_bcd8(msf0->cdte_addr.msf.second);
747
 
    msf->f = cdio_to_bcd8(msf0->cdte_addr.msf.frame);
748
 
    return true;
749
 
  }
750
 
}
751
 
 
752
 
#else 
753
 
/*!
754
 
  Return a string containing the default VCD device if none is specified.
755
 
 */
756
 
char *
757
 
cdio_get_default_device_solaris(void)
758
 
{
759
 
  return strdup(DEFAULT_CDIO_DEVICE);
760
 
}
761
 
 
762
 
#endif /* HAVE_SOLARIS_CDROM */
763
 
 
764
 
/*!
765
 
  Return an array of strings giving possible CD devices.
766
 
 */
767
 
char **
768
 
cdio_get_devices_solaris (void)
769
 
{
770
 
#ifndef HAVE_SOLARIS_CDROM
771
 
  return NULL;
772
 
#else
773
 
  char volpath[256];
774
 
  struct stat st;
775
 
  char **drives = NULL;
776
 
  unsigned int i_files=0;
777
 
#ifdef HAVE_GLOB_H
778
 
  unsigned int i;
779
 
  glob_t globbuf;
780
 
 
781
 
  globbuf.gl_offs = 0;
782
 
  glob("/vol/dev/aliases/cdrom*", GLOB_DOOFFS, NULL, &globbuf);
783
 
  for (i=0; i<globbuf.gl_pathc; i++) {
784
 
    if(stat(globbuf.gl_pathv[i], &st) < 0)
785
 
      continue;
786
 
 
787
 
    /* Check if this is a directory, if so it's probably Solaris media */
788
 
    if(S_ISDIR(st.st_mode)) {
789
 
      sprintf(volpath, "%s/s0", globbuf.gl_pathv[i]);
790
 
      if(stat(volpath, &st) == 0)
791
 
        cdio_add_device_list(&drives, volpath, &i_files);
792
 
        }else
793
 
      cdio_add_device_list(&drives, globbuf.gl_pathv[i], &i_files);
794
 
  }
795
 
  globfree(&globbuf);
796
 
#else
797
 
  if(stat(DEFAULT_CDIO_DEVICE, &st) == 0) {
798
 
    /* Check if this is a directory, if so it's probably Solaris media */
799
 
    if(S_ISDIR(st.st_mode)) {
800
 
      sprintf(volpath, "%s/s0", DEFAULT_CDIO_DEVICE);
801
 
      if(stat(volpath, &st) == 0)
802
 
        cdio_add_device_list(&drives, volpath, &i_files);
803
 
    }else
804
 
      cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &i_files);
805
 
  }
806
 
#endif /*HAVE_GLOB_H*/
807
 
  cdio_add_device_list(&drives, NULL, &i_files);
808
 
  return drives;
809
 
#endif /*HAVE_SOLARIS_CDROM*/
810
 
}
811
 
 
812
 
/*!
813
 
  Initialization routine. This is the only thing that doesn't
814
 
  get called via a function pointer. In fact *we* are the
815
 
  ones to set that up.
816
 
 */
817
 
CdIo *
818
 
cdio_open_solaris (const char *psz_source_name)
819
 
{
820
 
  return cdio_open_am_solaris(psz_source_name, NULL);
821
 
}
822
 
 
823
 
/*!
824
 
  Initialization routine. This is the only thing that doesn't
825
 
  get called via a function pointer. In fact *we* are the
826
 
  ones to set that up.
827
 
 */
828
 
CdIo *
829
 
cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode)
830
 
{
831
 
 
832
 
#ifdef HAVE_SOLARIS_CDROM
833
 
  CdIo *ret;
834
 
  _img_private_t *_data;
835
 
  char *psz_source;
836
 
 
837
 
  cdio_funcs _funcs;
838
 
 
839
 
  _funcs.eject_media        = eject_media_solaris;
840
 
  _funcs.free               = cdio_generic_free;
841
 
  _funcs.get_arg            = get_arg_solaris;
842
 
  _funcs.get_cdtext         = get_cdtext_generic;
843
 
  _funcs.get_default_device = cdio_get_default_device_solaris;
844
 
  _funcs.get_devices        = cdio_get_devices_solaris;
845
 
  _funcs.get_discmode       = get_discmode_solaris;
846
 
  _funcs.get_drive_cap      = scsi_mmc_get_drive_cap_generic;
847
 
  _funcs.get_first_track_num= get_first_track_num_generic;
848
 
  _funcs.get_hwinfo         = NULL;
849
 
  _funcs.get_mcn            = scsi_mmc_get_mcn_generic,
850
 
  _funcs.get_num_tracks     = get_num_tracks_generic;
851
 
  _funcs.get_track_format   = get_track_format_solaris;
852
 
  _funcs.get_track_green    = _cdio_get_track_green;
853
 
  _funcs.get_track_lba      = NULL; /* This could be implemented if need be. */
854
 
  _funcs.get_track_msf      = _cdio_get_track_msf;
855
 
  _funcs.lseek              = cdio_generic_lseek;
856
 
  _funcs.read               = cdio_generic_read;
857
 
  _funcs.read_audio_sectors = _read_audio_sectors_solaris;
858
 
  _funcs.read_mode1_sector  = _read_mode1_sector_solaris;
859
 
  _funcs.read_mode1_sectors = _read_mode1_sectors_solaris;
860
 
  _funcs.read_mode2_sector  = _read_mode2_sector_solaris;
861
 
  _funcs.read_mode2_sectors = _read_mode2_sectors_solaris;
862
 
  _funcs.read_toc           = read_toc_solaris;
863
 
  _funcs.run_scsi_mmc_cmd   = run_scsi_cmd_solaris;
864
 
  _funcs.stat_size          = _cdio_stat_size;
865
 
  _funcs.set_arg            = _set_arg_solaris;
866
 
 
867
 
  _data                 = _cdio_malloc (sizeof (_img_private_t));
868
 
 
869
 
  _data->access_mode    = _AM_SUN_CTRL_SCSI;
870
 
  _data->gen.init       = false;
871
 
  _data->gen.fd         = -1;
872
 
  _data->gen.toc_init   = false;
873
 
  _data->gen.b_cdtext_init  = false;
874
 
  _data->gen.b_cdtext_error = false;
875
 
 
876
 
  if (NULL == psz_orig_source) {
877
 
    psz_source = cdio_get_default_device_solaris();
878
 
    if (NULL == psz_source) return NULL;
879
 
    _set_arg_solaris(_data, "source", psz_source);
880
 
    free(psz_source);
881
 
  } else {
882
 
    if (cdio_is_device_generic(psz_orig_source))
883
 
      _set_arg_solaris(_data, "source", psz_orig_source);
884
 
    else {
885
 
      /* The below would be okay if all device drivers worked this way. */
886
 
#if 0
887
 
      cdio_info ("source %s is not a device", psz_orig_source);
888
 
#endif
889
 
      return NULL;
890
 
    }
891
 
  }
892
 
 
893
 
  ret = cdio_new ( (void *) _data, &_funcs );
894
 
  if (ret == NULL) return NULL;
895
 
 
896
 
  if (init_solaris(_data))
897
 
    return ret;
898
 
  else {
899
 
    cdio_generic_free (_data);
900
 
    return NULL;
901
 
  }
902
 
 
903
 
#else 
904
 
  return NULL;
905
 
#endif /* HAVE_SOLARIS_CDROM */
906
 
 
907
 
}
908
 
 
909
 
bool
910
 
cdio_have_solaris (void)
911
 
{
912
 
#ifdef HAVE_SOLARIS_CDROM
913
 
  return true;
914
 
#else 
915
 
  return false;
916
 
#endif /* HAVE_SOLARIS_CDROM */
917
 
}