| @@ -1,434 +1,434 @@ | | | @@ -1,434 +1,434 @@ |
1 | /* $NetBSD: tc_vsbus.c,v 1.8 2017/06/09 17:55:18 flxd Exp $ */ | | 1 | /* $NetBSD: tc_vsbus.c,v 1.9 2017/06/09 18:02:40 flxd Exp $ */ |
2 | /*- | | 2 | /*- |
3 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 3 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
4 | * All rights reserved. | | 4 | * All rights reserved. |
5 | * | | 5 | * |
6 | * This code is derived from software contributed to The NetBSD Foundation | | 6 | * This code is derived from software contributed to The NetBSD Foundation |
7 | * by Matt Thomas <matt@3am-software.com>. | | 7 | * by Matt Thomas <matt@3am-software.com>. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * | | 17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 18 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
19 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 19 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
20 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 20 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
21 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 21 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
28 | * POSSIBILITY OF SUCH DAMAGE. | | 28 | * POSSIBILITY OF SUCH DAMAGE. |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | #include <sys/cdefs.h> | | 31 | #include <sys/cdefs.h> |
32 | __KERNEL_RCSID(0, "$NetBSD: tc_vsbus.c,v 1.8 2017/06/09 17:55:18 flxd Exp $"); | | 32 | __KERNEL_RCSID(0, "$NetBSD: tc_vsbus.c,v 1.9 2017/06/09 18:02:40 flxd Exp $"); |
33 | | | 33 | |
34 | #include <sys/param.h> | | 34 | #include <sys/param.h> |
35 | #include <sys/bus.h> | | 35 | #include <sys/bus.h> |
36 | #include <sys/cpu.h> | | 36 | #include <sys/cpu.h> |
37 | #include <sys/device.h> | | 37 | #include <sys/device.h> |
38 | | | 38 | |
39 | #include <machine/cpu.h> | | 39 | #include <machine/cpu.h> |
40 | #include <machine/pte.h> | | 40 | #include <machine/pte.h> |
41 | #include <machine/scb.h> | | 41 | #include <machine/scb.h> |
42 | #include <machine/sid.h> | | 42 | #include <machine/sid.h> |
43 | #include <machine/vsbus.h> | | 43 | #include <machine/vsbus.h> |
44 | | | 44 | |
45 | #include <dev/tc/tcvar.h> | | 45 | #include <dev/tc/tcvar.h> |
46 | | | 46 | |
47 | #define NSLOTS 1 | | 47 | #define NSLOTS 1 |
48 | | | 48 | |
49 | struct tc_vsbus_softc { | | 49 | struct tc_vsbus_softc { |
50 | struct tc_softc sc_tc; | | 50 | struct tc_softc sc_tc; |
51 | struct tc_slotdesc sc_slots[NSLOTS]; | | 51 | struct tc_slotdesc sc_slots[NSLOTS]; |
52 | struct vax_bus_dma_tag sc_dmatag; | | 52 | struct vax_bus_dma_tag sc_dmatag; |
53 | struct vax_sgmap sc_sgmap; | | 53 | struct vax_sgmap sc_sgmap; |
54 | struct evcnt sc_ev; | | 54 | struct evcnt sc_ev; |
55 | int (*sc_intr_func)(void *); | | 55 | int (*sc_intr_func)(void *); |
56 | void *sc_intr_arg; | | 56 | void *sc_intr_arg; |
57 | bus_space_tag_t sc_bst; | | 57 | bus_space_tag_t sc_bst; |
58 | bus_space_handle_t sc_bsh_csr; | | 58 | bus_space_handle_t sc_bsh_csr; |
59 | int sc_cvec; | | 59 | int sc_cvec; |
60 | }; | | 60 | }; |
61 | | | 61 | |
62 | static int tc_vsbus_match(device_t, cfdata_t, void *); | | 62 | static int tc_vsbus_match(device_t, cfdata_t, void *); |
63 | static void tc_vsbus_attach(device_t, device_t, void *); | | 63 | static void tc_vsbus_attach(device_t, device_t, void *); |
64 | | | 64 | |
65 | static int tc_vsbus_dma_init(device_t); | | 65 | static int tc_vsbus_dma_init(device_t); |
66 | static bus_dma_tag_t tc_vsbus_get_dma_tag(int); | | 66 | static bus_dma_tag_t tc_vsbus_get_dma_tag(int); |
67 | | | 67 | |
68 | static void tc_vsbus_intr(void *); | | 68 | static void tc_vsbus_intr(void *); |
69 | static void tc_vsbus_intr_establish(device_t, void *, int, int (*)(void *), | | 69 | static void tc_vsbus_intr_establish(device_t, void *, int, int (*)(void *), |
70 | void *); | | 70 | void *); |
71 | static void tc_vsbus_intr_disestablish(device_t, void *); | | 71 | static void tc_vsbus_intr_disestablish(device_t, void *); |
72 | static const struct evcnt *tc_vsbus_intr_evcnt(device_t, void *); | | 72 | static const struct evcnt *tc_vsbus_intr_evcnt(device_t, void *); |
73 | | | 73 | |
74 | static int vax_tc_bus_space_map(void *, bus_addr_t, bus_size_t, int, | | 74 | static int vax_tc_bus_space_map(void *, bus_addr_t, bus_size_t, int, |
75 | bus_space_handle_t *, int); | | 75 | bus_space_handle_t *, int); |
76 | static int vax_tc_bus_space_subregion(void *, bus_space_handle_t, bus_size_t, | | 76 | static int vax_tc_bus_space_subregion(void *, bus_space_handle_t, bus_size_t, |
77 | bus_size_t, bus_space_handle_t *); | | 77 | bus_size_t, bus_space_handle_t *); |
78 | static void vax_tc_bus_space_unmap(void *, bus_space_handle_t, bus_size_t, int); | | 78 | static void vax_tc_bus_space_unmap(void *, bus_space_handle_t, bus_size_t, int); |
79 | static int vax_tc_bus_space_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, | | 79 | static int vax_tc_bus_space_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, |
80 | bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); | | 80 | bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); |
81 | static void vax_tc_bus_space_free(void *, bus_space_handle_t, bus_size_t); | | 81 | static void vax_tc_bus_space_free(void *, bus_space_handle_t, bus_size_t); |
82 | static paddr_t vax_tc_bus_space_mmap(void *, bus_addr_t, off_t, int, int); | | 82 | static paddr_t vax_tc_bus_space_mmap(void *, bus_addr_t, off_t, int, int); |
83 | | | 83 | |
84 | CFATTACH_DECL_NEW(tc_vsbus, sizeof(struct tc_vsbus_softc), | | 84 | CFATTACH_DECL_NEW(tc_vsbus, sizeof(struct tc_vsbus_softc), |
85 | tc_vsbus_match, tc_vsbus_attach, 0, 0); | | 85 | tc_vsbus_match, tc_vsbus_attach, 0, 0); |
86 | | | 86 | |
87 | static bus_dma_tag_t tc_vsbus_dmat; | | 87 | static bus_dma_tag_t tc_vsbus_dmat; |
88 | | | 88 | |
89 | struct vax_bus_space vax_tc_bus_space = { | | 89 | struct vax_bus_space vax_tc_bus_space = { |
90 | NULL, | | 90 | NULL, |
91 | vax_tc_bus_space_map, | | 91 | vax_tc_bus_space_map, |
92 | vax_tc_bus_space_unmap, | | 92 | vax_tc_bus_space_unmap, |
93 | vax_tc_bus_space_subregion, | | 93 | vax_tc_bus_space_subregion, |
94 | vax_tc_bus_space_alloc, | | 94 | vax_tc_bus_space_alloc, |
95 | vax_tc_bus_space_free, | | 95 | vax_tc_bus_space_free, |
96 | vax_tc_bus_space_mmap, | | 96 | vax_tc_bus_space_mmap, |
97 | }; | | 97 | }; |
98 | | | 98 | |
99 | /* | | 99 | /* |
100 | * taken from KA46 System Board Specification, KA46-0-DBF, Rev. X.02, | | 100 | * taken from KA46 System Board Specification, KA46-0-DBF, Rev. X.02, |
101 | * 10 October 1990 | | 101 | * 10 October 1990 |
102 | */ | | 102 | */ |
103 | #define KA46_BWF0 0x20080014 | | 103 | #define KA46_BWF0 0x20080014 |
104 | #define KA46_BWF0_ADP __BIT(31) | | 104 | #define KA46_BWF0_ADP __BIT(31) |
105 | #define KA46_BWF0_SZ 4 | | 105 | #define KA46_BWF0_SZ 4 |
106 | | | 106 | |
107 | /* | | 107 | /* |
108 | * taken from KA49 Processor Module Specification V 1.1, 20 August 1992 | | 108 | * taken from KA49 Processor Module Specification V 1.1, 20 August 1992 |
109 | */ | | 109 | */ |
110 | #define KA49_CFG 0x25800000 | | 110 | #define KA49_CFG 0x25800000 |
111 | #define KA49_CFG_BA __BIT(0) | | 111 | #define KA49_CFG_BA __BIT(0) |
112 | #define KA49_CFG_SZ 2 | | 112 | #define KA49_CFG_SZ 2 |
113 | | | 113 | |
114 | /* | | 114 | /* |
115 | * taken from Pmariah TURBOchannel Adapter Specification, 29 November 1991 | | 115 | * taken from Pmariah TURBOchannel Adapter Specification, 29 November 1991 |
116 | */ | | 116 | */ |
117 | #define KA4x_TCA_BASE 0x30000000 | | 117 | #define KA4x_TCA_BASE 0x30000000 |
118 | #define KA4x_TCA_DIAG_TRIG (KA4x_TCA_BASE + 0x4000000) | | 118 | #define KA4x_TCA_DIAG_TRIG (KA4x_TCA_BASE + 0x4000000) |
119 | #define KA4x_TCA_MAP_CHK_SEQ (KA4x_TCA_BASE + 0x4800000) | | 119 | #define KA4x_TCA_MAP_CHK_SEQ (KA4x_TCA_BASE + 0x4800000) |
120 | #define KA4x_TCA_FIFO_DIAG (KA4x_TCA_BASE + 0x5000000) | | 120 | #define KA4x_TCA_FIFO_DIAG (KA4x_TCA_BASE + 0x5000000) |
121 | #define KA4x_TCA_SGMAP (KA4x_TCA_BASE + 0x5800000) | | 121 | #define KA4x_TCA_SGMAP (KA4x_TCA_BASE + 0x5800000) |
122 | #define KA4x_TCA_DIAG_ROM (KA4x_TCA_BASE + 0x6000000) | | 122 | #define KA4x_TCA_DIAG_ROM (KA4x_TCA_BASE + 0x6000000) |
123 | #define KA4x_TCA_CSR (KA4x_TCA_BASE + 0x6800000) | | 123 | #define KA4x_TCA_CSR (KA4x_TCA_BASE + 0x6800000) |
124 | #define KA4x_TCA_CSR_BLK_SZ __BITS(0, 2) /* 0x00007 RW */ | | 124 | #define KA4x_TCA_CSR_BLK_SZ __BITS(0, 2) /* 0x00007 RW */ |
125 | #define KA4x_TCA_CSR_SPARE __BIT(3) /* 0x00008 RW */ | | 125 | #define KA4x_TCA_CSR_SPARE __BIT(3) /* 0x00008 RW */ |
126 | #define KA4x_TCA_CSR_BAD_PAR __BITS(4, 7) /* 0x000f0 RW */ | | 126 | #define KA4x_TCA_CSR_BAD_PAR __BITS(4, 7) /* 0x000f0 RW */ |
127 | #define KA4x_TCA_CSR_RST_TC __BIT(8) /* 0x00100 RW */ | | 127 | #define KA4x_TCA_CSR_RST_TC __BIT(8) /* 0x00100 RW */ |
128 | #define KA4x_TCA_CSR_EN_MAP __BIT(9) /* 0x00200 RW */ | | 128 | #define KA4x_TCA_CSR_EN_MAP __BIT(9) /* 0x00200 RW */ |
129 | #define KA4x_TCA_CSR_INVAL_REF __BIT(10) /* 0x00400 RW1C */ | | 129 | #define KA4x_TCA_CSR_INVAL_REF __BIT(10) /* 0x00400 RW1C */ |
130 | #define KA4x_TCA_CSR_TC_TMO __BIT(11) /* 0x00800 RW */ | | 130 | #define KA4x_TCA_CSR_TC_TMO __BIT(11) /* 0x00800 RW */ |
131 | #define KA4x_TCA_CSR_EN_TC_IRQ __BIT(12) /* 0x01000 RW */ | | 131 | #define KA4x_TCA_CSR_EN_TC_IRQ __BIT(12) /* 0x01000 RW */ |
132 | #define KA4x_TCA_CSR_TC_IRQ __BIT(13) /* 0x02000 R */ | | 132 | #define KA4x_TCA_CSR_TC_IRQ __BIT(13) /* 0x02000 R */ |
133 | #define KA4x_TCA_CSR_ERR __BIT(14) /* 0x04000 RW1C */ | | 133 | #define KA4x_TCA_CSR_ERR __BIT(14) /* 0x04000 RW1C */ |
134 | #define KA4x_TCA_CSR_ALT_CYC_ST __BIT(15) /* 0x08000 RW */ | | 134 | #define KA4x_TCA_CSR_ALT_CYC_ST __BIT(15) /* 0x08000 RW */ |
135 | #define KA4x_TCA_CSR_EN_PAR __BIT(16) /* 0x10000 RW */ | | 135 | #define KA4x_TCA_CSR_EN_PAR __BIT(16) /* 0x10000 RW */ |
136 | #define KA4x_TCA_CSR_FIFO_EMPTY __BIT(17) /* 0x20000 R */ | | 136 | #define KA4x_TCA_CSR_FIFO_EMPTY __BIT(17) /* 0x20000 R */ |
137 | #define KA4x_TCA_CSR_SZ 4 | | 137 | #define KA4x_TCA_CSR_SZ 4 |
138 | | | 138 | |
139 | static int | | 139 | static int |
140 | tc_vsbus_match(device_t parent, cfdata_t cfdata, void *aux) | | 140 | tc_vsbus_match(device_t parent, cfdata_t cfdata, void *aux) |
141 | { | | 141 | { |
142 | struct vsbus_attach_args * const va = aux; | | 142 | struct vsbus_attach_args * const va = aux; |
143 | uint32_t *csr; | | 143 | uint32_t *csr; |
144 | bus_space_tag_t bst = va->va_memt; | | 144 | bus_space_tag_t bst = va->va_memt; |
145 | bus_space_handle_t bsh; | | 145 | bus_space_handle_t bsh; |
146 | int found, rc; | | 146 | int found, rc; |
147 | | | 147 | |
148 | if (va->va_paddr != KA4x_TCA_CSR) | | 148 | if (va->va_paddr != KA4x_TCA_CSR) |
149 | return 0; | | 149 | return 0; |
150 | | | 150 | |
151 | /* Bus adaptor present? */ | | 151 | /* Bus adaptor present? */ |
152 | switch (vax_boardtype) { | | 152 | switch (vax_boardtype) { |
153 | case VAX_BTYP_46: | | 153 | case VAX_BTYP_46: |
154 | if (bus_space_map(bst, KA46_BWF0, KA46_BWF0_SZ, 0, &bsh)) | | 154 | if (bus_space_map(bst, KA46_BWF0, KA46_BWF0_SZ, 0, &bsh)) |
155 | return 0; | | 155 | return 0; |
156 | found = ((bus_space_read_4(bst, bsh, 0) & KA46_BWF0_ADP) != 0); | | 156 | found = ((bus_space_read_4(bst, bsh, 0) & KA46_BWF0_ADP) != 0); |
157 | bus_space_unmap(bst, bsh, KA46_BWF0_SZ); | | 157 | bus_space_unmap(bst, bsh, KA46_BWF0_SZ); |
158 | /* | | 158 | /* |
159 | * On VS4000/60, although interrupting on a real vector, fool | | 159 | * On VS4000/60, although interrupting on a real vector, fool |
160 | * vsbus interrupt, as no interrupt bit will be set in | | 160 | * vsbus interrupt, as no interrupt bit will be set in |
161 | * vsbus_softc's sc_intreq for TC adaptor. | | 161 | * vsbus_softc's sc_intreq for TC adaptor. |
162 | */ | | 162 | */ |
163 | rc = 20; | | 163 | rc = 20; |
164 | break; | | 164 | break; |
165 | case VAX_BTYP_49: | | 165 | case VAX_BTYP_49: |
166 | if (bus_space_map(bst, KA49_CFG, KA49_CFG_SZ, 0, &bsh)) | | 166 | if (bus_space_map(bst, KA49_CFG, KA49_CFG_SZ, 0, &bsh)) |
167 | return 0; | | 167 | return 0; |
168 | found = ((bus_space_read_2(bst, bsh, 0) & KA49_CFG_BA) != 0); | | 168 | found = ((bus_space_read_2(bst, bsh, 0) & KA49_CFG_BA) != 0); |
169 | bus_space_unmap(bst, bsh, KA49_CFG_SZ); | | 169 | bus_space_unmap(bst, bsh, KA49_CFG_SZ); |
170 | rc = 10; | | 170 | rc = 10; |
171 | break; | | 171 | break; |
172 | default: | | 172 | default: |
173 | return 0; | | 173 | return 0; |
174 | } | | 174 | } |
175 | if (!found) | | 175 | if (!found) |
176 | return 0; | | 176 | return 0; |
177 | | | 177 | |
178 | /* XXX Assume a found bus adaptor is the TC bus adaptor. */ | | 178 | /* XXX Assume a found bus adaptor is the TC bus adaptor. */ |
179 | | | 179 | |
180 | /* Force interrupt. */ | | 180 | /* Force interrupt. */ |
181 | csr = (uint32_t *)va->va_addr; | | 181 | csr = (uint32_t *)va->va_addr; |
182 | *csr |= KA4x_TCA_CSR_TC_TMO; | | 182 | *csr |= KA4x_TCA_CSR_TC_TMO; |
183 | DELAY(10000); | | 183 | DELAY(10000); |
184 | *csr &= ~KA4x_TCA_CSR_TC_TMO; | | 184 | *csr &= ~KA4x_TCA_CSR_TC_TMO; |
185 | DELAY(10000); | | 185 | DELAY(10000); |
186 | | | 186 | |
187 | return rc; | | 187 | return rc; |
188 | } | | 188 | } |
189 | | | 189 | |
190 | #define INIT_SLOTSZ 1 | | 190 | #define INIT_SLOTSZ 1 |
191 | | | 191 | |
192 | static void | | 192 | static void |
193 | tc_vsbus_attach(device_t parent, device_t self, void *aux) | | 193 | tc_vsbus_attach(device_t parent, device_t self, void *aux) |
194 | { | | 194 | { |
195 | struct tcbus_attach_args tba; | | 195 | struct tcbus_attach_args tba; |
196 | struct vsbus_attach_args * const va = aux; | | 196 | struct vsbus_attach_args * const va = aux; |
197 | struct tc_vsbus_softc * const sc = device_private(self); | | 197 | struct tc_vsbus_softc * const sc = device_private(self); |
198 | struct tc_rommap *rommap; | | 198 | struct tc_rommap *rommap; |
199 | bus_space_tag_t bst = va->va_memt; | | 199 | bus_space_tag_t bst = va->va_memt; |
200 | bus_space_handle_t bsh_csr, bsh_slot; | | 200 | bus_space_handle_t bsh_csr, bsh_slot; |
201 | const bus_size_t slotb = 4194304; | | 201 | const bus_size_t slotb = 4194304; |
202 | uint32_t csr; | | 202 | uint32_t csr; |
203 | int error, slotsz; | | 203 | int error, slotsz; |
204 | | | 204 | |
205 | sc->sc_cvec = va->va_cvec; | | 205 | sc->sc_cvec = va->va_cvec; |
206 | | | 206 | |
207 | error = bus_space_map(bst, KA4x_TCA_CSR, KA4x_TCA_CSR_SZ, 0, &bsh_csr); | | 207 | error = bus_space_map(bst, KA4x_TCA_CSR, KA4x_TCA_CSR_SZ, 0, &bsh_csr); |
208 | if (error) { | | 208 | if (error) { |
209 | aprint_normal(": failed to map TCA CSR: %d\n", error); | | 209 | aprint_normal(": failed to map TCA CSR: %d\n", error); |
210 | return; | | 210 | return; |
211 | } | | 211 | } |
212 | sc->sc_bst = bst; | | 212 | sc->sc_bst = bst; |
213 | sc->sc_bsh_csr = bsh_csr; | | 213 | sc->sc_bsh_csr = bsh_csr; |
214 | | | 214 | |
215 | /* Deassert TC option reset and clean up. */ | | 215 | /* Deassert TC option reset and clean up. */ |
216 | csr = bus_space_read_4(bst, bsh_csr, 0); | | 216 | csr = bus_space_read_4(bst, bsh_csr, 0); |
217 | csr &= ~(KA4x_TCA_CSR_TC_TMO | KA4x_TCA_CSR_RST_TC); | | 217 | csr &= ~(KA4x_TCA_CSR_TC_TMO | KA4x_TCA_CSR_RST_TC); |
218 | csr |= KA4x_TCA_CSR_ERR | KA4x_TCA_CSR_INVAL_REF; | | 218 | csr |= KA4x_TCA_CSR_ERR | KA4x_TCA_CSR_INVAL_REF; |
219 | bus_space_write_4(bst, bsh_csr, 0, csr); | | 219 | bus_space_write_4(bst, bsh_csr, 0, csr); |
220 | | | 220 | |
221 | /* | | 221 | /* |
222 | * Map initial number of "slots" (4 MB each) to read the option ROM | | 222 | * Map initial number of "slots" (4 MB each) to read the option ROM |
223 | * header. | | 223 | * header. |
224 | */ | | 224 | */ |
225 | error = bus_space_map(bst, KA4x_TCA_BASE, INIT_SLOTSZ * slotb, | | 225 | error = bus_space_map(bst, KA4x_TCA_BASE, INIT_SLOTSZ * slotb, |
226 | BUS_SPACE_MAP_LINEAR, &bsh_slot); | | 226 | BUS_SPACE_MAP_LINEAR, &bsh_slot); |
227 | if (error) { | | 227 | if (error) { |
228 | aprint_normal(": failed to map TC slot: %d", error); | | 228 | aprint_normal(": failed to map TC slot: %d", error); |
229 | goto fail; | | 229 | goto fail; |
230 | } | | 230 | } |
231 | /* Determine number of slots required from option ROM header. */ | | 231 | /* Determine number of slots required from option ROM header. */ |
232 | slotsz = 0; | | 232 | slotsz = 0; |
233 | if (tc_checkslot((tc_addr_t)bus_space_vaddr(bst, bsh_slot), NULL, | | 233 | if (tc_checkslot((tc_addr_t)bus_space_vaddr(bst, bsh_slot), NULL, |
234 | &rommap)) | | 234 | &rommap)) |
235 | slotsz = rommap->tcr_ssize.v; | | 235 | slotsz = rommap->tcr_ssize.v; |
236 | if (slotsz == 0) { | | 236 | if (slotsz == 0) { |
237 | /* Invalid option ROM header or no option present. */ | | 237 | /* Invalid option ROM header or no option present. */ |
238 | bus_space_unmap(bst, bsh_slot, INIT_SLOTSZ * slotb); | | 238 | bus_space_unmap(bst, bsh_slot, INIT_SLOTSZ * slotb); |
239 | goto fail; | | 239 | goto fail; |
240 | } else if (slotsz > INIT_SLOTSZ) { | | 240 | } else if (slotsz > INIT_SLOTSZ) { |
241 | /* Remap with actual slot size required. */ | | 241 | /* Remap with actual slot size required. */ |
242 | bus_space_unmap(bst, bsh_slot, INIT_SLOTSZ * slotb); | | 242 | bus_space_unmap(bst, bsh_slot, INIT_SLOTSZ * slotb); |
243 | error = bus_space_map(bst, KA4x_TCA_BASE, slotsz * slotb, | | 243 | error = bus_space_map(bst, KA4x_TCA_BASE, slotsz * slotb, |
244 | BUS_SPACE_MAP_LINEAR, &bsh_slot); | | 244 | BUS_SPACE_MAP_LINEAR, &bsh_slot); |
245 | if (error) { | | 245 | if (error) { |
246 | aprint_normal(": failed to map TC slot: %d", error); | | 246 | aprint_normal(": failed to map TC slot: %d", error); |
247 | goto fail; | | 247 | goto fail; |
248 | } | | 248 | } |
249 | } else | | 249 | } else |
250 | slotsz = INIT_SLOTSZ; | | 250 | slotsz = INIT_SLOTSZ; |
251 | | | 251 | |
252 | /* Pass pre-mapped space for TC drivers not bus_space'ified yet. */ | | 252 | /* Pass pre-mapped space for TC drivers not bus_space'ified yet. */ |
253 | sc->sc_slots[0].tcs_addr = (tc_addr_t)bus_space_vaddr(bst, bsh_slot); | | 253 | sc->sc_slots[0].tcs_addr = (tc_addr_t)bus_space_vaddr(bst, bsh_slot); |
254 | sc->sc_slots[0].tcs_cookie = sc; | | 254 | sc->sc_slots[0].tcs_cookie = sc; |
255 | sc->sc_slots[0].tcs_used = 0; | | 255 | sc->sc_slots[0].tcs_used = 0; |
256 | | | 256 | |
257 | tba.tba_busname = "tc"; | | 257 | tba.tba_busname = "tc"; |
258 | /* Tag with custom methods for pre-mapped bus_space. */ | | 258 | /* Tag with custom methods for pre-mapped bus_space. */ |
259 | tba.tba_memt = &vax_tc_bus_space; | | 259 | tba.tba_memt = &vax_tc_bus_space; |
260 | tba.tba_speed = TC_SPEED_12_5_MHZ; | | 260 | tba.tba_speed = TC_SPEED_12_5_MHZ; |
261 | tba.tba_nslots = __arraycount(sc->sc_slots); | | 261 | tba.tba_nslots = __arraycount(sc->sc_slots); |
262 | tba.tba_slots = sc->sc_slots; | | 262 | tba.tba_slots = sc->sc_slots; |
263 | tba.tba_nbuiltins = 0; | | 263 | tba.tba_nbuiltins = 0; |
264 | tba.tba_intr_evcnt = tc_vsbus_intr_evcnt; | | 264 | tba.tba_intr_evcnt = tc_vsbus_intr_evcnt; |
265 | tba.tba_intr_establish = tc_vsbus_intr_establish; | | 265 | tba.tba_intr_establish = tc_vsbus_intr_establish; |
266 | tba.tba_intr_disestablish = tc_vsbus_intr_disestablish; | | 266 | tba.tba_intr_disestablish = tc_vsbus_intr_disestablish; |
267 | tba.tba_get_dma_tag = tc_vsbus_get_dma_tag; | | 267 | tba.tba_get_dma_tag = tc_vsbus_get_dma_tag; |
268 | | | 268 | |
269 | error = tc_vsbus_dma_init(self); | | 269 | error = tc_vsbus_dma_init(self); |
270 | if (error) { | | 270 | if (error) { |
271 | aprint_normal(": failed to init DMA: %d", error); | | 271 | aprint_normal(": failed to init DMA: %d", error); |
272 | bus_space_unmap(bst, bsh_slot, slotsz * slotb); | | 272 | bus_space_unmap(bst, bsh_slot, slotsz * slotb); |
273 | goto fail; | | 273 | goto fail; |
274 | } | | 274 | } |
275 | | | 275 | |
276 | evcnt_attach_dynamic(&sc->sc_ev, EVCNT_TYPE_INTR, NULL, | | 276 | evcnt_attach_dynamic(&sc->sc_ev, EVCNT_TYPE_INTR, NULL, |
277 | device_xname(self), "intr"); | | 277 | device_xname(self), "intr"); |
278 | | | 278 | |
279 | /* Enable SGDMA and option IRQ now. */ | | 279 | /* Enable SGDMA and option IRQ now. */ |
280 | csr = bus_space_read_4(bst, bsh_csr, 0); | | 280 | csr = bus_space_read_4(bst, bsh_csr, 0); |
281 | csr &= ~(KA4x_TCA_CSR_TC_TMO | KA4x_TCA_CSR_RST_TC); | | 281 | csr &= ~(KA4x_TCA_CSR_TC_TMO | KA4x_TCA_CSR_RST_TC); |
282 | csr |= KA4x_TCA_CSR_ERR | KA4x_TCA_CSR_EN_TC_IRQ | | | 282 | csr |= KA4x_TCA_CSR_ERR | KA4x_TCA_CSR_EN_TC_IRQ | |
283 | KA4x_TCA_CSR_INVAL_REF | KA4x_TCA_CSR_EN_MAP; | | 283 | KA4x_TCA_CSR_INVAL_REF | KA4x_TCA_CSR_EN_MAP; |
284 | bus_space_write_4(bst, bsh_csr, 0, csr); | | 284 | bus_space_write_4(bst, bsh_csr, 0, csr); |
285 | | | 285 | |
286 | /* XXX: why not config_found(9)?? */ | | 286 | /* XXX: why not config_found(9)?? */ |
287 | tcattach(parent, self, &tba); | | 287 | tcattach(parent, self, &tba); |
288 | | | 288 | |
289 | return; | | 289 | return; |
290 | | | 290 | |
291 | fail: | | 291 | fail: |
292 | aprint_normal("\n"); | | 292 | aprint_normal("\n"); |
293 | /* Clear possible timeout bit which asserts TC interrupt. */ | | 293 | /* Clear possible timeout bit which asserts TC interrupt. */ |
294 | csr = bus_space_read_4(bst, bsh_csr, 0); | | 294 | csr = bus_space_read_4(bst, bsh_csr, 0); |
295 | csr &= ~KA4x_TCA_CSR_TC_TMO; | | 295 | csr &= ~KA4x_TCA_CSR_TC_TMO; |
296 | bus_space_write_4(bst, bsh_csr, 0, csr); | | 296 | bus_space_write_4(bst, bsh_csr, 0, csr); |
297 | bus_space_unmap(bst, bsh_csr, KA4x_TCA_CSR_SZ); | | 297 | bus_space_unmap(bst, bsh_csr, KA4x_TCA_CSR_SZ); |
298 | } | | 298 | } |
299 | | | 299 | |
300 | static int | | 300 | static int |
301 | tc_vsbus_dma_init(device_t dev) | | 301 | tc_vsbus_dma_init(device_t dev) |
302 | { | | 302 | { |
303 | struct tc_vsbus_softc * const sc = device_private(dev); | | 303 | struct tc_vsbus_softc * const sc = device_private(dev); |
304 | struct pte *pte; | | 304 | struct pte *pte; |
305 | bus_dma_tag_t dmat = &sc->sc_dmatag; | | 305 | bus_dma_tag_t dmat = &sc->sc_dmatag; |
306 | bus_space_tag_t bst = sc->sc_bst; | | 306 | bus_space_tag_t bst = sc->sc_bst; |
307 | bus_space_handle_t bsh; | | 307 | bus_space_handle_t bsh; |
308 | const bus_size_t ptecnt = 8192; | | 308 | const bus_size_t ptecnt = 8192; |
309 | const bus_size_t mapsize = ptecnt * sizeof(pte[0]); | | 309 | const bus_size_t mapsize = ptecnt * sizeof(pte[0]); |
310 | int error; | | 310 | int error; |
311 | | | 311 | |
312 | vax_sgmap_dmatag_init(dmat, sc, ptecnt); | | 312 | vax_sgmap_dmatag_init(dmat, sc, ptecnt); |
313 | | | 313 | |
314 | dmat->_sgmap = &sc->sc_sgmap; | | 314 | dmat->_sgmap = &sc->sc_sgmap; |
315 | | | 315 | |
316 | error = bus_space_map(bst, KA4x_TCA_SGMAP, mapsize, | | 316 | error = bus_space_map(bst, KA4x_TCA_SGMAP, mapsize, |
317 | BUS_SPACE_MAP_LINEAR, &bsh); | | 317 | BUS_SPACE_MAP_LINEAR, &bsh); |
318 | if (error) | | 318 | if (error) |
319 | return error; | | 319 | return error; |
320 | bus_space_set_region_4(bst, bsh, 0, 0, ptecnt); | | 320 | bus_space_set_region_4(bst, bsh, 0, 0, ptecnt); |
321 | pte = bus_space_vaddr(bst, bsh); | | 321 | pte = bus_space_vaddr(bst, bsh); |
322 | | | 322 | |
323 | /* Initialize the SGMAP. */ | | 323 | /* Initialize the SGMAP. */ |
324 | vax_sgmap_init(dmat, &sc->sc_sgmap, "tc_sgmap", dmat->_wbase, | | 324 | vax_sgmap_init(dmat, &sc->sc_sgmap, "tc_sgmap", dmat->_wbase, |
325 | dmat->_wsize, pte, 0); | | 325 | dmat->_wsize, pte, 0); |
326 | | | 326 | |
327 | tc_vsbus_dmat = dmat; | | 327 | tc_vsbus_dmat = dmat; |
328 | | | 328 | |
329 | return 0; | | 329 | return 0; |
330 | } | | 330 | } |
331 | | | 331 | |
332 | static bus_dma_tag_t | | 332 | static bus_dma_tag_t |
333 | tc_vsbus_get_dma_tag(int slotno) | | 333 | tc_vsbus_get_dma_tag(int slotno) |
334 | { | | 334 | { |
335 | | | 335 | |
336 | return tc_vsbus_dmat; | | 336 | return tc_vsbus_dmat; |
337 | } | | 337 | } |
338 | | | 338 | |
339 | static void | | 339 | static void |
340 | tc_vsbus_intr(void *arg) | | 340 | tc_vsbus_intr(void *arg) |
341 | { | | 341 | { |
342 | struct tc_vsbus_softc * const sc = arg; | | 342 | struct tc_vsbus_softc * const sc = arg; |
343 | bus_space_tag_t bst = sc->sc_bst; | | 343 | bus_space_tag_t bst = sc->sc_bst; |
344 | bus_space_handle_t bsh = sc->sc_bsh_csr; | | 344 | bus_space_handle_t bsh = sc->sc_bsh_csr; |
345 | uint32_t csr; | | 345 | uint32_t csr; |
346 | | | 346 | |
347 | sc->sc_ev.ev_count++; | | 347 | sc->sc_ev.ev_count++; |
348 | | | 348 | |
349 | csr = bus_space_read_4(bst, bsh, 0); | | 349 | csr = bus_space_read_4(bst, bsh, 0); |
350 | if (__predict_true((csr & KA4x_TCA_CSR_TC_IRQ) == 0)) /* active low */ | | 350 | if (__predict_true((csr & KA4x_TCA_CSR_TC_IRQ) == 0)) /* active low */ |
351 | sc->sc_intr_func(sc->sc_intr_arg); | | 351 | sc->sc_intr_func(sc->sc_intr_arg); |
352 | | | 352 | |
353 | /* Clear possible timeout bit which asserts TC interrupt. */ | | 353 | /* Clear possible timeout bit which asserts TC interrupt. */ |
354 | csr = bus_space_read_4(bst, bsh, 0); | | 354 | csr = bus_space_read_4(bst, bsh, 0); |
355 | csr &= ~KA4x_TCA_CSR_TC_TMO; | | 355 | csr &= ~KA4x_TCA_CSR_TC_TMO; |
356 | bus_space_write_4(bst, bsh, 0, csr); | | 356 | bus_space_write_4(bst, bsh, 0, csr); |
357 | } | | 357 | } |
358 | | | 358 | |
359 | static void | | 359 | static void |
360 | tc_vsbus_intr_establish(device_t dv, void *cookie, int level, | | 360 | tc_vsbus_intr_establish(device_t dv, void *cookie, int level, |
361 | int (*func)(void *), void *arg) | | 361 | int (*func)(void *), void *arg) |
362 | { | | 362 | { |
363 | struct tc_vsbus_softc * const sc = cookie; | | 363 | struct tc_vsbus_softc * const sc = cookie; |
364 | | | 364 | |
365 | sc->sc_intr_func = func; | | 365 | sc->sc_intr_func = func; |
366 | sc->sc_intr_arg = arg; | | 366 | sc->sc_intr_arg = arg; |
367 | | | 367 | |
368 | scb_vecalloc(sc->sc_cvec, tc_vsbus_intr, sc, SCB_ISTACK, &sc->sc_ev); | | 368 | scb_vecalloc(sc->sc_cvec, tc_vsbus_intr, sc, SCB_ISTACK, &sc->sc_ev); |
369 | } | | 369 | } |
370 | | | 370 | |
371 | static void | | 371 | static void |
372 | tc_vsbus_intr_disestablish(device_t dv, void *cookie) | | 372 | tc_vsbus_intr_disestablish(device_t dv, void *cookie) |
373 | { | | 373 | { |
374 | | | 374 | |
375 | /* Do nothing. */ | | 375 | /* Do nothing. */ |
376 | } | | 376 | } |
377 | | | 377 | |
378 | static const struct evcnt * | | 378 | static const struct evcnt * |
379 | tc_vsbus_intr_evcnt(device_t dv, void *cookie) | | 379 | tc_vsbus_intr_evcnt(device_t dv, void *cookie) |
380 | { | | 380 | { |
381 | struct tc_vsbus_softc * const sc = device_private(dv); | | 381 | struct tc_vsbus_softc * const sc = device_private(dv); |
382 | | | 382 | |
383 | return &sc->sc_ev; | | 383 | return &sc->sc_ev; |
384 | } | | 384 | } |
385 | | | 385 | |
386 | static int | | 386 | static int |
387 | vax_tc_bus_space_map(void *t, bus_addr_t pa, bus_size_t size, int cacheable, | | 387 | vax_tc_bus_space_map(void *t, bus_addr_t pa, bus_size_t size, int cacheable, |
388 | bus_space_handle_t *bshp, int f2) | | 388 | bus_space_handle_t *bshp, int f2) |
389 | { | | 389 | { |
390 | | | 390 | |
391 | /* bus_space is pre-mapped, so "pa" is a virtual address already. */ | | 391 | /* bus_space is pre-mapped, so "pa" is a virtual address already. */ |
392 | *bshp = pa; | | 392 | *bshp = pa; |
393 | return 0; | | 393 | return 0; |
394 | } | | 394 | } |
395 | | | 395 | |
396 | static int | | 396 | static int |
397 | vax_tc_bus_space_subregion(void *t, bus_space_handle_t h, bus_size_t o, | | 397 | vax_tc_bus_space_subregion(void *t, bus_space_handle_t h, bus_size_t o, |
398 | bus_size_t s, bus_space_handle_t *hp) | | 398 | bus_size_t s, bus_space_handle_t *hp) |
399 | { | | 399 | { |
400 | | | 400 | |
401 | *hp = h + o; | | 401 | *hp = h + o; |
402 | return 0; | | 402 | return 0; |
403 | } | | 403 | } |
404 | | | 404 | |
405 | static void | | 405 | static void |
406 | vax_tc_bus_space_unmap(void *t, bus_space_handle_t h, bus_size_t size, int f) | | 406 | vax_tc_bus_space_unmap(void *t, bus_space_handle_t h, bus_size_t size, int f) |
407 | { | | 407 | { |
408 | | | 408 | |
409 | /* Do nothing. */ | | 409 | /* Do nothing. */ |
410 | } | | 410 | } |
411 | | | 411 | |
412 | static int | | 412 | static int |
413 | vax_tc_bus_space_alloc(void *t, bus_addr_t rs, bus_addr_t re, bus_size_t s, | | 413 | vax_tc_bus_space_alloc(void *t, bus_addr_t rs, bus_addr_t re, bus_size_t s, |
414 | bus_size_t a, bus_size_t b, int f, bus_addr_t *ap, bus_space_handle_t *hp) | | 414 | bus_size_t a, bus_size_t b, int f, bus_addr_t *ap, bus_space_handle_t *hp) |
415 | { | | 415 | { |
416 | | | 416 | |
417 | panic("vax_tc_bus_space_alloc not implemented"); | | 417 | panic("vax_tc_bus_space_alloc not implemented"); |
418 | } | | 418 | } |
419 | | | 419 | |
420 | static void | | 420 | static void |
421 | vax_tc_bus_space_free(void *t, bus_space_handle_t h, bus_size_t s) | | 421 | vax_tc_bus_space_free(void *t, bus_space_handle_t h, bus_size_t s) |
422 | { | | 422 | { |
423 | | | 423 | |
424 | panic("vax_tc_bus_space_free not implemented"); | | 424 | panic("vax_tc_bus_space_free not implemented"); |
425 | } | | 425 | } |
426 | | | 426 | |
427 | static paddr_t | | 427 | static paddr_t |
428 | vax_tc_bus_space_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags) | | 428 | vax_tc_bus_space_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags) |
429 | { | | 429 | { |
430 | bus_addr_t rv; | | 430 | bus_addr_t rv; |
431 | | | 431 | |
432 | rv = addr + off; | | 432 | rv = addr + off; |
433 | return btop(rv); | | 433 | return btop(rv); |
434 | } | | 434 | } |