scsi-os2.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:17k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)scsi-os2.c 1.12 99/11/27 Copyright 1998 J. Schilling, C. Wohlgemuth */
  2. #ifndef lint
  3. static char __sccsid[] =
  4. "@(#)scsi-os2.c 1.12 99/11/27 Copyright 1998 J. Schilling, C. Wohlgemuth";
  5. #endif
  6. /*
  7.  * Interface for the OS/2 ASPI-Router ASPIROUT.SYS ((c) D. Dorau).
  8.  * This additional driver is a prerequisite for using cdrecord.
  9.  * Get it from HOBBES or LEO.
  10.  *
  11.  * Warning: you may change this source, but if you do that
  12.  * you need to change the _scg_version and _scg_auth* string below.
  13.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  14.  * Choose your name instead of "schily" and make clear that the version
  15.  * string is related to a modified source.
  16.  *
  17.  * XXX it currently uses static SRB and for this reason is not reentrant
  18.  *
  19.  * Copyright (c) 1998 J. Schilling
  20.  * Copyright (c) 1998 C. Wohlgemuth for this interface.
  21.  */
  22. /*
  23.  * This program is free software; you can redistribute it and/or modify
  24.  * it under the terms of the GNU General Public License as published by
  25.  * the Free Software Foundation; either version 2, or (at your option)
  26.  * any later version.
  27.  *
  28.  * This program is distributed in the hope that it will be useful,
  29.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.  * GNU General Public License for more details.
  32.  *
  33.  * You should have received a copy of the GNU General Public License
  34.  * along with this program; see the file COPYING.  If not, write to
  35.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  36.  */
  37. #undef sense
  38. /*#define DEBUG*/
  39. /* For AspiRouter */
  40. #include "scg/srb_os2.h"
  41. /*
  42.  * Warning: you may change this source, but if you do that
  43.  * you need to change the _scg_version and _scg_auth* string below.
  44.  * You may not return "schily" for an SCG_AUTHOR request anymore.
  45.  * Choose your name instead of "schily" and make clear that the version
  46.  * string is related to a modified source.
  47.  */
  48. LOCAL char _scg_trans_version[] = "scsi-os2.c-1.12"; /* The version for this transport*/
  49. #define FILE_OPEN 0x0001
  50. #define OPEN_SHARE_DENYREADWRITE 0x0010
  51. #define OPEN_ACCESS_READWRITE 0x0002
  52. #define DC_SEM_SHARED 0x01
  53. #define OBJ_TILE 0x0040
  54. #define PAG_READ 0x0001
  55. #define PAG_WRITE 0x0002
  56. #define PAG_COMMIT 0x0010
  57. typedef unsigned long LHANDLE;
  58. typedef unsigned long ULONG;
  59. typedef unsigned char *PSZ;
  60. typedef unsigned short USHORT;
  61. typedef unsigned char UCHAR;
  62. typedef LHANDLE HFILE;
  63. typedef ULONG HEV;
  64. #define MAX_SCG 16 /* Max # of SCSI controllers */
  65. #define MAX_TGT 16
  66. #define MAX_LUN 8
  67. struct scg_local {
  68. int dummy;
  69. };
  70. #define scglocal(p) ((struct scg_local *)((p)->local)) 
  71. #define MAX_DMA_OS2 (63*1024) /* ASPI-Router allows up to 64k */
  72. LOCAL void *buffer = NULL;
  73. LOCAL HFILE driver_handle = 0;
  74. LOCAL HEV postSema = 0;
  75. LOCAL BOOL open_driver __PR((void));
  76. LOCAL BOOL close_driver __PR((void));
  77. LOCAL ULONG wait_post __PR((ULONG ulTimeOut));
  78. LOCAL BOOL  init_buffer __PR((void* mem));
  79. EXPORT void exit_func __PR((void));
  80. LOCAL void set_error __PR((SRB *srb, struct scg_cmd *sp));
  81. EXPORT void
  82. exit_func()
  83. {
  84. if (!close_driver())
  85. fprintf(stderr, "Cannot close OS/2-ASPI-Router!n");
  86. }
  87. /*
  88.  * Return version information for the low level SCSI transport code.
  89.  * This has been introduced to make it easier to trace down problems
  90.  * in applications.
  91.  */
  92. EXPORT char *
  93. scg__version(scgp, what)
  94. SCSI *scgp;
  95. int what;
  96. {
  97. if (scgp != (SCSI *)0) {
  98. switch (what) {
  99. case SCG_VERSION:
  100. return (_scg_trans_version);
  101. /*
  102.  * If you changed this source, you are not allowed to
  103.  * return "schily" for the SCG_AUTHOR request.
  104.  */
  105. case SCG_AUTHOR:
  106. return (_scg_auth_schily);
  107. case SCG_SCCS_ID:
  108. return (__sccsid);
  109. }
  110. }
  111. return ((char *)0);
  112. }
  113. EXPORT int
  114. scsi_open(scgp, device, busno, tgt, tlun)
  115. SCSI *scgp;
  116. char *device;
  117. int busno;
  118. int tgt;
  119. int tlun;
  120. {
  121. if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
  122. errno = EINVAL;
  123. if (scgp->errstr)
  124. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  125. "Illegal value for busno, target or lun '%d,%d,%d'",
  126. busno, tgt, tlun);
  127. return (-1);
  128. }
  129. if ((device != NULL && *device != '') || (busno == -2 && tgt == -2)) {
  130. errno = EINVAL;
  131. if (scgp->errstr)
  132. js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
  133. "Open by 'devname' not supported on this OS");
  134. return (-1);
  135. }
  136. if (scgp->local == NULL) {
  137. scgp->local = malloc(sizeof(struct scg_local));
  138. if (scgp->local == NULL)
  139. return (0);
  140. }
  141. if (!open_driver()) /* Try to open ASPI-Router */
  142. return (-1);
  143. atexit(exit_func); /* Install Exit Function which closes the ASPI-Router */
  144.   
  145. /* 
  146.  * Success after all 
  147.  */ 
  148. return (1);
  149. }
  150. EXPORT int
  151. scsi_close(scgp)
  152. SCSI *scgp;
  153. {
  154. exit_func();
  155. return (0);
  156. }
  157. LOCAL long
  158. scsi_maxdma(scgp)
  159. SCSI *scgp;
  160. {
  161. long maxdma = MAX_DMA_OS2;
  162. return (maxdma);
  163. }
  164. EXPORT void *
  165. scsi_getbuf(scgp, amt)
  166. SCSI *scgp;
  167. long amt;
  168. {
  169. ULONG rc;
  170. if (amt <= 0 || amt > scsi_maxdma(scgp))
  171. return ((void *)0);
  172. #ifdef DEBUG
  173. printf("scsi_getbuf: %ld bytesn", amt);
  174. #endif
  175. rc = DosAllocMem(&buffer, amt, OBJ_TILE | PAG_READ | PAG_WRITE | PAG_COMMIT);
  176. if (rc) {
  177. fprintf(stderr, "Cannot allocate buffer.n");
  178. return ((void *)0);
  179. }
  180. scgp->bufbase = buffer;
  181. #ifdef DEBUG
  182. printf("Buffer allocated at: 0x%xn", scgp->bufbase);
  183. #endif
  184. /* Lock memory */
  185. if (init_buffer(scgp->bufbase))
  186. return (scgp->bufbase);
  187. fprintf(stderr, "Cannot lock memory buffer.n");
  188. return ((void *)0); /* Error */
  189. }
  190. EXPORT void
  191. scsi_freebuf(scgp)
  192. SCSI *scgp;
  193. {
  194. if (scgp->bufbase && DosFreeMem(scgp->bufbase))
  195. fprintf(stderr, "Cannot free buffer memory for ASPI-Router!n"); /* Free our memory buffer if not already done */
  196. if (buffer == scgp->bufbase)
  197. buffer = NULL;
  198. scgp->bufbase = NULL;
  199. }
  200. EXPORT
  201. BOOL scsi_havebus(scgp, busno)
  202. SCSI *scgp;
  203. int busno;
  204. {
  205. register int t;
  206. register int l;
  207. if (busno < 0 || busno >= MAX_SCG)
  208. return (FALSE);
  209. return (TRUE);
  210. }
  211. EXPORT
  212. int scsi_fileno(scgp, busno, tgt, tlun)
  213. SCSI *scgp;
  214. int busno;
  215. int tgt;
  216. int tlun;
  217. {
  218. if (busno < 0 || busno >= MAX_SCG ||
  219.     tgt < 0 || tgt >= MAX_TGT ||
  220.     tlun < 0 || tlun >= MAX_LUN)
  221. return (-1);
  222. /*
  223.  * Return fake
  224.  */
  225. return (1);
  226. }
  227. EXPORT int
  228. scsi_initiator_id(scgp)
  229. SCSI *scgp;
  230. {
  231. return (-1);
  232. }
  233. EXPORT int
  234. scsi_isatapi(scgp)
  235. SCSI *scgp;
  236. {
  237. return (FALSE);
  238. }
  239. EXPORT
  240. int scsireset(scgp)
  241. SCSI *scgp;
  242. {
  243. ULONG rc; /* return value */
  244. ULONG cbreturn;
  245. ULONG cbParam;
  246. BOOL success;
  247. static SRB SRBlock; /* XXX makes it non reentrant */
  248. SRBlock.cmd = SRB_Reset; /* reset device */
  249. SRBlock.ha_num = scgp->scsibus;/* host adapter number */
  250. SRBlock.flags = SRB_Post; /* posting enabled */
  251. SRBlock.u.res.target = scgp->target; /* target id */
  252. SRBlock.u.res.lun = scgp->lun; /* target LUN */
  253. rc = DosDevIOCtl(driver_handle, 0x92, 0x02, (void*) &SRBlock, sizeof(SRB), &cbParam,
  254. (void*) &SRBlock, sizeof(SRB), &cbreturn);
  255. if (rc) {
  256. fprintf(stderr, "DosDevIOCtl() failed in resetDevice.n");
  257. return (1); /* DosDevIOCtl failed */
  258. } else {
  259. success = wait_post(40000); /** wait for SRB being processed */
  260. if (success)
  261. return (2);
  262. }
  263. if (SRBlock.status != SRB_Done)
  264. return (3);
  265. #ifdef DEBUG
  266. printf("resetDevice of host: %d target: %d lun: %d successful.n", scgp->scsibus, scgp->target, scgp->lun);
  267. printf("SRBlock.ha_status: 0x%x, SRBlock.target_status: 0x%x, SRBlock.satus: 0x%xn",
  268.  SRBlock.u.cmd.ha_status, SRBlock.u.cmd.target_status, SRBlock.status);
  269. #endif
  270. return (0);
  271. }
  272. /*
  273.  * Set error flags
  274.  */
  275. LOCAL void
  276. set_error(srb, sp)
  277. SRB *srb;
  278. struct scg_cmd *sp;
  279. {
  280. switch (srb->status) {
  281. case SRB_InvalidCmd: /* 0x80 Invalid SCSI request      */
  282. case SRB_InvalidHA: /* 0x81 Invalid host adapter number  */
  283. case SRB_BadDevice: /* 0x82 SCSI device not installed    */
  284. sp->error = SCG_FATAL;
  285. sp->ux_errno = EINVAL;
  286. break;
  287. case SRB_Busy: /* 0x00 SCSI request in progress     */
  288. case SRB_Aborted: /* 0x02 SCSI aborted by host      */
  289. case SRB_BadAbort: /* 0x03 Unable to abort SCSI request */
  290. case SRB_Error: /* 0x04 SCSI request completed with error */
  291. default:
  292. sp->error = SCG_RETRYABLE;
  293. sp->ux_errno = EIO;
  294. break;
  295. }
  296. }
  297. LOCAL int
  298. scsi_send(scgp, f, sp)
  299. SCSI *scgp;
  300. int f;
  301. struct scg_cmd *sp;
  302. {
  303. ULONG rc; /* return value */
  304. static SRB SRBlock; /* XXX makes it non reentrant */
  305. Ulong cbreturn;
  306. Ulong cbParam;
  307. UCHAR* ptr;
  308. if (!f) { /* Set in scsi_open() */
  309. sp->error = SCG_FATAL;
  310. return (-1);
  311. }
  312. if (sp->cdb_len > sizeof(SRBlock.u.cmd.cdb_st)) { /* commandsize too big */
  313. sp->error = SCG_FATAL;
  314. sp->ux_errno = EINVAL;
  315. fprintf(stderr, "sp->cdb_len > SRBlock.u.cmd.cdb_st. Fatal error in scsi_send, exiting...n");
  316. return (-1);
  317. }
  318. /* clear command block */
  319. fillbytes((caddr_t)&SRBlock.u.cmd.cdb_st, sizeof(SRBlock.u.cmd.cdb_st), '');
  320. /* copy cdrecord command into SRB */
  321. movebytes(&sp->cdb, &SRBlock.u.cmd.cdb_st, sp->cdb_len);
  322. /* Build SRB command block */
  323. SRBlock.cmd = SRB_Command;
  324. SRBlock.ha_num = scgp->scsibus; /* host adapter number */
  325. SRBlock.flags = SRB_Post; /* flags */
  326. SRBlock.u.cmd.target = scgp->target; /* Target SCSI ID */
  327. SRBlock.u.cmd.lun = scgp->lun; /* Target SCSI LUN */
  328. SRBlock.u.cmd.data_len = sp->size; /* # of bytes transferred */
  329. SRBlock.u.cmd.data_ptr = 0; /* pointer to data buffer */
  330. SRBlock.u.cmd.sense_len = sp->sense_len;/* length of sense buffer */
  331. SRBlock.u.cmd.link_ptr = 0; /* pointer to next SRB */
  332. SRBlock.u.cmd.cdb_len = sp->cdb_len; /* SCSI command length */
  333. /* Specify direction */
  334. if (sp->flags & SCG_RECV_DATA) {
  335. SRBlock.flags |= SRB_Read;
  336. } else {
  337. if (sp->size > 0) {
  338. SRBlock.flags |= SRB_Write;
  339. if (scgp->bufbase != sp->addr) {/* Copy only if data not in ASPI-Mem */
  340. movebytes(sp->addr, scgp->bufbase, sp->size);
  341. }
  342. } else {
  343. SRBlock.flags |= SRB_NoTransfer;
  344. }
  345. }
  346. sp->error = SCG_NO_ERROR;
  347. sp->sense_count = 0;
  348. sp->u_scb.cmd_scb[0] = 0;
  349. sp->resid = 0;
  350. /* execute SCSI command */
  351. rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
  352.  (void*) &SRBlock, sizeof(SRB), &cbParam,
  353.  (void*) &SRBlock, sizeof(SRB), &cbreturn);
  354. if (rc) { /* An error occured */
  355. fprintf(stderr, "DosDevIOCtl() in sendCommand failed.n");
  356. sp->error = SCG_FATAL;
  357. sp->ux_errno = EIO; /* Sp鋞er vielleicht errno einsetzen */
  358. return (rc);
  359. } else {
  360. /* Wait until the command is processed */
  361. rc = wait_post(sp->timeout*1000);
  362. if (rc) { /* An error occured */
  363. if (rc == 640) {
  364. /* Timeout */
  365. sp->error = SCG_TIMEOUT;
  366. sp->ux_errno = EIO;
  367. fprintf(stderr, "Timeout during SCSI-Command.n");
  368. return (1);
  369. }
  370. sp->error = SCG_FATAL;
  371. sp->ux_errno = EIO;
  372. fprintf(stderr, "Fatal Error during DosWaitEventSem().n");
  373. return (1);
  374. }
  375. /* The command is processed */
  376. if (SRBlock.status == SRB_Done) { /* succesful completion */
  377. #ifdef DEBUG
  378. printf("Command successful finished. SRBlock.status=0x%xnn", SRBlock.status);
  379. #endif
  380. sp->sense_count = 0;
  381. sp->resid = 0;
  382. if (sp->flags & SCG_RECV_DATA) { /* We read data */
  383. if (sp->addr && sp->size) {
  384. if (scgp->bufbase != sp->addr) /* Copy only if data not in ASPI-Mem */
  385. movebytes(scgp->bufbase, sp->addr, SRBlock.u.cmd.data_len);
  386. ptr = (UCHAR*)sp->addr;
  387. sp->resid = sp->size - SRBlock.u.cmd.data_len;/*nicht 黚ertragene bytes. Korrekt berechnet???*/
  388. }
  389. } /* end of if (sp->flags & SCG_RECV_DATA) */
  390. if (SRBlock.u.cmd.target_status == SRB_CheckStatus) { /* Sense data valid */
  391. sp->sense_count = (int)SRBlock.u.cmd.sense_len;
  392. if (sp->sense_count > sp->sense_len)
  393. sp->sense_count = sp->sense_len;
  394. ptr = (UCHAR*)&SRBlock.u.cmd.cdb_st;
  395. ptr += SRBlock.u.cmd.cdb_len;
  396. fillbytes(&sp->u_sense.Sense, sizeof(sp->u_sense.Sense), '');
  397. movebytes(ptr, &sp->u_sense.Sense, sp->sense_len);
  398. sp->u_scb.cmd_scb[0] = SRBlock.u.cmd.target_status;
  399. sp->ux_errno = EIO; /* Sp鋞er differenzieren? */
  400. }
  401. return (0);
  402. }
  403. /* SCSI-Error occured */
  404. set_error(&SRBlock, sp);
  405. if (SRBlock.u.cmd.target_status == SRB_CheckStatus) { /* Sense data valid */
  406. sp->sense_count = (int)SRBlock.u.cmd.sense_len;
  407. if (sp->sense_count > sp->sense_len)
  408. sp->sense_count = sp->sense_len;
  409. ptr = (UCHAR*)&SRBlock.u.cmd.cdb_st;
  410. ptr += SRBlock.u.cmd.cdb_len;
  411. fillbytes(&sp->u_sense.Sense, sizeof(sp->u_sense.Sense), '');
  412. movebytes(ptr, &sp->u_sense.Sense, sp->sense_len);
  413. sp->u_scb.cmd_scb[0] = SRBlock.u.cmd.target_status;
  414. }
  415. if (sp->flags & SCG_RECV_DATA) {
  416. if (sp->addr && sp->size) {
  417. if (scgp->bufbase != sp->addr) /* Copy only if data not in ASPI-Mem */
  418. movebytes(scgp->bufbase, sp->addr, SRBlock.u.cmd.data_len);
  419. }
  420. }
  421. #ifdef really
  422. sp->resid = SRBlock.u.cmd.data_len;/* XXXXX Got no Data ????? */
  423. #else
  424. sp->resid = sp->size - SRBlock.u.cmd.data_len;
  425. #endif
  426. return (1);
  427. }
  428. }
  429. /***************************************************************************
  430.  *                                                                         *
  431.  *  BOOL open_driver()                                                     *
  432.  *                                                                         *
  433.  *  Opens the ASPI Router device driver and sets device_handle.            *
  434.  *  Returns:                                                               *
  435.  *    TRUE - Success                                                       *
  436.  *    FALSE - Unsuccessful opening of device driver                        *
  437.  *                                                                         *
  438.  *  Preconditions: ASPI Router driver has be loaded                        *
  439.  *                                                                         *
  440.  ***************************************************************************/
  441. LOCAL BOOL
  442. open_driver()
  443. {
  444. ULONG rc; /* return value */
  445. ULONG ActionTaken; /* return value */
  446. USHORT openSemaReturn; /* return value */
  447. ULONG cbreturn;
  448. ULONG cbParam;
  449. if (driver_handle) /* ASPI-Router already opened */
  450. return (TRUE);
  451. rc = DosOpen((PSZ) "aspirou$", /* open driver*/
  452. &driver_handle,
  453. &ActionTaken,
  454. 0,
  455. 0,
  456. FILE_OPEN,
  457. OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
  458. NULL);
  459. if (rc) {
  460. fprintf(stderr, "Cannot open ASPI-Router!n");
  461. return (FALSE); /* opening failed -> return false*/
  462. }
  463. /* Init semaphore */
  464. if (DosCreateEventSem(NULL, &postSema, /* create event semaphore */
  465.  DC_SEM_SHARED, 0)) {
  466. DosClose(driver_handle);
  467. fprintf(stderr, "Cannot create event semaphore!n");
  468. return (FALSE);
  469. }
  470. rc = DosDevIOCtl(driver_handle, 0x92, 0x03, /* pass semaphore handle */
  471. (void*) &postSema, sizeof(HEV), /* to driver  */
  472. &cbParam, (void*) &openSemaReturn,
  473. sizeof(USHORT), &cbreturn);
  474. if (rc||openSemaReturn) { /* Error */
  475. DosCloseEventSem(postSema);
  476. DosClose(driver_handle);
  477. return (FALSE);
  478. }
  479. return (TRUE);
  480. }
  481. /***************************************************************************
  482.  *                                                                         *
  483.  *  BOOL close_driver()                                                    *
  484.  *                                                                         *
  485.  *  Closes the device driver                                               *
  486.  *  Returns:                                                               *
  487.  *    TRUE - Success                                                       *
  488.  *    FALSE - Unsuccessful closing of device driver                        *
  489.  *                                                                         *
  490.  *  Preconditions: ASPI Router driver has be opened with open_driver       *
  491.  *                                                                         *
  492.  ***************************************************************************/
  493. LOCAL BOOL
  494. close_driver()
  495. {
  496. ULONG rc; /* return value */
  497. if (driver_handle) {
  498. rc = DosClose(driver_handle);
  499. if (rc)
  500. return (FALSE); /* closing failed -> return false */
  501. driver_handle = 0;
  502. if (DosCloseEventSem(postSema))
  503. fprintf(stderr, "Cannot close event semaphore!n");
  504. if (buffer && DosFreeMem(buffer))
  505. fprintf(stderr, "Cannot free buffer memory for ASPI-Router!n"); /* Free our memory buffer if not already done */
  506. buffer = NULL;
  507. }
  508. return (TRUE);
  509. }
  510. LOCAL ULONG
  511. wait_post(ULONG ulTimeOut)
  512. {
  513. ULONG count = 0;
  514. ULONG rc; /* return value */
  515. /* rc = DosWaitEventSem(postSema, -1);*/ /* wait forever*/
  516. rc = DosWaitEventSem(postSema, ulTimeOut);
  517. DosResetEventSem(postSema, &count);
  518. return (rc);
  519. }
  520. LOCAL BOOL 
  521. init_buffer(mem)
  522. void *mem;
  523. {
  524. ULONG rc; /* return value */
  525. USHORT lockSegmentReturn; /* return value */
  526. Ulong cbreturn;
  527. Ulong cbParam;
  528. rc = DosDevIOCtl(driver_handle, 0x92, 0x04, /* pass buffers pointer */
  529. (void*) mem, sizeof(void*), /* to driver */
  530. &cbParam, (void*) &lockSegmentReturn,
  531. sizeof(USHORT), &cbreturn);
  532. if (rc)
  533. return (FALSE); /* DosDevIOCtl failed */
  534. if (lockSegmentReturn)
  535. return (FALSE); /* Driver could not lock segment */
  536. return (TRUE);
  537. }
  538. #define sense u_sense.Sense