ScsiIf-freebsd-cam.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:6k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998, 1999  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: ScsiIf-freebsd-cam.cc,v $
  21.  * Revision 1.4  1999/09/02 19:45:12  mueller
  22.  * Added dummy implementation for 'scan()'.
  23.  *
  24.  * Revision 1.3  1999/04/25 10:02:11  mueller
  25.  * Set maximum transfer length to 32k.
  26.  *
  27.  * Revision 1.2  1999/04/02 16:44:30  mueller
  28.  * Removed 'revisionDate' because it is not available in general.
  29.  *
  30.  * Revision 1.1  1999/03/14 15:33:38  mueller
  31.  * Initial revision
  32.  *
  33.  */
  34. /* SCSI interface implemenation for FreeBSD.
  35.  * Written by Max Khon <fjoe@iclub.nsu.ru>
  36.  */
  37. static char rcsid[] = "$Id: ScsiIf-freebsd-cam.cc,v 1.4 1999/09/02 19:45:12 mueller Exp mueller $";
  38. #include <config.h>
  39. #include <fcntl.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <camlib.h>
  43. #include <cam/scsi/scsi_message.h>
  44. #include "ScsiIf.h"
  45. #include "util.h"
  46. #define DEF_RETRY_COUNT 1
  47. #include "decodeSense.cc"
  48. class ScsiIfImpl {
  49. public:
  50. char * devname;
  51. struct cam_device * dev;
  52. union ccb * ccb;
  53. int timeout; /* timeout in ms */
  54. };
  55. ScsiIf::ScsiIf(const char *devname)
  56. {
  57. impl_ = new ScsiIfImpl;
  58. impl_->devname = strdupCC(devname);
  59. impl_->dev = NULL;
  60. impl_->ccb = NULL;
  61. impl_->timeout = 5000;
  62. maxDataLen_ = 32 * 1024;
  63. vendor_[0] = 0;
  64. product_[0] = 0;
  65. revision_[0] = 0;
  66. }
  67. ScsiIf::~ScsiIf()
  68. {
  69. if (impl_->ccb)
  70. cam_freeccb(impl_->ccb);
  71. if (impl_->dev) 
  72. cam_close_device(impl_->dev);
  73. delete[] impl_->devname;
  74. delete impl_;
  75. }
  76. // opens scsi device
  77. // return: 0: OK
  78. //         1: device could not be opened
  79. //         2: inquiry failed
  80. int ScsiIf::init()
  81. {
  82. if ((impl_->dev = cam_open_device(impl_->devname, O_RDWR)) == NULL) {
  83. message(-2, "%s", cam_errbuf);
  84. return 1;
  85. }
  86.   
  87. impl_->ccb = cam_getccb(impl_->dev);
  88. if (impl_->ccb == NULL) {
  89. message(-2, "init: error allocating ccb");
  90. return 1;
  91. }
  92. if (inquiry()) 
  93. return 2;
  94. return 0;
  95. }
  96. // Sets given timeout value in seconds and returns old timeout.
  97. // return: old timeout
  98. int ScsiIf::timeout(int t)
  99. {
  100. int old = impl_->timeout;
  101. impl_->timeout = t*1000;
  102. return old/1000;
  103. }
  104. // sends a scsi command and receives data
  105. // return 0: OK
  106. //        1: scsi command failed (os level, no sense data available)
  107. //        2: scsi command failed (sense data available)
  108. int ScsiIf::sendCmd(const unsigned char *cmd, int cmdLen, 
  109.     const unsigned char *dataOut, int dataOutLen,
  110.     unsigned char *dataIn, int dataInLen,
  111.     int showMessage)
  112. {
  113. int retval;
  114. int flags = CAM_DIR_NONE;
  115. u_int8_t * data_ptr;
  116. size_t data_len;
  117. bzero(impl_->ccb, sizeof(union ccb));
  118. bcopy(cmd, &impl_->ccb->csio.cdb_io.cdb_bytes, cmdLen);
  119. if (dataOut && dataOutLen > 0) {
  120. data_ptr = (u_int8_t*) dataOut;
  121. data_len = dataOutLen;
  122. flags = CAM_DIR_OUT;
  123. }
  124. else if (dataIn && dataInLen > 0) {
  125. data_ptr = dataIn;
  126. data_len = dataInLen;
  127. flags = CAM_DIR_IN;
  128. }
  129. cam_fill_csio(&impl_->ccb->csio,
  130.       DEF_RETRY_COUNT,
  131.       NULL,
  132.       flags | CAM_DEV_QFRZDIS,
  133.       MSG_SIMPLE_Q_TAG,
  134.       data_ptr,
  135.       data_len,
  136.       SSD_FULL_SIZE,
  137.       cmdLen,
  138.       impl_->timeout);
  139. if ((retval = cam_send_ccb(impl_->dev, impl_->ccb)) < 0
  140. ||  (impl_->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  141. if (retval < 0) {
  142. message(-2, "sendCmd: error sending command");
  143. return 1;
  144. }
  145. if ((impl_->ccb->ccb_h.status & CAM_STATUS_MASK) ==
  146.     CAM_SCSI_STATUS_ERROR) {
  147.                         if (showMessage)
  148.         printError();
  149. return 2;
  150. }
  151. return 1;
  152. }
  153. return 0;
  154. }
  155. const unsigned char *ScsiIf::getSense(int &len) const
  156. {
  157. len = impl_->ccb->csio.sense_len;
  158. return (const unsigned char*) &impl_->ccb->csio.sense_data;
  159. }
  160. void ScsiIf::printError()
  161. {
  162.         decodeSense((const unsigned char*) &impl_->ccb->csio.sense_data,
  163.     impl_->ccb->csio.sense_len);
  164. }
  165. int ScsiIf::inquiry()
  166. {
  167. int i;
  168. struct scsi_inquiry_data inq_data;
  169. bzero(impl_->ccb, sizeof(union ccb));
  170. bzero(&inq_data, sizeof(inq_data));
  171. scsi_inquiry(&impl_->ccb->csio,
  172.      DEF_RETRY_COUNT,
  173.      NULL,
  174.      MSG_SIMPLE_Q_TAG,
  175.      (u_int8_t*) &inq_data,
  176.      sizeof(inq_data),
  177.      0,
  178.      0,
  179.      SSD_FULL_SIZE,
  180.      impl_->timeout);
  181. impl_->ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
  182. if (cam_send_ccb(impl_->dev, impl_->ccb) < 0) {
  183. if ((impl_->ccb->ccb_h.status & CAM_STATUS_MASK) !=
  184.     CAM_SCSI_STATUS_ERROR) {
  185. message(-2, "%s", cam_errbuf);
  186. return 1;
  187. }
  188. printError();
  189. return 1;
  190. }
  191. strncpy(vendor_, inq_data.vendor, 8);
  192. vendor_[8] = 0;
  193. strncpy(product_, inq_data.product, 16);
  194. product_[16] = 0;
  195. strncpy(revision_, inq_data.revision, 4);
  196. revision_[4] = 0;
  197. for (i = 7; i >= 0 && vendor_[i] == ' '; i--)
  198. vendor_[i] = 0;
  199. for (i = 15; i >= 0 && product_[i] == ' '; i--)
  200. product_[i] = 0;
  201. for (i = 3; i >= 0 && revision_[i] == ' '; i--)
  202. revision_[i] = 0;
  203. return 0;
  204. }
  205. ScsiIf::ScanData *ScsiIf::scan(int *len)
  206. {
  207.   *len = 0;
  208.   return NULL;
  209. }
  210. #include "ScsiIf-common.cc"