Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/amiga/dev Add some ATAPI support. My CDROM drive w...
details: https://anonhg.NetBSD.org/src/rev/3c73233b7a60
branches: trunk
changeset: 467590:3c73233b7a60
user: mhitch <mhitch%NetBSD.org@localhost>
date: Fri Mar 26 07:00:37 1999 +0000
description:
Add some ATAPI support. My CDROM drive works, but I don't have other devices to
test. This should provide interim ATAPI support until the MI wdc driver is used.
diffstat:
sys/arch/amiga/dev/idesc.c | 560 ++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 535 insertions(+), 25 deletions(-)
diffs (truncated from 754 to 300 lines):
diff -r ece02b947dce -r 3c73233b7a60 sys/arch/amiga/dev/idesc.c
--- a/sys/arch/amiga/dev/idesc.c Fri Mar 26 06:54:40 1999 +0000
+++ b/sys/arch/amiga/dev/idesc.c Fri Mar 26 07:00:37 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: idesc.c,v 1.36 1999/01/10 13:35:39 tron Exp $ */
+/* $NetBSD: idesc.c,v 1.37 1999/03/26 07:00:37 mhitch Exp $ */
/*
* Copyright (c) 1994 Michael L. Hitch
@@ -73,8 +73,6 @@
* A4000 IDE interface, emulating a SCSI controller
*/
-#include "idesc.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
@@ -92,12 +90,17 @@
#include <dev/scsipi/scsipi_disk.h>
#include <dev/scsipi/scsi_disk.h>
#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/atapi_all.h>
+#include <dev/ata/atareg.h>
#include <amiga/amiga/device.h>
#include <amiga/amiga/cia.h>
#include <amiga/amiga/custom.h>
#include <amiga/amiga/isr.h>
#include <amiga/dev/zbusvar.h>
+#include "atapibus.h"
+#include "idesc.h"
+
#define b_cylin b_resid
/* defines */
@@ -109,6 +112,7 @@
#define ide_precomp ide_error
char ____pad1[3];
volatile u_char ide_seccnt; /* 0a */
+#define ide_ireason ide_seccnt /* interrupt reason (ATAPI) */
char ____pad2[3];
volatile u_char ide_sector; /* 0e */
char ____pad3[3];
@@ -152,6 +156,24 @@
#define IDEC_READP 0xec
#define IDECTL_IDS 0x02 /* Interrupt disable */
+#define IDECTL_RST 0x04 /* Controller reset */
+
+/* ATAPI commands */
+#define ATAPI_NOP 0x00
+#define ATAPI_SOFT_RST 0x08
+#define ATAPI_PACKET 0xa0
+#define ATAPI_IDENTIFY 0xa1
+
+/* ATAPI ireason */
+#define IDEI_CMD 0x01 /* command(1) or data(0) */
+#define IDEI_IN 0x02 /* transfer to(1) to from(0) host */
+#define IDEI_RELEASE 0x04 /* bus released until finished */
+
+#define PHASE_CMDOUT (IDES_DRQ | IDEI_CMD)
+#define PHASE_DATAIN (IDES_DRQ | IDEI_IN)
+#define PHASE_DATAOUT (IDES_DRQ)
+#define PHASE_COMPLETED (IDEI_IN | IDEI_CMD)
+#define PHASE_ABORTED (0)
struct ideparams {
/* drive info */
@@ -194,6 +216,9 @@
long sc_blkcnt; /* block count of active request */
int sc_flags;
#define IDEF_ALIVE 0x01 /* it's a valid device */
+#define IDEF_ATAPI 0x02 /* it's an ATAPI device */
+#define IDEF_ACAPLEN 0x04
+#define IDEF_ACAPDRQ 0x08
short sc_error;
char sc_drive;
char sc_state;
@@ -233,6 +258,8 @@
int state;
int saved;
int retry;
+ char sc_status;
+ char sc_error;
char sc_stat[2];
struct ide_softc sc_ide[2];
};
@@ -253,6 +280,11 @@
void ide_scsidone __P((struct idec_softc *, int));
void ide_donextcmd __P((struct idec_softc *));
int idesc_intr __P((void *));
+int ide_atapi_icmd __P((struct idec_softc *, int, void *, int, void *, int));
+
+int ide_atapi_start __P((struct idec_softc *));
+int ide_atapi_intr __P((struct idec_softc *));
+void ide_atapi_done __P((struct idec_softc *));
struct scsipi_device idesc_scsidev = {
NULL, /* use default error handler */
@@ -274,6 +306,7 @@
{ 0x0002, 0x04, 0x06}, /* Reference position not found */
{ 0x0004, 0x05, 0x20}, /* Invalid command */
{ 0x0010, 0x03, 0x12}, /* ID address mark not found */
+ { 0x0020, 0x06, 0x00}, /* Media changed */
{ 0x0040, 0x03, 0x11}, /* Unrecovered read error */
{ 0x0080, 0x03, 0x11}, /* Bad block mark detected */
{ 0x0000, 0x05, 0x00} /* unknown */
@@ -354,6 +387,21 @@
if (ide_debug)
ide_dump_regs(rp);
#endif
+ if (idereset(sc) != 0) {
+#ifdef DEBUG_ATAPI
+ printf("\nIDE reset failed, checking ATAPI ");
+#endif
+ rp->ide_sdh = 0xb0; /* slave */
+#ifdef DEBUG_ATAPI
+ printf(" cyl lo %x hi %x\n", rp->ide_cyl_lo, rp->ide_cyl_hi);
+#endif
+ delay(500000);
+ idereset(sc);
+ }
+#ifdef DEBUG_ATAPI
+ if (rp->ide_cyl_lo == 0x14 && rp->ide_cyl_hi == 0xeb)
+ printf(" ATAPI drive present?\n");
+#endif
rp->ide_error = 0x5a;
rp->ide_cyl_lo = 0xa5;
if (rp->ide_error == 0x5a || rp->ide_cyl_lo != 0xa5) {
@@ -389,8 +437,83 @@
for (i = 0; i < 2; ++i) {
rp->ide_sdh = 0xa0 | (i << 4);
sc->sc_ide[i].sc_drive = i;
- if ((rp->ide_status & IDES_READY) == 0)
- continue;
+ if ((rp->ide_status & IDES_READY) == 0) {
+ int len;
+ struct ataparams id;
+ u_short *p = (u_short *)&id;
+
+ sc->sc_ide[i].sc_flags |= IDEF_ATAPI;
+ if (idecommand(&sc->sc_ide[i], 0, 0, 0, 0, ATAPI_SOFT_RST)
+ != 0) {
+ printf("\nATAPI_SOFT_RESET failed for drive %d",
+ i);
+ continue;
+ }
+ if (wait_for_unbusy(sc) != 0) {
+ printf("\nATAPI wait for unbusy failed");
+ continue;
+ }
+ if (idecommand(&sc->sc_ide[i], 0, 0, 0,
+ sizeof(struct ataparams), ATAPI_IDENTIFY) != 0 ||
+ wait_for_drq(sc) != 0) {
+ printf("\nATAPI_IDENTIFY failed for drive %d",
+ i);
+ continue;
+ }
+ len = rp->ide_cyl_lo + rp->ide_cyl_hi * 256;
+#ifdef DEBUG_ATAPI
+ printf("\nATAPI_IDENTIFY returned %d/%d bytes",
+ len, sizeof(struct ataparams));
+#endif
+ while (len) {
+ if (p < (u_short *)(&id + 1))
+ *p++ = rp->ide_data;
+ else
+ rp->ide_data;
+ len -= 2;
+ }
+ bswap(id.atap_model, sizeof(id.atap_model));
+ bswap(id.atap_serial, sizeof(id.atap_serial));
+ bswap(id.atap_revision, sizeof(id.atap_revision));
+ strncpy(sc->sc_ide[i].sc_params.idep_model, id.atap_model,
+ sizeof(sc->sc_ide[i].sc_params.idep_model));
+ strncpy(sc->sc_ide[i].sc_params.idep_rev, id.atap_revision,
+ sizeof(sc->sc_ide[i].sc_params.idep_rev));
+ for (len = sizeof(id.atap_model) - 1;
+ id.atap_model[len] == ' ' && len != 0; --len)
+ ;
+ if (len < sizeof(id.atap_model) - 1)
+ id.atap_model[len] = 0;
+ for (len = sizeof(id.atap_serial) - 1;
+ id.atap_serial[len] == ' ' && len != 0; --len)
+ ;
+ if (len < sizeof(id.atap_serial) - 1)
+ id.atap_serial[len] = 0;
+ for (len = sizeof(id.atap_revision) - 1;
+ id.atap_revision[len] == ' ' && len != 0; --len)
+ ;
+ if (len < sizeof(id.atap_revision) - 1)
+ id.atap_revision[len] = 0;
+ bswap((char *)&id.atap_config, sizeof(id.atap_config));
+#ifdef DEBUG_ATAPI
+ printf("\nATAPI device: type %x", ATAPI_CFG_TYPE(id.atap_config));
+ printf(" cyls %04x heads %04x",
+ id.atap_cylinders, id.atap_heads);
+ printf(" bpt %04x bps %04x",
+ id.__retired1[0],
+ id.__retired2[0]);
+ printf(" drq_rem %02x", id.atap_config& 0xff);
+ printf("\n model %s rev %s ser %s", id.atap_model,
+ id.atap_revision, id.atap_serial);
+ printf("\n cap %04x%04x sect %04x%04x",
+ id.atap_curcapacity[0], id.atap_curcapacity[1],
+ id.atap_capacity[0], id.atap_capacity[1]);
+#endif
+ if (id.atap_config & ATAPI_CFG_CMD_16)
+ sc->sc_ide[i].sc_flags |= IDEF_ACAPLEN;
+ if ((id.atap_config & ATAPI_CFG_DRQ_MASK) == ATAPI_CFG_IRQ_DRQ)
+ sc->sc_ide[i].sc_flags |= IDEF_ACAPDRQ;
+ }
sc->sc_ide[i].sc_flags |= IDEF_ALIVE;
rp->ide_ctlr = 0;
}
@@ -504,7 +627,8 @@
else
stat = dev->sc_stat[0];
- ide_scsidone(dev, stat);
+ if (dev->sc_xs)
+ ide_scsidone(dev, stat);
}
void
@@ -577,6 +701,8 @@
struct scsipi_sense rqs;
struct scsipi_link *slp;
+ if (dev->sc_cur->sc_flags & IDEF_ATAPI)
+ return (0);
slp = xs->sc_link;
rqs.opcode = REQUEST_SENSE;
@@ -610,6 +736,17 @@
idereset(sc)
struct idec_softc *sc;
{
+ ide_regmap_p regs=sc->sc_cregs;
+
+ regs->ide_ctlr = IDECTL_RST | IDECTL_IDS;
+ delay(1000);
+ regs->ide_ctlr = IDECTL_IDS;
+ delay(1000);
+ (void) regs->ide_error;
+ if (wait_for_unbusy(sc) < 0) {
+ printf("%s: reset failed\n", sc->sc_dev.dv_xname);
+ return (1);
+ }
return (0);
}
@@ -620,34 +757,39 @@
{
ide_regmap_p regs = sc->sc_cregs;
int timeout = 0;
+ int status = sc->sc_status = regs->ide_status;
- if ((regs->ide_status & IDES_BUSY) == 0 &&
- (regs->ide_status & mask) == mask)
+ if ((status & IDES_BUSY) == 0 && (status & mask) == mask)
return (0);
#ifdef DEBUG
if (ide_debug)
- printf ("idewait busy: %02x\n", regs->ide_status);
+ printf ("idewait busy: %02x\n", status);
#endif
for (;;) {
- if ((regs->ide_status & IDES_BUSY) == 0 &&
- (regs->ide_status & mask) == mask)
+ status = sc->sc_status = regs->ide_status;
+ if ((status & IDES_BUSY) == 0 && (status & mask) == mask)
break;
- if (regs->ide_status & IDES_ERR)
+#if 0
+ if (status & IDES_ERR)
break;
+#endif
if (++timeout > 10000) {
- printf ("idewait timeout %02x\n", regs->ide_status);
+ printf ("idewait timeout status %02x error %02x\n",
+ status, regs->ide_error);
return (-1);
}
delay (1000);
}
- if (regs->ide_status & IDES_ERR)
- printf ("idewait: error %02x %02x\n", regs->ide_error,
- regs->ide_status);
+ if (status & IDES_ERR) {
+ sc->sc_error = regs->ide_error;
+ printf ("idewait: status %02x error %02x\n", status,
+ sc->sc_error);
+ }
#ifdef DEBUG
else if (ide_debug)
- printf ("idewait delay %d %02x\n", timeout, regs->ide_status);
+ printf ("idewait delay %d %02x\n", timeout, status);
#endif
Home |
Main Index |
Thread Index |
Old Index