/* * A very simple driver which shows how to use some *very* basic * features of the Machine Independent VMEbus glue. * * Copy this file to sys/dev/vme/foovme.c * * You'll also need to add the following lines to the end of the file * sys/dev/vme/files.vme: * * # Dummy VMEbus slave device * device foo * attach foo at vme * file dev/vme/foovme.c foo * * * Use with the following entry in your kernel config file: * * foo0 at vme0 addr 0xff780000 irq 3 vect 0x80 */ #include #include #include #include #include /* For the bus_space*() macroes */ #include /* For the MI VMEbus glue */ #include /* * The dummy device maintains state here. */ struct foo_softc { struct device sc_dev; /* <-- must exist */ bus_space_tag_t sc_bust; bus_space_handle_t sc_bush; }; int foomatch __P((struct device *, struct cfdata *, void *)); void fooattach __P((struct device *, struct device *, void *)); int foointr __P((void *)); struct cfattach foo_ca = { sizeof(struct foo_softc), foomatch, fooattach }; extern struct cfdriver foo_cd; /* * The VMEbus Address Modifier the dummy device responds to: */ #define FOO_AM_MOD (VME_AM_MBO | VME_AM_A32 | VME_AM_SUPER | VME_AM_DATA) /* * Return non-zero if we can access the device at the * address specified in the config file */ int foomatch(parent, cf, aux) struct device *parent; struct cfdata *cf; void *aux; { struct vme_attach_args *va = aux; int error; error = vme_probe(va->va_vct, va->r[0].offset, 0x4, FOO_AM_MOD, VME_D32, NULL, 0); return ((error == 0)); } /* * Attach the device */ void fooattach(parent, self, aux) struct device *parent; struct device *self; void *aux; { struct vme_attach_args *va; struct foo_softc *sc; vme_chipset_tag_t ct; vme_mapresc_t resc; vme_intr_handle_t ih; int i; /* * The 'vme_attach_args' contains the details from the config * file line. */ va = aux; /* * The 'vme_chipset_tag' identifies the VMEbus we're * attaching to. */ ct = va->va_vct; /* * Here's our soft state structure; allocated automaticaly by * the configuration glue. */ sc = (struct foo_softc *)self; /* * Allocate the dummy device's registers at the offset * specified in the config file, of length 4096 bytes, * with the VMEbus address modifier defined above. */ if (vme_space_alloc(ct, va->r[0].offset, 0x1000, FOO_AM_MOD)) panic("foo: vme_space_alloc"); /* * Now get a handle to the registers in sc->sc_bust and sc->sc_bush. */ if (vme_space_map(ct, va->r[0].offset, 0x1000, FOO_AM_MOD, VME_D32, 0, &sc->sc_bust, &sc->sc_bush, &resc)) panic("foo: vme_space_map"); /* * Write a ramp to the device's registers */ for (i = 0; i < 0x1000; i += 4) bus_space_write_4(sc->sc_bust, sc->sc_bush, i, i); /* * The device generates an interrupt, so map it into the system */ if (vme_intr_map(ct, va->ilevel, va->ivector, &ih)) panic("foo: vme_intr_map"); /* * Finally, arrange for our handler `foointr' to be called * whenever the device interrupts. Our soft state pointer * will be passed in as the argument to the handler. */ if (vme_intr_establish(ct, ih, IPL_NONE, foointr, sc) == NULL) panic("foo: vme_intr_establish"); printf(": VMEbus test device\n"); } int foointr(arg) void *arg; { struct foo_softc *sc; sc = arg; /* * Print the contents of the 32-bit location at offet * zero of the device. */ printf("foointr: Location 0x0 == 0x%08x\n", bus_space_read_4(sc->sc_bust, sc->sc_bush, 0)); return (1); }