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
fwohci_pci_detach(int index)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
fwohci_pci_add_child(int index)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
fwohci_pci_attach(int index)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