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