From 7a599d2c3e5151dde6b81ef39a570c0c3a7bae96 Mon Sep 17 00:00:00 2001 From: ragge Date: Tue, 19 Aug 2003 10:51:57 +0000 Subject: [PATCH] Simple ebus, Massbus adapter and Massbus disk drivers. The Massbus disk drivers should be merged with the vax Massbus disk drivers when the 4.4BSD Massbus code gets free. --- sys/arch/pdp10/dev/ebus.c | 81 ++++++ sys/arch/pdp10/dev/ebus.h | 32 +++ sys/arch/pdp10/dev/hp.c | 505 +++++++++++++++++++++++++++++++++++++ sys/arch/pdp10/dev/hpreg.h | 125 +++++++++ sys/arch/pdp10/dev/rh.c | 306 ++++++++++++++++++++++ sys/arch/pdp10/dev/rhreg.h | 135 ++++++++++ sys/arch/pdp10/dev/rhvar.h | 117 +++++++++ 7 files changed, 1301 insertions(+) create mode 100644 sys/arch/pdp10/dev/ebus.c create mode 100644 sys/arch/pdp10/dev/ebus.h create mode 100644 sys/arch/pdp10/dev/hp.c create mode 100644 sys/arch/pdp10/dev/hpreg.h create mode 100644 sys/arch/pdp10/dev/rh.c create mode 100644 sys/arch/pdp10/dev/rhreg.h create mode 100644 sys/arch/pdp10/dev/rhvar.h diff --git a/sys/arch/pdp10/dev/ebus.c b/sys/arch/pdp10/dev/ebus.c new file mode 100644 index 000000000000..d334daa71844 --- /dev/null +++ b/sys/arch/pdp10/dev/ebus.c @@ -0,0 +1,81 @@ +/* $NetBSD: ebus.c,v 1.1 2003/08/19 10:51:57 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include + +static int +ebus_print(void *aux, const char *n) +{ + struct ebus_attach_args *ea = aux; + + printf(" csr %o", ea->ea_ioh); + return UNCONF; +} + +static int +ebus_match(struct device *parent, struct cfdata *cf, void *aux) +{ +#ifdef notyet + if (cputype != TYPE_KL) + return 0; +#endif + return 1; +} + +static int +ebus_search(struct device *parent, struct cfdata *cf, void *aux) +{ + struct ebus_attach_args ea; + int rv; + + ea.ea_iot = 0; + ea.ea_ioh = cf->cf_loc[0]; + rv = config_match(parent, cf, &ea); + if (rv == 0) + return 0; + config_attach(parent, cf, &ea, ebus_print); + return 1; +} + +static void +ebus_attach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); + + config_search(ebus_search, self, NULL); +} + +struct cfattach ebus_ca = { + sizeof(struct device), ebus_match, ebus_attach, +}; diff --git a/sys/arch/pdp10/dev/ebus.h b/sys/arch/pdp10/dev/ebus.h new file mode 100644 index 000000000000..78fefdf1ffde --- /dev/null +++ b/sys/arch/pdp10/dev/ebus.h @@ -0,0 +1,32 @@ +/* $NetBSD: ebus.h,v 1.1 2003/08/19 10:51:57 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +struct ebus_attach_args { + bus_space_tag_t ea_iot; + bus_space_handle_t ea_ioh; +}; diff --git a/sys/arch/pdp10/dev/hp.c b/sys/arch/pdp10/dev/hp.c new file mode 100644 index 000000000000..d8801bf73f9e --- /dev/null +++ b/sys/arch/pdp10/dev/hp.c @@ -0,0 +1,505 @@ +/* $NetBSD: hp.c,v 1.1 2003/08/19 10:51:57 ragge Exp $ */ +/* + * Copyright (c) 1996 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of + * Lule}, Sweden and its contributors. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Simple device driver routine for massbuss disks. + * TODO: + * Fix support for Standard DEC BAD144 bad block forwarding. + * Be able to to handle soft/hard transfer errors. + * Handle non-data transfer interrupts. + * Autoconfiguration of disk drives 'on the fly'. + * Handle disk media changes. + * Dual-port operations should be supported. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "ioconf.h" +#include "locators.h" + +struct hp_softc { + struct device sc_dev; + struct disk sc_disk; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + int sc_unit; + struct rh_device sc_md; /* Common struct used by mbaqueue. */ + int sc_wlabel; /* Disklabel area is writable */ +}; + +int hpmatch(struct device *, struct cfdata *, void *); +void hpattach(struct device *, struct device *, void *); +void hpstart(struct rh_device *); +int hpattn(struct rh_device *); +int hpfinish(struct rh_device *, int, int *); + +CFATTACH_DECL(hp, sizeof(struct hp_softc), hpmatch, hpattach, NULL, NULL); + +dev_type_open(hpopen); +dev_type_close(hpclose); +dev_type_read(hpread); +dev_type_write(hpwrite); +dev_type_ioctl(hpioctl); +dev_type_strategy(hpstrategy); +dev_type_size(hpsize); + +const struct bdevsw hp_bdevsw = { + hpopen, hpclose, hpstrategy, hpioctl, nulldump, hpsize, D_DISK +}; + +const struct cdevsw hp_cdevsw = { + hpopen, hpclose, hpread, hpwrite, hpioctl, + nostop, notty, nopoll, nommap, nokqfilter, D_DISK +}; + + +#define HP_WCSR(reg, val) \ + DATAO(sc->sc_ioh, ((reg) << 30) | (sc->sc_unit << 18) | \ + RH20_DATAO_LR | (val)) +#define HP_RCSR(reg, val) \ + DATAO(sc->sc_ioh, ((reg) << 30) | (sc->sc_unit << 18)); \ + DATAI(sc->sc_ioh, (val)) + +static struct hpsizes { + int type, sectrk, trkcyl, cylunit; +} hpsizes[] = { + { RH_DT_RP04, 20, 19, 400, }, + { RH_DT_RP05, 20, 19, 400, }, + { RH_DT_RP06, 20, 19, 800, }, + { RH_DT_RP07, 43, 32, 629, }, + { RH_DT_RM03, 30, 5, 820, }, + { RH_DT_RM05, 30, 19, 400, }, + { 0, }, +}; + +static void +hpfakelabel(int type, char *name, struct disklabel *dl) +{ + int i; + + for (i = 0; hpsizes[i].type; i++) + if (hpsizes[i].type == type) + break; + if (hpsizes[i].type == 0) + return; + dl->d_magic2 = dl->d_magic = DISKMAGIC; + dl->d_type = DTYPE_SMD; + strcpy(dl->d_typename, name); + dl->d_secsize = DEV_BSIZE; + dl->d_nsectors = hpsizes[i].sectrk; + dl->d_ntracks = hpsizes[i].trkcyl; + dl->d_ncylinders = hpsizes[i].cylunit; + dl->d_secpercyl = hpsizes[i].sectrk * hpsizes[i].trkcyl; + dl->d_secperunit = hpsizes[i].sectrk * hpsizes[i].trkcyl * + hpsizes[i].cylunit; + dl->d_rpm = 3600; + dl->d_interleave = 1; + dl->d_partitions[2].p_offset = 0; + dl->d_partitions[2].p_size = dl->d_secperunit; + dl->d_npartitions = 3; +} + +/* + * Check if this is a disk drive; done by checking type from mbaattach. + */ +int +hpmatch(struct device *parent, struct cfdata *cf, void *aux) +{ + struct rh_attach_args *ma = aux; + + if (cf->cf_loc[RHCF_DRIVE] != RHCF_DRIVE_DEFAULT && + cf->cf_loc[RHCF_DRIVE] != ma->ma_unit) + return 0; + + if (ma->ma_devtyp != MB_RP) + return 0; + + return 1; +} + +/* + * Disk drive found; fake a disklabel and try to read the real one. + * If the on-disk label can't be read; we lose. + */ +void +hpattach(struct device *parent, struct device *self, void *aux) +{ + struct hp_softc *sc = (void *)self; + struct rh_softc *ms = (void *)parent; + struct disklabel *dl; + struct rh_attach_args *ma = aux; + char *msg; + + sc->sc_iot = ma->ma_iot; + sc->sc_ioh = ma->ma_ioh; + /* + * Init the common struct for both the adapter and its slaves. + */ + bufq_alloc(&sc->sc_md.md_q, BUFQ_DISKSORT|BUFQ_SORT_CYLINDER); + sc->sc_md.md_softc = (void *)sc; /* Pointer to this softc */ + sc->sc_md.md_rh = (void *)parent; /* Pointer to parent softc */ + sc->sc_md.md_start = hpstart; /* Disk start routine */ + sc->sc_md.md_attn = hpattn; /* Disk attention routine */ + sc->sc_md.md_finish = hpfinish; /* Disk xfer finish routine */ + sc->sc_unit = ma->ma_unit; + ms->sc_md[ma->ma_unit] = &sc->sc_md; /* Per-unit backpointer */ + + /* + * Init and attach the disk structure. + */ + sc->sc_disk.dk_name = sc->sc_dev.dv_xname; + disk_attach(&sc->sc_disk); + + /* + * Fake a disklabel to be able to read in the real label. + */ + dl = sc->sc_disk.dk_label; + hpfakelabel(ma->ma_type, ma->ma_name, dl); + + /* + * Read in label. + */ + if ((msg = readdisklabel(makedev(0, self->dv_unit * 8), hpstrategy, + dl, NULL)) != NULL) + printf(": %s", msg); + printf(": %s, size = %d sectors\n", dl->d_typename, dl->d_secperunit); +} + + +void +hpstrategy(struct buf *bp) +{ + struct hp_softc *sc; + struct buf *gp; + int unit, s, err; + struct disklabel *lp; + + unit = DISKUNIT(bp->b_dev); + sc = hp_cd.cd_devs[unit]; + lp = sc->sc_disk.dk_label; + + err = bounds_check_with_label(&sc->sc_disk, bp, sc->sc_wlabel); + if (err < 0) + goto done; + + bp->b_rawblkno = + bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset; + bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl; + + s = splbio(); + + gp = BUFQ_PEEK(&sc->sc_md.md_q); + BUFQ_PUT(&sc->sc_md.md_q, bp); + if (gp == 0) + rhqueue(&sc->sc_md); + + splx(s); + return; + +done: + bp->b_resid = bp->b_bcount; + biodone(bp); +} + +/* + * Start transfer on given disk. Called from mbastart(). + */ +void +hpstart(struct rh_device *md) +{ + struct hp_softc *sc = md->md_softc; + struct disklabel *lp = sc->sc_disk.dk_label; + struct buf *bp = BUFQ_PEEK(&md->md_q); + unsigned bn, cn, sn, tn; + + /* + * Collect statistics. + */ + disk_busy(&sc->sc_disk); + sc->sc_disk.dk_seek++; + + bn = bp->b_rawblkno; + 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; + + HP_WCSR(HP_DC, cn); +#ifdef __pdp10__ + md->md_da = (tn << 8) | sn | (sc->sc_unit << 18); + md->md_csr = (bp->b_flags & B_READ ? HPCS_READ : HPCS_WRITE) | + (sc->sc_unit << 18); +#else + HP_WCSR(HP_DA, (tn << 8) | sn); + if (bp->b_flags & B_READ) + HP_WCSR(HP_CS1, HPCS_READ); + else + HP_WCSR(HP_CS1, HPCS_WRITE); +#endif +} + +int +hpopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + struct hp_softc *sc; + int unit, part; + + unit = DISKUNIT(dev); + if (unit >= hp_cd.cd_ndevs) + return ENXIO; + sc = hp_cd.cd_devs[unit]; + if (sc == 0) + return ENXIO; + + part = DISKPART(dev); + + if (part >= sc->sc_disk.dk_label->d_npartitions) + return ENXIO; + + switch (fmt) { + case S_IFCHR: + sc->sc_disk.dk_copenmask |= (1 << part); + break; + + case S_IFBLK: + sc->sc_disk.dk_bopenmask |= (1 << part); + break; + } + sc->sc_disk.dk_openmask = + sc->sc_disk.dk_copenmask | sc->sc_disk.dk_bopenmask; + + return 0; +} + +int +hpclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + struct hp_softc *sc; + int unit, part; + + unit = DISKUNIT(dev); + sc = hp_cd.cd_devs[unit]; + + part = DISKPART(dev); + + switch (fmt) { + case S_IFCHR: + sc->sc_disk.dk_copenmask &= ~(1 << part); + break; + + case S_IFBLK: + sc->sc_disk.dk_bopenmask &= ~(1 << part); + break; + } + sc->sc_disk.dk_openmask = + sc->sc_disk.dk_copenmask | sc->sc_disk.dk_bopenmask; + + return 0; +} + +int +hpioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) +{ + struct hp_softc *sc = hp_cd.cd_devs[DISKUNIT(dev)]; + struct disklabel *lp = sc->sc_disk.dk_label; + int error; + + switch (cmd) { + case DIOCGDINFO: + bcopy(lp, addr, sizeof (struct disklabel)); + return 0; + + case DIOCGPART: + ((struct partinfo *)addr)->disklab = lp; + ((struct partinfo *)addr)->part = + &lp->d_partitions[DISKPART(dev)]; + break; + + case DIOCSDINFO: + if ((flag & FWRITE) == 0) + return EBADF; + + return setdisklabel(lp, (struct disklabel *)addr, 0, 0); + + case DIOCWDINFO: + if ((flag & FWRITE) == 0) + error = EBADF; + else { + sc->sc_wlabel = 1; + error = writedisklabel(dev, hpstrategy, lp, 0); + sc->sc_wlabel = 0; + } + return error; + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + return EBADF; + sc->sc_wlabel = 1; + break; + + default: + return ENOTTY; + } + return 0; +} + +/* + * Called when a transfer is finished. Check if transfer went OK, + * Return info about what-to-do-now. + */ +int +hpfinish(struct rh_device *md, int mbasr, int *attn) +{ + struct hp_softc *sc = md->md_softc; + struct buf *bp = BUFQ_PEEK(&md->md_q); + int er1, er2; + + HP_RCSR(HP_ER1, er1); + er1 &= 0177777; + HP_RCSR(HP_ER2, er2); + er2 &= 0177777; + HP_WCSR(HP_ER1, 0); + HP_WCSR(HP_ER2, 0); + +hper1: + switch (ffs(er1) - 1) { + case -1: + HP_WCSR(HP_ER1, 0); + goto hper2; + + case HPER1_DCK: /* Corrected? data read. Just notice. */ +panic("hpfinish"); +#if 0 + bc = bus_space_read_4(md->md_mba->sc_iot, + md->md_mba->sc_ioh, MBA_BC); + byte = ~(bc >> 16); + diskerr(buf, hp_cd.cd_name, "soft ecc", LOG_PRINTF, + btodb(bp->b_bcount - byte), sc->sc_disk.dk_label); + er1 &= ~(1<sc_dev.dv_xname, er1, er2); + HP_WCSR(HP_ER1, 0); + HP_WCSR(HP_ER2, 0); + goto hper2; + } + goto hper1; + +hper2: + + mbasr &= ~(RH20_CONI_MBH|RH20_CONI_MEN|RH20_CONI_ATE| + RH20_CONI_DON|RH20_CONO_IMSK); + if (mbasr) + printf("massbuss error :%s %x\n", + sc->sc_dev.dv_xname, mbasr); + + BUFQ_PEEK(&md->md_q)->b_resid = 0; + disk_unbusy(&sc->sc_disk, BUFQ_PEEK(&md->md_q)->b_bcount, + (bp->b_flags & B_READ)); + return XFER_FINISH; +} + +/* + * Non-data transfer interrupt; like volume change. + */ +int +hpattn(struct rh_device *md) +{ + struct hp_softc *sc = md->md_softc; + int er1, er2; + + HP_RCSR(HP_ER1, er1); + HP_RCSR(HP_ER2, er2); + + printf("%s: Attention! er1 %x er2 %x\n", + sc->sc_dev.dv_xname, er1, er2); + return 0; +} + + +int +hpsize(dev_t dev) +{ + int size, unit = DISKUNIT(dev); + struct hp_softc *sc; + + if (unit >= hp_cd.cd_ndevs || hp_cd.cd_devs[unit] == 0) + return -1; + + sc = hp_cd.cd_devs[unit]; + size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size * + (sc->sc_disk.dk_label->d_secsize / DEV_BSIZE); + + return size; +} + +int +hpdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) +{ + return 0; +} + +int +hpread(dev_t dev, struct uio *uio, int ioflag) +{ + return (physio(hpstrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +hpwrite(dev_t dev, struct uio *uio, int ioflag) +{ + return (physio(hpstrategy, NULL, dev, B_WRITE, minphys, uio)); +} diff --git a/sys/arch/pdp10/dev/hpreg.h b/sys/arch/pdp10/dev/hpreg.h new file mode 100644 index 000000000000..a1f113a72b79 --- /dev/null +++ b/sys/arch/pdp10/dev/hpreg.h @@ -0,0 +1,125 @@ +/* $NetBSD: hpreg.h,v 1.1 2003/08/19 10:51:57 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of Lule}. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef notdef +struct hp_regs { + int hp_cs1; + int hp_ds; + int hp_er1; + int hp_mr1; + int hp_as; + int hp_da; + int hp_dt; + int hp_la; + int hp_sn; + int hp_of; + int hp_dc; + int hp_hr; + int hp_mr2; + int hp_er2; + int hp_ec1; + int hp_ec2; + int utrymme[16]; +}; +#endif + +#define HP_CS1 0 +#define HP_DS 1 +#define HP_ER1 2 +#define HP_MR1 3 +#define HP_AS 4 +#define HP_DA 5 +#define HP_DT 6 +#define HP_LA 7 +#define HP_SN 8 +#define HP_OF 9 +#define HP_DC 10 +#define HP_HR 11 +#define HP_MR2 12 +#define HP_ER2 13 +#define HP_EC1 14 +#define HP_EC2 15 + +#define HPCS_DVA 4000 /* Drive avail, in dual-port config */ +#define HPCS_WRITE 061 /* Write data */ +#define HPCS_WCHECK 051 /* Write check data */ +#define HPCS_WHEAD 063 /* Write header and data */ +#define HPCS_WCHEAD 053 /* Write check header and data */ +#define HPCS_READ 071 /* Read data */ +#define HPCS_RHEAD 073 /* Read header and data */ +#define HPCS_SEEK 005 /* Just seek */ +#define HPCS_RECAL 007 /* Recalibrate */ +#define HPCS_RTC 017 /* Return to centerline */ +#define HPCS_OFFSET 015 /* Offset */ +#define HPCS_SEARCH 031 /* Search */ +#define HPCS_UNLOAD 003 /* Unload pack (removable) */ +#define HPCS_RELEASE 013 /* Release massbuss port */ +#define HPCS_RPS 021 /* Read-in preset */ +#define HPCS_PA 023 /* Pack acknowledge */ +#define HPCS_DC 011 /* Drive clear */ + + +#define HPDS_VV 0x40 /* Volume valid, not changed */ +#define HPDS_DRY 0x80 /* Drive ready to accept commands */ +#define HPDS_DPR 0x100 /* Drive present */ +#define HPDS_PGM 0x200 /* Programmable in dual-port config */ +#define HPDS_LBT 0x400 /* Last block transferred */ +#define HPDS_WRL 0x800 /* Write locked media */ +#define HPDS_MOL 0x1000 /* Medium on-line */ +#define HPDS_PIP 0x2000 /* Positioning in progress */ +#define HPDS_ERR 0x4000 /* ORed error bit, something wrong */ +#define HPDS_ATA 0x8000 /* Attention drive */ + +#define HPDT_DRQ 0x800 /* Dual-port disk */ + +#define HPOF_FMT 0x1000 /* 16/18 bit data */ + +/* + * Error registers. The defines are the corresponding bit number + * in the error register, instead of a bit mask. + * Use (1< +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include "ioconf.h" +#include "locators.h" + +struct rhunit rhunit[] = { + {RH_DT_RP04, "rp04", MB_RP}, + {RH_DT_RP05, "rp05", MB_RP}, + {RH_DT_RP06, "rp06", MB_RP}, + {RH_DT_RP07, "rp07", MB_RP}, + {RH_DT_RM02, "rm02", MB_RP}, + {RH_DT_RM03, "rm03", MB_RP}, + {RH_DT_RM05, "rm05", MB_RP}, + {RH_DT_RM80, "rm80", MB_RP}, + {RH_DT_TU45, "tu45", MB_TU}, + {0, 0, 0} +}; + +int rhmatch(struct device *, struct cfdata *, void *); +void rhattach(struct device *, struct device *, void *); +void rhintr(void *); +int rhprint(void *, const char *); +void rhqueue(struct rh_device *); +void rhstart(struct rh_softc *); +void rhmapregs(struct rh_softc *); + +struct cfattach rh_ca = { + sizeof(struct rh_softc), rhmatch, rhattach +}; + +#define MBA_WCSR(reg, val) \ + DATAO(sc->sc_ioh | (reg << 30), val) +#define MBA_RCSR(reg) \ + ({ int rv; DATAI(sc->sc_ioh | (reg << 30), rv); rv; }) + +#define RH_READREG(disk, reg, val) \ + DATAO(sc->sc_ioh, ((reg) << 30) | ((disk) << 18)); \ + DATAI(sc->sc_ioh, val) +#define RH_WRITEREG(disk, reg, val) \ + DATAO(sc->sc_ioh, ((reg) << 30) | ((disk) << 18) | 04000000000 | (val)) + +/* + * Look if this is a massbuss adapter. + */ +int +rhmatch(struct device *parent, struct cfdata *cf, void *aux) +{ + struct ebus_attach_args *ea = aux; + int rv; + + /* Try a reset */ + CONO(ea->ea_ioh, RH20_CONO_RST|RH20_CONO_RCL); + /* DELAY(1000); */ + /* Check presence by toggling the ATE bit */ + CONI(ea->ea_ioh, rv); + if (rv & RH20_CONI_ATE) + return 0; + CONO(ea->ea_ioh, RH20_CONO_ATE); + CONI(ea->ea_ioh, rv); + if (rv & RH20_CONI_ATE) + return 1; + + return 0; +} + +/* + * Attach the found massbuss adapter. Setup its interrupt vectors, + * reset it and go searching for drives on it. + */ +void +rhattach(struct device *parent, struct device *self, void *aux) +{ + struct rh_softc *sc = (void *)self; + struct ebus_attach_args *ea = aux; + struct rh_attach_args ma; + int i, j, rv; + + printf(": RH20\n"); + sc->sc_iot = ea->ea_iot; + sc->sc_ioh = ea->ea_ioh; + + CONO(ea->ea_ioh, RH20_CONO_MEN|RH20_CONO_ATE|IPL_BIO); + + sc->sc_first = 0; + sc->sc_last = (void *)&sc->sc_first; + + RH_WRITEREG(0, RH_IVIR, MAKEIV(IPL_BIO)); + + for (i = 0; i < MAXMBADEV; i++) { + sc->sc_state = SC_AUTOCONF; + RH_READREG(i, RH_DS, rv); + if ((rv & RH_DS_DPR) == 0) { + CONO(sc->sc_ioh, RH20_CONO_RAE|RH20_CONO_ATE|IPL_BIO); + continue; + } + /* We have a drive, ok. */ + ma.ma_unit = i; + RH_READREG(i, RH_DT, rv); + ma.ma_type = rv & 0777; + j = 0; + while (rhunit[j++].nr) + if (rhunit[j].nr == ma.ma_type) + break; + ma.ma_devtyp = rhunit[j].devtyp; + ma.ma_name = rhunit[j].name; + ma.ma_iot = sc->sc_iot; + ma.ma_ioh = sc->sc_ioh; + config_found(&sc->sc_dev, (void *)&ma, rhprint); + } +} + +/* + * We got an interrupt. Check type of interrupt and call the specific + * device interrupt handling routine. + */ +void +rhintr(void *rh) +{ + struct rh_softc *sc = rh; + struct rh_device *md; + struct buf *bp; + int itype, attn, anr; + + sc = rh_cd.cd_devs[0]; + + CONI(sc->sc_ioh, itype); + CONO(sc->sc_ioh, itype & + (RH20_CONO_DON|RH20_CONO_ATE|RH20_CONO_MEN)); + RH_READREG(0, RH_AS, attn); + attn &= 0377; + RH_WRITEREG(0, RH_AS, attn); + + if (sc->sc_state == SC_AUTOCONF) + return; /* During autoconfig */ + + md = sc->sc_first; + bp = BUFQ_PEEK(&md->md_q); + /* + * A data-transfer interrupt. Current operation is finished, + * call that device's finish routine to see what to do next. + */ + if (sc->sc_state == SC_ACTIVE) { + + sc->sc_state = SC_IDLE; + switch ((*md->md_finish)(md, itype, &attn)) { + + case XFER_FINISH: + /* + * Transfer is finished. Take buffer of drive + * queue, and take drive of adapter queue. + * If more to transfer, start the adapter again + * by calling rhstart(). + */ + (void)BUFQ_GET(&md->md_q); + sc->sc_first = md->md_back; + md->md_back = 0; + if (sc->sc_first == 0) + sc->sc_last = (void *)&sc->sc_first; + + if (BUFQ_PEEK(&md->md_q) != NULL) { + sc->sc_last->md_back = md; + sc->sc_last = md; + } + + bp->b_resid = 0; + biodone(bp); + if (sc->sc_first) + rhstart(sc); + break; + + case XFER_RESTART: + /* + * Something went wrong with the transfer. Try again. + */ + rhstart(sc); + break; + } + } + + while (attn) { + anr = ffs(attn) - 1; + attn &= ~(1 << anr); + if (sc->sc_md[anr]->md_attn == 0) + panic("Should check for new MBA device %d", anr); + (*sc->sc_md[anr]->md_attn)(sc->sc_md[anr]); + } +} + +int +rhprint(void *aux, const char *rhname) +{ + struct rh_attach_args *ma = aux; + + if (rhname) { + if (ma->ma_name) + printf("%s", ma->ma_name); + else + printf("device type %o", ma->ma_type); + printf(" at %s", rhname); + } + printf(" drive %d", ma->ma_unit); + return (ma->ma_name ? UNCONF : UNSUPP); +} + +/* + * A device calls rhqueue() when it wants to get on the adapter queue. + * Called at splbio(). If the adapter is inactive, start it. + */ +void +rhqueue(struct rh_device *md) +{ + struct rh_softc *sc = md->md_rh; + int i = (int)sc->sc_first; + + sc->sc_last->md_back = md; + sc->sc_last = md; + + if (i == 0) + rhstart(sc); +} + +/* + * Start activity on (idling) adapter. Calls rhmapregs() to setup + * for dma transfer, then the unit-specific start routine. + */ +void +rhstart(struct rh_softc *sc) +{ + struct rh_device *md = sc->sc_first; + struct buf *bp = BUFQ_PEEK(&md->md_q); + int ncnt = bp->b_bcount/4; + int blkcnt = ncnt/128; + paddr_t pap; + + if (pmap_extract(pmap_kernel(), (vaddr_t)bp->b_data, &pap) == FALSE) + panic("rhstart"); + + if (pap & 03777) + panic("rhstart: bad align"); + + pap >>= 2; + + ept->ept_channel[0][DCH_CCL_OFF] = + DCH_CCW_XFR|DCH_CCW_XHLT| pap | (ncnt << DCH_CCW_CNTSH); + + sc->sc_state = SC_ACTIVE; + (*md->md_start)(md); /* machine-dependent start */ + RH_WRITEREG(0, RH_SBAR, md->md_da); + RH_WRITEREG(0, RH_STCR, + md->md_csr | RH_TCR_RCLP|RH_TCR_SES | + (((-blkcnt) << RH_TCR_NBCSH) & RH_TCR_NBC)); +} diff --git a/sys/arch/pdp10/dev/rhreg.h b/sys/arch/pdp10/dev/rhreg.h new file mode 100644 index 000000000000..125da88017c5 --- /dev/null +++ b/sys/arch/pdp10/dev/rhreg.h @@ -0,0 +1,135 @@ +/* $NetBSD: rhreg.h,v 1.1 2003/08/19 10:51:57 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * RH20 register definitions. + */ + +/* + * Different device codes. + */ +#define RH_DT_RP04 0x10 +#define RH_DT_RP05 0x11 +#define RH_DT_RP06 0x12 +#define RH_DT_RP07 0x22 +#define RH_DT_RM02 0x15 +#define RH_DT_RM03 0x14 +#define RH_DT_RM05 0x17 +#define RH_DT_RM80 0x16 +#define RH_DT_TU45 052 +#define RH_DT_DRQ 0x800 /* Dual ported */ +#define RH_DT_MOH 0x2000 /* Moving head device */ + +/* + * Some common registers used in the rh device driver. + */ +#define RH_DS 1 /* unit status */ +#define RH_AS 4 /* attention summary */ +#define RH_DT 6 /* drive type */ +#define RH_SBAR 070 /* Bus address register */ +#define RH_STCR 071 /* Transfer control register */ +#define RH_IVIR 074 /* Interrupt vector register */ + +#define RH_DS_DPR 0x100 /* Unit present */ +/* + * Internal register bits. + */ +#define RH_BAR_ADRMSK 0177777 /* Disk/tape address mask */ +#define RH_TCR_RCLP 0002000000000 /* Reset channel when starting */ +#define RH_TCR_SES 0000200000000 /* Store status after transfer */ +#define RH_TCR_DTES 0000000200000 /* Don't stop if errors */ +#define RH_TCR_NBC 0000000177700 /* Negative block count */ +#define RH_TCR_NBCSH 6 /* Block count shift */ + +/* + * RH20 register definitions. + */ +#define RH20_CONI_BPE 0400000 /* Data bus parity error */ +#define RH20_CONI_EXC 0200000 /* Exception */ +#define RH20_CONI_LWE 0100000 /* Long word count error */ +#define RH20_CONI_SWE 0040000 /* Short word count error */ +#define RH20_CONI_MBE 0020000 /* MBOX error */ +#define RH20_CONI_DRE 0010000 /* Drive response error */ +#define RH20_CONI_RAE 0004000 /* Register access error */ +#define RH20_CONI_MBH 0002000 /* MBOX halted */ +#define RH20_CONI_OVR 0001000 /* Data overrun */ +#define RH20_CONI_MEN 0000400 /* Massbus enable */ +#define RH20_CONI_ATN 0000200 /* Drive attention */ +#define RH20_CONI_2RF 0000100 /* Secondary command register full */ +#define RH20_CONI_ATE 0000040 /* Attention enable */ +#define RH20_CONI_1RF 0000020 /* Primary command register full */ +#define RH20_CONI_DON 0000010 /* Channel done */ + +#define RH20_CONO_RAE 0004000 /* Clear RAE */ +#define RH20_CONO_RST 0002000 /* Controller reset */ +#define RH20_CONO_XFR 0001000 /* Clear transfer error */ +#define RH20_CONO_MEN 0000400 /* Massbus enable */ +#define RH20_CONO_RCL 0000200 /* Reset MBOX command list pointer */ +#define RH20_CONO_DEL 0000100 /* Delete secondary command */ +#define RH20_CONO_ATE 0000040 /* Enable attention interrupts */ +#define RH20_CONO_STP 0000020 /* Stop current command */ +#define RH20_CONO_DON 0000010 /* Clear done */ +#define RH20_CONO_IMSK 0000007 /* Mask for interrupt level */ + +#define RH20_DATAI_CBPE 0001000000000 /* Control bus parity error */ +#define RH20_DATAI_TRA 0000200000000 /* Transfer received */ +#define RH20_DATAI_CPA 0000000200000 /* Massbus parity bit */ +#define RH20_DATAO_RS 0770000000000 /* Register select */ +#define RH20_DATAO_LR 0004000000000 /* Load register */ +#define RH20_DATAO_RAES 0000400000000 /* RAE Suppress */ + +/* + * Data channel defines. + */ +#define DCH_CCL_OFF 0 /* Channel Command List opcode */ +#define DCH_CST_OFF 1 /* Channel Status Word */ +#define DCH_CCW_OFF 2 /* Current Channel Command Word */ +#define DCH_CIV_OFF 3 /* Unused, free for software to use */ + +#define DCH_CCW_HLT 0000000000000 /* HALT opcode */ +#define DCH_CCW_JMP 0200000000000 /* JUMP opcode */ +#define DCH_CCW_XFR 0400000000000 /* XFER opcode, plus next 2 bits: */ +#define DCH_CCW_XHLT 0200000000000 /* Xfer cmd: "Halt after xfer" */ +#define DCH_CCW_XREV 0100000000000 /* Xfer cmd: "Reverse xfer" */ +#define DCH_CCW_CNTMSK 0077760000000 /* Word Count (positive) */ +#define DCH_CCW_CNTSH 22 /* Word Count shift */ +#define DCH_CCW_ADRMSK 0000017777777 /* 22-bit address */ + +/* Channel Status Word +*/ +#define DCH_CSW_SET 0400000000000 /* Always set 1 */ +#define DCH_CSW_MPAR 0200000000000 /* Mem Par Err during CCW fetch */ +#define DCH_CSW_NOAPE 0100000000000 /* Set if NO mem addr par err */ +#define DCH_CSW_NOWC0 0040000000000 /* CCW count NOT 0 when CSW set */ +#define DCH_CSW_NXM 0020000000000 /* Chan referenced NXM */ +#define DCH_CSW_LXFE 0000400000000 /* Last Transfer Error */ +#define DCH_CSW_RH20E 0000200000000 /* RH20 tried to start not-ready chn */ +#define DCH_CSW_LWCE 0000100000000 /* Long Word Count Error */ +#define DCH_CSW_SWCE 0000040000000 /* Short Word Count Error */ +#define DCH_CSW_OVN 0000020000000 /* Overrun */ +#define DCH_CSW_ADRMSK 0000017777777 /* 22-bit CCW addr+1 */ diff --git a/sys/arch/pdp10/dev/rhvar.h b/sys/arch/pdp10/dev/rhvar.h new file mode 100644 index 000000000000..98de6096c596 --- /dev/null +++ b/sys/arch/pdp10/dev/rhvar.h @@ -0,0 +1,117 @@ +/* $NetBSD: rhvar.h,v 1.1 2003/08/19 10:51:58 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of Lule}. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define MBCR_INIT 1 +#define MBCR_IE (1<<2) +#define MBDS_DPR (1<<8) +#define MBSR_NED (1<<18) +#define MBDT_MOH (1<<13) +#define MBDT_TYPE 511 +#define MBDT_TAP (1<<14) + +#define CLOSED 0 +#define WANTOPEN 1 +#define RDLABEL 2 +#define OPEN 3 +#define OPENRAW 4 + +#define MAXMBADEV 8 /* Max units per MBA */ + +/* + * Devices that have different device drivers. + */ +#define MB_RP 1 +#define MB_TU 2 +#define MB_MT 3 + +/* + * Current state of the adapter. + */ +#define SC_AUTOCONF 1 +#define SC_ACTIVE 2 +#define SC_IDLE 3 + +/* + * Return value after a finished data transfer, from device driver. + */ +#define XFER_RESTART 1 +#define XFER_FINISH 2 + +/* + * Info passed do unit device driver during autoconfig. + */ +struct rh_attach_args { + int ma_unit; + int ma_type; + int ma_devtyp; + bus_space_tag_t ma_iot; + bus_space_handle_t ma_ioh; + char *ma_name; +}; + +/* + * Common struct used to communicate between the rh device driver + * and the unit device driver. + */ +struct rh_device { + struct rh_device *md_back; /* linked list of runnable devices */ + /* Start routine to be called by rhstart. */ + void (*md_start)(struct rh_device *); + /* Routine to be called after attn intr */ + int (*md_attn)(struct rh_device *); + /* Call after xfer finish */ + int (*md_finish)(struct rh_device *, int, int *); + void *md_softc; /* Backpointer to this units softc. */ + struct rh_softc *md_rh; + struct bufq_state md_q; /* queue of I/O requests */ + int md_csr; /* Drive command given to RH20 */ + int md_da; /* Disk address given to RH20 */ +}; + +struct rh_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + struct evcnt sc_intrcnt; + struct rh_device *sc_first, *sc_last; + int sc_state; + struct rh_device *sc_md[MAXMBADEV]; +}; + +struct rhunit { + int nr; + char *name; + int devtyp; +}; + +/* Common prototypes */ +void rhqueue(struct rh_device *); +