diff options
author | 2009-02-12 22:03:46 +0000 | |
---|---|---|
committer | 2009-02-12 22:03:46 +0000 | |
commit | 65c7bb6d74ba8474accbd23d1c90e8d62911c405 (patch) | |
tree | f9c8e69ffee585e7f2edea9534401d1057113583 | |
parent | Add a pm_statistics struct to all pmap, and keep track of resident (diff) | |
download | wireguard-openbsd-65c7bb6d74ba8474accbd23d1c90e8d62911c405.tar.xz wireguard-openbsd-65c7bb6d74ba8474accbd23d1c90e8d62911c405.zip |
BPP routines for ``intelligent'' Motorola MVME boards. Currently not used
by anything, will eventually be used by the vx(4) MVME332 driver (once I
take the time to fix it) and the vsbic(4) MVME327 driver being worked on.
-rw-r--r-- | sys/arch/mvme88k/conf/files.mvme88k | 14 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/bpp.c | 369 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/bppvar.h | 193 |
3 files changed, 575 insertions, 1 deletions
diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index c6d5323745a..26a76100559 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.41 2006/05/02 21:43:07 miod Exp $ +# $OpenBSD: files.mvme88k,v 1.42 2009/02/12 22:03:46 miod Exp $ # maxpartitions 16 @@ -83,20 +83,32 @@ file arch/mvme88k/dev/bugio.c file arch/mvme88k/dev/mainbus.c file arch/mvme88k/dev/memdevs.c nvram | sram +define bpp +file arch/mvme88k/dev/bpp.c bpp + attach ie at pcctwo: ifnet, ether file arch/mvme88k/dev/if_ie.c ie +# MVME376 attach le at vmes file arch/mvme88k/dev/if_le.c le +# MVME374 #device vp: ether, ifnet, ifmedia #attach vp at vmes #file arch/mvme88k/dev/if_vp.c vp +# MVME332 device vx: tty attach vx at vmes file arch/mvme88k/dev/vx.c vx needs-count +# MVME328 device vs: scsi attach vs at vmes file arch/mvme88k/dev/vs.c vs + +# MVME327 +device vsbic: bpp, scsi +attach vsbic at vmes +file arch/mvme88k/dev/vsbic.c vsbic diff --git a/sys/arch/mvme88k/dev/bpp.c b/sys/arch/mvme88k/dev/bpp.c new file mode 100644 index 00000000000..05e0fe4cbc1 --- /dev/null +++ b/sys/arch/mvme88k/dev/bpp.c @@ -0,0 +1,369 @@ +/* $OpenBSD: bpp.c,v 1.1 2009/02/12 22:03:47 miod Exp $ */ + +/* + * Copyright (c) 2008, 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. And + * I won't mind if you keep the disclaimer below. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* BPP cards live in an A24/D16 world */ +#define __BUS_SPACE_RESTRICT_D16__ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/bus.h> + +#include <mvme88k/dev/bppvar.h> + +int bpp_csr_command(struct bpp_softc *, uint, bus_addr_t); + +void +bpp_attach(struct bpp_softc *sc, bus_space_tag_t iot, bus_space_handle_t ioh, + int ipl, int vec) +{ + sc->sc_ipl = ipl; + sc->sc_vec = vec; + + sc->sc_iot = iot; + sc->sc_ioh = ioh; +} + +/* + * CSR Command Protocol + * + * This protocol relies on atomic test-and-set instructions to claim the + * device for ourselves, using the test-and-set register. + * + * However, OpenBSD expects to be the only software talking to the BPP + * device, so it isn't really necessary to perform atomic operations here + * (such operations are not provided by the bus_space API anyway). + * + * Moreover, some MVME197 boards with early BusSwitch version, can not + * reliably perform test and set operations (xmem) on non-local memory + * addresses. Fun fun fun. + */ + +/* + * Send a command to the board through the (limited) CSR command protocol. + */ +int +bpp_csr_command(struct bpp_softc *sc, uint command, bus_addr_t addr) +{ + uint16_t csr, tas; +#if 1 + uint8_t tas8; + int tmo, tmo2, stat; + vaddr_t tasaddr; + + tasaddr = (vaddr_t)bus_space_vaddr(sc->sc_iot, sc->sc_ioh) + CSR_TAS; +#else + int tmo, stat; +#endif + +#if 1 + for (tmo = 1000; tmo != 0; tmo--) { + /* wait for the BUSY bit to clear */ + for (tmo2 = 1000; tmo2 != 0; tmo2--) { + csr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, + CSR_CONTROL); + if (!ISSET(csr, CSR_BUSY)) + break; + delay(100); + } + if (tmo2 == 0) + return STATUS_ERRNO + EAGAIN; + + /* + * Claim the TAS register. Note that, since there is no + * 16 bits modifier for xmem, we need to use the byte + * version. + */ + tas8 = TAS_TAS >> 8; + __asm__ __volatile__ ("xmem.bu %0, %2, r0" : + "+r"(tas8), "+m"(tasaddr) : "r"(tasaddr)); + + if (!ISSET(tas8, TAS_TAS >> 8)) + break; + + delay(100); + } + if (tmo == 0) + return STATUS_ERRNO + EAGAIN; +#else + /* wait for the BUSY bit to clear */ + for (tmo = 1000; tmo != 0; tmo--) { + csr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, CSR_CONTROL); + if (!ISSET(csr, CSR_BUSY)) + break; + delay(100); + } + if (tmo == 0) + return STATUS_ERRNO + EAGAIN; + + /* + * Claim the TAS register. + */ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, CSR_TAS, TAS_TAS); +#endif + + /* write the command information */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CSR_ADDR, addr); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, CSR_ADDR_MOD, ADRM_EXT_S_D); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, CSR_DATA_WIDTH, MEMT_D32); + bus_space_write_2(sc->sc_iot, sc->sc_ioh, CSR_TAS, + TAS_TAS | TAS_VALID_COMMAND | command); + + /* signal the board */ + bpp_attention(sc); + + /* wait for the command to complete */ + for (tmo = 1000; tmo != 0; tmo--) { + tas = bus_space_read_2(sc->sc_iot, sc->sc_ioh, CSR_TAS); + if (ISSET(tas, TAS_VALID_STATUS)) + break; + delay(100); + } + if (tmo == 0) + return STATUS_ERRNO + EAGAIN; + + stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CSR_STATUS); + + /* release the board */ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, CSR_TAS, + TAS_TAS | TAS_COMMAND_COMPLETE | + bus_space_read_2(sc->sc_iot, sc->sc_ioh, CSR_TAS)); + bpp_attention(sc); + + return (stat); +} + +/* + * Interrupt the board. + */ +void +bpp_attention(struct bpp_softc *sc) +{ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, CSR_CONTROL, + bus_space_read_2(sc->sc_iot, sc->sc_ioh, CSR_CONTROL) | + CSR_ATTENTION); +} + +/* + * Reset the board. This will take several seconds. + */ +int +bpp_reset(struct bpp_softc *sc) +{ + uint16_t csr; + int tmo; + + /* reset the board */ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, CSR_CONTROL, CSR_RESET); + delay(1000); + bus_space_write_2(sc->sc_iot, sc->sc_ioh, CSR_CONTROL, 0); + + /* wait for BUSY to clear in 10s */ + for (tmo = 10000; tmo != 0; tmo--) { + csr = bus_space_read_2(sc->sc_iot, sc->sc_ioh, CSR_CONTROL); + if (!ISSET(csr, CSR_BUSY)) { + return 0; + } + + delay(1000); + } + + return ENXIO; +} + +/* + * CSR operations + */ + +int +bpp_create_channel(struct bpp_softc *sc, struct bpp_chan *chan, int pri) +{ + struct bpp_channel *channel = chan->ch; + struct bpp_envelope *envcmd, *envsts; + + /* + * Setup the initial null envelopes. + */ + + envcmd = bpp_get_envelope(sc); + if (envcmd == NULL) + return STATUS_ERRNO + ENOMEM; + envsts = bpp_get_envelope(sc); + if (envsts == NULL) + return STATUS_ERRNO + ENOMEM; + + (*sc->bpp_env_sync)(sc, envcmd, BUS_DMASYNC_PREWRITE); + (*sc->bpp_env_sync)(sc, envsts, BUS_DMASYNC_PREWRITE); + + /* + * Setup channel header. + */ + + memset(channel, 0, sizeof (*channel)); + channel->ch_cmd_head = channel->ch_cmd_tail = + htobe32((*sc->bpp_env_pa)(sc, envcmd)); + channel->ch_status_head = channel->ch_status_tail = + htobe32((*sc->bpp_env_pa)(sc, envsts)); + channel->ch_ipl = sc->sc_ipl; + channel->ch_ivec = sc->sc_vec; + channel->ch_priority = pri; + channel->ch_addrmod = ADRM_EXT_S_D; + channel->ch_buswidth = MEMT_D32; + + (*sc->bpp_chan_sync)(sc, channel, BUS_DMASYNC_PREWRITE); + + chan->envcmd = envcmd; + chan->envsts = envsts; + + return bpp_csr_command(sc, COMMAND_CHANNEL_CREATE, + (*sc->bpp_chan_pa)(sc, channel)); +} + +/* + * BPP operations and envelope management + */ + +/* + * Initialize the free list as a set of contiguous envelopes. + */ +void +bpp_initialize_envelopes(struct bpp_softc *sc, struct bpp_envelope *env, + uint cnt) +{ + sc->sc_env_free = NULL; + while (cnt-- != 0) + bpp_put_envelope(sc, env++); +} + +/* + * Get a new envelope from the free list. + */ +struct bpp_envelope * +bpp_get_envelope(struct bpp_softc *sc) +{ + struct bpp_envelope *env; + + env = sc->sc_env_free; + if (env != NULL) { + sc->sc_env_free = (struct bpp_envelope *)env->env_link; + memset(env, 0, sizeof(*env)); + /* env->env_valid = ENVELOPE_INVALID; */ + } + + return env; +} + +/* + * Put an envelope into the free list. + */ +void +bpp_put_envelope(struct bpp_softc *sc, struct bpp_envelope *env) +{ + env->env_link = (uint32_t)sc->sc_env_free; + sc->sc_env_free = env; +} + +/* + * Send a command packet, replacing the NULL envelope with the given one, + * and enqueue it to the command pipe. + */ +void +bpp_queue_envelope(struct bpp_softc *sc, struct bpp_chan *chan, + struct bpp_envelope *tail, paddr_t cmdpa, uint32_t cmdextra) +{ + struct bpp_envelope *env; + struct bpp_channel *channel; + paddr_t tailpa; + + /* tail assumed to be unmodified since bpp_get_envelope(), + no need to memset() */ + (*sc->bpp_env_sync)(sc, tail, BUS_DMASYNC_PREWRITE); + tailpa = (*sc->bpp_env_pa)(sc, tail); + + /* + * Update the existing NULL envelope with data. + */ + + env = chan->envcmd; + env->env_link = htobe32(tailpa); + env->env_pkt = htobe32(cmdpa); + env->env_extra = cmdextra; + (*sc->bpp_env_sync)(sc, env, BUS_DMASYNC_PREWRITE); /* paranoia */ + env->env_valid = ENVELOPE_VALID; + (*sc->bpp_env_sync)(sc, env, BUS_DMASYNC_PREWRITE); + + /* + * Update the channel's command tail pointer to point to the + * new envelope. + */ + + channel = chan->ch; + channel->ch_cmd_tail = htobe32(tailpa); + /* really necessary? */ + (*sc->bpp_chan_sync)(sc, channel, BUS_DMASYNC_PREWRITE); + + chan->envcmd = tail; + + bpp_attention(sc); +} + +/* + * Dequeue an envelope from the status pipe, and return the command it + * was carrying. The envelope itself is returned to the free list. + */ +int +bpp_dequeue_envelope(struct bpp_softc *sc, struct bpp_chan *chan, + paddr_t *cmdpa, uint32_t *cmdextra) +{ + struct bpp_envelope *env; + struct bpp_channel *channel; + paddr_t headpa; + + /* + * Look at the head envelope. + */ + + env = chan->envsts; + (*sc->bpp_env_sync)(sc, env, BUS_DMASYNC_POSTREAD); + + if (env->env_valid == ENVELOPE_INVALID) + return EAGAIN; + + /* + * Dequeue the envelope, compute the new head envelope index, and + * finally release the envelope. + */ + + headpa = betoh32(env->env_link); + if (cmdpa != NULL) + *cmdpa = betoh32(env->env_pkt); + if (cmdextra != NULL) + *cmdextra = env->env_extra; + chan->envsts = (*sc->bpp_env_va)(sc, headpa); + + channel = chan->ch; + channel->ch_status_head = htobe32(headpa); + /* really necessary? */ + (*sc->bpp_chan_sync)(sc, channel, BUS_DMASYNC_PREWRITE); + + bpp_put_envelope(sc, env); + + return 0; +} diff --git a/sys/arch/mvme88k/dev/bppvar.h b/sys/arch/mvme88k/dev/bppvar.h new file mode 100644 index 00000000000..88bb95eba75 --- /dev/null +++ b/sys/arch/mvme88k/dev/bppvar.h @@ -0,0 +1,193 @@ +/* $OpenBSD: bppvar.h,v 1.1 2009/02/12 22:03:47 miod Exp $ */ + +/* + * Copyright (c) 2008, 2009 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. And + * I won't mind if you keep the disclaimer below. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Register and structure definitions for MVME boards using the Motorola + * Buffered Pipe Protocol. + */ + +/* + * Register layout (CSR space) + */ + +#define CSR_ADDR 0x00 /* 32 */ +#define CSR_ADDR_MOD 0x04 /* 8 */ +#define CSR_DATA_WIDTH 0x05 /* 8 */ +/* IPC control register */ +#define CSR_CONTROL 0x06 /* 16 */ +#define CSR_STATUS 0x08 /* 8 */ +#define CSR_DIAG 0x09 /* 8 */ +#define CSR_TAS 0x0e /* 16 */ + +/* CSR bits */ +#define CSR_BUSY 0x8000 /* firmware busy */ +#define CSR_RESET 0x4000 /* reset board */ +#define CSR_ATTENTION 0x2000 /* interrupt firmware */ +#define CSR_INHIBIT_SYSFAIL 0x1000 + +/* TAS bits */ +#define TAS_TAS 0x8000 /* test and set bit */ +#define TAS_VALID_COMMAND 0x4000 +#define TAS_VALID_STATUS 0x2000 +#define TAS_COMMAND_COMPLETE 0x1000 +#define TAS_COMMAND_MASK 0x0fff + +/* TAS commands */ +#define COMMAND_CHANNEL_CREATE 0x001 +#define COMMAND_CHANNEL_DELETE 0x002 +#define COMMAND_DUMP_MEMORY 0x101 + +/* command status values */ +#define STATUS_OK 0x00 +#define STATUS_INVALID_COMMAND 0x01 +#define STATUS_READ_CHANNEL_HEADER 0x02 +#define STATUS_WRITE_CHANNEL_HEADER 0x03 +#define STATUS_DMA_READ 0x04 +#define STATUS_DMA_WRITE 0x05 +#define STATUS_NO_MORE_CHANNELS 0x06 +#define STATUS_NO_SUCH_CHANNEL 0x07 +/* catastrophic errors start here... */ +#define STATUS_LOCAL_ADDRESS_ERROR 0xaa +#define STATUS_ACFAIL 0xac +#define STATUS_LOCAL_BUS_ERROR 0xbb +#define STATUS_CONFIDENCE_FAILED 0xcc +#define STATUS_UNEXPECTED_ERROR 0xee +#define STATUS_ERRNO 0x100 /* not from status reg */ + +/* + * BPP Channel header + */ + +struct bpp_channel { + uint32_t ch_cmd_head; /* command pipe head */ + uint32_t ch_cmd_tail; /* command pipe tail */ + uint32_t ch_status_head; /* status pipe head */ + uint32_t ch_status_tail; /* status pipe tail */ + uint8_t ch_ipl; /* channel interrupt level */ + uint8_t ch_ivec; /* channel interrupt vector */ + uint8_t ch_priority; /* channel priority */ +#define BPP_PRIORITY_HIGHEST 0x00 +#define BPP_PRIORITY_LOWEST 0xff + uint8_t ch_addrmod; /* envelope memory address modifier */ + uint8_t ch_num; /* set by firmware */ + uint8_t ch_valid; /* set by firmware */ + uint8_t ch_buswidth; /* unused */ + uint8_t reserved; +}; + +/* + * BPP Envelope structure + */ + +struct bpp_envelope { + uint32_t env_link; /* next envelope */ + uint32_t env_pkt; /* command packet physical address */ + uint8_t env_valid; +#define ENVELOPE_INVALID 0x00 +#define ENVELOPE_VALID 0x01 /* any nonzero value will do */ + uint8_t reserved[3]; + /* + * The following is not part of the envelope as defined by the + * firmware, but is used to page the envelope to a 68040/88200 + * cache line boundary. + * Plus this allows us to associate extra information to the + * envelope. + */ + uint32_t env_extra; + /* total size 0x10 bytes */ +}; + +/* + * Data bus width + */ + +#define MEMT_D16 1 +#define MEMT_D32 2 + +/* + * The following defines ought to be in a MI vme header file... + */ + +/* + * VME addressing modes + */ + +#define ADRM_STD_S_P 0x3e /* standard supervisory program */ +#define ADRM_STD_S_D 0x3d /* standard supervisory data */ +#define ADRM_STD_N_P 0x3a /* standard normal program */ +#define ADRM_STD_N_D 0x39 /* standard normal data */ +#define ADRM_SHT_S_IO 0x2d /* short supervisory I/O */ +#define ADRM_SHT_N_IO 0x29 /* short normal I/O */ +#define ADRM_EXT_S_P 0x0e /* extended supervisory program */ +#define ADRM_EXT_S_D 0x0d /* extended supervisory data */ +#define ADRM_EXT_N_P 0x0a /* extended normal program */ +#define ADRM_EXT_N_D 0x09 /* extended normal data */ +#define ADRM_EXT_S_BM 0x0f /* extended supervisory block mode */ +#define ADRM_EXT_S_D64 0x0c /* extended supervisory D64 mode */ + +/* + * Per channel information + */ + +struct bpp_chan { + struct bpp_channel *ch; /* bpp communication channel */ + + struct bpp_envelope *envcmd; /* command tail envelope */ + struct bpp_envelope *envsts; /* status head envelope */ +}; + +/* + * Device superset + */ + +struct bpp_softc { + struct device sc_dev; + + bus_space_tag_t sc_iot; /* CSR registers access */ + bus_space_handle_t sc_ioh; + + int sc_vec; /* interrupt vector */ + int sc_ipl; /* interrupt level */ + + struct bpp_envelope *sc_env_free; /* head of free envelope list */ + + /* channel function pointers */ + paddr_t (*bpp_chan_pa)(struct bpp_softc *, struct bpp_channel *); + void (*bpp_chan_sync)(struct bpp_softc *, struct bpp_channel *, int); + + /* envelope function pointers */ + paddr_t (*bpp_env_pa)(struct bpp_softc *, struct bpp_envelope *); + struct bpp_envelope *(*bpp_env_va)(struct bpp_softc *, paddr_t); + void (*bpp_env_sync)(struct bpp_softc *, struct bpp_envelope *, int); +}; + +void bpp_attach(struct bpp_softc *, bus_space_tag_t, bus_space_handle_t, + int, int); +void bpp_attention(struct bpp_softc *); +int bpp_create_channel(struct bpp_softc *, struct bpp_chan *, int); +int bpp_dequeue_envelope(struct bpp_softc *, struct bpp_chan *, paddr_t *, + uint32_t *); +struct bpp_envelope * + bpp_get_envelope(struct bpp_softc *); +void bpp_initialize_envelopes(struct bpp_softc *, struct bpp_envelope *, + uint); +void bpp_put_envelope(struct bpp_softc *, struct bpp_envelope *); +void bpp_queue_envelope(struct bpp_softc *, struct bpp_chan *, + struct bpp_envelope *, paddr_t, uint32_t); +int bpp_reset(struct bpp_softc *); |