Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Feb 1999 23:32:38 +0900 (JST)
From:      hnokubi@yyy.or.jp
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/10116: acd driver patch to support PD/CD drive.
Message-ID:  <199902161432.GAA24152@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         10116
>Category:       kern
>Synopsis:       acd driver patch to support PD/CD drive.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Feb 16 06:40:00 PST 1999
>Closed-Date:
>Last-Modified:
>Originator:     NOKUBI Hirotaka
>Release:        FreeBSD 4.0-CURRENT i386
>Organization:
>Environment:

FreeBSD alphazeal.nokubi.or.jp 4.0-CURRENT FreeBSD 4.0-CURRENT #26: Mon Feb 15 23:41:39 JST 1999     h-nokubi@alphazeal.nokubi.or.jp:/usr/src/sys/compile/ALPHAZEAL  i386

>Description:

I'm using FreeBSD on NEC PC98, and I want to use PD/CD drive on my machine.
I read INF-8070.PDF (ATAPI for Rewritable Removable Media spec.), made
patch to acd driver so that I can use my ODX654P NEC PD/CD drive as PD drive.
I'd appreciate to see that the patch will be included in the future
FreeBSD release.

Because I'd like to make the difference clear, appended patch has wrong
indentation. I'm sorry, but please correct that if you apply the patch.

>How-To-Repeat:

	

>Fix:
	
In original code, member `lun' in `struct acd' is initialized by `acdnlun'.
It seems to be wrong, when more than two CD-ROM changers are in same machine
(first changer will be assigned right lun numbers, second one will be assigned
 wrong lun numbers). Am I correct?

Index: i386/isa/atapi.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/atapi.c,v
retrieving revision 1.30
diff -u -r1.30 atapi.c
--- atapi.c	1998/12/27 17:12:01	1.30
+++ atapi.c	1999/02/16 13:45:26
@@ -340,11 +340,13 @@
 	case 0x01: return ("REZERO_UNIT");
 	case 0x03: return ("REQUEST_SENSE");
 	case 0x04: return ("FORMAT_UNIT");
+	case 0x12: return ("INQUIRY");
 	case 0x1b: return ("START_STOP");
 	case 0x1e: return ("PREVENT_ALLOW");
 	case 0x25: return ("READ_CAPACITY");
 	case 0x28: return ("READ_BIG");
 	case 0x2a: return ("WRITE_BIG");
+	case 0x2b: return ("SEEK");
 	case 0x35: return ("SYNCHRONIZE_CACHE");
 	case 0x42: return ("READ_SUBCHANNEL");
 	case 0x43: return ("READ_TOC");
Index: i386/isa/atapi.h
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/atapi.h,v
retrieving revision 1.16
diff -u -r1.16 atapi.h
--- atapi.h	1998/12/27 17:12:01	1.16
+++ atapi.h	1999/02/16 13:45:26
@@ -114,11 +114,13 @@
 #define ATAPI_TEST_UNIT_READY   0x00    /* check if the device is ready */
 #define ATAPI_REZERO_UNIT   	0x01    /* reinit device */
 #define ATAPI_REQUEST_SENSE     0x03    /* get sense data */
+#define ATAPI_INQUIRY           0x12    /* get information regarding param. */
 #define ATAPI_START_STOP        0x1b    /* start/stop the media */
 #define ATAPI_PREVENT_ALLOW     0x1e    /* prevent/allow media removal */
 #define ATAPI_READ_CAPACITY     0x25    /* get volume capacity */
 #define ATAPI_READ_BIG          0x28    /* read data */
 #define ATAPI_WRITE_BIG		0x2a    /* write data */
+#define ATAPI_SEEK		0x2b    /* seek */
 #define ATAPI_SYNCHRONIZE_CACHE	0x35    /* flush write buf, close write chan */
 #define ATAPI_READ_SUBCHANNEL   0x42    /* get subchannel info */
 #define ATAPI_READ_TOC          0x43    /* get table of contents */
@@ -200,6 +202,15 @@
 	short reserved7[2];
 	u_short         rls_ovlap;      /* release time (us) for overlap cmd - optional */
 	u_short         rls_service;    /* release time (us) for service cmd - optional */
