summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2006-11-06 20:28:20 +0000
committermiod <miod@openbsd.org>2006-11-06 20:28:20 +0000
commit4b97445288b9a171dbf15eb69c1345aaaf8e05ca (patch)
tree52d17dcb3dc0621c1c0181d470e8fd6413f79064
parentnoone needs to know about the D0 state change; ok miod (diff)
downloadwireguard-openbsd-4b97445288b9a171dbf15eb69c1345aaaf8e05ca.tar.xz
wireguard-openbsd-4b97445288b9a171dbf15eb69c1345aaaf8e05ca.zip
Sync the VS2000 (and some VS3100) MFM controller driver with NetBSD, and
enable it in GENERIC and RAMDISK. Completely untested due to lack of hardware (both my VS3100 are dual-SCSI), but it hopefully can't hurt.
-rw-r--r--sys/arch/vax/conf/GENERIC9
-rw-r--r--sys/arch/vax/conf/RAMDISK9
-rw-r--r--sys/arch/vax/vax/rootfil.c3
-rw-r--r--sys/arch/vax/vsa/hdc9224.c1368
-rw-r--r--sys/arch/vax/vsa/hdc9224.h16
5 files changed, 560 insertions, 845 deletions
diff --git a/sys/arch/vax/conf/GENERIC b/sys/arch/vax/conf/GENERIC
index 0ee5f498969..67c30fa724b 100644
--- a/sys/arch/vax/conf/GENERIC
+++ b/sys/arch/vax/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.47 2006/08/30 19:29:20 miod Exp $
+# $OpenBSD: GENERIC,v 1.48 2006/11/06 20:28:20 miod Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -61,7 +61,7 @@ le0 at vsbus0 csr 0x200e0000 # LANCE ethernet
ze0 at vsbus0 csr 0x20008000 # SGEC ethernet
dz0 at vsbus0 csr 0x200a0000 # DC-367 DZ-11 lookalike ctlr
dz0 at vsbus0 csr 0x25000000 # VS4000/90 4000/10X MV3100/9X serial
-#hdc0 at vsbus0 csr 0x200c0000 # HDC9224 MFM/floppy ctlr
+hdc0 at vsbus0 csr 0x200c0000 # HDC9224 MFM/floppy ctlr
ncr0 at vsbus0 csr 0x200c0080 # VS2000/3100 SCSI-ctlr
ncr1 at vsbus0 csr 0x200c0180 # VS2000/3100 SCSI-ctlr
asc0 at vsbus0 csr 0x200c0080 # VS4000/60 (or VLC) SCSI-ctlr
@@ -71,7 +71,7 @@ gpx0 at vsbus0 csr 0x3c000000 # VS3100 GPX display option
lcg0 at vsbus0 csr 0x20100000 # VS4000/60 (or VLC) frame buffer
lcspx0 at vsbus0 csr 0x39302000 # VS4000/90 frame buffer
-#hd* at hdc0 drive? # RD5x disks
+hd* at hdc0 drive? # RD5x disks
#ry* at hdc0 drive? # RX floppies
# Ibus, the internal bus on most Microvaxen
@@ -130,9 +130,6 @@ ra* at mscpbus? drive? # MSCP disk
rx* at mscpbus? drive? # MSCP floppy
mt* at mscpbus? drive? # MSCP tape
-# VS2000 builtin MFM controller (HDC9224)
-#hdc0 at vsbus0 # The strange builtin MFM controller
-
# SCSI devices
scsibus* at asc?
scsibus* at ncr?
diff --git a/sys/arch/vax/conf/RAMDISK b/sys/arch/vax/conf/RAMDISK
index 778a4b3042a..a0b6ae12940 100644
--- a/sys/arch/vax/conf/RAMDISK
+++ b/sys/arch/vax/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.27 2006/08/30 19:29:20 miod Exp $
+# $OpenBSD: RAMDISK,v 1.28 2006/11/06 20:28:20 miod Exp $
machine vax # machine type
@@ -69,7 +69,7 @@ le0 at vsbus0 csr 0x200e0000 # LANCE ethernet
ze0 at vsbus0 csr 0x20008000 # SGEC ethernet
dz0 at vsbus0 csr 0x200a0000 # DC-367 DZ-11 lookalike ctlr
dz0 at vsbus0 csr 0x25000000 # VS4000/90 4000/10X MV3100/9X serial
-#hdc0 at vsbus0 csr 0x200c0000 # HDC9224 MFM/floppy ctlr
+hdc0 at vsbus0 csr 0x200c0000 # HDC9224 MFM/floppy ctlr
ncr0 at vsbus0 csr 0x200c0080 # VS2000/3100 SCSI-ctlr
ncr1 at vsbus0 csr 0x200c0180 # VS2000/3100 SCSI-ctlr
asc0 at vsbus0 csr 0x200c0080 # VS4000/60 (or VLC) SCSI-ctlr
@@ -79,7 +79,7 @@ gpx0 at vsbus0 csr 0x3c000000 # VS3100 GPX display option
lcg0 at vsbus0 csr 0x20100000 # VS4000/60 (or VLC) frame buffer
lcspx0 at vsbus0 csr 0x39302000 # VS4000/90 frame buffer
-#hd* at hdc0 drive? # RD5x disks
+hd* at hdc0 drive? # RD5x disks
#ry* at hdc0 drive? # RX floppies
# Ibus, the internal bus on most Microvaxen
@@ -138,9 +138,6 @@ ra* at mscpbus? drive? # MSCP disk
rx* at mscpbus? drive? # MSCP floppy
mt* at mscpbus? drive? # MSCP tape
-# VS2000 builtin MFM controller (HDC9224)
-#hdc0 at vsbus0 # The strange builtin MFM controller
-
# SCSI devices
scsibus* at asc?
scsibus* at ncr?
diff --git a/sys/arch/vax/vax/rootfil.c b/sys/arch/vax/vax/rootfil.c
index 59d6afcf247..69e3a0392c7 100644
--- a/sys/arch/vax/vax/rootfil.c
+++ b/sys/arch/vax/vax/rootfil.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rootfil.c,v 1.18 2005/12/27 18:31:11 miod Exp $ */
+/* $OpenBSD: rootfil.c,v 1.19 2006/11/06 20:28:23 miod Exp $ */
/* $NetBSD: rootfil.c,v 1.14 1996/10/13 03:35:58 christos Exp $ */
/*
@@ -289,6 +289,7 @@ struct nam2blk {
{ "ra", 9 },
{ "rx", 12 },
{ "rl", 14 },
+ { "hd", 19 },
{ "sd", 20 },
{ "rd", 23 },
{ "raid", 25 },
diff --git a/sys/arch/vax/vsa/hdc9224.c b/sys/arch/vax/vsa/hdc9224.c
index 7abab2e74d5..c45fceaa751 100644
--- a/sys/arch/vax/vsa/hdc9224.c
+++ b/sys/arch/vax/vsa/hdc9224.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hdc9224.c,v 1.12 2005/02/17 23:49:25 miod Exp $ */
-/* $NetBSD: hdc9224.c,v 1.6 1997/03/15 16:32:22 ragge Exp $ */
+/* $OpenBSD: hdc9224.c,v 1.13 2006/11/06 20:28:23 miod Exp $ */
+/* $NetBSD: hdc9224.c,v 1.16 2001/07/26 15:05:09 wiz Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -39,21 +39,17 @@
* Roger Ivie
* Rick Macklem
* Mike Young
+ *
+ * Rewritten by Ragge 25 Jun 2000. New features:
+ * - Uses interrupts instead of polling to signal ready.
+ * - Can cooperate with the SCSI routines WRT. the DMA area.
+ *
+ * TODO:
+ * - Floppy support missing.
+ * - Bad block forwarding missing.
+ * - Statistics collection.
*/
-
-/* #define DEBUG /* */
-/* #define TRACE /* */
-static int haveLock = 0;
-static int keepLock = 0;
-
-#define F_READ 11
-#define F_WRITE 12
-
-#define trace(x)
-#define debug(x)
-
-#include "hdc.h"
-#if NHDC > 0
+#undef HDDEBUG
#include <sys/param.h>
#include <sys/systm.h>
@@ -66,12 +62,16 @@ static int keepLock = 0;
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/device.h>
-#include <sys/dkstat.h>
#include <sys/disklabel.h>
#include <sys/disk.h>
#include <sys/syslog.h>
#include <sys/reboot.h>
+#include <uvm/uvm_extern.h>
+
+#include <ufs/ufs/dinode.h> /* For BBSIZE */
+#include <ufs/ffs/fs.h>
+
#include <machine/pte.h>
#include <machine/sid.h>
#include <machine/cpu.h>
@@ -79,141 +79,131 @@ static int keepLock = 0;
#include <machine/ka410.h>
#include <machine/vsbus.h>
#include <machine/rpb.h>
+#include <machine/scb.h>
-#include <vax/vsa/hdc9224.h>
-
-
-/*
- * some definitions
- */
-#define CTLRNAME "hdc"
-#define UNITNAME "hd"
-#define HDC_PRI LOG_INFO
-
-/* Bits in minor device */
-#define HDCUNIT(dev) DISKUNIT(dev)
-#define HDCPART(dev) DISKPART(dev)
-#define HDCCTLR(dev) 0
-#define HDCLABELDEV(dev) (MAKEDISKDEV(major(dev),HDCUNIT(dev),RAW_PART))
-
-#define MAX_WAIT (1000*1000) /* # of loop-instructions in seconds */
+#include <arch/vax/mscp/mscp.h> /* For DEC disk encoding */
+#include <vax/vsa/hdc9224.h>
/*
* on-disk geometry block
*/
-#define _aP __attribute__ ((packed)) /* force byte-alignment */
struct hdgeom {
- char mbz[10]; /* 10 bytes of zero */
- long xbn_count _aP; /* number of XBNs */
- long dbn_count _aP; /* number of DBNs */
- long lbn_count _aP; /* number of LBNs (Logical-Block-Numbers) */
- long rbn_count _aP; /* number of RBNs (Replacement-Block-Numbers) */
- short nspt; /* number of sectors per track */
- short ntracks; /* number of tracks */
- short ncylinders; /* number of cylinders */
- short precomp; /* first cylinder for write precompensation */
- short reduced; /* first cylinder for reduced write current */
- short seek_rate; /* seek rate or zero for buffered seeks */
- short crc_eec; /* 0 if CRC is being used or 1 if ECC is being used */
- short rct; /* "replacement control table" (RCT) */
- short rct_ncopies; /* number of copies of the RCT */
- long media_id _aP; /* media identifier */
- short interleave; /* sector-to-sector interleave */
- short headskew; /* head-to-head skew */
- short cylskew; /* cylinder-to-cylinder skew */
- short gap0_size; /* size of GAP 0 in the MFM format */
- short gap1_size; /* size of GAP 1 in the MFM format */
- short gap2_size; /* size of GAP 2 in the MFM format */
- short gap3_size; /* size of GAP 3 in the MFM format */
- short sync_value; /* sync value used to start a track when formatting */
- char reserved[32]; /* reserved for use by the RQDX1/2/3 formatter */
- short serial_number; /* serial number */
+ char mbz[10]; /* 10 bytes of zero */
+ long xbn_count; /* number of XBNs */
+ long dbn_count; /* number of DBNs */
+ long lbn_count; /* number of LBNs (Logical-Block-Numbers) */
+ long rbn_count; /* number of RBNs (Replacement-Block-Numbers) */
+ short nspt; /* number of sectors per track */
+ short ntracks; /* number of tracks */
+ short ncylinders; /* number of cylinders */
+ short precomp; /* first cylinder for write precompensation */
+ short reduced; /* first cylinder for reduced write current */
+ short seek_rate; /* seek rate or zero for buffered seeks */
+ short crc_eec; /* 0 if CRC, 1 if ECC is being used */
+ short rct; /* "replacement control table" (RCT) */
+ short rct_ncopies; /* number of copies of the RCT */
+ long media_id; /* media identifier */
+ short interleave; /* sector-to-sector interleave */
+ short headskew; /* head-to-head skew */
+ short cylskew; /* cylinder-to-cylinder skew */
+ short gap0_size; /* size of GAP 0 in the MFM format */
+ short gap1_size; /* size of GAP 1 in the MFM format */
+ short gap2_size; /* size of GAP 2 in the MFM format */
+ short gap3_size; /* size of GAP 3 in the MFM format */
+ short sync_value; /* sync value used when formatting */
+ char reserved[32]; /* reserved for use by the RQDX formatter */
+ short serial_number; /* serial number */
#if 0 /* we don't need these 412 useless bytes ... */
- char fill[412-2]; /* Filler bytes to the end of the block */
- short checksum; /* checksum over the XBN */
+ char fill[412-2]; /* Filler bytes to the end of the block */
+ short checksum; /* checksum over the XBN */
#endif
-};
+} __packed;
/*
* Software status
*/
struct hdsoftc {
- struct device sc_dev; /* must be here! (pseudo-OOP:) */
- struct disk sc_dk; /* disklabel etc. */
- struct hdgeom sc_xbn; /* on-disk geometry information */
- struct hdparams {
- u_short cylinders; /* number of cylinders */
- u_char heads; /* number of heads (tracks) */
- u_char sectors; /* number of sectors/track */
- u_long diskblks; /* number of sectors/disk */
- u_long disklbns; /* number of available sectors */
- u_long blksize; /* number of bytes/sector */
- u_long diskbytes; /* number of bytes/disk */
- char diskname[8];
- } sc_param;
- int sc_drive; /* physical unit number */
- int sc_flags;
- int sc_state;
- int sc_mode;
+ struct device sc_dev; /* must be here! (pseudo-OOP:) */
+ struct disk sc_disk; /* disklabel etc. */
+ struct hdgeom sc_xbn; /* on-disk geometry information */
+ int sc_drive; /* physical unit number */
};
struct hdcsoftc {
struct device sc_dev; /* must be here (pseudo-OOP:) */
- struct hdc9224_DKCreg *sc_dkc; /* I/O address of the controller */
+ struct evcount sc_intrcnt;
+ struct vsbus_dma sc_vd;
+ vaddr_t sc_regs; /* register addresses */
+ struct buf sc_buf_queue;
+ struct buf *sc_active;
struct hdc9224_UDCreg sc_creg; /* (command) registers to be written */
struct hdc9224_UDCreg sc_sreg; /* (status) registers being read */
- struct confargs *sc_cfargs; /* remember args being probed with */
- char *sc_dmabase; /* */
- long sc_dmasize; /* */
- long sc_ioaddr; /* unmapped I/O address */
- long sc_ivec; /* interrupt vector address */
- short sc_ibit; /* bit-value in interrupt register */
- short sc_status; /* copy of status register */
- short sc_state;
- short sc_flags;
- short sc_errors;
+ caddr_t sc_dmabase; /* */
+ int sc_dmasize;
+ caddr_t sc_bufaddr; /* Current in-core address */
+ int sc_diskblk; /* Current block on disk */
+ int sc_bytecnt; /* How much left to transfer */
+ int sc_xfer; /* Current transfer size */
+ int sc_retries;
+ volatile u_char sc_status; /* last status from interrupt */
+ char sc_intbit;
+};
+
+struct hdc_attach_args {
+ int ha_drive;
};
/*
- * Device definition for (new) autoconfiguration.
+ * prototypes for (almost) all the internal routines
*/
-int hdcmatch(struct device *parent, void *cfdata, void *aux);
-void hdcattach(struct device *parent, struct device *self, void *aux);
-int hdcprint(void *aux, const char *name);
-
-struct cfdriver hdc_cd = {
- NULL, "hdc", DV_DULL
-};
-struct cfattach hdc_ca = {
+int hdcmatch(struct device *, void *, void *);
+void hdcattach(struct device *, struct device *, void *);
+int hdcprint(void *, const char *);
+int hdmatch(struct device *, void *, void *);
+void hdattach(struct device *, struct device *, void *);
+void hdcintr(void *);
+int hdc_command(struct hdcsoftc *, int);
+void hd_readgeom(struct hdcsoftc *, struct hdsoftc *);
+#ifdef HDDEBUG
+void hdc_printgeom( struct hdgeom *);
+#endif
+void hdc_writeregs(struct hdcsoftc *);
+void hdcstart(struct hdcsoftc *, struct buf *);
+int hdc_hdselect(struct hdcsoftc *, int);
+void hdmakelabel(struct disklabel *, struct hdgeom *);
+void hdc_writeregs(struct hdcsoftc *);
+void hdc_readregs(struct hdcsoftc *);
+void hdc_qstart(void *);
+
+bdev_decl(hd);
+cdev_decl(hd);
+
+const struct cfattach hdc_ca = {
sizeof(struct hdcsoftc), hdcmatch, hdcattach
};
-int hdmatch(struct device *parent, void *cfdata, void *aux);
-void hdattach(struct device *parent, struct device *self, void *aux);
-int hdprint(void *aux, const char *name);
-void hdstrategy(struct buf *bp);
-
-struct cfdriver hd_cd = {
- NULL, "hd", DV_DISK
+struct cfdriver hdc_cd = {
+ NULL, "hdc", DV_DULL
};
-struct cfattach hd_ca = {
+
+const struct cfattach hd_ca = {
sizeof(struct hdsoftc), hdmatch, hdattach
};
-struct dkdriver hddkdriver = { hdstrategy };
-
-/*
- * prototypes for (almost) all the internal routines
- */
-int hdc_reset(struct hdcsoftc *sc);
-int hdc_select(struct hdcsoftc *sc, int drive);
-int hdc_command(struct hdcsoftc *sc, int cmd);
+struct cfdriver hd_cd = {
+ NULL, "hd", DV_DISK
+};
-int hdc_getdata(struct hdcsoftc *hdc, struct hdsoftc *hd, int drive);
-int hdc_getlabel(struct hdcsoftc *hdc, struct hdsoftc *hd, int drive);
+/* At least 0.7 uS between register accesses */
+static int hd_dmasize, inq = 0; /* XXX should be in softc... but only 1 ctrl */
+static int u;
+#define WAIT asm("movl _u,_u;movl _u,_u;movl _u,_u; movl _u,_u")
-void hdgetlabel(struct hdsoftc *sc);
+#define HDC_WREG(x) *(volatile char *)(sc->sc_regs) = (x)
+#define HDC_RREG *(volatile char *)(sc->sc_regs)
+#define HDC_WCMD(x) *(volatile char *)(sc->sc_regs + 4) = (x)
+#define HDC_RSTAT *(volatile char *)(sc->sc_regs + 4)
/*
* new-config's hdcmatch() is similar to old-config's hdcprobe(),
@@ -222,391 +212,410 @@ void hdgetlabel(struct hdsoftc *sc);
* is not yet allocated. Thus we do this in hdcattach()...
*/
int
-hdcmatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+hdcmatch(struct device *parent, void *vcf, void *aux)
{
- struct cfdata *cf = match;
- struct confargs *ca = aux;
-
- trace(("hdcmatch(0x%x, %d, %s)\n", parent, cf->cf_unit, ca->ca_name));
+ static int matched = 0;
+ struct vsbus_attach_args *va = aux;
+ volatile char *hdc_csr = (char *)va->va_addr;
+ int i;
- if (strcmp(ca->ca_name, "hdc") &&
- strcmp(ca->ca_name, "hdc9224") &&
- strcmp(ca->ca_name, "HDC9224"))
+ if (vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_46 ||
+ vax_boardtype == VAX_BTYP_48 || vax_boardtype == VAX_BTYP_1303)
return (0);
- /*
- * only(?) VS2000/KA410 has exactly one HDC9224 controller
- */
- if (vax_boardtype != VAX_BTYP_410) {
- printf("unexpected boardtype 0x%x in hdcmatch()\n",
- vax_boardtype);
- return (0);
- }
- if (cf->cf_unit != 0)
+ /* Can only match once due to DMA setup. This should not be an issue. */
+ if (matched != 0)
return (0);
- return (1);
+ hdc_csr[4] = DKC_CMD_RESET; /* reset chip */
+ for (i = 0; i < 1000; i++) {
+ DELAY(1000);
+ if (hdc_csr[4] & DKC_ST_DONE)
+ break;
+ }
+ if (i == 100)
+ return 0; /* No response to reset */
+
+ hdc_csr[4] = DKC_CMD_SETREGPTR|UDC_TERM;
+ WAIT;
+ hdc_csr[0] = UDC_TC_CRCPRE|UDC_TC_INTDONE;
+ WAIT;
+ hdc_csr[4] = DKC_CMD_DRDESELECT; /* Should be harmless */
+ DELAY(1000);
+ return (matched = 1);
}
-struct hdc_attach_args {
- int ha_drive;
-};
-
int
-hdprint(aux, name)
- void *aux;
- const char *name;
+hdcprint(void *aux, const char *pnp)
{
struct hdc_attach_args *ha = aux;
- trace(("hdprint(%d, %s)\n", ha->ha_drive, name));
+ if (pnp != NULL)
+ printf("%s at %s drive %d",
+ ha->ha_drive == 2 ? "ry" : "hd", pnp, ha->ha_drive);
- if (!name)
- printf(" drive %d", ha->ha_drive);
- return (QUIET);
+ return (UNCONF);
}
/*
* hdc_attach() probes for all possible devices
*/
void
-hdcattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+hdcattach(struct device *parent, struct device *self, void *aux)
{
+ struct vsbus_attach_args *va = aux;
struct hdcsoftc *sc = (void *)self;
- struct confargs *ca = aux;
struct hdc_attach_args ha;
+ int status, i;
- trace(("hdcattach(0x%x, 0x%x, %s)\n", parent, self, ca->ca_name));
+ u = 0; /* !!! - GCC */
printf("\n");
+
/*
- * first reset/initialize the controller
+ * Get interrupt vector, enable instrumentation.
*/
- sc->sc_cfargs = ca;
+ scb_vecalloc(va->va_cvec, hdcintr, sc, SCB_ISTACK, &sc->sc_intrcnt);
+ evcount_attach(&sc->sc_intrcnt, self->dv_xname, (void *)va->va_cvec,
+ &evcount_intr);
- sc->sc_ioaddr = ca->ca_ioaddr;
- sc->sc_dkc = (void *)uvax_phys2virt(sc->sc_ioaddr);
- sc->sc_ibit = ca->ca_intbit;
- sc->sc_ivec = ca->ca_intvec;
- sc->sc_status = 0;
- sc->sc_state = 0;
- sc->sc_flags = 0;
- sc->sc_errors = 0;
-
- sc->sc_dkc = (void *)uvax_phys2virt(KA410_DKC_BASE);
- sc->sc_dmabase = (void *)uvax_phys2virt(KA410_DMA_BASE);
- sc->sc_dmasize = KA410_DMA_SIZE;
-
- if (hdc_reset(sc) != 0) {
- delay(500*1000); /* wait .5 seconds */
- if (hdc_reset(sc) != 0)
- printf("problems with hdc_reset()...\n");
- }
+ sc->sc_regs = vax_map_physmem(va->va_paddr, 1);
+ sc->sc_dmabase = (caddr_t)va->va_dmaaddr;
+ sc->sc_dmasize = va->va_dmasize;
+ sc->sc_intbit = va->va_maskno;
+ hd_dmasize = min(MAXPHYS, sc->sc_dmasize); /* Used in hd_minphys */
+
+ sc->sc_vd.vd_go = hdc_qstart;
+ sc->sc_vd.vd_arg = sc;
/*
- * now probe for all possible disks
+ * Reset controller.
*/
- for (ha.ha_drive=0; ha.ha_drive<3; ha.ha_drive++)
- (void)config_found(self, (void *)&ha, hdprint);
+ HDC_WCMD(DKC_CMD_RESET);
+ DELAY(1000);
+ status = HDC_RSTAT;
+ if (status != (DKC_ST_DONE|DKC_TC_SUCCESS)) {
+ printf("%s: RESET failed, status 0x%x\n",
+ sc->sc_dev.dv_xname, status);
+ return;
+ }
-#ifdef notyet
/*
- * now that probing is done, we can register and enable interrupts
+ * now probe for all possible hard drives
*/
- vsbus_intr_register(XXX);
- vsbus_intr_enable(XXX);
-#endif
+ for (i = 0; i < 4; i++) {
+ if (i == 2) /* Floppy, needs special handling */
+ continue;
+ HDC_WCMD(DKC_CMD_DRSELECT | i);
+ DELAY(1000);
+ status = HDC_RSTAT;
+ ha.ha_drive = i;
+ if ((status & DKC_ST_TERMCOD) == DKC_TC_SUCCESS)
+ config_found(self, (void *)&ha, hdcprint);
+ }
}
/*
- * hdmatch() probes for the existence of a RD-type disk/floppy
+ * hdmatch() probes for the existence of a HD-type disk/floppy
*/
int
-hdmatch(parent, match, aux)
+hdmatch(parent, vcf, aux)
struct device *parent;
- void *match, *aux;
+ void *vcf;
+ void *aux;
{
- struct hdcsoftc *hdc = (void *)parent;
- struct cfdata *cf = match;
struct hdc_attach_args *ha = aux;
- int drive = ha->ha_drive;
- int res;
+ struct cfdata *cf = vcf;
- trace(("hdmatch(%d, %d)\n", cf->cf_unit, drive));
+ if (cf->cf_loc[0] != -1 &&
+ cf->cf_loc[0] != ha->ha_drive)
+ return 0;
- if (cf->cf_unit != ha->ha_drive)
- return (0);
+ if (ha->ha_drive == 2) /* Always floppy, not supported */
+ return 0;
- switch (drive) {
- case 0:
- case 1:
- case 2:
- res = hdc_select(hdc, drive);
- break;
- default:
- printf("hdmatch: invalid unit-number %d\n", drive);
- return (0);
- }
-
- debug (("cstat: %x dstat: %x\n", hdc->sc_sreg.udc_cstat,
- hdc->sc_sreg.udc_dstat));
- if (drive == 1)
- return (0); /* XXX */
-
- return (1);
+ return 1;
}
+#define HDMAJOR 19
+
void
-hdattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+hdattach(struct device *parent, struct device *self, void *aux)
{
- struct hdcsoftc *hdc = (void *)parent;
- struct hdsoftc *hd = (void *)self;
+ struct hdcsoftc *sc = (void*)parent;
+ struct hdsoftc *hd = (void*)self;
struct hdc_attach_args *ha = aux;
- struct hdparams *hp = &hd->sc_param;
-
- trace(("hdattach(%d)\n", ha->ha_drive));
+ struct disklabel *dl;
+ char *msg;
hd->sc_drive = ha->ha_drive;
/*
* Initialize and attach the disk structure.
*/
- hd->sc_dk.dk_driver = &hddkdriver;
- hd->sc_dk.dk_name = hd->sc_dev.dv_xname;
- disk_attach(&hd->sc_dk);
+ hd->sc_disk.dk_name = hd->sc_dev.dv_xname;
+ disk_attach(&hd->sc_disk);
+
/*
* if it's not a floppy then evaluate the on-disk geometry.
* if necessary correct the label...
*/
- printf("\n%s: ", hd->sc_dev.dv_xname);
- if (hd->sc_drive == 2) {
- printf("floppy (RX33)\n");
+ hd_readgeom(sc, hd);
+ disk_printtype(hd->sc_drive, hd->sc_xbn.media_id);
+ dl = hd->sc_disk.dk_label;
+ hdmakelabel(dl, &hd->sc_xbn);
+ msg = readdisklabel(MAKEDISKDEV(HDMAJOR, hd->sc_dev.dv_unit, RAW_PART),
+ hdstrategy, dl, NULL, 0);
+ printf("%s: %luMB, %lu sectors\n",
+ hd->sc_dev.dv_xname, dl->d_secperunit / (1048576 / DEV_BSIZE),
+ dl->d_secperunit);
+ if (msg)
+ printf("%s: %s\n", hd->sc_dev.dv_xname, msg);
+#ifdef HDDEBUG
+ hdc_printgeom(&hd->sc_xbn);
+#endif
+}
+
+void
+hdcintr(void *arg)
+{
+ struct hdcsoftc *sc = arg;
+ struct buf *bp;
+
+ sc->sc_status = HDC_RSTAT;
+ if (sc->sc_active == 0)
+ return; /* Complain? */
+
+ if ((sc->sc_status & (DKC_ST_INTPEND | DKC_ST_DONE)) !=
+ (DKC_ST_INTPEND | DKC_ST_DONE))
+ return; /* Why spurious ints sometimes??? */
+
+ bp = sc->sc_active;
+ sc->sc_active = 0;
+ if ((sc->sc_status & DKC_ST_TERMCOD) != DKC_TC_SUCCESS) {
+ int i;
+ u_char *g = (u_char *)&sc->sc_sreg;
+
+ if (sc->sc_retries++ < 3) { /* Allow 3 retries */
+ hdcstart(sc, bp);
+ return;
+ }
+ printf("%s: failed, status 0x%x\n",
+ sc->sc_dev.dv_xname, sc->sc_status);
+ hdc_readregs(sc);
+ for (i = 0; i < 10; i++)
+ printf("%i: %x\n", i, g[i]);
+ bp->b_flags |= B_ERROR;
+ bp->b_error = ENXIO;
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+ vsbus_dma_intr();
+ return;
}
- else {
- hdc_getdata(hdc, hd, hd->sc_drive);
- printf("%s, %d MB, %d LBN, %d cyl, %d head, %d sect/track\n",
- hp->diskname, hp->diskblks / 2048, hp->disklbns,
- hp->cylinders, hp->heads, hp->sectors);
+
+ if (bp->b_flags & B_READ) {
+ vsbus_copytoproc(bp->b_proc, sc->sc_dmabase, sc->sc_bufaddr,
+ sc->sc_xfer);
}
- /*
- * Know where we booted from.
- */
- if ((B_TYPE(bootdev) == BDEV_RD) && (hd->sc_drive == B_UNIT(bootdev)))
- booted_from = self;
+ sc->sc_diskblk += (sc->sc_xfer/DEV_BSIZE);
+ sc->sc_bytecnt -= sc->sc_xfer;
+ sc->sc_bufaddr += sc->sc_xfer;
+
+ if (sc->sc_bytecnt == 0) { /* Finished transfer */
+ biodone(bp);
+ vsbus_dma_intr();
+ } else
+ hdcstart(sc, bp);
}
/*
- * Read/write routine for a buffer. For now we poll the controller,
- * thus this routine waits for the transfer to complete.
+ *
*/
void
-hdstrategy(bp)
- struct buf *bp;
+hdstrategy(struct buf *bp)
{
- struct hdsoftc *hd = hd_cd.cd_devs[HDCUNIT(bp->b_dev)];
- struct hdcsoftc *hdc = (void *)hd->sc_dev.dv_parent;
- struct partition *p;
- int blkno, i, s;
-
- trace (("hdstrategy(#%d/%d)\n", bp->b_blkno, bp->b_bcount));
+ struct hdsoftc *hd;
+ struct hdcsoftc *sc;
+ struct disklabel *lp;
+ int unit, s;
+ daddr_t bn;
+
+ unit = DISKUNIT(bp->b_dev);
+ if (unit > hd_cd.cd_ndevs || (hd = hd_cd.cd_devs[unit]) == NULL) {
+ bp->b_error = ENXIO;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+ sc = (void *)hd->sc_dev.dv_parent;
- /* XXX should make some checks... */
+ lp = hd->sc_disk.dk_label;
+ if ((bounds_check_with_label(bp, hd->sc_disk.dk_label,
+ hd->sc_disk.dk_cpulabel, 1)) <= 0)
+ goto done;
- /*
- * If it's a null transfer, return immediatly
- */
if (bp->b_bcount == 0)
goto done;
-
+
/*
- * what follows now should not be here but in hdstart...
+ * XXX Since we need to know blkno in hdcstart() and do not have a
+ * b_rawblkno field in struct buf (yet), abuse b_cylinder to store
+ * the block number instead of the cylinder number.
+ * This will be suboptimal in disksort(), but not harmful. Of course,
+ * this also truncates the block number at 4G, but there shouldn't be
+ * any MFM disk that large.
*/
- /*------------------------------*/
- blkno = bp->b_blkno / (hd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
- p = &hd->sc_dk.dk_label->d_partitions[HDCPART(bp->b_dev)];
- blkno += p->p_offset;
+ bn = bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
+ bp->b_cylinder = bn;
- /* nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label->d_secsize); */
+ s = splbio();
+ disksort(&sc->sc_buf_queue, bp);
+ if (inq == 0) {
+ inq = 1;
+ vsbus_dma_start(&sc->sc_vd);
+ }
+ splx(s);
+ return;
- if (hdc_strategy(hdc, hd, HDCUNIT(bp->b_dev),
- ((bp->b_flags & B_READ) ? F_READ : F_WRITE),
- blkno, bp->b_bcount, bp->b_data) == 0)
- goto done;
- /*------------------------------*/
-bad:
- bp->b_flags |= B_ERROR;
done:
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = 0; /* ??? bertram */
s = splbio();
biodone(bp);
splx(s);
}
-int
-hdc_strategy(hdc, hd, unit, func, dblk, size, buf)
- struct hdcsoftc *hdc;
- struct hdsoftc *hd;
- int unit;
- int func;
- int dblk;
- int size;
- char *buf;
+void
+hdc_qstart(void *arg)
{
- struct hdc9224_UDCreg *p = &hdc->sc_creg;
- struct disklabel *lp = hd->sc_dk.dk_label;
- int sect, head, cyl;
- int scount;
- int cmd, res = 0;
-
- trace (("hdc_strategy(%d, %d, %d, %d, 0x%x)\n",
- unit, func, dblk, size, buf));
-
- hdc_select(hdc, unit); /* select drive right now */
+ struct hdcsoftc *sc = arg;
+ struct buf *dp;
- if (unit != 2 && dblk == -1) { /* read the on-disk geometry */
+ inq = 0;
- p->udc_dma7 = 0;
- p->udc_dma15 = 0;
- p->udc_dma23 = 0;
-
- p->udc_dsect = 0;
- p->udc_dhead = 0;
- p->udc_dcyl = 0;
+ hdcstart(sc, NULL);
+ dp = &sc->sc_buf_queue;
+ if (dp->b_actf != NULL) {
+ vsbus_dma_start(&sc->sc_vd); /* More to go */
+ inq = 1;
+ }
+}
- p->udc_scnt = size/512;
- p->udc_rtcnt = 0xF0;
- p->udc_mode = 0xC0;
- p->udc_term = 0xB4;
+void
+hdcstart(struct hdcsoftc *sc, struct buf *ob)
+{
+ struct hdc9224_UDCreg *p = &sc->sc_creg;
+ struct disklabel *lp;
+ struct hdsoftc *hd;
+ struct buf *dp, *bp;
+ int cn, sn, tn, bn, blks;
+ volatile char ch;
+
+ splassert(IPL_BIO);
+
+ if (sc->sc_active)
+ return; /* Already doing something */
+
+ if (ob == 0) {
+ dp = &sc->sc_buf_queue;
+ if ((bp = dp->b_actf) == NULL)
+ return; /* Nothing to do */
+ dp->b_actf = bp->b_actf;
+ sc->sc_bufaddr = bp->b_data;
+ /* XXX see hdstrategy() comments regarding b_cylinder usage */
+ sc->sc_diskblk = bp->b_cylinder;
+ sc->sc_bytecnt = bp->b_bcount;
+ sc->sc_retries = 0;
+ bp->b_resid = 0;
+ } else
+ bp = ob;
+
+ hd = hd_cd.cd_devs[DISKUNIT(bp->b_dev)];
+ hdc_hdselect(sc, hd->sc_drive);
+ sc->sc_active = bp;
+
+ bn = sc->sc_diskblk;
+ lp = hd->sc_disk.dk_label;
+ if (bn) {
+ cn = bn / lp->d_secpercyl;
+ sn = bn % lp->d_secpercyl;
+ tn = sn / lp->d_nsectors;
+ sn = sn % lp->d_nsectors;
+ } else
+ cn = sn = tn = 0;
+
+ cn++; /* first cylinder is reserved */
+
+ bzero(p, sizeof(struct hdc9224_UDCreg));
- vsbus_lockDMA(hdc->sc_cfargs); /* bertram XXX */
- haveLock = 1;
- keepLock = 1;
+ /*
+ * Tricky thing: the controller itself only increases the sector
+ * number, not the track or cylinder number. Therefore the driver
+ * is not allowed to have transfers that crosses track boundaries.
+ */
+ blks = sc->sc_bytecnt / DEV_BSIZE;
+ if ((sn + blks) > lp->d_nsectors)
+ blks = lp->d_nsectors - sn;
+
+ p->udc_dsect = sn;
+ p->udc_dcyl = cn & 0xff;
+ p->udc_dhead = ((cn >> 4) & 0x70) | tn;
+ p->udc_scnt = blks;
+
+ p->udc_rtcnt = UDC_RC_RTRYCNT;
+ p->udc_mode = UDC_MD_HDD;
+ p->udc_term = UDC_TC_CRCPRE|UDC_TC_INTDONE|UDC_TC_TDELDAT|UDC_TC_TWRFLT;
+ hdc_writeregs(sc);
+
+ /* Count up vars */
+ sc->sc_xfer = blks * DEV_BSIZE;
+
+ ch = HDC_RSTAT; /* Avoid pending interrupts */
+ WAIT;
+ vsbus_clrintr(sc->sc_intbit); /* Clear pending int's */
+
+ if (bp->b_flags & B_READ) {
+ HDC_WCMD(DKC_CMD_READ_HDD);
+ } else {
+ vsbus_copyfromproc(bp->b_proc, sc->sc_bufaddr, sc->sc_dmabase,
+ sc->sc_xfer);
+ HDC_WCMD(DKC_CMD_WRITE_HDD);
+ }
+}
-#ifdef PARANOID
- bzero (hdc->sc_dmabase, size); /* clear disk buffer */
-#endif
- cmd = 0x5C | 0x03; /* bypass bad sectors */
- cmd = 0x5C | 0x01; /* terminate if bad sector */
+void
+hd_readgeom(struct hdcsoftc *sc, struct hdsoftc *hd)
+{
+ struct hdc9224_UDCreg *p = &sc->sc_creg;
- res = hdc_command (hdc, cmd);
- /* hold the locking ! */
- bcopy (hdc->sc_dmabase, buf, size); /* copy to buf */
- /* now release the locking */
+ hdc_hdselect(sc, hd->sc_drive); /* select drive right now */
- vsbus_unlockDMA(hdc->sc_cfargs);
- haveLock = 0;
- keepLock = 0;
+ bzero(p, sizeof(struct hdc9224_UDCreg));
- return (res);
- }
-
- scount = size / 512;
- while (scount) {
- /*
- * prepare drive/operation parameter
- */
- cyl = dblk / lp->d_secpercyl;
- sect = dblk % lp->d_secpercyl;
- head = sect / lp->d_nsectors;
- sect = sect % lp->d_nsectors;
- if (unit == 2)
- sect++;
- else
- cyl++; /* first cylinder is reserved */
-
- size = 512 * min(scount, lp->d_nsectors - sect);
-
- debug (("hdc_strategy: block #%d ==> s/t/c=%d/%d/%d (%d/%d)\n",
- dblk, sect, head, cyl, scount, size));
-
- /*
- * now initialize the register values ...
- */
- p->udc_dma7 = 0;
- p->udc_dma15 = 0;
- p->udc_dma23 = 0;
-
- p->udc_dsect = sect;
- head |= (cyl >> 4) & 0x70;
- p->udc_dhead = head;
- p->udc_dcyl = cyl;
-
- p->udc_scnt = size/512;
-
- if (unit == 2) { /* floppy */
- p->udc_rtcnt = 0xF2;
- p->udc_mode = 0x81; /* RX33 with RX50 media */
- p->udc_mode = 0x82; /* RX33 with RX33 media */
- p->udc_term = 0xB4;
- } else { /* disk */
- p->udc_rtcnt = 0xF0;
- p->udc_mode = 0xC0;
- p->udc_term = 0xB4;
- }
-
- vsbus_lockDMA(hdc->sc_cfargs);
- haveLock = 1;
- keepLock = 1;
-
- if (func == F_WRITE) {
- bcopy (buf, hdc->sc_dmabase, size); /* copy from buf */
- cmd = 0xA0 | (unit==2 ? 1 : 0);
- res = hdc_command (hdc, cmd);
- }
- else {
-#ifdef PARANOID
- bzero (hdc->sc_dmabase, size); /* clear disk buffer */
-#endif
- cmd = 0x5C | 0x03; /* bypass bad sectors */
- cmd = 0x5C | 0x01; /* terminate if bad sector */
- res = hdc_command (hdc, cmd);
- bcopy (hdc->sc_dmabase, buf, size); /* copy to buf */
- }
-
- vsbus_unlockDMA(hdc->sc_cfargs);
- haveLock = 0;
- keepLock = 0;
-
- scount -= size/512;
- dblk += size/512;
- buf += size;
- }
-
- if (unit != 2) /* deselect drive, if not floppy */
- hdc_command (hdc, DKC_CMD_DRDESELECT);
-
- return 0;
+ p->udc_scnt = 1;
+ p->udc_rtcnt = UDC_RC_RTRYCNT;
+ p->udc_mode = UDC_MD_HDD;
+ p->udc_term = UDC_TC_CRCPRE|UDC_TC_INTDONE|UDC_TC_TDELDAT|UDC_TC_TWPROT;
+ hdc_writeregs(sc);
+ sc->sc_status = 0;
+ HDC_WCMD(DKC_CMD_READ_HDD|2);
+ while ((sc->sc_status & DKC_ST_INTPEND) == 0)
+ ;
+ bcopy(sc->sc_dmabase, &hd->sc_xbn, sizeof(struct hdgeom));
}
-char hdc_iobuf[17*512]; /* we won't need more */
-
-#ifdef DEBUG
+#ifdef HDDEBUG
/*
* display the contents of the on-disk geometry structure
*/
-int
+void
hdc_printgeom(p)
struct hdgeom *p;
{
- char dname[8];
- hdc_mid2str(p->media_id, dname, sizeof dname);
-
- printf("**DiskData** XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n",
+ printf("**DiskData** XBNs: %ld, DBNs: %ld, LBNs: %ld, RBNs: %ld\n",
p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count);
printf("sec/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n",
p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced);
printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n",
p->seek_rate, p->crc_eec?"EEC":"CRC", p->rct, p->rct_ncopies);
- printf("media-ID: %s, interleave: %d, headskew: %d, cylskew: %d\n",
- dname, p->interleave, p->headskew, p->cylskew);
+ printf("media-ID: %lx, interleave: %d, headskew: %d, cylskew: %d\n",
+ p->media_id, p->interleave, p->headskew, p->cylskew);
printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n",
p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size,
p->sync_value);
@@ -614,133 +623,21 @@ hdc_printgeom(p)
#endif
/*
- * Convert media_id to string/name (encoding is documented in mscp.h)
+ * Return the size of a partition, if known, or -1 if not.
*/
int
-hdc_mid2str(media_id, name)
- long media_id;
- char *name;
- size_t len;
-{
- struct { /* For RD32 this struct holds: */
- u_long mt:7; /* number in name: 0x20 == 32 */
- u_long a2:5; /* ' ' encoded as 0x0 */
- u_long a1:5; /* 'D' encoded with base '@' */
- u_long a0:5; /* 'R' encoded with base '@' */
- u_long d1:5; /* 'U' encoded with base '@' */
- u_long d0:5; /* 'D' encoded with base '@' */
- } *p = (void *)&media_id;
-
-#define MIDCHR(x) (x ? x + '@' : ' ')
-
- snprintf(name, len, "%c%c%d", MIDCHR(p->a0), MIDCHR(p->a1), p->mt);
-}
-
-int
-hdc_getdata(hdc, hd, unit)
- struct hdcsoftc *hdc;
- struct hdsoftc *hd;
- int unit;
+hdsize(dev_t dev)
{
- struct disklabel *lp = hd->sc_dk.dk_label;
- struct hdparams *hp = &hd->sc_param;
- int res;
-
- trace (("hdc_getdata(%d)\n", unit));
-
- bzero(hd->sc_dk.dk_label, sizeof(struct disklabel));
- bzero(hd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
-
- if (unit == 2) {
- lp->d_secsize = DEV_BSIZE;
- lp->d_ntracks = 2;
- lp->d_nsectors = 15;
- lp->d_ncylinders = 80;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-
- return (0);
- }
-
- res = hdc_strategy(hdc, hd, unit, F_READ, -1, 4096, hdc_iobuf);
- bcopy (hdc_iobuf, &hd->sc_xbn, sizeof(struct hdgeom));
-#ifdef DEBUG
- hdc_printgeom(&hd->sc_xbn);
-#endif
- lp->d_secsize = DEV_BSIZE;
- lp->d_ntracks = hd->sc_xbn.ntracks;
- lp->d_nsectors = hd->sc_xbn.nspt;
- lp->d_ncylinders = hd->sc_xbn.ncylinders;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-
- hp->cylinders = hd->sc_xbn.ncylinders;
- hp->heads = hd->sc_xbn.ntracks;
- hp->sectors = hd->sc_xbn.nspt;
- hp->diskblks = hp->cylinders * hp->heads * hp->sectors;
- hp->disklbns = hd->sc_xbn.lbn_count;
- hp->blksize = DEV_BSIZE;
- hp->diskbytes = hp->disklbns * hp->blksize;
- hdc_mid2str(hd->sc_xbn.media_id, hp->diskname, sizeof hp->diskname);
-
- return (0);
-}
-
-int
-hdc_getlabel(hdc, hd, unit)
- struct hdcsoftc *hdc;
struct hdsoftc *hd;
- int unit;
-{
- struct disklabel *lp = hd->sc_dk.dk_label;
- struct disklabel *xp = (void *)(hdc_iobuf + 64);
- int res;
-
- trace(("hdc_getlabel(%d)\n", unit));
-
-#ifdef DEBUG
-#define LBL_CHECK(x) \
- if (xp->x != lp->x) { \
- printf("%d-->%d\n", xp->x, lp->x); \
- xp->x = lp->x; \
- }
-#else
-#define LBL_CHECK(x) xp->x = lp->x
-#endif
-
- res = hdc_strategy(hdc, hd, unit, F_READ, 0, DEV_BSIZE, hdc_iobuf);
- LBL_CHECK(d_secsize);
- LBL_CHECK(d_ntracks);
- LBL_CHECK(d_nsectors);
- LBL_CHECK(d_ncylinders);
- LBL_CHECK(d_secpercyl);
- bcopy(xp, lp, sizeof(struct disklabel));
-
- return (0);
-}
-
-/*
- * Return the size of a partition, if known, or -1 if not.
- */
-hdcsize(dev)
- dev_t dev;
-{
- int unit = HDCUNIT(dev);
- int part = HDCPART(dev);
- struct hdsoftc *hd = hd_cd.cd_devs[unit];
+ int unit = DISKUNIT(dev);
int size;
- trace (("hdcsize(%x == %d/%d)\n", dev, unit, part));
+ if (unit >= hd_cd.cd_ndevs || hd_cd.cd_devs[unit] == 0)
+ return -1;
+ hd = hd_cd.cd_devs[unit];
+ size = hd->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
+ (hd->sc_disk.dk_label->d_secsize / DEV_BSIZE);
- if (hdcopen(dev, 0, S_IFBLK) != 0)
- return (-1);
-#if 0
- if (hd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
- size = -1;
- else
-#endif
- size = hd->sc_dk.dk_label->d_partitions[part].p_size;
- if (hdcclose(dev, 0, S_IFBLK) != 0)
- return (-1);
- debug (("hdcsize: size=%d\n", size));
return (size);
}
@@ -748,179 +645,130 @@ hdcsize(dev)
*
*/
int
-hdcopen (dev, flag, fmt)
- dev_t dev;
- int flag;
- int fmt;
+hdopen(dev_t dev, int flag, int fmt, struct proc *p)
{
- int unit = HDCUNIT(dev);
- int part = HDCPART(dev);
- struct hdcsoftc *hdc;
struct hdsoftc *hd;
- int res, error;
+ int unit, part;
- trace (("hdcopen(0x%x = %d/%d)\n", dev, unit, part));
-
- if (unit >= hd_cd.cd_ndevs) {
- printf("hdcopen: invalid unit %d\n", unit);
- return (ENXIO);
- }
+ unit = DISKUNIT(dev);
+ if (unit >= hd_cd.cd_ndevs)
+ return ENXIO;
hd = hd_cd.cd_devs[unit];
- if (!hd) {
- printf("hdcopen: null-pointer in hdsoftc.\n");
- return (ENXIO);
- }
- hdc = (void *)hd->sc_dev.dv_parent;
-
- /* XXX here's much more to do! XXX */
+ if (hd == 0)
+ return ENXIO;
- hdc_getdata (hdc, hd, unit);
- hdc_getlabel (hdc, hd, unit);
+ part = DISKPART(dev);
+ if (part >= hd->sc_disk.dk_label->d_npartitions)
+ return ENXIO;
- return (0);
+ switch (fmt) {
+ case S_IFCHR:
+ hd->sc_disk.dk_copenmask |= (1 << part);
+ break;
+ case S_IFBLK:
+ hd->sc_disk.dk_bopenmask |= (1 << part);
+ break;
+ }
+ hd->sc_disk.dk_openmask =
+ hd->sc_disk.dk_copenmask | hd->sc_disk.dk_bopenmask;
+
+ return 0;
}
/*
*
*/
int
-hdcclose (dev, flag)
- dev_t dev;
- int flag;
+hdclose(dev_t dev, int flag, int fmt, struct proc *p)
{
- trace (("hdcclose()\n"));
- return (0);
-}
+ struct hdsoftc *hd;
+ int part;
-/*
- *
- */
-void
-hdcstrategy(bp)
- register struct buf *bp;
-{
- trace (("hdcstrategy()\n"));
- hdstrategy(bp);
- debug (("hdcstrategy done.\n"));
+ hd = hd_cd.cd_devs[DISKUNIT(dev)];
+ part = DISKPART(dev);
+
+ switch (fmt) {
+ case S_IFCHR:
+ hd->sc_disk.dk_copenmask &= ~(1 << part);
+ break;
+ case S_IFBLK:
+ hd->sc_disk.dk_bopenmask &= ~(1 << part);
+ break;
+ }
+ hd->sc_disk.dk_openmask =
+ hd->sc_disk.dk_copenmask | hd->sc_disk.dk_bopenmask;
+
+ return (0);
}
/*
*
*/
int
-hdcioctl(dev, cmd, data, flag, p)
- dev_t dev;
- int cmd;
- caddr_t data; /* aka: addr */
- int flag;
- struct proc *p;
+hdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
{
- struct hdsoftc *hd = hd_cd.cd_devs[HDCUNIT(dev)];
- struct hdcsoftc *hdc = (void *)hd->sc_dev.dv_parent;
- int error;
-
- trace (("hdcioctl(%x, %x)\n", dev, cmd));
-
- /*
- * If the device is not valid.. abandon ship
- */
- /* XXX */
+ struct hdsoftc *hd = hd_cd.cd_devs[DISKUNIT(dev)];
+ struct disklabel *lp = hd->sc_disk.dk_label;
+ int err = 0;
switch (cmd) {
case DIOCGDINFO:
- *(struct disklabel *)data = *(hd->sc_dk.dk_label);
- return (0);
+ bcopy(lp, addr, sizeof (struct disklabel));
+ break;
case DIOCGPART:
- ((struct partinfo *)data)->disklab = hd->sc_dk.dk_label;
- ((struct partinfo *)data)->part =
- &hd->sc_dk.dk_label->d_partitions[HDCPART(dev)];
- return (0);
+ ((struct partinfo *)addr)->disklab = lp;
+ ((struct partinfo *)addr)->part =
+ &lp->d_partitions[DISKPART(dev)];
+ break;
case DIOCWDINFO:
case DIOCSDINFO:
-/* XXX
if ((flag & FWRITE) == 0)
return EBADF;
-
- if ((error = sdlock(sd)) != 0)
- return error;
- sd->flags |= SDF_LABELLING;
-*/
- error = setdisklabel(hd->sc_dk.dk_label,
- (struct disklabel *)data, 0, hd->sc_dk.dk_cpulabel);
- if (error == 0) {
- if (cmd == DIOCWDINFO)
- error = writedisklabel(HDCLABELDEV(dev),
- hdstrategy, hd->sc_dk.dk_label,
- hd->sc_dk.dk_cpulabel);
- }
-/* XXX
- sd->flags &= ~SDF_LABELLING;
- sdunlock(sd);
-*/
- return (error);
+ else
+ err = (cmd == DIOCSDINFO ?
+ setdisklabel(lp, (struct disklabel *)addr, 0, 0) :
+ writedisklabel(dev, hdstrategy, lp, 0));
+ break;
case DIOCWLABEL:
if ((flag & FWRITE) == 0)
- return (EBADF);
-/* XXX
- if (*(int *)data)
- sd->flags |= SDF_WLABEL;
- else
- sd->flags &= ~SDF_WLABEL;
-*/
- return (0);
-
+ err = EBADF;
+ break;
+
default:
- if (HDCPART(dev) != RAW_PART)
- return (ENOTTY);
- printf("IOCTL %x not implemented.\n", cmd);
- return (-1);
+ err = ENOTTY;
+ break;
}
-}
-
-/*
- *
- */
-int
-hdcintr()
-{
- trace (("hdcintr()\n"));
+ return err;
}
/*
*
*/
int
-hdcread (dev, uio)
- dev_t dev;
- struct uio *uio;
+hdread(dev_t dev, struct uio *uio, int flag)
{
- trace (("hdcread()\n"));
- return (physio (hdcstrategy, NULL, dev, B_READ, minphys, uio));
+ return (physio(hdstrategy, NULL, dev, B_READ, minphys, uio));
}
/*
*
*/
int
-hdcwrite (dev, uio)
- dev_t dev;
- struct uio *uio;
+hdwrite(dev_t dev, struct uio *uio, int flag)
{
- trace (("hdcwrite()\n"));
- return (physio (hdcstrategy, NULL, dev, B_WRITE, minphys, uio));
+ return (physio(hdstrategy, NULL, dev, B_WRITE, minphys, uio));
}
/*
*
*/
int
-hdcdump(dev)
- dev_t dev;
+hddump(dev_t dev, daddr_t daddr, caddr_t addr, size_t size)
{
- trace (("hdcdump (%x)\n", dev));
+ return 0;
}
/*
@@ -929,33 +777,32 @@ hdcdump(dev)
* instruction. Thus the loop-overhead will be enough...
*/
void
-hdc_readregs(sc)
- struct hdcsoftc *sc;
+hdc_readregs(struct hdcsoftc *sc)
{
int i;
char *p;
- trace(("hdc_readregs()\n"));
-
- sc->sc_dkc->dkc_cmd = 0x40; /* set internal counter to zero */
+ HDC_WCMD(DKC_CMD_SETREGPTR);
+ WAIT;
p = (void *)&sc->sc_sreg;
- for (i=0; i<10; i++)
- *p++ = sc->sc_dkc->dkc_reg; /* dkc_reg auto-increments */
+ for (i = 0; i < 10; i++) {
+ *p++ = HDC_RREG; /* dkc_reg auto-increments */
+ WAIT;
+ }
}
void
-hdc_writeregs(sc)
- struct hdcsoftc *sc;
+hdc_writeregs(struct hdcsoftc *sc)
{
int i;
char *p;
- trace(("hdc_writeregs()\n"));
-
- sc->sc_dkc->dkc_cmd = 0x40; /* set internal counter to zero */
+ HDC_WCMD(DKC_CMD_SETREGPTR);
p = (void *)&sc->sc_creg;
- for (i=0; i<10; i++)
- sc->sc_dkc->dkc_reg = *p++; /* dkc_reg auto-increments */
+ for (i = 0; i < 10; i++) {
+ HDC_WREG(*p++); /* dkc_reg auto-increments */
+ WAIT;
+ }
}
/*
@@ -963,201 +810,72 @@ hdc_writeregs(sc)
* to find when command has completed
*/
int
-hdc_command(sc, cmd)
- struct hdcsoftc *sc;
- int cmd;
+hdc_command(struct hdcsoftc *sc, int cmd)
{
- volatile u_char *intreq = (void *)uvax_phys2virt(KA410_INTREQ);
- volatile u_char *intclr = (void *)uvax_phys2virt(KA410_INTCLR);
- volatile u_char *intmsk = (void *)uvax_phys2virt(KA410_INTMSK);
- int i, c;
-
- trace (("hdc_command(%x)\n", cmd));
- debug (("intr-state: %x %x %x\n", *intreq, *intclr, *intmsk));
-
- if (!haveLock) {
- vsbus_lockDMA(sc->sc_cfargs);
- haveLock = 1;
- }
-
hdc_writeregs(sc); /* write the prepared registers */
- *intclr = INTR_DC; /* clear any old interrupt */
- sc->sc_dkc->dkc_cmd = cmd; /* issue the command */
- for (i=0; i<MAX_WAIT; i++) {
- if ((c = *intreq) & INTR_DC)
- break;
- }
- if ((c & INTR_DC) == 0) {
- printf("hdc_command: timeout in command 0x%x\n", cmd);
- }
- hdc_readregs(sc); /* read the status registers */
- sc->sc_status = sc->sc_dkc->dkc_stat;
-
- if (!keepLock) {
- vsbus_unlockDMA(sc->sc_cfargs);
- haveLock = 0;
- }
-
- if (sc->sc_status != DKC_ST_DONE|DKC_TC_SUCCESS) {
- printf("command 0x%x completed with status 0x%x\n",
- cmd, sc->sc_status);
- return (-1);
- }
+ HDC_WCMD(cmd);
+ WAIT;
return (0);
}
-/*
- * writing zero into the command-register will reset the controller.
- * This will not interrupt data-transfer commands!
- * Also no interrupt is generated, thus we don't use hdc_command()
- */
-int
-hdc_reset(sc)
- struct hdcsoftc *sc;
-{
- trace (("hdc_reset()\n"));
-
- sc->sc_dkc->dkc_cmd = DKC_CMD_RESET; /* issue RESET command */
- hdc_readregs(sc); /* read the status registers */
- sc->sc_status = sc->sc_dkc->dkc_stat;
- if (sc->sc_status != DKC_ST_DONE|DKC_TC_SUCCESS) {
- printf("RESET command completed with status 0x%x\n",
- sc->sc_status);
- return (-1);
- }
- return (0);
-}
-
-int
-hdc_rxselect(sc, unit)
- struct hdcsoftc *sc;
- int unit;
-{
- register struct hdc9224_UDCreg *p = &sc->sc_creg;
- register struct hdc9224_UDCreg *q = &sc->sc_sreg;
- int error;
-
- /*
- * bring command-regs in some known-to-work state and
- * select the drive with the DRIVE SELECT command.
- */
- p->udc_dma7 = 0;
- p->udc_dma15 = 0;
- p->udc_dma23 = 0;
- p->udc_dsect = 1; /* sectors are numbered 1..15 !!! */
- p->udc_dhead = 0;
- p->udc_dcyl = 0;
- p->udc_scnt = 0;
-
- p->udc_rtcnt = UDC_RC_RX33READ;
- p->udc_mode = UDC_MD_RX33;
- p->udc_term = UDC_TC_FDD;
-
- /*
- * this is ...
- */
- error = hdc_command (sc, DKC_CMD_DRSEL_RX33 | unit);
-
- if ((error != 0) || ((q->udc_dstat & UDC_DS_READY) == 0)) {
- printf("\nfloppy-drive not ready (new floppy inserted?)\n\n");
- p->udc_rtcnt &= ~UDC_RC_INVRDY; /* clear INVRDY-flag */
- error = hdc_command(sc, DKC_CMD_DRSEL_RX33 | unit);
- if ((error != 0) || ((q->udc_dstat & UDC_DS_READY) == 0)) {
- printf("diskette not ready(1): %x/%x\n", error,
- q->udc_dstat);
- printf("floppy-drive offline?\n");
- return (-1);
- }
-
- if (q->udc_dstat & UDC_DS_TRK00) /* track-0: */
- error = hdc_command(sc, DKC_CMD_STEPIN_FDD);
- /* step in */
- else
- error = hdc_command(sc, DKC_CMD_STEPOUT_FDD);
- /* step out */
-
- if ((error != 0) || ((q->udc_dstat & UDC_DS_READY) == 1)) {
- printf("diskette not ready(2): %x/%x\n", error,
- q->udc_dstat);
- printf("No floppy inserted or drive offline\n");
- /* return (-1); */
- }
-
- p->udc_rtcnt |= UDC_RC_INVRDY;
- error = hdc_command(sc, DKC_CMD_DRSEL_RX33 | unit);
- if ((error != 0) || ((q->udc_dstat & UDC_DS_READY) == 0)) {
- printf("diskette not ready(3): %x/%x\n", error,
- q->udc_dstat);
- printf("no floppy inserted or floppy-door open\n");
- return(-1);
- }
- printf("floppy-drive reselected.\n");
- }
- if (error)
- error = hdc_command (sc, DKC_CMD_DRSEL_RX33 | unit);
-
- return (error);
-}
-
int
-hdc_hdselect(sc, unit)
- struct hdcsoftc *sc;
- int unit;
+hdc_hdselect(struct hdcsoftc *sc, int unit)
{
- register struct hdc9224_UDCreg *p = &sc->sc_creg;
- register struct hdc9224_UDCreg *q = &sc->sc_sreg;
+ struct hdc9224_UDCreg *p = &sc->sc_creg;
int error;
/*
* bring "creg" in some known-to-work state and
* select the drive with the DRIVE SELECT command.
*/
- p->udc_dma7 = 0;
- p->udc_dma15 = 0;
- p->udc_dma23 = 0;
- p->udc_dsect = 0; /* sectors are numbered 0..16 */
- p->udc_dhead = 0;
- p->udc_dcyl = 0;
- p->udc_scnt = 0;
+ bzero(p, sizeof(struct hdc9224_UDCreg));
p->udc_rtcnt = UDC_RC_HDD_READ;
p->udc_mode = UDC_MD_HDD;
p->udc_term = UDC_TC_HDD;
- error = hdc_command (sc, DKC_CMD_DRSEL_HDD | unit);
- if (error)
- error = hdc_command (sc, DKC_CMD_DRSEL_HDD | unit);
-
+ error = hdc_command(sc, DKC_CMD_DRSEL_HDD | unit);
+
return (error);
}
-/*
- * bring command-regs into some known-to-work state and select
- * the drive with the DRIVE SELECT command.
- */
-int
-hdc_select(sc, unit)
- struct hdcsoftc *sc;
- int unit;
+void
+hdmakelabel(struct disklabel *dl, struct hdgeom *g)
{
- int error;
-
- trace (("hdc_select(%x,%d)\n", sc, unit));
-
- switch (unit) {
- case 0:
- case 1:
- error = hdc_hdselect(sc, unit);
- break;
- case 2:
- error = hdc_rxselect(sc, unit);
- /* bertram: delay ??? XXX */
- break;
- default:
- printf("invalid unit %d in hdc_select()\n", unit);
- error = -1;
+ int n, p = 0;
+
+ dl->d_bbsize = BBSIZE;
+ dl->d_sbsize = SBSIZE;
+ dl->d_typename[p++] = MSCP_MID_CHAR(2, g->media_id);
+ dl->d_typename[p++] = MSCP_MID_CHAR(1, g->media_id);
+ if (MSCP_MID_ECH(0, g->media_id))
+ dl->d_typename[p++] = MSCP_MID_CHAR(0, g->media_id);
+ n = MSCP_MID_NUM(g->media_id);
+ if (n > 99) {
+ dl->d_typename[p++] = '1';
+ n -= 100;
}
-
- return (error);
+ if (n > 9) {
+ dl->d_typename[p++] = (n / 10) + '0';
+ n %= 10;
+ }
+ dl->d_typename[p++] = n + '0';
+ dl->d_typename[p] = 0;
+ dl->d_type = DTYPE_MSCP; /* XXX - what to use here??? */
+ dl->d_rpm = 3600;
+ dl->d_secsize = DEV_BSIZE;
+
+ dl->d_secperunit = g->lbn_count;
+ dl->d_nsectors = g->nspt;
+ dl->d_ntracks = g->ntracks;
+ dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
+ dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl;
+
+ dl->d_npartitions = MAXPARTITIONS;
+ dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
+ dl->d_secperunit;
+ dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
+ dl->d_interleave = dl->d_headswitch = 1;
+ dl->d_magic = dl->d_magic2 = DISKMAGIC;
+ dl->d_checksum = dkcksum(dl);
}
-#endif /* NHDC > 0 */
diff --git a/sys/arch/vax/vsa/hdc9224.h b/sys/arch/vax/vsa/hdc9224.h
index 4ec22fef206..04742b3442c 100644
--- a/sys/arch/vax/vsa/hdc9224.h
+++ b/sys/arch/vax/vsa/hdc9224.h
@@ -1,6 +1,5 @@
-/* $NetBSD: hdc9224.h,v 1.1 1996/07/20 18:55:12 ragge Exp $ */
-/* $OpenBSD: hdc9224.h,v 1.5 2003/11/07 10:16:45 jmc Exp $ */
-
+/* $OpenBSD: hdc9224.h,v 1.6 2006/11/06 20:28:23 miod Exp $ */
+/* $NetBSD: hdc9224.h,v 1.5 2003/11/10 08:51:52 wiz Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
@@ -34,14 +33,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-
+#if 0
struct hdc9224_DKCreg {
unsigned char dkc_reg; /* Disk Register Data Access Port (rw)*/
unsigned char fill[3]; /* bytes are longword aligned */
unsigned char dkc_cmd; /* Disk Controller Command Port (wo) */
#define dkc_stat dkc_cmd /* Interrupt Status Port (ro) */
};
+#endif
/*
* definition of some commands (constant bits only, incomplete!)
@@ -103,8 +102,8 @@ struct hdc9224_DKCreg {
* the Disk-Register-Data-Access-Port DKC_REG
*/
struct hdc9224_UDCreg { /* internal disk controller registers */
- u_char udc_dma7; /* 0: DMA address bits 0 - 7 */
- u_char udc_dma15; /* 1: DMA address bits 8 - 15 */
+ u_char udc_dma7; /* 0: DMA address bits 0 - 7 */
+ u_char udc_dma15; /* 1: DMA address bits 8 - 15 */
u_char udc_dma23; /* 2: DMA address bits 16 - 23 */
u_char udc_dsect; /* 3: desired/starting sector number */
#define udc_csect udc_dsect /* current sector number */
@@ -121,6 +120,9 @@ struct hdc9224_UDCreg { /* internal disk controller registers */
u_char udc_data; /* 10: data */
};
+/* UDC regs */
+#define UDC_TERM 9
+
/*
* Definition of bits in the Current-Head register
*/