For ports with __HAVE_LEGACY_INTRCNT, turn intrcnt[] and derived variables into u_int, to match with kern/subr_evcnt.c.diff -r1.21 -r1.22 src/sys/arch/atari/include/intr.h
(rin)
--- src/sys/arch/atari/include/intr.h 2009/07/08 12:23:10 1.21
+++ src/sys/arch/atari/include/intr.h 2021/04/02 12:11:41 1.22
@@ -1,136 +1,136 @@ | @@ -1,136 +1,136 @@ | |||
1 | /* $NetBSD: intr.h,v 1.21 2009/07/08 12:23:10 tsutsui Exp $ */ | 1 | /* $NetBSD: intr.h,v 1.22 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996, 1997, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996, 1997, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Leo Weppelman. | 8 | * by Leo Weppelman. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #ifndef _ATARI_INTR_H_ | 32 | #ifndef _ATARI_INTR_H_ | |
33 | #define _ATARI_INTR_H_ | 33 | #define _ATARI_INTR_H_ | |
34 | 34 | |||
35 | #define IPL_NONE 0 /* disable no interrupts */ | 35 | #define IPL_NONE 0 /* disable no interrupts */ | |
36 | #define IPL_SOFTCLOCK 1 | 36 | #define IPL_SOFTCLOCK 1 | |
37 | #define IPL_SOFTBIO 2 | 37 | #define IPL_SOFTBIO 2 | |
38 | #define IPL_SOFTNET 3 | 38 | #define IPL_SOFTNET 3 | |
39 | #define IPL_SOFTSERIAL 4 | 39 | #define IPL_SOFTSERIAL 4 | |
40 | #define IPL_VM 5 | 40 | #define IPL_VM 5 | |
41 | #define IPL_SCHED 6 | 41 | #define IPL_SCHED 6 | |
42 | #define IPL_HIGH 7 | 42 | #define IPL_HIGH 7 | |
43 | #define NIPL 8 | 43 | #define NIPL 8 | |
44 | 44 | |||
45 | #define IST_UNUSABLE -1 /* interrupt cannot be used */ | 45 | #define IST_UNUSABLE -1 /* interrupt cannot be used */ | |
46 | #define IST_NONE 0 /* none (dummy) */ | 46 | #define IST_NONE 0 /* none (dummy) */ | |
47 | #define IST_PULSE 1 /* pulsed */ | 47 | #define IST_PULSE 1 /* pulsed */ | |
48 | #define IST_EDGE 2 /* edge-triggered */ | 48 | #define IST_EDGE 2 /* edge-triggered */ | |
49 | #define IST_LEVEL 3 /* level-triggered */ | 49 | #define IST_LEVEL 3 /* level-triggered */ | |
50 | 50 | |||
51 | /* | 51 | /* | |
52 | * spl functions; all but spl0 are done in-line | 52 | * spl functions; all but spl0 are done in-line | |
53 | */ | 53 | */ | |
54 | #include <machine/psl.h> | 54 | #include <machine/psl.h> | |
55 | 55 | |||
56 | /* spl0 requires checking for software interrupts */ | 56 | /* spl0 requires checking for software interrupts */ | |
57 | 57 | |||
58 | #define splsoftclock() splraise1() | 58 | #define splsoftclock() splraise1() | |
59 | #define splsoftbio() splraise1() | 59 | #define splsoftbio() splraise1() | |
60 | #define splsoftnet() splraise1() | 60 | #define splsoftnet() splraise1() | |
61 | #define splsoftserial() splraise1() | 61 | #define splsoftserial() splraise1() | |
62 | #define splvm() splraise4() | 62 | #define splvm() splraise4() | |
63 | #define splsched() splraise6() | 63 | #define splsched() splraise6() | |
64 | #define splhigh() spl7() | 64 | #define splhigh() spl7() | |
65 | #define splx(s) ((s) & PSL_IPL ? _spl(s) : spl0()) | 65 | #define splx(s) ((s) & PSL_IPL ? _spl(s) : spl0()) | |
66 | 66 | |||
67 | #ifdef _KERNEL | 67 | #ifdef _KERNEL | |
68 | int spl0(void); | 68 | int spl0(void); | |
69 | 69 | |||
70 | extern const uint16_t ipl2psl_table[NIPL]; | 70 | extern const uint16_t ipl2psl_table[NIPL]; | |
71 | extern int idepth; | 71 | extern int idepth; | |
72 | 72 | |||
73 | typedef int ipl_t; | 73 | typedef int ipl_t; | |
74 | typedef struct { | 74 | typedef struct { | |
75 | uint16_t _psl; | 75 | uint16_t _psl; | |
76 | } ipl_cookie_t; | 76 | } ipl_cookie_t; | |
77 | 77 | |||
78 | static inline ipl_cookie_t | 78 | static inline ipl_cookie_t | |
79 | makeiplcookie(ipl_t ipl) | 79 | makeiplcookie(ipl_t ipl) | |
80 | { | 80 | { | |
81 | 81 | |||
82 | return (ipl_cookie_t){._psl = ipl2psl_table[ipl]}; | 82 | return (ipl_cookie_t){._psl = ipl2psl_table[ipl]}; | |
83 | } | 83 | } | |
84 | 84 | |||
85 | static inline int | 85 | static inline int | |
86 | splraiseipl(ipl_cookie_t icookie) | 86 | splraiseipl(ipl_cookie_t icookie) | |
87 | { | 87 | { | |
88 | 88 | |||
89 | return _splraise(icookie._psl); | 89 | return _splraise(icookie._psl); | |
90 | } | 90 | } | |
91 | 91 | |||
92 | #include <sys/queue.h> | 92 | #include <sys/queue.h> | |
93 | #include <machine/cpu.h> /* XXX: for clockframe */ | 93 | #include <machine/cpu.h> /* XXX: for clockframe */ | |
94 | 94 | |||
95 | struct clockframe; | 95 | struct clockframe; | |
96 | 96 | |||
97 | #define AUTO_VEC 0x0001 /* We're dealing with an auto-vector */ | 97 | #define AUTO_VEC 0x0001 /* We're dealing with an auto-vector */ | |
98 | #define USER_VEC 0x0002 /* We're dealing with an user-vector */ | 98 | #define USER_VEC 0x0002 /* We're dealing with an user-vector */ | |
99 | 99 | |||
100 | #define FAST_VEC 0x0010 /* Fast, stash right into vector-table */ | 100 | #define FAST_VEC 0x0010 /* Fast, stash right into vector-table */ | |
101 | #define ARG_CLOCKFRAME 0x0020 /* Supply clockframe as an argument */ | 101 | #define ARG_CLOCKFRAME 0x0020 /* Supply clockframe as an argument */ | |
102 | 102 | |||
103 | /* | 103 | /* | |
104 | * Interrupt handler chains. intr_establish() inserts a handler into | 104 | * Interrupt handler chains. intr_establish() inserts a handler into | |
105 | * the list. The handler is called with its (single) argument or with a | 105 | * the list. The handler is called with its (single) argument or with a | |
106 | * 'standard' clockframe. This depends on 'ih_type'. | 106 | * 'standard' clockframe. This depends on 'ih_type'. | |
107 | */ | 107 | */ | |
108 | typedef int (*hw_ifun_t)(void *, int); | 108 | typedef int (*hw_ifun_t)(void *, int); | |
109 | 109 | |||
110 | struct intrhand { | 110 | struct intrhand { | |
111 | LIST_ENTRY(intrhand) ih_link; | 111 | LIST_ENTRY(intrhand) ih_link; | |
112 | hw_ifun_t ih_fun; | 112 | hw_ifun_t ih_fun; | |
113 | void *ih_arg; | 113 | void *ih_arg; | |
114 | int ih_type; | 114 | int ih_type; | |
115 | int ih_pri; | 115 | int ih_pri; | |
116 | int ih_vector; | 116 | int ih_vector; | |
117 | u_long *ih_intrcnt; | 117 | u_int *ih_intrcnt; | |
118 | }; | 118 | }; | |
119 | 119 | |||
120 | void intr_init(void); | 120 | void intr_init(void); | |
121 | struct intrhand *intr_establish(int, int, int, hw_ifun_t, void *); | 121 | struct intrhand *intr_establish(int, int, int, hw_ifun_t, void *); | |
122 | int intr_disestablish(struct intrhand *); | 122 | int intr_disestablish(struct intrhand *); | |
123 | void intr_dispatch(struct clockframe); | 123 | void intr_dispatch(struct clockframe); | |
124 | void intr_glue(void); | 124 | void intr_glue(void); | |
125 | 125 | |||
126 | /* | 126 | /* | |
127 | * Exported by intrcnt.h | 127 | * Exported by intrcnt.h | |
128 | */ | 128 | */ | |
129 | extern u_long autovects[]; | 129 | extern u_long autovects[]; | |
130 | extern u_long intrcnt_auto[]; | 130 | extern u_int intrcnt_auto[]; | |
131 | extern u_long uservects[]; | 131 | extern u_long uservects[]; | |
132 | extern u_long intrcnt_user[]; | 132 | extern u_int intrcnt_user[]; | |
133 | 133 | |||
134 | #endif /* _KERNEL */ | 134 | #endif /* _KERNEL */ | |
135 | 135 | |||
136 | #endif /* _ATARI_INTR_H_ */ | 136 | #endif /* _ATARI_INTR_H_ */ |
--- src/sys/arch/cesfic/cesfic/isr.c 2020/11/18 03:40:50 1.18
+++ src/sys/arch/cesfic/cesfic/isr.c 2021/04/02 12:11:41 1.19
@@ -1,218 +1,218 @@ | @@ -1,218 +1,218 @@ | |||
1 | /* $NetBSD: isr.c,v 1.18 2020/11/18 03:40:50 thorpej Exp $ */ | 1 | /* $NetBSD: isr.c,v 1.19 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | 8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Link and dispatch interrupts. | 33 | * Link and dispatch interrupts. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.18 2020/11/18 03:40:50 thorpej Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.19 2021/04/02 12:11:41 rin Exp $"); | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/systm.h> | 40 | #include <sys/systm.h> | |
41 | #include <sys/queue.h> | 41 | #include <sys/queue.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | #include <sys/vmmeter.h> | 43 | #include <sys/vmmeter.h> | |
44 | #include <sys/cpu.h> | 44 | #include <sys/cpu.h> | |
45 | 45 | |||
46 | #include <uvm/uvm_extern.h> | 46 | #include <uvm/uvm_extern.h> | |
47 | 47 | |||
48 | #include <cesfic/cesfic/isr.h> | 48 | #include <cesfic/cesfic/isr.h> | |
49 | 49 | |||
50 | typedef LIST_HEAD(, isr) isr_list_t; | 50 | typedef LIST_HEAD(, isr) isr_list_t; | |
51 | isr_list_t isr_list[NISR]; | 51 | isr_list_t isr_list[NISR]; | |
52 | 52 | |||
53 | extern int intrcnt[]; /* from locore.s */ | 53 | extern u_int intrcnt[]; /* from locore.s */ | |
54 | 54 | |||
55 | void | 55 | void | |
56 | isrinit(void) | 56 | isrinit(void) | |
57 | { | 57 | { | |
58 | int i; | 58 | int i; | |
59 | 59 | |||
60 | /* Initialize the ISR lists. */ | 60 | /* Initialize the ISR lists. */ | |
61 | for (i = 0; i < NISR; ++i) { | 61 | for (i = 0; i < NISR; ++i) { | |
62 | LIST_INIT(&isr_list[i]); | 62 | LIST_INIT(&isr_list[i]); | |
63 | } | 63 | } | |
64 | } | 64 | } | |
65 | 65 | |||
66 | /* | 66 | /* | |
67 | * Establish an interrupt handler. | 67 | * Establish an interrupt handler. | |
68 | * Called by driver attach functions. | 68 | * Called by driver attach functions. | |
69 | */ | 69 | */ | |
70 | void * | 70 | void * | |
71 | isrlink(int (*func)(void *), void *arg, int ipl, int priority) | 71 | isrlink(int (*func)(void *), void *arg, int ipl, int priority) | |
72 | { | 72 | { | |
73 | struct isr *newisr, *curisr; | 73 | struct isr *newisr, *curisr; | |
74 | isr_list_t *list; | 74 | isr_list_t *list; | |
75 | 75 | |||
76 | if ((ipl < 0) || (ipl >= NISR)) | 76 | if ((ipl < 0) || (ipl >= NISR)) | |
77 | panic("isrlink: bad ipl %d", ipl); | 77 | panic("isrlink: bad ipl %d", ipl); | |
78 | 78 | |||
79 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | 79 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | |
80 | newisr->isr_func = func; | 80 | newisr->isr_func = func; | |
81 | newisr->isr_arg = arg; | 81 | newisr->isr_arg = arg; | |
82 | newisr->isr_ipl = ipl; | 82 | newisr->isr_ipl = ipl; | |
83 | newisr->isr_priority = priority; | 83 | newisr->isr_priority = priority; | |
84 | 84 | |||
85 | /* | 85 | /* | |
86 | * Some devices are particularly sensitive to interrupt | 86 | * Some devices are particularly sensitive to interrupt | |
87 | * handling latency. The DCA, for example, can lose many | 87 | * handling latency. The DCA, for example, can lose many | |
88 | * characters if its interrupt isn't handled with reasonable | 88 | * characters if its interrupt isn't handled with reasonable | |
89 | * speed. | 89 | * speed. | |
90 | * | 90 | * | |
91 | * To work around this problem, each device can give itself a | 91 | * To work around this problem, each device can give itself a | |
92 | * "priority". An unbuffered DCA would give itself a higher | 92 | * "priority". An unbuffered DCA would give itself a higher | |
93 | * priority than a SCSI device, for example. | 93 | * priority than a SCSI device, for example. | |
94 | * | 94 | * | |
95 | * This is necessary because of the flat spl scheme employed by | 95 | * This is necessary because of the flat spl scheme employed by | |
96 | * the hp300. Each device can be set from ipl 3 to ipl 5, which | 96 | * the hp300. Each device can be set from ipl 3 to ipl 5, which | |
97 | * in turn means that splbio, splnet, and spltty must all be at | 97 | * in turn means that splbio, splnet, and spltty must all be at | |
98 | * spl5. | 98 | * spl5. | |
99 | * | 99 | * | |
100 | * Don't blame me...I just work here. | 100 | * Don't blame me...I just work here. | |
101 | */ | 101 | */ | |
102 | 102 | |||
103 | /* | 103 | /* | |
104 | * Get the appropriate ISR list. If the list is empty, no | 104 | * Get the appropriate ISR list. If the list is empty, no | |
105 | * additional work is necessary; we simply insert ourselves | 105 | * additional work is necessary; we simply insert ourselves | |
106 | * at the head of the list. | 106 | * at the head of the list. | |
107 | */ | 107 | */ | |
108 | list = &isr_list[ipl]; | 108 | list = &isr_list[ipl]; | |
109 | if (list->lh_first == NULL) { | 109 | if (list->lh_first == NULL) { | |
110 | LIST_INSERT_HEAD(list, newisr, isr_link); | 110 | LIST_INSERT_HEAD(list, newisr, isr_link); | |
111 | goto done; | 111 | goto done; | |
112 | } | 112 | } | |
113 | 113 | |||
114 | /* | 114 | /* | |
115 | * A little extra work is required. We traverse the list | 115 | * A little extra work is required. We traverse the list | |
116 | * and place ourselves after any ISRs with our current (or | 116 | * and place ourselves after any ISRs with our current (or | |
117 | * higher) priority. | 117 | * higher) priority. | |
118 | */ | 118 | */ | |
119 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | 119 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | |
120 | curisr = curisr->isr_link.le_next) { | 120 | curisr = curisr->isr_link.le_next) { | |
121 | if (newisr->isr_priority > curisr->isr_priority) { | 121 | if (newisr->isr_priority > curisr->isr_priority) { | |
122 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | 122 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | |
123 | goto done; | 123 | goto done; | |
124 | } | 124 | } | |
125 | } | 125 | } | |
126 | 126 | |||
127 | /* | 127 | /* | |
128 | * We're the least important entry, it seems. We just go | 128 | * We're the least important entry, it seems. We just go | |
129 | * on the end. | 129 | * on the end. | |
130 | */ | 130 | */ | |
131 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | 131 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | |
132 | 132 | |||
133 | done: | 133 | done: | |
134 | return (newisr); | 134 | return (newisr); | |
135 | } | 135 | } | |
136 | 136 | |||
137 | #if 0 | 137 | #if 0 | |
138 | /* | 138 | /* | |
139 | * Disestablish an interrupt handler. | 139 | * Disestablish an interrupt handler. | |
140 | */ | 140 | */ | |
141 | void | 141 | void | |
142 | isrunlink(void *arg) | 142 | isrunlink(void *arg) | |
143 | { | 143 | { | |
144 | struct isr *isr = arg; | 144 | struct isr *isr = arg; | |
145 | 145 | |||
146 | LIST_REMOVE(isr, isr_link); | 146 | LIST_REMOVE(isr, isr_link); | |
147 | kmem_free(isr, sizeof(*isr)); | 147 | kmem_free(isr, sizeof(*isr)); | |
148 | } | 148 | } | |
149 | #endif | 149 | #endif | |
150 | 150 | |||
151 | /* | 151 | /* | |
152 | * This is the dispatcher called by the low-level | 152 | * This is the dispatcher called by the low-level | |
153 | * assembly language interrupt routine. | 153 | * assembly language interrupt routine. | |
154 | */ | 154 | */ | |
155 | static unsigned int idepth; | 155 | static unsigned int idepth; | |
156 | 156 | |||
157 | void | 157 | void | |
158 | isrdispatch(int evec) | 158 | isrdispatch(int evec) | |
159 | /* evec: format | vector offset */ | 159 | /* evec: format | vector offset */ | |
160 | { | 160 | { | |
161 | struct isr *isr; | 161 | struct isr *isr; | |
162 | isr_list_t *list; | 162 | isr_list_t *list; | |
163 | int handled, ipl, vec; | 163 | int handled, ipl, vec; | |
164 | static int straycount, unexpected; | 164 | static int straycount, unexpected; | |
165 | 165 | |||
166 | vec = (evec & 0xfff) >> 2; | 166 | vec = (evec & 0xfff) >> 2; | |
167 | if ((vec < ISRLOC) || (vec >= (ISRLOC + NISR))) | 167 | if ((vec < ISRLOC) || (vec >= (ISRLOC + NISR))) | |
168 | panic("isrdispatch: bad vec 0x%x", vec); | 168 | panic("isrdispatch: bad vec 0x%x", vec); | |
169 | ipl = vec - ISRLOC; | 169 | ipl = vec - ISRLOC; | |
170 | 170 | |||
171 | intrcnt[ipl]++; | 171 | intrcnt[ipl]++; | |
172 | curcpu()->ci_data.cpu_nintr++; | 172 | curcpu()->ci_data.cpu_nintr++; | |
173 | 173 | |||
174 | if (ipl >= IPL_VM) | 174 | if (ipl >= IPL_VM) | |
175 | idepth++; | 175 | idepth++; | |
176 | 176 | |||
177 | list = &isr_list[ipl]; | 177 | list = &isr_list[ipl]; | |
178 | if (list->lh_first == NULL) { | 178 | if (list->lh_first == NULL) { | |
179 | printf("intrhand: ipl %d unexpected\n", ipl); | 179 | printf("intrhand: ipl %d unexpected\n", ipl); | |
180 | if (++unexpected > 10) | 180 | if (++unexpected > 10) | |
181 | panic("isrdispatch: too many unexpected interrupts"); | 181 | panic("isrdispatch: too many unexpected interrupts"); | |
182 | goto out; | 182 | goto out; | |
183 | } | 183 | } | |
184 | 184 | |||
185 | handled = 0; | 185 | handled = 0; | |
186 | /* Give all the handlers a chance. */ | 186 | /* Give all the handlers a chance. */ | |
187 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) | 187 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) | |
188 | handled |= (*isr->isr_func)(isr->isr_arg); | 188 | handled |= (*isr->isr_func)(isr->isr_arg); | |
189 | 189 | |||
190 | if (handled) | 190 | if (handled) | |
191 | straycount = 0; | 191 | straycount = 0; | |
192 | else if (++straycount > 50) | 192 | else if (++straycount > 50) | |
193 | panic("isrdispatch: too many stray interrupts"); | 193 | panic("isrdispatch: too many stray interrupts"); | |
194 | else | 194 | else | |
195 | printf("isrdispatch: stray level %d interrupt\n", ipl); | 195 | printf("isrdispatch: stray level %d interrupt\n", ipl); | |
196 | 196 | |||
197 | out: | 197 | out: | |
198 | if (ipl >= IPL_VM) | 198 | if (ipl >= IPL_VM) | |
199 | idepth--; | 199 | idepth--; | |
200 | } | 200 | } | |
201 | 201 | |||
202 | bool | 202 | bool | |
203 | cpu_intr_p(void) | 203 | cpu_intr_p(void) | |
204 | { | 204 | { | |
205 | 205 | |||
206 | return idepth != 0; | 206 | return idepth != 0; | |
207 | } | 207 | } | |
208 | 208 | |||
209 | const uint16_t ipl2psl_table[NIPL] = { | 209 | const uint16_t ipl2psl_table[NIPL] = { | |
210 | [IPL_NONE] = PSL_S|PSL_IPL0, | 210 | [IPL_NONE] = PSL_S|PSL_IPL0, | |
211 | [IPL_SOFTCLOCK] = PSL_S|PSL_IPL1, | 211 | [IPL_SOFTCLOCK] = PSL_S|PSL_IPL1, | |
212 | [IPL_SOFTBIO] = PSL_S|PSL_IPL1, | 212 | [IPL_SOFTBIO] = PSL_S|PSL_IPL1, | |
213 | [IPL_SOFTNET] = PSL_S|PSL_IPL1, | 213 | [IPL_SOFTNET] = PSL_S|PSL_IPL1, | |
214 | [IPL_SOFTSERIAL] = PSL_S|PSL_IPL1, | 214 | [IPL_SOFTSERIAL] = PSL_S|PSL_IPL1, | |
215 | [IPL_VM] = PSL_S|PSL_IPL4, | 215 | [IPL_VM] = PSL_S|PSL_IPL4, | |
216 | [IPL_SCHED] = PSL_S|PSL_IPL6, | 216 | [IPL_SCHED] = PSL_S|PSL_IPL6, | |
217 | [IPL_HIGH] = PSL_S|PSL_IPL7, | 217 | [IPL_HIGH] = PSL_S|PSL_IPL7, | |
218 | }; | 218 | }; |
--- src/sys/arch/luna68k/luna68k/isr.c 2020/12/19 21:38:30 1.24
+++ src/sys/arch/luna68k/luna68k/isr.c 2021/04/02 12:11:41 1.25
@@ -1,279 +1,279 @@ | @@ -1,279 +1,279 @@ | |||
1 | /* $NetBSD: isr.c,v 1.24 2020/12/19 21:38:30 thorpej Exp $ */ | 1 | /* $NetBSD: isr.c,v 1.25 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | 8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | 32 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | |
33 | 33 | |||
34 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.24 2020/12/19 21:38:30 thorpej Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.25 2021/04/02 12:11:41 rin Exp $"); | |
35 | 35 | |||
36 | /* | 36 | /* | |
37 | * Link and dispatch interrupts. | 37 | * Link and dispatch interrupts. | |
38 | */ | 38 | */ | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/systm.h> | 41 | #include <sys/systm.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | #include <sys/vmmeter.h> | 43 | #include <sys/vmmeter.h> | |
44 | #include <sys/cpu.h> | 44 | #include <sys/cpu.h> | |
45 | 45 | |||
46 | #include <uvm/uvm_extern.h> | 46 | #include <uvm/uvm_extern.h> | |
47 | 47 | |||
48 | #include <luna68k/luna68k/isr.h> | 48 | #include <luna68k/luna68k/isr.h> | |
49 | 49 | |||
50 | isr_autovec_list_t isr_autovec[NISRAUTOVEC]; | 50 | isr_autovec_list_t isr_autovec[NISRAUTOVEC]; | |
51 | struct isr_vectored isr_vectored[NISRVECTORED]; | 51 | struct isr_vectored isr_vectored[NISRVECTORED]; | |
52 | int idepth; | 52 | int idepth; | |
53 | 53 | |||
54 | extern int intrcnt[]; /* from locore.s */ | 54 | extern u_int intrcnt[]; /* from locore.s */ | |
55 | extern void (*vectab[])(void); | 55 | extern void (*vectab[])(void); | |
56 | extern void badtrap(void); | 56 | extern void badtrap(void); | |
57 | extern void intrhand_vectored(void); | 57 | extern void intrhand_vectored(void); | |
58 | 58 | |||
59 | extern int getsr(void); /* in locore.s */ | 59 | extern int getsr(void); /* in locore.s */ | |
60 | 60 | |||
61 | void | 61 | void | |
62 | isrinit(void) | 62 | isrinit(void) | |
63 | { | 63 | { | |
64 | int i; | 64 | int i; | |
65 | 65 | |||
66 | /* Initialize the autovector lists. */ | 66 | /* Initialize the autovector lists. */ | |
67 | for (i = 0; i < NISRAUTOVEC; ++i) { | 67 | for (i = 0; i < NISRAUTOVEC; ++i) { | |
68 | LIST_INIT(&isr_autovec[i]); | 68 | LIST_INIT(&isr_autovec[i]); | |
69 | } | 69 | } | |
70 | } | 70 | } | |
71 | 71 | |||
72 | /* | 72 | /* | |
73 | * Establish an autovectored interrupt handler. | 73 | * Establish an autovectored interrupt handler. | |
74 | * Called by driver attach functions. | 74 | * Called by driver attach functions. | |
75 | */ | 75 | */ | |
76 | void | 76 | void | |
77 | isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority) | 77 | isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority) | |
78 | { | 78 | { | |
79 | struct isr_autovec *newisr, *curisr; | 79 | struct isr_autovec *newisr, *curisr; | |
80 | isr_autovec_list_t *list; | 80 | isr_autovec_list_t *list; | |
81 | 81 | |||
82 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 82 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
83 | panic("isrlink_autovec: bad ipl %d", ipl); | 83 | panic("isrlink_autovec: bad ipl %d", ipl); | |
84 | 84 | |||
85 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | 85 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | |
86 | newisr->isr_func = func; | 86 | newisr->isr_func = func; | |
87 | newisr->isr_arg = arg; | 87 | newisr->isr_arg = arg; | |
88 | newisr->isr_ipl = ipl; | 88 | newisr->isr_ipl = ipl; | |
89 | newisr->isr_priority = priority; | 89 | newisr->isr_priority = priority; | |
90 | 90 | |||
91 | /* | 91 | /* | |
92 | * Some devices are particularly sensitive to interrupt | 92 | * Some devices are particularly sensitive to interrupt | |
93 | * handling latency. The SCC, for example, can lose many | 93 | * handling latency. The SCC, for example, can lose many | |
94 | * characters if its interrupt isn't handled with reasonable | 94 | * characters if its interrupt isn't handled with reasonable | |
95 | * speed. | 95 | * speed. | |
96 | * | 96 | * | |
97 | * To work around this problem, each device can give itself a | 97 | * To work around this problem, each device can give itself a | |
98 | * "priority". An unbuffered SCC would give itself a higher | 98 | * "priority". An unbuffered SCC would give itself a higher | |
99 | * priority than a SCSI device, for example. | 99 | * priority than a SCSI device, for example. | |
100 | * | 100 | * | |
101 | * This solution was originally developed for the hp300, which | 101 | * This solution was originally developed for the hp300, which | |
102 | * has a flat spl scheme (by necessity). Thankfully, the | 102 | * has a flat spl scheme (by necessity). Thankfully, the | |
103 | * MVME systems don't have this problem, though this may serve | 103 | * MVME systems don't have this problem, though this may serve | |
104 | * a useful purpose in any case. | 104 | * a useful purpose in any case. | |
105 | */ | 105 | */ | |
106 | 106 | |||
107 | /* | 107 | /* | |
108 | * Get the appropriate ISR list. If the list is empty, no | 108 | * Get the appropriate ISR list. If the list is empty, no | |
109 | * additional work is necessary; we simply insert ourselves | 109 | * additional work is necessary; we simply insert ourselves | |
110 | * at the head of the list. | 110 | * at the head of the list. | |
111 | */ | 111 | */ | |
112 | list = &isr_autovec[ipl]; | 112 | list = &isr_autovec[ipl]; | |
113 | if (list->lh_first == NULL) { | 113 | if (list->lh_first == NULL) { | |
114 | LIST_INSERT_HEAD(list, newisr, isr_link); | 114 | LIST_INSERT_HEAD(list, newisr, isr_link); | |
115 | return; | 115 | return; | |
116 | } | 116 | } | |
117 | 117 | |||
118 | /* | 118 | /* | |
119 | * A little extra work is required. We traverse the list | 119 | * A little extra work is required. We traverse the list | |
120 | * and place ourselves after any ISRs with our current (or | 120 | * and place ourselves after any ISRs with our current (or | |
121 | * higher) priority. | 121 | * higher) priority. | |
122 | */ | 122 | */ | |
123 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | 123 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | |
124 | curisr = curisr->isr_link.le_next) { | 124 | curisr = curisr->isr_link.le_next) { | |
125 | if (newisr->isr_priority > curisr->isr_priority) { | 125 | if (newisr->isr_priority > curisr->isr_priority) { | |
126 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | 126 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | |
127 | return; | 127 | return; | |
128 | } | 128 | } | |
129 | } | 129 | } | |
130 | 130 | |||
131 | /* | 131 | /* | |
132 | * We're the least important entry, it seems. We just go | 132 | * We're the least important entry, it seems. We just go | |
133 | * on the end. | 133 | * on the end. | |
134 | */ | 134 | */ | |
135 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | 135 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | |
136 | } | 136 | } | |
137 | 137 | |||
138 | /* | 138 | /* | |
139 | * Establish a vectored interrupt handler. | 139 | * Establish a vectored interrupt handler. | |
140 | * Called by bus interrupt establish functions. | 140 | * Called by bus interrupt establish functions. | |
141 | */ | 141 | */ | |
142 | void | 142 | void | |
143 | isrlink_vectored(int (*func)(void *), void *arg, int ipl, int vec) | 143 | isrlink_vectored(int (*func)(void *), void *arg, int ipl, int vec) | |
144 | { | 144 | { | |
145 | struct isr_vectored *isr; | 145 | struct isr_vectored *isr; | |
146 | 146 | |||
147 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 147 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
148 | panic("isrlink_vectored: bad ipl %d", ipl); | 148 | panic("isrlink_vectored: bad ipl %d", ipl); | |
149 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | 149 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | |
150 | panic("isrlink_vectored: bad vec 0x%x", vec); | 150 | panic("isrlink_vectored: bad vec 0x%x", vec); | |
151 | 151 | |||
152 | isr = &isr_vectored[vec - ISRVECTORED]; | 152 | isr = &isr_vectored[vec - ISRVECTORED]; | |
153 | 153 | |||
154 | if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) | 154 | if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) | |
155 | panic("isrlink_vectored: vec 0x%x not available", vec); | 155 | panic("isrlink_vectored: vec 0x%x not available", vec); | |
156 | 156 | |||
157 | /* Fill in the new entry. */ | 157 | /* Fill in the new entry. */ | |
158 | isr->isr_func = func; | 158 | isr->isr_func = func; | |
159 | isr->isr_arg = arg; | 159 | isr->isr_arg = arg; | |
160 | isr->isr_ipl = ipl; | 160 | isr->isr_ipl = ipl; | |
161 | 161 | |||
162 | /* Hook into the vector table. */ | 162 | /* Hook into the vector table. */ | |
163 | vectab[vec] = intrhand_vectored; | 163 | vectab[vec] = intrhand_vectored; | |
164 | } | 164 | } | |
165 | 165 | |||
166 | /* | 166 | /* | |
167 | * Unhook a vectored interrupt. | 167 | * Unhook a vectored interrupt. | |
168 | */ | 168 | */ | |
169 | void | 169 | void | |
170 | isrunlink_vectored(int vec) | 170 | isrunlink_vectored(int vec) | |
171 | { | 171 | { | |
172 | 172 | |||
173 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | 173 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | |
174 | panic("isrunlink_vectored: bad vec 0x%x", vec); | 174 | panic("isrunlink_vectored: bad vec 0x%x", vec); | |
175 | 175 | |||
176 | if (vectab[vec] != intrhand_vectored) | 176 | if (vectab[vec] != intrhand_vectored) | |
177 | panic("isrunlink_vectored: not vectored interrupt"); | 177 | panic("isrunlink_vectored: not vectored interrupt"); | |
178 | 178 | |||
179 | vectab[vec] = badtrap; | 179 | vectab[vec] = badtrap; | |
180 | memset(&isr_vectored[vec - ISRVECTORED], 0, sizeof(struct isr_vectored)); | 180 | memset(&isr_vectored[vec - ISRVECTORED], 0, sizeof(struct isr_vectored)); | |
181 | } | 181 | } | |
182 | 182 | |||
183 | /* | 183 | /* | |
184 | * This is the dispatcher called by the low-level | 184 | * This is the dispatcher called by the low-level | |
185 | * assembly language autovectored interrupt routine. | 185 | * assembly language autovectored interrupt routine. | |
186 | */ | 186 | */ | |
187 | void | 187 | void | |
188 | isrdispatch_autovec(int evec) | 188 | isrdispatch_autovec(int evec) | |
189 | /* evec: format | vector offset */ | 189 | /* evec: format | vector offset */ | |
190 | { | 190 | { | |
191 | struct isr_autovec *isr; | 191 | struct isr_autovec *isr; | |
192 | isr_autovec_list_t *list; | 192 | isr_autovec_list_t *list; | |
193 | int handled = 0, ipl, vec; | 193 | int handled = 0, ipl, vec; | |
194 | static int straycount, unexpected; | 194 | static int straycount, unexpected; | |
195 | 195 | |||
196 | idepth++; | 196 | idepth++; | |
197 | vec = (evec & 0xfff) >> 2; | 197 | vec = (evec & 0xfff) >> 2; | |
198 | if ((vec < ISRAUTOVEC) || (vec >= (ISRAUTOVEC + NISRAUTOVEC))) | 198 | if ((vec < ISRAUTOVEC) || (vec >= (ISRAUTOVEC + NISRAUTOVEC))) | |
199 | panic("isrdispatch_autovec: bad vec 0x%x", vec); | 199 | panic("isrdispatch_autovec: bad vec 0x%x", vec); | |
200 | ipl = vec - ISRAUTOVEC; | 200 | ipl = vec - ISRAUTOVEC; | |
201 | 201 | |||
202 | intrcnt[ipl]++; | 202 | intrcnt[ipl]++; | |
203 | curcpu()->ci_data.cpu_nintr++; | 203 | curcpu()->ci_data.cpu_nintr++; | |
204 | 204 | |||
205 | list = &isr_autovec[ipl]; | 205 | list = &isr_autovec[ipl]; | |
206 | if (list->lh_first == NULL) { | 206 | if (list->lh_first == NULL) { | |
207 | printf("isrdispatch_autovec: ipl %d unexpected\n", ipl); | 207 | printf("isrdispatch_autovec: ipl %d unexpected\n", ipl); | |
208 | if (++unexpected > 10) | 208 | if (++unexpected > 10) | |
209 | panic("too many unexpected interrupts"); | 209 | panic("too many unexpected interrupts"); | |
210 | idepth--; | 210 | idepth--; | |
211 | return; | 211 | return; | |
212 | } | 212 | } | |
213 | 213 | |||
214 | /* Give all the handlers a chance. */ | 214 | /* Give all the handlers a chance. */ | |
215 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) | 215 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) | |
216 | handled |= (*isr->isr_func)(isr->isr_arg); | 216 | handled |= (*isr->isr_func)(isr->isr_arg); | |
217 | 217 | |||
218 | if (handled) | 218 | if (handled) | |
219 | straycount = 0; | 219 | straycount = 0; | |
220 | else if (++straycount > 50) | 220 | else if (++straycount > 50) | |
221 | panic("isr_dispatch_autovec: too many stray interrupts"); | 221 | panic("isr_dispatch_autovec: too many stray interrupts"); | |
222 | else | 222 | else | |
223 | printf("isrdispatch_autovec: stray level %d interrupt\n", ipl); | 223 | printf("isrdispatch_autovec: stray level %d interrupt\n", ipl); | |
224 | idepth--; | 224 | idepth--; | |
225 | } | 225 | } | |
226 | 226 | |||
227 | /* | 227 | /* | |
228 | * This is the dispatcher called by the low-level | 228 | * This is the dispatcher called by the low-level | |
229 | * assembly language vectored interrupt routine. | 229 | * assembly language vectored interrupt routine. | |
230 | */ | 230 | */ | |
231 | void | 231 | void | |
232 | isrdispatch_vectored(int pc, int evec, void *frame) | 232 | isrdispatch_vectored(int pc, int evec, void *frame) | |
233 | { | 233 | { | |
234 | struct isr_vectored *isr; | 234 | struct isr_vectored *isr; | |
235 | int ipl, vec; | 235 | int ipl, vec; | |
236 | 236 | |||
237 | idepth++; | 237 | idepth++; | |
238 | vec = (evec & 0xfff) >> 2; | 238 | vec = (evec & 0xfff) >> 2; | |
239 | ipl = (getsr() >> 8) & 7; | 239 | ipl = (getsr() >> 8) & 7; | |
240 | 240 | |||
241 | intrcnt[ipl]++; | 241 | intrcnt[ipl]++; | |
242 | curcpu()->ci_data.cpu_nintr++; | 242 | curcpu()->ci_data.cpu_nintr++; | |
243 | 243 | |||
244 | if ((vec < ISRVECTORED) || (vec >= (ISRVECTORED + NISRVECTORED))) | 244 | if ((vec < ISRVECTORED) || (vec >= (ISRVECTORED + NISRVECTORED))) | |
245 | panic("isrdispatch_vectored: bad vec 0x%x", vec); | 245 | panic("isrdispatch_vectored: bad vec 0x%x", vec); | |
246 | isr = &isr_vectored[vec - ISRVECTORED]; | 246 | isr = &isr_vectored[vec - ISRVECTORED]; | |
247 | 247 | |||
248 | if (isr->isr_func == NULL) { | 248 | if (isr->isr_func == NULL) { | |
249 | printf("isrdispatch_vectored: no handler for vec 0x%x\n", vec); | 249 | printf("isrdispatch_vectored: no handler for vec 0x%x\n", vec); | |
250 | vectab[vec] = badtrap; | 250 | vectab[vec] = badtrap; | |
251 | idepth--; | 251 | idepth--; | |
252 | return; | 252 | return; | |
253 | } | 253 | } | |
254 | 254 | |||
255 | /* | 255 | /* | |
256 | * Handler gets exception frame if argument is NULL. | 256 | * Handler gets exception frame if argument is NULL. | |
257 | */ | 257 | */ | |
258 | if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) | 258 | if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) | |
259 | printf("isrdispatch_vectored: vec 0x%x not claimed\n", vec); | 259 | printf("isrdispatch_vectored: vec 0x%x not claimed\n", vec); | |
260 | idepth--; | 260 | idepth--; | |
261 | } | 261 | } | |
262 | 262 | |||
263 | bool | 263 | bool | |
264 | cpu_intr_p(void) | 264 | cpu_intr_p(void) | |
265 | { | 265 | { | |
266 | 266 | |||
267 | return idepth != 0; | 267 | return idepth != 0; | |
268 | } | 268 | } | |
269 | 269 | |||
270 | const uint16_t ipl2psl_table[NIPL] = { | 270 | const uint16_t ipl2psl_table[NIPL] = { | |
271 | [IPL_NONE] = PSL_S|PSL_IPL0, | 271 | [IPL_NONE] = PSL_S|PSL_IPL0, | |
272 | [IPL_SOFTCLOCK] = PSL_S|PSL_IPL1, | 272 | [IPL_SOFTCLOCK] = PSL_S|PSL_IPL1, | |
273 | [IPL_SOFTBIO] = PSL_S|PSL_IPL1, | 273 | [IPL_SOFTBIO] = PSL_S|PSL_IPL1, | |
274 | [IPL_SOFTNET] = PSL_S|PSL_IPL1, | 274 | [IPL_SOFTNET] = PSL_S|PSL_IPL1, | |
275 | [IPL_SOFTSERIAL] = PSL_S|PSL_IPL1, | 275 | [IPL_SOFTSERIAL] = PSL_S|PSL_IPL1, | |
276 | [IPL_VM] = PSL_S|PSL_IPL4, | 276 | [IPL_VM] = PSL_S|PSL_IPL4, | |
277 | [IPL_SCHED] = PSL_S|PSL_IPL5, | 277 | [IPL_SCHED] = PSL_S|PSL_IPL5, | |
278 | [IPL_HIGH] = PSL_S|PSL_IPL7, | 278 | [IPL_HIGH] = PSL_S|PSL_IPL7, | |
279 | }; | 279 | }; |
--- src/sys/arch/mac68k/mac68k/intr.c 2020/07/21 06:10:26 1.31
+++ src/sys/arch/mac68k/mac68k/intr.c 2021/04/02 12:11:41 1.32
@@ -1,259 +1,259 @@ | @@ -1,259 +1,259 @@ | |||
1 | /* $NetBSD: intr.c,v 1.31 2020/07/21 06:10:26 rin Exp $ */ | 1 | /* $NetBSD: intr.c,v 1.32 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | 8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Link and dispatch interrupts. | 33 | * Link and dispatch interrupts. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.31 2020/07/21 06:10:26 rin Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.32 2021/04/02 12:11:41 rin Exp $"); | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/systm.h> | 40 | #include <sys/systm.h> | |
41 | #include <sys/malloc.h> | 41 | #include <sys/malloc.h> | |
42 | #include <sys/vmmeter.h> | 42 | #include <sys/vmmeter.h> | |
43 | #include <sys/cpu.h> | 43 | #include <sys/cpu.h> | |
44 | #include <sys/intr.h> | 44 | #include <sys/intr.h> | |
45 | 45 | |||
46 | #include <machine/psc.h> | 46 | #include <machine/psc.h> | |
47 | #include <machine/viareg.h> | 47 | #include <machine/viareg.h> | |
48 | 48 | |||
49 | #define NISR 8 | 49 | #define NISR 8 | |
50 | #define ISRLOC 0x18 | 50 | #define ISRLOC 0x18 | |
51 | 51 | |||
52 | static int intr_noint(void *); | 52 | static int intr_noint(void *); | |
53 | 53 | |||
54 | static int ((*intr_func[NISR])(void *)) = { | 54 | static int ((*intr_func[NISR])(void *)) = { | |
55 | intr_noint, | 55 | intr_noint, | |
56 | intr_noint, | 56 | intr_noint, | |
57 | intr_noint, | 57 | intr_noint, | |
58 | intr_noint, | 58 | intr_noint, | |
59 | intr_noint, | 59 | intr_noint, | |
60 | intr_noint, | 60 | intr_noint, | |
61 | intr_noint, | 61 | intr_noint, | |
62 | intr_noint | 62 | intr_noint | |
63 | }; | 63 | }; | |
64 | static void *intr_arg[NISR] = { | 64 | static void *intr_arg[NISR] = { | |
65 | (void *)0, | 65 | (void *)0, | |
66 | (void *)1, | 66 | (void *)1, | |
67 | (void *)2, | 67 | (void *)2, | |
68 | (void *)3, | 68 | (void *)3, | |
69 | (void *)4, | 69 | (void *)4, | |
70 | (void *)5, | 70 | (void *)5, | |
71 | (void *)6, | 71 | (void *)6, | |
72 | (void *)7 | 72 | (void *)7 | |
73 | }; | 73 | }; | |
74 | 74 | |||
75 | #ifdef DEBUG | 75 | #ifdef DEBUG | |
76 | int intr_debug = 0; | 76 | int intr_debug = 0; | |
77 | #endif | 77 | #endif | |
78 | 78 | |||
79 | /* | 79 | /* | |
80 | * Some of the below are not used yet, but might be used someday on the | 80 | * Some of the below are not used yet, but might be used someday on the | |
81 | * IIfx/Q700/900/950/etc. where the interrupt controller may be reprogrammed | 81 | * IIfx/Q700/900/950/etc. where the interrupt controller may be reprogrammed | |
82 | * to interrupt on different levels as listed in locore.s | 82 | * to interrupt on different levels as listed in locore.s | |
83 | */ | 83 | */ | |
84 | uint16_t ipl2psl_table[NIPL]; | 84 | uint16_t ipl2psl_table[NIPL]; | |
85 | int idepth; | 85 | int idepth; | |
86 | volatile int ssir; | 86 | volatile int ssir; | |
87 | 87 | |||
88 | extern int intrcnt[]; /* from locore.s */ | 88 | extern u_int intrcnt[]; /* from locore.s */ | |
89 | 89 | |||
90 | void intr_computeipl(void); | 90 | void intr_computeipl(void); | |
91 | 91 | |||
92 | #define MAX_INAME_LENGTH 53 | 92 | #define MAX_INAME_LENGTH 53 | |
93 | #define STD_INAMES \ | 93 | #define STD_INAMES \ | |
94 | "spur\0via1\0via2\0unused1\0scc\0unused2\0unused3\0nmi\0clock\0" | 94 | "spur\0via1\0via2\0unused1\0scc\0unused2\0unused3\0nmi\0clock\0" | |
95 | #define AUX_INAMES \ | 95 | #define AUX_INAMES \ | |
96 | "spur\0soft\0via2\0ethernet\0scc\0sound\0via1\0nmi\0clock\0 " | 96 | "spur\0soft\0via2\0ethernet\0scc\0sound\0via1\0nmi\0clock\0 " | |
97 | #define AV_INAMES \ | 97 | #define AV_INAMES \ | |
98 | "spur\0via1\0via2\0ethernet\0scc\0dsp\0unused1\0nmi\0clock\0 " | 98 | "spur\0via1\0via2\0ethernet\0scc\0dsp\0unused1\0nmi\0clock\0 " | |
99 | 99 | |||
100 | void | 100 | void | |
101 | intr_init(void) | 101 | intr_init(void) | |
102 | { | 102 | { | |
103 | extern char intrnames[MAX_INAME_LENGTH]; | 103 | extern char intrnames[MAX_INAME_LENGTH]; | |
104 | extern char eintrnames[] __diagused; | 104 | extern char eintrnames[] __diagused; | |
105 | const char *inames; | 105 | const char *inames; | |
106 | 106 | |||
107 | ipl2psl_table[IPL_NONE] = 0; | 107 | ipl2psl_table[IPL_NONE] = 0; | |
108 | ipl2psl_table[IPL_SOFTCLOCK] = PSL_S|PSL_IPL1; | 108 | ipl2psl_table[IPL_SOFTCLOCK] = PSL_S|PSL_IPL1; | |
109 | ipl2psl_table[IPL_SOFTNET] = PSL_S|PSL_IPL1; | 109 | ipl2psl_table[IPL_SOFTNET] = PSL_S|PSL_IPL1; | |
110 | ipl2psl_table[IPL_SOFTSERIAL] = PSL_S|PSL_IPL1; | 110 | ipl2psl_table[IPL_SOFTSERIAL] = PSL_S|PSL_IPL1; | |
111 | ipl2psl_table[IPL_SOFTBIO] = PSL_S|PSL_IPL1; | 111 | ipl2psl_table[IPL_SOFTBIO] = PSL_S|PSL_IPL1; | |
112 | ipl2psl_table[IPL_HIGH] = PSL_S|PSL_IPL7; | 112 | ipl2psl_table[IPL_HIGH] = PSL_S|PSL_IPL7; | |
113 | 113 | |||
114 | if (mac68k_machine.aux_interrupts) { | 114 | if (mac68k_machine.aux_interrupts) { | |
115 | inames = AUX_INAMES; | 115 | inames = AUX_INAMES; | |
116 | 116 | |||
117 | /* Standard spl(9) interrupt priorities */ | 117 | /* Standard spl(9) interrupt priorities */ | |
118 | ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL6); | 118 | ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL6); | |
119 | ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL6); | 119 | ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL6); | |
120 | } else { | 120 | } else { | |
121 | inames = STD_INAMES; | 121 | inames = STD_INAMES; | |
122 | 122 | |||
123 | /* Standard spl(9) interrupt priorities */ | 123 | /* Standard spl(9) interrupt priorities */ | |
124 | ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL2); | 124 | ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL2); | |
125 | ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL3); | 125 | ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL3); | |
126 | 126 | |||
127 | if (current_mac_model->class == MACH_CLASSAV) { | 127 | if (current_mac_model->class == MACH_CLASSAV) { | |
128 | inames = AV_INAMES; | 128 | inames = AV_INAMES; | |
129 | ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL4); | 129 | ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL4); | |
130 | ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL4); | 130 | ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL4); | |
131 | } | 131 | } | |
132 | } | 132 | } | |
133 | 133 | |||
134 | KASSERT(MAX_INAME_LENGTH <= | 134 | KASSERT(MAX_INAME_LENGTH <= | |
135 | ((uintptr_t)eintrnames - (uintptr_t)intrnames)); | 135 | ((uintptr_t)eintrnames - (uintptr_t)intrnames)); | |
136 | memcpy(intrnames, inames, MAX_INAME_LENGTH); | 136 | memcpy(intrnames, inames, MAX_INAME_LENGTH); | |
137 | 137 | |||
138 | intr_computeipl(); | 138 | intr_computeipl(); | |
139 | 139 | |||
140 | /* Initialize the VIAs */ | 140 | /* Initialize the VIAs */ | |
141 | via_init(); | 141 | via_init(); | |
142 | 142 | |||
143 | /* Initialize the PSC (if present) */ | 143 | /* Initialize the PSC (if present) */ | |
144 | psc_init(); | 144 | psc_init(); | |
145 | } | 145 | } | |
146 | 146 | |||
147 | 147 | |||
148 | /* | 148 | /* | |
149 | * Compute the interrupt levels for the spl*() | 149 | * Compute the interrupt levels for the spl*() | |
150 | * calls. This doesn't have to be fast. | 150 | * calls. This doesn't have to be fast. | |
151 | */ | 151 | */ | |
152 | void | 152 | void | |
153 | intr_computeipl(void) | 153 | intr_computeipl(void) | |
154 | { | 154 | { | |
155 | /* | 155 | /* | |
156 | * Enforce the following relationship, as defined in spl(9): | 156 | * Enforce the following relationship, as defined in spl(9): | |
157 | * `bio <= net <= tty <= vm <= statclock <= clock <= sched <= serial' | 157 | * `bio <= net <= tty <= vm <= statclock <= clock <= sched <= serial' | |
158 | */ | 158 | */ | |
159 | if (ipl2psl_table[IPL_VM] > ipl2psl_table[IPL_SCHED]) | 159 | if (ipl2psl_table[IPL_VM] > ipl2psl_table[IPL_SCHED]) | |
160 | ipl2psl_table[IPL_SCHED] = ipl2psl_table[IPL_VM]; | 160 | ipl2psl_table[IPL_SCHED] = ipl2psl_table[IPL_VM]; | |
161 | 161 | |||
162 | if (ipl2psl_table[IPL_SCHED] > ipl2psl_table[IPL_HIGH]) | 162 | if (ipl2psl_table[IPL_SCHED] > ipl2psl_table[IPL_HIGH]) | |
163 | ipl2psl_table[IPL_HIGH] = ipl2psl_table[IPL_SCHED]; | 163 | ipl2psl_table[IPL_HIGH] = ipl2psl_table[IPL_SCHED]; | |
164 | } | 164 | } | |
165 | 165 | |||
166 | /* | 166 | /* | |
167 | * Establish an autovectored interrupt handler. | 167 | * Establish an autovectored interrupt handler. | |
168 | * Called by driver attach functions. | 168 | * Called by driver attach functions. | |
169 | * | 169 | * | |
170 | * XXX Warning! DO NOT use Macintosh ROM traps from an interrupt handler | 170 | * XXX Warning! DO NOT use Macintosh ROM traps from an interrupt handler | |
171 | * established by this routine, either directly or indirectly, without | 171 | * established by this routine, either directly or indirectly, without | |
172 | * properly saving and restoring all registers. If not, chaos _will_ | 172 | * properly saving and restoring all registers. If not, chaos _will_ | |
173 | * ensue! (sar 19980806) | 173 | * ensue! (sar 19980806) | |
174 | */ | 174 | */ | |
175 | void | 175 | void | |
176 | intr_establish(int (*func)(void *), void *arg, int ipl) | 176 | intr_establish(int (*func)(void *), void *arg, int ipl) | |
177 | { | 177 | { | |
178 | if ((ipl < 0) || (ipl >= NISR)) | 178 | if ((ipl < 0) || (ipl >= NISR)) | |
179 | panic("intr_establish: bad ipl %d", ipl); | 179 | panic("intr_establish: bad ipl %d", ipl); | |
180 | 180 | |||
181 | #ifdef DIAGNOSTIC | 181 | #ifdef DIAGNOSTIC | |
182 | if (intr_func[ipl] != intr_noint) | 182 | if (intr_func[ipl] != intr_noint) | |
183 | printf("intr_establish: attempt to share ipl %d\n", ipl); | 183 | printf("intr_establish: attempt to share ipl %d\n", ipl); | |
184 | #endif | 184 | #endif | |
185 | 185 | |||
186 | intr_func[ipl] = func; | 186 | intr_func[ipl] = func; | |
187 | intr_arg[ipl] = arg; | 187 | intr_arg[ipl] = arg; | |
188 | } | 188 | } | |
189 | 189 | |||
190 | /* | 190 | /* | |
191 | * Disestablish an interrupt handler. | 191 | * Disestablish an interrupt handler. | |
192 | */ | 192 | */ | |
193 | void | 193 | void | |
194 | intr_disestablish(int ipl) | 194 | intr_disestablish(int ipl) | |
195 | { | 195 | { | |
196 | if ((ipl < 0) || (ipl >= NISR)) | 196 | if ((ipl < 0) || (ipl >= NISR)) | |
197 | panic("intr_disestablish: bad ipl %d", ipl); | 197 | panic("intr_disestablish: bad ipl %d", ipl); | |
198 | 198 | |||
199 | intr_func[ipl] = intr_noint; | 199 | intr_func[ipl] = intr_noint; | |
200 | intr_arg[ipl] = (void *)ipl; | 200 | intr_arg[ipl] = (void *)ipl; | |
201 | } | 201 | } | |
202 | 202 | |||
203 | /* | 203 | /* | |
204 | * This is the dispatcher called by the low-level | 204 | * This is the dispatcher called by the low-level | |
205 | * assembly language interrupt routine. | 205 | * assembly language interrupt routine. | |
206 | * | 206 | * | |
207 | * XXX Note: see the warning in intr_establish() | 207 | * XXX Note: see the warning in intr_establish() | |
208 | */ | 208 | */ | |
209 | #if __GNUC_PREREQ__(8, 0) | 209 | #if __GNUC_PREREQ__(8, 0) | |
210 | /* | 210 | /* | |
211 | * XXX rtclock_intr() requires this for unwinding stack frame. | 211 | * XXX rtclock_intr() requires this for unwinding stack frame. | |
212 | */ | 212 | */ | |
213 | #pragma GCC push_options | 213 | #pragma GCC push_options | |
214 | #pragma GCC optimize "-fno-omit-frame-pointer" | 214 | #pragma GCC optimize "-fno-omit-frame-pointer" | |
215 | #endif | 215 | #endif | |
216 | void | 216 | void | |
217 | intr_dispatch(int evec) /* format | vector offset */ | 217 | intr_dispatch(int evec) /* format | vector offset */ | |
218 | { | 218 | { | |
219 | int ipl, vec; | 219 | int ipl, vec; | |
220 | 220 | |||
221 | idepth++; | 221 | idepth++; | |
222 | vec = (evec & 0xfff) >> 2; | 222 | vec = (evec & 0xfff) >> 2; | |
223 | #ifdef DIAGNOSTIC | 223 | #ifdef DIAGNOSTIC | |
224 | if ((vec < ISRLOC) || (vec >= (ISRLOC + NISR))) | 224 | if ((vec < ISRLOC) || (vec >= (ISRLOC + NISR))) | |
225 | panic("intr_dispatch: bad vec 0x%x", vec); | 225 | panic("intr_dispatch: bad vec 0x%x", vec); | |
226 | #endif | 226 | #endif | |
227 | ipl = vec - ISRLOC; | 227 | ipl = vec - ISRLOC; | |
228 | 228 | |||
229 | intrcnt[ipl]++; | 229 | intrcnt[ipl]++; | |
230 | curcpu()->ci_data.cpu_nintr++; | 230 | curcpu()->ci_data.cpu_nintr++; | |
231 | 231 | |||
232 | (void)(*intr_func[ipl])(intr_arg[ipl]); | 232 | (void)(*intr_func[ipl])(intr_arg[ipl]); | |
233 | idepth--; | 233 | idepth--; | |
234 | } | 234 | } | |
235 | #if __GNUC_PREREQ__(8, 0) | 235 | #if __GNUC_PREREQ__(8, 0) | |
236 | #pragma GCC pop_options | 236 | #pragma GCC pop_options | |
237 | #endif | 237 | #endif | |
238 | 238 | |||
239 | /* | 239 | /* | |
240 | * Default interrupt handler: do nothing. | 240 | * Default interrupt handler: do nothing. | |
241 | */ | 241 | */ | |
242 | static int | 242 | static int | |
243 | intr_noint(void *arg) | 243 | intr_noint(void *arg) | |
244 | { | 244 | { | |
245 | #ifdef DEBUG | 245 | #ifdef DEBUG | |
246 | idepth++; | 246 | idepth++; | |
247 | if (intr_debug) | 247 | if (intr_debug) | |
248 | printf("intr_noint: ipl %d\n", (int)arg); | 248 | printf("intr_noint: ipl %d\n", (int)arg); | |
249 | idepth--; | 249 | idepth--; | |
250 | #endif | 250 | #endif | |
251 | return 0; | 251 | return 0; | |
252 | } | 252 | } | |
253 | 253 | |||
254 | bool | 254 | bool | |
255 | cpu_intr_p(void) | 255 | cpu_intr_p(void) | |
256 | { | 256 | { | |
257 | 257 | |||
258 | return idepth != 0; | 258 | return idepth != 0; | |
259 | } | 259 | } |
--- src/sys/arch/mvme68k/mvme68k/isr.c 2020/11/21 17:59:13 1.35
+++ src/sys/arch/mvme68k/mvme68k/isr.c 2021/04/02 12:11:41 1.36
@@ -1,342 +1,342 @@ | @@ -1,342 +1,342 @@ | |||
1 | /* $NetBSD: isr.c,v 1.35 2020/11/21 17:59:13 thorpej Exp $ */ | 1 | /* $NetBSD: isr.c,v 1.36 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | 8 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Link and dispatch interrupts. | 33 | * Link and dispatch interrupts. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.35 2020/11/21 17:59:13 thorpej Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.36 2021/04/02 12:11:41 rin Exp $"); | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/systm.h> | 40 | #include <sys/systm.h> | |
41 | #include <sys/kmem.h> | 41 | #include <sys/kmem.h> | |
42 | #include <sys/vmmeter.h> | 42 | #include <sys/vmmeter.h> | |
43 | #include <sys/device.h> | 43 | #include <sys/device.h> | |
44 | #include <sys/cpu.h> | 44 | #include <sys/cpu.h> | |
45 | 45 | |||
46 | #include <uvm/uvm_extern.h> | 46 | #include <uvm/uvm_extern.h> | |
47 | 47 | |||
48 | #include <mvme68k/mvme68k/isr.h> | 48 | #include <mvme68k/mvme68k/isr.h> | |
49 | 49 | |||
50 | volatile unsigned int interrupt_depth; | 50 | volatile unsigned int interrupt_depth; | |
51 | isr_autovec_list_t isr_autovec[NISRAUTOVEC]; | 51 | isr_autovec_list_t isr_autovec[NISRAUTOVEC]; | |
52 | struct isr_vectored isr_vectored[NISRVECTORED]; | 52 | struct isr_vectored isr_vectored[NISRVECTORED]; | |
53 | static const char irqgroupname[] = "hard irqs"; | 53 | static const char irqgroupname[] = "hard irqs"; | |
54 | struct evcnt mvme68k_irq_evcnt[] = { | 54 | struct evcnt mvme68k_irq_evcnt[] = { | |
55 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "spur"), | 55 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "spur"), | |
56 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev1"), | 56 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev1"), | |
57 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev2"), | 57 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev2"), | |
58 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev3"), | 58 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev3"), | |
59 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev4"), | 59 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev4"), | |
60 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev5"), | 60 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev5"), | |
61 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev6"), | 61 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev6"), | |
62 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "nmi") | 62 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "nmi") | |
63 | }; | 63 | }; | |
64 | static int idepth; | 64 | static int idepth; | |
65 | 65 | |||
66 | extern int intrcnt[]; /* from locore.s. XXXSCW: will go away soon */ | 66 | extern u_int intrcnt[]; /* from locore.s. XXXSCW: will go away soon */ | |
67 | extern void (*vectab[])(void); | 67 | extern void (*vectab[])(void); | |
68 | extern void badtrap(void); | 68 | extern void badtrap(void); | |
69 | extern void intrhand_vectored(void); | 69 | extern void intrhand_vectored(void); | |
70 | 70 | |||
71 | static int spurintr(void *); | 71 | static int spurintr(void *); | |
72 | 72 | |||
73 | 73 | |||
74 | void | 74 | void | |
75 | isrinit(void) | 75 | isrinit(void) | |
76 | { | 76 | { | |
77 | int i; | 77 | int i; | |
78 | 78 | |||
79 | /* Initialize the autovector lists. */ | 79 | /* Initialize the autovector lists. */ | |
80 | for (i = 0; i < NISRAUTOVEC; ++i) | 80 | for (i = 0; i < NISRAUTOVEC; ++i) | |
81 | LIST_INIT(&isr_autovec[i]); | 81 | LIST_INIT(&isr_autovec[i]); | |
82 | 82 | |||
83 | /* Initialise the interrupt event counts */ | 83 | /* Initialise the interrupt event counts */ | |
84 | for (i = 0; i < (sizeof(mvme68k_irq_evcnt) / sizeof(struct evcnt)); i++) | 84 | for (i = 0; i < (sizeof(mvme68k_irq_evcnt) / sizeof(struct evcnt)); i++) | |
85 | evcnt_attach_static(&mvme68k_irq_evcnt[i]); | 85 | evcnt_attach_static(&mvme68k_irq_evcnt[i]); | |
86 | 86 | |||
87 | /* Arrange to trap Spurious and NMI auto-vectored Interrupts */ | 87 | /* Arrange to trap Spurious and NMI auto-vectored Interrupts */ | |
88 | isrlink_autovec(spurintr, NULL, 0, 0, NULL); | 88 | isrlink_autovec(spurintr, NULL, 0, 0, NULL); | |
89 | isrlink_autovec(nmihand, NULL, 7, 0, NULL); | 89 | isrlink_autovec(nmihand, NULL, 7, 0, NULL); | |
90 | } | 90 | } | |
91 | 91 | |||
92 | /* | 92 | /* | |
93 | * Establish an autovectored interrupt handler. | 93 | * Establish an autovectored interrupt handler. | |
94 | * Called by driver attach functions. | 94 | * Called by driver attach functions. | |
95 | */ | 95 | */ | |
96 | void | 96 | void | |
97 | isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority, | 97 | isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority, | |
98 | struct evcnt *evcnt) | 98 | struct evcnt *evcnt) | |
99 | { | 99 | { | |
100 | struct isr_autovec *newisr, *curisr; | 100 | struct isr_autovec *newisr, *curisr; | |
101 | isr_autovec_list_t *list; | 101 | isr_autovec_list_t *list; | |
102 | 102 | |||
103 | #ifdef DIAGNOSTIC | 103 | #ifdef DIAGNOSTIC | |
104 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 104 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
105 | panic("%s: bad ipl %d", __func__, ipl); | 105 | panic("%s: bad ipl %d", __func__, ipl); | |
106 | #endif | 106 | #endif | |
107 | 107 | |||
108 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | 108 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | |
109 | newisr->isr_func = func; | 109 | newisr->isr_func = func; | |
110 | newisr->isr_arg = arg; | 110 | newisr->isr_arg = arg; | |
111 | newisr->isr_ipl = ipl; | 111 | newisr->isr_ipl = ipl; | |
112 | newisr->isr_priority = priority; | 112 | newisr->isr_priority = priority; | |
113 | newisr->isr_evcnt = evcnt; | 113 | newisr->isr_evcnt = evcnt; | |
114 | 114 | |||
115 | /* | 115 | /* | |
116 | * Some devices are particularly sensitive to interrupt | 116 | * Some devices are particularly sensitive to interrupt | |
117 | * handling latency. The SCC, for example, can lose many | 117 | * handling latency. The SCC, for example, can lose many | |
118 | * characters if its interrupt isn't handled with reasonable | 118 | * characters if its interrupt isn't handled with reasonable | |
119 | * speed. | 119 | * speed. | |
120 | * | 120 | * | |
121 | * To work around this problem, each device can give itself a | 121 | * To work around this problem, each device can give itself a | |
122 | * "priority". An unbuffered SCC would give itself a higher | 122 | * "priority". An unbuffered SCC would give itself a higher | |
123 | * priority than a SCSI device, for example. | 123 | * priority than a SCSI device, for example. | |
124 | * | 124 | * | |
125 | * This solution was originally developed for the hp300, which | 125 | * This solution was originally developed for the hp300, which | |
126 | * has a flat spl scheme (by necessity). Thankfully, the | 126 | * has a flat spl scheme (by necessity). Thankfully, the | |
127 | * MVME systems don't have this problem, though this may serve | 127 | * MVME systems don't have this problem, though this may serve | |
128 | * a useful purpose in any case. | 128 | * a useful purpose in any case. | |
129 | */ | 129 | */ | |
130 | 130 | |||
131 | /* | 131 | /* | |
132 | * Get the appropriate ISR list. If the list is empty, no | 132 | * Get the appropriate ISR list. If the list is empty, no | |
133 | * additional work is necessary; we simply insert ourselves | 133 | * additional work is necessary; we simply insert ourselves | |
134 | * at the head of the list. | 134 | * at the head of the list. | |
135 | */ | 135 | */ | |
136 | list = &isr_autovec[ipl]; | 136 | list = &isr_autovec[ipl]; | |
137 | if (list->lh_first == NULL) { | 137 | if (list->lh_first == NULL) { | |
138 | LIST_INSERT_HEAD(list, newisr, isr_link); | 138 | LIST_INSERT_HEAD(list, newisr, isr_link); | |
139 | return; | 139 | return; | |
140 | } | 140 | } | |
141 | 141 | |||
142 | /* | 142 | /* | |
143 | * A little extra work is required. We traverse the list | 143 | * A little extra work is required. We traverse the list | |
144 | * and place ourselves after any ISRs with our current (or | 144 | * and place ourselves after any ISRs with our current (or | |
145 | * higher) priority. | 145 | * higher) priority. | |
146 | */ | 146 | */ | |
147 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | 147 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | |
148 | curisr = curisr->isr_link.le_next) { | 148 | curisr = curisr->isr_link.le_next) { | |
149 | if (newisr->isr_priority > curisr->isr_priority) { | 149 | if (newisr->isr_priority > curisr->isr_priority) { | |
150 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | 150 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | |
151 | return; | 151 | return; | |
152 | } | 152 | } | |
153 | } | 153 | } | |
154 | 154 | |||
155 | /* | 155 | /* | |
156 | * We're the least important entry, it seems. We just go | 156 | * We're the least important entry, it seems. We just go | |
157 | * on the end. | 157 | * on the end. | |
158 | */ | 158 | */ | |
159 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | 159 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | |
160 | } | 160 | } | |
161 | 161 | |||
162 | /* | 162 | /* | |
163 | * Establish a vectored interrupt handler. | 163 | * Establish a vectored interrupt handler. | |
164 | * Called by bus interrupt establish functions. | 164 | * Called by bus interrupt establish functions. | |
165 | */ | 165 | */ | |
166 | void | 166 | void | |
167 | isrlink_vectored(int (*func)(void *), void *arg, int ipl, int vec, | 167 | isrlink_vectored(int (*func)(void *), void *arg, int ipl, int vec, | |
168 | struct evcnt *evcnt) | 168 | struct evcnt *evcnt) | |
169 | { | 169 | { | |
170 | struct isr_vectored *isr; | 170 | struct isr_vectored *isr; | |
171 | 171 | |||
172 | #ifdef DIAGNOSTIC | 172 | #ifdef DIAGNOSTIC | |
173 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 173 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
174 | panic("%s: bad ipl %d", __func__, ipl); | 174 | panic("%s: bad ipl %d", __func__, ipl); | |
175 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | 175 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | |
176 | panic("%s: bad vec 0x%x", __func__, vec); | 176 | panic("%s: bad vec 0x%x", __func__, vec); | |
177 | #endif | 177 | #endif | |
178 | 178 | |||
179 | isr = &isr_vectored[vec - ISRVECTORED]; | 179 | isr = &isr_vectored[vec - ISRVECTORED]; | |
180 | 180 | |||
181 | #ifdef DIAGNOSTIC | 181 | #ifdef DIAGNOSTIC | |
182 | if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) | 182 | if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) | |
183 | panic("%s: vec 0x%x not available", __func__, vec); | 183 | panic("%s: vec 0x%x not available", __func__, vec); | |
184 | #endif | 184 | #endif | |
185 | 185 | |||
186 | /* Fill in the new entry. */ | 186 | /* Fill in the new entry. */ | |
187 | isr->isr_func = func; | 187 | isr->isr_func = func; | |
188 | isr->isr_arg = arg; | 188 | isr->isr_arg = arg; | |
189 | isr->isr_ipl = ipl; | 189 | isr->isr_ipl = ipl; | |
190 | isr->isr_evcnt = evcnt; | 190 | isr->isr_evcnt = evcnt; | |
191 | 191 | |||
192 | /* Hook into the vector table. */ | 192 | /* Hook into the vector table. */ | |
193 | vectab[vec] = intrhand_vectored; | 193 | vectab[vec] = intrhand_vectored; | |
194 | } | 194 | } | |
195 | 195 | |||
196 | /* | 196 | /* | |
197 | * Return a pointer to the evcnt structure for | 197 | * Return a pointer to the evcnt structure for | |
198 | * the specified ipl. | 198 | * the specified ipl. | |
199 | */ | 199 | */ | |
200 | struct evcnt * | 200 | struct evcnt * | |
201 | isrlink_evcnt(int ipl) | 201 | isrlink_evcnt(int ipl) | |
202 | { | 202 | { | |
203 | 203 | |||
204 | #ifdef DIAGNOSTIC | 204 | #ifdef DIAGNOSTIC | |
205 | if (ipl < 0 || | 205 | if (ipl < 0 || | |
206 | ipl >= (sizeof(mvme68k_irq_evcnt) / sizeof(struct evcnt))) | 206 | ipl >= (sizeof(mvme68k_irq_evcnt) / sizeof(struct evcnt))) | |
207 | panic("%s: bad ipl %d", __func__, ipl); | 207 | panic("%s: bad ipl %d", __func__, ipl); | |
208 | #endif | 208 | #endif | |
209 | 209 | |||
210 | return &mvme68k_irq_evcnt[ipl]; | 210 | return &mvme68k_irq_evcnt[ipl]; | |
211 | } | 211 | } | |
212 | 212 | |||
213 | /* | 213 | /* | |
214 | * Unhook a vectored interrupt. | 214 | * Unhook a vectored interrupt. | |
215 | */ | 215 | */ | |
216 | void | 216 | void | |
217 | isrunlink_vectored(int vec) | 217 | isrunlink_vectored(int vec) | |
218 | { | 218 | { | |
219 | 219 | |||
220 | #ifdef DIAGNOSTIC | 220 | #ifdef DIAGNOSTIC | |
221 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | 221 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | |
222 | panic("%s: bad vec 0x%x", __func__, vec); | 222 | panic("%s: bad vec 0x%x", __func__, vec); | |
223 | 223 | |||
224 | if (vectab[vec] != intrhand_vectored) | 224 | if (vectab[vec] != intrhand_vectored) | |
225 | panic("%s: not vectored interrupt", __func__); | 225 | panic("%s: not vectored interrupt", __func__); | |
226 | #endif | 226 | #endif | |
227 | 227 | |||
228 | vectab[vec] = badtrap; | 228 | vectab[vec] = badtrap; | |
229 | memset(&isr_vectored[vec - ISRVECTORED], 0, | 229 | memset(&isr_vectored[vec - ISRVECTORED], 0, | |
230 | sizeof(struct isr_vectored)); | 230 | sizeof(struct isr_vectored)); | |
231 | } | 231 | } | |
232 | 232 | |||
233 | /* | 233 | /* | |
234 | * This is the dispatcher called by the low-level | 234 | * This is the dispatcher called by the low-level | |
235 | * assembly language autovectored interrupt routine. | 235 | * assembly language autovectored interrupt routine. | |
236 | */ | 236 | */ | |
237 | void | 237 | void | |
238 | isrdispatch_autovec(struct clockframe *frame) | 238 | isrdispatch_autovec(struct clockframe *frame) | |
239 | { | 239 | { | |
240 | struct isr_autovec *isr; | 240 | struct isr_autovec *isr; | |
241 | isr_autovec_list_t *list; | 241 | isr_autovec_list_t *list; | |
242 | int handled, ipl; | 242 | int handled, ipl; | |
243 | void *arg; | 243 | void *arg; | |
244 | static int straycount, unexpected; | 244 | static int straycount, unexpected; | |
245 | 245 | |||
246 | idepth++; | 246 | idepth++; | |
247 | ipl = (frame->vec >> 2) - ISRAUTOVEC; | 247 | ipl = (frame->vec >> 2) - ISRAUTOVEC; | |
248 | 248 | |||
249 | #ifdef DIAGNOSTIC | 249 | #ifdef DIAGNOSTIC | |
250 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 250 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
251 | panic("%s: bad vec 0x%x", __func__, frame->vec); | 251 | panic("%s: bad vec 0x%x", __func__, frame->vec); | |
252 | #endif | 252 | #endif | |
253 | 253 | |||
254 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | 254 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | |
255 | mvme68k_irq_evcnt[ipl].ev_count++; | 255 | mvme68k_irq_evcnt[ipl].ev_count++; | |
256 | curcpu()->ci_data.cpu_nintr++; | 256 | curcpu()->ci_data.cpu_nintr++; | |
257 | 257 | |||
258 | list = &isr_autovec[ipl]; | 258 | list = &isr_autovec[ipl]; | |
259 | if (list->lh_first == NULL) { | 259 | if (list->lh_first == NULL) { | |
260 | printf("%s: ipl %d unexpected\n", __func__, ipl); | 260 | printf("%s: ipl %d unexpected\n", __func__, ipl); | |
261 | if (++unexpected > 10) | 261 | if (++unexpected > 10) | |
262 | panic("too many unexpected interrupts"); | 262 | panic("too many unexpected interrupts"); | |
263 | idepth--; | 263 | idepth--; | |
264 | return; | 264 | return; | |
265 | } | 265 | } | |
266 | 266 | |||
267 | /* Give all the handlers a chance. */ | 267 | /* Give all the handlers a chance. */ | |
268 | handled = 0; | 268 | handled = 0; | |
269 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) { | 269 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) { | |
270 | arg = isr->isr_arg ? isr->isr_arg : frame; | 270 | arg = isr->isr_arg ? isr->isr_arg : frame; | |
271 | if ((*isr->isr_func)(arg) != 0) { | 271 | if ((*isr->isr_func)(arg) != 0) { | |
272 | if (isr->isr_evcnt) | 272 | if (isr->isr_evcnt) | |
273 | isr->isr_evcnt->ev_count++; | 273 | isr->isr_evcnt->ev_count++; | |
274 | handled++; | 274 | handled++; | |
275 | } | 275 | } | |
276 | } | 276 | } | |
277 | 277 | |||
278 | if (handled) | 278 | if (handled) | |
279 | straycount = 0; | 279 | straycount = 0; | |
280 | else if (++straycount > 50) | 280 | else if (++straycount > 50) | |
281 | panic("%s: too many stray interrupts", __func__); | 281 | panic("%s: too many stray interrupts", __func__); | |
282 | else | 282 | else | |
283 | printf("%s: stray level %d interrupt\n", __func__, ipl); | 283 | printf("%s: stray level %d interrupt\n", __func__, ipl); | |
284 | 284 | |||
285 | idepth--; | 285 | idepth--; | |
286 | } | 286 | } | |
287 | 287 | |||
288 | /* | 288 | /* | |
289 | * This is the dispatcher called by the low-level | 289 | * This is the dispatcher called by the low-level | |
290 | * assembly language vectored interrupt routine. | 290 | * assembly language vectored interrupt routine. | |
291 | */ | 291 | */ | |
292 | void | 292 | void | |
293 | isrdispatch_vectored(int ipl, struct clockframe *frame) | 293 | isrdispatch_vectored(int ipl, struct clockframe *frame) | |
294 | { | 294 | { | |
295 | struct isr_vectored *isr; | 295 | struct isr_vectored *isr; | |
296 | int vec; | 296 | int vec; | |
297 | 297 | |||
298 | idepth++; | 298 | idepth++; | |
299 | vec = (frame->vec >> 2) - ISRVECTORED; | 299 | vec = (frame->vec >> 2) - ISRVECTORED; | |
300 | 300 | |||
301 | #ifdef DIAGNOSTIC | 301 | #ifdef DIAGNOSTIC | |
302 | if ((vec < 0) || (vec >= NISRVECTORED)) | 302 | if ((vec < 0) || (vec >= NISRVECTORED)) | |
303 | panic("%s: bad vec 0x%x", __func__, frame->vec); | 303 | panic("%s: bad vec 0x%x", __func__, frame->vec); | |
304 | #endif | 304 | #endif | |
305 | 305 | |||
306 | isr = &isr_vectored[vec]; | 306 | isr = &isr_vectored[vec]; | |
307 | 307 | |||
308 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | 308 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | |
309 | mvme68k_irq_evcnt[ipl].ev_count++; | 309 | mvme68k_irq_evcnt[ipl].ev_count++; | |
310 | curcpu()->ci_data.cpu_nintr++; | 310 | curcpu()->ci_data.cpu_nintr++; | |
311 | 311 | |||
312 | if (isr->isr_func == NULL) { | 312 | if (isr->isr_func == NULL) { | |
313 | printf("%s: no handler for vec 0x%x\n", __func__, frame->vec); | 313 | printf("%s: no handler for vec 0x%x\n", __func__, frame->vec); | |
314 | vectab[vec + ISRVECTORED] = badtrap; | 314 | vectab[vec + ISRVECTORED] = badtrap; | |
315 | idepth--; | 315 | idepth--; | |
316 | return; | 316 | return; | |
317 | } | 317 | } | |
318 | 318 | |||
319 | /* | 319 | /* | |
320 | * Handler gets exception frame if argument is NULL. | 320 | * Handler gets exception frame if argument is NULL. | |
321 | */ | 321 | */ | |
322 | if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) | 322 | if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) | |
323 | printf("%s: vec 0x%x not claimed\n", __func__, frame->vec); | 323 | printf("%s: vec 0x%x not claimed\n", __func__, frame->vec); | |
324 | else if (isr->isr_evcnt) | 324 | else if (isr->isr_evcnt) | |
325 | isr->isr_evcnt->ev_count++; | 325 | isr->isr_evcnt->ev_count++; | |
326 | idepth--; | 326 | idepth--; | |
327 | } | 327 | } | |
328 | 328 | |||
329 | bool | 329 | bool | |
330 | cpu_intr_p(void) | 330 | cpu_intr_p(void) | |
331 | { | 331 | { | |
332 | 332 | |||
333 | return idepth != 0; | 333 | return idepth != 0; | |
334 | } | 334 | } | |
335 | 335 | |||
336 | /* ARGSUSED */ | 336 | /* ARGSUSED */ | |
337 | static int | 337 | static int | |
338 | spurintr(void *arg) | 338 | spurintr(void *arg) | |
339 | { | 339 | { | |
340 | 340 | |||
341 | return 1; | 341 | return 1; | |
342 | } | 342 | } |
--- src/sys/arch/next68k/next68k/isr.c 2020/11/21 17:49:20 1.31
+++ src/sys/arch/next68k/next68k/isr.c 2021/04/02 12:11:41 1.32
@@ -1,407 +1,407 @@ | @@ -1,407 +1,407 @@ | |||
1 | /* $NetBSD: isr.c,v 1.31 2020/11/21 17:49:20 thorpej Exp $ */ | 1 | /* $NetBSD: isr.c,v 1.32 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * This file was taken from mvme68k/mvme68k/isr.c | 4 | * This file was taken from mvme68k/mvme68k/isr.c | |
5 | * should probably be re-synced when needed. | 5 | * should probably be re-synced when needed. | |
6 | * Darrin B. Jewell <jewell@mit.edu> Tue Nov 10 05:07:16 1998 | 6 | * Darrin B. Jewell <jewell@mit.edu> Tue Nov 10 05:07:16 1998 | |
7 | * original cvs id: NetBSD: isr.c,v 1.12 1998/07/05 06:49:07 jonathan Exp | 7 | * original cvs id: NetBSD: isr.c,v 1.12 1998/07/05 06:49:07 jonathan Exp | |
8 | */ | 8 | */ | |
9 | 9 | |||
10 | /*- | 10 | /*- | |
11 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | 11 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | |
12 | * All rights reserved. | 12 | * All rights reserved. | |
13 | * | 13 | * | |
14 | * This code is derived from software contributed to The NetBSD Foundation | 14 | * This code is derived from software contributed to The NetBSD Foundation | |
15 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | 15 | * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. | |
16 | * | 16 | * | |
17 | * Redistribution and use in source and binary forms, with or without | 17 | * Redistribution and use in source and binary forms, with or without | |
18 | * modification, are permitted provided that the following conditions | 18 | * modification, are permitted provided that the following conditions | |
19 | * are met: | 19 | * are met: | |
20 | * 1. Redistributions of source code must retain the above copyright | 20 | * 1. Redistributions of source code must retain the above copyright | |
21 | * notice, this list of conditions and the following disclaimer. | 21 | * notice, this list of conditions and the following disclaimer. | |
22 | * 2. Redistributions in binary form must reproduce the above copyright | 22 | * 2. Redistributions in binary form must reproduce the above copyright | |
23 | * notice, this list of conditions and the following disclaimer in the | 23 | * notice, this list of conditions and the following disclaimer in the | |
24 | * documentation and/or other materials provided with the distribution. | 24 | * documentation and/or other materials provided with the distribution. | |
25 | * | 25 | * | |
26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
36 | * POSSIBILITY OF SUCH DAMAGE. | 36 | * POSSIBILITY OF SUCH DAMAGE. | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | /* | 39 | /* | |
40 | * Link and dispatch interrupts. | 40 | * Link and dispatch interrupts. | |
41 | */ | 41 | */ | |
42 | 42 | |||
43 | #include <sys/cdefs.h> | 43 | #include <sys/cdefs.h> | |
44 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.31 2020/11/21 17:49:20 thorpej Exp $"); | 44 | __KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.32 2021/04/02 12:11:41 rin Exp $"); | |
45 | 45 | |||
46 | #include <sys/param.h> | 46 | #include <sys/param.h> | |
47 | #include <sys/systm.h> | 47 | #include <sys/systm.h> | |
48 | #include <sys/kmem.h> | 48 | #include <sys/kmem.h> | |
49 | #include <sys/vmmeter.h> | 49 | #include <sys/vmmeter.h> | |
50 | #include <sys/device.h> | 50 | #include <sys/device.h> | |
51 | #include <sys/bus.h> | 51 | #include <sys/bus.h> | |
52 | #include <sys/cpu.h> | 52 | #include <sys/cpu.h> | |
53 | 53 | |||
54 | #include <uvm/uvm_extern.h> | 54 | #include <uvm/uvm_extern.h> | |
55 | 55 | |||
56 | #include <next68k/next68k/isr.h> | 56 | #include <next68k/next68k/isr.h> | |
57 | 57 | |||
58 | #include <next68k/dev/intiovar.h> | 58 | #include <next68k/dev/intiovar.h> | |
59 | 59 | |||
60 | volatile unsigned int interrupt_depth; | 60 | volatile unsigned int interrupt_depth; | |
61 | isr_autovec_list_t isr_autovec[NISRAUTOVEC]; | 61 | isr_autovec_list_t isr_autovec[NISRAUTOVEC]; | |
62 | struct isr_vectored isr_vectored[NISRVECTORED]; | 62 | struct isr_vectored isr_vectored[NISRVECTORED]; | |
63 | static const char irqgroupname[] = "hard irqs"; | 63 | static const char irqgroupname[] = "hard irqs"; | |
64 | struct evcnt next68k_irq_evcnt[] = { | 64 | struct evcnt next68k_irq_evcnt[] = { | |
65 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "spur"), | 65 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "spur"), | |
66 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev1"), | 66 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev1"), | |
67 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev2"), | 67 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev2"), | |
68 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev3"), | 68 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev3"), | |
69 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev4"), | 69 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev4"), | |
70 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev5"), | 70 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev5"), | |
71 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev6"), | 71 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "lev6"), | |
72 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "nmi") | 72 | EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, irqgroupname, "nmi") | |
73 | }; | 73 | }; | |
74 | 74 | |||
75 | int idepth; | 75 | int idepth; | |
76 | int ssir; | 76 | int ssir; | |
77 | extern int intrcnt[]; /* from locore.s. XXXSCW: will go away soon */ | 77 | extern u_int intrcnt[]; /* from locore.s. XXXSCW: will go away soon */ | |
78 | extern void (*vectab[])(void); | 78 | extern void (*vectab[])(void); | |
79 | extern void badtrap(void); | 79 | extern void badtrap(void); | |
80 | extern void intrhand_vectored(void); | 80 | extern void intrhand_vectored(void); | |
81 | 81 | |||
82 | #if 0 | 82 | #if 0 | |
83 | static int spurintr(void *); | 83 | static int spurintr(void *); | |
84 | #endif | 84 | #endif | |
85 | 85 | |||
86 | void | 86 | void | |
87 | isrinit(void) | 87 | isrinit(void) | |
88 | { | 88 | { | |
89 | int i; | 89 | int i; | |
90 | 90 | |||
91 | /* Initialize the autovector lists. */ | 91 | /* Initialize the autovector lists. */ | |
92 | for (i = 0; i < NISRAUTOVEC; ++i) | 92 | for (i = 0; i < NISRAUTOVEC; ++i) | |
93 | LIST_INIT(&isr_autovec[i]); | 93 | LIST_INIT(&isr_autovec[i]); | |
94 | 94 | |||
95 | /* Initialise the interrupt event counts */ | 95 | /* Initialise the interrupt event counts */ | |
96 | for (i = 0; i < (sizeof(next68k_irq_evcnt) / sizeof(struct evcnt)); i++) | 96 | for (i = 0; i < (sizeof(next68k_irq_evcnt) / sizeof(struct evcnt)); i++) | |
97 | evcnt_attach_static(&next68k_irq_evcnt[i]); | 97 | evcnt_attach_static(&next68k_irq_evcnt[i]); | |
98 | 98 | |||
99 | /* Arrange to trap Spurious and NMI auto-vectored Interrupts */ | 99 | /* Arrange to trap Spurious and NMI auto-vectored Interrupts */ | |
100 | /* isrlink_autovec(spurintr, NULL, 0, 0, NULL); */ | 100 | /* isrlink_autovec(spurintr, NULL, 0, 0, NULL); */ | |
101 | /* isrlink_autovec(nmihand, NULL, 7, 0, NULL); */ | 101 | /* isrlink_autovec(nmihand, NULL, 7, 0, NULL); */ | |
102 | } | 102 | } | |
103 | 103 | |||
104 | /* | 104 | /* | |
105 | * Establish an autovectored interrupt handler. | 105 | * Establish an autovectored interrupt handler. | |
106 | * Called by driver attach functions. | 106 | * Called by driver attach functions. | |
107 | */ | 107 | */ | |
108 | void | 108 | void | |
109 | isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority, | 109 | isrlink_autovec(int (*func)(void *), void *arg, int ipl, int priority, | |
110 | struct evcnt *evcnt) | 110 | struct evcnt *evcnt) | |
111 | { | 111 | { | |
112 | struct isr_autovec *newisr, *curisr; | 112 | struct isr_autovec *newisr, *curisr; | |
113 | isr_autovec_list_t *list; | 113 | isr_autovec_list_t *list; | |
114 | 114 | |||
115 | #ifdef DIAGNOSTIC | 115 | #ifdef DIAGNOSTIC | |
116 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 116 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
117 | panic("isrlink_autovec: bad ipl %d", ipl); | 117 | panic("isrlink_autovec: bad ipl %d", ipl); | |
118 | #endif | 118 | #endif | |
119 | 119 | |||
120 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | 120 | newisr = kmem_alloc(sizeof(*newisr), KM_SLEEP); | |
121 | newisr->isr_func = func; | 121 | newisr->isr_func = func; | |
122 | newisr->isr_arg = arg; | 122 | newisr->isr_arg = arg; | |
123 | newisr->isr_ipl = ipl; | 123 | newisr->isr_ipl = ipl; | |
124 | newisr->isr_priority = priority; | 124 | newisr->isr_priority = priority; | |
125 | newisr->isr_evcnt = evcnt; | 125 | newisr->isr_evcnt = evcnt; | |
126 | 126 | |||
127 | /* | 127 | /* | |
128 | * Some devices are particularly sensitive to interrupt | 128 | * Some devices are particularly sensitive to interrupt | |
129 | * handling latency. The SCC, for example, can lose many | 129 | * handling latency. The SCC, for example, can lose many | |
130 | * characters if its interrupt isn't handled with reasonable | 130 | * characters if its interrupt isn't handled with reasonable | |
131 | * speed. | 131 | * speed. | |
132 | * | 132 | * | |
133 | * To work around this problem, each device can give itself a | 133 | * To work around this problem, each device can give itself a | |
134 | * "priority". An unbuffered SCC would give itself a higher | 134 | * "priority". An unbuffered SCC would give itself a higher | |
135 | * priority than a SCSI device, for example. | 135 | * priority than a SCSI device, for example. | |
136 | * | 136 | * | |
137 | * This solution was originally developed for the hp300, which | 137 | * This solution was originally developed for the hp300, which | |
138 | * has a flat spl scheme (by necessity). Thankfully, the | 138 | * has a flat spl scheme (by necessity). Thankfully, the | |
139 | * MVME systems don't have this problem, though this may serve | 139 | * MVME systems don't have this problem, though this may serve | |
140 | * a useful purpose in any case. | 140 | * a useful purpose in any case. | |
141 | */ | 141 | */ | |
142 | 142 | |||
143 | /* | 143 | /* | |
144 | * Get the appropriate ISR list. If the list is empty, no | 144 | * Get the appropriate ISR list. If the list is empty, no | |
145 | * additional work is necessary; we simply insert ourselves | 145 | * additional work is necessary; we simply insert ourselves | |
146 | * at the head of the list. | 146 | * at the head of the list. | |
147 | */ | 147 | */ | |
148 | list = &isr_autovec[ipl]; | 148 | list = &isr_autovec[ipl]; | |
149 | if (list->lh_first == NULL) { | 149 | if (list->lh_first == NULL) { | |
150 | LIST_INSERT_HEAD(list, newisr, isr_link); | 150 | LIST_INSERT_HEAD(list, newisr, isr_link); | |
151 | return; | 151 | return; | |
152 | } | 152 | } | |
153 | 153 | |||
154 | /* | 154 | /* | |
155 | * A little extra work is required. We traverse the list | 155 | * A little extra work is required. We traverse the list | |
156 | * and place ourselves after any ISRs with our current (or | 156 | * and place ourselves after any ISRs with our current (or | |
157 | * higher) priority. | 157 | * higher) priority. | |
158 | */ | 158 | */ | |
159 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | 159 | for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; | |
160 | curisr = curisr->isr_link.le_next) { | 160 | curisr = curisr->isr_link.le_next) { | |
161 | if (newisr->isr_priority > curisr->isr_priority) { | 161 | if (newisr->isr_priority > curisr->isr_priority) { | |
162 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | 162 | LIST_INSERT_BEFORE(curisr, newisr, isr_link); | |
163 | return; | 163 | return; | |
164 | } | 164 | } | |
165 | } | 165 | } | |
166 | 166 | |||
167 | /* | 167 | /* | |
168 | * We're the least important entry, it seems. We just go | 168 | * We're the least important entry, it seems. We just go | |
169 | * on the end. | 169 | * on the end. | |
170 | */ | 170 | */ | |
171 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | 171 | LIST_INSERT_AFTER(curisr, newisr, isr_link); | |
172 | } | 172 | } | |
173 | 173 | |||
174 | /* | 174 | /* | |
175 | * Establish a vectored interrupt handler. | 175 | * Establish a vectored interrupt handler. | |
176 | * Called by bus interrupt establish functions. | 176 | * Called by bus interrupt establish functions. | |
177 | */ | 177 | */ | |
178 | void | 178 | void | |
179 | isrlink_vectored(int (*func)(void *), void *arg, int ipl, int vec, | 179 | isrlink_vectored(int (*func)(void *), void *arg, int ipl, int vec, | |
180 | struct evcnt *evcnt) | 180 | struct evcnt *evcnt) | |
181 | { | 181 | { | |
182 | struct isr_vectored *isr; | 182 | struct isr_vectored *isr; | |
183 | 183 | |||
184 | #ifdef DIAGNOSTIC | 184 | #ifdef DIAGNOSTIC | |
185 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 185 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
186 | panic("isrlink_vectored: bad ipl %d", ipl); | 186 | panic("isrlink_vectored: bad ipl %d", ipl); | |
187 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | 187 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | |
188 | panic("isrlink_vectored: bad vec 0x%x", vec); | 188 | panic("isrlink_vectored: bad vec 0x%x", vec); | |
189 | #endif | 189 | #endif | |
190 | 190 | |||
191 | isr = &isr_vectored[vec - ISRVECTORED]; | 191 | isr = &isr_vectored[vec - ISRVECTORED]; | |
192 | 192 | |||
193 | #ifdef DIAGNOSTIC | 193 | #ifdef DIAGNOSTIC | |
194 | if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) | 194 | if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) | |
195 | panic("isrlink_vectored: vec 0x%x not available", vec); | 195 | panic("isrlink_vectored: vec 0x%x not available", vec); | |
196 | #endif | 196 | #endif | |
197 | 197 | |||
198 | /* Fill in the new entry. */ | 198 | /* Fill in the new entry. */ | |
199 | isr->isr_func = func; | 199 | isr->isr_func = func; | |
200 | isr->isr_arg = arg; | 200 | isr->isr_arg = arg; | |
201 | isr->isr_ipl = ipl; | 201 | isr->isr_ipl = ipl; | |
202 | isr->isr_evcnt = evcnt; | 202 | isr->isr_evcnt = evcnt; | |
203 | 203 | |||
204 | /* Hook into the vector table. */ | 204 | /* Hook into the vector table. */ | |
205 | vectab[vec] = intrhand_vectored; | 205 | vectab[vec] = intrhand_vectored; | |
206 | } | 206 | } | |
207 | 207 | |||
208 | /* | 208 | /* | |
209 | * Return a pointer to the evcnt structure for | 209 | * Return a pointer to the evcnt structure for | |
210 | * the specified ipl. | 210 | * the specified ipl. | |
211 | */ | 211 | */ | |
212 | struct evcnt * | 212 | struct evcnt * | |
213 | isrlink_evcnt(int ipl) | 213 | isrlink_evcnt(int ipl) | |
214 | { | 214 | { | |
215 | 215 | |||
216 | #ifdef DIAGNOSTIC | 216 | #ifdef DIAGNOSTIC | |
217 | if (ipl < 0 || | 217 | if (ipl < 0 || | |
218 | ipl >= (sizeof(next68k_irq_evcnt) / sizeof(struct evcnt))) | 218 | ipl >= (sizeof(next68k_irq_evcnt) / sizeof(struct evcnt))) | |
219 | panic("isrlink_evcnt: bad ipl %d", ipl); | 219 | panic("isrlink_evcnt: bad ipl %d", ipl); | |
220 | #endif | 220 | #endif | |
221 | 221 | |||
222 | return (&next68k_irq_evcnt[ipl]); | 222 | return (&next68k_irq_evcnt[ipl]); | |
223 | } | 223 | } | |
224 | 224 | |||
225 | /* | 225 | /* | |
226 | * Unhook a vectored interrupt. | 226 | * Unhook a vectored interrupt. | |
227 | */ | 227 | */ | |
228 | void | 228 | void | |
229 | isrunlink_vectored(int vec) | 229 | isrunlink_vectored(int vec) | |
230 | { | 230 | { | |
231 | 231 | |||
232 | #ifdef DIAGNOSTIC | 232 | #ifdef DIAGNOSTIC | |
233 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | 233 | if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) | |
234 | panic("isrunlink_vectored: bad vec 0x%x", vec); | 234 | panic("isrunlink_vectored: bad vec 0x%x", vec); | |
235 | 235 | |||
236 | if (vectab[vec] != intrhand_vectored) | 236 | if (vectab[vec] != intrhand_vectored) | |
237 | panic("isrunlink_vectored: not vectored interrupt"); | 237 | panic("isrunlink_vectored: not vectored interrupt"); | |
238 | #endif | 238 | #endif | |
239 | 239 | |||
240 | vectab[vec] = badtrap; | 240 | vectab[vec] = badtrap; | |
241 | memset(&isr_vectored[vec - ISRVECTORED], 0, sizeof(struct isr_vectored)); | 241 | memset(&isr_vectored[vec - ISRVECTORED], 0, sizeof(struct isr_vectored)); | |
242 | } | 242 | } | |
243 | 243 | |||
244 | /* | 244 | /* | |
245 | * This is the dispatcher called by the low-level | 245 | * This is the dispatcher called by the low-level | |
246 | * assembly language autovectored interrupt routine. | 246 | * assembly language autovectored interrupt routine. | |
247 | */ | 247 | */ | |
248 | void | 248 | void | |
249 | isrdispatch_autovec(struct clockframe *frame) | 249 | isrdispatch_autovec(struct clockframe *frame) | |
250 | { | 250 | { | |
251 | struct isr_autovec *isr; | 251 | struct isr_autovec *isr; | |
252 | isr_autovec_list_t *list; | 252 | isr_autovec_list_t *list; | |
253 | int handled, ipl; | 253 | int handled, ipl; | |
254 | void *arg; | 254 | void *arg; | |
255 | static int straycount, unexpected; | 255 | static int straycount, unexpected; | |
256 | #ifdef INTRLOG | 256 | #ifdef INTRLOG | |
257 | static int logptr = 0; | 257 | static int logptr = 0; | |
258 | static struct { | 258 | static struct { | |
259 | int ipl; | 259 | int ipl; | |
260 | u_long intrstat, intrmask; | 260 | u_long intrstat, intrmask; | |
261 | int handled; | 261 | int handled; | |
262 | } log[256]; | 262 | } log[256]; | |
263 | #endif | 263 | #endif | |
264 | 264 | |||
265 | idepth++; | 265 | idepth++; | |
266 | 266 | |||
267 | ipl = (frame->vec >> 2) - ISRAUTOVEC; | 267 | ipl = (frame->vec >> 2) - ISRAUTOVEC; | |
268 | 268 | |||
269 | #ifdef DIAGNOSTIC | 269 | #ifdef DIAGNOSTIC | |
270 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | 270 | if ((ipl < 0) || (ipl >= NISRAUTOVEC)) | |
271 | panic("isrdispatch_autovec: bad vec 0x%x", frame->vec); | 271 | panic("isrdispatch_autovec: bad vec 0x%x", frame->vec); | |
272 | #endif | 272 | #endif | |
273 | 273 | |||
274 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | 274 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | |
275 | next68k_irq_evcnt[ipl].ev_count++; | 275 | next68k_irq_evcnt[ipl].ev_count++; | |
276 | curcpu()->ci_data.cpu_nintr++; | 276 | curcpu()->ci_data.cpu_nintr++; | |
277 | #ifdef INTRLOG | 277 | #ifdef INTRLOG | |
278 | log[logptr].ipl = ipl; | 278 | log[logptr].ipl = ipl; | |
279 | log[logptr].intrstat = *intrstat; | 279 | log[logptr].intrstat = *intrstat; | |
280 | log[logptr].intrmask = *intrmask; | 280 | log[logptr].intrmask = *intrmask; | |
281 | #endif | 281 | #endif | |
282 | 282 | |||
283 | list = &isr_autovec[ipl]; | 283 | list = &isr_autovec[ipl]; | |
284 | if (list->lh_first == NULL) { | 284 | if (list->lh_first == NULL) { | |
285 | printf("isrdispatch_autovec: ipl %d unexpected\n", ipl); | 285 | printf("isrdispatch_autovec: ipl %d unexpected\n", ipl); | |
286 | if (++unexpected > 10) | 286 | if (++unexpected > 10) | |
287 | panic("too many unexpected interrupts"); | 287 | panic("too many unexpected interrupts"); | |
288 | idepth--; | 288 | idepth--; | |
289 | return; | 289 | return; | |
290 | } | 290 | } | |
291 | 291 | |||
292 | /* Give all the handlers a chance. */ | 292 | /* Give all the handlers a chance. */ | |
293 | handled = 0; | 293 | handled = 0; | |
294 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) { | 294 | for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) { | |
295 | arg = isr->isr_arg ? isr->isr_arg : frame; | 295 | arg = isr->isr_arg ? isr->isr_arg : frame; | |
296 | if ((*isr->isr_func)(arg) != 0) { | 296 | if ((*isr->isr_func)(arg) != 0) { | |
297 | if (isr->isr_evcnt) | 297 | if (isr->isr_evcnt) | |
298 | isr->isr_evcnt->ev_count++; | 298 | isr->isr_evcnt->ev_count++; | |
299 | handled++; | 299 | handled++; | |
300 | } | 300 | } | |
301 | } | 301 | } | |
302 | 302 | |||
303 | #ifdef INTRLOG | 303 | #ifdef INTRLOG | |
304 | log[logptr].handled = handled; | 304 | log[logptr].handled = handled; | |
305 | logptr = (logptr + 1) & 255; | 305 | logptr = (logptr + 1) & 255; | |
306 | if (!handled && ++straycount >= 10) { | 306 | if (!handled && ++straycount >= 10) { | |
307 | int n, m; | 307 | int n, m; | |
308 | printf("%d stray interrupts, level %d\n", straycount, ipl); | 308 | printf("%d stray interrupts, level %d\n", straycount, ipl); | |
309 | for (n = 20; n; n--) { | 309 | for (n = 20; n; n--) { | |
310 | m = (logptr - n) & 255; | 310 | m = (logptr - n) & 255; | |
311 | printf("%02d: %d %08lx %08lx %d\n", n, log[m].ipl, | 311 | printf("%02d: %d %08lx %08lx %d\n", n, log[m].ipl, | |
312 | log[m].intrstat, log[m].intrmask, log[m].handled); | 312 | log[m].intrstat, log[m].intrmask, log[m].handled); | |
313 | } | 313 | } | |
314 | Debugger(); | 314 | Debugger(); | |
315 | straycount = 0; | 315 | straycount = 0; | |
316 | } | 316 | } | |
317 | #else | 317 | #else | |
318 | if (handled) | 318 | if (handled) | |
319 | straycount = 0; | 319 | straycount = 0; | |
320 | else if (++straycount > 50) | 320 | else if (++straycount > 50) | |
321 | panic("isr_dispatch_autovec: too many stray interrupts"); | 321 | panic("isr_dispatch_autovec: too many stray interrupts"); | |
322 | else { | 322 | else { | |
323 | char sbuf[256]; | 323 | char sbuf[256]; | |
324 | 324 | |||
325 | printf("isrdispatch_autovec: stray level %d interrupt\n", ipl); | 325 | printf("isrdispatch_autovec: stray level %d interrupt\n", ipl); | |
326 | 326 | |||
327 | snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, | 327 | snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, | |
328 | (*(volatile u_long *)IIOV(NEXT_P_INTRSTAT))); | 328 | (*(volatile u_long *)IIOV(NEXT_P_INTRSTAT))); | |
329 | printf(" *intrstat = %s\n", sbuf); | 329 | printf(" *intrstat = %s\n", sbuf); | |
330 | 330 | |||
331 | snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, | 331 | snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, | |
332 | (*(volatile u_long *)IIOV(NEXT_P_INTRMASK))); | 332 | (*(volatile u_long *)IIOV(NEXT_P_INTRMASK))); | |
333 | printf(" *intrmask = %s\n", sbuf); | 333 | printf(" *intrmask = %s\n", sbuf); | |
334 | } | 334 | } | |
335 | #endif | 335 | #endif | |
336 | 336 | |||
337 | idepth--; | 337 | idepth--; | |
338 | } | 338 | } | |
339 | 339 | |||
340 | bool | 340 | bool | |
341 | cpu_intr_p(void) | 341 | cpu_intr_p(void) | |
342 | { | 342 | { | |
343 | 343 | |||
344 | return idepth != 0; | 344 | return idepth != 0; | |
345 | } | 345 | } | |
346 | 346 | |||
347 | /* | 347 | /* | |
348 | * This is the dispatcher called by the low-level | 348 | * This is the dispatcher called by the low-level | |
349 | * assembly language vectored interrupt routine. | 349 | * assembly language vectored interrupt routine. | |
350 | */ | 350 | */ | |
351 | void | 351 | void | |
352 | isrdispatch_vectored(int ipl, struct clockframe *frame) | 352 | isrdispatch_vectored(int ipl, struct clockframe *frame) | |
353 | { | 353 | { | |
354 | struct isr_vectored *isr; | 354 | struct isr_vectored *isr; | |
355 | int vec; | 355 | int vec; | |
356 | 356 | |||
357 | vec = (frame->vec >> 2) - ISRVECTORED; | 357 | vec = (frame->vec >> 2) - ISRVECTORED; | |
358 | 358 | |||
359 | #ifdef DIAGNOSTIC | 359 | #ifdef DIAGNOSTIC | |
360 | if ((vec < 0) || (vec >= NISRVECTORED)) | 360 | if ((vec < 0) || (vec >= NISRVECTORED)) | |
361 | panic("isrdispatch_vectored: bad vec 0x%x", frame->vec); | 361 | panic("isrdispatch_vectored: bad vec 0x%x", frame->vec); | |
362 | #endif | 362 | #endif | |
363 | 363 | |||
364 | isr = &isr_vectored[vec]; | 364 | isr = &isr_vectored[vec]; | |
365 | 365 | |||
366 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | 366 | intrcnt[ipl]++; /* XXXSCW: Will go away soon */ | |
367 | next68k_irq_evcnt[ipl].ev_count++; | 367 | next68k_irq_evcnt[ipl].ev_count++; | |
368 | curcpu()->ci_data.cpu_nintr++; | 368 | curcpu()->ci_data.cpu_nintr++; | |
369 | 369 | |||
370 | if (isr->isr_func == NULL) { | 370 | if (isr->isr_func == NULL) { | |
371 | printf("isrdispatch_vectored: no handler for vec 0x%x\n", | 371 | printf("isrdispatch_vectored: no handler for vec 0x%x\n", | |
372 | frame->vec); | 372 | frame->vec); | |
373 | vectab[vec + ISRVECTORED] = badtrap; | 373 | vectab[vec + ISRVECTORED] = badtrap; | |
374 | return; | 374 | return; | |
375 | } | 375 | } | |
376 | 376 | |||
377 | /* | 377 | /* | |
378 | * Handler gets exception frame if argument is NULL. | 378 | * Handler gets exception frame if argument is NULL. | |
379 | */ | 379 | */ | |
380 | if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) | 380 | if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) | |
381 | printf("isrdispatch_vectored: vec 0x%x not claimed\n", | 381 | printf("isrdispatch_vectored: vec 0x%x not claimed\n", | |
382 | frame->vec); | 382 | frame->vec); | |
383 | else | 383 | else | |
384 | if (isr->isr_evcnt) | 384 | if (isr->isr_evcnt) | |
385 | isr->isr_evcnt->ev_count++; | 385 | isr->isr_evcnt->ev_count++; | |
386 | } | 386 | } | |
387 | 387 | |||
388 | #if 0 | 388 | #if 0 | |
389 | /* ARGSUSED */ | 389 | /* ARGSUSED */ | |
390 | static int | 390 | static int | |
391 | spurintr(void *arg) | 391 | spurintr(void *arg) | |
392 | { | 392 | { | |
393 | 393 | |||
394 | return (1); | 394 | return (1); | |
395 | } | 395 | } | |
396 | #endif | 396 | #endif | |
397 | 397 | |||
398 | const uint16_t ipl2psl_table[NIPL] = { | 398 | const uint16_t ipl2psl_table[NIPL] = { | |
399 | [IPL_NONE] = PSL_S | PSL_IPL0, | 399 | [IPL_NONE] = PSL_S | PSL_IPL0, | |
400 | [IPL_SOFTCLOCK] = PSL_S | PSL_IPL1, | 400 | [IPL_SOFTCLOCK] = PSL_S | PSL_IPL1, | |
401 | [IPL_SOFTNET] = PSL_S | PSL_IPL1, | 401 | [IPL_SOFTNET] = PSL_S | PSL_IPL1, | |
402 | [IPL_SOFTSERIAL] = PSL_S | PSL_IPL1, | 402 | [IPL_SOFTSERIAL] = PSL_S | PSL_IPL1, | |
403 | [IPL_SOFTBIO] = PSL_S | PSL_IPL1, | 403 | [IPL_SOFTBIO] = PSL_S | PSL_IPL1, | |
404 | [IPL_VM] = PSL_S | PSL_IPL6, | 404 | [IPL_VM] = PSL_S | PSL_IPL6, | |
405 | [IPL_SCHED] = PSL_S | PSL_IPL7, | 405 | [IPL_SCHED] = PSL_S | PSL_IPL7, | |
406 | [IPL_HIGH] = PSL_S | PSL_IPL7, | 406 | [IPL_HIGH] = PSL_S | PSL_IPL7, | |
407 | }; | 407 | }; |
--- src/sys/arch/sun3/sun3/clock.c 2013/09/07 15:56:11 1.64
+++ src/sys/arch/sun3/sun3/clock.c 2021/04/02 12:11:41 1.65
@@ -1,335 +1,335 @@ | @@ -1,335 +1,335 @@ | |||
1 | /* $NetBSD: clock.c,v 1.64 2013/09/07 15:56:11 tsutsui Exp $ */ | 1 | /* $NetBSD: clock.c,v 1.65 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1990, 1993 | 4 | * Copyright (c) 1982, 1990, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * the Systems Programming Group of the University of Utah Computer | 8 | * the Systems Programming Group of the University of Utah Computer | |
9 | * Science Department. | 9 | * Science Department. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * 3. Neither the name of the University nor the names of its contributors | 19 | * 3. Neither the name of the University nor the names of its contributors | |
20 | * may be used to endorse or promote products derived from this software | 20 | * may be used to endorse or promote products derived from this software | |
21 | * without specific prior written permission. | 21 | * without specific prior written permission. | |
22 | * | 22 | * | |
23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
33 | * SUCH DAMAGE. | 33 | * SUCH DAMAGE. | |
34 | * | 34 | * | |
35 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | 35 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | |
36 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | 36 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | /* | 39 | /* | |
40 | * Copyright (c) 1994 Gordon W. Ross | 40 | * Copyright (c) 1994 Gordon W. Ross | |
41 | * Copyright (c) 1993 Adam Glass | 41 | * Copyright (c) 1993 Adam Glass | |
42 | * Copyright (c) 1988 University of Utah. | 42 | * Copyright (c) 1988 University of Utah. | |
43 | * | 43 | * | |
44 | * This code is derived from software contributed to Berkeley by | 44 | * This code is derived from software contributed to Berkeley by | |
45 | * the Systems Programming Group of the University of Utah Computer | 45 | * the Systems Programming Group of the University of Utah Computer | |
46 | * Science Department. | 46 | * Science Department. | |
47 | * | 47 | * | |
48 | * Redistribution and use in source and binary forms, with or without | 48 | * Redistribution and use in source and binary forms, with or without | |
49 | * modification, are permitted provided that the following conditions | 49 | * modification, are permitted provided that the following conditions | |
50 | * are met: | 50 | * are met: | |
51 | * 1. Redistributions of source code must retain the above copyright | 51 | * 1. Redistributions of source code must retain the above copyright | |
52 | * notice, this list of conditions and the following disclaimer. | 52 | * notice, this list of conditions and the following disclaimer. | |
53 | * 2. Redistributions in binary form must reproduce the above copyright | 53 | * 2. Redistributions in binary form must reproduce the above copyright | |
54 | * notice, this list of conditions and the following disclaimer in the | 54 | * notice, this list of conditions and the following disclaimer in the | |
55 | * documentation and/or other materials provided with the distribution. | 55 | * documentation and/or other materials provided with the distribution. | |
56 | * 3. All advertising materials mentioning features or use of this software | 56 | * 3. All advertising materials mentioning features or use of this software | |
57 | * must display the following acknowledgement: | 57 | * must display the following acknowledgement: | |
58 | * This product includes software developed by the University of | 58 | * This product includes software developed by the University of | |
59 | * California, Berkeley and its contributors. | 59 | * California, Berkeley and its contributors. | |
60 | * 4. Neither the name of the University nor the names of its contributors | 60 | * 4. Neither the name of the University nor the names of its contributors | |
61 | * may be used to endorse or promote products derived from this software | 61 | * may be used to endorse or promote products derived from this software | |
62 | * without specific prior written permission. | 62 | * without specific prior written permission. | |
63 | * | 63 | * | |
64 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 64 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
65 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 65 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
66 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 66 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
68 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 68 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
69 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 69 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
70 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 70 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
71 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 71 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
72 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 72 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
73 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 73 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
74 | * SUCH DAMAGE. | 74 | * SUCH DAMAGE. | |
75 | * | 75 | * | |
76 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | 76 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | |
77 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | 77 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | |
78 | */ | 78 | */ | |
79 | 79 | |||
80 | /* | 80 | /* | |
81 | * Machine-dependent clock routines for the Intersil 7170: | 81 | * Machine-dependent clock routines for the Intersil 7170: | |
82 | * Original by Adam Glass; partially rewritten by Gordon Ross. | 82 | * Original by Adam Glass; partially rewritten by Gordon Ross. | |
83 | */ | 83 | */ | |
84 | 84 | |||
85 | #include <sys/cdefs.h> | 85 | #include <sys/cdefs.h> | |
86 | __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.64 2013/09/07 15:56:11 tsutsui Exp $"); | 86 | __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.65 2021/04/02 12:11:41 rin Exp $"); | |
87 | 87 | |||
88 | #include <sys/param.h> | 88 | #include <sys/param.h> | |
89 | #include <sys/systm.h> | 89 | #include <sys/systm.h> | |
90 | #include <sys/time.h> | 90 | #include <sys/time.h> | |
91 | #include <sys/kernel.h> | 91 | #include <sys/kernel.h> | |
92 | #include <sys/device.h> | 92 | #include <sys/device.h> | |
93 | 93 | |||
94 | #include <uvm/uvm_extern.h> | 94 | #include <uvm/uvm_extern.h> | |
95 | 95 | |||
96 | #include <m68k/asm_single.h> | 96 | #include <m68k/asm_single.h> | |
97 | 97 | |||
98 | #include <machine/autoconf.h> | 98 | #include <machine/autoconf.h> | |
99 | #include <machine/bus.h> | 99 | #include <machine/bus.h> | |
100 | #include <machine/cpu.h> | 100 | #include <machine/cpu.h> | |
101 | #include <machine/leds.h> | 101 | #include <machine/leds.h> | |
102 | 102 | |||
103 | #include <sun3/sun3/control.h> | 103 | #include <sun3/sun3/control.h> | |
104 | #include <sun3/sun3/interreg.h> | 104 | #include <sun3/sun3/interreg.h> | |
105 | #include <sun3/sun3/machdep.h> | 105 | #include <sun3/sun3/machdep.h> | |
106 | 106 | |||
107 | #include <dev/clock_subr.h> | 107 | #include <dev/clock_subr.h> | |
108 | #include <dev/ic/intersil7170reg.h> | 108 | #include <dev/ic/intersil7170reg.h> | |
109 | #include <dev/ic/intersil7170var.h> | 109 | #include <dev/ic/intersil7170var.h> | |
110 | 110 | |||
111 | extern int intrcnt[]; | 111 | extern u_int intrcnt[]; | |
112 | 112 | |||
113 | #define CLOCK_PRI 5 | 113 | #define CLOCK_PRI 5 | |
114 | #define IREG_CLK_BITS (IREG_CLOCK_ENAB_7 | IREG_CLOCK_ENAB_5) | 114 | #define IREG_CLK_BITS (IREG_CLOCK_ENAB_7 | IREG_CLOCK_ENAB_5) | |
115 | 115 | |||
116 | void _isr_clock(void); /* in locore.s */ | 116 | void _isr_clock(void); /* in locore.s */ | |
117 | void clock_intr(struct clockframe); | 117 | void clock_intr(struct clockframe); | |
118 | 118 | |||
119 | static volatile void *intersil_va; | 119 | static volatile void *intersil_va; | |
120 | 120 | |||
121 | #define intersil_clock ((volatile struct intersil7170 *)intersil_va) | 121 | #define intersil_clock ((volatile struct intersil7170 *)intersil_va) | |
122 | 122 | |||
123 | #define intersil_clear() (void)intersil_clock->clk_intr_reg | 123 | #define intersil_clear() (void)intersil_clock->clk_intr_reg | |
124 | 124 | |||
125 | static int oclock_match(device_t, cfdata_t, void *); | 125 | static int oclock_match(device_t, cfdata_t, void *); | |
126 | static void oclock_attach(device_t, device_t, void *); | 126 | static void oclock_attach(device_t, device_t, void *); | |
127 | 127 | |||
128 | CFATTACH_DECL_NEW(oclock, sizeof(struct intersil7170_softc), | 128 | CFATTACH_DECL_NEW(oclock, sizeof(struct intersil7170_softc), | |
129 | oclock_match, oclock_attach, NULL, NULL); | 129 | oclock_match, oclock_attach, NULL, NULL); | |
130 | 130 | |||
131 | static int | 131 | static int | |
132 | oclock_match(device_t parent, cfdata_t cf, void *aux) | 132 | oclock_match(device_t parent, cfdata_t cf, void *aux) | |
133 | { | 133 | { | |
134 | struct confargs *ca = aux; | 134 | struct confargs *ca = aux; | |
135 | 135 | |||
136 | /* This driver only supports one unit. */ | 136 | /* This driver only supports one unit. */ | |
137 | if (intersil_va) | 137 | if (intersil_va) | |
138 | return 0; | 138 | return 0; | |
139 | 139 | |||
140 | /* Make sure there is something there... */ | 140 | /* Make sure there is something there... */ | |
141 | if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1) | 141 | if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1) | |
142 | return 0; | 142 | return 0; | |
143 | 143 | |||
144 | /* Default interrupt priority. */ | 144 | /* Default interrupt priority. */ | |
145 | if (ca->ca_intpri == -1) | 145 | if (ca->ca_intpri == -1) | |
146 | ca->ca_intpri = CLOCK_PRI; | 146 | ca->ca_intpri = CLOCK_PRI; | |
147 | 147 | |||
148 | return 1; | 148 | return 1; | |
149 | } | 149 | } | |
150 | 150 | |||
151 | static void | 151 | static void | |
152 | oclock_attach(device_t parent, device_t self, void *aux) | 152 | oclock_attach(device_t parent, device_t self, void *aux) | |
153 | { | 153 | { | |
154 | struct intersil7170_softc *sc = device_private(self); | 154 | struct intersil7170_softc *sc = device_private(self); | |
155 | struct confargs *ca = aux; | 155 | struct confargs *ca = aux; | |
156 | 156 | |||
157 | sc->sc_dev = self; | 157 | sc->sc_dev = self; | |
158 | 158 | |||
159 | /* Get a mapping for it. */ | 159 | /* Get a mapping for it. */ | |
160 | sc->sc_bst = ca->ca_bustag; | 160 | sc->sc_bst = ca->ca_bustag; | |
161 | if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct intersil7170), | 161 | if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct intersil7170), | |
162 | 0, &sc->sc_bsh) != 0) { | 162 | 0, &sc->sc_bsh) != 0) { | |
163 | aprint_error(": can't map registers\n"); | 163 | aprint_error(": can't map registers\n"); | |
164 | return; | 164 | return; | |
165 | } | 165 | } | |
166 | 166 | |||
167 | intersil_va = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); | 167 | intersil_va = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); | |
168 | 168 | |||
169 | /* | 169 | /* | |
170 | * Set the clock to the correct interrupt rate, but | 170 | * Set the clock to the correct interrupt rate, but | |
171 | * do not enable the interrupt until cpu_initclocks. | 171 | * do not enable the interrupt until cpu_initclocks. | |
172 | * XXX: Actually, the interrupt_reg should be zero | 172 | * XXX: Actually, the interrupt_reg should be zero | |
173 | * at this point, so the clock interrupts should not | 173 | * at this point, so the clock interrupts should not | |
174 | * affect us, but we need to set the rate... | 174 | * affect us, but we need to set the rate... | |
175 | */ | 175 | */ | |
176 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, INTERSIL_ICMD, | 176 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, INTERSIL_ICMD, | |
177 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE)); | 177 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE)); | |
178 | (void)bus_space_read_1(sc->sc_bst, sc->sc_bsh, INTERSIL_IINTR); | 178 | (void)bus_space_read_1(sc->sc_bst, sc->sc_bsh, INTERSIL_IINTR); | |
179 | 179 | |||
180 | /* Set the clock to 100 Hz, but do not enable it yet. */ | 180 | /* Set the clock to 100 Hz, but do not enable it yet. */ | |
181 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, | 181 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, | |
182 | INTERSIL_IINTR, INTERSIL_INTER_CSECONDS); | 182 | INTERSIL_IINTR, INTERSIL_INTER_CSECONDS); | |
183 | 183 | |||
184 | sc->sc_year0 = 1968; | 184 | sc->sc_year0 = 1968; | |
185 | intersil7170_attach(sc); | 185 | intersil7170_attach(sc); | |
186 | 186 | |||
187 | aprint_normal("\n"); | 187 | aprint_normal("\n"); | |
188 | 188 | |||
189 | /* | 189 | /* | |
190 | * Can not hook up the ISR until cpu_initclocks() | 190 | * Can not hook up the ISR until cpu_initclocks() | |
191 | * because hardclock is not ready until then. | 191 | * because hardclock is not ready until then. | |
192 | * For now, the handler is _isr_autovec(), which | 192 | * For now, the handler is _isr_autovec(), which | |
193 | * will complain if it gets clock interrupts. | 193 | * will complain if it gets clock interrupts. | |
194 | */ | 194 | */ | |
195 | } | 195 | } | |
196 | 196 | |||
197 | /* | 197 | /* | |
198 | * Set and/or clear the desired clock bits in the interrupt | 198 | * Set and/or clear the desired clock bits in the interrupt | |
199 | * register. We have to be extremely careful that we do it | 199 | * register. We have to be extremely careful that we do it | |
200 | * in such a manner that we don't get ourselves lost. | 200 | * in such a manner that we don't get ourselves lost. | |
201 | * XXX: Watch out! It's really easy to break this! | 201 | * XXX: Watch out! It's really easy to break this! | |
202 | */ | 202 | */ | |
203 | void | 203 | void | |
204 | set_clk_mode(u_char on, u_char off, int enable_clk) | 204 | set_clk_mode(u_char on, u_char off, int enable_clk) | |
205 | { | 205 | { | |
206 | u_char interreg; | 206 | u_char interreg; | |
207 | 207 | |||
208 | /* | 208 | /* | |
209 | * If we have not yet mapped the register, | 209 | * If we have not yet mapped the register, | |
210 | * then we do not want to do any of this... | 210 | * then we do not want to do any of this... | |
211 | */ | 211 | */ | |
212 | if (!interrupt_reg) | 212 | if (!interrupt_reg) | |
213 | return; | 213 | return; | |
214 | 214 | |||
215 | #ifdef DIAGNOSTIC | 215 | #ifdef DIAGNOSTIC | |
216 | /* Assertion: were are at splhigh! */ | 216 | /* Assertion: were are at splhigh! */ | |
217 | if ((getsr() & PSL_IPL) < PSL_IPL7) | 217 | if ((getsr() & PSL_IPL) < PSL_IPL7) | |
218 | panic("set_clk_mode: bad ipl"); | 218 | panic("set_clk_mode: bad ipl"); | |
219 | #endif | 219 | #endif | |
220 | 220 | |||
221 | /* | 221 | /* | |
222 | * make sure that we are only playing w/ | 222 | * make sure that we are only playing w/ | |
223 | * clock interrupt register bits | 223 | * clock interrupt register bits | |
224 | */ | 224 | */ | |
225 | on &= IREG_CLK_BITS; | 225 | on &= IREG_CLK_BITS; | |
226 | off &= IREG_CLK_BITS; | 226 | off &= IREG_CLK_BITS; | |
227 | 227 | |||
228 | /* First, turn off the "master" enable bit. */ | 228 | /* First, turn off the "master" enable bit. */ | |
229 | single_inst_bclr_b(*interrupt_reg, IREG_ALL_ENAB); | 229 | single_inst_bclr_b(*interrupt_reg, IREG_ALL_ENAB); | |
230 | 230 | |||
231 | /* | 231 | /* | |
232 | * Save the current interrupt register clock bits, | 232 | * Save the current interrupt register clock bits, | |
233 | * and turn off/on the requested bits in the copy. | 233 | * and turn off/on the requested bits in the copy. | |
234 | */ | 234 | */ | |
235 | interreg = *interrupt_reg & IREG_CLK_BITS; | 235 | interreg = *interrupt_reg & IREG_CLK_BITS; | |
236 | interreg &= ~off; | 236 | interreg &= ~off; | |
237 | interreg |= on; | 237 | interreg |= on; | |
238 | 238 | |||
239 | /* Clear the CLK5 and CLK7 bits to clear the flip-flops. */ | 239 | /* Clear the CLK5 and CLK7 bits to clear the flip-flops. */ | |
240 | single_inst_bclr_b(*interrupt_reg, IREG_CLK_BITS); | 240 | single_inst_bclr_b(*interrupt_reg, IREG_CLK_BITS); | |
241 | 241 | |||
242 | if (intersil_va) { | 242 | if (intersil_va) { | |
243 | /* | 243 | /* | |
244 | * Then disable clock interrupts, and read the clock's | 244 | * Then disable clock interrupts, and read the clock's | |
245 | * interrupt register to clear any pending signals there. | 245 | * interrupt register to clear any pending signals there. | |
246 | */ | 246 | */ | |
247 | intersil_clock->clk_cmd_reg = | 247 | intersil_clock->clk_cmd_reg = | |
248 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); | 248 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); | |
249 | intersil_clear(); | 249 | intersil_clear(); | |
250 | } | 250 | } | |
251 | 251 | |||
252 | /* Set the requested bits in the interrupt register. */ | 252 | /* Set the requested bits in the interrupt register. */ | |
253 | single_inst_bset_b(*interrupt_reg, interreg); | 253 | single_inst_bset_b(*interrupt_reg, interreg); | |
254 | 254 | |||
255 | /* Turn the clock back on (maybe) */ | 255 | /* Turn the clock back on (maybe) */ | |
256 | if (intersil_va && enable_clk) | 256 | if (intersil_va && enable_clk) | |
257 | intersil_clock->clk_cmd_reg = | 257 | intersil_clock->clk_cmd_reg = | |
258 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); | 258 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); | |
259 | 259 | |||
260 | /* Finally, turn the "master" enable back on. */ | 260 | /* Finally, turn the "master" enable back on. */ | |
261 | single_inst_bset_b(*interrupt_reg, IREG_ALL_ENAB); | 261 | single_inst_bset_b(*interrupt_reg, IREG_ALL_ENAB); | |
262 | } | 262 | } | |
263 | 263 | |||
264 | /* | 264 | /* | |
265 | * Set up the real-time clock (enable clock interrupts). | 265 | * Set up the real-time clock (enable clock interrupts). | |
266 | * Leave stathz 0 since there is no secondary clock available. | 266 | * Leave stathz 0 since there is no secondary clock available. | |
267 | * Note that clock interrupts MUST STAY DISABLED until here. | 267 | * Note that clock interrupts MUST STAY DISABLED until here. | |
268 | */ | 268 | */ | |
269 | void | 269 | void | |
270 | cpu_initclocks(void) | 270 | cpu_initclocks(void) | |
271 | { | 271 | { | |
272 | int s; | 272 | int s; | |
273 | 273 | |||
274 | s = splhigh(); | 274 | s = splhigh(); | |
275 | 275 | |||
276 | /* Install isr (in locore.s) that calls clock_intr(). */ | 276 | /* Install isr (in locore.s) that calls clock_intr(). */ | |
277 | isr_add_custom(CLOCK_PRI, (void *)_isr_clock); | 277 | isr_add_custom(CLOCK_PRI, (void *)_isr_clock); | |
278 | 278 | |||
279 | /* Now enable the clock at level 5 in the interrupt reg. */ | 279 | /* Now enable the clock at level 5 in the interrupt reg. */ | |
280 | set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1); | 280 | set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1); | |
281 | 281 | |||
282 | splx(s); | 282 | splx(s); | |
283 | } | 283 | } | |
284 | 284 | |||
285 | /* | 285 | /* | |
286 | * This doesn't need to do anything, as we have only one timer and | 286 | * This doesn't need to do anything, as we have only one timer and | |
287 | * profhz==stathz==hz. | 287 | * profhz==stathz==hz. | |
288 | */ | 288 | */ | |
289 | void | 289 | void | |
290 | setstatclockrate(int newhz) | 290 | setstatclockrate(int newhz) | |
291 | { | 291 | { | |
292 | 292 | |||
293 | /* nothing */ | 293 | /* nothing */ | |
294 | } | 294 | } | |
295 | 295 | |||
296 | /* | 296 | /* | |
297 | * This is called by the "custom" interrupt handler. | 297 | * This is called by the "custom" interrupt handler. | |
298 | * Note that we can get ZS interrupts while this runs, | 298 | * Note that we can get ZS interrupts while this runs, | |
299 | * and zshard may touch the interrupt_reg, so we must | 299 | * and zshard may touch the interrupt_reg, so we must | |
300 | * be careful to use the single_inst_* macros to modify | 300 | * be careful to use the single_inst_* macros to modify | |
301 | * the interrupt register atomically. | 301 | * the interrupt register atomically. | |
302 | */ | 302 | */ | |
303 | void | 303 | void | |
304 | clock_intr(struct clockframe cf) | 304 | clock_intr(struct clockframe cf) | |
305 | { | 305 | { | |
306 | 306 | |||
307 | idepth++; | 307 | idepth++; | |
308 | 308 | |||
309 | /* Read the clock interrupt register. */ | 309 | /* Read the clock interrupt register. */ | |
310 | intersil_clear(); | 310 | intersil_clear(); | |
311 | 311 | |||
312 | /* Pulse the clock intr. enable low. */ | 312 | /* Pulse the clock intr. enable low. */ | |
313 | single_inst_bclr_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | 313 | single_inst_bclr_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | |
314 | single_inst_bset_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | 314 | single_inst_bset_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | |
315 | 315 | |||
316 | /* Read the clock intr. reg. AGAIN! */ | 316 | /* Read the clock intr. reg. AGAIN! */ | |
317 | intersil_clear(); | 317 | intersil_clear(); | |
318 | 318 | |||
319 | intrcnt[CLOCK_PRI]++; | 319 | intrcnt[CLOCK_PRI]++; | |
320 | curcpu()->ci_data.cpu_nintr++; | 320 | curcpu()->ci_data.cpu_nintr++; | |
321 | 321 | |||
322 | { /* Entertainment! */ | 322 | { /* Entertainment! */ | |
323 | #ifdef LED_IDLE_CHECK | 323 | #ifdef LED_IDLE_CHECK | |
324 | /* With this option, LEDs move only when CPU is idle. */ | 324 | /* With this option, LEDs move only when CPU is idle. */ | |
325 | extern char _Idle[]; /* locore.s */ | 325 | extern char _Idle[]; /* locore.s */ | |
326 | if (cf.cf_pc == (long)_Idle) | 326 | if (cf.cf_pc == (long)_Idle) | |
327 | #endif | 327 | #endif | |
328 | leds_intr(); | 328 | leds_intr(); | |
329 | } | 329 | } | |
330 | 330 | |||
331 | /* Call common clock interrupt handler. */ | 331 | /* Call common clock interrupt handler. */ | |
332 | hardclock(&cf); | 332 | hardclock(&cf); | |
333 | 333 | |||
334 | idepth--; | 334 | idepth--; | |
335 | } | 335 | } |
--- src/sys/arch/sun3/sun3x/clock.c 2013/09/06 17:43:19 1.40
+++ src/sys/arch/sun3/sun3x/clock.c 2021/04/02 12:11:41 1.41
@@ -1,456 +1,456 @@ | @@ -1,456 +1,456 @@ | |||
1 | /* $NetBSD: clock.c,v 1.40 2013/09/06 17:43:19 tsutsui Exp $ */ | 1 | /* $NetBSD: clock.c,v 1.41 2021/04/02 12:11:41 rin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1990, 1993 | 4 | * Copyright (c) 1982, 1990, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * the Systems Programming Group of the University of Utah Computer | 8 | * the Systems Programming Group of the University of Utah Computer | |
9 | * Science Department. | 9 | * Science Department. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * 3. Neither the name of the University nor the names of its contributors | 19 | * 3. Neither the name of the University nor the names of its contributors | |
20 | * may be used to endorse or promote products derived from this software | 20 | * may be used to endorse or promote products derived from this software | |
21 | * without specific prior written permission. | 21 | * without specific prior written permission. | |
22 | * | 22 | * | |
23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
33 | * SUCH DAMAGE. | 33 | * SUCH DAMAGE. | |
34 | * | 34 | * | |
35 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | 35 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | |
36 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | 36 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | /* | 39 | /* | |
40 | * Copyright (c) 1994 Gordon W. Ross | 40 | * Copyright (c) 1994 Gordon W. Ross | |
41 | * Copyright (c) 1993 Adam Glass | 41 | * Copyright (c) 1993 Adam Glass | |
42 | * Copyright (c) 1988 University of Utah. | 42 | * Copyright (c) 1988 University of Utah. | |
43 | * | 43 | * | |
44 | * This code is derived from software contributed to Berkeley by | 44 | * This code is derived from software contributed to Berkeley by | |
45 | * the Systems Programming Group of the University of Utah Computer | 45 | * the Systems Programming Group of the University of Utah Computer | |
46 | * Science Department. | 46 | * Science Department. | |
47 | * | 47 | * | |
48 | * Redistribution and use in source and binary forms, with or without | 48 | * Redistribution and use in source and binary forms, with or without | |
49 | * modification, are permitted provided that the following conditions | 49 | * modification, are permitted provided that the following conditions | |
50 | * are met: | 50 | * are met: | |
51 | * 1. Redistributions of source code must retain the above copyright | 51 | * 1. Redistributions of source code must retain the above copyright | |
52 | * notice, this list of conditions and the following disclaimer. | 52 | * notice, this list of conditions and the following disclaimer. | |
53 | * 2. Redistributions in binary form must reproduce the above copyright | 53 | * 2. Redistributions in binary form must reproduce the above copyright | |
54 | * notice, this list of conditions and the following disclaimer in the | 54 | * notice, this list of conditions and the following disclaimer in the | |
55 | * documentation and/or other materials provided with the distribution. | 55 | * documentation and/or other materials provided with the distribution. | |
56 | * 3. All advertising materials mentioning features or use of this software | 56 | * 3. All advertising materials mentioning features or use of this software | |
57 | * must display the following acknowledgement: | 57 | * must display the following acknowledgement: | |
58 | * This product includes software developed by the University of | 58 | * This product includes software developed by the University of | |
59 | * California, Berkeley and its contributors. | 59 | * California, Berkeley and its contributors. | |
60 | * 4. Neither the name of the University nor the names of its contributors | 60 | * 4. Neither the name of the University nor the names of its contributors | |
61 | * may be used to endorse or promote products derived from this software | 61 | * may be used to endorse or promote products derived from this software | |
62 | * without specific prior written permission. | 62 | * without specific prior written permission. | |
63 | * | 63 | * | |
64 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 64 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
65 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 65 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
66 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 66 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 67 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
68 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 68 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
69 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 69 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
70 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 70 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
71 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 71 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
72 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 72 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
73 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 73 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
74 | * SUCH DAMAGE. | 74 | * SUCH DAMAGE. | |
75 | * | 75 | * | |
76 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | 76 | * from: Utah Hdr: clock.c 1.18 91/01/21$ | |
77 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | 77 | * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 | |
78 | */ | 78 | */ | |
79 | 79 | |||
80 | /* | 80 | /* | |
81 | * Machine-dependent clock routines. Sun3X machines may have | 81 | * Machine-dependent clock routines. Sun3X machines may have | |
82 | * either the Mostek 48T02 or the Intersil 7170 clock. | 82 | * either the Mostek 48T02 or the Intersil 7170 clock. | |
83 | * | 83 | * | |
84 | * It is tricky to determine which you have, because there is | 84 | * It is tricky to determine which you have, because there is | |
85 | * always something responding at the address where the Mostek | 85 | * always something responding at the address where the Mostek | |
86 | * clock might be found: either a Mostek or plain-old EEPROM. | 86 | * clock might be found: either a Mostek or plain-old EEPROM. | |
87 | * Therefore, we cheat. If we find an Intersil clock, assume | 87 | * Therefore, we cheat. If we find an Intersil clock, assume | |
88 | * that what responds at the end of the EEPROM space is just | 88 | * that what responds at the end of the EEPROM space is just | |
89 | * plain-old EEPROM (not a Mostek clock). Worse, there are | 89 | * plain-old EEPROM (not a Mostek clock). Worse, there are | |
90 | * H/W problems with probing for an Intersil on the 3/80, so | 90 | * H/W problems with probing for an Intersil on the 3/80, so | |
91 | * on that machine we "know" there is a Mostek clock. | 91 | * on that machine we "know" there is a Mostek clock. | |
92 | * | 92 | * | |
93 | * Note that the probing algorithm described above requires | 93 | * Note that the probing algorithm described above requires | |
94 | * that we probe the intersil before we probe the mostek! | 94 | * that we probe the intersil before we probe the mostek! | |
95 | */ | 95 | */ | |
96 | 96 | |||
97 | #include <sys/cdefs.h> | 97 | #include <sys/cdefs.h> | |
98 | __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.40 2013/09/06 17:43:19 tsutsui Exp $"); | 98 | __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.41 2021/04/02 12:11:41 rin Exp $"); | |
99 | 99 | |||
100 | #include <sys/param.h> | 100 | #include <sys/param.h> | |
101 | #include <sys/systm.h> | 101 | #include <sys/systm.h> | |
102 | #include <sys/time.h> | 102 | #include <sys/time.h> | |
103 | #include <sys/kernel.h> | 103 | #include <sys/kernel.h> | |
104 | #include <sys/device.h> | 104 | #include <sys/device.h> | |
105 | 105 | |||
106 | #include <uvm/uvm_extern.h> | 106 | #include <uvm/uvm_extern.h> | |
107 | 107 | |||
108 | #include <m68k/asm_single.h> | 108 | #include <m68k/asm_single.h> | |
109 | 109 | |||
110 | #include <machine/autoconf.h> | 110 | #include <machine/autoconf.h> | |
111 | #include <machine/bus.h> | 111 | #include <machine/bus.h> | |
112 | #include <machine/cpu.h> | 112 | #include <machine/cpu.h> | |
113 | #include <machine/idprom.h> | 113 | #include <machine/idprom.h> | |
114 | #include <machine/leds.h> | 114 | #include <machine/leds.h> | |
115 | 115 | |||
116 | #include <dev/clock_subr.h> | 116 | #include <dev/clock_subr.h> | |
117 | #include <dev/ic/intersil7170reg.h> | 117 | #include <dev/ic/intersil7170reg.h> | |
118 | #include <dev/ic/intersil7170var.h> | 118 | #include <dev/ic/intersil7170var.h> | |
119 | #include <dev/ic/mk48txxreg.h> | 119 | #include <dev/ic/mk48txxreg.h> | |
120 | #include <dev/ic/mk48txxvar.h> | 120 | #include <dev/ic/mk48txxvar.h> | |
121 | 121 | |||
122 | #include <sun3/sun3/machdep.h> | 122 | #include <sun3/sun3/machdep.h> | |
123 | #include <sun3/sun3/interreg.h> | 123 | #include <sun3/sun3/interreg.h> | |
124 | 124 | |||
125 | extern int intrcnt[]; | 125 | extern u_int intrcnt[]; | |
126 | 126 | |||
127 | #define SUN3_470 Yes | 127 | #define SUN3_470 Yes | |
128 | 128 | |||
129 | #define CLOCK_PRI 5 | 129 | #define CLOCK_PRI 5 | |
130 | #define IREG_CLK_BITS (IREG_CLOCK_ENAB_7 | IREG_CLOCK_ENAB_5) | 130 | #define IREG_CLK_BITS (IREG_CLOCK_ENAB_7 | IREG_CLOCK_ENAB_5) | |
131 | 131 | |||
132 | #define MKCLOCK_REG_OFFSET (MK48T02_CLKOFF + MK48TXX_ICSR) | 132 | #define MKCLOCK_REG_OFFSET (MK48T02_CLKOFF + MK48TXX_ICSR) | |
133 | 133 | |||
134 | /* | 134 | /* | |
135 | * Only one of these two variables should be non-zero after | 135 | * Only one of these two variables should be non-zero after | |
136 | * autoconfiguration determines which clock we have. | 136 | * autoconfiguration determines which clock we have. | |
137 | */ | 137 | */ | |
138 | static volatile void *intersil_va; | 138 | static volatile void *intersil_va; | |
139 | static volatile void *mostek_clk_va; | 139 | static volatile void *mostek_clk_va; | |
140 | 140 | |||
141 | void _isr_clock(void); /* in locore.s */ | 141 | void _isr_clock(void); /* in locore.s */ | |
142 | void clock_intr(struct clockframe); | 142 | void clock_intr(struct clockframe); | |
143 | 143 | |||
144 | 144 | |||
145 | static int clock_match(device_t, cfdata_t, void *); | 145 | static int clock_match(device_t, cfdata_t, void *); | |
146 | static void clock_attach(device_t, device_t, void *); | 146 | static void clock_attach(device_t, device_t, void *); | |
147 | 147 | |||
148 | CFATTACH_DECL_NEW(clock, sizeof(struct mk48txx_softc), | 148 | CFATTACH_DECL_NEW(clock, sizeof(struct mk48txx_softc), | |
149 | clock_match, clock_attach, NULL, NULL); | 149 | clock_match, clock_attach, NULL, NULL); | |
150 | 150 | |||
151 | #ifdef SUN3_470 | 151 | #ifdef SUN3_470 | |
152 | 152 | |||
153 | #define intersil_clock ((volatile struct intersil7170 *)intersil_va) | 153 | #define intersil_clock ((volatile struct intersil7170 *)intersil_va) | |
154 | 154 | |||
155 | #define intersil_clear() (void)intersil_clock->clk_intr_reg | 155 | #define intersil_clear() (void)intersil_clock->clk_intr_reg | |
156 | 156 | |||
157 | static int oclock_match(device_t, cfdata_t, void *); | 157 | static int oclock_match(device_t, cfdata_t, void *); | |
158 | static void oclock_attach(device_t, device_t, void *); | 158 | static void oclock_attach(device_t, device_t, void *); | |
159 | 159 | |||
160 | CFATTACH_DECL_NEW(oclock, sizeof(struct intersil7170_softc), | 160 | CFATTACH_DECL_NEW(oclock, sizeof(struct intersil7170_softc), | |
161 | oclock_match, oclock_attach, NULL, NULL); | 161 | oclock_match, oclock_attach, NULL, NULL); | |
162 | 162 | |||
163 | 163 | |||
164 | /* | 164 | /* | |
165 | * Is there an intersil clock? | 165 | * Is there an intersil clock? | |
166 | */ | 166 | */ | |
167 | static int | 167 | static int | |
168 | oclock_match(device_t parent, cfdata_t cf, void *aux) | 168 | oclock_match(device_t parent, cfdata_t cf, void *aux) | |
169 | { | 169 | { | |
170 | struct confargs *ca = aux; | 170 | struct confargs *ca = aux; | |
171 | 171 | |||
172 | /* This driver only supports one unit. */ | 172 | /* This driver only supports one unit. */ | |
173 | if (intersil_va) | 173 | if (intersil_va) | |
174 | return 0; | 174 | return 0; | |
175 | 175 | |||
176 | /* | 176 | /* | |
177 | * The 3/80 can not probe the Intersil absent, | 177 | * The 3/80 can not probe the Intersil absent, | |
178 | * but it never has one, so "just say no." | 178 | * but it never has one, so "just say no." | |
179 | */ | 179 | */ | |
180 | if (cpu_machine_id == ID_SUN3X_80) | 180 | if (cpu_machine_id == ID_SUN3X_80) | |
181 | return 0; | 181 | return 0; | |
182 | 182 | |||
183 | /* OK, really probe for the Intersil. */ | 183 | /* OK, really probe for the Intersil. */ | |
184 | if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1) | 184 | if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1) | |
185 | return 0; | 185 | return 0; | |
186 | 186 | |||
187 | /* Default interrupt priority. */ | 187 | /* Default interrupt priority. */ | |
188 | if (ca->ca_intpri == -1) | 188 | if (ca->ca_intpri == -1) | |
189 | ca->ca_intpri = CLOCK_PRI; | 189 | ca->ca_intpri = CLOCK_PRI; | |
190 | 190 | |||
191 | return 1; | 191 | return 1; | |
192 | } | 192 | } | |
193 | 193 | |||
194 | /* | 194 | /* | |
195 | * Attach the intersil clock. | 195 | * Attach the intersil clock. | |
196 | */ | 196 | */ | |
197 | static void | 197 | static void | |
198 | oclock_attach(device_t parent, device_t self, void *aux) | 198 | oclock_attach(device_t parent, device_t self, void *aux) | |
199 | { | 199 | { | |
200 | struct intersil7170_softc *sc = device_private(self); | 200 | struct intersil7170_softc *sc = device_private(self); | |
201 | struct confargs *ca = aux; | 201 | struct confargs *ca = aux; | |
202 | 202 | |||
203 | sc->sc_dev = self; | 203 | sc->sc_dev = self; | |
204 | 204 | |||
205 | /* Get a mapping for it. */ | 205 | /* Get a mapping for it. */ | |
206 | sc->sc_bst = ca->ca_bustag; | 206 | sc->sc_bst = ca->ca_bustag; | |
207 | if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct intersil7170), | 207 | if (bus_space_map(sc->sc_bst, ca->ca_paddr, sizeof(struct intersil7170), | |
208 | 0, &sc->sc_bsh) != 0) { | 208 | 0, &sc->sc_bsh) != 0) { | |
209 | aprint_error(": can't map registers\n"); | 209 | aprint_error(": can't map registers\n"); | |
210 | return; | 210 | return; | |
211 | } | 211 | } | |
212 | 212 | |||
213 | intersil_va = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); | 213 | intersil_va = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); | |
214 | 214 | |||
215 | #ifdef DIAGNOSTIC | 215 | #ifdef DIAGNOSTIC | |
216 | /* Verify correct probe order... */ | 216 | /* Verify correct probe order... */ | |
217 | if (mostek_clk_va) { | 217 | if (mostek_clk_va) { | |
218 | mostek_clk_va = NULL; | 218 | mostek_clk_va = NULL; | |
219 | aprint_normal("\n"); | 219 | aprint_normal("\n"); | |
220 | aprint_error_dev(self, "warning - mostek found also!\n"); | 220 | aprint_error_dev(self, "warning - mostek found also!\n"); | |
221 | } | 221 | } | |
222 | #endif | 222 | #endif | |
223 | 223 | |||
224 | /* | 224 | /* | |
225 | * Set the clock to the correct interrupt rate, but | 225 | * Set the clock to the correct interrupt rate, but | |
226 | * do not enable the interrupt until cpu_initclocks. | 226 | * do not enable the interrupt until cpu_initclocks. | |
227 | * XXX: Actually, the interrupt_reg should be zero | 227 | * XXX: Actually, the interrupt_reg should be zero | |
228 | * at this point, so the clock interrupts should not | 228 | * at this point, so the clock interrupts should not | |
229 | * affect us, but we need to set the rate... | 229 | * affect us, but we need to set the rate... | |
230 | */ | 230 | */ | |
231 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, INTERSIL_ICMD, | 231 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, INTERSIL_ICMD, | |
232 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE)); | 232 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE)); | |
233 | (void)bus_space_read_1(sc->sc_bst, sc->sc_bsh, INTERSIL_IINTR); | 233 | (void)bus_space_read_1(sc->sc_bst, sc->sc_bsh, INTERSIL_IINTR); | |
234 | 234 | |||
235 | /* Set the clock to 100 Hz, but do not enable it yet. */ | 235 | /* Set the clock to 100 Hz, but do not enable it yet. */ | |
236 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, | 236 | bus_space_write_1(sc->sc_bst, sc->sc_bsh, | |
237 | INTERSIL_IINTR, INTERSIL_INTER_CSECONDS); | 237 | INTERSIL_IINTR, INTERSIL_INTER_CSECONDS); | |
238 | 238 | |||
239 | sc->sc_year0 = 1968; | 239 | sc->sc_year0 = 1968; | |
240 | intersil7170_attach(sc); | 240 | intersil7170_attach(sc); | |
241 | 241 | |||
242 | aprint_normal("\n"); | 242 | aprint_normal("\n"); | |
243 | 243 | |||
244 | /* | 244 | /* | |
245 | * Can not hook up the ISR until cpu_initclocks() | 245 | * Can not hook up the ISR until cpu_initclocks() | |
246 | * because hardclock is not ready until then. | 246 | * because hardclock is not ready until then. | |
247 | * For now, the handler is _isr_autovec(), which | 247 | * For now, the handler is _isr_autovec(), which | |
248 | * will complain if it gets clock interrupts. | 248 | * will complain if it gets clock interrupts. | |
249 | */ | 249 | */ | |
250 | } | 250 | } | |
251 | #endif /* SUN3_470 */ | 251 | #endif /* SUN3_470 */ | |
252 | 252 | |||
253 | 253 | |||
254 | /* | 254 | /* | |
255 | * Is there a Mostek clock? Hard to tell... | 255 | * Is there a Mostek clock? Hard to tell... | |
256 | * (See comment at top of this file.) | 256 | * (See comment at top of this file.) | |
257 | */ | 257 | */ | |
258 | static int | 258 | static int | |
259 | clock_match(device_t parent, cfdata_t cf, void *args) | 259 | clock_match(device_t parent, cfdata_t cf, void *args) | |
260 | { | 260 | { | |
261 | struct confargs *ca = args; | 261 | struct confargs *ca = args; | |
262 | 262 | |||
263 | /* This driver only supports one unit. */ | 263 | /* This driver only supports one unit. */ | |
264 | if (mostek_clk_va) | 264 | if (mostek_clk_va) | |
265 | return 0; | 265 | return 0; | |
266 | 266 | |||
267 | /* If intersil was found, use that. */ | 267 | /* If intersil was found, use that. */ | |
268 | if (intersil_va) | 268 | if (intersil_va) | |
269 | return 0; | 269 | return 0; | |
270 | /* Else assume a Mostek is there... */ | 270 | /* Else assume a Mostek is there... */ | |
271 | 271 | |||
272 | /* Default interrupt priority. */ | 272 | /* Default interrupt priority. */ | |
273 | if (ca->ca_intpri == -1) | 273 | if (ca->ca_intpri == -1) | |
274 | ca->ca_intpri = CLOCK_PRI; | 274 | ca->ca_intpri = CLOCK_PRI; | |
275 | 275 | |||
276 | return 1; | 276 | return 1; | |
277 | } | 277 | } | |
278 | 278 | |||
279 | /* | 279 | /* | |
280 | * Attach the mostek clock. | 280 | * Attach the mostek clock. | |
281 | */ | 281 | */ | |
282 | static void | 282 | static void | |
283 | clock_attach(device_t parent, device_t self, void *aux) | 283 | clock_attach(device_t parent, device_t self, void *aux) | |
284 | { | 284 | { | |
285 | struct mk48txx_softc *sc = device_private(self); | 285 | struct mk48txx_softc *sc = device_private(self); | |
286 | struct confargs *ca = aux; | 286 | struct confargs *ca = aux; | |
287 | 287 | |||
288 | sc->sc_dev = self; | 288 | sc->sc_dev = self; | |
289 | sc->sc_bst = ca->ca_bustag; | 289 | sc->sc_bst = ca->ca_bustag; | |
290 | if (bus_space_map(sc->sc_bst, ca->ca_paddr - MKCLOCK_REG_OFFSET, | 290 | if (bus_space_map(sc->sc_bst, ca->ca_paddr - MKCLOCK_REG_OFFSET, | |
291 | MK48T02_CLKSZ, 0, &sc->sc_bsh) != 0) { | 291 | MK48T02_CLKSZ, 0, &sc->sc_bsh) != 0) { | |
292 | aprint_error(": can't map device space\n"); | 292 | aprint_error(": can't map device space\n"); | |
293 | return; | 293 | return; | |
294 | } | 294 | } | |
295 | 295 | |||
296 | mostek_clk_va = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); | 296 | mostek_clk_va = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); | |
297 | 297 | |||
298 | sc->sc_model = "mk48t02"; | 298 | sc->sc_model = "mk48t02"; | |
299 | sc->sc_year0 = 1968; | 299 | sc->sc_year0 = 1968; | |
300 | 300 | |||
301 | mk48txx_attach(sc); | 301 | mk48txx_attach(sc); | |
302 | 302 | |||
303 | aprint_normal("\n"); | 303 | aprint_normal("\n"); | |
304 | } | 304 | } | |
305 | 305 | |||
306 | /* | 306 | /* | |
307 | * Set and/or clear the desired clock bits in the interrupt | 307 | * Set and/or clear the desired clock bits in the interrupt | |
308 | * register. We have to be extremely careful that we do it | 308 | * register. We have to be extremely careful that we do it | |
309 | * in such a manner that we don't get ourselves lost. | 309 | * in such a manner that we don't get ourselves lost. | |
310 | * XXX: Watch out! It's really easy to break this! | 310 | * XXX: Watch out! It's really easy to break this! | |
311 | */ | 311 | */ | |
312 | void | 312 | void | |
313 | set_clk_mode(u_char on, u_char off, int enable_clk) | 313 | set_clk_mode(u_char on, u_char off, int enable_clk) | |
314 | { | 314 | { | |
315 | u_char interreg; | 315 | u_char interreg; | |
316 | 316 | |||
317 | /* | 317 | /* | |
318 | * If we have not yet mapped the register, | 318 | * If we have not yet mapped the register, | |
319 | * then we do not want to do any of this... | 319 | * then we do not want to do any of this... | |
320 | */ | 320 | */ | |
321 | if (!interrupt_reg) | 321 | if (!interrupt_reg) | |
322 | return; | 322 | return; | |
323 | 323 | |||
324 | #ifdef DIAGNOSTIC | 324 | #ifdef DIAGNOSTIC | |
325 | /* Assertion: were are at splhigh! */ | 325 | /* Assertion: were are at splhigh! */ | |
326 | if ((getsr() & PSL_IPL) < PSL_IPL7) | 326 | if ((getsr() & PSL_IPL) < PSL_IPL7) | |
327 | panic("set_clk_mode: bad ipl"); | 327 | panic("set_clk_mode: bad ipl"); | |
328 | #endif | 328 | #endif | |
329 | 329 | |||
330 | /* | 330 | /* | |
331 | * make sure that we are only playing w/ | 331 | * make sure that we are only playing w/ | |
332 | * clock interrupt register bits | 332 | * clock interrupt register bits | |
333 | */ | 333 | */ | |
334 | on &= IREG_CLK_BITS; | 334 | on &= IREG_CLK_BITS; | |
335 | off &= IREG_CLK_BITS; | 335 | off &= IREG_CLK_BITS; | |
336 | 336 | |||
337 | /* First, turn off the "master" enable bit. */ | 337 | /* First, turn off the "master" enable bit. */ | |
338 | single_inst_bclr_b(*interrupt_reg, IREG_ALL_ENAB); | 338 | single_inst_bclr_b(*interrupt_reg, IREG_ALL_ENAB); | |
339 | 339 | |||
340 | /* | 340 | /* | |
341 | * Save the current interrupt register clock bits, | 341 | * Save the current interrupt register clock bits, | |
342 | * and turn off/on the requested bits in the copy. | 342 | * and turn off/on the requested bits in the copy. | |
343 | */ | 343 | */ | |
344 | interreg = *interrupt_reg & IREG_CLK_BITS; | 344 | interreg = *interrupt_reg & IREG_CLK_BITS; | |
345 | interreg &= ~off; | 345 | interreg &= ~off; | |
346 | interreg |= on; | 346 | interreg |= on; | |
347 | 347 | |||
348 | /* Clear the CLK5 and CLK7 bits to clear the flip-flops. */ | 348 | /* Clear the CLK5 and CLK7 bits to clear the flip-flops. */ | |
349 | single_inst_bclr_b(*interrupt_reg, IREG_CLK_BITS); | 349 | single_inst_bclr_b(*interrupt_reg, IREG_CLK_BITS); | |
350 | 350 | |||
351 | #ifdef SUN3_470 | 351 | #ifdef SUN3_470 | |
352 | if (intersil_va) { | 352 | if (intersil_va) { | |
353 | /* | 353 | /* | |
354 | * Then disable clock interrupts, and read the clock's | 354 | * Then disable clock interrupts, and read the clock's | |
355 | * interrupt register to clear any pending signals there. | 355 | * interrupt register to clear any pending signals there. | |
356 | */ | 356 | */ | |
357 | intersil_clock->clk_cmd_reg = | 357 | intersil_clock->clk_cmd_reg = | |
358 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); | 358 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); | |
359 | intersil_clear(); | 359 | intersil_clear(); | |
360 | } | 360 | } | |
361 | #endif /* SUN3_470 */ | 361 | #endif /* SUN3_470 */ | |
362 | 362 | |||
363 | /* Set the requested bits in the interrupt register. */ | 363 | /* Set the requested bits in the interrupt register. */ | |
364 | single_inst_bset_b(*interrupt_reg, interreg); | 364 | single_inst_bset_b(*interrupt_reg, interreg); | |
365 | 365 | |||
366 | #ifdef SUN3_470 | 366 | #ifdef SUN3_470 | |
367 | /* Turn the clock back on (maybe) */ | 367 | /* Turn the clock back on (maybe) */ | |
368 | if (intersil_va && enable_clk) | 368 | if (intersil_va && enable_clk) | |
369 | intersil_clock->clk_cmd_reg = | 369 | intersil_clock->clk_cmd_reg = | |
370 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); | 370 | INTERSIL_COMMAND(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); | |
371 | #endif /* SUN3_470 */ | 371 | #endif /* SUN3_470 */ | |
372 | 372 | |||
373 | /* Finally, turn the "master" enable back on. */ | 373 | /* Finally, turn the "master" enable back on. */ | |
374 | single_inst_bset_b(*interrupt_reg, IREG_ALL_ENAB); | 374 | single_inst_bset_b(*interrupt_reg, IREG_ALL_ENAB); | |
375 | } | 375 | } | |
376 | 376 | |||
377 | /* | 377 | /* | |
378 | * Set up the real-time clock (enable clock interrupts). | 378 | * Set up the real-time clock (enable clock interrupts). | |
379 | * Leave stathz 0 since there is no secondary clock available. | 379 | * Leave stathz 0 since there is no secondary clock available. | |
380 | * Note that clock interrupts MUST STAY DISABLED until here. | 380 | * Note that clock interrupts MUST STAY DISABLED until here. | |
381 | */ | 381 | */ | |
382 | void | 382 | void | |
383 | cpu_initclocks(void) | 383 | cpu_initclocks(void) | |
384 | { | 384 | { | |
385 | int s; | 385 | int s; | |
386 | 386 | |||
387 | s = splhigh(); | 387 | s = splhigh(); | |
388 | 388 | |||
389 | /* Install isr (in locore.s) that calls clock_intr(). */ | 389 | /* Install isr (in locore.s) that calls clock_intr(). */ | |
390 | isr_add_custom(CLOCK_PRI, (void *)_isr_clock); | 390 | isr_add_custom(CLOCK_PRI, (void *)_isr_clock); | |
391 | 391 | |||
392 | /* Now enable the clock at level 5 in the interrupt reg. */ | 392 | /* Now enable the clock at level 5 in the interrupt reg. */ | |
393 | set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1); | 393 | set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1); | |
394 | 394 | |||
395 | splx(s); | 395 | splx(s); | |
396 | } | 396 | } | |
397 | 397 | |||
398 | /* | 398 | /* | |
399 | * This doesn't need to do anything, as we have only one timer and | 399 | * This doesn't need to do anything, as we have only one timer and | |
400 | * profhz==stathz==hz. | 400 | * profhz==stathz==hz. | |
401 | */ | 401 | */ | |
402 | void | 402 | void | |
403 | setstatclockrate(int newhz) | 403 | setstatclockrate(int newhz) | |
404 | { | 404 | { | |
405 | 405 | |||
406 | /* nothing */ | 406 | /* nothing */ | |
407 | } | 407 | } | |
408 | 408 | |||
409 | /* | 409 | /* | |
410 | * Clock interrupt handler (for both Intersil and Mostek). | 410 | * Clock interrupt handler (for both Intersil and Mostek). | |
411 | * XXX - Is it worth the trouble to save a few cycles here | 411 | * XXX - Is it worth the trouble to save a few cycles here | |
412 | * by making two separate interrupt handlers? | 412 | * by making two separate interrupt handlers? | |
413 | * | 413 | * | |
414 | * This is called by the "custom" interrupt handler. | 414 | * This is called by the "custom" interrupt handler. | |
415 | * Note that we can get ZS interrupts while this runs, | 415 | * Note that we can get ZS interrupts while this runs, | |
416 | * and zshard may touch the interrupt_reg, so we must | 416 | * and zshard may touch the interrupt_reg, so we must | |
417 | * be careful to use the single_inst_* macros to modify | 417 | * be careful to use the single_inst_* macros to modify | |
418 | * the interrupt register atomically. | 418 | * the interrupt register atomically. | |
419 | */ | 419 | */ | |
420 | void | 420 | void | |
421 | clock_intr(struct clockframe cf) | 421 | clock_intr(struct clockframe cf) | |
422 | { | 422 | { | |
423 | extern char _Idle[]; /* locore.s */ | 423 | extern char _Idle[]; /* locore.s */ | |
424 | 424 | |||
425 | idepth++; | 425 | idepth++; | |
426 | 426 | |||
427 | #ifdef SUN3_470 | 427 | #ifdef SUN3_470 | |
428 | if (intersil_va) { | 428 | if (intersil_va) { | |
429 | /* Read the clock interrupt register. */ | 429 | /* Read the clock interrupt register. */ | |
430 | intersil_clear(); | 430 | intersil_clear(); | |
431 | } | 431 | } | |
432 | #endif /* SUN3_470 */ | 432 | #endif /* SUN3_470 */ | |
433 | 433 | |||
434 | /* Pulse the clock intr. enable low. */ | 434 | /* Pulse the clock intr. enable low. */ | |
435 | single_inst_bclr_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | 435 | single_inst_bclr_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | |
436 | single_inst_bset_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | 436 | single_inst_bset_b(*interrupt_reg, IREG_CLOCK_ENAB_5); | |
437 | 437 | |||
438 | #ifdef SUN3_470 | 438 | #ifdef SUN3_470 | |
439 | if (intersil_va) { | 439 | if (intersil_va) { | |
440 | /* Read the clock intr. reg. AGAIN! */ | 440 | /* Read the clock intr. reg. AGAIN! */ | |
441 | intersil_clear(); | 441 | intersil_clear(); | |
442 | } | 442 | } | |
443 | #endif /* SUN3_470 */ | 443 | #endif /* SUN3_470 */ | |
444 | 444 | |||
445 | intrcnt[CLOCK_PRI]++; | 445 | intrcnt[CLOCK_PRI]++; | |
446 | curcpu()->ci_data.cpu_nintr++; | 446 | curcpu()->ci_data.cpu_nintr++; | |
447 | 447 | |||
448 | /* Entertainment! */ | 448 | /* Entertainment! */ | |
449 | if (cf.cf_pc == (long)_Idle) | 449 | if (cf.cf_pc == (long)_Idle) | |
450 | leds_intr(); | 450 | leds_intr(); | |
451 | 451 | |||
452 | /* Call common clock interrupt handler. */ | 452 | /* Call common clock interrupt handler. */ | |
453 | hardclock(&cf); | 453 | hardclock(&cf); | |
454 | 454 | |||
455 | idepth--; | 455 | idepth--; | |
456 | } | 456 | } |