Home | History | Annotate | Line # | Download | only in dev
ts102.c revision 1.10.16.1
      1        1.1  macallan /*	$OpenBSD: ts102.c,v 1.14 2005/01/27 17:03:23 millert Exp $	*/
      2  1.10.16.1      yamt /*	$NetBSD: ts102.c,v 1.10.16.1 2008/05/18 12:32:46 yamt Exp $ */
      3        1.1  macallan /*
      4        1.1  macallan  * Copyright (c) 2003, 2004, Miodrag Vallat.
      5  1.10.16.1      yamt  * Copyright (c) 2005, Michael Lorenz.
      6        1.1  macallan  *
      7        1.1  macallan  * Redistribution and use in source and binary forms, with or without
      8        1.1  macallan  * modification, are permitted provided that the following conditions
      9        1.1  macallan  * are met:
     10        1.1  macallan  * 1. Redistributions of source code must retain the above copyright
     11        1.1  macallan  *    notice, this list of conditions and the following disclaimer.
     12        1.1  macallan  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1  macallan  *    notice, this list of conditions and the following disclaimer in the
     14        1.1  macallan  *    documentation and/or other materials provided with the distribution.
     15        1.1  macallan  *
     16        1.1  macallan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17        1.1  macallan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18        1.1  macallan  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19        1.1  macallan  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     20        1.1  macallan  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21        1.1  macallan  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22        1.1  macallan  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23        1.1  macallan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     24        1.1  macallan  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     25        1.1  macallan  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26        1.1  macallan  * POSSIBILITY OF SUCH DAMAGE.
     27        1.1  macallan  */
     28        1.1  macallan 
     29        1.1  macallan /*
     30        1.1  macallan  * Driver for the PCMCIA controller found in Tadpole SPARCbook 3 series
     31        1.1  macallan  * notebooks.
     32        1.1  macallan  *
     33        1.1  macallan  * Based on the information provided in the SPARCbook 3 Technical Reference
     34        1.1  macallan  * Manual (s3gxtrmb.pdf), chapter 7.  A few ramblings against this document
     35        1.1  macallan  * and/or the chip itself are scattered across this file.
     36        1.1  macallan  *
     37        1.1  macallan  * Implementation notes:
     38        1.1  macallan  *
     39        1.1  macallan  * - The TS102 exports its PCMCIA windows as SBus memory ranges: 64MB for
     40        1.1  macallan  *   the common memory window, and 16MB for the attribute and I/O windows.
     41        1.1  macallan  *
     42        1.1  macallan  *   Mapping the whole windows would consume 192MB of address space, which
     43        1.1  macallan  *   is much more that what the iospace can offer.
     44        1.1  macallan  *
     45        1.1  macallan  *   A best-effort solution would be to map the windows on demand. However,
     46        1.1  macallan  *   due to the wap mapdev() works, the va used for the mappings would be
     47        1.1  macallan  *   lost after unmapping (although using an extent to register iospace memory
     48        1.1  macallan  *   usage would fix this). So, instead, we will do a fixed mapping of a subset
     49        1.1  macallan  *   of each window upon attach - this is similar to what the stp4020 driver
     50        1.1  macallan  *   does.
     51        1.1  macallan  *
     52        1.1  macallan  * Endianness farce:
     53        1.1  macallan  *
     54        1.1  macallan  * - The documentation pretends that the endianness settings only affect the
     55        1.1  macallan  *   common memory window. Gee, thanks a lot. What about other windows, then?
     56        1.1  macallan  *   As a result, this driver runs with endianness conversions turned off.
     57        1.1  macallan  *
     58        1.1  macallan  * - One of the little-endian SBus and big-endian PCMCIA flags has the reverse
     59        1.1  macallan  *   meaning, actually. To achieve a ``no endianness conversion'' status,
     60        1.1  macallan  *   one has to be set and the other unset. It does not matter which one,
     61        1.1  macallan  *   though.
     62        1.1  macallan  */
     63        1.1  macallan 
     64        1.1  macallan #include <sys/cdefs.h>
     65        1.1  macallan 
     66        1.1  macallan #include <sys/param.h>
     67        1.1  macallan #include <sys/systm.h>
     68        1.1  macallan #include <sys/errno.h>
     69        1.1  macallan #include <sys/malloc.h>
     70        1.1  macallan #include <sys/extent.h>
     71        1.1  macallan #include <sys/proc.h>
     72        1.1  macallan #include <sys/kernel.h>
     73        1.1  macallan #include <sys/kthread.h>
     74        1.1  macallan #include <sys/device.h>
     75        1.1  macallan 
     76        1.1  macallan #include <dev/pcmcia/pcmciareg.h>
     77        1.1  macallan #include <dev/pcmcia/pcmciavar.h>
     78        1.1  macallan #include <dev/pcmcia/pcmciachip.h>
     79        1.1  macallan 
     80        1.1  macallan #include <machine/bus.h>
     81        1.1  macallan #include <machine/intr.h>
     82        1.1  macallan #include <machine/autoconf.h>
     83        1.1  macallan 
     84        1.1  macallan #include <dev/sbus/sbusvar.h>
     85        1.1  macallan #include <sparc/dev/ts102reg.h>
     86        1.1  macallan 
     87        1.1  macallan #include "tctrl.h"
     88        1.1  macallan 
     89        1.1  macallan #if NTCTRL > 0
     90        1.1  macallan #include <machine/tctrl.h>
     91        1.1  macallan #include <sparc/dev/tctrlvar.h>
     92        1.1  macallan #endif
     93        1.1  macallan 
     94        1.1  macallan #define	TS102_NUM_SLOTS		2
     95        1.1  macallan 
     96        1.1  macallan /*
     97        1.1  macallan  * Memory ranges
     98        1.1  macallan  */
     99        1.1  macallan #define	TS102_RANGE_COMMON	0
    100        1.1  macallan #define	TS102_RANGE_ATTR	1
    101        1.1  macallan #define	TS102_RANGE_IO		2
    102        1.1  macallan 
    103        1.1  macallan #define	TS102_RANGE_CNT		3
    104        1.1  macallan #define	TS102_NUM_RANGES	(TS102_RANGE_CNT * TS102_NUM_SLOTS)
    105        1.1  macallan 
    106        1.1  macallan #define	TS102_ARBITRARY_MAP_SIZE	(1 * 1024 * 1024)
    107        1.1  macallan 
    108        1.1  macallan struct	tslot_softc;
    109        1.1  macallan 
    110        1.1  macallan #ifdef TSLOT_DEBUG
    111        1.1  macallan #define TSPRINTF	printf
    112        1.1  macallan #else
    113        1.1  macallan #define TSPRINTF	while (0) printf
    114        1.1  macallan #endif
    115        1.1  macallan 
    116        1.1  macallan /*
    117        1.1  macallan  * Per-slot data
    118        1.1  macallan  */
    119        1.1  macallan struct	tslot_data {
    120        1.1  macallan 	struct tslot_softc	*td_parent;
    121  1.10.16.1      yamt 	device_t		td_pcmcia;
    122        1.1  macallan 
    123        1.5  macallan 	volatile uint8_t	*td_regs;
    124        1.1  macallan 	bus_addr_t		td_space[TS102_RANGE_CNT];
    125        1.1  macallan 	bus_space_tag_t		td_pcmciat;	/* for accessing cards */
    126        1.1  macallan 
    127        1.1  macallan 	/* Interrupt handler */
    128        1.1  macallan 	int			(*td_intr)(void *);
    129        1.1  macallan 	void			*td_intrarg;
    130        1.1  macallan 	void			*td_softint;
    131        1.1  macallan 
    132        1.1  macallan 	/* Socket status */
    133        1.1  macallan 	int			td_slot;
    134        1.1  macallan 	int			td_status;
    135        1.1  macallan #define	TS_CARD			0x0001
    136        1.1  macallan };
    137        1.1  macallan 
    138        1.1  macallan struct	tslot_softc {
    139  1.10.16.1      yamt 	device_t	sc_dev;
    140        1.1  macallan 	struct sbusdev	sc_sd;
    141        1.1  macallan 
    142        1.1  macallan 	bus_space_tag_t	sc_bustag;		/* socket control io	*/
    143        1.1  macallan 	bus_space_handle_t	sc_regh;	/*  space		*/
    144        1.1  macallan 
    145        1.1  macallan 	pcmcia_chipset_tag_t sc_pct;
    146        1.1  macallan 
    147        1.8        ad 	lwp_t		*sc_thread;	/* event thread */
    148        1.5  macallan 	uint32_t	sc_events;	/* sockets with pending events */
    149        1.1  macallan 
    150        1.1  macallan 	/* bits 0 and 1 are set according to card presence in slot 0 and 1 */
    151        1.5  macallan 	uint32_t 	sc_active;
    152        1.1  macallan 
    153        1.1  macallan 	struct tslot_data sc_slot[TS102_NUM_SLOTS];
    154        1.1  macallan };
    155        1.1  macallan 
    156  1.10.16.1      yamt static void tslot_attach(device_t, device_t, void *);
    157        1.5  macallan static void tslot_event_thread(void *);
    158        1.5  macallan static int  tslot_intr(void *);
    159        1.5  macallan static void tslot_intr_disestablish(pcmcia_chipset_handle_t, void *);
    160        1.5  macallan static void *tslot_intr_establish(pcmcia_chipset_handle_t,
    161        1.5  macallan     struct pcmcia_function *, int, int (*)(void *), void *);
    162        1.5  macallan 
    163        1.5  macallan const char  *tslot_intr_string(pcmcia_chipset_handle_t, void *);
    164        1.5  macallan static int  tslot_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
    165        1.1  macallan     bus_size_t, struct pcmcia_io_handle *);
    166        1.5  macallan static void tslot_io_free(pcmcia_chipset_handle_t, struct pcmcia_io_handle *);
    167        1.5  macallan static int  tslot_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
    168        1.1  macallan     struct pcmcia_io_handle *, int *);
    169        1.5  macallan static void tslot_io_unmap(pcmcia_chipset_handle_t, int);
    170  1.10.16.1      yamt static int  tslot_match(device_t, struct cfdata *, void *);
    171        1.5  macallan static int  tslot_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
    172        1.1  macallan     struct pcmcia_mem_handle *);
    173        1.5  macallan static void tslot_mem_free(pcmcia_chipset_handle_t, struct pcmcia_mem_handle *);
    174        1.5  macallan static int  tslot_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
    175        1.1  macallan     struct pcmcia_mem_handle *, bus_size_t *, int *);
    176        1.5  macallan static void tslot_mem_unmap(pcmcia_chipset_handle_t, int);
    177        1.5  macallan static int  tslot_print(void *, const char *);
    178        1.5  macallan static void tslot_queue_event(struct tslot_softc *, int);
    179        1.5  macallan static void tslot_reset(struct tslot_data *, uint32_t);
    180        1.5  macallan static void tslot_slot_disable(pcmcia_chipset_handle_t);
    181        1.5  macallan static void tslot_slot_enable(pcmcia_chipset_handle_t);
    182        1.5  macallan static void tslot_slot_intr(struct tslot_data *, int);
    183        1.5  macallan static void tslot_slot_settype(pcmcia_chipset_handle_t, int);
    184        1.5  macallan static void tslot_update_lcd(struct tslot_softc *, int, int);
    185        1.1  macallan static void tslot_intr_dispatch(void *arg);
    186        1.1  macallan 
    187        1.1  macallan CFATTACH_DECL(tslot, sizeof(struct tslot_softc),
    188        1.1  macallan     tslot_match, tslot_attach, NULL, NULL);
    189        1.1  macallan 
    190        1.1  macallan extern struct cfdriver tslot_cd;
    191        1.1  macallan 
    192        1.1  macallan /*
    193        1.1  macallan  * PCMCIA chipset methods
    194        1.1  macallan  */
    195        1.1  macallan struct	pcmcia_chip_functions tslot_functions = {
    196        1.1  macallan 	tslot_mem_alloc,
    197        1.1  macallan 	tslot_mem_free,
    198        1.1  macallan 	tslot_mem_map,
    199        1.1  macallan 	tslot_mem_unmap,
    200        1.1  macallan 
    201        1.1  macallan 	tslot_io_alloc,
    202        1.1  macallan 	tslot_io_free,
    203        1.1  macallan 	tslot_io_map,
    204        1.1  macallan 	tslot_io_unmap,
    205        1.1  macallan 
    206        1.1  macallan 	tslot_intr_establish,
    207        1.1  macallan 	tslot_intr_disestablish,
    208        1.1  macallan 
    209        1.1  macallan 	tslot_slot_enable,
    210        1.1  macallan 	tslot_slot_disable,
    211        1.1  macallan 	tslot_slot_settype
    212        1.1  macallan };
    213        1.1  macallan 
    214        1.5  macallan static	uint16_t ts102_read_2(bus_space_tag_t,
    215        1.1  macallan 				 bus_space_handle_t,
    216        1.1  macallan 				 bus_size_t);
    217        1.5  macallan static	uint32_t ts102_read_4(bus_space_tag_t,
    218        1.1  macallan 				 bus_space_handle_t,
    219        1.1  macallan 				 bus_size_t);
    220        1.5  macallan static	uint64_t ts102_read_8(bus_space_tag_t,
    221        1.1  macallan 				 bus_space_handle_t,
    222        1.1  macallan 				 bus_size_t);
    223        1.1  macallan static	void	ts102_write_2(bus_space_tag_t,
    224        1.1  macallan 				bus_space_handle_t,
    225        1.1  macallan 				bus_size_t,
    226        1.5  macallan 				uint16_t);
    227        1.1  macallan static	void	ts102_write_4(bus_space_tag_t,
    228        1.1  macallan 				bus_space_handle_t,
    229        1.1  macallan 				bus_size_t,
    230        1.5  macallan 				uint32_t);
    231        1.1  macallan static	void	ts102_write_8(bus_space_tag_t,
    232        1.1  macallan 				bus_space_handle_t,
    233        1.1  macallan 				bus_size_t,
    234        1.5  macallan 				uint64_t);
    235        1.1  macallan 
    236        1.5  macallan static uint16_t
    237        1.5  macallan ts102_read_2(bus_space_tag_t space, bus_space_handle_t handle,
    238        1.5  macallan     bus_size_t offset)
    239        1.1  macallan {
    240        1.5  macallan 	return (le16toh(*(volatile uint16_t *)(handle +
    241        1.1  macallan 	    offset)));
    242        1.1  macallan }
    243        1.1  macallan 
    244        1.5  macallan static uint32_t
    245        1.5  macallan ts102_read_4(bus_space_tag_t space, bus_space_handle_t handle,
    246        1.5  macallan     bus_size_t offset)
    247        1.1  macallan {
    248        1.5  macallan 	return (le32toh(*(volatile uint32_t *)(handle +
    249        1.1  macallan 	    offset)));
    250        1.1  macallan }
    251        1.1  macallan 
    252        1.5  macallan static uint64_t
    253        1.5  macallan ts102_read_8(bus_space_tag_t space, bus_space_handle_t handle,
    254        1.5  macallan     bus_size_t offset)
    255        1.1  macallan {
    256        1.5  macallan 	return (le64toh(*(volatile uint64_t *)(handle +
    257        1.1  macallan 	    offset)));
    258        1.1  macallan }
    259        1.1  macallan 
    260        1.1  macallan static void
    261        1.5  macallan ts102_write_2(bus_space_tag_t space, bus_space_handle_t handle,
    262        1.5  macallan     bus_size_t offset, uint16_t value)
    263        1.1  macallan {
    264        1.5  macallan 	(*(volatile uint16_t *)(handle + offset)) =
    265        1.1  macallan 	    htole16(value);
    266        1.1  macallan }
    267        1.1  macallan 
    268        1.1  macallan static void
    269        1.5  macallan ts102_write_4(bus_space_tag_t space, bus_space_handle_t handle,
    270        1.5  macallan     bus_size_t offset, uint32_t value)
    271        1.1  macallan {
    272        1.5  macallan 	(*(volatile uint32_t *)(handle + offset)) =
    273        1.1  macallan 	    htole32(value);
    274        1.1  macallan }
    275        1.1  macallan 
    276        1.1  macallan static void
    277        1.5  macallan ts102_write_8(bus_space_tag_t space, bus_space_handle_t handle,
    278        1.5  macallan     bus_size_t offset, uint64_t value)
    279        1.1  macallan {
    280        1.5  macallan 	(*(volatile uint64_t *)(handle + offset)) =
    281        1.1  macallan 	    htole64(value);
    282        1.1  macallan }
    283        1.1  macallan 
    284        1.1  macallan 
    285        1.1  macallan #define	TSLOT_READ(slot, offset) \
    286        1.6       uwe 	*(volatile uint16_t *)((slot)->td_regs + (offset))
    287        1.1  macallan #define	TSLOT_WRITE(slot, offset, value) \
    288        1.6       uwe 	*(volatile uint16_t *)((slot)->td_regs + (offset)) = (value)
    289        1.1  macallan 
    290        1.1  macallan /*
    291        1.1  macallan  * Attachment and initialization
    292        1.1  macallan  */
    293        1.1  macallan 
    294        1.5  macallan static int
    295  1.10.16.1      yamt tslot_match(device_t parent, struct cfdata *vcf, void *aux)
    296        1.1  macallan {
    297        1.1  macallan 	struct sbus_attach_args *sa = aux;
    298        1.1  macallan 
    299        1.1  macallan 	return (strcmp("ts102", sa->sa_name) == 0);
    300        1.1  macallan }
    301        1.1  macallan 
    302        1.5  macallan static void
    303  1.10.16.1      yamt tslot_attach(device_t parent, device_t self, void *args)
    304        1.1  macallan {
    305        1.1  macallan 	struct sbus_attach_args *sa = args;
    306  1.10.16.1      yamt 	struct tslot_softc *sc = device_private(self);
    307        1.1  macallan 	struct tslot_data *td;
    308        1.6       uwe 	volatile uint8_t *regs;
    309        1.1  macallan 	int node, slot, rnum, base, size;
    310        1.1  macallan 	uint32_t ranges[30];
    311        1.1  macallan 	void *rptr = ranges;
    312        1.1  macallan 	bus_space_handle_t hrang = 0;
    313        1.1  macallan 	bus_space_tag_t tag;
    314        1.5  macallan 
    315  1.10.16.1      yamt 	sc->sc_dev = self;
    316        1.1  macallan 	node = sa->sa_node;
    317        1.1  macallan 	sc->sc_bustag=sa->sa_bustag;
    318        1.1  macallan 	if (sbus_bus_map(sa->sa_bustag,
    319        1.1  macallan 			 sa->sa_slot,
    320        1.1  macallan 			 sa->sa_offset,
    321        1.1  macallan 			 sa->sa_size,
    322        1.1  macallan 			 0, &sc->sc_regh) != 0) {
    323        1.1  macallan 		printf("%s: cannot map registers\n", self->dv_xname);
    324        1.1  macallan 		return;
    325        1.1  macallan 	}
    326        1.5  macallan 	regs = (uint8_t *)bus_space_vaddr(sa->sa_bustag, sc->sc_regh);
    327        1.5  macallan 
    328        1.1  macallan 	tag = bus_space_tag_alloc(sa->sa_bustag, sc);
    329        1.1  macallan 	if (tag == NULL) {
    330        1.1  macallan 		printf("%s: attach: out of memory\n", self->dv_xname);
    331        1.1  macallan 		return;
    332        1.1  macallan 	}
    333        1.1  macallan 	tag->sparc_read_2 = ts102_read_2;
    334        1.1  macallan 	tag->sparc_read_4 = ts102_read_4;
    335        1.1  macallan 	tag->sparc_read_8 = ts102_read_8;
    336        1.1  macallan 	tag->sparc_write_2 = ts102_write_2;
    337        1.1  macallan 	tag->sparc_write_4 = ts102_write_4;
    338        1.1  macallan 	tag->sparc_write_8 = ts102_write_8;
    339        1.1  macallan 
    340        1.1  macallan 	sbus_establish(&sc->sc_sd, self);
    341        1.1  macallan 
    342        1.5  macallan 	bus_intr_establish(sa->sa_bustag, sa->sa_intr[0].oi_pri,
    343        1.1  macallan 	    IPL_NONE, tslot_intr, sc);
    344        1.1  macallan 
    345        1.1  macallan 	printf(": %d slots\n", TS102_NUM_SLOTS);
    346        1.5  macallan 
    347        1.1  macallan 	size = sizeof(ranges);
    348        1.1  macallan 	if (prom_getprop(node, "ranges", 4, &size, &rptr) != 0) {
    349        1.1  macallan 		printf("couldn't read ranges\n");
    350        1.1  macallan 		return;
    351        1.1  macallan 	}
    352        1.1  macallan 
    353        1.1  macallan 	/*
    354        1.1  macallan 	 * Setup asynchronous event handler
    355        1.1  macallan 	 */
    356        1.1  macallan 	sc->sc_events = 0;
    357        1.8        ad 
    358        1.8        ad 	TSPRINTF("starting event thread...\n");
    359        1.8        ad 	if (kthread_create(PRI_NONE, 0, NULL, tslot_event_thread, sc,
    360        1.8        ad 	    &sc->sc_thread, "%s", self->dv_xname) != 0) {
    361        1.8        ad 		panic("%s: unable to create event kthread",
    362        1.8        ad 		    self->dv_xname);
    363        1.8        ad 	}
    364        1.1  macallan 
    365        1.1  macallan 	sc->sc_pct = (pcmcia_chipset_tag_t)&tslot_functions;
    366        1.1  macallan 	sc->sc_active = 0;
    367        1.1  macallan 
    368        1.1  macallan 	/*
    369        1.1  macallan 	 * Setup slots
    370        1.1  macallan 	 */
    371        1.1  macallan 	TSPRINTF("mapping resources...\n");
    372        1.1  macallan 	for (slot = 0; slot < TS102_NUM_SLOTS; slot++) {
    373        1.1  macallan 		td = &sc->sc_slot[slot];
    374        1.1  macallan 		TSPRINTF("slot %d, ",slot);
    375        1.1  macallan 		for (rnum = 0; rnum < TS102_RANGE_CNT; rnum++) {
    376        1.1  macallan 			base = (slot * TS102_RANGE_CNT + rnum) * 5;
    377        1.5  macallan 			TSPRINTF("%d: %08x %08x ",rnum,ranges[base + 3],
    378        1.1  macallan 			    ranges[base + 4]);
    379        1.1  macallan 			if(sbus_bus_map(sc->sc_bustag,
    380        1.1  macallan 					sa->sa_slot,
    381        1.1  macallan 				 	ranges[base+3],
    382        1.1  macallan 				 	TS102_ARBITRARY_MAP_SIZE,
    383        1.1  macallan 					0, &hrang) != 0) {
    384        1.5  macallan 				printf("%s: cannot map registers\n",
    385        1.1  macallan 				    self->dv_xname);
    386        1.1  macallan 				return;
    387        1.1  macallan 			}
    388        1.5  macallan 			TSPRINTF("%08x: %08x ",(uint32_t)ranges[base + 3],
    389        1.1  macallan 			    (uint32_t)hrang);
    390        1.1  macallan 			td->td_space[rnum] = hrang;
    391        1.1  macallan 		}
    392        1.1  macallan 		td->td_parent = sc;
    393        1.1  macallan 		td->td_pcmciat = tag;
    394        1.1  macallan 		td->td_softint = NULL;
    395        1.5  macallan 		td->td_regs = regs + slot * (TS102_REG_CARD_B_INT -
    396        1.1  macallan 		    TS102_REG_CARD_A_INT);
    397        1.1  macallan 		td->td_slot = slot;
    398        1.1  macallan 
    399        1.1  macallan 		TSPRINTF("resetting slot %d %d\n", slot, (int)td->td_regs);
    400        1.1  macallan 		tslot_reset(td, TS102_ARBITRARY_MAP_SIZE);
    401        1.1  macallan 	}
    402        1.1  macallan }
    403        1.1  macallan 
    404        1.5  macallan static void
    405        1.5  macallan tslot_reset(struct tslot_data *td, uint32_t iosize)
    406        1.1  macallan {
    407        1.1  macallan 	struct pcmciabus_attach_args paa;
    408        1.1  macallan 	int ctl, status;
    409        1.1  macallan 
    410        1.1  macallan 	paa.paa_busname = "pcmcia";
    411        1.1  macallan 	paa.pct = (pcmcia_chipset_tag_t)td->td_parent->sc_pct;
    412        1.1  macallan 	paa.pch = (pcmcia_chipset_handle_t)td;
    413        1.1  macallan 	paa.iobase = 0;
    414        1.1  macallan 	paa.iosize = iosize;
    415        1.1  macallan 
    416  1.10.16.1      yamt 	td->td_pcmcia = config_found(td->td_parent->sc_dev, &paa, tslot_print);
    417        1.1  macallan 
    418        1.1  macallan 	if (td->td_pcmcia == NULL) {
    419        1.1  macallan 		/*
    420        1.1  macallan 		 * If no pcmcia attachment, power down the slot.
    421        1.1  macallan 		 */
    422        1.1  macallan 		tslot_slot_disable((pcmcia_chipset_handle_t)td);
    423        1.1  macallan 		return;
    424        1.1  macallan 	}
    425        1.1  macallan 
    426        1.1  macallan 	/*
    427        1.1  macallan 	 * Initialize the slot
    428        1.1  macallan 	 */
    429        1.1  macallan 
    430        1.1  macallan 	ctl = TSLOT_READ(td, TS102_REG_CARD_A_CTL);
    431        1.1  macallan 
    432        1.1  macallan 	/* force low addresses */
    433        1.1  macallan 	ctl &= ~(TS102_CARD_CTL_AA_MASK | TS102_CARD_CTL_IA_MASK);
    434        1.1  macallan 
    435        1.1  macallan 	/* Put SBus and PCMCIA in their respective endian mode */
    436        1.5  macallan 	ctl |= TS102_CARD_CTL_SBLE;	/* this is not what it looks like! */
    437        1.5  macallan 	ctl &= ~TS102_CARD_CTL_PCMBE;	/* default */
    438        1.1  macallan 
    439        1.1  macallan 	/* disable read ahead and address increment */
    440        1.1  macallan 	ctl &= ~TS102_CARD_CTL_RAHD;
    441        1.1  macallan 	ctl |= TS102_CARD_CTL_INCDIS;
    442        1.1  macallan 
    443        1.1  macallan 	/* power on */
    444        1.1  macallan 	ctl &= ~TS102_CARD_CTL_PWRD;
    445        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_CTL, ctl);
    446        1.1  macallan 	TSPRINTF("ctl: %x\n", ctl);
    447        1.1  macallan 
    448        1.1  macallan 	/*
    449        1.1  macallan 	 * Enable interrupt upon insertion/removal
    450        1.1  macallan 	 */
    451        1.1  macallan 
    452        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
    453        1.1  macallan 	    TS102_CARD_INT_MASK_CARDDETECT_STATUS);
    454        1.1  macallan 
    455        1.1  macallan 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    456        1.1  macallan 	if (status & TS102_CARD_STS_PRES) {
    457        1.1  macallan 		td->td_status = TS_CARD;
    458        1.1  macallan 		pcmcia_card_attach(td->td_pcmcia);
    459        1.1  macallan 	} else
    460        1.1  macallan 		td->td_status = 0;
    461        1.1  macallan }
    462        1.1  macallan 
    463        1.1  macallan /* XXX there ought to be a common function for this... */
    464        1.5  macallan static int
    465        1.1  macallan tslot_print(void *aux, const char *description)
    466        1.1  macallan {
    467        1.1  macallan 	struct pcmciabus_attach_args *paa = aux;
    468        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)paa->pch;
    469        1.1  macallan 
    470        1.1  macallan 	printf(" socket %d", td->td_slot);
    471        1.1  macallan 	return (UNCONF);
    472        1.1  macallan }
    473        1.1  macallan 
    474        1.1  macallan /*
    475        1.1  macallan  * PCMCIA Helpers
    476        1.1  macallan  */
    477        1.1  macallan 
    478        1.5  macallan static int
    479        1.1  macallan tslot_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size,
    480        1.1  macallan     bus_size_t align, struct pcmcia_io_handle *pih)
    481        1.1  macallan {
    482        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    483        1.1  macallan 
    484        1.1  macallan #ifdef TSLOT_DEBUG
    485        1.1  macallan 	printf("[io alloc %x]", (uint32_t)size);
    486        1.1  macallan #endif
    487        1.1  macallan 
    488        1.1  macallan 	pih->iot = td->td_pcmciat;
    489        1.1  macallan 	pih->ioh = td->td_space[TS102_RANGE_IO];
    490        1.1  macallan 	pih->addr = start;
    491        1.1  macallan 	pih->size = size;
    492        1.1  macallan 	pih->flags = 0;
    493        1.1  macallan 
    494        1.1  macallan 	return (0);
    495        1.1  macallan }
    496        1.1  macallan 
    497        1.5  macallan static void
    498        1.1  macallan tslot_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
    499        1.1  macallan {
    500        1.1  macallan #ifdef TSLOT_DEBUG
    501        1.1  macallan 	printf("[io free]");
    502        1.1  macallan #endif
    503        1.1  macallan }
    504        1.1  macallan 
    505        1.5  macallan static int
    506        1.1  macallan tslot_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
    507        1.1  macallan     bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
    508        1.1  macallan {
    509        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    510        1.1  macallan 
    511        1.1  macallan #ifdef TSLOT_DEBUG
    512        1.1  macallan 	printf("[io map %x/%x", (uint32_t)offset, (uint32_t)size);
    513        1.1  macallan #endif
    514        1.1  macallan 
    515        1.1  macallan 	pih->iot = td->td_pcmciat;
    516        1.1  macallan 	if (bus_space_subregion(pih->iot, td->td_space[TS102_RANGE_IO],
    517        1.1  macallan 	    offset, size, &pih->ioh) != 0)
    518        1.1  macallan 		printf("io_map failed, offset %x\n", (uint32_t)offset);
    519        1.1  macallan 	*windowp = 0; /* TS102_RANGE_IO */
    520        1.1  macallan 
    521        1.1  macallan #ifdef TSLOT_DEBUG
    522        1.1  macallan 	printf("->%x/%x]", (uint32_t)pih->ioh, (uint32_t)size);
    523        1.1  macallan 	{
    524        1.1  macallan 		int addr, line;
    525        1.1  macallan 		for( addr = offset; addr < (offset + size); addr += 16) {
    526        1.1  macallan 			printf("%04x:", addr);
    527        1.1  macallan 			for(line = addr; line < (addr + 16); line += 2) {
    528        1.5  macallan 				printf(" %04x", bus_space_read_2(pih->iot,
    529        1.1  macallan 				    pih->ioh, line));
    530        1.1  macallan 			}
    531        1.1  macallan 			printf("\n");
    532        1.1  macallan 		}
    533        1.1  macallan 	}
    534        1.1  macallan #endif
    535        1.1  macallan 
    536        1.1  macallan 	return (0);
    537        1.1  macallan }
    538        1.1  macallan 
    539        1.5  macallan static void
    540        1.1  macallan tslot_io_unmap(pcmcia_chipset_handle_t pch, int win)
    541        1.1  macallan {
    542        1.1  macallan #ifdef TSLOT_DEBUG
    543        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    544        1.5  macallan 
    545        1.1  macallan 	printf("[io unmap]");
    546        1.1  macallan 	{
    547        1.1  macallan 		int addr, line, offset = 0, size = 0x80;
    548        1.1  macallan 		for (addr = offset; addr < (offset + size); addr += 16) {
    549        1.1  macallan 			printf("%04x:", addr);
    550        1.1  macallan 			for (line = addr; line < (addr + 16); line += 2){
    551        1.1  macallan 				printf(" %04x", bus_space_read_2(td->td_pcmciat,
    552        1.1  macallan 				    td->td_space[2], line));
    553        1.1  macallan 			}
    554        1.1  macallan 			printf("\n");
    555        1.1  macallan 		}
    556        1.1  macallan 	}
    557        1.1  macallan #endif
    558        1.1  macallan }
    559        1.1  macallan 
    560        1.5  macallan static int
    561        1.1  macallan tslot_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
    562        1.1  macallan     struct pcmcia_mem_handle *pmh)
    563        1.1  macallan {
    564        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    565        1.1  macallan 
    566        1.1  macallan #ifdef TSLOT_DEBUG
    567        1.1  macallan 	printf("[mem alloc %x]", (uint32_t)size);
    568        1.1  macallan #endif
    569        1.1  macallan 	pmh->memt = td->td_pcmciat;
    570        1.5  macallan 	pmh->size = size;
    571        1.1  macallan 	pmh->addr = 0;
    572        1.1  macallan 	pmh->mhandle = 0;
    573        1.1  macallan 	pmh->realsize = size;	/* nothing so far! */
    574        1.1  macallan 
    575        1.1  macallan 	return (0);
    576        1.1  macallan }
    577        1.1  macallan 
    578        1.5  macallan static void
    579        1.1  macallan tslot_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
    580        1.1  macallan {
    581        1.1  macallan #ifdef TSLOT_DEBUG
    582        1.1  macallan 	printf("[mem free]");
    583        1.1  macallan #endif
    584        1.1  macallan }
    585        1.1  macallan 
    586        1.5  macallan static int
    587        1.1  macallan tslot_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr,
    588        1.1  macallan     bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp,
    589        1.1  macallan     int *windowp)
    590        1.1  macallan {
    591        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    592        1.1  macallan 	int slot;
    593        1.1  macallan 
    594        1.1  macallan 	slot = kind & PCMCIA_MEM_ATTR ? TS102_RANGE_ATTR : TS102_RANGE_COMMON;
    595        1.1  macallan #ifdef TSLOT_DEBUG
    596        1.1  macallan 	printf("[mem map %d %x/%x", slot, (uint32_t)addr, (uint32_t)size);
    597        1.1  macallan #endif
    598        1.1  macallan 
    599        1.1  macallan 	pmh->memt = td->td_parent->sc_bustag;
    600        1.1  macallan 	if (bus_space_subregion(pmh->memt, td->td_space[slot],
    601        1.1  macallan 	    addr, size, &pmh->memh) != 0)
    602        1.1  macallan 		printf("mem_map failed, offset %x\n", (uint32_t)addr);
    603        1.1  macallan 	pmh->realsize = TS102_ARBITRARY_MAP_SIZE - addr;
    604        1.1  macallan 	pmh->size = size;
    605        1.1  macallan 	*offsetp = 0;
    606        1.1  macallan 	*windowp = 0;
    607        1.1  macallan 
    608        1.1  macallan #ifdef TSLOT_DEBUG
    609        1.1  macallan 	printf("->%x/%x]", (uint32_t)pmh->memh, (uint32_t)size);
    610        1.1  macallan #endif
    611        1.1  macallan 
    612        1.1  macallan 	return (0);
    613        1.1  macallan }
    614        1.1  macallan 
    615        1.5  macallan static void
    616        1.1  macallan tslot_mem_unmap(pcmcia_chipset_handle_t pch, int win)
    617        1.1  macallan {
    618        1.1  macallan #ifdef TSLOT_DEBUG
    619        1.1  macallan 	printf("[mem unmap %d]", win);
    620        1.1  macallan #endif
    621        1.1  macallan }
    622        1.1  macallan 
    623        1.5  macallan static void
    624        1.1  macallan tslot_slot_disable(pcmcia_chipset_handle_t pch)
    625        1.1  macallan {
    626        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    627        1.1  macallan #ifdef TSLOT_DEBUG
    628        1.1  macallan 	printf("%s: disable slot %d\n",
    629        1.1  macallan 	    td->td_parent->sc_dev.dv_xname, td->td_slot);
    630        1.1  macallan #endif
    631        1.1  macallan 
    632        1.1  macallan 	/*
    633        1.1  macallan 	 * Disable card access.
    634        1.1  macallan 	 */
    635        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
    636        1.1  macallan 	    TSLOT_READ(td, TS102_REG_CARD_A_STS) & ~TS102_CARD_STS_ACEN);
    637        1.1  macallan 
    638        1.1  macallan 	/*
    639        1.1  macallan 	 * Disable interrupts, except for insertion.
    640        1.1  macallan 	 */
    641        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
    642        1.1  macallan 	    TS102_CARD_INT_MASK_CARDDETECT_STATUS);
    643        1.1  macallan }
    644        1.1  macallan 
    645        1.5  macallan static void
    646        1.1  macallan tslot_slot_enable(pcmcia_chipset_handle_t pch)
    647        1.1  macallan {
    648        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    649        1.1  macallan 	int status, intr, i;
    650        1.1  macallan 
    651        1.1  macallan #ifdef TSLOT_DEBUG
    652        1.1  macallan 	printf("%s: enable slot %d\n",
    653        1.1  macallan 	    td->td_parent->sc_dev.dv_xname, td->td_slot);
    654        1.1  macallan #endif
    655        1.1  macallan 
    656        1.1  macallan 	/* Power down the socket to reset it */
    657        1.1  macallan 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    658        1.1  macallan 	TSPRINTF("status: %x\n", status);
    659        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status | TS102_CARD_STS_VCCEN);
    660        1.1  macallan 
    661        1.1  macallan 	/*
    662        1.1  macallan 	 * wait 300ms until power fails (Tpf).  Then, wait 100ms since we
    663        1.1  macallan 	 * are changing Vcc (Toff).
    664        1.1  macallan 	 */
    665        1.1  macallan 	DELAY((300 + 100) * 1000);
    666        1.1  macallan 
    667        1.1  macallan 	/*
    668        1.1  macallan 	 * Power on the card if not already done, and enable card access
    669        1.1  macallan 	 */
    670        1.1  macallan 	status |= TS102_CARD_STS_ACEN;
    671        1.1  macallan 	status &= ~TS102_CARD_STS_VCCEN;
    672        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
    673        1.1  macallan 
    674        1.1  macallan 	/*
    675        1.1  macallan 	 * wait 100ms until power raise (Tpr) and 20ms to become
    676        1.1  macallan 	 * stable (Tsu(Vcc)).
    677        1.1  macallan 	 */
    678        1.1  macallan 	DELAY((100 + 20) * 1000);
    679        1.1  macallan 
    680        1.1  macallan 	status &= ~TS102_CARD_STS_VPP1_MASK;
    681        1.1  macallan 	status |= TS102_CARD_STS_VPP1_VCC;
    682        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
    683        1.1  macallan 
    684        1.1  macallan 	/*
    685        1.1  macallan 	 * hold RESET at least 20us.
    686        1.1  macallan 	 */
    687        1.1  macallan 	intr = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    688        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TS102_CARD_INT_SOFT_RESET);
    689        1.1  macallan 	DELAY(20);
    690        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, intr);
    691        1.1  macallan 
    692        1.1  macallan 	/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
    693        1.1  macallan 	DELAY(20 * 1000);
    694        1.1  macallan 
    695        1.1  macallan 	/* We need level-triggered interrupts for PC Card hardware */
    696        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
    697        1.1  macallan 		TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_LVL);
    698        1.1  macallan 
    699        1.1  macallan 	/*
    700        1.1  macallan 	 * Wait until the card is unbusy. If it is still busy after 3 seconds,
    701        1.1  macallan 	 * give up. We could enable card interrupts and wait for the interrupt
    702        1.1  macallan 	 * to happen when BUSY is released, but the interrupt could also be
    703        1.1  macallan 	 * triggered by the card itself if it's an I/O card, so better poll
    704        1.1  macallan 	 * here.
    705        1.1  macallan 	 */
    706        1.1  macallan 	for (i = 30000; i != 0; i--) {
    707        1.1  macallan 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    708        1.1  macallan 		/* If the card has been removed, abort */
    709        1.1  macallan 		if ((status & TS102_CARD_STS_PRES) == 0) {
    710        1.1  macallan 			tslot_slot_disable(pch);
    711        1.1  macallan 			return;
    712        1.1  macallan 		}
    713        1.1  macallan 		if (status & TS102_CARD_STS_RDY)
    714        1.1  macallan 			break;
    715        1.1  macallan 		else
    716        1.1  macallan 			DELAY(100);
    717        1.1  macallan 	}
    718        1.1  macallan 
    719        1.1  macallan 	if (i == 0) {
    720        1.1  macallan 		printf("%s: slot %d still busy after 3 seconds, status 0x%x\n",
    721  1.10.16.1      yamt 		    device_xname(td->td_parent->sc_dev), td->td_slot,
    722        1.1  macallan 		    TSLOT_READ(td, TS102_REG_CARD_A_STS));
    723        1.1  macallan 		return;
    724        1.1  macallan 	}
    725        1.1  macallan }
    726        1.5  macallan static void
    727        1.1  macallan tslot_event_thread(void *v)
    728        1.1  macallan {
    729        1.1  macallan 	struct tslot_softc *sc = v;
    730        1.1  macallan 	struct tslot_data *td;
    731        1.3  macallan 	int s, status;
    732        1.1  macallan 	unsigned int socket;
    733        1.5  macallan 
    734        1.3  macallan #if NTCTRL > 0
    735        1.3  macallan 	int i;
    736        1.3  macallan 
    737        1.1  macallan 	/*
    738        1.1  macallan 	 * First-time setup of our LCD symbol. When a card is present at boot
    739        1.1  macallan 	 * time we won't detect a change here and therefore the LCD symbol won't
    740        1.1  macallan 	 * light up.
    741        1.1  macallan 	 */
    742        1.1  macallan 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
    743        1.1  macallan 		td = &sc->sc_slot[i];
    744        1.1  macallan 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    745        1.1  macallan 		tslot_update_lcd(sc, i, status & TS102_CARD_STS_PRES);
    746        1.1  macallan 	}
    747        1.1  macallan #endif
    748        1.1  macallan 
    749        1.1  macallan 	for (;;) {
    750        1.1  macallan 		s = splhigh();
    751        1.1  macallan 
    752        1.1  macallan 		if ((socket = ffs(sc->sc_events)) == 0) {
    753        1.1  macallan 			splx(s);
    754        1.7  macallan 			tsleep(&sc->sc_events, PWAIT, "tslot_event", hz * 30);
    755        1.1  macallan 			continue;
    756        1.1  macallan 		}
    757        1.1  macallan 		socket--;
    758        1.1  macallan 		sc->sc_events &= ~(1 << socket);
    759        1.1  macallan 		splx(s);
    760        1.1  macallan 
    761        1.1  macallan 		if (socket >= TS102_NUM_SLOTS) {
    762        1.1  macallan #ifdef DEBUG
    763        1.1  macallan 			printf("%s: invalid slot number %d\n",
    764  1.10.16.1      yamt 			    device_xname(sc->sc_dev), socket);
    765        1.1  macallan #endif
    766        1.1  macallan 			continue;
    767        1.1  macallan 		}
    768        1.1  macallan 
    769        1.1  macallan 		td = &sc->sc_slot[socket];
    770        1.1  macallan 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    771        1.1  macallan 
    772        1.1  macallan 		if (status & TS102_CARD_STS_PRES) {
    773        1.1  macallan 			/* Card insertion */
    774        1.1  macallan 			if ((td->td_status & TS_CARD) == 0) {
    775        1.1  macallan 				td->td_status |= TS_CARD;
    776        1.1  macallan 				tslot_update_lcd(sc, socket, 1);
    777        1.1  macallan 				pcmcia_card_attach(td->td_pcmcia);
    778        1.1  macallan 			}
    779        1.1  macallan 		} else {
    780        1.1  macallan 			/* Card removal */
    781        1.1  macallan 			if ((td->td_status & TS_CARD) != 0) {
    782        1.1  macallan 				tslot_update_lcd(sc, socket, 0);
    783        1.1  macallan 				td->td_status &= ~TS_CARD;
    784        1.1  macallan 				pcmcia_card_detach(td->td_pcmcia,
    785        1.1  macallan 				    DETACH_FORCE);
    786        1.1  macallan 			}
    787        1.1  macallan 		}
    788        1.1  macallan 	}
    789        1.1  macallan }
    790        1.1  macallan 
    791        1.1  macallan /*
    792        1.1  macallan  * Interrupt handling
    793        1.1  macallan  */
    794        1.1  macallan 
    795        1.5  macallan static int
    796        1.1  macallan tslot_intr(void *v)
    797        1.1  macallan {
    798        1.1  macallan 	struct tslot_softc *sc = v;
    799        1.1  macallan 	struct tslot_data *td;
    800        1.1  macallan 	int intregs[TS102_NUM_SLOTS], *intreg;
    801        1.1  macallan 	int i, s, rc = 0;
    802        1.1  macallan 
    803        1.1  macallan 	s = splhigh();
    804        1.1  macallan 
    805        1.1  macallan 	/*
    806        1.1  macallan 	 * Scan slots, and acknowledge the interrupt if necessary first
    807        1.1  macallan 	 */
    808        1.1  macallan 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
    809        1.1  macallan 		td = &sc->sc_slot[i];
    810        1.1  macallan 		intreg = &intregs[i];
    811        1.1  macallan 		*intreg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    812        1.1  macallan 
    813        1.1  macallan 		/*
    814        1.1  macallan 		 * Acknowledge all interrupt situations at once, even if they
    815        1.1  macallan 		 * did not occur.
    816        1.1  macallan 		 */
    817        1.1  macallan 		if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
    818        1.1  macallan 		    TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
    819        1.1  macallan 		    TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
    820        1.1  macallan 		    TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0) {
    821        1.1  macallan 			rc = 1;
    822        1.1  macallan 			TSLOT_WRITE(td, TS102_REG_CARD_A_INT, *intreg |
    823        1.1  macallan 			    TS102_CARD_INT_RQST_IRQ |
    824        1.1  macallan 			    TS102_CARD_INT_RQST_WP_STATUS_CHANGED |
    825        1.1  macallan 			    TS102_CARD_INT_RQST_BATTERY_STATUS_CHANGED |
    826        1.1  macallan 			    TS102_CARD_INT_RQST_CARDDETECT_STATUS_CHANGED);
    827        1.1  macallan 		}
    828        1.1  macallan 	}
    829        1.1  macallan 
    830        1.1  macallan #ifdef TSLOT_DEBUG
    831        1.1  macallan 	printf("tslot_intr: %x %x\n", intregs[0], intregs[1]);
    832        1.1  macallan #endif
    833        1.1  macallan 
    834        1.1  macallan 	/*
    835        1.1  macallan 	 * Invoke the interrupt handler for each slot
    836        1.1  macallan 	 */
    837        1.1  macallan 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
    838        1.1  macallan 		td = &sc->sc_slot[i];
    839        1.1  macallan 		intreg = &intregs[i];
    840        1.1  macallan 
    841        1.1  macallan 		if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
    842        1.1  macallan 		    TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
    843        1.1  macallan 		    TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
    844        1.1  macallan 		    TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0)
    845        1.1  macallan 			tslot_slot_intr(td, *intreg);
    846        1.1  macallan 	}
    847        1.1  macallan 	splx(s);
    848        1.1  macallan 
    849        1.1  macallan 	return (rc);
    850        1.1  macallan }
    851        1.1  macallan 
    852        1.5  macallan static void
    853        1.1  macallan tslot_queue_event(struct tslot_softc *sc, int slot)
    854        1.1  macallan {
    855        1.1  macallan 	int s;
    856        1.1  macallan 
    857        1.1  macallan 	s = splhigh();
    858        1.1  macallan 	sc->sc_events |= (1 << slot);
    859        1.1  macallan 	splx(s);
    860        1.1  macallan 	wakeup(&sc->sc_events);
    861        1.1  macallan }
    862        1.1  macallan 
    863        1.5  macallan static void
    864        1.1  macallan tslot_slot_intr(struct tslot_data *td, int intreg)
    865        1.1  macallan {
    866        1.1  macallan 	struct tslot_softc *sc = td->td_parent;
    867        1.1  macallan 	int status, sockstat;
    868        1.1  macallan 	uint32_t ireg;
    869        1.5  macallan 
    870        1.1  macallan 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    871        1.1  macallan #ifdef TSLOT_DEBUG
    872        1.1  macallan 	printf("%s: interrupt on socket %d ir %x sts %x\n",
    873  1.10.16.1      yamt 	    device_xname(sc->sc_dev), td->td_slot, intreg, status);
    874        1.1  macallan #endif
    875        1.1  macallan 
    876        1.1  macallan 	sockstat = td->td_status;
    877        1.1  macallan 
    878        1.1  macallan 	/*
    879        1.1  macallan 	 * The TS102 queues interrupt request, and may trigger an interrupt
    880        1.1  macallan 	 * for a condition the driver does not want to receive anymore (for
    881        1.1  macallan 	 * example, after a card gets removed).
    882        1.1  macallan 	 * Thus, only proceed if the driver is currently allowing a particular
    883        1.1  macallan 	 * condition.
    884        1.1  macallan 	 */
    885        1.1  macallan 
    886        1.1  macallan 	if ((intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) != 0 &&
    887        1.1  macallan 	    (intreg & TS102_CARD_INT_MASK_CARDDETECT_STATUS) != 0) {
    888        1.1  macallan 		tslot_queue_event(sc, td->td_slot);
    889        1.1  macallan #ifdef TSLOT_DEBUG
    890        1.1  macallan 		printf("%s: slot %d status changed from %d to %d\n",
    891  1.10.16.1      yamt 		    device_xname(sc->sc_dev), td->td_slot, sockstat,
    892  1.10.16.1      yamt 		    td->td_status);
    893        1.1  macallan #endif
    894        1.1  macallan 		/*
    895        1.1  macallan 		 * Ignore extra interrupt bits, they are part of the change.
    896        1.1  macallan 		 */
    897        1.1  macallan 		return;
    898        1.1  macallan 	}
    899        1.1  macallan 
    900        1.1  macallan 	if ((intreg & TS102_CARD_INT_STATUS_IRQ) != 0 &&
    901        1.1  macallan 	    (intreg & TS102_CARD_INT_MASK_IRQ) != 0) {
    902        1.1  macallan 		/* ignore interrupts if we have a pending state change */
    903        1.1  macallan 		if (sc->sc_events & (1 << td->td_slot))
    904        1.1  macallan 		{
    905        1.1  macallan 			TSPRINTF("ev: %d\n", sc->sc_events);
    906        1.1  macallan 			return;
    907        1.1  macallan 		}
    908        1.1  macallan 		if ((sockstat & TS_CARD) == 0) {
    909        1.1  macallan 			printf("%s: spurious interrupt on slot %d isr %x\n",
    910  1.10.16.1      yamt 			    device_xname(sc->sc_dev), td->td_slot, intreg);
    911        1.1  macallan 			return;
    912        1.1  macallan 		}
    913        1.1  macallan 
    914        1.1  macallan 		if (td->td_intr != NULL) {
    915        1.1  macallan 
    916        1.1  macallan 			if (td->td_softint != NULL)
    917       1.10        ad 				sparc_softintr_schedule(td->td_softint);
    918        1.1  macallan 			/*
    919        1.1  macallan 			 * Disable this sbus interrupt, until the soft-int
    920        1.1  macallan 			 * handler had a chance to run
    921        1.1  macallan 			 */
    922        1.1  macallan 			ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    923        1.5  macallan 			TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg &
    924        1.1  macallan 			    ~TS102_CARD_INT_MASK_IRQ);
    925        1.1  macallan 		}
    926        1.1  macallan 	}
    927        1.1  macallan }
    928        1.1  macallan 
    929        1.5  macallan static void
    930        1.1  macallan tslot_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
    931        1.1  macallan {
    932        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    933        1.1  macallan 
    934        1.1  macallan 	td->td_intr = NULL;
    935        1.1  macallan 	td->td_intrarg = NULL;
    936        1.1  macallan 	if (td->td_softint) {
    937       1.10        ad 		sparc_softintr_disestablish(td->td_softint);
    938        1.1  macallan 		td->td_softint = NULL;
    939        1.1  macallan 	}
    940        1.1  macallan }
    941        1.1  macallan 
    942        1.1  macallan const char *
    943        1.1  macallan tslot_intr_string(pcmcia_chipset_handle_t pch, void *ih)
    944        1.1  macallan {
    945        1.1  macallan 	if (ih == NULL)
    946        1.1  macallan 		return ("couldn't establish interrupt");
    947        1.1  macallan 	else
    948        1.1  macallan 		return ("");	/* nothing for now */
    949        1.1  macallan }
    950        1.1  macallan 
    951        1.5  macallan static void *
    952        1.1  macallan tslot_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
    953        1.5  macallan     int ipl, int (*handler)(void *), void *arg)
    954        1.1  macallan {
    955        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    956        1.1  macallan 
    957        1.1  macallan 	td->td_intr = handler;
    958        1.1  macallan 	td->td_intrarg = arg;
    959       1.10        ad 	td->td_softint = sparc_softintr_establish(ipl, tslot_intr_dispatch, td);
    960        1.1  macallan 
    961        1.1  macallan 	return (td);
    962        1.1  macallan }
    963        1.1  macallan 
    964        1.1  macallan /*
    965        1.1  macallan  * Softinterrupt called to invoke the real driver interrupt handler.
    966        1.1  macallan  */
    967        1.1  macallan static void
    968        1.5  macallan tslot_intr_dispatch(void *arg)
    969        1.1  macallan {
    970        1.1  macallan 	struct tslot_data *td = arg;
    971        1.1  macallan 	int s;
    972        1.1  macallan 	uint32_t ireg;
    973        1.1  macallan 
    974        1.1  macallan 	/* invoke driver handler */
    975        1.1  macallan 	td->td_intr(td->td_intrarg);
    976        1.1  macallan 
    977        1.1  macallan 	/* enable SBUS interrupts for pcmcia interrupts again */
    978        1.1  macallan 	s = splhigh();
    979        1.1  macallan 	ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    980        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg | TS102_CARD_INT_MASK_IRQ);
    981        1.1  macallan 	splx(s);
    982        1.1  macallan }
    983        1.1  macallan 
    984        1.5  macallan static void
    985        1.5  macallan tslot_slot_settype(pcmcia_chipset_handle_t pch, int type)
    986        1.1  macallan {
    987        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    988        1.1  macallan 	uint32_t reg;
    989        1.1  macallan 
    990        1.1  macallan 	/*
    991        1.1  macallan 	 * Enable the card interrupts if this is an I/O card.
    992        1.1  macallan 	 * Note that the TS102_CARD_STS_IO bit in the status register will
    993        1.1  macallan 	 * never get set, despite what the documentation says!
    994        1.1  macallan 	 */
    995        1.1  macallan 	TSPRINTF("tslot_slot_settype(%d)\n",type);
    996        1.1  macallan 	if (type == PCMCIA_IFTYPE_IO) {
    997        1.1  macallan 		TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
    998        1.1  macallan 		    TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_IO);
    999        1.1  macallan 		TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
   1000        1.1  macallan 		    TS102_CARD_INT_MASK_CARDDETECT_STATUS |
   1001        1.1  macallan 		    TS102_CARD_INT_MASK_IRQ);
   1002        1.1  macallan 		reg=TSLOT_READ(td, TS102_REG_CARD_A_STS);
   1003        1.1  macallan 		TSPRINTF("status: %x\n", reg);
   1004        1.1  macallan 	}
   1005        1.1  macallan }
   1006        1.1  macallan 
   1007        1.5  macallan static void
   1008        1.1  macallan tslot_update_lcd(struct tslot_softc *sc, int socket, int status)
   1009        1.1  macallan {
   1010        1.1  macallan #if NTCTRL > 0
   1011        1.1  macallan 	int was = (sc->sc_active != 0), is;
   1012        1.1  macallan 	int mask = 1 << socket;
   1013        1.5  macallan 
   1014        1.5  macallan 	if (status > 0) {
   1015        1.1  macallan 		sc->sc_active |= mask;
   1016        1.1  macallan 	} else {
   1017        1.1  macallan 		sc->sc_active &= (mask ^ 3);
   1018        1.1  macallan 	}
   1019        1.1  macallan 	is = (sc->sc_active != 0);
   1020        1.1  macallan 	if (was != is) {
   1021        1.7  macallan 		tadpole_set_lcd(is, 0x40);
   1022        1.1  macallan 	}
   1023        1.1  macallan #endif
   1024        1.1  macallan }
   1025