xref: /haiku/src/add-ons/kernel/bus_managers/firewire/fwohci_pci.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*-
2  * Copyright (c) 2003 Hidetoshi Shimokawa
3  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the acknowledgement as bellow:
16  *
17  *    This product includes software developed by K. Kobayashi and H. SHimokawa
18  *
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * $FreeBSD: src/sys/dev/firewire/fwohci_pci.c,v 1.60 2007/06/06 14:31:36 simokawa Exp $
35  */
36 
37 #include <OS.h>
38 #include <KernelExport.h>
39 #include <lock.h>
40 #include <SupportDefs.h>
41 #include <PCI.h>
42 
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <malloc.h>
47 
48 #include "util.h"
49 #include "fwdebug.h"
50 #include "fwglue.h"
51 #include "queue.h"
52 #include "firewire.h"
53 #include "iec13213.h"
54 #include "firewirereg.h"
55 
56 #include "fwdma.h"
57 #include "fwohcireg.h"
58 #include "fwohcivar.h"
59 
60 #define PCIM_CMD_IOS		0x0001
61 #define	PCIM_CMD_MEMEN		0x0002
62 #define	PCIM_CMD_BUSMASTEREN	0x0004
63 #define	PCIM_CMD_MWRICEN	0x0010
64 #define	PCIM_CMD_PERRESPEN	0x0040
65 #define	PCIM_CMD_SERRESPEN	0x0100
66 
67 extern pci_module_info	*gPci;
68 extern pci_info *pciInfo[MAX_CARDS];
69 extern fwohci_softc_t *gFwohci_softc[MAX_CARDS];
70 extern struct firewire_softc *gFirewire_softc[MAX_CARDS];
71 
72 status_t
73 fwohci_pci_detach(int index)
74 {
75 	fwohci_softc_t *sc = gFwohci_softc[index];
76 	int s;
77 
78 	s = splfw();
79 
80 	fwohci_stop(sc);
81 
82 //	bus_generic_detach(self);
83 	firewire_detach(gFirewire_softc[index]);
84 /*	if (sc->fc.bdev) {
85 		device_delete_child(self, sc->fc.bdev);
86 		sc->fc.bdev = NULL;
87 	}*/
88 
89 	/* disable interrupts that might have been switched on */
90 	OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
91 	remove_io_interrupt_handler (sc->irq, fwohci_intr, sc);
92 	delete_area(sc->regArea);
93 
94 	fwohci_detach(sc);
95 	mtx_destroy(FW_GMTX(&sc->fc));
96 	splx(s);
97 	return B_OK;
98 }
99 
100 static void
101 fwohci_pci_add_child(int index)
102 {
103 	struct fwohci_softc *sc;
104 	int err = 0;
105 
106 	sc = gFwohci_softc[index];
107 
108 /*	child = device_add_child(dev, name, unit);
109 	if (child == NULL)
110 		return (child);
111 
112 	sc->fc.bdev = child;
113 	device_set_ivars(child, (void *)&sc->fc);*/
114 
115 //	err = device_probe_and_attach(child);
116 	err = firewire_attach(&sc->fc, gFirewire_softc[index]);
117 
118 	if (err) {
119 		device_printf(dev, "firewire_attach failed with err=%d\n",
120 		    err);
121 		fwohci_pci_detach(index);
122 //		device_delete_child(dev, child);
123 		return;
124 	}
125 	/* XXX
126 	 * Clear the bus reset event flag to start transactions even when
127 	 * interrupt is disabled during the boot process.
128 	 */
129 //	if (cold) {
130 //		int s;
131 //		DELAY(250); /* 2 cycles */
132 //		s = splfw();
133 //		fwohci_poll((void *)sc, 0, -1);
134 //		splx(s);
135 //	}
136 
137 }
138 
139 status_t
140 fwohci_pci_attach(int index)
141 {
142 	fwohci_softc_t *sc = gFwohci_softc[index];
143 	pci_info *info = pciInfo[index];
144 	uint32 olatency, latency, ocache_line, cache_line;
145 	uint32 val;
146 
147 	mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF);
148 
149 	val = gPci->read_pci_config(info->bus, info->device, info->function,
150 			PCI_command, 2);
151 	val |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
152 
153 #if 1  /* for broken hardware */
154 	val &= ~PCIM_CMD_MWRICEN;
155 	val &= ~(PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN);
156 #endif
157 	gPci->write_pci_config(info->bus, info->device, info->function,
158 			PCI_command, 2, val);
159 
160 	/*
161 	 * Some Sun PCIO-2 FireWire controllers have their intpin register
162 	 * bogusly set to 0, although it should be 3. Correct that.
163 	 */
164 	if (info->vendor_id == FW_VENDORID_SUN && info->device_id == (FW_DEVICE_PCIO2FW >> 16) &&
165 			info->u.h0.interrupt_pin == 0)
166 		info->u.h0.interrupt_pin = 3;
167 
168 	latency = olatency = gPci->read_pci_config(info->bus, info->device, info->function,
169 			PCI_latency, 1);
170 #define DEF_LATENCY 0x20
171 	if (olatency < DEF_LATENCY) {
172 		latency = DEF_LATENCY;
173 		gPci->write_pci_config(info->bus, info->device, info->function,
174 				PCI_latency, 1, latency);
175 	}
176 
177 	cache_line = ocache_line = gPci->read_pci_config(info->bus, info->device,
178 			info->function, PCI_line_size, 1);
179 #define DEF_CACHE_LINE 8
180 	if (ocache_line < DEF_CACHE_LINE) {
181 		cache_line = DEF_CACHE_LINE;
182 		gPci->write_pci_config(info->bus, info->device, info->function,
183 				PCI_line_size, 1, cache_line);
184 	}
185 	TRACE("latency timer %lx -> %lx.\n", olatency, latency);
186 	TRACE("cache size %lx -> %lx.\n", ocache_line, cache_line);
187 
188 	// get IRQ
189 	sc->irq = gPci->read_pci_config(info->bus, info->device, info->function,
190 			PCI_interrupt_line, 1);
191 	if (sc->irq == 0 || sc->irq == 0xff) {
192 		ERROR("no IRQ assigned\n");
193 		goto err;
194 	}
195 	TRACE("IRQ %d\n", sc->irq);
196 
197 	// map registers into memory
198 //	val = gPci->read_pci_config(info->bus, info->device, info->function, 0x14, 4);
199 //	val &= PCI_address_memory_32_mask;
200 //	TRACE("hardware register address %p\n", (void *) val);
201 	TRACE("hardware register address %lx\n", info->u.h0.base_registers[0]);
202 	sc->regArea = map_mem(&sc->regAddr, (void *)info->u.h0.base_registers[0], 0x800,
203 			B_READ_AREA | B_WRITE_AREA, "fw ohci register");
204 	if (sc->regArea < B_OK) {
205 		ERROR("can't map hardware registers\n");
206 		goto err;
207 	}
208 	TRACE("mapped registers to %p\n", sc->regAddr);
209 
210 	// setup interrupt handler
211 	if (install_io_interrupt_handler(sc->irq, fwohci_intr,
212 				sc, 0) < B_OK) {
213 		ERROR("can't install interrupt handler\n");
214 		goto err;
215 	}
216 
217 	if (fwohci_init(sc) < B_OK){
218 
219 		ERROR("fwohci_init failed");
220 		goto err;
221 	}
222 	fwohci_pci_add_child(index);
223 	return B_OK;
224 err:
225 	delete_area(sc->regArea);
226 	mtx_destroy(FW_GMTX(&sc->fc));
227 	return B_ERROR;
228 }
229