Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/amiga/dev add PCMCIA generic support
details: https://anonhg.NetBSD.org/src/rev/e61a9dd02a2f
branches: trunk
changeset: 481131:e61a9dd02a2f
user: aymeric <aymeric%NetBSD.org@localhost>
date: Sun Jan 23 20:57:27 2000 +0000
description:
add PCMCIA generic support
diffstat:
sys/arch/amiga/dev/gayle_pcmcia.c | 600 ++++++++++++++++++++++++++++++++++++++
1 files changed, 600 insertions(+), 0 deletions(-)
diffs (truncated from 604 to 300 lines):
diff -r 1903b828936f -r e61a9dd02a2f sys/arch/amiga/dev/gayle_pcmcia.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/amiga/dev/gayle_pcmcia.c Sun Jan 23 20:57:27 2000 +0000
@@ -0,0 +1,600 @@
+/* $NetBSD: gayle_pcmcia.c,v 1.1 2000/01/23 20:57:27 aymeric Exp $ */
+
+/* PCMCIA front-end driver for A1200's and A600's. */
+
+#include <sys/param.h>
+#include <sys/cdefs.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <uvm/uvm.h>
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+
+#include <machine/cpu.h>
+#include <amiga/amiga/custom.h>
+#include <amiga/amiga/device.h>
+#include <amiga/amiga/gayle.h>
+#include <amiga/amiga/isr.h>
+
+
+/*
+ * There is one of these for each slot. This is useless since we have only one,
+ * but it makes it clearer if someone wants to understand better the NetBSD
+ * device drivers scheme.
+ */
+struct pccard_slot {
+ struct pccard_softc *sc; /* refer to `parent' */
+ int (*intr_func)(void *);
+ void * intr_arg;
+ struct device *card;
+ int flags;
+#define SLOT_OCCUPIED 0x01
+#define SLOT_NEW_CARD_EVENT 0x02
+};
+
+struct pccard_softc {
+ struct device sc_dev;
+ struct bus_space_tag io_space;
+ struct bus_space_tag attr_space;
+ struct bus_space_tag mem_space;
+ struct pccard_slot devs[1];
+ struct isr intr6;
+ struct isr intr2;
+};
+
+static int pccard_probe __P((struct device *, struct cfdata *, void *));
+static void pccard_attach __P((struct device *, struct device *, void *));
+static void pccard_attach_slot __P((struct pccard_slot *));
+static int pccard_intr6 __P((void *));
+static int pccard_intr2 __P((void *));
+static void pccard_create_kthread __P((void *));
+static void pccard_kthread __P((void *));
+
+static int pcf_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t,
+ struct pcmcia_mem_handle *));
+static void pcf_mem_free __P((pcmcia_chipset_handle_t,
+ struct pcmcia_mem_handle *));
+static int pcf_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t,
+ bus_size_t, struct pcmcia_mem_handle *, bus_addr_t *, int *));
+static void pcf_mem_unmap __P((pcmcia_chipset_handle_t, int));
+static int pcf_io_alloc __P((pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
+ bus_size_t, struct pcmcia_io_handle *));
+static void pcf_io_free __P((pcmcia_chipset_handle_t,
+ struct pcmcia_io_handle *));
+static int pcf_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t,
+ bus_size_t, struct pcmcia_io_handle *, int *));
+static void pcf_io_unmap __P((pcmcia_chipset_handle_t, int));
+static void *pcf_intr_establish __P((pcmcia_chipset_handle_t,
+ struct pcmcia_function *, int, int (*)(void *), void *));
+static void pcf_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
+static void pcf_socket_enable __P((pcmcia_chipset_handle_t));
+static void pcf_socket_disable __P((pcmcia_chipset_handle_t));
+
+static bsr(pcmio_bsr1, u_int8_t);
+static bsw(pcmio_bsw1, u_int8_t);
+static bsrm(pcmio_bsrm1, u_int8_t);
+static bswm(pcmio_bswm1, u_int8_t);
+static bsrm(pcmio_bsrr1, u_int8_t);
+static bswm(pcmio_bswr1, u_int8_t);
+static bssr(pcmio_bssr1, u_int8_t);
+static bscr(pcmio_bscr1, u_int8_t);
+
+static u_int8_t *reset_card_reg;
+
+struct cfattach pccard_ca = {
+ sizeof(struct pccard_softc), pccard_probe, pccard_attach
+};
+
+struct pcmcia_chip_functions chip_functions = {
+ pcf_mem_alloc, pcf_mem_free,
+ pcf_mem_map, pcf_mem_unmap,
+ pcf_io_alloc, pcf_io_free,
+ pcf_io_map, pcf_io_unmap,
+ pcf_intr_establish, pcf_intr_disestablish,
+ pcf_socket_enable, pcf_socket_disable
+};
+
+struct amiga_bus_space_methods pcmio_bs_methods;
+
+static int
+pccard_probe(dev, cfd, aux)
+ struct device *dev;
+ struct cfdata *cfd;
+ void *aux;
+{
+ return (/*is_a600() || */is_a1200()) && matchname(aux, "pccard");
+}
+
+static void
+pccard_attach(parent, myself, aux)
+ struct device *parent, *myself;
+ void *aux;
+{
+ struct pccard_softc *self = (struct pccard_softc *) myself;
+ struct pcmciabus_attach_args paa;
+ vaddr_t pcmcia_base = GAYLE_PCMCIA_START;
+ vaddr_t i;
+ int ret;
+
+ printf("\n");
+
+ gayle_init();
+
+ ret = uvm_map(kernel_map, &pcmcia_base,
+ GAYLE_PCMCIA_END - GAYLE_PCMCIA_START, NULL,
+ UVM_UNKNOWN_OFFSET, UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE,
+ UVM_INH_NONE, UVM_ADV_RANDOM, 0));
+ if (ret != KERN_SUCCESS) {
+ printf("attach failed (no virtual memory)\n");
+ return;
+ }
+
+ for (i = GAYLE_PCMCIA_START; i < GAYLE_PCMCIA_END; i += PAGE_SIZE)
+ pmap_enter(kernel_map->pmap,
+ i - GAYLE_PCMCIA_START + pcmcia_base, i,
+ VM_PROT_READ | VM_PROT_WRITE, TRUE);
+
+ /* override the one-byte access methods for I/O space */
+ pcmio_bs_methods = amiga_bus_stride_1;
+ pcmio_bs_methods.bsr1 = pcmio_bsr1;
+ pcmio_bs_methods.bsw1 = pcmio_bsw1;
+ pcmio_bs_methods.bsrm1 = pcmio_bsrm1;
+ pcmio_bs_methods.bswm1 = pcmio_bswm1;
+ pcmio_bs_methods.bsrr1 = pcmio_bsrr1;
+ pcmio_bs_methods.bswr1 = pcmio_bswr1;
+ pcmio_bs_methods.bssr1 = pcmio_bssr1;
+ pcmio_bs_methods.bscr1 = pcmio_bscr1;
+
+ reset_card_reg = (u_int8_t *) pcmcia_base - GAYLE_PCMCIA_START +
+ GAYLE_PCMCIA_RESET;
+
+ self->io_space.base = (u_int) pcmcia_base - GAYLE_PCMCIA_START +
+ GAYLE_PCMCIA_IO_START;
+ self->io_space.absm = &pcmio_bs_methods;
+
+ self->attr_space.base = (u_int) pcmcia_base - GAYLE_PCMCIA_START +
+ GAYLE_PCMCIA_ATTR_START;
+ self->attr_space.absm = &amiga_bus_stride_1;
+
+ /* XXX should be invalid */
+ self->mem_space.base = (u_int) pcmcia_base;
+ self->mem_space.absm = &amiga_bus_stride_1;
+
+ self->devs[0].sc = self;
+ self->devs[0].intr_func = NULL;
+ self->devs[0].intr_arg = NULL;
+ self->devs[0].flags = 0;
+
+ gayle.pcc_status = 0;
+ gayle.intreq = 0;
+ gayle.pcc_config = 0;
+ gayle.intena &= GAYLE_INT_IDE;
+
+ paa.paa_busname = "pcmcia";
+ paa.pct = &chip_functions;
+ paa.pch = &self->devs[0];
+ paa.iobase = 0;
+ paa.iosize = 0;
+ self->devs[0].card =
+ config_found_sm(myself, &paa, simple_devprint, NULL);
+ if (self->devs[0].card == NULL) {
+ printf("attach failed, config_found_sm() returned NULL\n");
+ return;
+ }
+
+ self->intr6.isr_intr = pccard_intr6;
+ self->intr6.isr_arg = self;
+ self->intr6.isr_ipl = 6;
+ add_isr(&self->intr6);
+
+ self->intr2.isr_intr = pccard_intr2;
+ self->intr2.isr_arg = self;
+ self->intr2.isr_ipl = 2;
+ add_isr(&self->intr2);
+
+ kthread_create(pccard_create_kthread, self);
+
+ gayle.intena |= GAYLE_INT_DETECT | GAYLE_INT_IREQ;
+
+ /* reset the card if it's already there */
+ if (gayle.pcc_status & GAYLE_CCMEM_DETECT) {
+ volatile u_int8_t x;
+ *reset_card_reg = 0x0;
+ delay(1000);
+ x = *reset_card_reg;
+ gayle.pcc_status = GAYLE_CCMEM_WP | GAYLE_CCIO_SPKR;
+ }
+
+ pccard_attach_slot(&self->devs[0]);
+}
+
+/* This is called as soon as it is possible to create a kernel thread */
+static void
+pccard_create_kthread(arg)
+ void *arg;
+{
+ struct pccard_softc *self = arg;
+
+ if (kthread_create1(pccard_kthread, self, NULL, "pccard thread")) {
+ printf("%s: can't create kernel thread\n",
+ self->sc_dev.dv_xname);
+ panic("pccard kthread_create() failed");
+ }
+}
+
+static int
+pccard_intr6(arg)
+ void *arg;
+{
+ struct pccard_softc *self = arg;
+
+ if (gayle.intreq & GAYLE_INT_DETECT) {
+ gayle.intreq = GAYLE_INT_IDE | GAYLE_INT_IREQ;
+ self->devs[0].flags |= SLOT_NEW_CARD_EVENT;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pccard_intr2(arg)
+ void *arg;
+{
+ struct pccard_softc *self = arg;
+ struct pccard_slot *slot = &self->devs[0];
+
+ if (slot->flags & SLOT_NEW_CARD_EVENT) {
+ slot->flags &= ~SLOT_NEW_CARD_EVENT;
+
+ /* reset the registers */
+ gayle.intreq = GAYLE_INT_IDE | GAYLE_INT_DETECT;
+ gayle.pcc_status = GAYLE_CCMEM_WP | GAYLE_CCIO_SPKR;
+ gayle.pcc_config = 0;
+ pccard_attach_slot(&self->devs[0]);
+ } else {
+ int intreq = gayle.intreq;
+ if (intreq & GAYLE_INT_IREQ) {
+ gayle.intreq = (intreq ^ GAYLE_INT_IREQ) |
+ GAYLE_INT_IDE | GAYLE_INT_DETECT;
+
+ if (slot->flags & SLOT_OCCUPIED &&
+ slot->intr_func != NULL)
+ slot->intr_func(slot->intr_arg);
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+pccard_kthread(arg)
+ void *arg;
+{
+ struct pccard_softc *self = arg;
+ struct pccard_slot *slot = &self->devs[0];
+
+ for (;;) {
+ int s = spl2();
+
+ if (slot->flags & SLOT_NEW_CARD_EVENT) {
+ slot->flags &= ~SLOT_NEW_CARD_EVENT;
+ gayle.intreq = 0xc0;
+
+ /* reset the registers */
+ gayle.intreq = GAYLE_INT_IDE | GAYLE_INT_DETECT;
+ gayle.pcc_status = GAYLE_CCMEM_WP | GAYLE_CCIO_SPKR;
+ gayle.pcc_config = 0;
+ pccard_attach_slot(&self->devs[0]);
+ }
+ splx(s);
+
Home |
Main Index |
Thread Index |
Old Index