⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freebsd_cam.c

📁 linux下的MPEG1
💻 C
字号:
/*    $Id: freebsd_cam.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $    Copyright (C) 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 via SCSI emulation.*/#ifdef HAVE_CONFIG_H# include "config.h"#endifstatic const char _rcsid[] = "$Id: freebsd_cam.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $";#ifdef HAVE_FREEBSD_CDROM#include "freebsd.h"#include <cdio/scsi_mmc.h>/* Default value in seconds we will wait for a command to    complete. */#define DEFAULT_TIMEOUT_MSECS 10000/*!  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. */intrun_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 ){  const _img_private_t *p_env = p_user_data;  int   i_status;  int direction = CAM_DEV_QFRZDIS;  union ccb ccb;  if (!p_env || !p_env->cam) return -2;      memset(&ccb, 0, sizeof(ccb));  ccb.ccb_h.path_id    = p_env->cam->path_id;  ccb.ccb_h.target_id  = p_env->cam->target_id;  ccb.ccb_h.target_lun = p_env->cam->target_lun;  ccb.ccb_h.timeout    = i_timeout_ms;   if (!i_cdb)      direction |= CAM_DIR_NONE;   else      direction |= (e_direction == SCSI_MMC_DATA_READ)?CAM_DIR_IN : CAM_DIR_OUT;  cam_fill_csio (&(ccb.csio), 1, NULL, 		 direction | CAM_DEV_QFRZDIS, MSG_SIMPLE_Q_TAG, p_buf, i_buf, 		 sizeof(ccb.csio.sense_data), 0, 30*1000);  memcpy(ccb.csio.cdb_io.cdb_bytes, p_cdb, i_cdb);    ccb.csio.cdb_len =     scsi_mmc_get_cmd_len(ccb.csio.cdb_io.cdb_bytes[0]);    if ((i_status = cam_send_ccb(p_env->cam, &ccb)) < 0)    {      cdio_warn ("transport failed: %d", i_status);      return -1;    }  if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)    {      return 0;    }  errno = EIO;  i_status = ERRCODE(((unsigned char *)&ccb.csio.sense_data));  if (i_status == 0)    i_status = -1;  else    CREAM_ON_ERRNO(((unsigned char *)&ccb.csio.sense_data));  cdio_warn ("transport failed: %d", i_status);  return i_status;}boolinit_freebsd_cam (_img_private_t *p_env){  char pass[100];    p_env->cam=NULL;  memset (&p_env->ccb, 0, sizeof(p_env->ccb));  p_env->ccb.ccb_h.func_code = XPT_GDEVLIST;  if (-1 == p_env->gen.fd)     p_env->gen.fd = open (p_env->device, O_RDONLY, 0);  if (p_env->gen.fd < 0)    {      cdio_warn ("open (%s): %s", p_env->device, strerror (errno));      return false;    }  if (ioctl (p_env->gen.fd, CAMGETPASSTHRU, &p_env->ccb) < 0)    {      cdio_warn ("open: %s", strerror (errno));      return false;    }  sprintf (pass,"/dev/%.15s%u",	   p_env->ccb.cgdl.periph_name,	   p_env->ccb.cgdl.unit_number);  p_env->cam = cam_open_pass (pass,O_RDWR,NULL);  if (!p_env->cam) return false;    p_env->gen.init   = true;  p_env->b_cam_init = true;  return true;}voidfree_freebsd_cam (void *user_data){  _img_private_t *p_env = user_data;  if (NULL == p_env) return;  if (p_env->gen.fd > 0)    close (p_env->gen.fd);  p_env->gen.fd = -1;  if(p_env->cam)    cam_close_device(p_env->cam);  free (p_env);}static int _set_bsize (_img_private_t *p_env, unsigned int bsize){  scsi_mmc_cdb_t cdb = {{0, }};  struct  {    uint8_t reserved1;    uint8_t medium;    uint8_t reserved2;    uint8_t block_desc_length;    uint8_t density;    uint8_t number_of_blocks_hi;    uint8_t number_of_blocks_med;    uint8_t number_of_blocks_lo;    uint8_t reserved3;    uint8_t block_length_hi;    uint8_t block_length_med;    uint8_t block_length_lo;  } mh;  memset (&mh, 0, sizeof (mh));  mh.block_desc_length = 0x08;  mh.block_length_hi   = (bsize >> 16) & 0xff;  mh.block_length_med  = (bsize >>  8) & 0xff;  mh.block_length_lo   = (bsize >>  0) & 0xff;  memset (&cdb, 0, sizeof (cdb));    CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_6);  cdb.field[1] = 1 << 4;  cdb.field[4] = 12;    return run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS,				   scsi_mmc_get_cmd_len(cdb.field[0]), 				   &cdb, SCSI_MMC_DATA_WRITE, 				   sizeof(mh), &mh);}intread_mode2_sector_freebsd_cam (_img_private_t *p_env, void *data, lsn_t lsn, 			       bool b_form2){  if ( b_form2 )    return read_mode2_sectors_freebsd_cam(p_env, data, lsn, 1);  else {    /* Need to pick out the data portion from a mode2 form2 frame */    char buf[M2RAW_SECTOR_SIZE] = { 0, };    int retval = read_mode2_sectors_freebsd_cam(p_env, buf, lsn, 1);    if ( retval ) return retval;    memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);    return 0;  }}/*!   Reads nblocks of mode2 sectors from cd device into data starting   from lsn.   Returns 0 if no error.  */intread_mode2_sectors_freebsd_cam (_img_private_t *p_env, void *p_buf, 				lsn_t lsn, unsigned int nblocks){  scsi_mmc_cdb_t cdb = {{0, }};  bool b_read_10 = false;  CDIO_MMC_SET_READ_LBA(cdb.field, lsn);    if (b_read_10) {    int retval;        CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_10);    CDIO_MMC_SET_READ_LENGTH16(cdb.field, nblocks);    if ((retval = _set_bsize (p_env, M2RAW_SECTOR_SIZE)))      return retval;        if ((retval = run_scsi_cmd_freebsd_cam (p_env, 0, 						scsi_mmc_get_cmd_len(cdb.field[0]), 						&cdb, 						SCSI_MMC_DATA_READ,						M2RAW_SECTOR_SIZE * nblocks, 						p_buf)))      {	_set_bsize (p_env, CDIO_CD_FRAMESIZE);	return retval;      }        if ((retval = _set_bsize (p_env, CDIO_CD_FRAMESIZE)))      return retval;  } else    CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD);    CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks);    cdb.field[1] = 0; /* sector size mode2 */    cdb.field[9] = 0x58; /* 2336 mode2 */    return run_scsi_cmd_freebsd_cam (p_env, 0, 					 scsi_mmc_get_cmd_len(cdb.field[0]), 					 &cdb, 					 SCSI_MMC_DATA_READ,					 M2RAW_SECTOR_SIZE * nblocks, p_buf);  return 0;}/*!   Return the size of the CD in logical block address (LBA) units. */uint32_tstat_size_freebsd_cam (_img_private_t *p_env){  scsi_mmc_cdb_t cdb = {{0, }};  uint8_t buf[12] = { 0, };  uint32_t retval;  int i_status;  /* Operation code */  CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);  cdb.field[1] = 0; /* lba; msf: 0x2 */  /* Format */  cdb.field[2] = CDIO_MMC_READTOC_FMT_TOC;  CDIO_MMC_SET_START_TRACK(cdb.field, CDIO_CDROM_LEADOUT_TRACK);  CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf));    p_env->ccb.csio.data_ptr = buf;  p_env->ccb.csio.dxfer_len = sizeof (buf);  i_status = run_scsi_cmd_freebsd_cam(p_env, DEFAULT_TIMEOUT_MSECS,					  scsi_mmc_get_cmd_len(cdb.field[0]), 					  &cdb, SCSI_MMC_DATA_READ, 					  sizeof(buf), buf);  if (0 != i_status)    return 0;  {    int i;    retval = 0;    for (i = 8; i < 12; i++)      {        retval <<= 8;        retval += buf[i];      }  }  return retval;}/*! * Eject using SCSI MMC commands. Return 0 if successful. */inteject_media_freebsd_cam (_img_private_t *p_env) {  int i_status;  scsi_mmc_cdb_t cdb = {{0, }};  uint8_t buf[1];    CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL);  i_status = run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS,					   scsi_mmc_get_cmd_len(cdb.field[0]), 					   &cdb, SCSI_MMC_DATA_WRITE, 0, &buf);  if (0 != i_status)    return i_status;    cdb.field[4] = 1;  i_status = run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS,				 scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, 				 SCSI_MMC_DATA_WRITE, 0, &buf);  if (0 != i_status)    return i_status;    CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP);  cdb.field[4] = 2; /* eject */  return run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS,				       scsi_mmc_get_cmd_len(cdb.field[0]), 				       &cdb, 				       SCSI_MMC_DATA_WRITE, 0, &buf);}#endif /* HAVE_FREEBSD_CDROM */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -