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>
