[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[debian-users:38708] USB MO 動作報告(長文)



山森です。

もっと適切なMLがあるかもしれませんが、登録しているMLがこちら
くらいなのでここに書きます。
最近のLinuxではUSBのMOなど余裕で使えるようになっているだろう
と思い、中古のUSB MOドライブを買いました。が、動きませんでした。
FreeBSDでも試しましたがダメでした。
FreeBSDのソースも見ましたが、Linuxのほうがより多くの機種に対応
できそうな感じでした。
購入したyano U640MO-02という機種は、富士通のATAPIドライブに
USB/ATAPIブリッジが付いているだけなので、なんとかなりそうな感じ
です。
試行錯誤しながらも以下のパッチで一応動くようになりました。
コンソールにはSCSIのINQUIRYの結果が以下のように表示されてます。

   Vendor: FUJITSU   Model: M25-MCC3064AP     Rev: 0051
   Type:   Optical Device                     ANSI SCSI revision: 02

### patch-1 ###
--- 2.4.22/drivers/usb/storage/unusual_devs.h
+++ new/drivers/usb/storage/unusual_devs.h
@@ -565,6 +565,11 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_FIX_CAPACITY ),
 
+UNUSUAL_DEV(  0x094f, 0x0101, 0x0000, 0x9999, 
+		"yano",
+		"U640MO-02 (USB/ATAPI Bridge)",
+		US_SC_8070, US_PR_CBI, NULL, 0),
+
 UNUSUAL_DEV(  0x097a, 0x0001, 0x0000, 0x0001,
 		"Minds@Work",
 		"Digital Wallet",
### end patch ###

しかし上のパッチでは問題があり、メディアの交換が認識できず、
交換するとエラーになってアクセスできなくなります。
DEBUGプリントで調べてみると、TEST_UNIT_READYコマンドがちゃんと
動いてなく、いつも正常リターンしていることが分かりました。
そこで代替のコマンドを発行するようにして無理やり動くようにして
みたのが以下のパッチです。
scsi層には手をつけたくなかったのですが、メディアが入ってないとき
延々とリトライを繰り返すので、早々に見切りをつけるようにしてみま
した。SCSIのHDDとMOが付いてるマシンでテストしましたが問題ない
ようです。

### patch-2 ###
--- 2.4.22/drivers/usb/storage/unusual_devs.h	2003-08-25 20:44:42.000000000 +0900
+++ new/drivers/usb/storage/unusual_devs.h	2003-11-05 21:49:13.000000000 +0900
@@ -565,6 +565,11 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_FIX_CAPACITY ),
 
