diff options
| author | Jordan K. Hubbard <jkh@FreeBSD.org> | 1995-09-30 00:11:19 +0000 |
|---|---|---|
| committer | Jordan K. Hubbard <jkh@FreeBSD.org> | 1995-09-30 00:11:19 +0000 |
| commit | 5f614f1df91db97f51b628824f9977e442902e5c (patch) | |
| tree | 87850db51be9ef4ddcbde09f254a9ce4d20d0f96 /sys | |
| parent | a67ac8c6f2763ef7193f0d4391e18012d5979c41 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/i386/isa/atapi.c | 136 | ||||
| -rw-r--r-- | sys/i386/isa/atapi.h | 29 | ||||
| -rw-r--r-- | sys/i386/isa/wcd.c | 128 | ||||
| -rw-r--r-- | sys/i386/isa/wd.c | 27 | ||||
| -rw-r--r-- | sys/pc98/pc98/atapi.h | 29 |
5 files changed, 231 insertions, 118 deletions
diff --git a/sys/i386/isa/atapi.c b/sys/i386/isa/atapi.c index 75e18a48fc545..540c2bd2d26b3 100644 --- a/sys/i386/isa/atapi.c +++ b/sys/i386/isa/atapi.c @@ -11,7 +11,7 @@ * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * - * Version 1.3, Mon Aug 28 21:44:01 MSD 1995 + * Version 1.5, Thu Sep 21 23:08:11 MSD 1995 */ /* @@ -129,6 +129,7 @@ #define PHASE_DATAIN (ARS_DRQ | ARI_IN) #define PHASE_DATAOUT ARS_DRQ #define PHASE_COMPLETED (ARI_IN | ARI_CMD) +#define PHASE_ABORTED 0 /* nonstandard - for NEC 260 */ struct atapicmd { /* ATAPI command block */ struct atapicmd *next; /* next command in queue */ @@ -172,6 +173,7 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) struct atapi *ata = atapitab + ctlr; struct atapi_params *ap; char buf [sizeof(ap->model) + 1]; + char revbuf [sizeof(ap->revision) + 1]; struct atapicmd *ac; print (("atapi%d.%d at 0x%x: attach called\n", ctlr, unit, port)); @@ -181,7 +183,11 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) bcopy (ap->model, buf, sizeof(buf)-1); buf[sizeof(buf)-1] = 0; - printf ("wdc%d: unit %d (atapi): <%s>", ctlr, unit, buf); + + bcopy (ap->revision, revbuf, sizeof(revbuf)-1); + revbuf[sizeof(revbuf)-1] = 0; + + printf ("wdc%d: unit %d (atapi): <%s/%s>", ctlr, unit, buf, revbuf); /* device is removable */ if (ap->removable) @@ -199,7 +205,7 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) 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->cmdsz); + default: printf (", drq%d", ap->drqtype); } /* overlap operation supported */ @@ -242,22 +248,16 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) return; } switch (ap->devtype) { - default: /* unknown ATAPI device */ - printf ("wdc%d: unit %d: unknown ATAPI device type=%d\n", + default: + /* unknown ATAPI device */ + printf ("wdc%d: unit %d: unknown ATAPI type=%d\n", ctlr, unit, ap->devtype); break; - case AT_TYPE_DIRECT: /* direct-access (magnetic disk) */ -#if NWHD > 0 - /* Add your driver here */ -#else - printf ("wdc%d: ATAPI hard disks not supported\n", ctlr); - printf ("wdc%d: Could be old ATAPI CDROM, trying...\n", ctlr); - break; -#endif - + case AT_TYPE_DIRECT: /* direct-access */ case AT_TYPE_CDROM: /* CD-ROM device */ #if NWCD > 0 + /* ATAPI CD-ROM */ { int wcdattach (struct atapi*, int, struct atapi_params*, int, struct kern_devconf*); @@ -275,7 +275,7 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) #if NWMT > 0 /* Add your driver here */ #else - printf ("wdc%d: ATAPI streaming tapes not supported\n", ctlr); + printf ("wdc%d: ATAPI streaming tapes not supported yet\n", ctlr); break; #endif @@ -283,7 +283,7 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) #if NWMD > 0 /* Add your driver here */ #else - printf ("wdc%d: ATAPI optical disks not supported\n", ctlr); + printf ("wdc%d: ATAPI optical disks not supported yet\n", ctlr); break; #endif } @@ -291,6 +291,25 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) free (ap, M_TEMP); } +static void bswap (char *buf, int len) +{ + u_short *p = (u_short*) (buf + len); + while (--p >= (u_short*) buf) + *p = ntohs (*p); +} + +static void btrim (char *buf, int len) +{ + char *p; + + /* Remove the trailing spaces. */ + for (p=buf; p<buf+len; ++p) + if (! *p) + *p = ' '; + for (p=buf+len-1; p>=buf && *p==' '; --p) + *p = 0; +} + /* * Issue IDENTIFY command to ATAPI drive to ask it what it is. */ @@ -298,11 +317,10 @@ static struct atapi_params *atapi_probe (int port, int unit) { struct atapi_params *ap; char tb [DEV_BSIZE]; - int i; /* Wait for controller not busy. */ if (atapi_wait (port, 0) < 0) { - print (("atapi.%d at 0x%x: controller busy, status=%b\n", + print (("atapiX.%d at 0x%x: controller busy, status=%b\n", unit, port, inb (port + AR_STATUS), ARS_BITS)); return (0); } @@ -313,7 +331,7 @@ static struct atapi_params *atapi_probe (int port, int unit) /* Check that device is present. */ if (inb (port + AR_STATUS) == 0xff) { - print (("atapi.%d at 0x%x: no device\n", unit, port)); + print (("atapiX.%d at 0x%x: no device\n", unit, port)); if (unit == 1) /* Select unit 0. */ outb (port + AR_DRIVE, ARD_DRIVE0); @@ -322,7 +340,7 @@ static struct atapi_params *atapi_probe (int port, int unit) /* Wait for data ready. */ if (atapi_wait (port, ARS_DRQ) != 0) { - print (("atapi.%d at 0x%x: identify not ready, status=%b\n", + print (("atapiX.%d at 0x%x: identify not ready, status=%b\n", unit, port, inb (port + AR_STATUS), ARS_BITS)); if (unit == 1) /* Select unit 0. */ @@ -344,18 +362,15 @@ static struct atapi_params *atapi_probe (int port, int unit) */ if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') || (ap->model[0] == 'F' && ap->model[1] == 'X'))) { - u_short *p = (u_short*) (ap->model + sizeof(ap->model)); - while (--p >= (u_short*) ap->model) - *p = ntohs (*p); + bswap (ap->model, sizeof(ap->model)); + bswap (ap->serial, sizeof(ap->serial)); + bswap (ap->revision, sizeof(ap->revision)); } - /* Clean up the model by converting nulls to spaces, and - * then removing the trailing spaces. */ - for (i=0; i < sizeof(ap->model); i++) - if (! ap->model[i]) - ap->model[i] = ' '; - for (i=sizeof(ap->model)-1; i>=0 && ap->model[i]==' '; i--) - ap->model[i] = 0; + /* Clean up the model name, serial and revision numbers. */ + btrim (ap->model, sizeof(ap->model)); + btrim (ap->serial, sizeof(ap->serial)); + btrim (ap->revision, sizeof(ap->revision)); return (ap); } @@ -585,7 +600,7 @@ int atapi_intr (int ctrlr) int atapi_io (struct atapi *ata, struct atapicmd *ac) { u_char ireason; - u_short len; + u_short len, i; if (atapi_wait (ata->port, 0) < 0) { ac->result.status = inb (ata->port + AR_STATUS); @@ -635,12 +650,16 @@ int atapi_io (struct atapi *ata, struct atapicmd *ac) break; } if (-ac->count < len) { - printf ("atapi%d.%d: send data underrun, %d bytes left\n", - ata->ctrlr, ac->unit, -ac->count); + print (("atapi%d.%d: send data underrun, %d bytes left\n", + ata->ctrlr, ac->unit, -ac->count)); ac->result.code = RES_UNDERRUN; - break; - } - outsw (ata->port + AR_DATA, ac->addr, len / sizeof(short)); + outsw (ata->port + AR_DATA, ac->addr, + -ac->count / sizeof(short)); + for (i= -ac->count; i<len; i+=sizeof(short)) + outw (ata->port + AR_DATA, 0); + } else + outsw (ata->port + AR_DATA, ac->addr, + len / sizeof(short)); ac->addr += len; ac->count += len; return (1); @@ -654,34 +673,35 @@ int atapi_io (struct atapi *ata, struct atapicmd *ac) break; } if (ac->count < len) { - printf ("atapi%d.%d: recv data overrun, %d bytes left\n", - ata->ctrlr, ac->unit, ac->count); + print (("atapi%d.%d: recv data overrun, %d bytes left\n", + ata->ctrlr, ac->unit, ac->count)); ac->result.code = RES_OVERRUN; - break; - } - insw (ata->port + AR_DATA, ac->addr, len / sizeof(short)); + 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); + } else + insw (ata->port + AR_DATA, ac->addr, + len / sizeof(short)); ac->addr += len; ac->count -= len; return (1); + case PHASE_ABORTED: case PHASE_COMPLETED: - if (ac->result.status & (ARS_CHECK | ARS_DF)) { + if (ac->result.status & (ARS_CHECK | ARS_DF)) ac->result.code = RES_ERR; - break; - } - if (ac->count < 0) { - printf ("atapi%d.%d: send data overrun, %d bytes left\n", - ata->ctrlr, ac->unit, -ac->count); + else if (ac->count < 0) { + print (("atapi%d.%d: send data overrun, %d bytes left\n", + ata->ctrlr, ac->unit, -ac->count)); ac->result.code = RES_OVERRUN; - break; - } - if (ac->count > 0) { - printf ("atapi%d.%d: recv data underrun, %d bytes left\n", - ata->ctrlr, ac->unit, ac->count); + } else if (ac->count > 0) { + print (("atapi%d.%d: recv data underrun, %d bytes left\n", + ata->ctrlr, ac->unit, ac->count)); ac->result.code = RES_UNDERRUN; - break; - } - ac->result.code = RES_OK; + bzero (ac->addr, ac->count); + } else + ac->result.code = RES_OK; break; } return (0); @@ -818,6 +838,12 @@ struct atapires atapi_request_immediate (struct atapi *ata, int unit, /* Send packet command. */ atapi_send_cmd (ata, ac); + /* Wait for data i/o phase. */ + for (cnt=20000; cnt>0; --cnt) + if (((inb (ata->port + AR_IREASON) & (ARI_CMD | ARI_IN)) | + (inb (ata->port + AR_STATUS) & ARS_DRQ)) != PHASE_CMDOUT) + break; + /* Do all needed i/o. */ while (atapi_io (ata, ac)) /* Wait for DRQ deassert. */ diff --git a/sys/i386/isa/atapi.h b/sys/i386/isa/atapi.h index 7374acdcf010e..cb46dccea0aa5 100644 --- a/sys/i386/isa/atapi.h +++ b/sys/i386/isa/atapi.h @@ -11,7 +11,7 @@ * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * - * Version 1.1, Mon Jul 10 21:55:11 MSD 1995 + * Version 1.8, Thu Sep 28 20:24:38 MSK 1995 */ /* @@ -90,7 +90,7 @@ #define ATAPIC_PACKET 0xa0 /* execute packet command */ /* - * Packet commands + * Mandatory packet commands */ #define ATAPI_TEST_UNIT_READY 0x00 /* check if the device is ready */ #define ATAPI_REQUEST_SENSE 0x03 /* get sense data */ @@ -100,11 +100,20 @@ #define ATAPI_READ_BIG 0x28 /* read data */ #define ATAPI_READ_TOC 0x43 /* get table of contents */ #define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */ -#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */ -#define ATAPI_PLAY_TRACK 0x48 /* play by track number */ -#define ATAPI_PAUSE 0x4b /* stop/start audio operation */ #define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */ #define ATAPI_MODE_SENSE 0x5a /* get device parameters */ +#define ATAPI_PLAY_CD 0xb4 /* universal play command */ + +/* + * Optional packet commands + */ +#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */ +#define ATAPI_PAUSE 0x4b /* stop/start audio operation */ + +/* + * Nonstandard packet commands + */ +#define ATAPI_PLAY_TRACK 0x48 /* play by track number */ #define ATAPI_PLAY_BIG 0xa5 /* play by logical block address */ /* @@ -112,21 +121,21 @@ */ struct atapi_params { unsigned cmdsz : 2; /* packet command size */ -#define AT_PSIZE_12 0 -#define AT_PSIZE_16 1 +#define AT_PSIZE_12 0 /* 12 bytes */ +#define AT_PSIZE_16 1 /* 16 bytes */ unsigned : 3; unsigned drqtype : 2; /* DRQ type */ #define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */ #define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */ #define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */ unsigned removable : 1; /* device is removable */ - unsigned devtype : 5; /* packet command size */ + unsigned devtype : 5; /* device type */ #define AT_TYPE_DIRECT 0 /* direct-access (magnetic disk) */ #define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */ #define AT_TYPE_CDROM 5 /* CD-ROM device */ #define AT_TYPE_OPTICAL 7 /* optical disk */ unsigned : 1; - unsigned proto : 2; /* packet command size */ + unsigned proto : 2; /* command protocol */ #define AT_PROTO_ATAPI 2 short reserved1[9]; char serial[20]; /* serial number - optional */ @@ -146,7 +155,7 @@ struct atapi_params { short reserved4; u_short pio_timing; /* PIO cycle timing */ u_short dma_timing; /* DMA cycle timing */ - u_short flags; /* flags */ + u_short flags; #define AT_FLAG_54_58 1 /* words 54-58 valid */ #define AT_FLAG_64_70 2 /* words 64-70 valid */ short reserved5[8]; diff --git a/sys/i386/isa/wcd.c b/sys/i386/isa/wcd.c index 76cb6407dfadc..a5a2dffc5a24b 100644 --- a/sys/i386/isa/wcd.c +++ b/sys/i386/isa/wcd.c @@ -12,12 +12,9 @@ * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * - * Version 1.2, Mon Jul 24 17:21:25 MSD 1995 + * Version 1.8, Thu Sep 28 21:04:16 MSK 1995 */ -/* - * The driver was tested on Toshiba XM-5302TA drive. (vak) - */ #include "wdc.h" #include "wcd.h" #if NWCD > 0 && NWDC > 0 && defined (ATAPI) @@ -35,13 +32,14 @@ #include <i386/include/cpufunc.h> #include <i386/isa/atapi.h> -#define NUNIT (NWDC*2) /* Max. number of devices */ -#define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */ -#define SECSIZE 2048 /* CD-ROM sector size in bytes */ +#define NUNIT (NWDC*2) /* Max. number of devices */ +#define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */ +#define SECSIZE 2048 /* CD-ROM sector size in bytes */ -#define F_OPEN 0x0001 /* The drive os opened */ -#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */ -#define F_DEBUG 0x0004 /* The media have changed since open */ +#define F_OPEN 0x0001 /* The drive os opened */ +#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */ +#define F_DEBUG 0x0004 /* The media have changed since open */ +#define F_NOPLAYCD 0x0008 /* The PLAY_CD op not supported */ /* * Disc table of contents. @@ -166,6 +164,19 @@ struct cappage { u_short max_vol_levels; /* number of discrete volume levels */ u_short buf_size; /* internal buffer size in bytes/1024 */ u_short cur_speed; /* current data rate in bytes/1000 */ + + /* Digital drive output format description (optional?) */ + u_char reserved3; + u_char bckf : 1; /* data valid on failing edge of BCK */ + u_char rch : 1; /* high LRCK indicates left channel */ + u_char lsbf : 1; /* set if LSB first */ + u_char dlen: 2; +#define DLEN_32 0 /* 32 BCKs */ +#define DLEN_16 1 /* 16 BCKs */ +#define DLEN_24 2 /* 24 BCKs */ +#define DLEN_24_I2S 3 /* 24 BCKs (I2S) */ + u_char : 3; + u_char reserved4[2]; }; struct wcd { @@ -262,16 +273,22 @@ void wcdattach (struct atapi *ata, int unit, struct atapi_params *ap, int debug, } /* Get drive capabilities. */ - /* Do it twice to avoid the stale media changed state. */ result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE, 0, CAP_PAGE, 0, 0, 0, 0, sizeof (t->cap) >> 8, sizeof (t->cap), 0, 0, 0, 0, 0, 0, 0, (char*) &t->cap, sizeof (t->cap)); - if (result.code == RES_ERR && result.error == AER_SK_UNIT_ATTENTION) + /* 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 (t->cap) >> 8, sizeof (t->cap), 0, 0, 0, 0, 0, 0, 0, (char*) &t->cap, sizeof (t->cap)); + + /* Some drives have shorter capabilities page. */ + if (result.code == RES_UNDERRUN) + result.code = 0; + if (result.code == 0) { wcd_describe (t); if (t->flags & F_DEBUG) @@ -302,7 +319,7 @@ void wcd_describe (struct wcd *t) printf ("wcd%d: ", t->lun); if (t->cap.cur_speed != t->cap.max_speed) printf ("%d/", t->cap.cur_speed * 1000 / 1024); - printf ("%dKb/sec", t->cap.max_speed * 1000 / 1024, t->cap.buf_size); + printf ("%dKb/sec", t->cap.max_speed * 1000 / 1024); if (t->cap.buf_size) printf (", %dKb cache", t->cap.buf_size); @@ -373,7 +390,8 @@ int wcdopen (dev_t dev, int flags, int fmt, struct proc *p) result = atapi_request_wait (t->ata, t->unit, ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if (result.code == RES_ERR && result.error == AER_SK_UNIT_ATTENTION) { + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) { t->flags |= F_MEDIA_CHANGED; result = atapi_request_wait (t->ata, t->unit, ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0, @@ -386,15 +404,19 @@ int wcdopen (dev_t dev, int flags, int fmt, struct proc *p) /* Read table of contents. */ if (wcd_read_toc (t) != 0) - return (EIO); + bzero (&t->toc, sizeof (t->toc)); /* Read disc capacity. */ if (wcd_request_wait (t, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, sizeof(t->info), 0, (char*)&t->info, sizeof(t->info)) != 0) - return (EIO); + bzero (&t->info, sizeof (t->info)); t->info.volsize = ntohl (t->info.volsize); t->info.blksize = ntohl (t->info.blksize); - if (t->flags & (F_MEDIA_CHANGED | F_DEBUG)) { + + /* Print the disc description string on every disc change. + * It would help to track the history of disc changes. */ + if (t->info.volsize && t->toc.hdr.ending_track && + (t->flags & F_MEDIA_CHANGED) && (t->flags & F_DEBUG)) { printf ("wcd%d: ", t->lun); if (t->toc.tab[0].control & 4) printf ("%ldMB ", t->info.volsize / 512); @@ -538,37 +560,34 @@ static void wcd_error (struct wcd *t, struct atapires result) { if (result.code != RES_ERR) return; - switch (result.error) { + switch (result.error & AER_SKEY) { case AER_SK_NOT_READY: + if (result.error & ~AER_SKEY) { + /* Audio disc. */ + printf ("wcd%d: cannot read audio disc\n", t->lun); + return; + } /* Tray open. */ if (! (t->flags & F_MEDIA_CHANGED)) printf ("wcd%d: tray open\n", t->lun); t->flags |= F_MEDIA_CHANGED; - break; + return; case AER_SK_UNIT_ATTENTION: /* Media changed. */ if (! (t->flags & F_MEDIA_CHANGED)) printf ("wcd%d: media changed\n", t->lun); t->flags |= F_MEDIA_CHANGED; - break; - - case AER_SK_NOT_READY | AER_ILI | AER_EOM: - /* Audio disc. */ - printf ("wcd%d: cannot read audio disc\n", t->lun); - break; + return; case AER_SK_ILLEGAL_REQUEST: /* Unknown command or invalid command arguments. */ if (t->flags & F_DEBUG) printf ("wcd%d: invalid command\n", t->lun); - break; - - default: - printf ("wcd%d: i/o error, status=%b, error=%b\n", t->lun, - result.status, ARS_BITS, result.error, AER_BITS); - break; + return; } + printf ("wcd%d: i/o error, status=%b, error=%b\n", t->lun, + result.status, ARS_BITS, result.error, AER_BITS); } static int wcd_request_wait (struct wcd *t, u_char cmd, u_char a1, u_char a2, @@ -589,6 +608,34 @@ static int wcd_request_wait (struct wcd *t, u_char cmd, u_char a1, u_char a2, return (0); } +static int wcd_play (struct wcd *t, u_char cmd, u_char a1, u_char a2, + u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8, + u_char a9, char *addr, int count) +{ + struct atapires result; + + if (! (t->flags & F_NOPLAYCD)) { + t->cf.kdc_state = DC_BUSY; + result = atapi_request_wait (t->ata, t->unit, ATAPI_PLAY_CD, + cmd == ATAPI_PLAY_MSF ? 2 : 0, a2, a3, a4, a5, a6, + a7, a8, a9, 0, 0, 0, 0, 0, 0, addr, count); + t->cf.kdc_state = DC_IDLE; + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_ILLEGAL_REQUEST) { + /* Some drives don't support a PLAY_CD command. + * Remember this and use PLAY_MSF instead. */ + t->flags |= F_NOPLAYCD; + result.code = 0; + } + if (result.code) { + wcd_error (t, result); + return (EIO); + } + } + return wcd_request_wait (t, cmd, a1, a2, a3, a4, a5, a6, + a7, a8, a9, addr, count); +} + static inline void lba2msf (int lba, u_char *m, u_char *s, u_char *f) { lba += 150; /* offset of first logical frame */ @@ -617,11 +664,15 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) return (ENOTTY); case CDIOCSETDEBUG: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); t->flags |= F_DEBUG; atapi_debug (t->ata, 1); return 0; case CDIOCCLRDEBUG: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); t->flags &= ~F_DEBUG; atapi_debug (t->ata, 0); return 0; @@ -651,6 +702,8 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); case CDIOCRESET: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); return wcd_request_wait (t, ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @@ -668,6 +721,8 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0); case CDIOREADTOCHEADER: + if (! t->toc.hdr.ending_track) + return (ENODEV); bcopy (&t->toc.hdr, addr, sizeof t->toc.hdr); break; @@ -678,6 +733,8 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) struct toc buf; u_long len; + if (! t->toc.hdr.ending_track) + return (ENODEV); if (te->starting_track < toc->hdr.starting_track || te->starting_track > toc->hdr.ending_track) return (EINVAL); @@ -751,14 +808,14 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) case CDIOCPLAYMSF: { struct ioc_play_msf *args = (struct ioc_play_msf*) addr; - return wcd_request_wait (t, ATAPI_PLAY_MSF, 0, 0, + return wcd_play (t, ATAPI_PLAY_MSF, 0, 0, args->start_m, args->start_s, args->start_f, args->end_m, args->end_s, args->end_f, 0, 0, 0); } case CDIOCPLAYBLOCKS: { struct ioc_play_blocks *args = (struct ioc_play_blocks*) addr; - return wcd_request_wait (t, ATAPI_PLAY_BIG, 0, + return wcd_play (t, ATAPI_PLAY_BIG, 0, args->blk >> 24 & 0xff, args->blk >> 16 & 0xff, args->blk >> 8 & 0xff, args->blk & 0xff, args->len >> 24 & 0xff, args->len >> 16 & 0xff, @@ -769,6 +826,9 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) u_long start, len; int t1, t2; + if (! t->toc.hdr.ending_track) + return (ENODEV); + /* Ignore index fields, * play from start_track to end_track inclusive. */ if (args->end_track < t->toc.hdr.ending_track+1) @@ -782,7 +842,7 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) start = t->toc.tab[t1].addr.lba; len = t->toc.tab[t2].addr.lba - start; - return wcd_request_wait (t, ATAPI_PLAY_BIG, 0, + return wcd_play (t, ATAPI_PLAY_BIG, 0, start >> 24 & 0xff, start >> 16 & 0xff, start >> 8 & 0xff, start & 0xff, len >> 24 & 0xff, len >> 16 & 0xff, diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 66f16e0e8db67..2fe5fda5caf33 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.83 1995/09/06 05:06:18 dyson Exp $ + * $Id: wd.c,v 1.84 1995/09/07 08:20:18 swallace Exp $ */ /* TODO: @@ -299,6 +299,7 @@ wdprobe(struct isa_device *dvp) wdc_registerdev(dvp); /* check if we have registers that work */ + outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */ outb(du->dk_port + wd_cyl_lo, 0xa5); /* wd_cyl_lo is read/write */ if (inb(du->dk_port + wd_cyl_lo) == 0xff) /* XXX too weak */ goto nodevice; @@ -1900,22 +1901,30 @@ wdflushirq(struct disk *du, int old_ipl) static int wdreset(struct disk *du) { - int wdc; + int wdc, err; wdc = du->dk_port; (void)wdwait(du, 0, TIMEOUT); outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST); DELAY(10 * 1000); outb(wdc + wd_ctlr, WDCTL_IDS); - if (wdwait(du, 0, TIMEOUT) != 0) - return (1); - du->dk_status = inb(wdc + wd_status); + err = 0; + if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0) + err = 1; /* no IDE drive found */ du->dk_error = inb(wdc + wd_error); - if ((du->dk_status & ~(WDCS_READY | WDCS_SEEKCMPLT)) != 0 || - du->dk_error != 0x01) - return (1); + if (du->dk_error != 0x01) + err = 1; /* the drive is incompatible */ +#ifdef ATAPI + if (err) { + /* no IDE drive, test for ATAPI signature */ + int lo = inb(wdc + wd_cyl_lo); + int hi = inb(wdc + wd_cyl_hi); + if (lo == 0x14 && hi == 0xeb) + err = 0; /* ATAPI drive detected */ + } +#endif outb(wdc + wd_ctlr, WDCTL_4BIT); - return (0); + return (err); } /* diff --git a/sys/pc98/pc98/atapi.h b/sys/pc98/pc98/atapi.h index 7374acdcf010e..cb46dccea0aa5 100644 --- a/sys/pc98/pc98/atapi.h +++ b/sys/pc98/pc98/atapi.h @@ -11,7 +11,7 @@ * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * - * Version 1.1, Mon Jul 10 21:55:11 MSD 1995 + * Version 1.8, Thu Sep 28 20:24:38 MSK 1995 */ /* @@ -90,7 +90,7 @@ #define ATAPIC_PACKET 0xa0 /* execute packet command */ /* - * Packet commands + * Mandatory packet commands */ #define ATAPI_TEST_UNIT_READY 0x00 /* check if the device is ready */ #define ATAPI_REQUEST_SENSE 0x03 /* get sense data */ @@ -100,11 +100,20 @@ #define ATAPI_READ_BIG 0x28 /* read data */ #define ATAPI_READ_TOC 0x43 /* get table of contents */ #define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */ -#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */ -#define ATAPI_PLAY_TRACK 0x48 /* play by track number */ -#define ATAPI_PAUSE 0x4b /* stop/start audio operation */ #define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */ #define ATAPI_MODE_SENSE 0x5a /* get device parameters */ +#define ATAPI_PLAY_CD 0xb4 /* universal play command */ + +/* + * Optional packet commands + */ +#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */ +#define ATAPI_PAUSE 0x4b /* stop/start audio operation */ + +/* + * Nonstandard packet commands + */ +#define ATAPI_PLAY_TRACK 0x48 /* play by track number */ #define ATAPI_PLAY_BIG 0xa5 /* play by logical block address */ /* @@ -112,21 +121,21 @@ */ struct atapi_params { unsigned cmdsz : 2; /* packet command size */ -#define AT_PSIZE_12 0 -#define AT_PSIZE_16 1 +#define AT_PSIZE_12 0 /* 12 bytes */ +#define AT_PSIZE_16 1 /* 16 bytes */ unsigned : 3; unsigned drqtype : 2; /* DRQ type */ #define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */ #define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */ #define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */ unsigned removable : 1; /* device is removable */ - unsigned devtype : 5; /* packet command size */ + unsigned devtype : 5; /* device type */ #define AT_TYPE_DIRECT 0 /* direct-access (magnetic disk) */ #define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */ #define AT_TYPE_CDROM 5 /* CD-ROM device */ #define AT_TYPE_OPTICAL 7 /* optical disk */ unsigned : 1; - unsigned proto : 2; /* packet command size */ + unsigned proto : 2; /* command protocol */ #define AT_PROTO_ATAPI 2 short reserved1[9]; char serial[20]; /* serial number - optional */ @@ -146,7 +155,7 @@ struct atapi_params { short reserved4; u_short pio_timing; /* PIO cycle timing */ u_short dma_timing; /* DMA cycle timing */ - u_short flags; /* flags */ + u_short flags; #define AT_FLAG_54_58 1 /* words 54-58 valid */ #define AT_FLAG_64_70 2 /* words 64-70 valid */ short reserved5[8]; |
