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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)drv_simul.c 1.12 99/08/30 Copyright 1998 J. Schilling */
  2. #ifndef lint
  3. static char sccsid[] =
  4. "@(#)drv_simul.c 1.12 99/08/30 Copyright 1998 J. Schilling";
  5. #endif
  6. /*
  7.  * Simulation device driver
  8.  *
  9.  * Copyright (c) 1998 J. Schilling
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26. #define DEBUG
  27. #include <mconfig.h>
  28. #include <stdio.h>
  29. #include <standard.h>
  30. #include <stdxlib.h>
  31. #include <unixstd.h>
  32. #include <errno.h>
  33. #include <strdefs.h>
  34. #include <sys/types.h>
  35. #include <sys/time.h>
  36. #include <utypes.h>
  37. #include <btorder.h>
  38. /*#include <scgio.h>*/
  39. #include <scg/scsidefs.h>
  40. #include <scg/scsireg.h>
  41. #include <scg/scsitransp.h>
  42. #include <libport.h>
  43. #include "cdrecord.h"
  44. extern int silent;
  45. extern int verbose;
  46. extern int lverbose;
  47. LOCAL int simul_load __PR((SCSI *scgp));
  48. LOCAL int simul_unload __PR((SCSI *scgp));
  49. LOCAL cdr_t *identify_simul __PR((SCSI *scgp, cdr_t *, struct scsi_inquiry *));
  50. LOCAL int getdisktype_simul __PR((SCSI *scgp, cdr_t *dp, dstat_t *dsp));
  51. LOCAL int speed_select_simul __PR((SCSI *scgp, int *speedp, int dummy));
  52. LOCAL int next_wr_addr_simul __PR((SCSI *scgp, int track, track_t *trackp, long *ap));
  53. LOCAL int cdr_write_simul __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
  54. LOCAL int open_track_simul __PR((SCSI *scgp, cdr_t *dp, int track, track_t *trackp));
  55. LOCAL int close_track_simul __PR((SCSI *scgp, int track, track_t *trackp));
  56. LOCAL int open_session_simul __PR((SCSI *scgp, int tracks, track_t *trackp, int toctype, int multi));
  57. LOCAL int fixate_simul __PR((SCSI *scgp, int onp, int dummy, int toctype, int tracks, track_t *trackp));
  58. LOCAL void tv_sub __PR((struct timeval *tvp1, struct timeval *tvp2));
  59. LOCAL int
  60. simul_load(scgp)
  61. SCSI *scgp;
  62. {
  63. return (0);
  64. }
  65. LOCAL int
  66. simul_unload(scgp)
  67. SCSI *scgp;
  68. {
  69. return (0);
  70. }
  71. cdr_t cdr_cdr_simul = {
  72. 0,
  73. CDR_TAO|CDR_DAO|CDR_PACKET,
  74. "cdr_simul",
  75. "simulation CD-R driver for timing/speed tests",
  76. 0,
  77. identify_simul,
  78. drive_attach,
  79. getdisktype_simul,
  80. simul_load,
  81. simul_unload,
  82. buf_dummy,
  83. (int(*)__PR((SCSI *)))cmd_dummy, /* recovery_needed */
  84. (int(*)__PR((SCSI *, int)))cmd_dummy, /* recover */
  85. speed_select_simul,
  86. select_secsize,
  87. next_wr_addr_simul,
  88. (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */
  89. cdr_write_simul,
  90. (int(*)__PR((SCSI *scgp, int, track_t *)))cmd_dummy, /* send_cue */
  91. open_track_simul,
  92. close_track_simul,
  93. open_session_simul,
  94. cmd_dummy,
  95. read_session_offset,
  96. fixate_simul,
  97. blank_dummy,
  98. };
  99. cdr_t cdr_dvd_simul = {
  100. 0,
  101. CDR_TAO|CDR_DAO|CDR_PACKET,
  102. "dvd_simul",
  103. "simulation DVD-R driver for timing/speed tests",
  104. 0,
  105. identify_simul,
  106. drive_attach,
  107. getdisktype_simul,
  108. simul_load,
  109. simul_unload,
  110. buf_dummy,
  111. (int(*)__PR((SCSI *)))cmd_dummy, /* recovery_needed */
  112. (int(*)__PR((SCSI *, int)))cmd_dummy, /* recover */
  113. speed_select_simul,
  114. select_secsize,
  115. next_wr_addr_simul,
  116. (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */
  117. cdr_write_simul,
  118. (int(*)__PR((SCSI *scgp, int, track_t *)))cmd_dummy, /* send_cue */
  119. open_track_simul,
  120. close_track_simul,
  121. open_session_simul,
  122. cmd_dummy,
  123. read_session_offset,
  124. fixate_simul,
  125. blank_dummy,
  126. };
  127. LOCAL cdr_t *
  128. identify_simul(scgp, dp, ip)
  129. SCSI *scgp;
  130. cdr_t *dp;
  131. struct scsi_inquiry *ip;
  132. {
  133. return (dp);
  134. }
  135. LOCAL int simul_speed = 1;
  136. LOCAL int simul_dummy;
  137. LOCAL int simul_isdvd;
  138. LOCAL int simul_bufsize = 1024;
  139. LOCAL Uint sleep_rest;
  140. LOCAL Uint sleep_max;
  141. LOCAL Uint sleep_min;
  142. LOCAL int
  143. getdisktype_simul(scgp, dp, dsp)
  144. SCSI *scgp;
  145. cdr_t *dp;
  146. dstat_t *dsp;
  147. {
  148. if (strcmp(dp->cdr_drname, cdr_cdr_simul.cdr_drname) == 0) {
  149. dsp->ds_maxblocks = 333000;
  150. simul_isdvd = FALSE;
  151. } else {
  152. dsp->ds_maxblocks = 2464153; /* 4.7 GB  */
  153. /* dsp->ds_maxblocks = 1927896;*/ /* 3.95 GB */
  154. simul_isdvd = TRUE;
  155. }
  156. return (drive_getdisktype(scgp, dp, dsp));
  157. }
  158. LOCAL int
  159. speed_select_simul(scgp, speedp, dummy)
  160. SCSI *scgp;
  161. int *speedp;
  162. int dummy;
  163. {
  164. long val;
  165. char *p;
  166. if (speedp)
  167. simul_speed = *speedp;
  168. simul_dummy = dummy;
  169. if ((p = getenv("CDR_SIMUL_BUFSIZE")) != NULL) {
  170. if (getnum(p, &val) == 1)
  171. simul_bufsize = val / 1024;
  172. }
  173. /*
  174.  * sleep_max is the time to empty the drive's buffer in 祍.
  175.  * sector size is from 2048 bytes to 2352 bytes.
  176.  * If sector size is 2048 bytes, 1k takes 6.666 ms.
  177.  * If sector size is 2352 bytes, 1k takes 5.805 ms.
  178.  * We take the 6 ms as an average between both values.
  179.  * simul_bufsize is the number of kilobytes in drive buffer.
  180.  */
  181. sleep_max = 6 * 1000 * simul_bufsize / simul_speed;
  182. if (lverbose) {
  183. printf("Simulation drive buffer size: %d KBn", simul_bufsize);
  184. printf("Mamimum reserve time in drive buffer: %d.%3.3d msn",
  185. sleep_max / 1000,
  186. sleep_max % 1000);
  187. }
  188. return (0);
  189. }
  190. LOCAL int
  191. next_wr_addr_simul(scgp, track, trackp, ap)
  192. SCSI *scgp;
  193. int track;
  194. track_t *trackp;
  195. long *ap;
  196. {
  197. if (ap)
  198. *ap = 0L;
  199. return (0);
  200. }
  201. LOCAL int
  202. cdr_write_simul(scgp, bp, sectaddr, size, blocks, islast)
  203. SCSI *scgp;
  204. caddr_t bp; /* address of buffer */
  205. long sectaddr; /* disk address (sector) to put */
  206. long size; /* number of bytes to transfer */
  207. int blocks; /* sector count */
  208. BOOL islast; /* last write for track */
  209. {
  210. Uint sleep_time;
  211. Uint sleep_diff;
  212. struct timeval tv1;
  213. static struct timeval tv2;
  214. if (lverbose > 1 && islast)
  215. printf("nWriting last record for this track.n");
  216. gettimeofday(&tv1, (struct timezone *)0);
  217. if (tv2.tv_sec != 0) { /* Already did gettimeofday(&tv2) */
  218. tv_sub(&tv1, &tv2);
  219. if (sleep_rest != 0) {
  220. sleep_diff = tv1.tv_sec * 1000000 + tv1.tv_usec;
  221. if (sleep_min > (sleep_rest - sleep_diff))
  222. sleep_min = (sleep_rest - sleep_diff);
  223. if (sleep_diff > sleep_rest) {
  224. printf("Buffer underrun: actual delay was %d.%3.3d ms, max delay was %d.%3.3d ms.n",
  225. sleep_diff / 1000,
  226. sleep_diff % 1000,
  227. sleep_rest / 1000,
  228. sleep_rest % 1000);
  229. if (!simul_dummy)
  230. return (-1);
  231. }
  232. /*
  233.  * If we spent time outside the write function
  234.  * subtract this time.
  235.  */
  236. sleep_diff = tv1.tv_sec * 1000000 + tv1.tv_usec;
  237. if (sleep_rest >= sleep_diff)
  238. sleep_rest -= sleep_diff;
  239. else
  240. sleep_rest = 0;
  241. }
  242. }
  243. /*
  244.  * Speed 1 ist 150 Sektoren/s
  245.  */
  246. sleep_time = 1000000 * blocks / 75 / simul_speed;
  247. sleep_time += sleep_rest;
  248. if (sleep_time > sleep_max) {
  249. int mod;
  250. sleep_rest = sleep_max;
  251. sleep_time -= sleep_rest;
  252. mod = sleep_time % 20000;
  253. sleep_rest += mod;
  254. sleep_time -= mod;
  255. if (sleep_time > 0)
  256. usleep(sleep_time);
  257. } else {
  258. sleep_rest = sleep_time;
  259. }
  260. gettimeofday(&tv2, (struct timezone *)0);
  261. return (size);
  262. }
  263. LOCAL int
  264. open_track_simul(scgp, dp, track, trackp)
  265. SCSI *scgp;
  266. cdr_t *dp;
  267. int track;
  268. track_t *trackp;
  269. {
  270. sleep_min = 999 * 1000000;
  271. return (0);
  272. }
  273. LOCAL int
  274. close_track_simul(scgp, track, trackp)
  275. SCSI *scgp;
  276. int track;
  277. track_t *trackp;
  278. {
  279. if (lverbose) {
  280. printf("Remaining reserve time in drive buffer: %d.%3.3d msn",
  281. sleep_rest / 1000,
  282. sleep_rest % 1000);
  283. printf("Minimum reserve time in drive buffer: %d.%3.3d msn",
  284. sleep_min / 1000,
  285. sleep_min % 1000);
  286. }
  287. usleep(sleep_rest);
  288. sleep_rest = 0;
  289. return (0);
  290. }
  291. LOCAL int
  292. open_session_simul(scgp, tracks, trackp, toctype, multi)
  293. SCSI *scgp;
  294. int tracks;
  295. track_t *trackp;
  296. int toctype;
  297. int multi;
  298. {
  299. return (0);
  300. }
  301. LOCAL int
  302. fixate_simul(scgp, onp, dummy, toctype, tracks, trackp)
  303. SCSI *scgp;
  304. int onp;
  305. int dummy;
  306. int toctype;
  307. int tracks;
  308. track_t *trackp;
  309. {
  310. return (0);
  311. }
  312. LOCAL void
  313. tv_sub(tvp1, tvp2)
  314. struct timeval *tvp1;
  315. struct timeval *tvp2;
  316. {
  317. tvp1->tv_sec -= tvp2->tv_sec;
  318. tvp1->tv_usec -= tvp2->tv_usec;
  319. while (tvp1->tv_usec < 0) {
  320. tvp1->tv_usec += 1000000;
  321. tvp1->tv_sec -= 1;
  322. }
  323. }