]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/pci/t2.c
Modify the critical section API as follows:
[FreeBSD/FreeBSD.git] / sys / alpha / pci / t2.c
1 /*
2  * Copyright (c) 2000 Andrew Gallatin & Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * Portions of this file were obtained from Compaq intellectual
27  * property which was made available under the following copyright:
28  *
29  * *****************************************************************
30  * *                                                               *
31  * *    Copyright Compaq Computer Corporation, 2000                *
32  * *                                                               *
33  * *   Permission to use, copy, modify, distribute, and sell       *
34  * *   this software and its documentation for any purpose is      *
35  * *   hereby granted without fee, provided that the above         *
36  * *   copyright notice appear in all copies and that both         *
37  * *   that copyright notice and this permission notice appear     *
38  * *   in supporting documentation, and that the name of           *
39  * *   Compaq Computer Corporation not be used in advertising      *
40  * *   or publicity pertaining to distribution of the software     *
41  * *   without specific, written prior permission.  Compaq         *
42  * *   makes no representations about the suitability of this      *
43  * *   software for any purpose.  It is provided "AS IS"           *
44  * *   without express or implied warranty.                        *
45  * *                                                               *
46  * *****************************************************************
47  *
48  * $FreeBSD$
49  */
50
51 /*
52  * T2 CBUS to PCI bridge
53  */
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kernel.h>
58 #include <sys/module.h>
59 #include <sys/malloc.h>
60 #include <sys/bus.h>
61 #include <machine/bus.h>
62 #include <sys/proc.h>
63 #include <sys/rman.h>
64 #include <sys/interrupt.h>
65
66 #include <alpha/pci/t2reg.h>
67 #include <alpha/pci/t2var.h>
68 #include <alpha/isa/isavar.h>
69 #include <machine/intr.h>
70 #include <machine/resource.h>
71 #include <machine/intrcnt.h>
72 #include <machine/cpuconf.h>
73 #include <machine/swiz.h>
74 #include <machine/sgmap.h>
75 #include <pci/pcivar.h>
76
77 #include <vm/vm.h>
78 #include <vm/vm_page.h>
79
80 #define KV(pa)                  ALPHA_PHYS_TO_K0SEG(pa + sable_lynx_base)
81
82 vm_offset_t     sable_lynx_base = 0UL;
83
84 volatile t2_csr_t *t2_csr[2];
85 static int pci_int_type[2];
86
87 static devclass_t       t2_devclass;
88 static device_t         t2_0;           /* XXX only one for now */
89
90 struct t2_softc {
91         int             junk;
92 };
93
94 #define T2_SOFTC(dev)   (struct t2_softc*) device_get_softc(dev)
95
96 static alpha_chipset_read_hae_t t2_read_hae;
97 static alpha_chipset_write_hae_t t2_write_hae;
98
99 static alpha_chipset_t t2_chipset = {
100         t2_read_hae,
101         t2_write_hae,
102 };
103
104 static u_int32_t        t2_hae_mem[2];
105
106 #define REG1 (1UL << 24)
107
108 static u_int32_t
109 t2_set_hae_mem(void *arg, u_int32_t pa)
110 {
111         int s; 
112         u_int32_t msb;
113         int hose;
114
115         hose = (long)arg;
116
117         if(pa >= REG1){
118                 msb = pa & 0xf8000000;
119                 pa -= msb;
120                 msb >>= 27;     /* t2 puts high bits in the bottom of the register */
121                 s = cpu_critical_enter();
122                 if (msb != t2_hae_mem[hose]) {
123                         t2_hae_mem[hose] = msb;
124                         t2_csr[hose]->hae0_1 = t2_hae_mem[hose];
125                         alpha_mb();
126                         t2_hae_mem[hose] = t2_csr[hose]->hae0_1;
127                 }
128                 cpu_critical_exit(s);
129         }
130         return pa;
131 }
132
133 static u_int64_t
134 t2_read_hae(void)
135 {
136         return t2_hae_mem[0] << 27;
137 }
138
139 static void
140 t2_write_hae(u_int64_t hae)
141 {
142         u_int32_t pa = hae;
143         t2_set_hae_mem(0, pa);
144 }
145
146 static int t2_probe(device_t dev);
147 static int t2_attach(device_t dev);
148 static int t2_setup_intr(device_t dev, device_t child,
149                             struct resource *irq, int flags,
150                             void *intr, void *arg, void **cookiep);
151 static int t2_teardown_intr(device_t dev, device_t child,
152                             struct resource *irq, void *cookie);
153 static void
154 t2_dispatch_intr(void *frame, unsigned long vector);
155 static void
156 t2_machine_check(unsigned long mces, struct trapframe *framep, 
157                  unsigned long vector, unsigned long param);
158
159
160 static device_method_t t2_methods[] = {
161         /* Device interface */
162         DEVMETHOD(device_probe,                 t2_probe),
163         DEVMETHOD(device_attach,                t2_attach),
164
165         /* Bus interface */
166         DEVMETHOD(bus_setup_intr,               t2_setup_intr),
167         DEVMETHOD(bus_teardown_intr,            t2_teardown_intr),
168
169         { 0, 0 }
170 };
171
172 static driver_t t2_driver = {
173         "t2",
174         t2_methods,
175         sizeof(struct t2_softc),
176 };
177
178
179 #define T2_SGMAP_BASE           (8*1024*1024)
180 #define T2_SGMAP_SIZE           (8*1024*1024)
181
182 static void
183 t2_sgmap_invalidate(void)
184 {
185         u_int64_t val;
186
187         alpha_mb();
188         val = REGVAL64(T2_IOCSR);
189         val |= T2_IOCSRL_ITLB;
190         REGVAL64(T2_IOCSR) = val;
191         alpha_mb();
192         alpha_mb();
193         val = REGVAL64(T2_IOCSR);
194         val &= ~T2_IOCSRL_ITLB;
195         REGVAL64(T2_IOCSR) = val;
196         alpha_mb();
197         alpha_mb();
198 }
199
200 static void
201 t2_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
202 {
203         u_int64_t *sgtable = arg;
204         int index = alpha_btop(ba - T2_SGMAP_BASE);
205
206         if (pa) {
207                 if (pa > (1L<<32))
208                         panic("t2_sgmap_map: can't map address 0x%lx", pa);
209                 sgtable[index] = ((pa >> 13) << 1) | 1;
210         } else {
211                 sgtable[index] = 0;
212         }
213         alpha_mb();
214         t2_sgmap_invalidate();
215 }
216
217
218 static void
219 t2_init_sgmap(int h)
220 {
221         void *sgtable;
222
223         /*
224          * First setup Window 2 to map 8Mb to 16Mb with an
225          * sgmap. Allocate the map aligned to a 32 boundary.
226          *
227          *  bits 31..20 of WBASE represent the pci start address
228          *  (in units of 1Mb), and bits 11..0 represent the pci
229          *  end address
230          */
231         t2_csr[h]->wbase2 = T2_WSIZE_8M|T2_WINDOW_ENABLE|T2_WINDOW_SG
232                              | ((T2_SGMAP_BASE >> 20) << 20)
233                              | ((T2_SGMAP_BASE + T2_SGMAP_SIZE) >> 20);
234         t2_csr[h]->wmask2 = T2_WMASK_8M;
235         alpha_mb();
236
237         sgtable = contigmalloc(8192, M_DEVBUF, M_NOWAIT,
238                                0, (1L<<34),
239                                32*1024, (1L<<34));
240         if (!sgtable)
241                 panic("t2_init_sgmap: can't allocate page table");
242
243         t2_csr[h]->tbase2 =
244             (pmap_kextract((vm_offset_t) sgtable) >> T2_TBASE_SHIFT);
245
246         chipset.sgmap = sgmap_map_create(T2_SGMAP_BASE,
247                                          T2_SGMAP_BASE + T2_SGMAP_SIZE,
248                                          t2_sgmap_map, sgtable);
249 }
250
251 static void
252 t2_csr_init(int h)
253 {
254         /* 
255          * initialize the DMA windows
256          */
257         t2_csr[h]->wbase1 = T2_WSIZE_1G|T2_WINDOW_ENABLE|T2_WINDOW_DIRECT|0x7ff;
258         t2_csr[h]->wmask1 = T2_WMASK_1G;
259         t2_csr[h]->tbase1 = 0x0;
260
261         t2_csr[h]->wbase2 = 0x0;
262
263         /* 
264          *  enable the PCI "Hole" for ISA devices which use memory in
265          *  the 512k - 1MB range
266          */
267         t2_csr[h]->hbase = 1 << 13;
268         t2_init_sgmap(0);
269
270         /* initialize the HAEs */
271         t2_csr[h]->hae0_1 = 0x0;
272         alpha_mb();
273         t2_csr[h]->hae0_2 = 0x0;
274         alpha_mb();
275         t2_csr[h]->hae0_3 = 0x0;
276         alpha_mb();
277
278 }
279
280 /*
281  * Perform basic chipset init/fixup.  Called by various early
282  * consumers to ensure that the system will work before the 
283  * bus methods are invoked.
284  *
285  */
286
287 void
288 t2_init()
289 {
290         static int initted = 0;
291         static struct swiz_space io_space, mem_space;
292
293         if (initted) return;
294         initted = 1;
295
296         swiz_init_space(&io_space, KV(T2_PCI_SIO));
297         swiz_init_space_hae(&mem_space, KV(T2_PCI_SPARSE),
298                             t2_set_hae_mem, 0);
299
300         busspace_isa_io = (struct alpha_busspace *) &io_space;
301         busspace_isa_mem = (struct alpha_busspace *) &mem_space;
302
303         chipset = t2_chipset;
304
305 }
306
307 static int
308 t2_probe(device_t dev)
309 {
310         int h, t2_num_hoses = 1;
311         device_t child;
312
313         if (t2_0)
314                 return ENXIO;
315
316         t2_0 = dev;
317         device_set_desc(dev, "T2 Core Logic chipset"); 
318         t2_csr[0] = (t2_csr_t *)
319             ALPHA_PHYS_TO_K0SEG(sable_lynx_base + PCI0_BASE);
320         t2_csr[1] = (t2_csr_t *)
321             ALPHA_PHYS_TO_K0SEG(sable_lynx_base + PCI1_BASE);
322
323         /* Look at the rev of the chip.  If the high bit is set in the
324          * rev field then we have either a T3 or a T4 chip, so use the
325          * new interrupt structure.  If it is clear, then we have a T2
326          * so use the old way */
327
328         platform.mcheck_handler = t2_machine_check;
329
330         if (((t2_csr[0]->iocsr) >> 35) & 1)
331                 pci_int_type[0] = 1;
332          else 
333                 pci_int_type[0] = 0;
334
335         device_printf(dev, "using interrupt type %d on pci bus 0\n", 
336             pci_int_type[0]);
337
338         if (!badaddr((void *)&t2_csr[1]->tlbbr, sizeof(long))) {
339                 pci_int_type[1] = 1; /* PCI1 always uses the new scheme */
340                 /* Clear any errors that the BADADDR probe may have caused */
341                 t2_csr[1]->cerr1 |= t2_csr[1]->cerr1;
342                 t2_csr[1]->pcierr1 |= t2_csr[1]->pcierr1;
343                 device_printf(dev, "found EXT_IO!!!!!\n");
344                 /* t2_num_hoses = 2; XXX not ready for this yet */
345         }
346
347         for (h = 0; h < t2_num_hoses; h++)
348                 t2_csr_init(h);
349
350         
351         child = device_add_child(dev, "pcib", 0);
352         device_set_ivars(child, 0);
353
354         return 0;
355 }
356
357 static int
358 t2_attach(device_t dev)
359 {
360         t2_init();
361
362         set_iointr(t2_dispatch_intr);
363         platform.isa_setup_intr = t2_setup_intr;
364         platform.isa_teardown_intr = t2_teardown_intr;
365
366         snprintf(chipset_type, sizeof(chipset_type), "t2");
367
368         bus_generic_attach(dev);
369
370         return 0;
371 }
372
373
374 /*
375  * magical mystery table partly obtained from Linux
376  * at least some of their values for PCI masks
377  * were incorrect, and I've filled in my own extrapolations
378  * XXX this needs more testers 
379  */
380
381 unsigned long t2_shadow_mask = -1L;
382 static const char irq_to_mask[40] = {
383         -1,  6, -1,  8, 15, 12,  7,  9,         /* ISA 0-7  */
384         -1, 16, 17, 18,  3, -1, 21, 22,         /* ISA 8-15 */
385         -1, -1, -1, -1, -1, -1, -1, -1,         /* ?? EISA XXX */
386         -1, -1, -1, -1, -1, -1, -1, -1,         /* ?? EISA XXX */
387          0,  1,  2,  3,  4,  5,  6,  7          /* PCI 0-7 XXX */
388 };
389
390
391 static void
392 t2_8259_disable_mask(int mask)
393 {
394         t2_shadow_mask |= (1UL << mask);
395
396         if (mask <= 7)
397                 outb(SLAVE0_ICU, t2_shadow_mask);
398         else if (mask <= 15)
399                 outb(SLAVE1_ICU, t2_shadow_mask >> 8);
400         else 
401                 outb(SLAVE2_ICU, t2_shadow_mask >> 16);
402 }
403
404 static void
405 t2_8259_enable_mask(int mask)
406 {
407         t2_shadow_mask &= ~(1UL << mask);
408
409         if (mask <= 7)
410                 outb(SLAVE0_ICU, t2_shadow_mask);
411         else if (mask <= 15)
412                 outb(SLAVE1_ICU, t2_shadow_mask >> 8);
413         else 
414                 outb(SLAVE2_ICU, t2_shadow_mask >> 16);
415 }
416
417
418 static void 
419 t2_eoi( int vector)
420 {
421         int irq, hose;
422
423         hose = (vector >= 0xC00);
424         irq = (vector - 0x800) >> 4;
425
426         if (pci_int_type[hose]) {
427
428                 /* New interrupt scheme.  Both PCI0 and PCI1 can use
429                  * the same handler.  Dispatching interrupts with the
430                  * IC IC chip is easy.  We simply write the vector
431                  * address  register (var) on the T3/T4 (offset
432                  * 0x480) with the IRQ  level (0 - 63) of what came in.  */
433                 t2_csr[hose]->var = (u_long) irq;
434                 alpha_mb();
435                 alpha_mb();
436         } else {
437                 switch (irq) {
438                 case 0 ... 7:
439                         outb(SLAVE0_ICU-1, (0xe0 | (irq)));
440                         outb(MASTER_ICU-1, (0xe0 | 1));
441                         break;
442                 case 8 ... 15:
443                         outb(SLAVE1_ICU-1, (0xe0 | (irq - 8)));
444                         outb(MASTER_ICU-1, (0xe0 | 3));
445                         break;
446                 case 16 ... 24:
447                         outb(SLAVE2_ICU-1, (0xe0 | (irq - 16)));
448                         outb(MASTER_ICU-1, (0xe0 | 4));
449                         break;
450                 }       
451         }
452 }
453
454 static void
455 t2_enable_vec(int vector)
456 {
457         int irq, hose;
458         u_long IC_mask, scratch;
459
460         hose = (vector >= 0xC00);
461         irq = (vector - 0x800) >> 4;
462
463         if (pci_int_type[hose]) {
464
465                 /* Write the air register on the T3/T4 with the
466                  * address of the IC IC masks register (offset 0x40) */
467                 t2_csr[hose]->air = 0x40;
468                 alpha_mb();
469                 scratch = t2_csr[hose]->air;    
470                 alpha_mb();
471                 IC_mask = t2_csr[hose]->dir;
472                 IC_mask &= ~(1L << ( (u_long) irq));
473                 t2_csr[hose]->dir = IC_mask;    
474                 alpha_mb();
475                 alpha_mb();
476                 /*
477                  * EOI the interrupt we just enabled.
478                  */
479                 t2_eoi(vector);
480         } else {
481                 /* Old style 8259 (Gack!!!) interrupts */
482                 t2_8259_enable_mask(irq);
483         }
484 }
485
486 static void
487 t2_disable_vec(int vector)
488 {
489         int hose, irq;
490         u_long scratch, IC_mask;
491
492         hose = (vector >= 0xC00);
493         irq =  (vector - 0x800) >> 4;
494
495         if (pci_int_type[hose]) {
496
497                 /* Write the air register on the T3/T4 wioth the
498                  * address of the IC IC masks register (offset 0x40) */
499
500                 t2_csr[hose]->air = 0x40;
501                 alpha_mb();
502                 scratch = t2_csr[hose]->air;    
503                 alpha_mb();
504                 /*
505                  * Read the dir register to fetch the mask data, 'or' in the
506                  * new disable bit, and write the data back.
507                  */
508                 IC_mask = t2_csr[hose]->dir;
509                 IC_mask |= (1L << ( (u_long) irq));
510                 /* Set the disable bit */
511                 t2_csr[hose]->dir = IC_mask;    
512                 alpha_mb();
513                 alpha_mb();
514         } else {
515                 /* Old style 8259 (Gack!!!) interrupts */
516                 t2_8259_disable_mask(irq);
517         }
518 }
519
520
521 static int
522 t2_setup_intr(device_t dev, device_t child,
523                struct resource *irq, int flags,
524                void *intr, void *arg, void **cookiep)
525 {
526         int error, vector, stdio_irq;
527         const char *name;
528         device_t bus, parent;
529
530         name = device_get_nameunit(dev);
531         stdio_irq = irq->r_start;
532         if (strncmp(name, "eisa", 4) == 0) {
533                 if ((stdio_irq != 6 ) && (stdio_irq != 3 )) {
534                         stdio_irq = 
535                             T2_EISA_IRQ_TO_STDIO_IRQ(stdio_irq);
536                 }
537         } else if ((strncmp(name, "isa", 3)) == 0) {
538                 stdio_irq = irq_to_mask[stdio_irq];
539         }
540
541         parent = dev;
542         do {
543                 bus = parent;
544                 parent = device_get_parent(bus);
545         } while (parent && strncmp("t2", device_get_nameunit(parent), 2));
546
547         if (parent && (device_get_unit(bus) != 0))
548                 vector = STDIO_PCI1_IRQ_TO_SCB_VECTOR(stdio_irq);
549         else    
550                 vector = STDIO_PCI0_IRQ_TO_SCB_VECTOR(stdio_irq);
551
552         error = rman_activate_resource(irq);
553         if (error)
554                 return error;
555
556         error = alpha_setup_intr(device_get_nameunit(child ? child : dev),
557                         vector, intr, arg, flags, cookiep,
558                         &intrcnt[irq->r_start], t2_disable_vec, t2_enable_vec);
559             
560         if (error)
561                 return error;
562
563         /* Enable interrupt */
564         t2_enable_vec(vector);
565         
566         if (bootverbose != 0) 
567                 device_printf(child, 
568                     "interrupting at T2 irq %d (stdio irq %d)\n",
569                       (int) irq->r_start, stdio_irq);
570         return 0;
571 }
572
573 static int
574 t2_teardown_intr(device_t dev, device_t child,
575                struct resource *irq, void *cookie)
576 {
577         int mask;
578         
579         mask = irq_to_mask[irq->r_start];
580
581         /* Disable interrupt */
582         
583         /* 
584          *  XXX this is totally broken! 
585          *  we don't have enough info to figure out where the interrupt 
586          *  came from if hose != 0 and pci_int_type[hose] != 0
587          *  We should probably carry around the vector someplace --
588          *  that would be enough to figure out the hose and the stdio irq
589          */
590
591         t2_shadow_mask |= (1UL << mask);
592
593         if (mask <= 7)
594                 outb(SLAVE0_ICU, t2_shadow_mask);
595         else if (mask <= 15)
596                 outb(SLAVE1_ICU, t2_shadow_mask >> 8);
597         else 
598                 outb(SLAVE2_ICU, t2_shadow_mask >> 16);
599
600         alpha_teardown_intr(cookie);
601         return rman_deactivate_resource(irq);
602 }
603
604
605
606 static void
607 t2_dispatch_intr(void *frame, unsigned long vector)
608 {
609         alpha_dispatch_intr(frame, vector);
610         t2_eoi(vector);
611 }
612
613 static void
614 t2_machine_check(unsigned long mces, struct trapframe *framep, 
615     unsigned long vector, unsigned long param)
616 {
617         int expected;
618
619         expected = mc_expected;
620         machine_check(mces, framep, vector, param);
621         /* for some reason the alpha_pal_wrmces() doesn't clear all
622            pending machine checks & we may take another */
623         mc_expected = expected;
624 }
625
626 DRIVER_MODULE(t2, root, t2_driver, t2_devclass, 0, 0);