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