+	u_short		major_rev;
+	u_short		minor_ver;
+	u_short		reserved8[51];
+	unsigned	last_lun : 3;
+	unsigned	: 13;
+	unsigned	media_status : 2;
+	unsigned	: 6;
+	unsigned	write_protect : 1;
+	unsigned	: 7;
 };
 
 /*
Index: i386/isa/atapi-cd.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/atapi-cd.c,v
retrieving revision 1.11
diff -u -r1.11 atapi-cd.c
--- atapi-cd.c	1999/02/10 00:03:32	1.11
+++ atapi-cd.c	1999/02/16 13:45:26
@@ -96,6 +96,7 @@
 static int acd_read_toc(struct acd *);
 static int acd_request_wait(struct acd *, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, char *, int);
 static void acd_describe(struct acd *);
+static void aod_describe(struct acd *);
 static int acd_setchan(struct acd *, u_char, u_char, u_char, u_char);
 static int acd_eject(struct acd *, int);
 static void acd_select_slot(struct acd *);
@@ -168,6 +169,7 @@
     struct atapires result;
     struct changer *chp;
     int i, count;
+    int lun = 0;
 
     if (acdnlun >= NUNIT) {
         printf("acd: too many units\n");
@@ -177,7 +179,9 @@
         printf("acd: configuration error, ATAPI code not present!\n");
         return 0;
     }
-    if ((cdp = acd_init_lun(ata, unit, ap, acdnlun, NULL)) == NULL) {
+    do {
+
+    if ((cdp = acd_init_lun(ata, unit, ap, lun, NULL)) == NULL) {
         printf("acd: out of memory\n");
         return 0;
     }
@@ -187,12 +191,23 @@
         cdp->flags |= F_DEBUG;
         atapi_dump(cdp->ata->ctrlr, cdp->lun, "info", ap, sizeof(*ap));
     }
-
+    result = atapi_request_immediate(ata, unit,
+				     ATAPI_INQUIRY,
+				     lun << 5, 0,
+				     0, sizeof(cdp->inq), 0, 0, 
+				     0, 0,
+				     0, 0, 0, 0, 0, 0, 0, 
+				     (char *)&cdp->inq, sizeof(cdp->inq));
+    if (result.code == RES_OK ||
+	result.code == RES_UNDERRUN || result.code == RES_OVERRUN)
+	if (cdp->flags & F_DEBUG)
+	    atapi_dump(cdp->ata->ctrlr, cdp->lun, "info", &cdp->inq, sizeof(cdp->inq));
+    if (cdp->inq.devicetype == DEVICE_CD) {
     /* Get drive capabilities, some drives needs this repeated */
     for (count = 0 ; count < 5 ; count++) {
         result = atapi_request_immediate(ata, unit,
         				 ATAPI_MODE_SENSE,
-        				 0, ATAPI_CDROM_CAP_PAGE,
+        				 lun << 5, ATAPI_CDROM_CAP_PAGE,
         				 0, 0, 0, 0, 
 					 sizeof(cdp->cap)>>8, sizeof(cdp->cap),
         				 0, 0, 0, 0, 0, 0, 0, 
@@ -244,7 +259,7 @@
             chp->table_length = htons(chp->table_length);
             for (i = 0; i < chp->slots && acdnlun < NUNIT; i++) {
                 if (i > 0) {
-                    tmpcdp = acd_init_lun(ata, unit, ap, acdnlun, 
+                    tmpcdp = acd_init_lun(ata, unit, ap, ++lun, 
 					  cdp->device_stats);
 		    if (!tmpcdp) {
                         printf("acd: out of memory\n");
@@ -253,7 +268,7 @@
                 }
                 tmpcdp->slot = i;
                 tmpcdp->changer_info = chp;
-                printf("acd%d: changer slot %d %s\n", acdnlun, i,
+                printf("acd%d: changer slot %d %s\n", lun, i,
 		       (chp->slot[i].present ? "disk present" : "no disk"));
                 acdtab[acdnlun++] = tmpcdp;
             }
@@ -266,15 +281,19 @@
         devstat_add_entry(cdp->device_stats, string, tmpcdp->lun, DEV_BSIZE,
                           DEVSTAT_NO_ORDERED_TAGS,
                           DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
-			  DEVSTAT_PRIORITY_WCD);
-    }
-    else {
-        acdnlun++;
-        devstat_add_entry(cdp->device_stats, "acd", cdp->lun, DEV_BSIZE,
-                          DEVSTAT_NO_ORDERED_TAGS,
-                          DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE,
 			  DEVSTAT_PRIORITY_WCD);
+	continue;
     }
+    } else if (cdp->inq.devicetype == DEVICE_OD) {
+        cdp->block_size = 512; /* XXX */
+	aod_describe(cdp);
+    }
+    acdnlun++;
+    devstat_add_entry(cdp->device_stats, "acd", cdp->lun, DEV_BSIZE,
+                      DEVSTAT_NO_ORDERED_TAGS,
+		      cdp->inq.devicetype | DEVSTAT_TYPE_IF_IDE,
+		      DEVSTAT_PRIORITY_WCD);
+    } while (++lun <= ap->last_lun);
     return 1;
 }
 
@@ -284,6 +303,7 @@
     int comma;
     char *mechanism;
 
+    printf("acd%d: CD-ROM device\n", cdp->lun);
     printf("acd%d: drive speed ", cdp->lun);
     if (cdp->cap.cur_speed != cdp->cap.max_speed)
         printf("%d - ", cdp->cap.cur_speed * 1000 / 1024);
@@ -399,6 +419,12 @@
     printf("\n");
 }
 
+void
+aod_describe(struct acd *cdp)
+{
+    printf("acd%d: Optical memory device\n", cdp->lun);
+}
+
 static int
 acdopen(dev_t dev, int flags, int fmt, struct proc *p)
 {
@@ -427,6 +453,7 @@
                 printf("acd%d: rezero failed\n", lun);
                 return EIO;
             }
+	    cdp->flags &= ~F_MEDIA_CHANGED;
         } else {
             /* read only */
             if (acd_read_toc(cdp) != 0) {
@@ -533,6 +560,7 @@
     acd_select_slot(cdp);
 
     if ((bp->b_flags & B_READ) == B_WRITE) {
+        if (cdp->inq.devicetype == DEVICE_CD)
         if ((cdp->flags & F_TRACK_PREPED) == 0) {
             if ((cdp->flags & F_TRACK_PREP) == 0) {
                 printf("acd%d: sequence error\n", cdp->lun);
@@ -556,8 +584,12 @@
 #else
     	lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
 #endif
-    else 
+    else {
+        if (cdp->inq.devicetype == DEVICE_CD)
 	lba = cdp->next_writeable_lba + (bp->b_offset / cdp->block_size);
+	else
+	lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
+    }
     blocks = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size;
 
     if ((bp->b_flags & B_READ) == B_WRITE) {
@@ -570,7 +602,7 @@
 
     devstat_start_transaction(cdp->device_stats);
 
-    atapi_request_callback(cdp->ata, cdp->unit, cmd, 0,
+    atapi_request_callback(cdp->ata, cdp->unit, cmd, cdp->lun << 5,
         		   lba>>24, lba>>16, lba>>8, lba, 0, 
 			   blocks>>8, blocks, 0, 0, 0, 0, 0, 0, 0, 
 			   (u_char *)bp->b_data, count, 
@@ -604,7 +636,8 @@
 {
     struct atapires result;
 
-    result = atapi_request_wait(cdp->ata, cdp->unit, cmd, a1, a2, a3, a4, a5,
+    result = atapi_request_wait(cdp->ata, cdp->unit, cmd, cdp->lun << 5 | a1,
+				a2, a3, a4, a5,
 			        a6, a7, a8, a9, 0, 0, 0, 0, 0, 0, addr, count);
     if (result.code) {
         atapi_error(cdp->ata, cdp->unit, result);
@@ -636,6 +669,8 @@
     int lun = dkunit(dev);
     struct acd *cdp = acdtab[lun];
     int error = 0;
+    struct disklabel *dl;
+    char buffer[DEV_BSIZE];
 
     if (cdp->flags & F_MEDIA_CHANGED)
         switch (cmd) {
@@ -649,6 +684,51 @@
             break;
         }
     switch (cmd) {
+    case DIOCGDINFO:
+	if (cdp->inq.devicetype != DEVICE_OD) {
+	    error = EINVAL;
+	    break;
+	}
+	bzero(buffer, sizeof (buffer));
+	dl = (struct disklabel *)buffer;
+	dl->d_secsize = 512;
+	dl->d_secpercyl = 32;
+	dl->d_type = DTYPE_FLOPPY;/* XXX */
+
+	if (readdisklabel(dkmodpart(dev, RAW_PART), acdstrategy, dl)
+	    == NULL)
+	    error = 0;
+	else
+	    error = EINVAL;
+
+	*(struct disklabel *)addr = *dl;
+	break;
+
+    case DIOCSDINFO:
+	if ((flag & FWRITE) == 0)
+	    error = EBADF;
+	break;
+
+    case DIOCWLABEL:
+	if ((flag & FWRITE) == 0)
+	    error = EBADF;
+	break;
+
+    case DIOCWDINFO:
+	if ((flag & FWRITE) == 0) {
+	    error = EBADF;
+	    break;
+	}
+
+	dl = (struct disklabel *)addr;
+
+	if ((error = setdisklabel((struct disklabel *)buffer, dl,
+				  (u_long)0)) != 0)
+	    break;
+
+	error = writedisklabel(dev, acdstrategy,
+			       (struct disklabel *)buffer);
+	break;
 /*
     case CDIOCRESUME:
         bzero(cdb);
@@ -1121,7 +1201,7 @@
     acd_select_slot(cdp);
 
     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_TEST_UNIT_READY,
-        			0, 0, 0, 0, 0, 0, 0, 0,
+        			cdp->lun << 5, 0, 0, 0, 0, 0, 0, 0,
 				0, 0, 0, 0, 0, 0, 0, 0, 0);
 
     if (result.code == RES_ERR &&
@@ -1129,7 +1209,7 @@
         cdp->flags |= F_MEDIA_CHANGED;
     	cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
         result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_TEST_UNIT_READY,
-				    0, 0, 0, 0, 0, 0, 0, 0,
+				    cdp->lun << 5, 0, 0, 0, 0, 0, 0, 0,
 				    0, 0, 0, 0, 0, 0, 0, 0, 0);
     }
 
@@ -1225,7 +1305,8 @@
 
     acd_select_slot(cdp);
 
-    result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_START_STOP, 1,
+    result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_START_STOP,
+				cdp->lun << 5 | 1,
 			        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
     if (result.code == RES_ERR &&
@@ -1295,8 +1376,14 @@
 static int
 acd_rezero_unit(struct acd *cdp)
 {
-    return acd_request_wait(cdp, ATAPI_REZERO_UNIT, 0, 0, 0, 0,
-			    0, 0, 0, 0, 0, 0, 0);
+    if (cdp->inq.devicetype == DEVICE_CD)
+        return acd_request_wait(cdp, ATAPI_REZERO_UNIT, 0, 0, 0, 0,
+			        0, 0, 0, 0, 0, 0, 0);
+    else
+        /* Does rezero unit have special effect to CD-R/RW drive? */
+        /* My ODX654P PD/CD drive does not support rezero unit */
+        return acd_request_wait(cdp, ATAPI_SEEK, 0, 0, 0, 0,
+			        0, 0, 0, 0, 0, 0, 0);
 }
 
 static int
@@ -1320,7 +1407,7 @@
     struct atapires result;
 
     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SENSE,
-        			0, 0x05, 0, 0, 0, 0, 
+        			cdp->lun << 5, 0x05, 0, 0, 0, 0, 
 				sizeof(param)>>8, sizeof(param),
         			0, 0, 0, 0, 0, 0, 0,
         			(char *)&param, sizeof(param));
@@ -1397,7 +1484,7 @@
         atapi_dump(cdp->ata->ctrlr, cdp->lun, "0x05", &param, sizeof(param));
 
     result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SELECT,
-        			0x10, 0, 0, 0, 0, 0, 
+        			cdp->lun << 5 | 0x10, 0, 0, 0, 0, 0, 
 				sizeof(param)>>8, sizeof(param),
         			0, 0, 0, 0, 0, 0, 0,
         			(char *)&param, -sizeof(param));
Index: i386/isa/atapi-cd.h
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/atapi-cd.h,v
retrieving revision 1.3
diff -u -r1.3 atapi-cd.h
--- atapi-cd.h	1999/01/31 21:51:03	1.3
+++ atapi-cd.h	1999/02/16 13:45:26
@@ -37,6 +37,16 @@
 	struct cd_toc_entry tab[MAXTRK + 1];
 };
 
+struct inquirydata {
+#define	DEVICE_CD	5
+#define	DEVICE_OD	7
+	u_char devicetype:5;
+	u_char :3;
+	u_char :7;
+	u_char removable:1;
+	char data[54];
+};
+
 /*
  * CDROM Audio Control Parameters Page
  */
@@ -105,6 +115,7 @@
 
 	/* Capabilities page */
 	u_char page_code;
+#define ATAPI_REMOVABLE_CAP_PAGE    0x1b
 #define ATAPI_CDROM_CAP_PAGE        0x2a
 
 	u_char param_len;
@@ -326,6 +337,7 @@
 	}      info;
 	struct audiopage au;		/* Audio page info */
 	struct cappage cap;		/* Capabilities page info */
+	struct inquirydata inq;
 	struct audiopage aumask;	/* Audio page mask */
 	struct {			/* Subchannel info */
 		u_char void0;
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199902161432.GAA24152>