Home | History | Annotate | Line # | Download | only in isa
isa_shark_machdep.c revision 1.4
      1  1.4    lukem /*	$NetBSD: isa_shark_machdep.c,v 1.4 2003/07/15 03:36:01 lukem Exp $	*/
      2  1.1  thorpej 
      3  1.1  thorpej /*
      4  1.1  thorpej  * Copyright 1997
      5  1.1  thorpej  * Digital Equipment Corporation. All rights reserved.
      6  1.1  thorpej  *
      7  1.1  thorpej  * This software is furnished under license and may be used and
      8  1.1  thorpej  * copied only in accordance with the following terms and conditions.
      9  1.1  thorpej  * Subject to these conditions, you may download, copy, install,
     10  1.1  thorpej  * use, modify and distribute this software in source and/or binary
     11  1.1  thorpej  * form. No title or ownership is transferred hereby.
     12  1.1  thorpej  *
     13  1.1  thorpej  * 1) Any source code used, modified or distributed must reproduce
     14  1.1  thorpej  *    and retain this copyright notice and list of conditions as
     15  1.1  thorpej  *    they appear in the source file.
     16  1.1  thorpej  *
     17  1.1  thorpej  * 2) No right is granted to use any trade name, trademark, or logo of
     18  1.1  thorpej  *    Digital Equipment Corporation. Neither the "Digital Equipment
     19  1.1  thorpej  *    Corporation" name nor any trademark or logo of Digital Equipment
     20  1.1  thorpej  *    Corporation may be used to endorse or promote products derived
     21  1.1  thorpej  *    from this software without the prior written permission of
     22  1.1  thorpej  *    Digital Equipment Corporation.
     23  1.1  thorpej  *
     24  1.1  thorpej  * 3) This software is provided "AS-IS" and any express or implied
     25  1.1  thorpej  *    warranties, including but not limited to, any implied warranties
     26  1.1  thorpej  *    of merchantability, fitness for a particular purpose, or
     27  1.1  thorpej  *    non-infringement are disclaimed. In no event shall DIGITAL be
     28  1.1  thorpej  *    liable for any damages whatsoever, and in particular, DIGITAL
     29  1.1  thorpej  *    shall not be liable for special, indirect, consequential, or
     30  1.1  thorpej  *    incidental damages or damages for lost profits, loss of
     31  1.1  thorpej  *    revenue or loss of use, whether such damages arise in contract,
     32  1.1  thorpej  *    negligence, tort, under statute, in equity, at law or otherwise,
     33  1.1  thorpej  *    even if advised of the possibility of such damage.
     34  1.1  thorpej  */
     35  1.4    lukem 
     36  1.4    lukem #include <sys/cdefs.h>
     37  1.4    lukem __KERNEL_RCSID(0, "$NetBSD: isa_shark_machdep.c,v 1.4 2003/07/15 03:36:01 lukem Exp $");
     38  1.1  thorpej 
     39  1.1  thorpej #include <sys/param.h>
     40  1.1  thorpej #include <sys/systm.h>
     41  1.1  thorpej #include <sys/kernel.h>
     42  1.1  thorpej #include <sys/syslog.h>
     43  1.1  thorpej #include <sys/device.h>
     44  1.1  thorpej #include <sys/malloc.h>
     45  1.1  thorpej 
     46  1.1  thorpej #include <machine/intr.h>
     47  1.1  thorpej #include <machine/pio.h>
     48  1.1  thorpej 
     49  1.1  thorpej #include <dev/isa/isareg.h>
     50  1.1  thorpej #include <dev/isa/isavar.h>
     51  1.1  thorpej #include <dev/isa/isadmavar.h>
     52  1.1  thorpej #include <shark/isa/icu.h>
     53  1.1  thorpej 
     54  1.1  thorpej #include <machine/ofw.h>
     55  1.1  thorpej 
     56  1.1  thorpej struct arm32_isa_chipset isa_chipset_tag;
     57  1.1  thorpej 
     58  1.1  thorpej unsigned i8259_mask;
     59  1.1  thorpej 
     60  1.3      chs void isa_init8259s(void);
     61  1.3      chs 
     62  1.1  thorpej /* Notes on the interaction of StrongARM and ISA.  A lot of the nastiness
     63  1.1  thorpej    is caused by consciously prostituting shark to a low bill of materials.
     64  1.1  thorpej 
     65  1.1  thorpej    It takes on the order of 700ns (about 150 instruction cycles at
     66  1.1  thorpej    233 MHz) to access the ISA bus, so it is important to minimize the number
     67  1.1  thorpej    of ISA accesses, in particular to the 8259 interrupt controllers.
     68  1.1  thorpej 
     69  1.1  thorpej    To reduce the number of accesses, the 8259's are NOT run in the
     70  1.1  thorpej    same mode as on a typical Intel (IBM AT) system, which requires
     71  1.1  thorpej    an interrupt acknowledge sequence (INTA) for every interrupt.
     72  1.1  thorpej    Instead, the 8259's are used as big OR gates with interrupt masks
     73  1.1  thorpej    on the front.  The code in irq.S takes particular care to cache
     74  1.1  thorpej    the state of the interrupt masks and only update them when absolutely
     75  1.1  thorpej    necessary.
     76  1.1  thorpej 
     77  1.1  thorpej    Unfortunately, resetting the 8259 edge detectors without a real
     78  1.1  thorpej    INTA sequence is problematic at best.  To complicate matters further,
     79  1.1  thorpej    (unlike EISA components) the 8259s on the Sequoia core logic do
     80  1.1  thorpej    not allow configuration of edge vs. level on an IRQ-by-IRQ basis.
     81  1.1  thorpej    Thus, all interrupts must be either edge-triggered or level-triggered.
     82  1.1  thorpej    To preserve the sanity of the system, this code chooses the
     83  1.1  thorpej    level-triggered configuration.
     84  1.1  thorpej 
     85  1.1  thorpej    None of the possible operation modes of the 8254 interval timers can
     86  1.1  thorpej    be used to generate a periodic, level-triggered, clearable clock
     87  1.1  thorpej    interrupt.  This restriction means that TIMER0 -- hardwired to IRQ0 --
     88  1.1  thorpej    may not be used as the heartbeat timer, as it is on Intel-based PCs.
     89  1.1  thorpej    Instead, the real-time clock (RTC) interrupt -- connected to
     90  1.1  thorpej    IRQ8 -- has the right properties and is used for the heartbeat interrupt.
     91  1.1  thorpej    TIMER0 may still be used to implement a microsecond timer.
     92  1.1  thorpej    See clock.c for details.
     93  1.1  thorpej 
     94  1.1  thorpej    As on most PC systems, 8254 TIMER1 is used for the ISA refresh signal.
     95  1.1  thorpej 
     96  1.1  thorpej    Unlike most PC systems, 8254 TIMER2 is not used for cheap tone
     97  1.1  thorpej    generation.  Instead, it is used to create a high-availability interrupt
     98  1.1  thorpej    for bit-bashing functions (e.g. for SmartCard access).  TIMER2 output,
     99  1.1  thorpej    called "SPKR" on Sequoia 2, is routed back into the SWTCH input on
    100  1.1  thorpej    Sequoia 1.  This input eventually reemerges from Sequoia 1 on the SMI pin,
    101  1.1  thorpej    which is then converted into the StrongARM FIQ (fast interrupt request).
    102  1.1  thorpej    To clear this interrupt, the StrongARM clears the SMI.
    103  1.1  thorpej    See .../shark/fiq.S for details.
    104  1.1  thorpej 
    105  1.1  thorpej    One more complication: ISA devices can be rather nasty with respect
    106  1.1  thorpej    to ISA bus usage.  For example, the CS8900 ethernet chip will occupy
    107  1.1  thorpej    the bus for very long DMA streams.  It is possible to configure the
    108  1.1  thorpej    chip so it relinquishes the ISA bus every 28 usec or so
    109  1.1  thorpej    (about every 6500 instructions).  This causes problems when trying
    110  1.1  thorpej    to run the TIMER2/SMI/FIQ at 50 kHz, which is required to detect the
    111  1.1  thorpej    baud rate of the SmartCard.  A modification to .../dev/isa/isadma.c
    112  1.1  thorpej    allows the processor to freeze DMA during critial periods of time.
    113  1.1  thorpej    This is a working -- but not very satisfactory -- solution to the problem.
    114  1.1  thorpej */
    115  1.1  thorpej 
    116  1.1  thorpej /*
    117  1.1  thorpej  * Initialize the interrupt controllers.
    118  1.1  thorpej  */
    119  1.1  thorpej void
    120  1.3      chs isa_init8259s(void)
    121  1.1  thorpej {
    122  1.1  thorpej   /* initialize 8259's */
    123  1.1  thorpej   outb(IO_ICU1, 0x19);		   /* reset; four bytes, level triggered */
    124  1.1  thorpej   outb(IO_ICU1+1, ICU_OFFSET);	   /* int base: not used */
    125  1.1  thorpej   outb(IO_ICU1+1, 1 << IRQ_SLAVE); /* slave on line 2 */
    126  1.1  thorpej   outb(IO_ICU1+1, 2 | 1);	   /* auto EOI, 8086 mode */
    127  1.1  thorpej   outb(IO_ICU1+1, 0xff);	   /* disable all interrupts */
    128  1.1  thorpej   outb(IO_ICU1, 0x68);		   /* special mask mode (if available) */
    129  1.1  thorpej   outb(IO_ICU1, 0x0a);		   /* Read IRR, not ISR */
    130  1.1  thorpej 
    131  1.1  thorpej   outb(IO_ICU2, 0x19);		   /* reset; four bytes, level triggered */
    132  1.1  thorpej   outb(IO_ICU2+1, ICU_OFFSET+8);   /* int base + offset for master: not used */
    133  1.1  thorpej   outb(IO_ICU2+1, IRQ_SLAVE);      /* who ami i? */
    134  1.1  thorpej   outb(IO_ICU2+1, 2 | 1);	   /* auto EOI, 8086 mode */
    135  1.1  thorpej   outb(IO_ICU2+1, 0xff);	   /* disable all interrupts */
    136  1.1  thorpej   outb(IO_ICU2, 0x68);		   /* special mask mode (if available) */
    137  1.1  thorpej   outb(IO_ICU2, 0x0a);		   /* Read IRR by default. */
    138  1.1  thorpej 
    139  1.1  thorpej   i8259_mask = 0x0000ffff;         /* everything disabled */
    140  1.1  thorpej }
    141  1.1  thorpej 
    142  1.1  thorpej #define	LEGAL_IRQ(x)	((x) >= 0 && (x) < ICU_LEN && (x) != 2)
    143  1.1  thorpej 
    144  1.1  thorpej const struct evcnt *
    145  1.1  thorpej isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
    146  1.1  thorpej {
    147  1.1  thorpej 
    148  1.1  thorpej 	/* XXX for now, no evcnt parent reported */
    149  1.1  thorpej 	return NULL;
    150  1.1  thorpej }
    151  1.1  thorpej 
    152  1.1  thorpej /*
    153  1.1  thorpej  * Set up an interrupt handler to start being called.
    154  1.1  thorpej  */
    155  1.2      cgd static const char * const isa_intr_names[16] = {
    156  1.2      cgd 	"isa intr  0", "isa intr  1", "isa intr  2", "isa intr  3",
    157  1.2      cgd 	"isa intr  4", "isa intr  5", "isa intr  6", "isa intr  7",
    158  1.2      cgd 	"isa intr  8", "isa intr  9", "isa intr 10", "isa intr 11",
    159  1.2      cgd 	"isa intr 12", "isa intr 13", "isa intr 14", "isa intr 15"
    160  1.2      cgd };
    161  1.2      cgd 
    162  1.1  thorpej void *
    163  1.1  thorpej isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
    164  1.1  thorpej 	isa_chipset_tag_t ic;
    165  1.1  thorpej 	int irq;
    166  1.1  thorpej 	int type;
    167  1.1  thorpej 	int level;
    168  1.1  thorpej 	int (*ih_fun) __P((void *));
    169  1.1  thorpej 	void *ih_arg;
    170  1.1  thorpej {
    171  1.1  thorpej 	    irqhandler_t *ih;
    172  1.1  thorpej 
    173  1.1  thorpej 	    /* no point in sleeping unless someone can free memory. */
    174  1.1  thorpej 	    ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    175  1.1  thorpej 	    if (ih == NULL)
    176  1.1  thorpej 		panic("isa_intr_establish: can't malloc handler info");
    177  1.1  thorpej 
    178  1.1  thorpej 	    if (!LEGAL_IRQ(irq) || type == IST_NONE)
    179  1.1  thorpej 		panic("intr_establish: bogus irq or type");
    180  1.1  thorpej 
    181  1.1  thorpej 	    /* Note: sequoia doesn't allow configuration of edge vs. level
    182  1.1  thorpej 	       on an IRQ-by-IRQ basis.  */
    183  1.1  thorpej 	    if (type != IST_LEVEL)
    184  1.1  thorpej 	      printf("WARNING: irq %d not level triggered\n", irq);
    185  1.1  thorpej 
    186  1.1  thorpej 	    memset(ih, 0, sizeof *ih);
    187  1.1  thorpej 	    ih->ih_func = ih_fun;
    188  1.1  thorpej 	    ih->ih_arg = ih_arg;
    189  1.1  thorpej 	    ih->ih_level = level;
    190  1.2      cgd 	    if (irq >= 0 &&
    191  1.2      cgd 		irq < (sizeof isa_intr_names / sizeof isa_intr_names[0]))
    192  1.2      cgd 		    ih->ih_name = isa_intr_names[irq];
    193  1.2      cgd 	    else
    194  1.2      cgd 		    ih->ih_name = "isa intr";
    195  1.1  thorpej 
    196  1.1  thorpej 	    if (irq_claim(irq, ih) == -1)
    197  1.1  thorpej 		panic("isa_intr_establish: can't install handler");
    198  1.1  thorpej 
    199  1.1  thorpej 	    return (ih);
    200  1.1  thorpej }
    201  1.1  thorpej 
    202  1.1  thorpej 
    203  1.1  thorpej /*
    204  1.1  thorpej  * Deregister an interrupt handler.
    205  1.1  thorpej  */
    206  1.1  thorpej void
    207  1.1  thorpej isa_intr_disestablish(ic, arg)
    208  1.1  thorpej 	isa_chipset_tag_t ic;
    209  1.1  thorpej 	void *arg;
    210  1.1  thorpej {
    211  1.1  thorpej     panic("isa_intr_disestablish");
    212  1.1  thorpej }
    213  1.1  thorpej 
    214  1.1  thorpej /* isa_init() might eventually become the ISA attach routine */
    215  1.1  thorpej void
    216  1.1  thorpej isa_init(vm_offset_t isa_io_addr, vm_offset_t isa_mem_addr)
    217  1.1  thorpej {
    218  1.1  thorpej   /* initialize the bus space functions */
    219  1.1  thorpej   isa_io_init(isa_io_addr, isa_mem_addr);
    220  1.1  thorpej 
    221  1.1  thorpej   /* Clear the IRQ/FIQ masks */
    222  1.1  thorpej   isa_init8259s();
    223  1.1  thorpej 
    224  1.1  thorpej   /* Initialize the ISA interrupt handling code */
    225  1.1  thorpej   irq_init();
    226  1.1  thorpej }
    227  1.1  thorpej 
    228  1.1  thorpej void
    229  1.1  thorpej isa_attach_hook(parent, self, iba)
    230  1.1  thorpej         struct device *parent, *self;
    231  1.1  thorpej         struct isabus_attach_args *iba;
    232  1.1  thorpej {
    233  1.1  thorpej 
    234  1.1  thorpej 	/*
    235  1.1  thorpej 	 * Since we can only have one ISA bus, we just use a single
    236  1.1  thorpej 	 * statically allocated ISA chipset structure.  Pass it up
    237  1.1  thorpej 	 * now.
    238  1.1  thorpej 	 */
    239  1.1  thorpej 	iba->iba_ic = &isa_chipset_tag;
    240  1.1  thorpej }
    241