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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*
  2. XXX
  3. SIZEOF testen !!!
  4. */
  5. /* @(#)scsi_cdr.c 1.84 00/01/28 Copyright 1995 J. Schilling */
  6. #ifndef lint
  7. static char sccsid[] =
  8. "@(#)scsi_cdr.c 1.84 00/01/28 Copyright 1995 J. Schilling";
  9. #endif
  10. /*
  11.  * SCSI command functions for cdrecord
  12.  *
  13.  * Copyright (c) 1995 J. Schilling
  14.  */
  15. /*
  16.  * This program is free software; you can redistribute it and/or modify
  17.  * it under the terms of the GNU General Public License as published by
  18.  * the Free Software Foundation; either version 2, or (at your option)
  19.  * any later version.
  20.  *
  21.  * This program is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  * GNU General Public License for more details.
  25.  *
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with this program; see the file COPYING.  If not, write to
  28.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  */
  30. /*
  31.  * NOTICE: The Philips CDD 521 has several firmware bugs.
  32.  * One of them is not to respond to a SCSI selection
  33.  * within 200ms if the general load on the
  34.  * SCSI bus is high. To deal with this problem
  35.  * most of the SCSI commands are send with the
  36.  * SCG_CMD_RETRY flag enabled.
  37.  */
  38. #include <mconfig.h>
  39. #include <stdio.h>
  40. #include <standard.h>
  41. #include <stdxlib.h>
  42. #include <unixstd.h>
  43. #include <fctldefs.h>
  44. #include <errno.h>
  45. #include <strdefs.h>
  46. #include <utypes.h>
  47. #include <btorder.h>
  48. #include <intcvt.h>
  49. #include <scg/scgcmd.h>
  50. #include <scg/scsidefs.h>
  51. #include <scg/scsireg.h>
  52. #include <scg/scsitransp.h>
  53. #include "cdrecord.h"
  54. #define strbeg(s1,s2) (strstr((s2), (s1)) == (s2))
  55. EXPORT BOOL unit_ready __PR((SCSI *scgp));
  56. EXPORT BOOL wait_unit_ready __PR((SCSI *scgp, int secs));
  57. EXPORT int test_unit_ready __PR((SCSI *scgp));
  58. EXPORT int rezero_unit __PR((SCSI *scgp));
  59. EXPORT int request_sense __PR((SCSI *scgp));
  60. EXPORT int inquiry __PR((SCSI *scgp, caddr_t, int));
  61. EXPORT int read_capacity __PR((SCSI *scgp));
  62. EXPORT int scsi_load_unload __PR((SCSI *scgp, int));
  63. EXPORT int scsi_prevent_removal __PR((SCSI *scgp, int));
  64. EXPORT int scsi_start_stop_unit __PR((SCSI *scgp, int, int));
  65. EXPORT int scsi_set_speed __PR((SCSI *scgp, int readspeed, int writespeed));
  66. EXPORT int scsi_get_speed __PR((SCSI *scgp, int *readspeedp, int *writespeedp));
  67. EXPORT int qic02 __PR((SCSI *scgp, int));
  68. EXPORT int write_xg0 __PR((SCSI *scgp, caddr_t, long, long, int));
  69. EXPORT int write_xg1 __PR((SCSI *scgp, caddr_t, long, long, int));
  70. EXPORT int write_xg5 __PR((SCSI *scgp, caddr_t, long, long, int));
  71. EXPORT int scsi_flush_cache __PR((SCSI *scgp));
  72. EXPORT int read_buffer __PR((SCSI *scgp, caddr_t bp, int cnt, int mode));
  73. EXPORT int read_subchannel __PR((SCSI *scgp, caddr_t bp, int track,
  74. int cnt,int msf, int subq, int fmt));
  75. EXPORT int read_toc __PR((SCSI *scgp, caddr_t, int, int, int, int));
  76. EXPORT int read_toc_philips __PR((SCSI *scgp, caddr_t, int, int, int, int));
  77. EXPORT int read_header __PR((SCSI *scgp, caddr_t, long, int, int));
  78. EXPORT int read_disk_info __PR((SCSI *scgp, caddr_t, int));
  79. EXPORT int read_track_info __PR((SCSI *scgp, caddr_t, int, int));
  80. EXPORT int read_track_info_philips __PR((SCSI *scgp, caddr_t, int, int));
  81. EXPORT int scsi_close_tr_session __PR((SCSI *scgp, int type, int track));
  82. EXPORT int read_master_cue __PR((SCSI *scgp, caddr_t bp, int sheet, int cnt));
  83. EXPORT int send_cue_sheet __PR((SCSI *scgp, caddr_t bp, long size));
  84. EXPORT int read_buff_cap __PR((SCSI *scgp, long *, long *));
  85. EXPORT int scsi_blank __PR((SCSI *scgp, long addr, int blanktype));
  86. EXPORT BOOL allow_atapi __PR((SCSI *scgp, BOOL new));
  87. EXPORT int mode_select __PR((SCSI *scgp, Uchar *, int, int, int));
  88. EXPORT int mode_sense __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  89. EXPORT int mode_select_sg0 __PR((SCSI *scgp, Uchar *, int, int, int));
  90. EXPORT int mode_sense_sg0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  91. EXPORT int mode_select_g0 __PR((SCSI *scgp, Uchar *, int, int, int));
  92. EXPORT int mode_select_g1 __PR((SCSI *scgp, Uchar *, int, int, int));
  93. EXPORT int mode_sense_g0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  94. EXPORT int mode_sense_g1 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  95. EXPORT int read_tochdr __PR((SCSI *scgp, cdr_t *, int *, int *));
  96. EXPORT int read_cdtext __PR((SCSI *scgp));
  97. EXPORT int read_trackinfo __PR((SCSI *scgp, int, long *, struct msf *, int *, int *, int *));
  98. EXPORT int read_B0 __PR((SCSI *scgp, BOOL isbcd, long *b0p, long *lop));
  99. EXPORT int read_session_offset __PR((SCSI *scgp, long *));
  100. EXPORT int read_session_offset_philips __PR((SCSI *scgp, long *));
  101. EXPORT int sense_secsize __PR((SCSI *scgp, int current));
  102. EXPORT int select_secsize __PR((SCSI *scgp, int));
  103. EXPORT BOOL is_cddrive __PR((SCSI *scgp));
  104. EXPORT BOOL is_unknown_dev __PR((SCSI *scgp));
  105. EXPORT int read_scsi __PR((SCSI *scgp, caddr_t, long, int));
  106. EXPORT int read_g0 __PR((SCSI *scgp, caddr_t, long, int));
  107. EXPORT int read_g1 __PR((SCSI *scgp, caddr_t, long, int));
  108. EXPORT BOOL getdev __PR((SCSI *scgp, BOOL));
  109. EXPORT void printdev __PR((SCSI *scgp));
  110. EXPORT BOOL do_inquiry __PR((SCSI *scgp, BOOL));
  111. EXPORT BOOL recovery_needed __PR((SCSI *scgp));
  112. EXPORT int scsi_load __PR((SCSI *scgp));
  113. EXPORT int scsi_unload __PR((SCSI *scgp));
  114. EXPORT int scsi_cdr_write __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
  115. EXPORT struct cd_mode_page_2A * mmc_cap __PR((SCSI *scgp, Uchar *modep));
  116. EXPORT void mmc_getval __PR((struct cd_mode_page_2A *mp,
  117. BOOL *cdrrp, BOOL *cdwrp,
  118. BOOL *cdrrwp, BOOL *cdwrwp,
  119. BOOL *dvdp));
  120. EXPORT BOOL is_mmc __PR((SCSI *scgp, BOOL *dvdp));
  121. EXPORT BOOL mmc_check __PR((SCSI *scgp, BOOL *cdrrp, BOOL *cdwrp,
  122. BOOL *cdrrwp, BOOL *cdwrwp,
  123. BOOL *dvdp));
  124. EXPORT void print_capabilities __PR((SCSI *scgp));
  125. EXPORT BOOL
  126. unit_ready(scgp)
  127. SCSI *scgp;
  128. {
  129. register struct scg_cmd *scmd = scgp->scmd;
  130. if (test_unit_ready(scgp) >= 0) /* alles OK */
  131. return (TRUE);
  132. else if (scmd->error >= SCG_FATAL) /* nicht selektierbar */
  133. return (FALSE);
  134. if (scmd->sense.code < 0x70) { /* non extended Sense */
  135. if (scmd->sense.code == 0x04) /* NOT_READY */
  136. return (FALSE);
  137. return (TRUE);
  138. }
  139. if (((struct scsi_ext_sense *)&scmd->sense)->key == SC_UNIT_ATTENTION) {
  140. if (test_unit_ready(scgp) >= 0) /* alles OK */
  141. return (TRUE);
  142. }
  143. /* FALSE wenn NOT_READY */
  144. return (((struct scsi_ext_sense *)&scmd->sense)->key != SC_NOT_READY);
  145. }
  146. EXPORT BOOL
  147. wait_unit_ready(scgp, secs)
  148. SCSI *scgp;
  149. int secs;
  150. {
  151. int i;
  152. int c;
  153. int k;
  154. int ret;
  155. scgp->silent++;
  156. ret = test_unit_ready(scgp); /* eat up unit attention */
  157. if (ret < 0)
  158. ret = test_unit_ready(scgp); /* got power on condition? */
  159. scgp->silent--;
  160. if (ret >= 0) /* success that's enough */
  161. return (TRUE);
  162. scgp->silent++;
  163. for (i=0; i < secs && (ret = test_unit_ready(scgp)) < 0; i++) {
  164. if (scgp->scmd->scb.busy != 0) {
  165. sleep(1);
  166. continue;
  167. }
  168. c = scsi_sense_code(scgp);
  169. k = scsi_sense_key(scgp);
  170. if (k == SC_NOT_READY && (c == 0x3A || c == 0x30)) {
  171. if (scgp->silent <= 1)
  172. scsiprinterr(scgp);
  173. scgp->silent--;
  174. return (FALSE);
  175. }
  176. sleep(1);
  177. }
  178. scgp->silent--;
  179. if (ret < 0)
  180. return (FALSE);
  181. return (TRUE);
  182. }
  183. EXPORT int
  184. test_unit_ready(scgp)
  185. SCSI *scgp;
  186. {
  187. register struct scg_cmd *scmd = scgp->scmd;
  188. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  189. scmd->addr = (caddr_t)0;
  190. scmd->size = 0;
  191. scmd->flags = SCG_DISRE_ENA | (scgp->silent ? SCG_SILENT:0);
  192. scmd->cdb_len = SC_G0_CDBLEN;
  193. scmd->sense_len = CCS_SENSE_LEN;
  194. scmd->target = scgp->target;
  195. scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
  196. scmd->cdb.g0_cdb.lun = scgp->lun;
  197. scgp->cmdname = "test unit ready";
  198. return (scsicmd(scgp));
  199. }
  200. EXPORT int
  201. rezero_unit(scgp)
  202. SCSI *scgp;
  203. {
  204. register struct scg_cmd *scmd = scgp->scmd;
  205. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  206. scmd->addr = (caddr_t)0;
  207. scmd->size = 0;
  208. scmd->flags = SCG_DISRE_ENA;
  209. scmd->cdb_len = SC_G0_CDBLEN;
  210. scmd->sense_len = CCS_SENSE_LEN;
  211. scmd->target = scgp->target;
  212. scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
  213. scmd->cdb.g0_cdb.lun = scgp->lun;
  214. scgp->cmdname = "rezero unit";
  215. return (scsicmd(scgp));
  216. }
  217. EXPORT int
  218. request_sense(scgp)
  219. SCSI *scgp;
  220. {
  221.  char sensebuf[CCS_SENSE_LEN];
  222. register struct scg_cmd *scmd = scgp->scmd;
  223. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  224. scmd->addr = sensebuf;
  225. scmd->size = sizeof(sensebuf);;
  226. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  227. scmd->cdb_len = SC_G0_CDBLEN;
  228. scmd->sense_len = CCS_SENSE_LEN;
  229. scmd->target = scgp->target;
  230. scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
  231. scmd->cdb.g0_cdb.lun = scgp->lun;
  232. scmd->cdb.g0_cdb.count = CCS_SENSE_LEN;
  233. scgp->cmdname = "request_sense";
  234. if (scsicmd(scgp) < 0)
  235. return (-1);
  236. scsiprsense((Uchar *)sensebuf, CCS_SENSE_LEN - scsigetresid(scgp));
  237. return (0);
  238. }
  239. EXPORT int
  240. inquiry(scgp, bp, cnt)
  241. SCSI *scgp;
  242. caddr_t bp;
  243. int cnt;
  244. {
  245. register struct scg_cmd *scmd = scgp->scmd;
  246. fillbytes(bp, cnt, '');
  247. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  248. scmd->addr = bp;
  249. scmd->size = cnt;
  250. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  251. scmd->cdb_len = SC_G0_CDBLEN;
  252. scmd->sense_len = CCS_SENSE_LEN;
  253. scmd->target = scgp->target;
  254. scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
  255. scmd->cdb.g0_cdb.lun = scgp->lun;
  256. scmd->cdb.g0_cdb.count = cnt;
  257. scgp->cmdname = "inquiry";
  258. if (scsicmd(scgp) < 0)
  259. return (-1);
  260. if (scgp->verbose)
  261. scsiprbytes("Inquiry Data   :", (Uchar *)bp, cnt - scsigetresid(scgp));
  262. return (0);
  263. }
  264. EXPORT int
  265. read_capacity(scgp)
  266. SCSI *scgp;
  267. {
  268. register struct scg_cmd *scmd = scgp->scmd;
  269. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  270. scmd->addr = (caddr_t)scgp->cap;
  271. scmd->size = sizeof(struct scsi_capacity);
  272. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  273. scmd->cdb_len = SC_G1_CDBLEN;
  274. scmd->sense_len = CCS_SENSE_LEN;
  275. scmd->target = scgp->target;
  276. scmd->cdb.g1_cdb.cmd = 0x25; /* Read Capacity */
  277. scmd->cdb.g1_cdb.lun = scgp->lun;
  278. g1_cdblen(&scmd->cdb.g1_cdb, 0); /* Full Media */
  279. scgp->cmdname = "read capacity";
  280. if (scsicmd(scgp) < 0) {
  281. return (-1);
  282. } else {
  283. long kb;
  284. long mb;
  285. long prmb;
  286. double dkb;
  287. long cbsize;
  288. long cbaddr;
  289. /*
  290.  * c_bsize & c_baddr are signed Int32_t
  291.  * so we use signed int conversion here.
  292.  */
  293. cbsize = a_to_4_byte(&scgp->cap->c_bsize);
  294. cbaddr = a_to_4_byte(&scgp->cap->c_baddr);
  295. scgp->cap->c_bsize = cbsize;
  296. scgp->cap->c_baddr = cbaddr;
  297. if (scgp->silent)
  298. return (0);
  299. dkb =  (scgp->cap->c_baddr+1.0) * (scgp->cap->c_bsize/1024.0);
  300. kb = dkb;
  301. mb = dkb / 1024.0;
  302. prmb = dkb / 1000.0 * 1.024;
  303. printf("Capacity: %ld Blocks = %ld kBytes = %ld MBytes = %ld prMBn",
  304. (long)scgp->cap->c_baddr+1, kb, mb, prmb);
  305. printf("Sectorsize: %ld Bytesn", (long)scgp->cap->c_bsize);
  306. }
  307. return (0);
  308. }
  309. EXPORT int
  310. scsi_load_unload(scgp, load)
  311. SCSI *scgp;
  312. int load;
  313. {
  314. register struct scg_cmd *scmd = scgp->scmd;
  315. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  316. scmd->flags = SCG_DISRE_ENA;
  317. scmd->cdb_len = SC_G5_CDBLEN;
  318. scmd->sense_len = CCS_SENSE_LEN;
  319. scmd->target = scgp->target;
  320. scmd->cdb.g5_cdb.cmd = 0xA6;
  321. scmd->cdb.g5_cdb.lun = scgp->lun;
  322. scmd->cdb.g5_cdb.addr[1] = load?3:2;
  323. scmd->cdb.g5_cdb.count[2] = 0; /* slot # */
  324. scgp->cmdname = "medium load/unload";
  325. if (scsicmd(scgp) < 0)
  326. return (-1);
  327. return (0);
  328. }
  329. EXPORT int
  330. scsi_prevent_removal(scgp, prevent)
  331. SCSI *scgp;
  332. int prevent;
  333. {
  334. register struct scg_cmd *scmd = scgp->scmd;
  335. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  336. scmd->flags = SCG_DISRE_ENA;
  337. scmd->cdb_len = SC_G0_CDBLEN;
  338. scmd->sense_len = CCS_SENSE_LEN;
  339. scmd->target = scgp->target;
  340. scmd->cdb.g0_cdb.cmd = 0x1E;
  341. scmd->cdb.g0_cdb.lun = scgp->lun;
  342. scmd->cdb.g0_cdb.count = prevent & 1;
  343. scgp->cmdname = "prevent/allow medium removal";
  344. if (scsicmd(scgp) < 0)
  345. return (-1);
  346. return (0);
  347. }
  348. EXPORT int
  349. scsi_start_stop_unit(scgp, flg, loej)
  350. SCSI *scgp;
  351. int flg;
  352. int loej;
  353. {
  354. register struct scg_cmd *scmd = scgp->scmd;
  355. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  356. scmd->flags = SCG_DISRE_ENA;
  357. scmd->cdb_len = SC_G0_CDBLEN;
  358. scmd->sense_len = CCS_SENSE_LEN;
  359. scmd->target = scgp->target;
  360. scmd->cdb.g0_cdb.cmd = 0x1B; /* Start Stop Unit */
  361. scmd->cdb.g0_cdb.lun = scgp->lun;
  362. scmd->cdb.g0_cdb.count = (flg ? 1:0) | (loej ? 2:0);
  363. scgp->cmdname = "start/stop unit";
  364. return (scsicmd(scgp));
  365. }
  366. EXPORT int
  367. scsi_set_speed(scgp, readspeed, writespeed)
  368. SCSI *scgp;
  369. int readspeed;
  370. int writespeed;
  371. {
  372. register struct scg_cmd *scmd = scgp->scmd;
  373. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  374. scmd->flags = SCG_DISRE_ENA;
  375. scmd->cdb_len = SC_G5_CDBLEN;
  376. scmd->sense_len = CCS_SENSE_LEN;
  377. scmd->target = scgp->target;
  378. scmd->cdb.g5_cdb.cmd = 0xBB;
  379. scmd->cdb.g5_cdb.lun = scgp->lun;
  380. i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
  381. i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
  382. scgp->cmdname = "set cd speed";
  383. if (scsicmd(scgp) < 0)
  384. return (-1);
  385. return (0);
  386. }
  387. EXPORT int
  388. scsi_get_speed(scgp, readspeedp, writespeedp)
  389. SCSI *scgp;
  390. int *readspeedp;
  391. int *writespeedp;
  392. {
  393. struct cd_mode_page_2A *mp;
  394. Uchar m[256];
  395. int val;
  396. scgp->silent++;
  397. mp = mmc_cap(scgp, m);/* Get MMC capabilities in allocated mp */
  398. scgp->silent--;
  399. if (mp == NULL)
  400. return (-1); /* Pre SCSI-3/mmc drive   */
  401. val = a_to_u_2_byte(mp->cur_read_speed);
  402. if (readspeedp)
  403. *writespeedp = val;
  404. val = a_to_u_2_byte(mp->cur_write_speed);
  405. if (writespeedp)
  406. *writespeedp = val;
  407. return (0);
  408. }
  409. EXPORT int
  410. qic02(scgp, cmd)
  411. SCSI *scgp;
  412. int cmd;
  413. {
  414. register struct scg_cmd *scmd = scgp->scmd;
  415. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  416. scmd->addr = (caddr_t)0;
  417. scmd->size = 0;
  418. scmd->flags = SCG_DISRE_ENA;
  419. scmd->cdb_len = SC_G0_CDBLEN;
  420. scmd->sense_len = DEF_SENSE_LEN;
  421. scmd->target = scgp->target;
  422. scmd->cdb.g0_cdb.cmd = 0x0D; /* qic02 Sysgen SC4000 */
  423. scmd->cdb.g0_cdb.lun = scgp->lun;
  424. scmd->cdb.g0_cdb.mid_addr = cmd;
  425. scgp->cmdname = "qic 02";
  426. return (scsicmd(scgp));
  427. }
  428. EXPORT int
  429. write_xg0(scgp, bp, addr, size, cnt)
  430. SCSI *scgp;
  431. caddr_t bp; /* address of buffer */
  432. long addr; /* disk address (sector) to put */
  433. long size; /* number of bytes to transfer */
  434. int cnt; /* sectorcount */
  435. {
  436. register struct scg_cmd *scmd = scgp->scmd;
  437. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  438. scmd->addr = bp;
  439. scmd->size = size;
  440. scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
  441. /* scmd->flags = SCG_DISRE_ENA;*/
  442. scmd->cdb_len = SC_G0_CDBLEN;
  443. scmd->sense_len = CCS_SENSE_LEN;
  444. scmd->target = scgp->target;
  445. scmd->cdb.g0_cdb.cmd = SC_WRITE;
  446. scmd->cdb.g0_cdb.lun = scgp->lun;
  447. g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
  448. scmd->cdb.g0_cdb.count = cnt;
  449. scgp->cmdname = "write_g0";
  450. if (scsicmd(scgp) < 0)
  451. return (-1);
  452. return (size - scsigetresid(scgp));
  453. }
  454. EXPORT int
  455. write_xg1(scgp, bp, addr, size, cnt)
  456. SCSI *scgp;
  457. caddr_t bp; /* address of buffer */
  458. long addr; /* disk address (sector) to put */
  459. long size; /* number of bytes to transfer */
  460. int cnt; /* sectorcount */
  461. {
  462. register struct scg_cmd *scmd = scgp->scmd;
  463. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  464. scmd->addr = bp;
  465. scmd->size = size;
  466. scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
  467. /* scmd->flags = SCG_DISRE_ENA;*/
  468. scmd->cdb_len = SC_G1_CDBLEN;
  469. scmd->sense_len = CCS_SENSE_LEN;
  470. scmd->target = scgp->target;
  471. scmd->cdb.g1_cdb.cmd = SC_EWRITE;
  472. scmd->cdb.g1_cdb.lun = scgp->lun;
  473. g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  474. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  475. scgp->cmdname = "write_g1";
  476. if (scsicmd(scgp) < 0)
  477. return (-1);
  478. return (size - scsigetresid(scgp));
  479. }
  480. EXPORT int
  481. write_xg5(scgp, bp, addr, size, cnt)
  482. SCSI *scgp;
  483. caddr_t bp; /* address of buffer */
  484. long addr; /* disk address (sector) to put */
  485. long size; /* number of bytes to transfer */
  486. int cnt; /* sectorcount */
  487. {
  488. register struct scg_cmd *scmd = scgp->scmd;
  489. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  490. scmd->addr = bp;
  491. scmd->size = size;
  492. scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
  493. /* scmd->flags = SCG_DISRE_ENA;*/
  494. scmd->cdb_len = SC_G5_CDBLEN;
  495. scmd->sense_len = CCS_SENSE_LEN;
  496. scmd->target = scgp->target;
  497. scmd->cdb.g5_cdb.cmd = 0xAA;
  498. scmd->cdb.g5_cdb.lun = scgp->lun;
  499. g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
  500. g5_cdblen(&scmd->cdb.g5_cdb, cnt);
  501. scgp->cmdname = "write_g5";
  502. if (scsicmd(scgp) < 0)
  503. return (-1);
  504. return (size - scsigetresid(scgp));
  505. }
  506. EXPORT int
  507. scsi_flush_cache(scgp)
  508. SCSI *scgp;
  509. {
  510. register struct scg_cmd *scmd = scgp->scmd;
  511. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  512. scmd->flags = SCG_DISRE_ENA;
  513. scmd->cdb_len = SC_G1_CDBLEN;
  514. scmd->sense_len = CCS_SENSE_LEN;
  515. scmd->target = scgp->target;
  516. scmd->timeout = 2 * 60; /* Max: sizeof(CDR-cache)/150KB/s */
  517. scmd->cdb.g1_cdb.cmd = 0x35;
  518. scmd->cdb.g1_cdb.lun = scgp->lun;
  519. scgp->cmdname = "flush cache";
  520. if (scsicmd(scgp) < 0)
  521. return (-1);
  522. return (0);
  523. }
  524. EXPORT int
  525. read_buffer(scgp, bp, cnt, mode)
  526. SCSI *scgp;
  527. caddr_t bp;
  528. int cnt;
  529. int mode;
  530. {
  531. register struct scg_cmd *scmd = scgp->scmd;
  532. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  533. scmd->addr = bp;
  534. scmd->size = cnt;
  535. scmd->dma_read = 1;
  536. scmd->cdb_len = SC_G1_CDBLEN;
  537. scmd->sense_len = CCS_SENSE_LEN;
  538. scmd->target = scgp->target;
  539. scmd->cdb.g1_cdb.cmd = 0x3C; /* Read Buffer */
  540. scmd->cdb.g1_cdb.lun = scgp->lun;
  541. scmd->cdb.cmd_cdb[1] |= (mode & 7);
  542. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  543. scgp->cmdname = "read buffer";
  544. return (scsicmd(scgp));
  545. }
  546. EXPORT int
  547. read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
  548. SCSI *scgp;
  549. caddr_t bp;
  550. int track;
  551. int cnt;
  552. int msf;
  553. int subq;
  554. int fmt;
  555. {
  556. register struct scg_cmd *scmd = scgp->scmd;
  557. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  558. scmd->addr = bp;
  559. scmd->size = cnt;
  560. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  561. scmd->cdb_len = SC_G1_CDBLEN;
  562. scmd->sense_len = CCS_SENSE_LEN;
  563. scmd->target = scgp->target;
  564. scmd->cdb.g1_cdb.cmd = 0x42;
  565. scmd->cdb.g1_cdb.lun = scgp->lun;
  566. if (msf)
  567. scmd->cdb.g1_cdb.res = 1;
  568. if (subq)
  569. scmd->cdb.g1_cdb.addr[0] = 0x40;
  570. scmd->cdb.g1_cdb.addr[1] = fmt;
  571. scmd->cdb.g1_cdb.res6 = track;
  572. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  573. scgp->cmdname = "read subchannel";
  574. if (scsicmd(scgp) < 0)
  575. return (-1);
  576. return (0);
  577. }
  578. EXPORT int
  579. read_toc(scgp, bp, track, cnt, msf, fmt)
  580. SCSI *scgp;
  581. caddr_t bp;
  582. int track;
  583. int cnt;
  584. int msf;
  585. int fmt;
  586. {
  587. register struct scg_cmd *scmd = scgp->scmd;
  588. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  589. scmd->addr = bp;
  590. scmd->size = cnt;
  591. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  592. scmd->cdb_len = SC_G1_CDBLEN;
  593. scmd->sense_len = CCS_SENSE_LEN;
  594. scmd->target = scgp->target;
  595. scmd->cdb.g1_cdb.cmd = 0x43;
  596. scmd->cdb.g1_cdb.lun = scgp->lun;
  597. if (msf)
  598. scmd->cdb.g1_cdb.res = 1;
  599. scmd->cdb.g1_cdb.addr[0] = fmt & 0x0F;
  600. scmd->cdb.g1_cdb.res6 = track;
  601. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  602. scgp->cmdname = "read toc";
  603. if (scsicmd(scgp) < 0)
  604. return (-1);
  605. return (0);
  606. }
  607. EXPORT int
  608. read_toc_philips(scgp, bp, track, cnt, msf, fmt)
  609. SCSI *scgp;
  610. caddr_t bp;
  611. int track;
  612. int cnt;
  613. int msf;
  614. int fmt;
  615. {
  616. register struct scg_cmd *scmd = scgp->scmd;
  617. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  618. scmd->addr = bp;
  619. scmd->size = cnt;
  620. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  621. scmd->cdb_len = SC_G1_CDBLEN;
  622. scmd->sense_len = CCS_SENSE_LEN;
  623. scmd->target = scgp->target;
  624. scmd->timeout = 4 * 60; /* May last  174s on a TEAC CD-R55S */
  625. scmd->cdb.g1_cdb.cmd = 0x43;
  626. scmd->cdb.g1_cdb.lun = scgp->lun;
  627. if (msf)
  628. scmd->cdb.g1_cdb.res = 1;
  629. scmd->cdb.g1_cdb.res6 = track;
  630. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  631. if (fmt & 1)
  632. scmd->cdb.g1_cdb.vu_96 = 1;
  633. if (fmt & 2)
  634. scmd->cdb.g1_cdb.vu_97 = 1;
  635. scgp->cmdname = "read toc";
  636. if (scsicmd(scgp) < 0)
  637. return (-1);
  638. return (0);
  639. }
  640. EXPORT int
  641. read_header(scgp, bp, addr, cnt, msf)
  642. SCSI *scgp;
  643. caddr_t bp;
  644. long addr;
  645. int cnt;
  646. int msf;
  647. {
  648. register struct scg_cmd *scmd = scgp->scmd;
  649. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  650. scmd->addr = bp;
  651. scmd->size = cnt;
  652. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  653. scmd->cdb_len = SC_G1_CDBLEN;
  654. scmd->sense_len = CCS_SENSE_LEN;
  655. scmd->target = scgp->target;
  656. scmd->cdb.g1_cdb.cmd = 0x44;
  657. scmd->cdb.g1_cdb.lun = scgp->lun;
  658. if (msf)
  659. scmd->cdb.g1_cdb.res = 1;
  660. g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  661. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  662. scgp->cmdname = "read header";
  663. if (scsicmd(scgp) < 0)
  664. return (-1);
  665. return (0);
  666. }
  667. EXPORT int
  668. read_disk_info(scgp, bp, cnt)
  669. SCSI *scgp;
  670. caddr_t bp;
  671. int cnt;
  672. {
  673. register struct scg_cmd *scmd = scgp->scmd;
  674. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  675. scmd->addr = bp;
  676. scmd->size = cnt;
  677. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  678. scmd->cdb_len = SC_G1_CDBLEN;
  679. scmd->sense_len = CCS_SENSE_LEN;
  680. scmd->target = scgp->target;
  681. scmd->timeout = 4 * 60; /* Needs up to 2 minutes */
  682. scmd->cdb.g1_cdb.cmd = 0x51;
  683. scmd->cdb.g1_cdb.lun = scgp->lun;
  684. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  685. scgp->cmdname = "read disk info";
  686. if (scsicmd(scgp) < 0)
  687. return (-1);
  688. return (0);
  689. }
  690. EXPORT int
  691. read_track_info(scgp, bp, track, cnt)
  692. SCSI *scgp;
  693. caddr_t bp;
  694. int track;
  695. int cnt;
  696. {
  697. register struct scg_cmd *scmd = scgp->scmd;
  698. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  699. scmd->addr = bp;
  700. scmd->size = cnt;
  701. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  702. scmd->cdb_len = SC_G1_CDBLEN;
  703. scmd->sense_len = CCS_SENSE_LEN;
  704. scmd->target = scgp->target;
  705. scmd->timeout = 4 * 60; /* Needs up to 2 minutes */
  706. scmd->cdb.g1_cdb.cmd = 0x52;
  707. scmd->cdb.g1_cdb.lun = scgp->lun;
  708. scmd->cdb.g1_cdb.reladr = 1; /* Track */
  709. g1_cdbaddr(&scmd->cdb.g1_cdb, track);
  710. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  711. scgp->cmdname = "read track info";
  712. if (scsicmd(scgp) < 0)
  713. return (-1);
  714. return (0);
  715. }
  716. EXPORT int
  717. read_track_info_philips(scgp, bp, track, cnt)
  718. SCSI *scgp;
  719. caddr_t bp;
  720. int track;
  721. int cnt;
  722. {
  723. register struct scg_cmd *scmd = scgp->scmd;
  724. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  725. scmd->addr = bp;
  726. scmd->size = cnt;
  727. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  728. scmd->cdb_len = SC_G1_CDBLEN;
  729. scmd->sense_len = CCS_SENSE_LEN;
  730. scmd->target = scgp->target;
  731. scmd->cdb.g1_cdb.cmd = 0xE5;
  732. scmd->cdb.g1_cdb.lun = scgp->lun;
  733. g1_cdbaddr(&scmd->cdb.g1_cdb, track);
  734. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  735. scgp->cmdname = "read track info";
  736. if (scsicmd(scgp) < 0)
  737. return (-1);
  738. return (0);
  739. }
  740. EXPORT int
  741. scsi_close_tr_session(scgp, type, track)
  742. SCSI *scgp;
  743. int type;
  744. int track;
  745. {
  746. register struct scg_cmd *scmd = scgp->scmd;
  747. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  748. scmd->flags = SCG_DISRE_ENA;
  749. scmd->cdb_len = SC_G1_CDBLEN;
  750. scmd->sense_len = CCS_SENSE_LEN;
  751. scmd->target = scgp->target;
  752. scmd->timeout = 8 * 60; /* Needs up to 4 minutes */
  753. scmd->cdb.g1_cdb.cmd = 0x5B;
  754. scmd->cdb.g1_cdb.lun = scgp->lun;
  755. scmd->cdb.g1_cdb.addr[0] = type;
  756. scmd->cdb.g1_cdb.addr[3] = track;
  757. #ifdef nono
  758. scmd->cdb.g1_cdb.reladr = 1; /* IMM hack to test Mitsumi behaviour*/
  759. #endif
  760. scgp->cmdname = "close track/session";
  761. if (scsicmd(scgp) < 0)
  762. return (-1);
  763. return (0);
  764. }
  765. EXPORT int
  766. read_master_cue(scgp, bp, sheet, cnt)
  767. SCSI *scgp;
  768. caddr_t bp; /* address of master cue sheet */
  769. int sheet; /* Sheet number */
  770. int cnt; /* Transfer count */
  771. {
  772. register struct scg_cmd *scmd = scgp->scmd;
  773. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  774. scmd->addr = bp;
  775. scmd->size = cnt;
  776. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  777. scmd->cdb_len = SC_G1_CDBLEN;
  778. scmd->sense_len = CCS_SENSE_LEN;
  779. scmd->target = scgp->target;
  780. scmd->cdb.g1_cdb.cmd = 0x59; /* Read master cue */
  781. scmd->cdb.g1_cdb.lun = scgp->lun;
  782. scmd->cdb.g1_cdb.addr[2] = sheet;
  783. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  784. scgp->cmdname = "read master cue";
  785. if (scsicmd(scgp) < 0)
  786. return (-1);
  787. return (0);
  788. }
  789. EXPORT int
  790. send_cue_sheet(scgp, bp, size)
  791. SCSI *scgp;
  792. caddr_t bp; /* address of cue sheet buffer */
  793. long size; /* number of bytes to transfer */
  794. {
  795. register struct scg_cmd *scmd = scgp->scmd;
  796. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  797. scmd->addr = bp;
  798. scmd->size = size;
  799. scmd->flags = SCG_DISRE_ENA;
  800. scmd->cdb_len = SC_G1_CDBLEN;
  801. scmd->sense_len = CCS_SENSE_LEN;
  802. scmd->target = scgp->target;
  803. scmd->cdb.g1_cdb.cmd = 0x5D; /* Send CUE sheet */
  804. scmd->cdb.g1_cdb.lun = scgp->lun;
  805. g1_cdblen(&scmd->cdb.g1_cdb, size); 
  806. scgp->cmdname = "send_cue_sheet";
  807. if (scsicmd(scgp) < 0)
  808. return (-1);
  809. return (size - scmd->resid);
  810. }
  811. EXPORT int
  812. read_buff_cap(scgp, sp, fp)
  813. SCSI *scgp;
  814. long *sp; /* Size pointer */
  815. long *fp; /* Free pointer */
  816. {
  817. char resp[12];
  818. Ulong freespace;
  819. Ulong bufsize;
  820. int per;
  821. register struct scg_cmd *scmd = scgp->scmd;
  822. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  823. scmd->addr = (caddr_t)resp;
  824. scmd->size = sizeof(resp);
  825. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  826. scmd->cdb_len = SC_G1_CDBLEN;
  827. scmd->sense_len = CCS_SENSE_LEN;
  828. scmd->target = scgp->target;
  829. scmd->cdb.g1_cdb.cmd = 0x5C; /* Read buffer cap */
  830. scmd->cdb.g1_cdb.lun = scgp->lun;
  831. g1_cdblen(&scmd->cdb.g1_cdb, sizeof(resp));
  832. scgp->cmdname = "read buffer cap";
  833. if (scsicmd(scgp) < 0)
  834. return (-1);
  835. bufsize   = a_to_u_4_byte(&resp[4]);
  836. freespace = a_to_u_4_byte(&resp[8]);
  837. if (sp)
  838. *sp = bufsize;
  839. if (fp)
  840. *fp = freespace;
  841. if (scgp->verbose || (sp == 0 && fp == 0))
  842. printf("BFree: %ld K BSize: %ld Kn", freespace >> 10, bufsize >> 10);
  843. if (bufsize == 0)
  844. return (0);
  845. per = (100 * (bufsize - freespace)) / bufsize;
  846. if (per < 0)
  847. return (0);
  848. if (per > 100)
  849. return (100);
  850. return (per);
  851. }
  852. EXPORT int
  853. scsi_blank(scgp, addr, blanktype)
  854. SCSI *scgp;
  855. long addr;
  856. int blanktype;
  857. {
  858. register struct scg_cmd *scmd = scgp->scmd;
  859. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  860. scmd->flags = SCG_DISRE_ENA;
  861. scmd->cdb_len = SC_G5_CDBLEN;
  862. scmd->sense_len = CCS_SENSE_LEN;
  863. scmd->target = scgp->target;
  864. scmd->timeout = 160 * 60; /* full blank at 1x could take 80 minutes */
  865. scmd->cdb.g5_cdb.cmd = 0xA1; /* Blank */
  866. scmd->cdb.g0_cdb.high_addr = blanktype;
  867. g1_cdbaddr(&scmd->cdb.g5_cdb, addr);
  868. scgp->cmdname = "blank unit";
  869. return (scsicmd(scgp));
  870. }
  871. /*
  872.  * XXX First try to handle ATAPI:
  873.  * XXX ATAPI cannot handle SCSI 6 byte commands.
  874.  * XXX We try to simulate 6 byte mode sense/select.
  875.  */
  876. LOCAL BOOL is_atapi;
  877. EXPORT BOOL
  878. allow_atapi(scgp, new)
  879. SCSI *scgp;
  880. BOOL new;
  881. {
  882. BOOL old = is_atapi;
  883. Uchar mode[256];
  884. if (new == old)
  885. return (old);
  886. scgp->silent++;
  887. if (new &&
  888.     mode_sense_g1(scgp, mode, 8, 0x3F, 0) < 0) { /* All pages current */
  889. new = FALSE;
  890. }
  891. scgp->silent--;
  892. is_atapi = new;
  893. return (old);
  894. }
  895. EXPORT int
  896. mode_select(scgp, dp, cnt, smp, pf)
  897. SCSI *scgp;
  898. Uchar *dp;
  899. int cnt;
  900. int smp;
  901. int pf;
  902. {
  903. if (is_atapi)
  904. return (mode_select_sg0(scgp, dp, cnt, smp, pf));
  905. return (mode_select_g0(scgp, dp, cnt, smp, pf));
  906. }
  907. EXPORT int
  908. mode_sense(scgp, dp, cnt, page, pcf)
  909. SCSI *scgp;
  910. Uchar *dp;
  911. int cnt;
  912. int page;
  913. int pcf;
  914. {
  915. if (is_atapi)
  916. return (mode_sense_sg0(scgp, dp, cnt, page, pcf));
  917. return (mode_sense_g0(scgp, dp, cnt, page, pcf));
  918. }
  919. /*
  920.  * Simulate mode select g0 with mode select g1.
  921.  */
  922. EXPORT int
  923. mode_select_sg0(scgp, dp, cnt, smp, pf)
  924. SCSI *scgp;
  925. Uchar *dp;
  926. int cnt;
  927. int smp;
  928. int pf;
  929. {
  930. Uchar xmode[256+4];
  931. int amt = cnt;
  932. if (amt < 1 || amt > 255) {
  933. /* XXX clear SCSI error codes ??? */
  934. return (-1);
  935. }
  936. if (amt < 4) { /* Data length. medium type & VU */
  937. amt += 1;
  938. } else {
  939. amt += 4;
  940. movebytes(&dp[4], &xmode[8], cnt-4);
  941. }
  942. xmode[0] = 0;
  943. xmode[1] = 0;
  944. xmode[2] = dp[1];
  945. xmode[3] = dp[2];
  946. xmode[4] = 0;
  947. xmode[5] = 0;
  948. i_to_2_byte(&xmode[6], (unsigned int)dp[3]);
  949. if (scgp->verbose) scsiprbytes("Mode Parameters (un-converted)", dp, cnt);
  950. return (mode_select_g1(scgp, xmode, amt, smp, pf));
  951. }
  952. /*
  953.  * Simulate mode sense g0 with mode sense g1.
  954.  */
  955. EXPORT int
  956. mode_sense_sg0(scgp, dp, cnt, page, pcf)
  957. SCSI *scgp;
  958. Uchar *dp;
  959. int cnt;
  960. int page;
  961. int pcf;
  962. {
  963. Uchar xmode[256+4];
  964. int amt = cnt;
  965. int len;
  966. if (amt < 1 || amt > 255) {
  967. /* XXX clear SCSI error codes ??? */
  968. return (-1);
  969. }
  970. fillbytes((caddr_t)xmode, sizeof(xmode), '');
  971. if (amt < 4) { /* Data length. medium type & VU */
  972. amt += 1;
  973. } else {
  974. amt += 4;
  975. }
  976. if (mode_sense_g1(scgp, xmode, amt, page, pcf) < 0)
  977. return (-1);
  978. amt = cnt - scsigetresid(scgp);
  979. if (amt > 4)
  980. movebytes(&xmode[8], &dp[4], amt-4);
  981. len = a_to_u_2_byte(xmode);
  982. if (len == 0) {
  983. dp[0] = 0;
  984. } else if (len < 6) {
  985. if (len > 2)
  986. len = 2;
  987. dp[0] = len;
  988. } else {
  989. dp[0] = len - 3;
  990. }
  991. dp[1] = xmode[2];
  992. dp[2] = xmode[3];
  993. len = a_to_u_2_byte(&xmode[6]);
  994. dp[3] = len;
  995. if (scgp->verbose) scsiprbytes("Mode Sense Data (converted)", dp, amt);
  996. return (0);
  997. }
  998. EXPORT int
  999. mode_select_g0(scgp, dp, cnt, smp, pf)
  1000. SCSI *scgp;
  1001. Uchar *dp;
  1002. int cnt;
  1003. int smp;
  1004. int pf;
  1005. {
  1006. register struct scg_cmd *scmd = scgp->scmd;
  1007. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  1008. scmd->addr = (caddr_t)dp;
  1009. scmd->size = cnt;
  1010. scmd->flags = SCG_DISRE_ENA;
  1011. scmd->cdb_len = SC_G0_CDBLEN;
  1012. scmd->sense_len = CCS_SENSE_LEN;
  1013. scmd->target = scgp->target;
  1014. scmd->cdb.g0_cdb.cmd = SC_MODE_SELECT;
  1015. scmd->cdb.g0_cdb.lun = scgp->lun;
  1016. scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
  1017. scmd->cdb.g0_cdb.count = cnt;
  1018. if (scgp->verbose) {
  1019. printf("%s ", smp?"Save":"Set ");
  1020. scsiprbytes("Mode Parameters", dp, cnt);
  1021. }
  1022. scgp->cmdname = "mode select g0";
  1023. return (scsicmd(scgp));
  1024. }
  1025. EXPORT int
  1026. mode_select_g1(scgp, dp, cnt, smp, pf)
  1027. SCSI *scgp;
  1028. Uchar *dp;
  1029. int cnt;
  1030. int smp;
  1031. int pf;
  1032. {
  1033. register struct scg_cmd *scmd = scgp->scmd;
  1034. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  1035. scmd->addr = (caddr_t)dp;
  1036. scmd->size = cnt;
  1037. scmd->flags = SCG_DISRE_ENA;
  1038. scmd->cdb_len = SC_G1_CDBLEN;
  1039. scmd->sense_len = CCS_SENSE_LEN;
  1040. scmd->target = scgp->target;
  1041. scmd->cdb.g1_cdb.cmd = 0x55;
  1042. scmd->cdb.g1_cdb.lun = scgp->lun;
  1043. scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
  1044. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  1045. if (scgp->verbose) {
  1046. printf("%s ", smp?"Save":"Set ");
  1047. scsiprbytes("Mode Parameters", dp, cnt);
  1048. }
  1049. scgp->cmdname = "mode select g1";
  1050. return (scsicmd(scgp));
  1051. }
  1052. EXPORT int
  1053. mode_sense_g0(scgp, dp, cnt, page, pcf)
  1054. SCSI *scgp;
  1055. Uchar *dp;
  1056. int cnt;
  1057. int page;
  1058. int pcf;
  1059. {
  1060. register struct scg_cmd *scmd = scgp->scmd;
  1061. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  1062. scmd->addr = (caddr_t)dp;
  1063. scmd->size = 0xFF;
  1064. scmd->size = cnt;
  1065. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1066. scmd->cdb_len = SC_G0_CDBLEN;
  1067. scmd->sense_len = CCS_SENSE_LEN;
  1068. scmd->target = scgp->target;
  1069. scmd->cdb.g0_cdb.cmd = SC_MODE_SENSE;
  1070. scmd->cdb.g0_cdb.lun = scgp->lun;
  1071. #ifdef nonono
  1072. scmd->cdb.g0_cdb.high_addr = 1<<4; /* DBD Disable Block desc. */
  1073. #endif
  1074. scmd->cdb.g0_cdb.mid_addr = (page&0x3F) | ((pcf<<6)&0xC0);
  1075. scmd->cdb.g0_cdb.count = page ? 0xFF : 24;
  1076. scmd->cdb.g0_cdb.count = cnt;
  1077. scgp->cmdname = "mode sense g0";
  1078. if (scsicmd(scgp) < 0)
  1079. return (-1);
  1080. if (scgp->verbose) scsiprbytes("Mode Sense Data", dp, cnt - scsigetresid(scgp));
  1081. return (0);
  1082. }
  1083. EXPORT int
  1084. mode_sense_g1(scgp, dp, cnt, page, pcf)
  1085. SCSI *scgp;
  1086. Uchar *dp;
  1087. int cnt;
  1088. int page;
  1089. int pcf;
  1090. {
  1091. register struct scg_cmd *scmd = scgp->scmd;
  1092. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  1093. scmd->addr = (caddr_t)dp;
  1094. scmd->size = cnt;
  1095. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1096. scmd->cdb_len = SC_G1_CDBLEN;
  1097. scmd->sense_len = CCS_SENSE_LEN;
  1098. scmd->target = scgp->target;
  1099. scmd->cdb.g1_cdb.cmd = 0x5A;
  1100. scmd->cdb.g1_cdb.lun = scgp->lun;
  1101. #ifdef nonono
  1102. scmd->cdb.g0_cdb.high_addr = 1<<4; /* DBD Disable Block desc. */
  1103. #endif
  1104. scmd->cdb.g1_cdb.addr[0] = (page&0x3F) | ((pcf<<6)&0xC0);
  1105. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  1106. scgp->cmdname = "mode sense g1";
  1107. if (scsicmd(scgp) < 0)
  1108. return (-1);
  1109. if (scgp->verbose) scsiprbytes("Mode Sense Data", dp, cnt - scsigetresid(scgp));
  1110. return (0);
  1111. }
  1112. struct tocheader {
  1113. Uchar len[2];
  1114. Uchar first;
  1115. Uchar last;
  1116. };
  1117. struct trackdesc {
  1118. Uchar res0;
  1119. #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
  1120. Ucbit control : 4;
  1121. Ucbit adr : 4;
  1122. #else /* Motorola byteorder */
  1123. Ucbit adr : 4;
  1124. Ucbit control : 4;
  1125. #endif
  1126. Uchar track;
  1127. Uchar res3;
  1128. Uchar addr[4];
  1129. };
  1130. struct diskinfo {
  1131. struct tocheader hd;
  1132. struct trackdesc desc[1];
  1133. };
  1134. struct siheader {
  1135. Uchar len[2];
  1136. Uchar finished;
  1137. Uchar unfinished;
  1138. };
  1139. struct sidesc {
  1140. Uchar sess_number;
  1141. Uchar res1;
  1142. Uchar track;
  1143. Uchar res3;
  1144. Uchar addr[4];
  1145. };
  1146. struct sinfo {
  1147. struct siheader hd;
  1148. struct sidesc desc[1];
  1149. };
  1150. struct trackheader {
  1151. Uchar mode;
  1152. Uchar res[3];
  1153. Uchar addr[4];
  1154. };
  1155. #define TRM_ZERO 0
  1156. #define TRM_USER_ECC 1 /* 2048 bytes user data + 288 Bytes ECC/EDC */
  1157. #define TRM_USER 2 /* All user data (2336 bytes) */
  1158. struct ftrackdesc {
  1159. Uchar sess_number;
  1160. #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
  1161. Ucbit control : 4;
  1162. Ucbit adr : 4;
  1163. #else /* Motorola byteorder */
  1164. Ucbit adr : 4;
  1165. Ucbit control : 4;
  1166. #endif
  1167. Uchar track;
  1168. Uchar point;
  1169. Uchar amin;
  1170. Uchar asec;
  1171. Uchar aframe;
  1172. Uchar res7;
  1173. Uchar pmin;
  1174. Uchar psec;
  1175. Uchar pframe;
  1176. };
  1177. struct fdiskinfo {
  1178. struct tocheader hd;
  1179. struct ftrackdesc desc[1];
  1180. };
  1181. EXPORT int
  1182. read_tochdr(scgp, dp, fp, lp)
  1183. SCSI *scgp;
  1184. cdr_t *dp;
  1185. int *fp;
  1186. int *lp;
  1187. {
  1188. struct tocheader *tp;
  1189. char xb[256];
  1190. int len;
  1191. tp = (struct tocheader *)xb;
  1192. fillbytes((caddr_t)xb, sizeof(xb), '');
  1193. if (read_toc(scgp, xb, 0, sizeof(struct tocheader), 0, FMT_TOC) < 0) {
  1194. if (scgp->silent == 0)
  1195. errmsgno(EX_BAD, "Cannot read TOC headern");
  1196. return (-1);
  1197. }
  1198. len = a_to_u_2_byte(tp->len) + sizeof(struct tocheader)-2;
  1199. if (len >= 4) {
  1200. if (fp)
  1201. *fp = tp->first;
  1202. if (lp)
  1203. *lp = tp->last;
  1204. return (0);
  1205. }
  1206. return (-1);
  1207. }
  1208. EXPORT int
  1209. read_cdtext(scgp)
  1210. SCSI *scgp;
  1211. {
  1212. struct tocheader *tp;
  1213. char xb[256];
  1214. int len;
  1215. char xxb[10000];
  1216. tp = (struct tocheader *)xb;
  1217. fillbytes((caddr_t)xb, sizeof(xb), '');
  1218. if (read_toc(scgp, xb, 0, sizeof(struct tocheader), 0, FMT_CDTEXT) < 0) {
  1219. if (scgp->silent == 0 || scgp->verbose > 0)
  1220. errmsgno(EX_BAD, "Cannot read CD-Text headern");
  1221. return (-1);
  1222. }
  1223. len = a_to_u_2_byte(tp->len) + sizeof(struct tocheader)-2;
  1224. printf("CD-Text len: %dn", len);
  1225. if (read_toc(scgp, xxb, 0, len, 0, FMT_CDTEXT) < 0) {
  1226. if (scgp->silent == 0)
  1227. errmsgno(EX_BAD, "Cannot read CD-Textn");
  1228. return (-1);
  1229. }
  1230. {
  1231. FILE *f = fileopen("cdtext.dat", "wct");
  1232. filewrite(f, xxb, len);
  1233. }
  1234. return (0);
  1235. }
  1236. EXPORT int
  1237. read_trackinfo(scgp, track, offp, msfp, adrp, controlp, modep)
  1238. SCSI *scgp;
  1239. int track;
  1240. long *offp;
  1241. struct msf *msfp;
  1242. int *adrp;
  1243. int *controlp;
  1244. int *modep;
  1245. {
  1246. struct diskinfo *dp;
  1247. char xb[256];
  1248. int len;
  1249. dp = (struct diskinfo *)xb;
  1250. fillbytes((caddr_t)xb, sizeof(xb), '');
  1251. if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 0, FMT_TOC) < 0) {
  1252. if (scgp->silent <= 0)
  1253. errmsgno(EX_BAD, "Cannot read TOCn");
  1254. return (-1);
  1255. }
  1256. len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
  1257. if (len <  (int)sizeof(struct diskinfo))
  1258. return (-1);
  1259. if (offp)
  1260. *offp = a_to_4_byte(dp->desc[0].addr);
  1261. if (adrp)
  1262. *adrp = dp->desc[0].adr;
  1263. if (controlp)
  1264. *controlp = dp->desc[0].control;
  1265. if (msfp) {
  1266. scgp->silent++;
  1267. if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 1, FMT_TOC)
  1268. >= 0) {
  1269. msfp->msf_min = dp->desc[0].addr[1];
  1270. msfp->msf_sec = dp->desc[0].addr[2];
  1271. msfp->msf_frame = dp->desc[0].addr[3];
  1272. } else if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 0, FMT_TOC)
  1273. >= 0) {
  1274. /*
  1275.  * Some drives (e.g. the Philips CDD-522) don't support
  1276.  * to read the TOC in MSF mode.
  1277.  */
  1278. long off = a_to_4_byte(dp->desc[0].addr);
  1279. lba_to_msf(off, msfp);
  1280. } else {
  1281. msfp->msf_min = 0;
  1282. msfp->msf_sec = 0;
  1283. msfp->msf_frame = 0;
  1284. }
  1285. scgp->silent--;
  1286. }
  1287. if (modep == NULL)
  1288. return (0);
  1289. if (track == 0xAA) {
  1290. *modep = -1;
  1291. return (0);
  1292. }
  1293. fillbytes((caddr_t)xb, sizeof(xb), '');
  1294. scgp->silent++;
  1295. if (read_header(scgp, xb, *offp, 8, 0) >= 0) {
  1296. *modep = xb[0];
  1297. } else if (read_track_info_philips(scgp, xb, track, 14) >= 0) {
  1298. *modep = xb[0xb] & 0xF;
  1299. } else {
  1300. *modep = -1;
  1301. }
  1302. scgp->silent--;
  1303. return (0);
  1304. }
  1305. EXPORT int
  1306. read_B0(scgp, isbcd, b0p, lop)
  1307. SCSI *scgp;
  1308. BOOL isbcd;
  1309. long *b0p;
  1310. long *lop;
  1311. {
  1312. struct fdiskinfo *dp;
  1313. struct ftrackdesc *tp;
  1314. char xb[8192];
  1315. char *pe;
  1316. int len;
  1317. long l;
  1318. dp = (struct fdiskinfo *)xb;
  1319. fillbytes((caddr_t)xb, sizeof(xb), '');
  1320. if (read_toc_philips(scgp, xb, 1, sizeof(struct tocheader), 0, FMT_FULLTOC) < 0) {
  1321. return (-1);
  1322. }
  1323. len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
  1324. if (len <  (int)sizeof(struct fdiskinfo))
  1325. return (-1);
  1326. if (read_toc_philips(scgp, xb, 1, len, 0, FMT_FULLTOC) < 0) {
  1327. return (-1);
  1328. }
  1329. if (scgp->verbose) {
  1330. scsiprbytes("TOC data: ", (Uchar *)xb,
  1331. len > (int)sizeof(xb) - scsigetresid(scgp) ?
  1332. sizeof(xb) - scsigetresid(scgp) : len);
  1333. tp = &dp->desc[0];
  1334. pe = &xb[len];
  1335. while ((char *)tp < pe) {
  1336. scsiprbytes("ENT: ", (Uchar *)tp, 11);
  1337. tp++;
  1338. }
  1339. }
  1340. tp = &dp->desc[0];
  1341. pe = &xb[len];
  1342. for (; (char *)tp < pe; tp++) {
  1343. if (tp->sess_number != dp->hd.last)
  1344. continue;
  1345. if (tp->point != 0xB0)
  1346. continue;
  1347. if (scgp->verbose)
  1348. scsiprbytes("B0: ", (Uchar *)tp, 11);
  1349. if (isbcd) {
  1350. l = msf_to_lba(from_bcd(tp->amin),
  1351. from_bcd(tp->asec),
  1352. from_bcd(tp->aframe));
  1353. } else {
  1354. l = msf_to_lba(tp->amin,
  1355. tp->asec,
  1356. tp->aframe);
  1357. }
  1358. if (b0p)
  1359. *b0p = l;
  1360. if (scgp->verbose)
  1361. printf("B0 start: %ldn", l);
  1362. if (isbcd) {
  1363. l = msf_to_lba(from_bcd(tp->pmin),
  1364. from_bcd(tp->psec),
  1365. from_bcd(tp->pframe));
  1366. } else {
  1367. l = msf_to_lba(tp->pmin,
  1368. tp->psec,
  1369. tp->pframe);
  1370. }
  1371. if (scgp->verbose)
  1372. printf("B0 lout: %ldn", l);
  1373. if (lop)
  1374. *lop = l;
  1375. return (0);
  1376. }
  1377. return (-1);
  1378. }
  1379. /*
  1380.  * Return address of first track in last session (SCSI-3/mmc version).
  1381.  */
  1382. EXPORT int
  1383. read_session_offset(scgp, offp)
  1384. SCSI *scgp;
  1385. long *offp;
  1386. {
  1387. struct diskinfo *dp;
  1388. char xb[256];
  1389. int len;
  1390. dp = (struct diskinfo *)xb;
  1391. fillbytes((caddr_t)xb, sizeof(xb), '');
  1392. if (read_toc(scgp, (caddr_t)xb, 0, sizeof(struct tocheader), 0, FMT_SINFO) < 0)
  1393. return (-1);
  1394. if (scgp->verbose)
  1395. scsiprbytes("tocheader: ",
  1396. (Uchar *)xb, sizeof(struct tocheader) - scsigetresid(scgp));
  1397. len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
  1398. if (len > (int)sizeof(xb)) {
  1399. errmsgno(EX_BAD, "Session info too big.n");
  1400. return (-1);
  1401. }
  1402. if (read_toc(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
  1403. return (-1);
  1404. if (scgp->verbose)
  1405. scsiprbytes("tocheader: ",
  1406. (Uchar *)xb, len - scsigetresid(scgp));
  1407. dp = (struct diskinfo *)xb;
  1408. if (offp)
  1409. *offp = a_to_u_4_byte(dp->desc[0].addr);
  1410. return (0);
  1411. }
  1412. /*
  1413.  * Return address of first track in last session (pre SCSI-3 version).
  1414.  */
  1415. EXPORT int
  1416. read_session_offset_philips(scgp, offp)
  1417. SCSI *scgp;
  1418. long *offp;
  1419. {
  1420. struct sinfo *sp;
  1421. char xb[256];
  1422. int len;
  1423. sp = (struct sinfo *)xb;
  1424. fillbytes((caddr_t)xb, sizeof(xb), '');
  1425. if (read_toc_philips(scgp, (caddr_t)xb, 0, sizeof(struct siheader), 0, FMT_SINFO) < 0)
  1426. return (-1);
  1427. len = a_to_u_2_byte(sp->hd.len) + sizeof(struct siheader)-2;
  1428. if (len > (int)sizeof(xb)) {
  1429. errmsgno(EX_BAD, "Session info too big.n");
  1430. return (-1);
  1431. }
  1432. if (read_toc_philips(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
  1433. return (-1);
  1434. /*
  1435.  * Old drives return the number of finished sessions in first/finished
  1436.  * a descriptor is returned for each session. 
  1437.  * New drives return the number of the first and last session
  1438.  * one descriptor for the last finished session is returned
  1439.  * as in SCSI-3
  1440.  * In all cases the lowest session number is set to 1.
  1441.  */
  1442. sp = (struct sinfo *)xb;
  1443. if (offp)
  1444. *offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr);
  1445. return (0);
  1446. }
  1447. EXPORT int
  1448. sense_secsize(scgp, current)
  1449. SCSI *scgp;
  1450. int current;
  1451. {
  1452. Uchar mode[0x100];
  1453. Uchar *p;
  1454. Uchar *ep;
  1455. int secsize = -1;
  1456. scgp->silent++;
  1457. (void)unit_ready(scgp);
  1458. scgp->silent--;
  1459. /* XXX Quick and dirty, musz verallgemeinert werden !!! */
  1460. fillbytes(mode, sizeof(mode), '');
  1461. scgp->silent++;
  1462. if (mode_sense(scgp, mode, 0xFF, 0x3F, current?0:2) < 0) { /* All Pages */
  1463. fillbytes(mode, sizeof(mode), '');
  1464. if (mode_sense(scgp, mode, 0xFF, 0, current?0:2) < 0) {/* VU (block desc) */
  1465. scgp->silent--;
  1466. return (-1);
  1467. }
  1468. }
  1469. scgp->silent--;
  1470. ep = mode+mode[0]; /* Points to last byte of data */
  1471. p = &mode[4];
  1472. p += mode[3];
  1473. if (scgp->debug) {
  1474. printf("Pages: ");
  1475. while (p < ep) {
  1476. printf("0x%x ", *p&0x3F);
  1477. p += p[1]+2;
  1478. }
  1479. printf("n");
  1480. }
  1481. if (mode[3] == 8) {
  1482. if (scgp->debug) {
  1483. printf("Density: 0x%xn", mode[4]);
  1484. printf("Blocks:  %ldn", a_to_u_3_byte(&mode[5]));
  1485. printf("Blocklen:%ldn", a_to_u_3_byte(&mode[9]));
  1486. }
  1487. secsize = a_to_u_3_byte(&mode[9]);
  1488. }
  1489. return (secsize);
  1490. }
  1491. EXPORT int
  1492. select_secsize(scgp, secsize)
  1493. SCSI *scgp;
  1494. int secsize;
  1495. {
  1496. struct scsi_mode_data md;
  1497. int count = sizeof(struct scsi_mode_header) +
  1498. sizeof(struct scsi_mode_blockdesc);
  1499. (void)test_unit_ready(scgp); /* clear any error situation */
  1500. fillbytes((caddr_t)&md, sizeof(md), '');
  1501. md.header.blockdesc_len = 8;
  1502. i_to_3_byte(md.blockdesc.lblen, secsize);
  1503. return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
  1504. }
  1505. EXPORT BOOL
  1506. is_cddrive(scgp)
  1507. SCSI *scgp;
  1508. {
  1509. return (scgp->inq->type == INQ_ROMD || scgp->inq->type == INQ_WORM);
  1510. }
  1511. EXPORT BOOL
  1512. is_unknown_dev(scgp)
  1513. SCSI *scgp;
  1514. {
  1515. return (scgp->dev == DEV_UNKNOWN);
  1516. }
  1517. #define DEBUG
  1518. #ifdef DEBUG
  1519. #define G0_MAXADDR 0x1FFFFFL
  1520. EXPORT int
  1521. read_scsi(scgp, bp, addr, cnt)
  1522. SCSI *scgp;
  1523. caddr_t bp;
  1524. long addr;
  1525. int cnt;
  1526. {
  1527. if(addr <= G0_MAXADDR && cnt < 256 && !is_atapi)
  1528. return (read_g0(scgp, bp, addr, cnt));
  1529. else
  1530. return (read_g1(scgp, bp, addr, cnt));
  1531. }
  1532. EXPORT int
  1533. read_g0(scgp, bp, addr, cnt)
  1534. SCSI *scgp;
  1535. caddr_t bp;
  1536. long addr;
  1537. int cnt;
  1538. {
  1539. register struct scg_cmd *scmd = scgp->scmd;
  1540. if (scgp->cap->c_bsize <= 0)
  1541. raisecond("capacity_not_set", 0L);
  1542. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  1543. scmd->addr = bp;
  1544. scmd->size = cnt*scgp->cap->c_bsize;
  1545. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1546. scmd->cdb_len = SC_G0_CDBLEN;
  1547. scmd->sense_len = CCS_SENSE_LEN;
  1548. scmd->target = scgp->target;
  1549. scmd->cdb.g0_cdb.cmd = SC_READ;
  1550. scmd->cdb.g0_cdb.lun = scgp->lun;
  1551. g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
  1552. scmd->cdb.g0_cdb.count = cnt;
  1553. /* scmd->cdb.g0_cdb.vu_56 = 1;*/
  1554. scgp->cmdname = "read_g0";
  1555. return (scsicmd(scgp));
  1556. }
  1557. EXPORT int
  1558. read_g1(scgp, bp, addr, cnt)
  1559. SCSI *scgp;
  1560. caddr_t bp;
  1561. long addr;
  1562. int cnt;
  1563. {
  1564. register struct scg_cmd *scmd = scgp->scmd;
  1565. if (scgp->cap->c_bsize <= 0)
  1566. raisecond("capacity_not_set", 0L);
  1567. fillbytes((caddr_t)scmd, sizeof(*scmd), '');
  1568. scmd->addr = bp;
  1569. scmd->size = cnt*scgp->cap->c_bsize;
  1570. scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1571. scmd->cdb_len = SC_G1_CDBLEN;
  1572. scmd->sense_len = CCS_SENSE_LEN;
  1573. scmd->target = scgp->target;
  1574. scmd->cdb.g1_cdb.cmd = SC_EREAD;
  1575. scmd->cdb.g1_cdb.lun = scgp->lun;
  1576. g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  1577. g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  1578. scgp->cmdname = "read_g1";
  1579. return (scsicmd(scgp));
  1580. }
  1581. #endif /* DEBUG */
  1582. EXPORT BOOL
  1583. getdev(scgp, print)
  1584. SCSI *scgp;
  1585. BOOL print;
  1586. {
  1587.  BOOL got_inquiry = TRUE;
  1588.  char vendor_info[8+1];
  1589.  char prod_ident[16+1];
  1590.  char prod_revision[4+1];
  1591.  int inq_len = 0;
  1592. register struct scg_cmd *scmd = scgp->scmd;
  1593. register struct scsi_inquiry *inq = scgp->inq;
  1594. fillbytes((caddr_t)inq, sizeof(*inq), '');
  1595. scgp->dev = DEV_UNKNOWN;
  1596. scgp->silent++;
  1597. (void)unit_ready(scgp);
  1598. if (scmd->error >= SCG_FATAL &&
  1599. !(scmd->scb.chk && scmd->sense_count > 0)) {
  1600. scgp->silent--;
  1601. return (FALSE);
  1602. }
  1603. /* if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/
  1604. if (inquiry(scgp, (caddr_t)inq, sizeof(*inq)) < 0) {
  1605. got_inquiry = FALSE;
  1606. } else {
  1607. inq_len = sizeof(*inq) - scsigetresid(scgp);
  1608. }
  1609. if (!got_inquiry) {
  1610. if (scgp->verbose) {
  1611. printf(
  1612. "error: %d scb.chk: %d sense_count: %d sense.code: 0x%xn",
  1613. scmd->error, scmd->scb.chk,
  1614. scmd->sense_count, scmd->sense.code);
  1615. }
  1616. /*
  1617.  * Folgende Kontroller kennen das Kommando
  1618.  * INQUIRY nicht:
  1619.  *
  1620.  * ADAPTEC ACB-4000, ACB-4010, ACB 4070
  1621.  * SYSGEN SC4000
  1622.  *
  1623.  * Leider reagieren ACB40X0 und ACB5500 identisch
  1624.  * wenn drive not ready (code == not ready),
  1625.  * sie sind dann nicht zu unterscheiden.
  1626.  */
  1627. if (scmd->scb.chk && scmd->sense_count == 4) {
  1628. /* Test auf SYSGEN  */
  1629. (void)qic02(scgp, 0x12); /* soft lock on  */
  1630. if (qic02(scgp, 1) < 0) { /* soft lock off */
  1631. scgp->dev = DEV_ACB40X0;
  1632. /* scgp->dev = acbdev();*/
  1633. } else {
  1634. scgp->dev = DEV_SC4000;
  1635. inq->type = INQ_SEQD;
  1636. inq->removable = 1;
  1637. }
  1638. }
  1639. } else if (scgp->verbose) {
  1640. int i;
  1641. int len = inq->add_len + 5;
  1642. Uchar ibuf[256+5];
  1643. Uchar *ip = (Uchar *)inq;
  1644. Uchar c;
  1645. if (len > (int)sizeof (*inq) &&
  1646. inquiry(scgp, (caddr_t)ibuf, inq->add_len+5) >= 0) {
  1647. len = inq->add_len+5 - scsigetresid(scgp);
  1648. ip = ibuf;
  1649. } else {
  1650. len = sizeof (*inq);
  1651. }
  1652. printf("Inquiry Data   : ");
  1653. for (i = 0; i < len; i++) {
  1654. c = ip[i];
  1655. if (c >= ' ' && c < 0177)
  1656. printf("%c", c);
  1657. else
  1658. printf(".");
  1659. }
  1660. printf("n");
  1661. }
  1662. strncpy(vendor_info, inq->vendor_info, sizeof(inq->vendor_info));
  1663. strncpy(prod_ident, inq->prod_ident, sizeof(inq->prod_ident));
  1664. strncpy(prod_revision, inq->prod_revision, sizeof(inq->prod_revision));
  1665. vendor_info[sizeof(inq->vendor_info)] = '';
  1666. prod_ident[sizeof(inq->prod_ident)] = '';
  1667. prod_revision[sizeof(inq->prod_revision)] = '';
  1668. switch (inq->type) {
  1669. case INQ_DASD:
  1670. if (inq->add_len == 0 && inq->vendor_info[0] != '') {
  1671. Uchar *p;
  1672. /*
  1673.  * NT-4.0 creates fake inquiry data for IDE disks.
  1674.  * Unfortunately, it does not set add_len wo we
  1675.  * check if vendor_info, prod_ident and prod_revision
  1676.  * contains valid chars for a CCS inquiry.
  1677.  */
  1678. if (inq_len >= 36)
  1679. inq->add_len = 31;
  1680. for (p = (Uchar *)&inq->vendor_info[0];
  1681. p < (Uchar *)&inq->prod_revision[4];
  1682. p++) {
  1683. if (*p < 0x20 || *p > 0x7E) {
  1684. inq->add_len = 0;
  1685. break;
  1686. }
  1687. }
  1688. }
  1689. if (inq->add_len == 0) {
  1690. if (scgp->dev == DEV_UNKNOWN && got_inquiry) {
  1691. scgp->dev = DEV_ACB5500;
  1692. strcpy(inq->vendor_info,
  1693. "ADAPTEC ACB-5500        FAKE");
  1694. } else switch (scgp->dev) {
  1695. case DEV_ACB40X0:
  1696. strcpy(inq->vendor_info,
  1697. "ADAPTEC ACB-40X0        FAKE");
  1698. break;
  1699. case DEV_ACB4000:
  1700. strcpy(inq->vendor_info,
  1701. "ADAPTEC ACB-4000        FAKE");
  1702. break;
  1703. case DEV_ACB4010:
  1704. strcpy(inq->vendor_info,
  1705. "ADAPTEC ACB-4010        FAKE");
  1706. break;
  1707. case DEV_ACB4070:
  1708. strcpy(inq->vendor_info,
  1709. "ADAPTEC ACB-4070        FAKE");
  1710. break;
  1711. }
  1712. } else if (inq->add_len < 31) {
  1713. scgp->dev = DEV_NON_CCS_DSK;
  1714. } else if (strbeg("EMULEX", vendor_info)) {
  1715. if (strbeg("MD21", prod_ident))
  1716. scgp->dev = DEV_MD21;
  1717. if (strbeg("MD23", prod_ident))
  1718. scgp->dev = DEV_MD23;
  1719. else
  1720. scgp->dev = DEV_CCS_GENDISK;
  1721. } else if (strbeg("ADAPTEC", vendor_info)) {
  1722. if (strbeg("ACB-4520", prod_ident))
  1723. scgp->dev = DEV_ACB4520A;
  1724. if (strbeg("ACB-4525", prod_ident))
  1725. scgp->dev = DEV_ACB4525;
  1726. else
  1727. scgp->dev = DEV_CCS_GENDISK;
  1728. } else if (strbeg("SONY", vendor_info) &&
  1729. strbeg("SMO-C501", prod_ident)) {
  1730. scgp->dev = DEV_SONY_SMO;
  1731. } else {
  1732. scgp->dev = DEV_CCS_GENDISK;
  1733. }
  1734. break;
  1735. case INQ_SEQD:
  1736. if (scgp->dev == DEV_SC4000) {
  1737. strcpy(inq->vendor_info,
  1738. "SYSGEN  SC4000          FAKE");
  1739. } else if (inq->add_len == 0 &&
  1740. inq->removable &&
  1741. inq->ansi_version == 1) {
  1742. scgp->dev = DEV_MT02;
  1743. strcpy(inq->vendor_info,
  1744. "EMULEX  MT02            FAKE");
  1745. }
  1746. break;
  1747. /* case INQ_OPTD:*/
  1748. case INQ_ROMD:
  1749. case INQ_WORM:
  1750. if (strbeg("RXT-800S", prod_ident))
  1751. scgp->dev = DEV_RXT800S;
  1752. /*
  1753.  * Start of CD-Recorders:
  1754.  */
  1755. if (strbeg("ACER", vendor_info)) { 
  1756. if (strbeg("CR-4020C", prod_ident)) 
  1757.                                 scgp->dev = DEV_RICOH_RO_1420C;
  1758. } else if (strbeg("CREATIVE", vendor_info)) { 
  1759. if (strbeg("CDR2000", prod_ident))
  1760. scgp->dev = DEV_RICOH_RO_1060C;
  1761. } else if (strbeg("GRUNDIG", vendor_info)) { 
  1762. if (strbeg("CDR100IPW", prod_ident))
  1763. scgp->dev = DEV_CDD_2000;
  1764. } else if (strbeg("JVC", vendor_info)) {
  1765. if (strbeg("XR-W2001", prod_ident))
  1766. scgp->dev = DEV_TEAC_CD_R50S;
  1767. else if (strbeg("XR-W2010", prod_ident))
  1768. scgp->dev = DEV_TEAC_CD_R50S;
  1769. else if (strbeg("R2626", prod_ident))
  1770. scgp->dev = DEV_TEAC_CD_R50S;
  1771. } else if (strbeg("MITSBISH", vendor_info)) {
  1772. #ifdef XXXX_REALLY
  1773. /* It's MMC compliant */
  1774. if (strbeg("CDRW226", prod_ident))
  1775. scgp->dev = DEV_MMC_CDRW;
  1776. #endif
  1777. } else if (strbeg("MITSUMI", vendor_info)) {
  1778. /* Don't know any product string */
  1779. scgp->dev = DEV_CDD_522;
  1780. } else if (strbeg("OPTIMA", vendor_info)) {
  1781. if (strbeg("CD-R 650", prod_ident))
  1782. scgp->dev = DEV_SONY_CDU_924;
  1783. } else if (strbeg("PHILIPS", vendor_info) ||
  1784. strbeg("IMS", vendor_info) ||
  1785. strbeg("KODAK", vendor_info) ||
  1786. strbeg("HP", vendor_info)) {
  1787. if (strbeg("CDD521/00", prod_ident))
  1788. scgp->dev = DEV_CDD_521_OLD;
  1789. else if (strbeg("CDD521/02", prod_ident))
  1790. scgp->dev = DEV_CDD_521_OLD; /* PCD 200R? */
  1791. else if (strbeg("CDD521", prod_ident))
  1792. scgp->dev = DEV_CDD_521;
  1793. if (strbeg("CDD522", prod_ident))
  1794. scgp->dev = DEV_CDD_522;
  1795. if (strbeg("PCD225", prod_ident))
  1796. scgp->dev = DEV_CDD_522;
  1797. if (strbeg("KHSW/OB", prod_ident)) /* PCD600 */
  1798. scgp->dev = DEV_PCD_600;
  1799. if (strbeg("CDR-240", prod_ident))
  1800. scgp->dev = DEV_CDD_2000;
  1801. if (strbeg("CDD20", prod_ident))
  1802. scgp->dev = DEV_CDD_2000;
  1803. if (strbeg("CDD26", prod_ident))
  1804. scgp->dev = DEV_CDD_2600;
  1805. if (strbeg("C4324/C4325", prod_ident))
  1806. scgp->dev = DEV_CDD_2000;
  1807. if (strbeg("CD-Writer 6020", prod_ident))
  1808. scgp->dev = DEV_CDD_2600;
  1809. } else if (strbeg("PINNACLE", vendor_info)) {
  1810. if (strbeg("RCD-1000", prod_ident))
  1811. scgp->dev = DEV_TEAC_CD_R50S;
  1812. if (strbeg("RCD5020", prod_ident))
  1813. scgp->dev = DEV_TEAC_CD_R50S;
  1814. if (strbeg("RCD5040", prod_ident))
  1815. scgp->dev = DEV_TEAC_CD_R50S;
  1816. if (strbeg("RCD 4X4", prod_ident))
  1817. scgp->dev = DEV_TEAC_CD_R50S;
  1818. } else if (strbeg("PIONEER", vendor_info)) {
  1819. if (strbeg("CD-WO DW-S114X", prod_ident))
  1820. scgp->dev = DEV_PIONEER_DW_S114X;
  1821. else if (strbeg("DVD-R DVR-S101", prod_ident))
  1822. scgp->dev = DEV_PIONEER_DVDR_S101;
  1823. } else if (strbeg("PLASMON", vendor_info)) {
  1824. if (strbeg("RF4100", prod_ident))
  1825. scgp->dev = DEV_PLASMON_RF_4100;
  1826. else if (strbeg("CDR4220", prod_ident))
  1827. scgp->dev = DEV_CDD_2000;
  1828. } else if (strbeg("PLEXTOR", vendor_info)) {
  1829. if (strbeg("CD-R   PX-R24CS", prod_ident))
  1830. scgp->dev = DEV_RICOH_RO_1420C;
  1831. } else if (strbeg("RICOH", vendor_info)) {
  1832. if (strbeg("RO-1420C", prod_ident))
  1833. scgp->dev = DEV_RICOH_RO_1420C;
  1834. if (strbeg("RO1060C", prod_ident))
  1835. scgp->dev = DEV_RICOH_RO_1060C;
  1836. } else if (strbeg("SAF", vendor_info)) { /* Smart & Friendly */
  1837. if (strbeg("CD-R2004", prod_ident) ||
  1838.     strbeg("CD-R2006 ", prod_ident))
  1839. scgp->dev = DEV_SONY_CDU_924;
  1840. else if (strbeg("CD-R2006PLUS", prod_ident))
  1841. scgp->dev = DEV_TEAC_CD_R50S;
  1842. else if (strbeg("CD-RW226", prod_ident))
  1843. scgp->dev = DEV_TEAC_CD_R50S;
  1844. else if (strbeg("CD-R4012", prod_ident))
  1845. scgp->dev = DEV_TEAC_CD_R50S;
  1846. } else if (strbeg("SONY", vendor_info)) {
  1847. if (strbeg("CD-R   CDU92", prod_ident) ||
  1848.     strbeg("CD-R   CDU94", prod_ident))
  1849. scgp->dev = DEV_SONY_CDU_924;
  1850. } else if (strbeg("TEAC", vendor_info)) {
  1851. if (strbeg("CD-R50S", prod_ident) ||
  1852.     strbeg("CD-R55S", prod_ident))
  1853. scgp->dev = DEV_TEAC_CD_R50S;
  1854. } else if (strbeg("TRAXDATA", vendor_info) ||
  1855. strbeg("Traxdata", vendor_info)) {
  1856. if (strbeg("CDR4120", prod_ident))
  1857. scgp->dev = DEV_TEAC_CD_R50S;
  1858. } else if (strbeg("T.YUDEN", vendor_info)) {
  1859. if (strbeg("CD-WO EW-50", prod_ident))
  1860. scgp->dev = DEV_CDD_521;
  1861. } else if (strbeg("WPI", vendor_info)) { /* Wearnes */
  1862. if (strbeg("CDR-632P", prod_ident))
  1863. scgp->dev = DEV_CDD_2600;
  1864. } else if (strbeg("YAMAHA", vendor_info)) {
  1865. if (strbeg("CDR10", prod_ident))
  1866. scgp->dev = DEV_YAMAHA_CDR_100;
  1867. if (strbeg("CDR200", prod_ident))
  1868. scgp->dev = DEV_YAMAHA_CDR_400;
  1869. if (strbeg("CDR400", prod_ident))
  1870. scgp->dev = DEV_YAMAHA_CDR_400;
  1871. } else if (strbeg("MATSHITA", vendor_info)) {
  1872. if (strbeg("CD-R   CW-7501", prod_ident))
  1873. scgp->dev = DEV_MATSUSHITA_7501;
  1874. if (strbeg("CD-R   CW-7502", prod_ident))
  1875. scgp->dev = DEV_MATSUSHITA_7502;
  1876. }
  1877. if (scgp->dev == DEV_UNKNOWN) {
  1878. /*
  1879.  * We do not have Manufacturer strings for
  1880.  * the following drives.
  1881.  */
  1882. if (strbeg("CDS615E", prod_ident)) /* Olympus */
  1883. scgp->dev = DEV_SONY_CDU_924;
  1884. }
  1885. if (scgp->dev == DEV_UNKNOWN && inq->type == INQ_ROMD) {
  1886. BOOL cdrr  = FALSE;
  1887. BOOL cdwr  = FALSE;
  1888. BOOL cdrrw  = FALSE;
  1889. BOOL cdwrw  = FALSE;
  1890. BOOL dvd  = FALSE;
  1891. scgp->dev = DEV_CDROM;
  1892. if (mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, &dvd))
  1893. scgp->dev = DEV_MMC_CDROM;
  1894. if (cdwr)
  1895. scgp->dev = DEV_MMC_CDR;
  1896. if (cdwrw)
  1897. scgp->dev = DEV_MMC_CDRW;
  1898. if (dvd)
  1899. scgp->dev = DEV_MMC_DVD;
  1900. }
  1901. case INQ_PROCD:
  1902. if (strbeg("BERTHOLD", vendor_info)) {
  1903. if (strbeg("", prod_ident))
  1904. scgp->dev = DEV_HRSCAN;
  1905. }
  1906. break;
  1907. case INQ_SCAN:
  1908. scgp->dev = DEV_MS300A;
  1909. break;
  1910. }
  1911. scgp->silent--;
  1912. if (!print)
  1913. return (TRUE);
  1914. if (scgp->dev == DEV_UNKNOWN && !got_inquiry) {
  1915. #ifdef PRINT_INQ_ERR
  1916. scsiprinterr(scgp);
  1917. #endif
  1918. return (FALSE);
  1919. }
  1920. printf("Device type    : ");
  1921. scsiprintdev(inq);
  1922. printf("Version        : %dn", inq->ansi_version);
  1923. printf("Response Format: %dn", inq->data_format);
  1924. if (inq->data_format >= 2) {
  1925. printf("Capabilities   : ");
  1926. if (inq->aenc) printf("AENC ");
  1927. if (inq->termiop) printf("TERMIOP ");
  1928. if (inq->reladr) printf("RELADR ");
  1929. if (inq->wbus32) printf("WBUS32 ");
  1930. if (inq->wbus16) printf("WBUS16 ");
  1931. if (inq->sync) printf("SYNC ");
  1932. if (inq->linked) printf("LINKED ");
  1933. if (inq->cmdque) printf("CMDQUE ");
  1934. if (inq->softreset) printf("SOFTRESET ");
  1935. printf("n");
  1936. }
  1937. if (inq->add_len >= 31 ||
  1938. inq->info[0] || inq->ident[0] || inq->revision[0]) {
  1939. printf("Vendor_info    : '%.8s'n", inq->info);
  1940. printf("Identifikation : '%.16s'n", inq->ident);
  1941. printf("Revision       : '%.4s'n", inq->revision);
  1942. }
  1943. return (TRUE);
  1944. }
  1945. EXPORT void
  1946. printdev(scgp)
  1947. SCSI *scgp;
  1948. {
  1949. printf("Device seems to be: ");
  1950. switch (scgp->dev) {
  1951. case DEV_UNKNOWN: printf("unknown"); break;
  1952. case DEV_ACB40X0: printf("Adaptec 4000/4010/4070");break;
  1953. case DEV_ACB4000: printf("Adaptec 4000"); break;
  1954. case DEV_ACB4010: printf("Adaptec 4010"); break;
  1955. case DEV_ACB4070: printf("Adaptec 4070"); break;
  1956. case DEV_ACB5500: printf("Adaptec 5500"); break;
  1957. case DEV_ACB4520A: printf("Adaptec 4520A"); break;
  1958. case DEV_ACB4525: printf("Adaptec 4525"); break;
  1959. case DEV_MD21: printf("Emulex MD21"); break;
  1960. case DEV_MD23: printf("Emulex MD23"); break;
  1961. case DEV_NON_CCS_DSK: printf("Generic NON CCS Disk"); break;
  1962. case DEV_CCS_GENDISK: printf("Generic CCS Disk"); break;
  1963. case DEV_SONY_SMO: printf("Sony SMO-C501"); break;
  1964. case DEV_MT02: printf("Emulex MT02"); break;
  1965. case DEV_SC4000: printf("Sysgen SC4000"); break;
  1966. case DEV_RXT800S: printf("Maxtor RXT800S"); break;
  1967. case DEV_HRSCAN: printf("Berthold HR-Scanner"); break;
  1968. case DEV_MS300A: printf("Microtek MS300A"); break;
  1969. case DEV_CDROM: printf("Generic CD-ROM"); break;
  1970. case DEV_MMC_CDROM: printf("Generic mmc CD-ROM"); break;
  1971. case DEV_MMC_CDR: printf("Generic mmc CD-R"); break;
  1972. case DEV_MMC_CDRW: printf("Generic mmc CD-RW"); break;
  1973. case DEV_MMC_DVD: printf("Generic mmc2 DVD"); break;
  1974. case DEV_CDD_521_OLD: printf("Philips old CDD-521"); break;
  1975. case DEV_CDD_521: printf("Philips CDD-521"); break;
  1976. case DEV_CDD_522: printf("Philips CDD-522"); break;
  1977. case DEV_PCD_600: printf("Kodak PCD-600"); break;
  1978. case DEV_CDD_2000: printf("Philips CDD-2000"); break;
  1979. case DEV_CDD_2600: printf("Philips CDD-2600"); break;
  1980. case DEV_YAMAHA_CDR_100:printf("Yamaha CDR-100"); break;
  1981. case DEV_YAMAHA_CDR_400:printf("Yamaha CDR-400"); break;
  1982. case DEV_PLASMON_RF_4100:printf("Plasmon RF-4100"); break;
  1983. case DEV_SONY_CDU_924: printf("Sony CDU-924S"); break;
  1984. case DEV_RICOH_RO_1060C:printf("Ricoh RO-1060C"); break;
  1985. case DEV_RICOH_RO_1420C:printf("Ricoh RO-1420C"); break;
  1986. case DEV_TEAC_CD_R50S: printf("Teac CD-R50S"); break;
  1987. case DEV_MATSUSHITA_7501:printf("Matsushita CW-7501"); break;
  1988. case DEV_MATSUSHITA_7502:printf("Matsushita CW-7502"); break;
  1989. case DEV_PIONEER_DW_S114X: printf("Pioneer DW-S114X"); break;
  1990. case DEV_PIONEER_DVDR_S101:printf("Pioneer DVD-R S101");break;
  1991. default: printf("Missing Entry for dev %d",
  1992. scgp->dev); break;
  1993. }
  1994. printf(".n");
  1995. }
  1996. EXPORT BOOL
  1997. do_inquiry(scgp, print)
  1998. SCSI *scgp;
  1999. int print;
  2000. {
  2001. if (getdev(scgp, print)) {
  2002. if (print)
  2003. printdev(scgp);
  2004. return (TRUE);
  2005. } else {
  2006. return (FALSE);
  2007. }
  2008. }
  2009. EXPORT BOOL
  2010. recovery_needed(scgp)
  2011. SCSI *scgp;
  2012. {
  2013.  int err;
  2014. register struct scg_cmd *scmd = scgp->scmd;
  2015. scgp->silent++;
  2016. err = test_unit_ready(scgp);
  2017. scgp->silent--;
  2018. if (err >= 0)
  2019. return (FALSE);
  2020. else if (scmd->error >= SCG_FATAL) /* nicht selektierbar */
  2021. return (FALSE);
  2022. if (scmd->sense.code < 0x70) /* non extended Sense */
  2023. return (FALSE);
  2024. /* XXX Old Philips code */
  2025. return (((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0xD0);
  2026. }
  2027. EXPORT int
  2028. scsi_load(scgp)
  2029. SCSI *scgp;
  2030. {
  2031. return (scsi_start_stop_unit(scgp, 1, 1));
  2032. }
  2033. EXPORT int
  2034. scsi_unload(scgp)
  2035. SCSI *scgp;
  2036. {
  2037. return (scsi_start_stop_unit(scgp, 0, 1));
  2038. }
  2039. EXPORT int
  2040. scsi_cdr_write(scgp, bp, sectaddr, size, blocks, islast)
  2041. SCSI *scgp;
  2042. caddr_t bp; /* address of buffer */
  2043. long sectaddr; /* disk address (sector) to put */
  2044. long size; /* number of bytes to transfer */
  2045. int blocks; /* sector count */
  2046. BOOL islast; /* last write for track */
  2047. {
  2048. return (write_xg1(scgp, bp, sectaddr, size, blocks));
  2049. }
  2050. EXPORT struct cd_mode_page_2A *
  2051. mmc_cap(scgp, modep)
  2052. SCSI *scgp;
  2053. Uchar *modep;
  2054. {
  2055. int len;
  2056. int val;
  2057. Uchar mode[0x100];
  2058. struct cd_mode_page_2A *mp;
  2059. struct cd_mode_page_2A *mp2;
  2060. retry:
  2061. fillbytes((caddr_t)mode, sizeof(mode), '');
  2062. if (!get_mode_params(scgp, 0x2A, "CD capabilities",
  2063. mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
  2064. if (scsi_sense_key(scgp) == SC_NOT_READY) {
  2065. if (wait_unit_ready(scgp, 60))
  2066. goto retry;
  2067. }
  2068. return (NULL); /* Pre SCSI-3/mmc drive   */
  2069. }
  2070. if (len == 0) /* Pre SCSI-3/mmc drive   */
  2071. return (NULL);
  2072. mp = (struct cd_mode_page_2A *)
  2073. (mode + sizeof(struct scsi_mode_header) +
  2074. ((struct scsi_mode_header *)mode)->blockdesc_len);
  2075. /*
  2076.  * Do some heuristics against pre SCSI-3/mmc VU page 2A
  2077.  * We should test for a minimum p_len of 0x14, but some
  2078.  * buggy CD-ROM readers ommit the write speed values.
  2079.  */
  2080. if (mp->p_len < 0x10)
  2081. return (NULL);
  2082. val = a_to_u_2_byte(mp->max_read_speed);
  2083. if (val != 0 && val < 176)
  2084. return (NULL);
  2085. val = a_to_u_2_byte(mp->cur_read_speed);
  2086. if (val != 0 && val < 176)
  2087. return (NULL);
  2088. len -= sizeof(struct scsi_mode_header) +
  2089. ((struct scsi_mode_header *)mode)->blockdesc_len;
  2090. if (modep)
  2091. mp2 = (struct cd_mode_page_2A *)modep;
  2092. else
  2093. mp2 = (struct cd_mode_page_2A *)malloc(len);
  2094. if (mp2)
  2095. movebytes(mp, mp2, len);
  2096. return (mp2);
  2097. }
  2098. EXPORT void
  2099. mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp)
  2100. struct cd_mode_page_2A *mp;
  2101. BOOL *cdrrp;
  2102. BOOL *cdwrp;
  2103. BOOL *cdrrwp;
  2104. BOOL *cdwrwp;
  2105. BOOL *dvdp;
  2106. {
  2107. if (cdrrp)
  2108. *cdrrp = (mp->cd_r_read != 0); /* SCSI-3/mmc CD */
  2109. if (cdwrp)
  2110. *cdwrp = (mp->cd_r_write != 0); /* SCSI-3/mmc CD-R */
  2111. if (cdrrwp)
  2112. *cdrrwp = (mp->cd_rw_read != 0);/* SCSI-3/mmc CD */
  2113. if (cdwrwp)
  2114. *cdwrwp = (mp->cd_rw_write != 0);/* SCSI-3/mmc CD-RW */
  2115. if (dvdp) {
  2116. *dvdp =  /* SCSI-3/mmc2 DVD  */
  2117. (mp->dvd_ram_read + mp->dvd_r_read  + mp->dvd_rom_read +
  2118.  mp->dvd_ram_write + mp->dvd_r_write) != 0;
  2119. }
  2120. }
  2121. EXPORT BOOL
  2122. is_mmc(scgp, dvdp)
  2123. SCSI *scgp;
  2124. BOOL *dvdp;
  2125. {
  2126. return (mmc_check(scgp, NULL, NULL, NULL, NULL, dvdp));
  2127. }
  2128. EXPORT BOOL
  2129. mmc_check(scgp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp)
  2130. SCSI *scgp;
  2131. BOOL *cdrrp;
  2132. BOOL *cdwrp;
  2133. BOOL *cdrrwp;
  2134. BOOL *cdwrwp;
  2135. BOOL *dvdp;
  2136. {
  2137. Uchar mode[0x100];
  2138. BOOL was_atapi;
  2139. struct cd_mode_page_2A *mp;
  2140. if (scgp->inq->type != INQ_ROMD)
  2141. return (FALSE);
  2142. fillbytes((caddr_t)mode, sizeof(mode), '');
  2143. was_atapi = allow_atapi(scgp, TRUE);
  2144. scgp->silent++;
  2145. mp = mmc_cap(scgp, mode);
  2146. scgp->silent--;
  2147. allow_atapi(scgp, was_atapi);
  2148. if (mp == NULL)
  2149. return (FALSE);
  2150. mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp);
  2151. return (TRUE); /* Generic SCSI-3/mmc CD */
  2152. }
  2153. #define DOES(what,flag) printf("  Does %s%sn", flag?"":"not ",what);
  2154. #define IS(what,flag) printf("  Is %s%sn", flag?"":"not ",what);
  2155. #define VAL(what,val) printf("  %s: %dn", what, val[0]*256 + val[1]);
  2156. #define SVAL(what,val) printf("  %s: %sn", what, val);
  2157. EXPORT void
  2158. print_capabilities(scgp)
  2159. SCSI *scgp;
  2160. {
  2161. BOOL was_atapi;
  2162. Uchar mode[0x100];
  2163. struct cd_mode_page_2A *mp;
  2164. static const char *bclk[4] = {"32", "16", "24", "24 (I2S)"};
  2165. static const char *load[8] = {"caddy", "tray", "pop-up", "reserved(3)",
  2166. "disc changer", "cartridge changer",
  2167. "reserved(6)", "reserved(7)" };
  2168. if (scgp->inq->type != INQ_ROMD)
  2169. return;
  2170. fillbytes((caddr_t)mode, sizeof(mode), '');
  2171. was_atapi = allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
  2172. scgp->silent++;
  2173. mp = mmc_cap(scgp, mode);
  2174. scgp->silent--;
  2175. allow_atapi(scgp, was_atapi);
  2176. if (mp == NULL)
  2177. return;
  2178. printf ("nDrive capabilities, per page 2A:nn");
  2179. DOES("read CD-R media", mp->cd_r_read);
  2180. DOES("write CD-R media", mp->cd_r_write);
  2181. DOES("read CD-RW media", mp->cd_rw_read);
  2182. DOES("write CD-RW media", mp->cd_rw_write);
  2183. DOES("read DVD-ROM media", mp->dvd_rom_read);
  2184. DOES("read DVD-R media", mp->dvd_r_read);
  2185. DOES("write DVD-R media", mp->dvd_r_write);
  2186. DOES("read DVD-RAM media", mp->dvd_ram_read);
  2187. DOES("write DVD-RAM media", mp->dvd_ram_write);
  2188. DOES("support test writing", mp->test_write);
  2189. printf("n");
  2190. DOES("read Mode 2 Form 1 blocks", mp->mode_2_form_1);
  2191. DOES("read Mode 2 Form 2 blocks", mp->mode_2_form_2);
  2192. DOES("read digital audio blocks", mp->cd_da_supported);
  2193. if (mp->cd_da_supported) 
  2194. DOES("restart non-streamed digital audio reads accurately", mp->cd_da_accurate);
  2195. DOES("read multi-session CDs", mp->multi_session);
  2196. DOES("read fixed-packet CD media using Method 2", mp->method2);
  2197. DOES("read CD bar code", mp->read_bar_code);
  2198. DOES("read R-W subcode information", mp->rw_supported);
  2199. if (mp->rw_supported) 
  2200. DOES("return R-W subcode de-interleaved and error-corrected", mp->rw_deint_corr);
  2201. DOES("return CD media catalog number", mp->UPC);
  2202. DOES("return CD ISRC information", mp->ISRC);
  2203. DOES("support C2 error pointers", mp->c2_pointers);
  2204. DOES("deliver composite A/V data", mp->composite);
  2205. printf("n");
  2206. DOES("play audio CDs", mp->audio_play);
  2207. if (mp->audio_play) {
  2208. VAL("Number of volume control levels", mp->num_vol_levels);
  2209. DOES("support individual volume control setting for each channel", mp->sep_chan_vol);
  2210. DOES("support independent mute setting for each channel", mp->sep_chan_mute);
  2211. DOES("support digital output on port 1", mp->digital_port_1);
  2212. DOES("support digital output on port 2", mp->digital_port_2);
  2213. if (mp->digital_port_1 || mp->digital_port_2) {
  2214. DOES("send digital data LSB-first", mp->LSBF);
  2215. DOES("set LRCK high for left-channel data", mp->RCK);
  2216. DOES("have valid data on falling edge of clock", mp->BCK);
  2217. SVAL("Length of data in BCLKs", bclk[mp->length]);
  2218. }
  2219. }
  2220. printf("n");
  2221. SVAL("Loading mechanism type", load[mp->loading_type]);
  2222. DOES("support ejection of CD via START/STOP command", mp->eject);
  2223. DOES("lock media on power up via prevent jumper", mp->prevent_jumper);
  2224. DOES("allow media to be locked in the drive via PREVENT/ALLOW command", mp->lock);
  2225. IS("currently in a media-locked state", mp->lock_state);
  2226. DOES("have load-empty-slot-in-changer feature", mp->sw_slot_sel);
  2227. DOES("support Individual Disk Present feature", mp->disk_present_rep);
  2228. printf("n");
  2229. VAL("Maximum read  speed in kB/s", mp->max_read_speed);
  2230. VAL("Current read  speed in kB/s", mp->cur_read_speed);
  2231. VAL("Maximum write speed in kB/s", mp->max_write_speed);
  2232. VAL("Current write speed in kB/s", mp->cur_write_speed);
  2233. VAL("Buffer size in KB", mp->buffer_size);
  2234. return; /* Generic SCSI-3/mmc CD */
  2235. }