+UNUSUAL_DEV(  0x094f, 0x0101, 0x0000, 0x9999, 
+		"yano",
+		"U640MO-02 (USB/ATAPI Bridge)",
+		US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_TEST_UNIT),
+
 UNUSUAL_DEV(  0x097a, 0x0001, 0x0000, 0x0001,
 		"Minds@Work",
 		"Digital Wallet",
--- 2.4.22/drivers/usb/storage/usb.h	2003-08-25 20:44:42.000000000 +0900
+++ new/drivers/usb/storage/usb.h	2003-11-05 21:45:00.000000000 +0900
@@ -103,6 +103,7 @@
 #define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets */
 #define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs fixing */
 #define US_FL_FIX_CAPACITY    0x00000080 /* READ_CAPACITY response too big */
+#define US_FL_FIX_TEST_UNIT   0x00000100 /* TEST_UNIT_READY not work fix */
 
 #define USB_STOR_STRING_LEN 32
 
--- 2.4.22/drivers/usb/storage/usb.c	2003-08-25 20:44:42.000000000 +0900
+++ new/drivers/usb/storage/usb.c	2003-11-05 23:05:15.000000000 +0900
@@ -442,6 +442,58 @@
 					US_DEBUGP("Faking INQUIRY command\n");
 					fill_inquiry_response(us, data_ptr, 36);
 					us->srb->result = GOOD << 1;
+#if 1 /* fix TEST_UNIT_READY */
+				} else if (us->srb->cmnd[0] == TEST_UNIT_READY
+					 && (us->flags & US_FL_FIX_TEST_UNIT)) {
+					unsigned char *oldp;
+					unsigned char cabuf[8];
+
+					US_DEBUGP(
+					  "TEST_UNIT_READY => REQUEST_SENSE\n");
+					oldp = us->srb->request_buffer;
+					us->srb->request_buffer =
+							us->srb->sense_buffer;
+					us->srb->request_bufflen = 18;
+					memset(us->srb->sense_buffer, 0, 18);
+					memset(us->srb->cmnd, 0, 12);
+					us->srb->cmnd[0] = REQUEST_SENSE;
+					us->srb->cmnd[4] = 18;
+					us->srb->cmd_len = 12;
+					us->srb->sc_data_direction =
+							SCSI_DATA_READ;
+					US_DEBUG(usb_stor_show_command(
+								us->srb));
+					us->proto_handler(us->srb, us);
+					US_DEBUGP(
+					  " result1:%08x sense:%02x,%02x\n",
+						us->srb->result,
+						us->srb->sense_buffer[2],
+						us->srb->sense_buffer[12]);
+					if (us->srb->sense_buffer[2] == 0) {
+						US_DEBUGP(
+						"  additional READ_CAPACITY\n");
+						memset(us->srb->sense_buffer,
+									0, 18);
+						memset(us->srb->cmnd, 0, 12);
+						us->srb->cmnd[0] =
+								READ_CAPACITY;
+						us->srb->cmd_len = 10;
+						us->srb->request_buffer = cabuf;
+						us->srb->request_bufflen = 8;
+						US_DEBUG(usb_stor_show_command(
+								us->srb));
+						us->proto_handler(us->srb, us);
+						US_DEBUGP(
+					" result2:%08x sense:%02x,%02x\n",
+						us->srb->result,
+						us->srb->sense_buffer[2],
+						us->srb->sense_buffer[12]);
+						/* no retry */
+						us->srb->result = 0;
+					}
+					us->srb->request_buffer = oldp;
+					us->srb->request_bufflen = 0;
+#endif
 				} else {
 					/* we've got a command, let's do it! */
 					US_DEBUG(usb_stor_show_command(us->srb));
--- 2.4.22/drivers/scsi/scsi_ioctl.c	2003-08-25 20:44:42.000000000 +0900
+++ new/drivers/scsi/scsi_ioctl.c	2003-11-05 22:36:08.000000000 +0900
@@ -118,7 +118,11 @@
 				printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
 			break;
 		case NOT_READY:	/* This happens if there is no disc in drive */
+#if 1 /* fix usb mo */
+			if (dev->removable) {
+#else
 			if (dev->removable && (cmd[0] != TEST_UNIT_READY)) {
+#endif
 				printk(KERN_INFO "Device not ready.  Make sure there is a disc in the drive.\n");
 				break;
 			}
--- 2.4.22/drivers/scsi/sd.c	2003-08-25 20:44:42.000000000 +0900
+++ new/drivers/scsi/sd.c	2003-11-05 22:48:35.000000000 +0900
@@ -837,6 +837,20 @@
 			     || ((driver_byte(the_result) & DRIVER_SENSE)
 				 && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)));
 
+#if 1 /* fix usb mo */
+		if (the_result != 0
+		    && rscsi_disks[i].device->removable
+		    && SRpnt->sr_sense_buffer[2] == NOT_READY
+		    && SRpnt->sr_sense_buffer[12] == 0x3A) {
+			printk("%s : no medium.\n", nbuff);
+			rscsi_disks[i].capacity = 0;
+			rscsi_disks[i].device->changed = 1;
+			rscsi_disks[i].ready = 0;
+			scsi_release_request(SRpnt);
+			scsi_free(buffer, 512);
+			return i;
+		}
+#endif
 		/*
 		 * If the drive has indicated to us that it doesn't have
 		 * any media in it, don't bother with any of the rest of
@@ -1372,6 +1386,11 @@
 		printk("Device busy for revalidation (usage=%d)\n", USAGE);
 		return -EBUSY;
 	}
+#if 1 /* fix usb mo */
+	if (rscsi_disks[target].ready == 0 &&
+	    rscsi_disks[target].device->removable)
+		return -ENOMEDIUM;
+#endif
 	DEVICE_BUSY = 1;
 
 	sdgd = &SD_GENDISK(target);
### end patch ###

--
山森 浩幸
Hiroyuki YAMAMORI <h-yamamo@xxxxxxxxxxxxxxxx>
GnuPG FP: D9D2 F04D DD2D 720E E564  D1EC 4617 22C1 B881 226E
Home Page: http://www002.upp.so-net.ne.jp/h-yamamo/