Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Feb 1998 17:40:25 -0400 (AST)
From:      The Hermit Hacker <scrappy@hub.org>
To:        freebsd-current@FreeBSD.ORG
Subject:   ATAPI related patch ..
Message-ID:  <Pine.BSF.3.96.980223173713.241D-100000@thelab.hub.org>

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

Hi...

	I recently grabbed a patch that Luigi (freebsd-multimedia) has
that is required in order to read audio tracks (using something like
tosha) from a CD...with minor modifications, I've got it in my -current
kernel and haven't noticed any problems.

	I would like to commit the patch to the -current source tree, so
am asking here if there are any objections to doing this.  If I hear
nothing by Wednesday (long enough?), I'll assume that it is okay and
commit it...

	Patch included below...

Thanks...

Marc G. Fournier                                
Systems Administrator @ hub.org 
primary: scrappy@hub.org           secondary: scrappy@{freebsd|postgresql}.org 


*** isa/wcd.c	Mon Feb  9 02:08:43 1998
--- isa.n/wcd.c	Sun Feb 22 23:33:18 1998
***************
*** 346,351 ****
--- 346,352 ----
  	struct atapires result;
  	struct changer *chp;
  	int i;
+ 	int loops = 0;
  
  	if (wcdnlun >= NUNIT) {
  		printf ("wcd: too many units\n");
***************
*** 369,385 ****
  	}
  
  	/* Get drive capabilities. */
  	result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE,
  		0, CAP_PAGE, 0, 0, 0, 0, sizeof (cdp->cap) >> 8, sizeof (cdp->cap),
  		0, 0, 0, 0, 0, 0, 0, (char*) &cdp->cap, sizeof (cdp->cap));
  
! 	/* Do it twice to avoid the stale media changed state. */
! 	if (result.code == RES_ERR &&
! 	    (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION)
! 		result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE,
! 			0, CAP_PAGE, 0, 0, 0, 0, sizeof (cdp->cap) >> 8,
! 			sizeof (cdp->cap), 0, 0, 0, 0, 0, 0, 0,
! 			(char*) &cdp->cap, sizeof (cdp->cap));
  
  	/* Some drives have shorter capabilities page. */
  	if (result.code == RES_UNDERRUN)
--- 370,384 ----
  	}
  
  	/* Get drive capabilities. */
+ 	for (loops = 0 ; loops < 10 ; loops++) {
+ 		/* some drives are slow to respond at boot time... */
  	result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE,
  		0, CAP_PAGE, 0, 0, 0, 0, sizeof (cdp->cap) >> 8, sizeof (cdp->cap),
  		0, 0, 0, 0, 0, 0, 0, (char*) &cdp->cap, sizeof (cdp->cap));
  
! 		if (result.code == 0 || result.code == RES_UNDERRUN)
! 			break;
! 	}
  
  	/* Some drives have shorter capabilities page. */
  	if (result.code == RES_UNDERRUN)
***************
*** 511,516 ****
--- 510,544 ----
  	if (t->cap.prevent)
  		printf (", lock protected");
  	printf ("\n");
+  
+         printf ("wcd%d: ", t->lun);
+         if (t->cap.composite)
+                 printf(" comp. A/V,");
+         if (t->cap.dport1 || t->cap.dport2)
+                 printf(" dig.audio %s%s,",
+                     t->cap.dport1 ? "1 ":"", t->cap.dport2 ? "2":"");
+         if (t->cap.mode2_form1 || t->cap.mode2_form2)
+                 printf(" mode 2 form %s%s,",
+                         t->cap.mode2_form1 ? "1(XA) ":"",
+                         t->cap.mode2_form2 ? "2":"");
+         if (t->cap.multisession)
+                 printf(" multisession,");
+         if (t->cap.cd_da || t->cap.cd_da_stream)
+                 printf(" CD-DA %s%s,",
+                         t->cap.cd_da ? "read ":"",
+                         t->cap.cd_da_stream ? "stream":"");
+         if (t->cap.rw)
+                 printf(" combined rw,");
+         if (t->cap.rw_corr)
+                 printf(" rw correct.,");
+         if (t->cap.c2)
+                 printf(" C2,");
+         if (t->cap.isrc)
+                 printf(" ISRC,");
+         if (t->cap.upc)
+                 printf(" UPC");
+         printf("\n");
+ 
  }
  
  static int 
