📄 freebsd.c
字号:
/* $Id: freebsd.c,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"#endifstatic const char _rcsid[] = "$Id: freebsd.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $";#include "freebsd.h"#ifdef HAVE_FREEBSD_CDROM#include <cdio/sector.h>static access_mode_t str_to_access_mode_freebsd(const char *psz_access_mode) { const access_mode_t default_access_mode = DEFAULT_FREEBSD_AM; if (NULL==psz_access_mode) return default_access_mode; if (!strcmp(psz_access_mode, "ioctl")) return _AM_IOCTL; else if (!strcmp(psz_access_mode, "CAM")) return _AM_CAM; else { cdio_warn ("unknown access type: %s. Default ioctl used.", psz_access_mode); return default_access_mode; }}static void_free_freebsd (void *obj){ _img_private_t *env = obj; if (NULL == env) return; if (NULL != env->device) free(env->device); if (_AM_CAM == env->access_mode) return free_freebsd_cam(env); else return cdio_generic_free(obj);}/* Check a drive to see if it is a CD-ROM Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive and -1 if no device exists .*/static boolcdio_is_cdrom(char *drive, char *mnttype){ return cdio_is_cdrom_freebsd_ioctl(drive, mnttype);}/*! Reads nblocks of audio sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_read_audio_sectors_freebsd (void *user_data, void *data, lsn_t lsn, unsigned int nblocks){ return read_audio_sectors_freebsd_ioctl(user_data, data, lsn, nblocks);}/*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode2_sector_freebsd (void *user_data, void *data, lsn_t lsn, bool b_form2){ _img_private_t *env = user_data; if ( env->access_mode == _AM_CAM ) return read_mode2_sector_freebsd_cam(env, data, lsn, b_form2); else return read_mode2_sector_freebsd_ioctl(env, data, lsn, b_form2);}/*! Reads nblocks of mode2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode2_sectors_freebsd (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks){ _img_private_t *env = user_data; if ( env->access_mode == _AM_CAM && b_form2) { /* We have a routine that covers this case without looping. */ return read_mode2_sectors_freebsd_cam(env, data, lsn, nblocks); } else { unsigned int i; unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; /* For each frame, pick out the data part we need */ for (i = 0; i < nblocks; i++) { int retval = _read_mode2_sector_freebsd (env, ((char *)data) + (i_blocksize * i), lsn + i, b_form2); if (retval) return retval; } } return 0;}/*! Return the size of the CD in logical block address (LBA) units. */static uint32_t _stat_size_freebsd (void *obj){ _img_private_t *env = obj; if (NULL == env) return CDIO_INVALID_LBA; if (_AM_CAM == env->access_mode) return stat_size_freebsd_cam(env); else return stat_size_freebsd_ioctl(env);}/*! Set the key "arg" to "value" in source device.*/static int_set_arg_freebsd (void *user_data, const char key[], const char value[]){ _img_private_t *env = user_data; if (!strcmp (key, "source")) { if (!value) return -2; free (env->gen.source_name); env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { env->access_mode = str_to_access_mode_freebsd(value); if (env->access_mode == _AM_CAM && !env->b_cam_init) return init_freebsd_cam(env) ? 1 : -3; return 0; } else return -1; return 0;}/*! Read and cache the CD's Track Table of Contents and track info. Return false if unsuccessful;*/static boolread_toc_freebsd (void *p_user_data) { _img_private_t *p_env = p_user_data; track_t i, j; /* read TOC header */ if ( ioctl(p_env->gen.fd, CDIOREADTOCHEADER, &p_env->tochdr) == -1 ) { cdio_warn("error in ioctl(CDIOREADTOCHEADER): %s\n", strerror(errno)); return false; } p_env->gen.i_first_track = p_env->tochdr.starting_track; p_env->gen.i_tracks = p_env->tochdr.ending_track - p_env->gen.i_first_track + 1; j=0; for (i=p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++, j++) { p_env->tocent[j].track = i; p_env->tocent[j].address_format = CD_LBA_FORMAT; if ( ioctl(p_env->gen.fd, CDIOREADTOCENTRY, &(p_env->tocent[j]) ) ) { cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; } } p_env->tocent[j].track = CDIO_CDROM_LEADOUT_TRACK; p_env->tocent[j].address_format = CD_LBA_FORMAT; if ( ioctl(p_env->gen.fd, CDIOREADTOCENTRY, &(p_env->tocent[j]) ) ){ cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for leadout track", strerror(errno)); return false; } p_env->gen.toc_init = true; return true;}/*! Eject media. Return 1 if successful, 0 otherwise. */static int _eject_media_freebsd (void *user_data) { _img_private_t *p_env = user_data; return (p_env->access_mode == _AM_IOCTL) ? eject_media_freebsd_ioctl(p_env) : eject_media_freebsd_cam(p_env);}/*! Return the value associated with the key "arg".*/static const char *_get_arg_freebsd (void *user_data, const char key[]){ _img_private_t *env = user_data; if (!strcmp (key, "source")) { return env->gen.source_name; } else if (!strcmp (key, "access-mode")) { switch (env->access_mode) { case _AM_IOCTL: return "ioctl"; case _AM_CAM: return "CAM"; case _AM_NONE: return "no access method"; } } return NULL;}/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. FIXME: This is just a guess. */static char *_get_mcn_freebsd (const void *p_user_data) { const _img_private_t *p_env = p_user_data; return (p_env->access_mode == _AM_IOCTL) ? get_mcn_freebsd_ioctl(p_env) : scsi_mmc_get_mcn(p_env->gen.cdio);}static voidget_drive_cap_freebsd (const void *p_user_data, cdio_drive_read_cap_t *p_read_cap, cdio_drive_write_cap_t *p_write_cap, cdio_drive_misc_cap_t *p_misc_cap) { const _img_private_t *p_env = p_user_data; if (p_env->access_mode == _AM_CAM) scsi_mmc_get_drive_cap_generic (p_user_data, p_read_cap, p_write_cap, p_misc_cap); } /*! Run a SCSI MMC command. p_user_data internal CD structure. i_timeout_ms 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. */static intrun_scsi_cmd_freebsd( 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 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -