Bring IDE CDROM support up to latest version (1.8a?) from Serge.
Submitted by: vak@cronyx.ru
This commit is contained in:
parent
a67ac8c6f2
commit
5f614f1df9
@ -11,7 +11,7 @@
|
|||||||
* or modify this software as long as this message is kept with the software,
|
* or modify this software as long as this message is kept with the software,
|
||||||
* all derivative works or modified versions.
|
* 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_DATAIN (ARS_DRQ | ARI_IN)
|
||||||
#define PHASE_DATAOUT ARS_DRQ
|
#define PHASE_DATAOUT ARS_DRQ
|
||||||
#define PHASE_COMPLETED (ARI_IN | ARI_CMD)
|
#define PHASE_COMPLETED (ARI_IN | ARI_CMD)
|
||||||
|
#define PHASE_ABORTED 0 /* nonstandard - for NEC 260 */
|
||||||
|
|
||||||
struct atapicmd { /* ATAPI command block */
|
struct atapicmd { /* ATAPI command block */
|
||||||
struct atapicmd *next; /* next command in queue */
|
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 *ata = atapitab + ctlr;
|
||||||
struct atapi_params *ap;
|
struct atapi_params *ap;
|
||||||
char buf [sizeof(ap->model) + 1];
|
char buf [sizeof(ap->model) + 1];
|
||||||
|
char revbuf [sizeof(ap->revision) + 1];
|
||||||
struct atapicmd *ac;
|
struct atapicmd *ac;
|
||||||
|
|
||||||
print (("atapi%d.%d at 0x%x: attach called\n", ctlr, unit, port));
|
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);
|
bcopy (ap->model, buf, sizeof(buf)-1);
|
||||||
buf[sizeof(buf)-1] = 0;
|
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 */
|
/* device is removable */
|
||||||
if (ap->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_MPROC: ata->slow = 1; break;
|
||||||
case AT_DRQT_INTR: printf (", intr"); ata->intrcmd = 1; break;
|
case AT_DRQT_INTR: printf (", intr"); ata->intrcmd = 1; break;
|
||||||
case AT_DRQT_ACCEL: printf (", accel"); break;
|
case AT_DRQT_ACCEL: printf (", accel"); break;
|
||||||
default: printf (", drq%d", ap->cmdsz);
|
default: printf (", drq%d", ap->drqtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* overlap operation supported */
|
/* overlap operation supported */
|
||||||
@ -242,22 +248,16 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (ap->devtype) {
|
switch (ap->devtype) {
|
||||||
default: /* unknown ATAPI device */
|
default:
|
||||||
printf ("wdc%d: unit %d: unknown ATAPI device type=%d\n",
|
/* unknown ATAPI device */
|
||||||
|
printf ("wdc%d: unit %d: unknown ATAPI type=%d\n",
|
||||||
ctlr, unit, ap->devtype);
|
ctlr, unit, ap->devtype);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AT_TYPE_DIRECT: /* direct-access (magnetic disk) */
|
case AT_TYPE_DIRECT: /* direct-access */
|
||||||
#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_CDROM: /* CD-ROM device */
|
case AT_TYPE_CDROM: /* CD-ROM device */
|
||||||
#if NWCD > 0
|
#if NWCD > 0
|
||||||
|
/* ATAPI CD-ROM */
|
||||||
{
|
{
|
||||||
int wcdattach (struct atapi*, int, struct atapi_params*,
|
int wcdattach (struct atapi*, int, struct atapi_params*,
|
||||||
int, struct kern_devconf*);
|
int, struct kern_devconf*);
|
||||||
@ -275,7 +275,7 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent)
|
|||||||
#if NWMT > 0
|
#if NWMT > 0
|
||||||
/* Add your driver here */
|
/* Add your driver here */
|
||||||
#else
|
#else
|
||||||
printf ("wdc%d: ATAPI streaming tapes not supported\n", ctlr);
|
printf ("wdc%d: ATAPI streaming tapes not supported yet\n", ctlr);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent)
|
|||||||
#if NWMD > 0
|
#if NWMD > 0
|
||||||
/* Add your driver here */
|
/* Add your driver here */
|
||||||
#else
|
#else
|
||||||
printf ("wdc%d: ATAPI optical disks not supported\n", ctlr);
|
printf ("wdc%d: ATAPI optical disks not supported yet\n", ctlr);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -291,6 +291,25 @@ void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent)
|
|||||||
free (ap, M_TEMP);
|
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.
|
* 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;
|
struct atapi_params *ap;
|
||||||
char tb [DEV_BSIZE];
|
char tb [DEV_BSIZE];
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Wait for controller not busy. */
|
/* Wait for controller not busy. */
|
||||||
if (atapi_wait (port, 0) < 0) {
|
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));
|
unit, port, inb (port + AR_STATUS), ARS_BITS));
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -313,7 +331,7 @@ static struct atapi_params *atapi_probe (int port, int unit)
|
|||||||
|
|
||||||
/* Check that device is present. */
|
/* Check that device is present. */
|
||||||
if (inb (port + AR_STATUS) == 0xff) {
|
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)
|
if (unit == 1)
|
||||||
/* Select unit 0. */
|
/* Select unit 0. */
|
||||||
outb (port + AR_DRIVE, ARD_DRIVE0);
|
outb (port + AR_DRIVE, ARD_DRIVE0);
|
||||||
@ -322,7 +340,7 @@ static struct atapi_params *atapi_probe (int port, int unit)
|
|||||||
|
|
||||||
/* Wait for data ready. */
|
/* Wait for data ready. */
|
||||||
if (atapi_wait (port, ARS_DRQ) != 0) {
|
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));
|
unit, port, inb (port + AR_STATUS), ARS_BITS));
|
||||||
if (unit == 1)
|
if (unit == 1)
|
||||||
/* Select unit 0. */
|
/* 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') ||
|
if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') ||
|
||||||
(ap->model[0] == 'F' && ap->model[1] == 'X'))) {
|
(ap->model[0] == 'F' && ap->model[1] == 'X'))) {
|
||||||
u_short *p = (u_short*) (ap->model + sizeof(ap->model));
|
bswap (ap->model, sizeof(ap->model));
|
||||||
while (--p >= (u_short*) ap->model)
|
bswap (ap->serial, sizeof(ap->serial));
|
||||||
*p = ntohs (*p);
|
bswap (ap->revision, sizeof(ap->revision));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the model by converting nulls to spaces, and
|
/* Clean up the model name, serial and revision numbers. */
|
||||||
* then removing the trailing spaces. */
|
btrim (ap->model, sizeof(ap->model));
|
||||||
for (i=0; i < sizeof(ap->model); i++)
|
btrim (ap->serial, sizeof(ap->serial));
|
||||||
if (! ap->model[i])
|
btrim (ap->revision, sizeof(ap->revision));
|
||||||
ap->model[i] = ' ';
|
|
||||||
for (i=sizeof(ap->model)-1; i>=0 && ap->model[i]==' '; i--)
|
|
||||||
ap->model[i] = 0;
|
|
||||||
return (ap);
|
return (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +600,7 @@ int atapi_intr (int ctrlr)
|
|||||||
int atapi_io (struct atapi *ata, struct atapicmd *ac)
|
int atapi_io (struct atapi *ata, struct atapicmd *ac)
|
||||||
{
|
{
|
||||||
u_char ireason;
|
u_char ireason;
|
||||||
u_short len;
|
u_short len, i;
|
||||||
|
|
||||||
if (atapi_wait (ata->port, 0) < 0) {
|
if (atapi_wait (ata->port, 0) < 0) {
|
||||||
ac->result.status = inb (ata->port + AR_STATUS);
|
ac->result.status = inb (ata->port + AR_STATUS);
|
||||||
@ -635,12 +650,16 @@ int atapi_io (struct atapi *ata, struct atapicmd *ac)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (-ac->count < len) {
|
if (-ac->count < len) {
|
||||||
printf ("atapi%d.%d: send data underrun, %d bytes left\n",
|
print (("atapi%d.%d: send data underrun, %d bytes left\n",
|
||||||
ata->ctrlr, ac->unit, -ac->count);
|
ata->ctrlr, ac->unit, -ac->count));
|
||||||
ac->result.code = RES_UNDERRUN;
|
ac->result.code = RES_UNDERRUN;
|
||||||
break;
|
outsw (ata->port + AR_DATA, ac->addr,
|
||||||
}
|
-ac->count / sizeof(short));
|
||||||
outsw (ata->port + AR_DATA, ac->addr, len / 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->addr += len;
|
||||||
ac->count += len;
|
ac->count += len;
|
||||||
return (1);
|
return (1);
|
||||||
@ -654,34 +673,35 @@ int atapi_io (struct atapi *ata, struct atapicmd *ac)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ac->count < len) {
|
if (ac->count < len) {
|
||||||
printf ("atapi%d.%d: recv data overrun, %d bytes left\n",
|
print (("atapi%d.%d: recv data overrun, %d bytes left\n",
|
||||||
ata->ctrlr, ac->unit, ac->count);
|
ata->ctrlr, ac->unit, ac->count));
|
||||||
ac->result.code = RES_OVERRUN;
|
ac->result.code = RES_OVERRUN;
|
||||||
break;
|
insw (ata->port + AR_DATA, ac->addr,
|
||||||
}
|
ac->count / sizeof(short));
|
||||||
insw (ata->port + AR_DATA, ac->addr, len / 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->addr += len;
|
||||||
ac->count -= len;
|
ac->count -= len;
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
|
case PHASE_ABORTED:
|
||||||
case PHASE_COMPLETED:
|
case PHASE_COMPLETED:
|
||||||
if (ac->result.status & (ARS_CHECK | ARS_DF)) {
|
if (ac->result.status & (ARS_CHECK | ARS_DF))
|
||||||
ac->result.code = RES_ERR;
|
ac->result.code = RES_ERR;
|
||||||
break;
|
else if (ac->count < 0) {
|
||||||
}
|
print (("atapi%d.%d: send data overrun, %d bytes left\n",
|
||||||
if (ac->count < 0) {
|
ata->ctrlr, ac->unit, -ac->count));
|
||||||
printf ("atapi%d.%d: send data overrun, %d bytes left\n",
|
|
||||||
ata->ctrlr, ac->unit, -ac->count);
|
|
||||||
ac->result.code = RES_OVERRUN;
|
ac->result.code = RES_OVERRUN;
|
||||||
break;
|
} else if (ac->count > 0) {
|
||||||
}
|
print (("atapi%d.%d: recv data underrun, %d bytes left\n",
|
||||||
if (ac->count > 0) {
|
ata->ctrlr, ac->unit, ac->count));
|
||||||
printf ("atapi%d.%d: recv data underrun, %d bytes left\n",
|
|
||||||
ata->ctrlr, ac->unit, ac->count);
|
|
||||||
ac->result.code = RES_UNDERRUN;
|
ac->result.code = RES_UNDERRUN;
|
||||||
break;
|
bzero (ac->addr, ac->count);
|
||||||
}
|
} else
|
||||||
ac->result.code = RES_OK;
|
ac->result.code = RES_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
@ -818,6 +838,12 @@ struct atapires atapi_request_immediate (struct atapi *ata, int unit,
|
|||||||
/* Send packet command. */
|
/* Send packet command. */
|
||||||
atapi_send_cmd (ata, ac);
|
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. */
|
/* Do all needed i/o. */
|
||||||
while (atapi_io (ata, ac))
|
while (atapi_io (ata, ac))
|
||||||
/* Wait for DRQ deassert. */
|
/* Wait for DRQ deassert. */
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* or modify this software as long as this message is kept with the software,
|
* or modify this software as long as this message is kept with the software,
|
||||||
* all derivative works or modified versions.
|
* 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 */
|
#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_TEST_UNIT_READY 0x00 /* check if the device is ready */
|
||||||
#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
|
#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
|
||||||
@ -100,11 +100,20 @@
|
|||||||
#define ATAPI_READ_BIG 0x28 /* read data */
|
#define ATAPI_READ_BIG 0x28 /* read data */
|
||||||
#define ATAPI_READ_TOC 0x43 /* get table of contents */
|
#define ATAPI_READ_TOC 0x43 /* get table of contents */
|
||||||
#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
|
#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_SELECT_BIG 0x55 /* set device parameters */
|
||||||
#define ATAPI_MODE_SENSE 0x5a /* get 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 */
|
#define ATAPI_PLAY_BIG 0xa5 /* play by logical block address */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -112,21 +121,21 @@
|
|||||||
*/
|
*/
|
||||||
struct atapi_params {
|
struct atapi_params {
|
||||||
unsigned cmdsz : 2; /* packet command size */
|
unsigned cmdsz : 2; /* packet command size */
|
||||||
#define AT_PSIZE_12 0
|
#define AT_PSIZE_12 0 /* 12 bytes */
|
||||||
#define AT_PSIZE_16 1
|
#define AT_PSIZE_16 1 /* 16 bytes */
|
||||||
unsigned : 3;
|
unsigned : 3;
|
||||||
unsigned drqtype : 2; /* DRQ type */
|
unsigned drqtype : 2; /* DRQ type */
|
||||||
#define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */
|
#define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */
|
||||||
#define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */
|
#define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */
|
||||||
#define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */
|
#define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */
|
||||||
unsigned removable : 1; /* device is removable */
|
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_DIRECT 0 /* direct-access (magnetic disk) */
|
||||||
#define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */
|
#define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */
|
||||||
#define AT_TYPE_CDROM 5 /* CD-ROM device */
|
#define AT_TYPE_CDROM 5 /* CD-ROM device */
|
||||||
#define AT_TYPE_OPTICAL 7 /* optical disk */
|
#define AT_TYPE_OPTICAL 7 /* optical disk */
|
||||||
unsigned : 1;
|
unsigned : 1;
|
||||||
unsigned proto : 2; /* packet command size */
|
unsigned proto : 2; /* command protocol */
|
||||||
#define AT_PROTO_ATAPI 2
|
#define AT_PROTO_ATAPI 2
|
||||||
short reserved1[9];
|
short reserved1[9];
|
||||||
char serial[20]; /* serial number - optional */
|
char serial[20]; /* serial number - optional */
|
||||||
@ -146,7 +155,7 @@ struct atapi_params {
|
|||||||
short reserved4;
|
short reserved4;
|
||||||
u_short pio_timing; /* PIO cycle timing */
|
u_short pio_timing; /* PIO cycle timing */
|
||||||
u_short dma_timing; /* DMA 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_54_58 1 /* words 54-58 valid */
|
||||||
#define AT_FLAG_64_70 2 /* words 64-70 valid */
|
#define AT_FLAG_64_70 2 /* words 64-70 valid */
|
||||||
short reserved5[8];
|
short reserved5[8];
|
||||||
|
@ -12,12 +12,9 @@
|
|||||||
* or modify this software as long as this message is kept with the software,
|
* or modify this software as long as this message is kept with the software,
|
||||||
* all derivative works or modified versions.
|
* 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 "wdc.h"
|
||||||
#include "wcd.h"
|
#include "wcd.h"
|
||||||
#if NWCD > 0 && NWDC > 0 && defined (ATAPI)
|
#if NWCD > 0 && NWDC > 0 && defined (ATAPI)
|
||||||
@ -35,13 +32,14 @@
|
|||||||
#include <i386/include/cpufunc.h>
|
#include <i386/include/cpufunc.h>
|
||||||
#include <i386/isa/atapi.h>
|
#include <i386/isa/atapi.h>
|
||||||
|
|
||||||
#define NUNIT (NWDC*2) /* Max. number of devices */
|
#define NUNIT (NWDC*2) /* Max. number of devices */
|
||||||
#define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */
|
#define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */
|
||||||
#define SECSIZE 2048 /* CD-ROM sector size in bytes */
|
#define SECSIZE 2048 /* CD-ROM sector size in bytes */
|
||||||
|
|
||||||
#define F_OPEN 0x0001 /* The drive os opened */
|
#define F_OPEN 0x0001 /* The drive os opened */
|
||||||
#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */
|
#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */
|
||||||
#define F_DEBUG 0x0004 /* 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.
|
* Disc table of contents.
|
||||||
@ -166,6 +164,19 @@ struct cappage {
|
|||||||
u_short max_vol_levels; /* number of discrete volume levels */
|
u_short max_vol_levels; /* number of discrete volume levels */
|
||||||
u_short buf_size; /* internal buffer size in bytes/1024 */
|
u_short buf_size; /* internal buffer size in bytes/1024 */
|
||||||
u_short cur_speed; /* current data rate in bytes/1000 */
|
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 {
|
struct wcd {
|
||||||
@ -262,16 +273,22 @@ void wcdattach (struct atapi *ata, int unit, struct atapi_params *ap, int debug,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get drive capabilities. */
|
/* Get drive capabilities. */
|
||||||
/* Do it twice to avoid the stale media changed state. */
|
|
||||||
result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE,
|
result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE,
|
||||||
0, CAP_PAGE, 0, 0, 0, 0, sizeof (t->cap) >> 8, sizeof (t->cap),
|
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));
|
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,
|
result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE,
|
||||||
0, CAP_PAGE, 0, 0, 0, 0, sizeof (t->cap) >> 8,
|
0, CAP_PAGE, 0, 0, 0, 0, sizeof (t->cap) >> 8,
|
||||||
sizeof (t->cap), 0, 0, 0, 0, 0, 0, 0,
|
sizeof (t->cap), 0, 0, 0, 0, 0, 0, 0,
|
||||||
(char*) &t->cap, sizeof (t->cap));
|
(char*) &t->cap, sizeof (t->cap));
|
||||||
|
|
||||||
|
/* Some drives have shorter capabilities page. */
|
||||||
|
if (result.code == RES_UNDERRUN)
|
||||||
|
result.code = 0;
|
||||||
|
|
||||||
if (result.code == 0) {
|
if (result.code == 0) {
|
||||||
wcd_describe (t);
|
wcd_describe (t);
|
||||||
if (t->flags & F_DEBUG)
|
if (t->flags & F_DEBUG)
|
||||||
@ -302,7 +319,7 @@ void wcd_describe (struct wcd *t)
|
|||||||
printf ("wcd%d: ", t->lun);
|
printf ("wcd%d: ", t->lun);
|
||||||
if (t->cap.cur_speed != t->cap.max_speed)
|
if (t->cap.cur_speed != t->cap.max_speed)
|
||||||
printf ("%d/", t->cap.cur_speed * 1000 / 1024);
|
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)
|
if (t->cap.buf_size)
|
||||||
printf (", %dKb cache", 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,
|
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);
|
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;
|
t->flags |= F_MEDIA_CHANGED;
|
||||||
result = atapi_request_wait (t->ata, t->unit,
|
result = atapi_request_wait (t->ata, t->unit,
|
||||||
ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0,
|
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. */
|
/* Read table of contents. */
|
||||||
if (wcd_read_toc (t) != 0)
|
if (wcd_read_toc (t) != 0)
|
||||||
return (EIO);
|
bzero (&t->toc, sizeof (t->toc));
|
||||||
|
|
||||||
/* Read disc capacity. */
|
/* Read disc capacity. */
|
||||||
if (wcd_request_wait (t, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0,
|
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)
|
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.volsize = ntohl (t->info.volsize);
|
||||||
t->info.blksize = ntohl (t->info.blksize);
|
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);
|
printf ("wcd%d: ", t->lun);
|
||||||
if (t->toc.tab[0].control & 4)
|
if (t->toc.tab[0].control & 4)
|
||||||
printf ("%ldMB ", t->info.volsize / 512);
|
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)
|
if (result.code != RES_ERR)
|
||||||
return;
|
return;
|
||||||
switch (result.error) {
|
switch (result.error & AER_SKEY) {
|
||||||
case AER_SK_NOT_READY:
|
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. */
|
/* Tray open. */
|
||||||
if (! (t->flags & F_MEDIA_CHANGED))
|
if (! (t->flags & F_MEDIA_CHANGED))
|
||||||
printf ("wcd%d: tray open\n", t->lun);
|
printf ("wcd%d: tray open\n", t->lun);
|
||||||
t->flags |= F_MEDIA_CHANGED;
|
t->flags |= F_MEDIA_CHANGED;
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case AER_SK_UNIT_ATTENTION:
|
case AER_SK_UNIT_ATTENTION:
|
||||||
/* Media changed. */
|
/* Media changed. */
|
||||||
if (! (t->flags & F_MEDIA_CHANGED))
|
if (! (t->flags & F_MEDIA_CHANGED))
|
||||||
printf ("wcd%d: media changed\n", t->lun);
|
printf ("wcd%d: media changed\n", t->lun);
|
||||||
t->flags |= F_MEDIA_CHANGED;
|
t->flags |= F_MEDIA_CHANGED;
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case AER_SK_NOT_READY | AER_ILI | AER_EOM:
|
|
||||||
/* Audio disc. */
|
|
||||||
printf ("wcd%d: cannot read audio disc\n", t->lun);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AER_SK_ILLEGAL_REQUEST:
|
case AER_SK_ILLEGAL_REQUEST:
|
||||||
/* Unknown command or invalid command arguments. */
|
/* Unknown command or invalid command arguments. */
|
||||||
if (t->flags & F_DEBUG)
|
if (t->flags & F_DEBUG)
|
||||||
printf ("wcd%d: invalid command\n", t->lun);
|
printf ("wcd%d: invalid command\n", t->lun);
|
||||||
break;
|
return;
|
||||||
|
|
||||||
default:
|
|
||||||
printf ("wcd%d: i/o error, status=%b, error=%b\n", t->lun,
|
|
||||||
result.status, ARS_BITS, result.error, AER_BITS);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
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,
|
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);
|
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)
|
static inline void lba2msf (int lba, u_char *m, u_char *s, u_char *f)
|
||||||
{
|
{
|
||||||
lba += 150; /* offset of first logical frame */
|
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);
|
return (ENOTTY);
|
||||||
|
|
||||||
case CDIOCSETDEBUG:
|
case CDIOCSETDEBUG:
|
||||||
|
if (p->p_cred->pc_ucred->cr_uid)
|
||||||
|
return (EPERM);
|
||||||
t->flags |= F_DEBUG;
|
t->flags |= F_DEBUG;
|
||||||
atapi_debug (t->ata, 1);
|
atapi_debug (t->ata, 1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case CDIOCCLRDEBUG:
|
case CDIOCCLRDEBUG:
|
||||||
|
if (p->p_cred->pc_ucred->cr_uid)
|
||||||
|
return (EPERM);
|
||||||
t->flags &= ~F_DEBUG;
|
t->flags &= ~F_DEBUG;
|
||||||
atapi_debug (t->ata, 0);
|
atapi_debug (t->ata, 0);
|
||||||
return 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);
|
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
case CDIOCRESET:
|
case CDIOCRESET:
|
||||||
|
if (p->p_cred->pc_ucred->cr_uid)
|
||||||
|
return (EPERM);
|
||||||
return wcd_request_wait (t, ATAPI_TEST_UNIT_READY,
|
return wcd_request_wait (t, ATAPI_TEST_UNIT_READY,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
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);
|
0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
case CDIOREADTOCHEADER:
|
case CDIOREADTOCHEADER:
|
||||||
|
if (! t->toc.hdr.ending_track)
|
||||||
|
return (ENODEV);
|
||||||
bcopy (&t->toc.hdr, addr, sizeof t->toc.hdr);
|
bcopy (&t->toc.hdr, addr, sizeof t->toc.hdr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -678,6 +733,8 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
|
|||||||
struct toc buf;
|
struct toc buf;
|
||||||
u_long len;
|
u_long len;
|
||||||
|
|
||||||
|
if (! t->toc.hdr.ending_track)
|
||||||
|
return (ENODEV);
|
||||||
if (te->starting_track < toc->hdr.starting_track ||
|
if (te->starting_track < toc->hdr.starting_track ||
|
||||||
te->starting_track > toc->hdr.ending_track)
|
te->starting_track > toc->hdr.ending_track)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
@ -751,14 +808,14 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
|
|||||||
case CDIOCPLAYMSF: {
|
case CDIOCPLAYMSF: {
|
||||||
struct ioc_play_msf *args = (struct ioc_play_msf*) addr;
|
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->start_m, args->start_s, args->start_f,
|
||||||
args->end_m, args->end_s, args->end_f, 0, 0, 0);
|
args->end_m, args->end_s, args->end_f, 0, 0, 0);
|
||||||
}
|
}
|
||||||
case CDIOCPLAYBLOCKS: {
|
case CDIOCPLAYBLOCKS: {
|
||||||
struct ioc_play_blocks *args = (struct ioc_play_blocks*) addr;
|
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 >> 24 & 0xff, args->blk >> 16 & 0xff,
|
||||||
args->blk >> 8 & 0xff, args->blk & 0xff,
|
args->blk >> 8 & 0xff, args->blk & 0xff,
|
||||||
args->len >> 24 & 0xff, args->len >> 16 & 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;
|
u_long start, len;
|
||||||
int t1, t2;
|
int t1, t2;
|
||||||
|
|
||||||
|
if (! t->toc.hdr.ending_track)
|
||||||
|
return (ENODEV);
|
||||||
|
|
||||||
/* Ignore index fields,
|
/* Ignore index fields,
|
||||||
* play from start_track to end_track inclusive. */
|
* play from start_track to end_track inclusive. */
|
||||||
if (args->end_track < t->toc.hdr.ending_track+1)
|
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;
|
start = t->toc.tab[t1].addr.lba;
|
||||||
len = t->toc.tab[t2].addr.lba - start;
|
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 >> 24 & 0xff, start >> 16 & 0xff,
|
||||||
start >> 8 & 0xff, start & 0xff,
|
start >> 8 & 0xff, start & 0xff,
|
||||||
len >> 24 & 0xff, len >> 16 & 0xff,
|
len >> 24 & 0xff, len >> 16 & 0xff,
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
|
* 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:
|
/* TODO:
|
||||||
@ -299,6 +299,7 @@ wdprobe(struct isa_device *dvp)
|
|||||||
wdc_registerdev(dvp);
|
wdc_registerdev(dvp);
|
||||||
|
|
||||||
/* check if we have registers that work */
|
/* 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 */
|
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 */
|
if (inb(du->dk_port + wd_cyl_lo) == 0xff) /* XXX too weak */
|
||||||
goto nodevice;
|
goto nodevice;
|
||||||
@ -1900,22 +1901,30 @@ wdflushirq(struct disk *du, int old_ipl)
|
|||||||
static int
|
static int
|
||||||
wdreset(struct disk *du)
|
wdreset(struct disk *du)
|
||||||
{
|
{
|
||||||
int wdc;
|
int wdc, err;
|
||||||
|
|
||||||
wdc = du->dk_port;
|
wdc = du->dk_port;
|
||||||
(void)wdwait(du, 0, TIMEOUT);
|
(void)wdwait(du, 0, TIMEOUT);
|
||||||
outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
|
outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
|
||||||
DELAY(10 * 1000);
|
DELAY(10 * 1000);
|
||||||
outb(wdc + wd_ctlr, WDCTL_IDS);
|
outb(wdc + wd_ctlr, WDCTL_IDS);
|
||||||
if (wdwait(du, 0, TIMEOUT) != 0)
|
err = 0;
|
||||||
return (1);
|
if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
|
||||||
du->dk_status = inb(wdc + wd_status);
|
err = 1; /* no IDE drive found */
|
||||||
du->dk_error = inb(wdc + wd_error);
|
du->dk_error = inb(wdc + wd_error);
|
||||||
if ((du->dk_status & ~(WDCS_READY | WDCS_SEEKCMPLT)) != 0 ||
|
if (du->dk_error != 0x01)
|
||||||
du->dk_error != 0x01)
|
err = 1; /* the drive is incompatible */
|
||||||
return (1);
|
#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);
|
outb(wdc + wd_ctlr, WDCTL_4BIT);
|
||||||
return (0);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* or modify this software as long as this message is kept with the software,
|
* or modify this software as long as this message is kept with the software,
|
||||||
* all derivative works or modified versions.
|
* 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 */
|
#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_TEST_UNIT_READY 0x00 /* check if the device is ready */
|
||||||
#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
|
#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
|
||||||
@ -100,11 +100,20 @@
|
|||||||
#define ATAPI_READ_BIG 0x28 /* read data */
|
#define ATAPI_READ_BIG 0x28 /* read data */
|
||||||
#define ATAPI_READ_TOC 0x43 /* get table of contents */
|
#define ATAPI_READ_TOC 0x43 /* get table of contents */
|
||||||
#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
|
#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_SELECT_BIG 0x55 /* set device parameters */
|
||||||
#define ATAPI_MODE_SENSE 0x5a /* get 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 */
|
#define ATAPI_PLAY_BIG 0xa5 /* play by logical block address */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -112,21 +121,21 @@
|
|||||||
*/
|
*/
|
||||||
struct atapi_params {
|
struct atapi_params {
|
||||||
unsigned cmdsz : 2; /* packet command size */
|
unsigned cmdsz : 2; /* packet command size */
|
||||||
#define AT_PSIZE_12 0
|
#define AT_PSIZE_12 0 /* 12 bytes */
|
||||||
#define AT_PSIZE_16 1
|
#define AT_PSIZE_16 1 /* 16 bytes */
|
||||||
unsigned : 3;
|
unsigned : 3;
|
||||||
unsigned drqtype : 2; /* DRQ type */
|
unsigned drqtype : 2; /* DRQ type */
|
||||||
#define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */
|
#define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */
|
||||||
#define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */
|
#define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */
|
||||||
#define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */
|
#define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */
|
||||||
unsigned removable : 1; /* device is removable */
|
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_DIRECT 0 /* direct-access (magnetic disk) */
|
||||||
#define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */
|
#define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */
|
||||||
#define AT_TYPE_CDROM 5 /* CD-ROM device */
|
#define AT_TYPE_CDROM 5 /* CD-ROM device */
|
||||||
#define AT_TYPE_OPTICAL 7 /* optical disk */
|
#define AT_TYPE_OPTICAL 7 /* optical disk */
|
||||||
unsigned : 1;
|
unsigned : 1;
|
||||||
unsigned proto : 2; /* packet command size */
|
unsigned proto : 2; /* command protocol */
|
||||||
#define AT_PROTO_ATAPI 2
|
#define AT_PROTO_ATAPI 2
|
||||||
short reserved1[9];
|
short reserved1[9];
|
||||||
char serial[20]; /* serial number - optional */
|
char serial[20]; /* serial number - optional */
|
||||||
@ -146,7 +155,7 @@ struct atapi_params {
|
|||||||
short reserved4;
|
short reserved4;
|
||||||
u_short pio_timing; /* PIO cycle timing */
|
u_short pio_timing; /* PIO cycle timing */
|
||||||
u_short dma_timing; /* DMA 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_54_58 1 /* words 54-58 valid */
|
||||||
#define AT_FLAG_64_70 2 /* words 64-70 valid */
|
#define AT_FLAG_64_70 2 /* words 64-70 valid */
|
||||||
short reserved5[8];
|
short reserved5[8];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user