***************
*** 738,743 ****
--- 766,827 ----
  	*f = lba % 75;
  }
  
+ #if 1
+ #define CDIOCATAPIREQ  _IOWR('c',100,struct atapireq)
+ 
+ struct atapireq {
+        u_char  cmd[16];
+        caddr_t databuf;
+        int     datalen;
+        struct  atapires result;
+ };
+ 
+ static void arstrategy(struct buf *);
+ static void ar_done(struct wcd *, struct buf *, int, struct atapires);
+ 
+ static void
+ arstrategy(struct buf *bp)
+ {
+        struct wcd *t = bp->b_driver1;
+        struct atapireq *ar = bp->b_driver2;
+ 
+        if (t == NULL || ar == NULL) {
+                bp->b_error = EINVAL;
+                bp->b_flags |= B_ERROR;
+                biodone(bp);
+                return;
+        }
+ 
+        /* Can't ever write to a CD. */
+        if (!(bp->b_flags & B_READ)) {
+                bp->b_error = EROFS;
+                bp->b_flags |= B_ERROR;
+                biodone(bp);
+                return;
+        }
+ 
+        atapi_request_callback(t->ata, t->unit,
+                ar->cmd[0],  ar->cmd[1],  ar->cmd[2],  ar->cmd[3],
+                ar->cmd[4],  ar->cmd[5],  ar->cmd[6],  ar->cmd[7],
+                ar->cmd[8],  ar->cmd[9],  ar->cmd[10], ar->cmd[11],
+                ar->cmd[12], ar->cmd[13], ar->cmd[14], ar->cmd[15],
+                (u_char*) bp->b_data, bp->b_bcount, ar_done, t, bp);
+ }
+ 
+ static void
+ ar_done(struct wcd *t, struct buf *bp, int resid, struct atapires result)
+ {
+        struct atapireq *ar = bp->b_driver2;
+ 
+        if (result.code)
+                wcd_error(t, result);
+        bp->b_resid = 0;
+        ar->datalen -= resid;
+        ar->result = result;
+        biodone(bp);
+ }
+ #endif
+ 
  /*
   * Perform special action on behalf of the user.
   * Knows about the internals of this device
***************
*** 834,839 ****
--- 918,973 ----
  			return (EIO);
  		bcopy (&t->toc.hdr, addr, sizeof t->toc.hdr);
  		break;
+ 
+ #ifdef CDIOCATAPIREQ
+        case CDIOCATAPIREQ: {
+                struct atapireq *ar, *oar = (struct atapireq *)addr;
+                struct buf *bp;
+ 
+                MALLOC(ar, struct atapireq *, sizeof *ar, M_TEMP, M_WAITOK);
+                MALLOC(bp, struct buf *, sizeof *bp, M_TEMP, M_WAITOK);
+ 
+                bcopy(oar, ar, sizeof *ar);
+                bzero(bp, sizeof *bp);
+ 
+                bp->b_proc = p;
+                bp->b_dev = dev;
+                bp->b_driver1 = t;
+                bp->b_driver2 = ar;
+ 
+                if (ar->datalen) {
+                        struct uio auio;
+                        struct iovec aiov;
+ 
+                        if (ar->datalen < 0)
+                                return (EINVAL);
+ 
+                        aiov.iov_base = ar->databuf;
+                        aiov.iov_len = ar->datalen;
+                        auio.uio_iov = &aiov;
+                        auio.uio_iovcnt = 1;
+ 
+                        auio.uio_offset = 0;
+                        auio.uio_resid = ar->datalen;
+ 
+                        auio.uio_rw = UIO_READ; /* CD is readonly */
+                        auio.uio_segflg = UIO_USERSPACE;
+                        auio.uio_procp = p;
+ 
+                        bp->b_bcount = ar->datalen;
+                        error = physio(arstrategy, bp, dev, 1, minphys, &auio);
+                } else {
+                        bp->b_flags = B_READ | B_BUSY;
+                        arstrategy(bp);
+                        error = bp->b_error;
+                }
+ 
+                bcopy(ar, oar, sizeof *ar);
+                FREE(ar, M_TEMP);
+                FREE(bp, M_TEMP);
+                break;
+        }
+ #endif
  
  	case CDIOREADTOCENTRYS: {
  		struct ioc_read_toc_entry *te =
*** isa/atapi.c	Mon Feb  9 02:08:24 1998
--- isa.n/atapi.c	Sun Feb 22 22:44:16 1998
***************
*** 214,220 ****
  
  	/* DRQ type */
  	switch (ap->drqtype) {
! 	case AT_DRQT_MPROC: ata->slow = 1; break;
  	case AT_DRQT_INTR:  printf (", intr"); ata->intrcmd = 1; break;
  	case AT_DRQT_ACCEL: printf (", accel"); break;
  	default:            printf (", drq%d", ap->drqtype);
--- 214,220 ----
  
  	/* DRQ type */
  	switch (ap->drqtype) {
! 	case AT_DRQT_MPROC: printf (", slow"); ata->slow = 1; break;
  	case AT_DRQT_INTR:  printf (", intr"); ata->intrcmd = 1; break;
  	case AT_DRQT_ACCEL: printf (", accel"); break;
  	default:            printf (", drq%d", ap->drqtype);
***************
*** 338,343 ****
--- 338,344 ----
  	case 0x4b: return ("PAUSE");
  	case 0x48: return ("PLAY_TRACK");
  	case 0xa5: return ("PLAY_BIG");
+ 	case 0xbe: return ("READ_CD"); /* XXX */
  	}
  	sprintf (buf, "[0x%x]", cmd);
  	return (buf);
***************
*** 778,796 ****
--- 779,841 ----
  			print (("atapi%d.%d: recv data overrun, %d bytes left\n",
  				ata->ctrlr, ac->unit, ac->count));
  			ac->result.code = RES_OVERRUN;
+                     if(ac->count != 0)
  			insw (ata->port + AR_DATA, ac->addr,
  				ac->count / sizeof(short));
  			for (i=ac->count; i<len; i+=sizeof(short))
  				inw (ata->port + AR_DATA);
+                     len = ac->count;
  		} else
  			insw (ata->port + AR_DATA, ac->addr,
  				len / sizeof(short));
  		ac->addr += len;
  		ac->count -= len;
+ #if 1
+                /*
+                 * some drives appear not to assert BSY after a
+                 * CDDA transfer, and then do not generate the intrq
+                 * to complete the transfer. Among these:
+                 *      Sony CDU331, Goldstar GCD580
+                 * Obviate by testing BSY and going on anyways.
+                 */
+                for (i = 0 ; i < 2 ; i++) {
+                    int j = inb (ata->port + AR_STATUS);
+                    if (  (j & (ARS_DRQ | ARS_BSY)) == ARS_BSY )
+                        break;
+                }
+                if (i == 2 ) {
+                if (atapi_wait (ata->port, 0) < 0) {
+                    ac->result.status = inb (ata->port + AR_STATUS);
+                    ac->result.error = inb (ata->port + AR_ERROR);
+                    ac->result.code = RES_NOTRDY;
+                    printf ("atapi%d.%d: controller not ready, status=%b, error= %b\n",
+                        ata->ctrlr, ac->unit, ac->result.status, ARS_BITS,
+                        ac->result.error, AER_BITS);
+                    return (0);
+                }
+ 
+                ac->result.status = inb (ata->port + AR_STATUS);
+                ac->result.error = inb (ata->port + AR_ERROR);
+                len = inb (ata->port + AR_CNTLO);
+                len |= inb (ata->port + AR_CNTHI) << 8;
+                ireason = inb (ata->port + AR_IREASON);
+ 
+                    goto complete;
+                /*
+                 * unfortunately, my Sony CDU-55E does assert BSY
+                 * but then forgets to generate the intrq at times...
+                 * Maybe I should check that len is a multiple of
+                 * the CDDA size (2352) and return anyways if
+                 * count == 0 ?
+                 */
+                 }
+ #endif
+ 
  		return (1);
  
  	case PHASE_ABORTED:
  	case PHASE_COMPLETED:
+ complete:
  		if (ac->result.status & (ARS_CHECK | ARS_DF))
  			ac->result.code = RES_ERR;
  		else if (ac->count < 0) {


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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980223173713.241D-100000>