Home | History | Annotate | Line # | Download | only in dev
ts102.c revision 1.16.12.2
      1        1.1  macallan /*	$OpenBSD: ts102.c,v 1.14 2005/01/27 17:03:23 millert Exp $	*/
      2  1.16.12.2       tls /*	$NetBSD: ts102.c,v 1.16.12.2 2014/08/20 00:03:24 tls Exp $ */
      3        1.1  macallan /*
      4        1.1  macallan  * Copyright (c) 2003, 2004, Miodrag Vallat.
      5       1.11  macallan  * 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.15    dyoung #include <sys/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.12  macallan 	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.12  macallan 	device_t	sc_dev;
    140        1.1  macallan 
    141        1.1  macallan 	bus_space_tag_t	sc_bustag;		/* socket control io	*/
    142        1.1  macallan 	bus_space_handle_t	sc_regh;	/*  space		*/
    143        1.1  macallan 
    144        1.1  macallan 	pcmcia_chipset_tag_t sc_pct;
    145        1.1  macallan 
    146        1.8        ad 	lwp_t		*sc_thread;	/* event thread */
    147        1.5  macallan 	uint32_t	sc_events;	/* sockets with pending events */
    148        1.1  macallan 
    149        1.1  macallan 	/* bits 0 and 1 are set according to card presence in slot 0 and 1 */
    150        1.5  macallan 	uint32_t 	sc_active;
    151        1.1  macallan 
    152        1.1  macallan 	struct tslot_data sc_slot[TS102_NUM_SLOTS];
    153        1.1  macallan };
    154        1.1  macallan 
    155       1.12  macallan static void tslot_attach(device_t, device_t, void *);
    156        1.5  macallan static void tslot_event_thread(void *);
    157        1.5  macallan static int  tslot_intr(void *);
    158        1.5  macallan static void tslot_intr_disestablish(pcmcia_chipset_handle_t, void *);
    159        1.5  macallan static void *tslot_intr_establish(pcmcia_chipset_handle_t,
    160        1.5  macallan     struct pcmcia_function *, int, int (*)(void *), void *);
    161        1.5  macallan 
    162        1.5  macallan const char  *tslot_intr_string(pcmcia_chipset_handle_t, void *);
    163        1.5  macallan static int  tslot_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
    164        1.1  macallan     bus_size_t, struct pcmcia_io_handle *);
    165        1.5  macallan static void tslot_io_free(pcmcia_chipset_handle_t, struct pcmcia_io_handle *);
    166        1.5  macallan static int  tslot_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
    167        1.1  macallan     struct pcmcia_io_handle *, int *);
    168        1.5  macallan static void tslot_io_unmap(pcmcia_chipset_handle_t, int);
    169       1.12  macallan static int  tslot_match(device_t, struct cfdata *, void *);
    170        1.5  macallan static int  tslot_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
    171        1.1  macallan     struct pcmcia_mem_handle *);
    172        1.5  macallan static void tslot_mem_free(pcmcia_chipset_handle_t, struct pcmcia_mem_handle *);
    173        1.5  macallan static int  tslot_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
    174        1.1  macallan     struct pcmcia_mem_handle *, bus_size_t *, int *);
    175        1.5  macallan static void tslot_mem_unmap(pcmcia_chipset_handle_t, int);
    176        1.5  macallan static int  tslot_print(void *, const char *);
    177        1.5  macallan static void tslot_queue_event(struct tslot_softc *, int);
    178        1.5  macallan static void tslot_reset(struct tslot_data *, uint32_t);
    179        1.5  macallan static void tslot_slot_disable(pcmcia_chipset_handle_t);
    180        1.5  macallan static void tslot_slot_enable(pcmcia_chipset_handle_t);
    181        1.5  macallan static void tslot_slot_intr(struct tslot_data *, int);
    182        1.5  macallan static void tslot_slot_settype(pcmcia_chipset_handle_t, int);
    183        1.5  macallan static void tslot_update_lcd(struct tslot_softc *, int, int);
    184        1.1  macallan static void tslot_intr_dispatch(void *arg);
    185        1.1  macallan 
    186       1.13  macallan CFATTACH_DECL_NEW(tslot, sizeof(struct tslot_softc),
    187        1.1  macallan     tslot_match, tslot_attach, NULL, NULL);
    188        1.1  macallan 
    189        1.1  macallan extern struct cfdriver tslot_cd;
    190        1.1  macallan 
    191        1.1  macallan /*
    192        1.1  macallan  * PCMCIA chipset methods
    193        1.1  macallan  */
    194        1.1  macallan struct	pcmcia_chip_functions tslot_functions = {
    195        1.1  macallan 	tslot_mem_alloc,
    196        1.1  macallan 	tslot_mem_free,
    197        1.1  macallan 	tslot_mem_map,
    198        1.1  macallan 	tslot_mem_unmap,
    199        1.1  macallan 
    200        1.1  macallan 	tslot_io_alloc,
    201        1.1  macallan 	tslot_io_free,
    202        1.1  macallan 	tslot_io_map,
    203        1.1  macallan 	tslot_io_unmap,
    204        1.1  macallan 
    205        1.1  macallan 	tslot_intr_establish,
    206        1.1  macallan 	tslot_intr_disestablish,
    207        1.1  macallan 
    208        1.1  macallan 	tslot_slot_enable,
    209        1.1  macallan 	tslot_slot_disable,
    210        1.1  macallan 	tslot_slot_settype
    211        1.1  macallan };
    212        1.1  macallan 
    213        1.5  macallan static	uint16_t ts102_read_2(bus_space_tag_t,
    214        1.1  macallan 				 bus_space_handle_t,
    215        1.1  macallan 				 bus_size_t);
    216        1.5  macallan static	uint32_t ts102_read_4(bus_space_tag_t,
    217        1.1  macallan 				 bus_space_handle_t,
    218        1.1  macallan 				 bus_size_t);
    219        1.5  macallan static	uint64_t ts102_read_8(bus_space_tag_t,
    220        1.1  macallan 				 bus_space_handle_t,
    221        1.1  macallan 				 bus_size_t);
    222        1.1  macallan static	void	ts102_write_2(bus_space_tag_t,
    223        1.1  macallan 				bus_space_handle_t,
    224        1.1  macallan 				bus_size_t,
    225        1.5  macallan 				uint16_t);
    226        1.1  macallan static	void	ts102_write_4(bus_space_tag_t,
    227        1.1  macallan 				bus_space_handle_t,
    228        1.1  macallan 				bus_size_t,
    229        1.5  macallan 				uint32_t);
    230        1.1  macallan static	void	ts102_write_8(bus_space_tag_t,
    231        1.1  macallan 				bus_space_handle_t,
    232        1.1  macallan 				bus_size_t,
    233        1.5  macallan 				uint64_t);
    234        1.1  macallan 
    235        1.5  macallan static uint16_t
    236        1.5  macallan ts102_read_2(bus_space_tag_t space, bus_space_handle_t handle,
    237        1.5  macallan     bus_size_t offset)
    238        1.1  macallan {
    239        1.5  macallan 	return (le16toh(*(volatile uint16_t *)(handle +
    240        1.1  macallan 	    offset)));
    241        1.1  macallan }
    242        1.1  macallan 
    243        1.5  macallan static uint32_t
    244        1.5  macallan ts102_read_4(bus_space_tag_t space, bus_space_handle_t handle,
    245        1.5  macallan     bus_size_t offset)
    246        1.1  macallan {
    247        1.5  macallan 	return (le32toh(*(volatile uint32_t *)(handle +
    248        1.1  macallan 	    offset)));
    249        1.1  macallan }
    250        1.1  macallan 
    251        1.5  macallan static uint64_t
    252        1.5  macallan ts102_read_8(bus_space_tag_t space, bus_space_handle_t handle,
    253        1.5  macallan     bus_size_t offset)
    254        1.1  macallan {
    255        1.5  macallan 	return (le64toh(*(volatile uint64_t *)(handle +
    256        1.1  macallan 	    offset)));
    257        1.1  macallan }
    258        1.1  macallan 
    259        1.1  macallan static void
    260        1.5  macallan ts102_write_2(bus_space_tag_t space, bus_space_handle_t handle,
    261        1.5  macallan     bus_size_t offset, uint16_t value)
    262        1.1  macallan {
    263        1.5  macallan 	(*(volatile uint16_t *)(handle + offset)) =
    264        1.1  macallan 	    htole16(value);
    265        1.1  macallan }
    266        1.1  macallan 
    267        1.1  macallan static void
    268        1.5  macallan ts102_write_4(bus_space_tag_t space, bus_space_handle_t handle,
    269        1.5  macallan     bus_size_t offset, uint32_t value)
    270        1.1  macallan {
    271        1.5  macallan 	(*(volatile uint32_t *)(handle + offset)) =
    272        1.1  macallan 	    htole32(value);
    273        1.1  macallan }
    274        1.1  macallan 
    275        1.1  macallan static void
    276        1.5  macallan ts102_write_8(bus_space_tag_t space, bus_space_handle_t handle,
    277        1.5  macallan     bus_size_t offset, uint64_t value)
    278        1.1  macallan {
    279        1.5  macallan 	(*(volatile uint64_t *)(handle + offset)) =
    280        1.1  macallan 	    htole64(value);
    281        1.1  macallan }
    282        1.1  macallan 
    283        1.1  macallan 
    284        1.1  macallan #define	TSLOT_READ(slot, offset) \
    285        1.6       uwe 	*(volatile uint16_t *)((slot)->td_regs + (offset))
    286        1.1  macallan #define	TSLOT_WRITE(slot, offset, value) \
    287        1.6       uwe 	*(volatile uint16_t *)((slot)->td_regs + (offset)) = (value)
    288        1.1  macallan 
    289        1.1  macallan /*
    290        1.1  macallan  * Attachment and initialization
    291        1.1  macallan  */
    292        1.1  macallan 
    293        1.5  macallan static int
    294       1.12  macallan tslot_match(device_t parent, struct cfdata *vcf, void *aux)
    295        1.1  macallan {
    296        1.1  macallan 	struct sbus_attach_args *sa = aux;
    297        1.1  macallan 
    298        1.1  macallan 	return (strcmp("ts102", sa->sa_name) == 0);
    299        1.1  macallan }
    300        1.1  macallan 
    301        1.5  macallan static void
    302       1.12  macallan tslot_attach(device_t parent, device_t self, void *args)
    303        1.1  macallan {
    304        1.1  macallan 	struct sbus_attach_args *sa = args;
    305       1.12  macallan 	struct tslot_softc *sc = device_private(self);
    306        1.1  macallan 	struct tslot_data *td;
    307        1.6       uwe 	volatile uint8_t *regs;
    308        1.1  macallan 	int node, slot, rnum, base, size;
    309        1.1  macallan 	uint32_t ranges[30];
    310        1.1  macallan 	void *rptr = ranges;
    311        1.1  macallan 	bus_space_handle_t hrang = 0;
    312        1.1  macallan 	bus_space_tag_t tag;
    313        1.5  macallan 
    314       1.12  macallan 	sc->sc_dev = self;
    315        1.1  macallan 	node = sa->sa_node;
    316        1.1  macallan 	sc->sc_bustag=sa->sa_bustag;
    317        1.1  macallan 	if (sbus_bus_map(sa->sa_bustag,
    318        1.1  macallan 			 sa->sa_slot,
    319        1.1  macallan 			 sa->sa_offset,
    320        1.1  macallan 			 sa->sa_size,
    321        1.1  macallan 			 0, &sc->sc_regh) != 0) {
    322  1.16.12.1       tls 		printf("%s: cannot map registers\n", device_xname(self));
    323        1.1  macallan 		return;
    324        1.1  macallan 	}
    325        1.5  macallan 	regs = (uint8_t *)bus_space_vaddr(sa->sa_bustag, sc->sc_regh);
    326        1.5  macallan 
    327        1.1  macallan 	tag = bus_space_tag_alloc(sa->sa_bustag, sc);
    328        1.1  macallan 	if (tag == NULL) {
    329  1.16.12.1       tls 		printf("%s: attach: out of memory\n", device_xname(self));
    330        1.1  macallan 		return;
    331        1.1  macallan 	}
    332        1.1  macallan 	tag->sparc_read_2 = ts102_read_2;
    333        1.1  macallan 	tag->sparc_read_4 = ts102_read_4;
    334        1.1  macallan 	tag->sparc_read_8 = ts102_read_8;
    335        1.1  macallan 	tag->sparc_write_2 = ts102_write_2;
    336        1.1  macallan 	tag->sparc_write_4 = ts102_write_4;
    337        1.1  macallan 	tag->sparc_write_8 = ts102_write_8;
    338        1.1  macallan 
    339        1.5  macallan 	bus_intr_establish(sa->sa_bustag, sa->sa_intr[0].oi_pri,
    340        1.1  macallan 	    IPL_NONE, tslot_intr, sc);
    341        1.1  macallan 
    342        1.1  macallan 	printf(": %d slots\n", TS102_NUM_SLOTS);
    343        1.5  macallan 
    344        1.1  macallan 	size = sizeof(ranges);
    345        1.1  macallan 	if (prom_getprop(node, "ranges", 4, &size, &rptr) != 0) {
    346        1.1  macallan 		printf("couldn't read ranges\n");
    347        1.1  macallan 		return;
    348        1.1  macallan 	}
    349        1.1  macallan 
    350        1.1  macallan 	/*
    351        1.1  macallan 	 * Setup asynchronous event handler
    352        1.1  macallan 	 */
    353        1.1  macallan 	sc->sc_events = 0;
    354        1.8        ad 
    355        1.8        ad 	TSPRINTF("starting event thread...\n");
    356        1.8        ad 	if (kthread_create(PRI_NONE, 0, NULL, tslot_event_thread, sc,
    357       1.13  macallan 	    &sc->sc_thread, "%s", device_xname(self)) != 0) {
    358        1.8        ad 		panic("%s: unable to create event kthread",
    359       1.13  macallan 		    device_xname(self));
    360        1.8        ad 	}
    361        1.1  macallan 
    362        1.1  macallan 	sc->sc_pct = (pcmcia_chipset_tag_t)&tslot_functions;
    363        1.1  macallan 	sc->sc_active = 0;
    364        1.1  macallan 
    365        1.1  macallan 	/*
    366        1.1  macallan 	 * Setup slots
    367        1.1  macallan 	 */
    368        1.1  macallan 	TSPRINTF("mapping resources...\n");
    369        1.1  macallan 	for (slot = 0; slot < TS102_NUM_SLOTS; slot++) {
    370        1.1  macallan 		td = &sc->sc_slot[slot];
    371        1.1  macallan 		TSPRINTF("slot %d, ",slot);
    372        1.1  macallan 		for (rnum = 0; rnum < TS102_RANGE_CNT; rnum++) {
    373        1.1  macallan 			base = (slot * TS102_RANGE_CNT + rnum) * 5;
    374        1.5  macallan 			TSPRINTF("%d: %08x %08x ",rnum,ranges[base + 3],
    375        1.1  macallan 			    ranges[base + 4]);
    376        1.1  macallan 			if(sbus_bus_map(sc->sc_bustag,
    377        1.1  macallan 					sa->sa_slot,
    378        1.1  macallan 				 	ranges[base+3],
    379        1.1  macallan 				 	TS102_ARBITRARY_MAP_SIZE,
    380        1.1  macallan 					0, &hrang) != 0) {
    381        1.5  macallan 				printf("%s: cannot map registers\n",
    382  1.16.12.1       tls 				    device_xname(self));
    383        1.1  macallan 				return;
    384        1.1  macallan 			}
    385        1.5  macallan 			TSPRINTF("%08x: %08x ",(uint32_t)ranges[base + 3],
    386        1.1  macallan 			    (uint32_t)hrang);
    387        1.1  macallan 			td->td_space[rnum] = hrang;
    388        1.1  macallan 		}
    389        1.1  macallan 		td->td_parent = sc;
    390        1.1  macallan 		td->td_pcmciat = tag;
    391        1.1  macallan 		td->td_softint = NULL;
    392        1.5  macallan 		td->td_regs = regs + slot * (TS102_REG_CARD_B_INT -
    393        1.1  macallan 		    TS102_REG_CARD_A_INT);
    394        1.1  macallan 		td->td_slot = slot;
    395        1.1  macallan 
    396        1.1  macallan 		TSPRINTF("resetting slot %d %d\n", slot, (int)td->td_regs);
    397        1.1  macallan 		tslot_reset(td, TS102_ARBITRARY_MAP_SIZE);
    398        1.1  macallan 	}
    399        1.1  macallan }
    400        1.1  macallan 
    401        1.5  macallan static void
    402        1.5  macallan tslot_reset(struct tslot_data *td, uint32_t iosize)
    403        1.1  macallan {
    404        1.1  macallan 	struct pcmciabus_attach_args paa;
    405        1.1  macallan 	int ctl, status;
    406        1.1  macallan 
    407        1.1  macallan 	paa.paa_busname = "pcmcia";
    408        1.1  macallan 	paa.pct = (pcmcia_chipset_tag_t)td->td_parent->sc_pct;
    409        1.1  macallan 	paa.pch = (pcmcia_chipset_handle_t)td;
    410        1.1  macallan 
    411       1.12  macallan 	td->td_pcmcia = config_found(td->td_parent->sc_dev, &paa, tslot_print);
    412        1.1  macallan 
    413        1.1  macallan 	if (td->td_pcmcia == NULL) {
    414        1.1  macallan 		/*
    415        1.1  macallan 		 * If no pcmcia attachment, power down the slot.
    416        1.1  macallan 		 */
    417        1.1  macallan 		tslot_slot_disable((pcmcia_chipset_handle_t)td);
    418        1.1  macallan 		return;
    419        1.1  macallan 	}
    420        1.1  macallan 
    421        1.1  macallan 	/*
    422        1.1  macallan 	 * Initialize the slot
    423        1.1  macallan 	 */
    424        1.1  macallan 
    425        1.1  macallan 	ctl = TSLOT_READ(td, TS102_REG_CARD_A_CTL);
    426        1.1  macallan 
    427        1.1  macallan 	/* force low addresses */
    428        1.1  macallan 	ctl &= ~(TS102_CARD_CTL_AA_MASK | TS102_CARD_CTL_IA_MASK);
    429        1.1  macallan 
    430        1.1  macallan 	/* Put SBus and PCMCIA in their respective endian mode */
    431        1.5  macallan 	ctl |= TS102_CARD_CTL_SBLE;	/* this is not what it looks like! */
    432        1.5  macallan 	ctl &= ~TS102_CARD_CTL_PCMBE;	/* default */
    433        1.1  macallan 
    434        1.1  macallan 	/* disable read ahead and address increment */
    435        1.1  macallan 	ctl &= ~TS102_CARD_CTL_RAHD;
    436        1.1  macallan 	ctl |= TS102_CARD_CTL_INCDIS;
    437        1.1  macallan 
    438        1.1  macallan 	/* power on */
    439        1.1  macallan 	ctl &= ~TS102_CARD_CTL_PWRD;
    440        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_CTL, ctl);
    441        1.1  macallan 	TSPRINTF("ctl: %x\n", ctl);
    442        1.1  macallan 
    443        1.1  macallan 	/*
    444        1.1  macallan 	 * Enable interrupt upon insertion/removal
    445        1.1  macallan 	 */
    446        1.1  macallan 
    447        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
    448        1.1  macallan 	    TS102_CARD_INT_MASK_CARDDETECT_STATUS);
    449        1.1  macallan 
    450        1.1  macallan 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    451        1.1  macallan 	if (status & TS102_CARD_STS_PRES) {
    452        1.1  macallan 		td->td_status = TS_CARD;
    453        1.1  macallan 		pcmcia_card_attach(td->td_pcmcia);
    454        1.1  macallan 	} else
    455        1.1  macallan 		td->td_status = 0;
    456        1.1  macallan }
    457        1.1  macallan 
    458        1.1  macallan /* XXX there ought to be a common function for this... */
    459        1.5  macallan static int
    460        1.1  macallan tslot_print(void *aux, const char *description)
    461        1.1  macallan {
    462        1.1  macallan 	struct pcmciabus_attach_args *paa = aux;
    463        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)paa->pch;
    464        1.1  macallan 
    465        1.1  macallan 	printf(" socket %d", td->td_slot);
    466        1.1  macallan 	return (UNCONF);
    467        1.1  macallan }
    468        1.1  macallan 
    469        1.1  macallan /*
    470        1.1  macallan  * PCMCIA Helpers
    471        1.1  macallan  */
    472        1.1  macallan 
    473        1.5  macallan static int
    474        1.1  macallan tslot_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size,
    475        1.1  macallan     bus_size_t align, struct pcmcia_io_handle *pih)
    476        1.1  macallan {
    477        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    478        1.1  macallan 
    479        1.1  macallan #ifdef TSLOT_DEBUG
    480        1.1  macallan 	printf("[io alloc %x]", (uint32_t)size);
    481        1.1  macallan #endif
    482        1.1  macallan 
    483        1.1  macallan 	pih->iot = td->td_pcmciat;
    484        1.1  macallan 	pih->ioh = td->td_space[TS102_RANGE_IO];
    485        1.1  macallan 	pih->addr = start;
    486        1.1  macallan 	pih->size = size;
    487        1.1  macallan 	pih->flags = 0;
    488        1.1  macallan 
    489        1.1  macallan 	return (0);
    490        1.1  macallan }
    491        1.1  macallan 
    492        1.5  macallan static void
    493        1.1  macallan tslot_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
    494        1.1  macallan {
    495        1.1  macallan #ifdef TSLOT_DEBUG
    496        1.1  macallan 	printf("[io free]");
    497        1.1  macallan #endif
    498        1.1  macallan }
    499        1.1  macallan 
    500        1.5  macallan static int
    501        1.1  macallan tslot_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
    502        1.1  macallan     bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
    503        1.1  macallan {
    504        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    505        1.1  macallan 
    506        1.1  macallan #ifdef TSLOT_DEBUG
    507        1.1  macallan 	printf("[io map %x/%x", (uint32_t)offset, (uint32_t)size);
    508        1.1  macallan #endif
    509        1.1  macallan 
    510        1.1  macallan 	pih->iot = td->td_pcmciat;
    511        1.1  macallan 	if (bus_space_subregion(pih->iot, td->td_space[TS102_RANGE_IO],
    512        1.1  macallan 	    offset, size, &pih->ioh) != 0)
    513        1.1  macallan 		printf("io_map failed, offset %x\n", (uint32_t)offset);
    514        1.1  macallan 	*windowp = 0; /* TS102_RANGE_IO */
    515        1.1  macallan 
    516        1.1  macallan #ifdef TSLOT_DEBUG
    517        1.1  macallan 	printf("->%x/%x]", (uint32_t)pih->ioh, (uint32_t)size);
    518        1.1  macallan 	{
    519        1.1  macallan 		int addr, line;
    520        1.1  macallan 		for( addr = offset; addr < (offset + size); addr += 16) {
    521        1.1  macallan 			printf("%04x:", addr);
    522        1.1  macallan 			for(line = addr; line < (addr + 16); line += 2) {
    523        1.5  macallan 				printf(" %04x", bus_space_read_2(pih->iot,
    524        1.1  macallan 				    pih->ioh, line));
    525        1.1  macallan 			}
    526        1.1  macallan 			printf("\n");
    527        1.1  macallan 		}
    528        1.1  macallan 	}
    529        1.1  macallan #endif
    530        1.1  macallan 
    531        1.1  macallan 	return (0);
    532        1.1  macallan }
    533        1.1  macallan 
    534        1.5  macallan static void
    535        1.1  macallan tslot_io_unmap(pcmcia_chipset_handle_t pch, int win)
    536        1.1  macallan {
    537        1.1  macallan #ifdef TSLOT_DEBUG
    538        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    539        1.5  macallan 
    540        1.1  macallan 	printf("[io unmap]");
    541        1.1  macallan 	{
    542        1.1  macallan 		int addr, line, offset = 0, size = 0x80;
    543        1.1  macallan 		for (addr = offset; addr < (offset + size); addr += 16) {
    544        1.1  macallan 			printf("%04x:", addr);
    545        1.1  macallan 			for (line = addr; line < (addr + 16); line += 2){
    546        1.1  macallan 				printf(" %04x", bus_space_read_2(td->td_pcmciat,
    547        1.1  macallan 				    td->td_space[2], line));
    548        1.1  macallan 			}
    549        1.1  macallan 			printf("\n");
    550        1.1  macallan 		}
    551        1.1  macallan 	}
    552        1.1  macallan #endif
    553        1.1  macallan }
    554        1.1  macallan 
    555        1.5  macallan static int
    556        1.1  macallan tslot_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
    557        1.1  macallan     struct pcmcia_mem_handle *pmh)
    558        1.1  macallan {
    559        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    560        1.1  macallan 
    561        1.1  macallan #ifdef TSLOT_DEBUG
    562        1.1  macallan 	printf("[mem alloc %x]", (uint32_t)size);
    563        1.1  macallan #endif
    564        1.1  macallan 	pmh->memt = td->td_pcmciat;
    565        1.5  macallan 	pmh->size = size;
    566        1.1  macallan 	pmh->addr = 0;
    567        1.1  macallan 	pmh->mhandle = 0;
    568        1.1  macallan 	pmh->realsize = size;	/* nothing so far! */
    569        1.1  macallan 
    570        1.1  macallan 	return (0);
    571        1.1  macallan }
    572        1.1  macallan 
    573        1.5  macallan static void
    574        1.1  macallan tslot_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
    575        1.1  macallan {
    576        1.1  macallan #ifdef TSLOT_DEBUG
    577        1.1  macallan 	printf("[mem free]");
    578        1.1  macallan #endif
    579        1.1  macallan }
    580        1.1  macallan 
    581        1.5  macallan static int
    582        1.1  macallan tslot_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr,
    583        1.1  macallan     bus_size_t size, struct pcmcia_mem_handle *pmh, bus_size_t *offsetp,
    584        1.1  macallan     int *windowp)
    585        1.1  macallan {
    586        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    587        1.1  macallan 	int slot;
    588        1.1  macallan 
    589        1.1  macallan 	slot = kind & PCMCIA_MEM_ATTR ? TS102_RANGE_ATTR : TS102_RANGE_COMMON;
    590        1.1  macallan #ifdef TSLOT_DEBUG
    591        1.1  macallan 	printf("[mem map %d %x/%x", slot, (uint32_t)addr, (uint32_t)size);
    592        1.1  macallan #endif
    593        1.1  macallan 
    594        1.1  macallan 	pmh->memt = td->td_parent->sc_bustag;
    595        1.1  macallan 	if (bus_space_subregion(pmh->memt, td->td_space[slot],
    596        1.1  macallan 	    addr, size, &pmh->memh) != 0)
    597        1.1  macallan 		printf("mem_map failed, offset %x\n", (uint32_t)addr);
    598        1.1  macallan 	pmh->realsize = TS102_ARBITRARY_MAP_SIZE - addr;
    599        1.1  macallan 	pmh->size = size;
    600        1.1  macallan 	*offsetp = 0;
    601        1.1  macallan 	*windowp = 0;
    602        1.1  macallan 
    603        1.1  macallan #ifdef TSLOT_DEBUG
    604        1.1  macallan 	printf("->%x/%x]", (uint32_t)pmh->memh, (uint32_t)size);
    605        1.1  macallan #endif
    606        1.1  macallan 
    607        1.1  macallan 	return (0);
    608        1.1  macallan }
    609        1.1  macallan 
    610        1.5  macallan static void
    611        1.1  macallan tslot_mem_unmap(pcmcia_chipset_handle_t pch, int win)
    612        1.1  macallan {
    613        1.1  macallan #ifdef TSLOT_DEBUG
    614        1.1  macallan 	printf("[mem unmap %d]", win);
    615        1.1  macallan #endif
    616        1.1  macallan }
    617        1.1  macallan 
    618        1.5  macallan static void
    619        1.1  macallan tslot_slot_disable(pcmcia_chipset_handle_t pch)
    620        1.1  macallan {
    621        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    622        1.1  macallan #ifdef TSLOT_DEBUG
    623        1.1  macallan 	printf("%s: disable slot %d\n",
    624  1.16.12.1       tls 	    device_xname(td->td_parent->sc_dev), td->td_slot);
    625        1.1  macallan #endif
    626        1.1  macallan 
    627        1.1  macallan 	/*
    628        1.1  macallan 	 * Disable card access.
    629        1.1  macallan 	 */
    630        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
    631        1.1  macallan 	    TSLOT_READ(td, TS102_REG_CARD_A_STS) & ~TS102_CARD_STS_ACEN);
    632        1.1  macallan 
    633        1.1  macallan 	/*
    634        1.1  macallan 	 * Disable interrupts, except for insertion.
    635        1.1  macallan 	 */
    636        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
    637        1.1  macallan 	    TS102_CARD_INT_MASK_CARDDETECT_STATUS);
    638        1.1  macallan }
    639        1.1  macallan 
    640        1.5  macallan static void
    641        1.1  macallan tslot_slot_enable(pcmcia_chipset_handle_t pch)
    642        1.1  macallan {
    643        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    644        1.1  macallan 	int status, intr, i;
    645        1.1  macallan 
    646        1.1  macallan #ifdef TSLOT_DEBUG
    647        1.1  macallan 	printf("%s: enable slot %d\n",
    648  1.16.12.1       tls 	    device_xname(td->td_parent->sc_dev), td->td_slot);
    649        1.1  macallan #endif
    650        1.1  macallan 
    651        1.1  macallan 	/* Power down the socket to reset it */
    652        1.1  macallan 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    653        1.1  macallan 	TSPRINTF("status: %x\n", status);
    654        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status | TS102_CARD_STS_VCCEN);
    655        1.1  macallan 
    656        1.1  macallan 	/*
    657        1.1  macallan 	 * wait 300ms until power fails (Tpf).  Then, wait 100ms since we
    658        1.1  macallan 	 * are changing Vcc (Toff).
    659        1.1  macallan 	 */
    660        1.1  macallan 	DELAY((300 + 100) * 1000);
    661        1.1  macallan 
    662        1.1  macallan 	/*
    663        1.1  macallan 	 * Power on the card if not already done, and enable card access
    664        1.1  macallan 	 */
    665        1.1  macallan 	status |= TS102_CARD_STS_ACEN;
    666        1.1  macallan 	status &= ~TS102_CARD_STS_VCCEN;
    667        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
    668        1.1  macallan 
    669        1.1  macallan 	/*
    670        1.1  macallan 	 * wait 100ms until power raise (Tpr) and 20ms to become
    671        1.1  macallan 	 * stable (Tsu(Vcc)).
    672        1.1  macallan 	 */
    673        1.1  macallan 	DELAY((100 + 20) * 1000);
    674        1.1  macallan 
    675        1.1  macallan 	status &= ~TS102_CARD_STS_VPP1_MASK;
    676        1.1  macallan 	status |= TS102_CARD_STS_VPP1_VCC;
    677        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status);
    678        1.1  macallan 
    679        1.1  macallan 	/*
    680        1.1  macallan 	 * hold RESET at least 20us.
    681        1.1  macallan 	 */
    682        1.1  macallan 	intr = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    683        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TS102_CARD_INT_SOFT_RESET);
    684        1.1  macallan 	DELAY(20);
    685        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, intr);
    686        1.1  macallan 
    687        1.1  macallan 	/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
    688        1.1  macallan 	DELAY(20 * 1000);
    689        1.1  macallan 
    690        1.1  macallan 	/* We need level-triggered interrupts for PC Card hardware */
    691        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
    692        1.1  macallan 		TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_LVL);
    693        1.1  macallan 
    694        1.1  macallan 	/*
    695        1.1  macallan 	 * Wait until the card is unbusy. If it is still busy after 3 seconds,
    696        1.1  macallan 	 * give up. We could enable card interrupts and wait for the interrupt
    697        1.1  macallan 	 * to happen when BUSY is released, but the interrupt could also be
    698        1.1  macallan 	 * triggered by the card itself if it's an I/O card, so better poll
    699        1.1  macallan 	 * here.
    700        1.1  macallan 	 */
    701        1.1  macallan 	for (i = 30000; i != 0; i--) {
    702        1.1  macallan 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    703        1.1  macallan 		/* If the card has been removed, abort */
    704        1.1  macallan 		if ((status & TS102_CARD_STS_PRES) == 0) {
    705        1.1  macallan 			tslot_slot_disable(pch);
    706        1.1  macallan 			return;
    707        1.1  macallan 		}
    708        1.1  macallan 		if (status & TS102_CARD_STS_RDY)
    709        1.1  macallan 			break;
    710        1.1  macallan 		else
    711        1.1  macallan 			DELAY(100);
    712        1.1  macallan 	}
    713        1.1  macallan 
    714        1.1  macallan 	if (i == 0) {
    715        1.1  macallan 		printf("%s: slot %d still busy after 3 seconds, status 0x%x\n",
    716       1.12  macallan 		    device_xname(td->td_parent->sc_dev), td->td_slot,
    717        1.1  macallan 		    TSLOT_READ(td, TS102_REG_CARD_A_STS));
    718        1.1  macallan 		return;
    719        1.1  macallan 	}
    720        1.1  macallan }
    721        1.5  macallan static void
    722        1.1  macallan tslot_event_thread(void *v)
    723        1.1  macallan {
    724        1.1  macallan 	struct tslot_softc *sc = v;
    725        1.1  macallan 	struct tslot_data *td;
    726        1.3  macallan 	int s, status;
    727        1.1  macallan 	unsigned int socket;
    728        1.5  macallan 
    729        1.3  macallan #if NTCTRL > 0
    730        1.3  macallan 	int i;
    731        1.3  macallan 
    732        1.1  macallan 	/*
    733        1.1  macallan 	 * First-time setup of our LCD symbol. When a card is present at boot
    734        1.1  macallan 	 * time we won't detect a change here and therefore the LCD symbol won't
    735        1.1  macallan 	 * light up.
    736        1.1  macallan 	 */
    737        1.1  macallan 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
    738        1.1  macallan 		td = &sc->sc_slot[i];
    739        1.1  macallan 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    740        1.1  macallan 		tslot_update_lcd(sc, i, status & TS102_CARD_STS_PRES);
    741        1.1  macallan 	}
    742        1.1  macallan #endif
    743        1.1  macallan 
    744        1.1  macallan 	for (;;) {
    745        1.1  macallan 		s = splhigh();
    746        1.1  macallan 
    747        1.1  macallan 		if ((socket = ffs(sc->sc_events)) == 0) {
    748        1.1  macallan 			splx(s);
    749        1.7  macallan 			tsleep(&sc->sc_events, PWAIT, "tslot_event", hz * 30);
    750        1.1  macallan 			continue;
    751        1.1  macallan 		}
    752        1.1  macallan 		socket--;
    753        1.1  macallan 		sc->sc_events &= ~(1 << socket);
    754        1.1  macallan 		splx(s);
    755        1.1  macallan 
    756        1.1  macallan 		if (socket >= TS102_NUM_SLOTS) {
    757        1.1  macallan #ifdef DEBUG
    758        1.1  macallan 			printf("%s: invalid slot number %d\n",
    759       1.12  macallan 			    device_xname(sc->sc_dev), socket);
    760        1.1  macallan #endif
    761        1.1  macallan 			continue;
    762        1.1  macallan 		}
    763        1.1  macallan 
    764        1.1  macallan 		td = &sc->sc_slot[socket];
    765        1.1  macallan 		status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    766        1.1  macallan 
    767        1.1  macallan 		if (status & TS102_CARD_STS_PRES) {
    768        1.1  macallan 			/* Card insertion */
    769        1.1  macallan 			if ((td->td_status & TS_CARD) == 0) {
    770        1.1  macallan 				td->td_status |= TS_CARD;
    771        1.1  macallan 				tslot_update_lcd(sc, socket, 1);
    772        1.1  macallan 				pcmcia_card_attach(td->td_pcmcia);
    773        1.1  macallan 			}
    774        1.1  macallan 		} else {
    775        1.1  macallan 			/* Card removal */
    776        1.1  macallan 			if ((td->td_status & TS_CARD) != 0) {
    777        1.1  macallan 				tslot_update_lcd(sc, socket, 0);
    778        1.1  macallan 				td->td_status &= ~TS_CARD;
    779        1.1  macallan 				pcmcia_card_detach(td->td_pcmcia,
    780        1.1  macallan 				    DETACH_FORCE);
    781        1.1  macallan 			}
    782        1.1  macallan 		}
    783        1.1  macallan 	}
    784        1.1  macallan }
    785        1.1  macallan 
    786        1.1  macallan /*
    787        1.1  macallan  * Interrupt handling
    788        1.1  macallan  */
    789        1.1  macallan 
    790        1.5  macallan static int
    791        1.1  macallan tslot_intr(void *v)
    792        1.1  macallan {
    793        1.1  macallan 	struct tslot_softc *sc = v;
    794        1.1  macallan 	struct tslot_data *td;
    795        1.1  macallan 	int intregs[TS102_NUM_SLOTS], *intreg;
    796        1.1  macallan 	int i, s, rc = 0;
    797        1.1  macallan 
    798        1.1  macallan 	s = splhigh();
    799        1.1  macallan 
    800        1.1  macallan 	/*
    801        1.1  macallan 	 * Scan slots, and acknowledge the interrupt if necessary first
    802        1.1  macallan 	 */
    803        1.1  macallan 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
    804        1.1  macallan 		td = &sc->sc_slot[i];
    805        1.1  macallan 		intreg = &intregs[i];
    806        1.1  macallan 		*intreg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    807        1.1  macallan 
    808        1.1  macallan 		/*
    809        1.1  macallan 		 * Acknowledge all interrupt situations at once, even if they
    810        1.1  macallan 		 * did not occur.
    811        1.1  macallan 		 */
    812        1.1  macallan 		if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
    813        1.1  macallan 		    TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
    814        1.1  macallan 		    TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
    815        1.1  macallan 		    TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0) {
    816        1.1  macallan 			rc = 1;
    817        1.1  macallan 			TSLOT_WRITE(td, TS102_REG_CARD_A_INT, *intreg |
    818        1.1  macallan 			    TS102_CARD_INT_RQST_IRQ |
    819        1.1  macallan 			    TS102_CARD_INT_RQST_WP_STATUS_CHANGED |
    820        1.1  macallan 			    TS102_CARD_INT_RQST_BATTERY_STATUS_CHANGED |
    821        1.1  macallan 			    TS102_CARD_INT_RQST_CARDDETECT_STATUS_CHANGED);
    822        1.1  macallan 		}
    823        1.1  macallan 	}
    824        1.1  macallan 
    825        1.1  macallan #ifdef TSLOT_DEBUG
    826        1.1  macallan 	printf("tslot_intr: %x %x\n", intregs[0], intregs[1]);
    827        1.1  macallan #endif
    828        1.1  macallan 
    829        1.1  macallan 	/*
    830        1.1  macallan 	 * Invoke the interrupt handler for each slot
    831        1.1  macallan 	 */
    832        1.1  macallan 	for (i = 0; i < TS102_NUM_SLOTS; i++) {
    833        1.1  macallan 		td = &sc->sc_slot[i];
    834        1.1  macallan 		intreg = &intregs[i];
    835        1.1  macallan 
    836        1.1  macallan 		if ((*intreg & (TS102_CARD_INT_STATUS_IRQ |
    837        1.1  macallan 		    TS102_CARD_INT_STATUS_WP_STATUS_CHANGED |
    838        1.1  macallan 		    TS102_CARD_INT_STATUS_BATTERY_STATUS_CHANGED |
    839        1.1  macallan 		    TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED)) != 0)
    840        1.1  macallan 			tslot_slot_intr(td, *intreg);
    841        1.1  macallan 	}
    842        1.1  macallan 	splx(s);
    843        1.1  macallan 
    844        1.1  macallan 	return (rc);
    845        1.1  macallan }
    846        1.1  macallan 
    847        1.5  macallan static void
    848        1.1  macallan tslot_queue_event(struct tslot_softc *sc, int slot)
    849        1.1  macallan {
    850        1.1  macallan 	int s;
    851        1.1  macallan 
    852        1.1  macallan 	s = splhigh();
    853        1.1  macallan 	sc->sc_events |= (1 << slot);
    854        1.1  macallan 	splx(s);
    855        1.1  macallan 	wakeup(&sc->sc_events);
    856        1.1  macallan }
    857        1.1  macallan 
    858        1.5  macallan static void
    859        1.1  macallan tslot_slot_intr(struct tslot_data *td, int intreg)
    860        1.1  macallan {
    861        1.1  macallan 	struct tslot_softc *sc = td->td_parent;
    862        1.1  macallan 	int status, sockstat;
    863        1.1  macallan 	uint32_t ireg;
    864        1.5  macallan 
    865        1.1  macallan 	status = TSLOT_READ(td, TS102_REG_CARD_A_STS);
    866        1.1  macallan #ifdef TSLOT_DEBUG
    867        1.1  macallan 	printf("%s: interrupt on socket %d ir %x sts %x\n",
    868       1.12  macallan 	    device_xname(sc->sc_dev), td->td_slot, intreg, status);
    869  1.16.12.2       tls #else
    870  1.16.12.2       tls 	__USE(status);
    871        1.1  macallan #endif
    872        1.1  macallan 
    873        1.1  macallan 	sockstat = td->td_status;
    874        1.1  macallan 
    875        1.1  macallan 	/*
    876        1.1  macallan 	 * The TS102 queues interrupt request, and may trigger an interrupt
    877        1.1  macallan 	 * for a condition the driver does not want to receive anymore (for
    878        1.1  macallan 	 * example, after a card gets removed).
    879        1.1  macallan 	 * Thus, only proceed if the driver is currently allowing a particular
    880        1.1  macallan 	 * condition.
    881        1.1  macallan 	 */
    882        1.1  macallan 
    883        1.1  macallan 	if ((intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) != 0 &&
    884        1.1  macallan 	    (intreg & TS102_CARD_INT_MASK_CARDDETECT_STATUS) != 0) {
    885        1.1  macallan 		tslot_queue_event(sc, td->td_slot);
    886        1.1  macallan #ifdef TSLOT_DEBUG
    887        1.1  macallan 		printf("%s: slot %d status changed from %d to %d\n",
    888       1.12  macallan 		    device_xname(sc->sc_dev), td->td_slot, sockstat,
    889       1.12  macallan 		    td->td_status);
    890        1.1  macallan #endif
    891        1.1  macallan 		/*
    892        1.1  macallan 		 * Ignore extra interrupt bits, they are part of the change.
    893        1.1  macallan 		 */
    894        1.1  macallan 		return;
    895        1.1  macallan 	}
    896        1.1  macallan 
    897        1.1  macallan 	if ((intreg & TS102_CARD_INT_STATUS_IRQ) != 0 &&
    898        1.1  macallan 	    (intreg & TS102_CARD_INT_MASK_IRQ) != 0) {
    899        1.1  macallan 		/* ignore interrupts if we have a pending state change */
    900        1.1  macallan 		if (sc->sc_events & (1 << td->td_slot))
    901        1.1  macallan 		{
    902        1.1  macallan 			TSPRINTF("ev: %d\n", sc->sc_events);
    903        1.1  macallan 			return;
    904        1.1  macallan 		}
    905        1.1  macallan 		if ((sockstat & TS_CARD) == 0) {
    906        1.1  macallan 			printf("%s: spurious interrupt on slot %d isr %x\n",
    907       1.12  macallan 			    device_xname(sc->sc_dev), td->td_slot, intreg);
    908        1.1  macallan 			return;
    909        1.1  macallan 		}
    910        1.1  macallan 
    911        1.1  macallan 		if (td->td_intr != NULL) {
    912        1.1  macallan 
    913        1.1  macallan 			if (td->td_softint != NULL)
    914       1.10        ad 				sparc_softintr_schedule(td->td_softint);
    915        1.1  macallan 			/*
    916        1.1  macallan 			 * Disable this sbus interrupt, until the soft-int
    917        1.1  macallan 			 * handler had a chance to run
    918        1.1  macallan 			 */
    919        1.1  macallan 			ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    920        1.5  macallan 			TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg &
    921        1.1  macallan 			    ~TS102_CARD_INT_MASK_IRQ);
    922        1.1  macallan 		}
    923        1.1  macallan 	}
    924        1.1  macallan }
    925        1.1  macallan 
    926        1.5  macallan static void
    927        1.1  macallan tslot_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
    928        1.1  macallan {
    929        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    930        1.1  macallan 
    931        1.1  macallan 	td->td_intr = NULL;
    932        1.1  macallan 	td->td_intrarg = NULL;
    933        1.1  macallan 	if (td->td_softint) {
    934       1.10        ad 		sparc_softintr_disestablish(td->td_softint);
    935        1.1  macallan 		td->td_softint = NULL;
    936        1.1  macallan 	}
    937        1.1  macallan }
    938        1.1  macallan 
    939        1.1  macallan const char *
    940        1.1  macallan tslot_intr_string(pcmcia_chipset_handle_t pch, void *ih)
    941        1.1  macallan {
    942        1.1  macallan 	if (ih == NULL)
    943        1.1  macallan 		return ("couldn't establish interrupt");
    944        1.1  macallan 	else
    945        1.1  macallan 		return ("");	/* nothing for now */
    946        1.1  macallan }
    947        1.1  macallan 
    948        1.5  macallan static void *
    949        1.1  macallan tslot_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
    950        1.5  macallan     int ipl, int (*handler)(void *), void *arg)
    951        1.1  macallan {
    952        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    953        1.1  macallan 
    954        1.1  macallan 	td->td_intr = handler;
    955        1.1  macallan 	td->td_intrarg = arg;
    956       1.10        ad 	td->td_softint = sparc_softintr_establish(ipl, tslot_intr_dispatch, td);
    957        1.1  macallan 
    958        1.1  macallan 	return (td);
    959        1.1  macallan }
    960        1.1  macallan 
    961        1.1  macallan /*
    962        1.1  macallan  * Softinterrupt called to invoke the real driver interrupt handler.
    963        1.1  macallan  */
    964        1.1  macallan static void
    965        1.5  macallan tslot_intr_dispatch(void *arg)
    966        1.1  macallan {
    967        1.1  macallan 	struct tslot_data *td = arg;
    968        1.1  macallan 	int s;
    969        1.1  macallan 	uint32_t ireg;
    970        1.1  macallan 
    971        1.1  macallan 	/* invoke driver handler */
    972        1.1  macallan 	td->td_intr(td->td_intrarg);
    973        1.1  macallan 
    974        1.1  macallan 	/* enable SBUS interrupts for pcmcia interrupts again */
    975        1.1  macallan 	s = splhigh();
    976        1.1  macallan 	ireg = TSLOT_READ(td, TS102_REG_CARD_A_INT);
    977        1.1  macallan 	TSLOT_WRITE(td, TS102_REG_CARD_A_INT, ireg | TS102_CARD_INT_MASK_IRQ);
    978        1.1  macallan 	splx(s);
    979        1.1  macallan }
    980        1.1  macallan 
    981        1.5  macallan static void
    982        1.5  macallan tslot_slot_settype(pcmcia_chipset_handle_t pch, int type)
    983        1.1  macallan {
    984        1.1  macallan 	struct tslot_data *td = (struct tslot_data *)pch;
    985        1.1  macallan 	uint32_t reg;
    986        1.1  macallan 
    987        1.1  macallan 	/*
    988        1.1  macallan 	 * Enable the card interrupts if this is an I/O card.
    989        1.1  macallan 	 * Note that the TS102_CARD_STS_IO bit in the status register will
    990        1.1  macallan 	 * never get set, despite what the documentation says!
    991        1.1  macallan 	 */
    992        1.1  macallan 	TSPRINTF("tslot_slot_settype(%d)\n",type);
    993        1.1  macallan 	if (type == PCMCIA_IFTYPE_IO) {
    994        1.1  macallan 		TSLOT_WRITE(td, TS102_REG_CARD_A_STS,
    995        1.1  macallan 		    TSLOT_READ(td, TS102_REG_CARD_A_STS) | TS102_CARD_STS_IO);
    996        1.1  macallan 		TSLOT_WRITE(td, TS102_REG_CARD_A_INT,
    997        1.1  macallan 		    TS102_CARD_INT_MASK_CARDDETECT_STATUS |
    998        1.1  macallan 		    TS102_CARD_INT_MASK_IRQ);
    999        1.1  macallan 		reg=TSLOT_READ(td, TS102_REG_CARD_A_STS);
   1000        1.1  macallan 		TSPRINTF("status: %x\n", reg);
   1001        1.1  macallan 	}
   1002        1.1  macallan }
   1003        1.1  macallan 
   1004        1.5  macallan static void
   1005        1.1  macallan tslot_update_lcd(struct tslot_softc *sc, int socket, int status)
   1006        1.1  macallan {
   1007        1.1  macallan #if NTCTRL > 0
   1008        1.1  macallan 	int was = (sc->sc_active != 0), is;
   1009        1.1  macallan 	int mask = 1 << socket;
   1010        1.5  macallan 
   1011        1.5  macallan 	if (status > 0) {
   1012        1.1  macallan 		sc->sc_active |= mask;
   1013        1.1  macallan 	} else {
   1014        1.1  macallan 		sc->sc_active &= (mask ^ 3);
   1015        1.1  macallan 	}
   1016        1.1  macallan 	is = (sc->sc_active != 0);
   1017        1.1  macallan 	if (was != is) {
   1018        1.7  macallan 		tadpole_set_lcd(is, 0x40);
   1019        1.1  macallan 	}
   1020        1.1  macallan #endif
   1021        1.1  macallan }
   1022