if_ntwoc_pci.c revision 1.1 1 1.1 explorer /* $Id: if_ntwoc_pci.c,v 1.1 1998/07/26 03:28:28 explorer Exp $ */
2 1.1 explorer
3 1.1 explorer /*
4 1.1 explorer * Copyright (c) 1998 Vixie Enterprises
5 1.1 explorer * All rights reserved.
6 1.1 explorer *
7 1.1 explorer * Redistribution and use in source and binary forms, with or without
8 1.1 explorer * modification, are permitted provided that the following conditions
9 1.1 explorer * are met:
10 1.1 explorer *
11 1.1 explorer * 1. Redistributions of source code must retain the above copyright
12 1.1 explorer * notice, this list of conditions and the following disclaimer.
13 1.1 explorer * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 explorer * notice, this list of conditions and the following disclaimer in the
15 1.1 explorer * documentation and/or other materials provided with the distribution.
16 1.1 explorer * 3. Neither the name of Vixie Enterprises nor the names
17 1.1 explorer * of its contributors may be used to endorse or promote products derived
18 1.1 explorer * from this software without specific prior written permission.
19 1.1 explorer *
20 1.1 explorer * THIS SOFTWARE IS PROVIDED BY VIXIE ENTERPRISES AND
21 1.1 explorer * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 1.1 explorer * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 1.1 explorer * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 1.1 explorer * DISCLAIMED. IN NO EVENT SHALL VIXIE ENTERPRISES OR
25 1.1 explorer * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 1.1 explorer * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 1.1 explorer * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 1.1 explorer * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 1.1 explorer * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 1.1 explorer * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 1.1 explorer * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 explorer * SUCH DAMAGE.
33 1.1 explorer *
34 1.1 explorer * This software has been written for Vixie Enterprises by Michael Graff
35 1.1 explorer * <explorer (at) flame.org>. To learn more about Vixie Enterprises, see
36 1.1 explorer * ``http://www.vix.com''.
37 1.1 explorer */
38 1.1 explorer
39 1.1 explorer #include <sys/param.h>
40 1.1 explorer #include <sys/systm.h>
41 1.1 explorer #include <sys/device.h>
42 1.1 explorer #include <sys/mbuf.h>
43 1.1 explorer #include <sys/socket.h>
44 1.1 explorer
45 1.1 explorer #include <net/if.h>
46 1.1 explorer
47 1.1 explorer #include <machine/cpu.h>
48 1.1 explorer #include <machine/bus.h>
49 1.1 explorer #include <machine/intr.h>
50 1.1 explorer
51 1.1 explorer #include <dev/pci/pcivar.h>
52 1.1 explorer #include <dev/pci/pcireg.h>
53 1.1 explorer #include <dev/pci/pcidevs.h>
54 1.1 explorer
55 1.1 explorer #include <dev/ic/hd64570reg.h>
56 1.1 explorer #include <dev/ic/hd64570var.h>
57 1.1 explorer
58 1.1 explorer #include <dev/pci/if_ntwoc_pcireg.h>
59 1.1 explorer
60 1.1 explorer #if 0
61 1.1 explorer #define NTWO_DEBUG
62 1.1 explorer #endif
63 1.1 explorer
64 1.1 explorer #ifdef NTWO_DEBUG
65 1.1 explorer #define NTWO_DPRINTF(x) printf x
66 1.1 explorer #else
67 1.1 explorer #define NTWO_DPRINTF(x)
68 1.1 explorer #endif
69 1.1 explorer
70 1.1 explorer /*
71 1.1 explorer * Card specific config register location
72 1.1 explorer */
73 1.1 explorer #define PCI_CBMA_ASIC 0x10 /* Configuration Base Memory Address */
74 1.1 explorer #define PCI_CBMA_SCA 0x18
75 1.1 explorer
76 1.1 explorer struct ntwoc_pci_softc {
77 1.1 explorer /* Generic device stuff */
78 1.1 explorer struct device sc_dev; /* Common to all devices */
79 1.1 explorer
80 1.1 explorer /* PCI chipset glue */
81 1.1 explorer pci_intr_handle_t *sc_ih; /* Interrupt handler */
82 1.1 explorer pci_chipset_tag_t sc_sr; /* PCI chipset handle */
83 1.1 explorer
84 1.1 explorer bus_space_tag_t sc_asic_iot; /* space cookie (for ASIC) */
85 1.1 explorer bus_space_handle_t sc_asic_ioh; /* bus space handle (for ASIC) */
86 1.1 explorer
87 1.1 explorer struct sca_softc sc_sca; /* the SCA itself */
88 1.1 explorer };
89 1.1 explorer
90 1.1 explorer static int ntwoc_pci_match __P((struct device *, struct cfdata *, void *));
91 1.1 explorer static void ntwoc_pci_attach __P((struct device *, struct device *, void *));
92 1.1 explorer
93 1.1 explorer static int ntwoc_intr __P((void *));
94 1.1 explorer static void ntwoc_shutdown __P((void *sc));
95 1.1 explorer static void ntwoc_dtr_callback __P((void *, int, int));
96 1.1 explorer
97 1.1 explorer struct cfattach ntwoc_pci_ca = {
98 1.1 explorer sizeof(struct ntwoc_pci_softc), ntwoc_pci_match, ntwoc_pci_attach,
99 1.1 explorer };
100 1.1 explorer
101 1.1 explorer /*
102 1.1 explorer * Names for daughter card types. These match the NTWOC_DB_* defines.
103 1.1 explorer */
104 1.1 explorer char *ntwoc_db_names[] = {
105 1.1 explorer "V.35", "Unknown 0x01", "Test", "Unknown 0x03",
106 1.1 explorer "RS232", "Unknown 0x05", "RS422", "None"
107 1.1 explorer };
108 1.1 explorer
109 1.1 explorer static int
110 1.1 explorer ntwoc_pci_match(struct device *parent, struct cfdata *match, void *aux)
111 1.1 explorer {
112 1.1 explorer struct pci_attach_args *pa = (struct pci_attach_args *)aux;
113 1.1 explorer
114 1.1 explorer if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RISCOM)
115 1.1 explorer && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RISCOM_N2))
116 1.1 explorer return 1;
117 1.1 explorer
118 1.1 explorer return 0;
119 1.1 explorer }
120 1.1 explorer
121 1.1 explorer static void
122 1.1 explorer ntwoc_pci_attach(struct device *parent, struct device *self, void *aux)
123 1.1 explorer {
124 1.1 explorer struct ntwoc_pci_softc *sc = (void *)self;
125 1.1 explorer struct pci_attach_args *pa = aux;
126 1.1 explorer struct sca_softc *sca = &sc->sc_sca;
127 1.1 explorer pci_intr_handle_t ih;
128 1.1 explorer const char *intrstr;
129 1.1 explorer pcireg_t csr;
130 1.1 explorer u_int16_t frontend_cr;
131 1.1 explorer u_int16_t db0, db1;
132 1.1 explorer u_int numports;
133 1.1 explorer
134 1.1 explorer printf(": N2 Serial Interface\n");
135 1.1 explorer
136 1.1 explorer /*
137 1.1 explorer * Map in the ASIC configuration space
138 1.1 explorer */
139 1.1 explorer if (pci_mapreg_map(pa, PCI_CBMA_ASIC, PCI_MAPREG_TYPE_MEM, 0,
140 1.1 explorer &sc->sc_asic_iot, &sc->sc_asic_ioh, NULL, NULL)) {
141 1.1 explorer printf("%s: Can't map register space (ASIC)\n",
142 1.1 explorer sc->sc_dev.dv_xname);
143 1.1 explorer return;
144 1.1 explorer }
145 1.1 explorer /*
146 1.1 explorer * Map in the serial controller configuration space
147 1.1 explorer */
148 1.1 explorer if (pci_mapreg_map(pa, PCI_CBMA_SCA, PCI_MAPREG_TYPE_MEM, 0,
149 1.1 explorer &sca->sc_iot, &sca->sc_ioh, NULL, NULL)) {
150 1.1 explorer printf("%s: Can't map register space (SCA)\n",
151 1.1 explorer sc->sc_dev.dv_xname);
152 1.1 explorer return;
153 1.1 explorer }
154 1.1 explorer
155 1.1 explorer /*
156 1.1 explorer * Enable the card
157 1.1 explorer */
158 1.1 explorer csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
159 1.1 explorer pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);
160 1.1 explorer
161 1.1 explorer /*
162 1.1 explorer * Map and establish the interrupt
163 1.1 explorer */
164 1.1 explorer if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
165 1.1 explorer pa->pa_intrline, &ih)) {
166 1.1 explorer printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
167 1.1 explorer return;
168 1.1 explorer }
169 1.1 explorer intrstr = pci_intr_string(pa->pa_pc, ih);
170 1.1 explorer sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, ntwoc_intr, sc);
171 1.1 explorer if (sc->sc_ih == NULL) {
172 1.1 explorer printf("%s: couldn't establish interrupt",
173 1.1 explorer sc->sc_dev.dv_xname);
174 1.1 explorer if (intrstr != NULL)
175 1.1 explorer printf(" at %s", intrstr);
176 1.1 explorer printf("\n");
177 1.1 explorer return;
178 1.1 explorer }
179 1.1 explorer printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
180 1.1 explorer
181 1.1 explorer /*
182 1.1 explorer * Perform total black magic. This is not only extremely
183 1.1 explorer * disgusting, but it should be explained a lot more in the
184 1.1 explorer * card's documentation.
185 1.1 explorer *
186 1.1 explorer * From what I gather, this does nothing more than configure the
187 1.1 explorer * PCI to ISA translator ASIC the N2pci card uses.
188 1.1 explorer *
189 1.1 explorer * From the FreeBSD driver:
190 1.1 explorer * offset
191 1.1 explorer * 0x00 - Map Range - Mem-mapped to locate anywhere
192 1.1 explorer * 0x04 - Re-Map - PCI address decode enable
193 1.1 explorer * 0x18 - Bus Region - 32-bit bus, ready enable
194 1.1 explorer * 0x1c - Master Range - include all 16 MB
195 1.1 explorer * 0x20 - Master RAM - Map SCA Base at 0
196 1.1 explorer * 0x28 - Master Remap - direct master memory enable
197 1.1 explorer * 0x68 - Interrupt - Enable interrupt (0 to disable)
198 1.1 explorer */
199 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
200 1.1 explorer 0x00, 0xfffff000);
201 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
202 1.1 explorer 0x04, 1);
203 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
204 1.1 explorer 0x18, 0x40030043);
205 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
206 1.1 explorer 0x1c, 0xff000000);
207 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
208 1.1 explorer 0x20, 0);
209 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
210 1.1 explorer 0x28, 0xe9);
211 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
212 1.1 explorer 0x68, 0x10900);
213 1.1 explorer
214 1.1 explorer /*
215 1.1 explorer * pass the dma tag to the SCA
216 1.1 explorer */
217 1.1 explorer sca->sc_dmat = pa->pa_dmat;
218 1.1 explorer
219 1.1 explorer /*
220 1.1 explorer * Read the configuration information off the daughter card.
221 1.1 explorer */
222 1.1 explorer frontend_cr = bus_space_read_2(sca->sc_iot, sca->sc_ioh, NTWOC_FECR);
223 1.1 explorer NTWO_DPRINTF(("%s: frontend_cr = 0x%04x\n",
224 1.1 explorer sc->sc_dev.dv_xname, frontend_cr));
225 1.1 explorer
226 1.1 explorer db0 = (frontend_cr & NTWOC_FECR_ID0) >> NTWOC_FECR_ID0_SHIFT;
227 1.1 explorer db1 = (frontend_cr & NTWOC_FECR_ID1) >> NTWOC_FECR_ID1_SHIFT;
228 1.1 explorer
229 1.1 explorer /*
230 1.1 explorer * Port 1 HAS to be present. If it isn't, don't attach anything.
231 1.1 explorer */
232 1.1 explorer if (db0 == NTWOC_FE_ID_NONE) {
233 1.1 explorer printf("%s: no ports available\n", sc->sc_dev.dv_xname);
234 1.1 explorer return;
235 1.1 explorer }
236 1.1 explorer
237 1.1 explorer /*
238 1.1 explorer * Port 1 is present. Now, check to see if port 2 is also
239 1.1 explorer * present.
240 1.1 explorer */
241 1.1 explorer numports = 1;
242 1.1 explorer if (db1 != NTWOC_FE_ID_NONE)
243 1.1 explorer numports++;
244 1.1 explorer
245 1.1 explorer printf("%s: %d port%s\n", sc->sc_dev.dv_xname, numports,
246 1.1 explorer (numports > 1 ? "s" : ""));
247 1.1 explorer printf("%s: port 0 interface card: %s\n", sc->sc_dev.dv_xname,
248 1.1 explorer ntwoc_db_names[db0]);
249 1.1 explorer if (numports > 1)
250 1.1 explorer printf("%s: port 1 interface card: %s\n", sc->sc_dev.dv_xname,
251 1.1 explorer ntwoc_db_names[db1]);
252 1.1 explorer
253 1.1 explorer /*
254 1.1 explorer * enable the RS422 tristate transmit
255 1.1 explorer * diable clock output (use receiver clock for both)
256 1.1 explorer */
257 1.1 explorer frontend_cr |= (NTWOC_FECR_TE0 | NTWOC_FECR_TE1);
258 1.1 explorer frontend_cr &= ~(NTWOC_FECR_ETC0 | NTWOC_FECR_ETC1);
259 1.1 explorer bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
260 1.1 explorer NTWOC_FECR, frontend_cr);
261 1.1 explorer
262 1.1 explorer /*
263 1.1 explorer * initialize the SCA. This will allocate DMAable memory based
264 1.1 explorer * on the number of ports we passed in, the size of each
265 1.1 explorer * buffer, and the number of buffers per port.
266 1.1 explorer */
267 1.1 explorer sca->parent = &sc->sc_dev;
268 1.1 explorer sca->dtr_callback = ntwoc_dtr_callback;
269 1.1 explorer sca->dtr_aux = sc;
270 1.1 explorer sca_init(sca, numports);
271 1.1 explorer
272 1.1 explorer /*
273 1.1 explorer * always initialize port 0, since we have to have found it to
274 1.1 explorer * get this far. If we have two ports, attach the second
275 1.1 explorer * as well.
276 1.1 explorer */
277 1.1 explorer sca_port_attach(sca, 0);
278 1.1 explorer if (numports == 2)
279 1.1 explorer sca_port_attach(sca, 1);
280 1.1 explorer
281 1.1 explorer /*
282 1.1 explorer * Add shutdown hook so that DMA is disabled prior to reboot. Not
283 1.1 explorer * doing do could allow DMA to corrupt kernel memory during the
284 1.1 explorer * reboot before the driver initializes.
285 1.1 explorer */
286 1.1 explorer shutdownhook_establish(ntwoc_shutdown, sc);
287 1.1 explorer }
288 1.1 explorer
289 1.1 explorer static int
290 1.1 explorer ntwoc_intr(void *arg)
291 1.1 explorer {
292 1.1 explorer struct ntwoc_pci_softc *sc = (struct ntwoc_pci_softc *)arg;
293 1.1 explorer
294 1.1 explorer return sca_hardintr(&sc->sc_sca);
295 1.1 explorer }
296 1.1 explorer
297 1.1 explorer /*
298 1.1 explorer * shut down interrupts and DMA, so we don't trash the kernel on warm
299 1.1 explorer * boot. Also, lower DTR on each port and disable card interrupts.
300 1.1 explorer */
301 1.1 explorer static void
302 1.1 explorer ntwoc_shutdown(void *aux)
303 1.1 explorer {
304 1.1 explorer struct ntwoc_pci_softc *sc = aux;
305 1.1 explorer u_int16_t fecr;
306 1.1 explorer
307 1.1 explorer /*
308 1.1 explorer * shut down the SCA ports
309 1.1 explorer */
310 1.1 explorer sca_shutdown(&sc->sc_sca);
311 1.1 explorer
312 1.1 explorer /*
313 1.1 explorer * disable interupts for the whole card. Black magic, see comment
314 1.1 explorer * above.
315 1.1 explorer */
316 1.1 explorer bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
317 1.1 explorer 0x68, 0x10900);
318 1.1 explorer
319 1.1 explorer /*
320 1.1 explorer * lower DTR on both ports
321 1.1 explorer */
322 1.1 explorer fecr = bus_space_read_2(sc->sc_sca.sc_iot,
323 1.1 explorer sc->sc_sca.sc_ioh, NTWOC_FECR);
324 1.1 explorer fecr |= (NTWOC_FECR_DTR0 | NTWOC_FECR_DTR1);
325 1.1 explorer bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
326 1.1 explorer NTWOC_FECR, fecr);
327 1.1 explorer }
328 1.1 explorer
329 1.1 explorer static void
330 1.1 explorer ntwoc_dtr_callback(void *aux, int port, int state)
331 1.1 explorer {
332 1.1 explorer struct ntwoc_pci_softc *sc = aux;
333 1.1 explorer u_int16_t fecr;
334 1.1 explorer
335 1.1 explorer fecr = bus_space_read_2(sc->sc_sca.sc_iot,
336 1.1 explorer sc->sc_sca.sc_ioh, NTWOC_FECR);
337 1.1 explorer
338 1.1 explorer NTWO_DPRINTF(("port == %d, state == %d, old fecr: 0x%04x\n",
339 1.1 explorer port, state, fecr));
340 1.1 explorer
341 1.1 explorer if (port == 0) {
342 1.1 explorer if (state == 0)
343 1.1 explorer fecr |= NTWOC_FECR_DTR0;
344 1.1 explorer else
345 1.1 explorer fecr &= ~NTWOC_FECR_DTR0;
346 1.1 explorer } else {
347 1.1 explorer if (state == 0)
348 1.1 explorer fecr |= NTWOC_FECR_DTR1;
349 1.1 explorer else
350 1.1 explorer fecr &= ~NTWOC_FECR_DTR1;
351 1.1 explorer }
352 1.1 explorer
353 1.1 explorer NTWO_DPRINTF(("new fecr: 0x%04x\n", fecr));
354 1.1 explorer
355 1.1 explorer bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
356 1.1 explorer NTWOC_FECR, fecr);
357 1.1 explorer }
358