fwohci.c revision 1.111 1 1.111 dogcow /* $NetBSD: fwohci.c,v 1.111 2007/11/06 12:32:12 dogcow Exp $ */
2 1.91 christos
3 1.1 matt /*-
4 1.89 kiyohara * Copyright (c) 2003 Hidetoshi Shimokawa
5 1.89 kiyohara * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
6 1.1 matt * All rights reserved.
7 1.1 matt *
8 1.1 matt * Redistribution and use in source and binary forms, with or without
9 1.1 matt * modification, are permitted provided that the following conditions
10 1.1 matt * are met:
11 1.1 matt * 1. Redistributions of source code must retain the above copyright
12 1.1 matt * notice, this list of conditions and the following disclaimer.
13 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 matt * notice, this list of conditions and the following disclaimer in the
15 1.1 matt * documentation and/or other materials provided with the distribution.
16 1.1 matt * 3. All advertising materials mentioning features or use of this software
17 1.89 kiyohara * must display the acknowledgement as bellow:
18 1.89 kiyohara *
19 1.89 kiyohara * This product includes software developed by K. Kobayashi and H. Shimokawa
20 1.89 kiyohara *
21 1.89 kiyohara * 4. The name of the author may not be used to endorse or promote products
22 1.89 kiyohara * derived from this software without specific prior written permission.
23 1.1 matt *
24 1.89 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 1.89 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 1.89 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 1.89 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28 1.89 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 1.89 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 1.89 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 1.89 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 1.89 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 1.89 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 1.1 matt * POSSIBILITY OF SUCH DAMAGE.
35 1.100 blymn *
36 1.110 kiyohara * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.93 2007/06/08 09:04:30 simokawa Exp $
37 1.89 kiyohara *
38 1.1 matt */
39 1.1 matt
40 1.89 kiyohara #define ATRQ_CH 0
41 1.89 kiyohara #define ATRS_CH 1
42 1.89 kiyohara #define ARRQ_CH 2
43 1.89 kiyohara #define ARRS_CH 3
44 1.89 kiyohara #define ITX_CH 4
45 1.89 kiyohara #define IRX_CH 0x24
46 1.3 onoe
47 1.89 kiyohara #if defined(__FreeBSD__)
48 1.89 kiyohara #include <sys/param.h>
49 1.89 kiyohara #include <sys/systm.h>
50 1.89 kiyohara #include <sys/mbuf.h>
51 1.89 kiyohara #include <sys/malloc.h>
52 1.89 kiyohara #include <sys/sockio.h>
53 1.89 kiyohara #include <sys/sysctl.h>
54 1.89 kiyohara #include <sys/bus.h>
55 1.89 kiyohara #include <sys/kernel.h>
56 1.89 kiyohara #include <sys/conf.h>
57 1.89 kiyohara #include <sys/endian.h>
58 1.110 kiyohara #include <sys/kdb.h>
59 1.45 lukem
60 1.111 dogcow #include <sys/bus.h>
61 1.91 christos #include <sys/cdefs.h>
62 1.111 dogcow
63 1.111 dogcow __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.111 2007/11/06 12:32:12 dogcow Exp $");
64 1.45 lukem
65 1.89 kiyohara #if defined(__DragonFly__) || __FreeBSD_version < 500000
66 1.89 kiyohara #include <machine/clock.h> /* for DELAY() */
67 1.89 kiyohara #endif
68 1.3 onoe
69 1.89 kiyohara #ifdef __DragonFly__
70 1.89 kiyohara #include "fw_port.h"
71 1.89 kiyohara #include "firewire.h"
72 1.89 kiyohara #include "firewirereg.h"
73 1.89 kiyohara #include "fwdma.h"
74 1.89 kiyohara #include "fwohcireg.h"
75 1.89 kiyohara #include "fwohcivar.h"
76 1.89 kiyohara #include "firewire_phy.h"
77 1.89 kiyohara #else
78 1.89 kiyohara #include <dev/firewire/fw_port.h>
79 1.89 kiyohara #include <dev/firewire/firewire.h>
80 1.89 kiyohara #include <dev/firewire/firewirereg.h>
81 1.89 kiyohara #include <dev/firewire/fwdma.h>
82 1.89 kiyohara #include <dev/firewire/fwohcireg.h>
83 1.89 kiyohara #include <dev/firewire/fwohcivar.h>
84 1.89 kiyohara #include <dev/firewire/firewire_phy.h>
85 1.89 kiyohara #endif
86 1.89 kiyohara #elif defined(__NetBSD__)
87 1.1 matt #include <sys/param.h>
88 1.1 matt #include <sys/device.h>
89 1.89 kiyohara #include <sys/errno.h>
90 1.89 kiyohara #include <sys/conf.h>
91 1.7 onoe #include <sys/kernel.h>
92 1.3 onoe #include <sys/malloc.h>
93 1.3 onoe #include <sys/mbuf.h>
94 1.89 kiyohara #include <sys/proc.h>
95 1.89 kiyohara #include <sys/reboot.h>
96 1.89 kiyohara #include <sys/sysctl.h>
97 1.89 kiyohara #include <sys/systm.h>
98 1.7 onoe
99 1.109 ad #include <sys/bus.h>
100 1.1 matt
101 1.89 kiyohara #include <dev/ieee1394/fw_port.h>
102 1.89 kiyohara #include <dev/ieee1394/firewire.h>
103 1.89 kiyohara #include <dev/ieee1394/firewirereg.h>
104 1.89 kiyohara #include <dev/ieee1394/fwdma.h>
105 1.1 matt #include <dev/ieee1394/fwohcireg.h>
106 1.1 matt #include <dev/ieee1394/fwohcivar.h>
107 1.89 kiyohara #include <dev/ieee1394/firewire_phy.h>
108 1.105 kiyohara
109 1.105 kiyohara #include "ioconf.h"
110 1.5 matt #endif
111 1.24 jmc
112 1.89 kiyohara #undef OHCI_DEBUG
113 1.5 matt
114 1.89 kiyohara static int nocyclemaster = 0;
115 1.110 kiyohara int firewire_phydma_enable = 1;
116 1.89 kiyohara #if defined(__FreeBSD__)
117 1.89 kiyohara SYSCTL_DECL(_hw_firewire);
118 1.89 kiyohara SYSCTL_INT(_hw_firewire, OID_AUTO, nocyclemaster, CTLFLAG_RW, &nocyclemaster, 0,
119 1.89 kiyohara "Do not send cycle start packets");
120 1.110 kiyohara SYSCTL_INT(_hw_firewire, OID_AUTO, phydma_enable, CTLFLAG_RW,
121 1.110 kiyohara &firewire_phydma_enable, 1, "Allow physical request DMA from firewire");
122 1.110 kiyohara TUNABLE_INT("hw.firewire.phydma_enable", &firewire_phydma_enable);
123 1.89 kiyohara #elif defined(__NetBSD__)
124 1.89 kiyohara /*
125 1.89 kiyohara * Setup sysctl(3) MIB, hw.fwohci.*
126 1.89 kiyohara *
127 1.89 kiyohara * TBD condition CTLFLAG_PERMANENT on being an LKM or not
128 1.89 kiyohara */
129 1.89 kiyohara SYSCTL_SETUP(sysctl_fwohci, "sysctl fwohci(4) subtree setup")
130 1.89 kiyohara {
131 1.110 kiyohara int rc, fwohci_node_num;
132 1.89 kiyohara const struct sysctlnode *node;
133 1.89 kiyohara
134 1.89 kiyohara if ((rc = sysctl_createv(clog, 0, NULL, NULL,
135 1.89 kiyohara CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
136 1.89 kiyohara NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
137 1.89 kiyohara goto err;
138 1.89 kiyohara }
139 1.89 kiyohara
140 1.89 kiyohara if ((rc = sysctl_createv(clog, 0, NULL, &node,
141 1.89 kiyohara CTLFLAG_PERMANENT, CTLTYPE_NODE, "fwohci",
142 1.89 kiyohara SYSCTL_DESCR("fwohci controls"),
143 1.89 kiyohara NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
144 1.89 kiyohara goto err;
145 1.89 kiyohara }
146 1.110 kiyohara fwohci_node_num = node->sysctl_num;
147 1.89 kiyohara
148 1.89 kiyohara /* fwohci no cyclemaster flag */
149 1.89 kiyohara if ((rc = sysctl_createv(clog, 0, NULL, &node,
150 1.100 blymn CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
151 1.89 kiyohara "nocyclemaster", SYSCTL_DESCR("Do not send cycle start packets"),
152 1.89 kiyohara NULL, 0, &nocyclemaster,
153 1.110 kiyohara 0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) {
154 1.110 kiyohara goto err;
155 1.110 kiyohara }
156 1.110 kiyohara
157 1.110 kiyohara /* fwohci physical request DMA enable */
158 1.110 kiyohara if ((rc = sysctl_createv(clog, 0, NULL, &node,
159 1.110 kiyohara CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "phydma_enable",
160 1.110 kiyohara SYSCTL_DESCR("Allow physical request DMA from firewire"),
161 1.110 kiyohara NULL, 0, &firewire_phydma_enable,
162 1.110 kiyohara 0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) {
163 1.89 kiyohara goto err;
164 1.89 kiyohara }
165 1.89 kiyohara return;
166 1.89 kiyohara
167 1.89 kiyohara err:
168 1.89 kiyohara printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
169 1.89 kiyohara }
170 1.89 kiyohara #endif
171 1.89 kiyohara
172 1.90 drochner static const char * const dbcode[16] = {"OUTM", "OUTL","INPM","INPL",
173 1.90 drochner "STOR","LOAD","NOP ","STOP",
174 1.90 drochner "", "", "", "", "", "", "", ""};
175 1.89 kiyohara
176 1.90 drochner static const char * const dbkey[8] = {"ST0", "ST1","ST2","ST3",
177 1.89 kiyohara "UNDEF","REG","SYS","DEV"};
178 1.90 drochner static const char * const dbcond[4] = {"NEV","C=1", "C=0", "ALL"};
179 1.90 drochner static const char * const fwohcicode[32] = {
180 1.89 kiyohara "No stat","Undef","long","miss Ack err",
181 1.110 kiyohara "FIFO underrun","FIFO overrun","desc err", "data read err",
182 1.89 kiyohara "data write err","bus reset","timeout","tcode err",
183 1.89 kiyohara "Undef","Undef","unknown event","flushed",
184 1.89 kiyohara "Undef","ack complete","ack pend","Undef",
185 1.89 kiyohara "ack busy_X","ack busy_A","ack busy_B","Undef",
186 1.89 kiyohara "Undef","Undef","Undef","ack tardy",
187 1.89 kiyohara "Undef","ack data_err","ack type_err",""};
188 1.89 kiyohara
189 1.89 kiyohara #define MAX_SPEED 3
190 1.90 drochner extern const char *fw_linkspeed[];
191 1.90 drochner static uint32_t const tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
192 1.89 kiyohara
193 1.90 drochner static const struct tcode_info tinfo[] = {
194 1.110 kiyohara /* hdr_len block flag valid_response*/
195 1.110 kiyohara /* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES},
196 1.110 kiyohara /* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES},
197 1.110 kiyohara /* 2 WRES */ {12, FWTI_RES, 0xff},
198 1.110 kiyohara /* 3 XXX */ { 0, 0, 0xff},
199 1.110 kiyohara /* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ},
200 1.110 kiyohara /* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB},
201 1.110 kiyohara /* 6 RRESQ */ {16, FWTI_RES, 0xff},
202 1.110 kiyohara /* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff},
203 1.110 kiyohara /* 8 CYCS */ { 0, 0, 0xff},
204 1.110 kiyohara /* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES},
205 1.110 kiyohara /* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR, 0xff},
206 1.110 kiyohara /* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff},
207 1.110 kiyohara /* c XXX */ { 0, 0, 0xff},
208 1.110 kiyohara /* d XXX */ { 0, 0, 0xff},
209 1.110 kiyohara /* e PHY */ {12, FWTI_REQ, 0xff},
210 1.110 kiyohara /* f XXX */ { 0, 0, 0xff}
211 1.89 kiyohara };
212 1.8 onoe
213 1.89 kiyohara #define OHCI_WRITE_SIGMASK 0xffff0000
214 1.89 kiyohara #define OHCI_READ_SIGMASK 0xffff0000
215 1.62 haya
216 1.89 kiyohara #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
217 1.89 kiyohara #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
218 1.62 haya
219 1.89 kiyohara static void fwohci_ibr (struct firewire_comm *);
220 1.89 kiyohara static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *);
221 1.89 kiyohara static void fwohci_db_free (struct fwohci_dbch *);
222 1.89 kiyohara static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int);
223 1.89 kiyohara static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *);
224 1.89 kiyohara static void fwohci_start_atq (struct firewire_comm *);
225 1.89 kiyohara static void fwohci_start_ats (struct firewire_comm *);
226 1.89 kiyohara static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *);
227 1.89 kiyohara static uint32_t fwphy_wrdata ( struct fwohci_softc *, uint32_t, uint32_t);
228 1.89 kiyohara static uint32_t fwphy_rddata ( struct fwohci_softc *, uint32_t);
229 1.89 kiyohara static int fwohci_rx_enable (struct fwohci_softc *, struct fwohci_dbch *);
230 1.89 kiyohara static int fwohci_tx_enable (struct fwohci_softc *, struct fwohci_dbch *);
231 1.89 kiyohara static int fwohci_irx_enable (struct firewire_comm *, int);
232 1.89 kiyohara static int fwohci_irx_disable (struct firewire_comm *, int);
233 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
234 1.89 kiyohara static void fwohci_irx_post (struct firewire_comm *, uint32_t *);
235 1.89 kiyohara #endif
236 1.89 kiyohara static int fwohci_itxbuf_enable (struct firewire_comm *, int);
237 1.89 kiyohara static int fwohci_itx_disable (struct firewire_comm *, int);
238 1.89 kiyohara static void fwohci_timeout (void *);
239 1.89 kiyohara static void fwohci_set_intr (struct firewire_comm *, int);
240 1.89 kiyohara
241 1.89 kiyohara static int fwohci_add_rx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *);
242 1.89 kiyohara static int fwohci_add_tx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int);
243 1.89 kiyohara static void dump_db (struct fwohci_softc *, uint32_t);
244 1.89 kiyohara static void print_db (struct fwohcidb_tr *, struct fwohcidb *, uint32_t , uint32_t);
245 1.89 kiyohara static void dump_dma (struct fwohci_softc *, uint32_t);
246 1.89 kiyohara static uint32_t fwohci_cyctimer (struct firewire_comm *);
247 1.89 kiyohara static void fwohci_rbuf_update (struct fwohci_softc *, int);
248 1.89 kiyohara static void fwohci_tbuf_update (struct fwohci_softc *, int);
249 1.89 kiyohara void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *);
250 1.110 kiyohara static void fwohci_task_busreset(void *, int);
251 1.110 kiyohara static void fwohci_task_sid(void *, int);
252 1.110 kiyohara static void fwohci_task_dma(void *, int);
253 1.89 kiyohara #if defined(__NetBSD__)
254 1.89 kiyohara int fwohci_print(void *, const char *);
255 1.5 matt #endif
256 1.5 matt
257 1.89 kiyohara /*
258 1.89 kiyohara * memory allocated for DMA programs
259 1.89 kiyohara */
260 1.89 kiyohara #define DMA_PROG_ALLOC (8 * PAGE_SIZE)
261 1.1 matt
262 1.89 kiyohara #define NDB FWMAXQUEUE
263 1.89 kiyohara
264 1.89 kiyohara #define OHCI_VERSION 0x00
265 1.89 kiyohara #define OHCI_ATRETRY 0x08
266 1.89 kiyohara #define OHCI_CROMHDR 0x18
267 1.89 kiyohara #define OHCI_BUS_OPT 0x20
268 1.89 kiyohara #define OHCI_BUSIRMC (1 << 31)
269 1.89 kiyohara #define OHCI_BUSCMC (1 << 30)
270 1.89 kiyohara #define OHCI_BUSISC (1 << 29)
271 1.89 kiyohara #define OHCI_BUSBMC (1 << 28)
272 1.89 kiyohara #define OHCI_BUSPMC (1 << 27)
273 1.89 kiyohara #define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
274 1.89 kiyohara OHCI_BUSBMC | OHCI_BUSPMC
275 1.89 kiyohara
276 1.89 kiyohara #define OHCI_EUID_HI 0x24
277 1.89 kiyohara #define OHCI_EUID_LO 0x28
278 1.89 kiyohara
279 1.89 kiyohara #define OHCI_CROMPTR 0x34
280 1.89 kiyohara #define OHCI_HCCCTL 0x50
281 1.89 kiyohara #define OHCI_HCCCTLCLR 0x54
282 1.89 kiyohara #define OHCI_AREQHI 0x100
283 1.89 kiyohara #define OHCI_AREQHICLR 0x104
284 1.89 kiyohara #define OHCI_AREQLO 0x108
285 1.89 kiyohara #define OHCI_AREQLOCLR 0x10c
286 1.89 kiyohara #define OHCI_PREQHI 0x110
287 1.89 kiyohara #define OHCI_PREQHICLR 0x114
288 1.89 kiyohara #define OHCI_PREQLO 0x118
289 1.89 kiyohara #define OHCI_PREQLOCLR 0x11c
290 1.89 kiyohara #define OHCI_PREQUPPER 0x120
291 1.89 kiyohara
292 1.89 kiyohara #define OHCI_SID_BUF 0x64
293 1.89 kiyohara #define OHCI_SID_CNT 0x68
294 1.89 kiyohara #define OHCI_SID_ERR (1 << 31)
295 1.89 kiyohara #define OHCI_SID_CNT_MASK 0xffc
296 1.89 kiyohara
297 1.89 kiyohara #define OHCI_IT_STAT 0x90
298 1.89 kiyohara #define OHCI_IT_STATCLR 0x94
299 1.89 kiyohara #define OHCI_IT_MASK 0x98
300 1.89 kiyohara #define OHCI_IT_MASKCLR 0x9c
301 1.89 kiyohara
302 1.89 kiyohara #define OHCI_IR_STAT 0xa0
303 1.89 kiyohara #define OHCI_IR_STATCLR 0xa4
304 1.89 kiyohara #define OHCI_IR_MASK 0xa8
305 1.89 kiyohara #define OHCI_IR_MASKCLR 0xac
306 1.89 kiyohara
307 1.89 kiyohara #define OHCI_LNKCTL 0xe0
308 1.89 kiyohara #define OHCI_LNKCTLCLR 0xe4
309 1.89 kiyohara
310 1.89 kiyohara #define OHCI_PHYACCESS 0xec
311 1.89 kiyohara #define OHCI_CYCLETIMER 0xf0
312 1.89 kiyohara
313 1.89 kiyohara #define OHCI_DMACTL(off) (off)
314 1.89 kiyohara #define OHCI_DMACTLCLR(off) (off + 4)
315 1.89 kiyohara #define OHCI_DMACMD(off) (off + 0xc)
316 1.89 kiyohara #define OHCI_DMAMATCH(off) (off + 0x10)
317 1.89 kiyohara
318 1.89 kiyohara #define OHCI_ATQOFF 0x180
319 1.89 kiyohara #define OHCI_ATQCTL OHCI_ATQOFF
320 1.89 kiyohara #define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4)
321 1.89 kiyohara #define OHCI_ATQCMD (OHCI_ATQOFF + 0xc)
322 1.89 kiyohara #define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10)
323 1.89 kiyohara
324 1.89 kiyohara #define OHCI_ATSOFF 0x1a0
325 1.89 kiyohara #define OHCI_ATSCTL OHCI_ATSOFF
326 1.89 kiyohara #define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4)
327 1.89 kiyohara #define OHCI_ATSCMD (OHCI_ATSOFF + 0xc)
328 1.89 kiyohara #define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10)
329 1.89 kiyohara
330 1.89 kiyohara #define OHCI_ARQOFF 0x1c0
331 1.89 kiyohara #define OHCI_ARQCTL OHCI_ARQOFF
332 1.89 kiyohara #define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4)
333 1.89 kiyohara #define OHCI_ARQCMD (OHCI_ARQOFF + 0xc)
334 1.89 kiyohara #define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10)
335 1.89 kiyohara
336 1.89 kiyohara #define OHCI_ARSOFF 0x1e0
337 1.89 kiyohara #define OHCI_ARSCTL OHCI_ARSOFF
338 1.89 kiyohara #define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4)
339 1.89 kiyohara #define OHCI_ARSCMD (OHCI_ARSOFF + 0xc)
340 1.89 kiyohara #define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10)
341 1.89 kiyohara
342 1.89 kiyohara #define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH))
343 1.89 kiyohara #define OHCI_ITCTL(CH) (OHCI_ITOFF(CH))
344 1.89 kiyohara #define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4)
345 1.89 kiyohara #define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc)
346 1.89 kiyohara
347 1.89 kiyohara #define OHCI_IROFF(CH) (0x400 + 0x20 * (CH))
348 1.89 kiyohara #define OHCI_IRCTL(CH) (OHCI_IROFF(CH))
349 1.89 kiyohara #define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4)
350 1.89 kiyohara #define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc)
351 1.89 kiyohara #define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10)
352 1.89 kiyohara
353 1.89 kiyohara #if defined(__FreeBSD__)
354 1.89 kiyohara d_ioctl_t fwohci_ioctl;
355 1.89 kiyohara #elif defined(__NetBSD__)
356 1.89 kiyohara dev_type_ioctl(fwohci_ioctl);
357 1.89 kiyohara #endif
358 1.89 kiyohara
359 1.89 kiyohara /*
360 1.89 kiyohara * Communication with PHY device
361 1.89 kiyohara */
362 1.110 kiyohara /* XXX need lock for phy access */
363 1.89 kiyohara static uint32_t
364 1.89 kiyohara fwphy_wrdata( struct fwohci_softc *sc, uint32_t addr, uint32_t data)
365 1.89 kiyohara {
366 1.89 kiyohara uint32_t fun;
367 1.89 kiyohara
368 1.89 kiyohara addr &= 0xf;
369 1.89 kiyohara data &= 0xff;
370 1.89 kiyohara
371 1.89 kiyohara fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
372 1.89 kiyohara OWRITE(sc, OHCI_PHYACCESS, fun);
373 1.89 kiyohara DELAY(100);
374 1.89 kiyohara
375 1.89 kiyohara return(fwphy_rddata( sc, addr));
376 1.89 kiyohara }
377 1.89 kiyohara
378 1.89 kiyohara static uint32_t
379 1.89 kiyohara fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
380 1.89 kiyohara {
381 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
382 1.89 kiyohara int i;
383 1.89 kiyohara uint32_t bm;
384 1.89 kiyohara
385 1.89 kiyohara #define OHCI_CSR_DATA 0x0c
386 1.89 kiyohara #define OHCI_CSR_COMP 0x10
387 1.89 kiyohara #define OHCI_CSR_CONT 0x14
388 1.89 kiyohara #define OHCI_BUS_MANAGER_ID 0
389 1.89 kiyohara
390 1.89 kiyohara OWRITE(sc, OHCI_CSR_DATA, node);
391 1.89 kiyohara OWRITE(sc, OHCI_CSR_COMP, 0x3f);
392 1.89 kiyohara OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
393 1.89 kiyohara for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
394 1.89 kiyohara DELAY(10);
395 1.89 kiyohara bm = OREAD(sc, OHCI_CSR_DATA);
396 1.89 kiyohara if((bm & 0x3f) == 0x3f)
397 1.89 kiyohara bm = node;
398 1.89 kiyohara if (firewire_debug)
399 1.110 kiyohara fw_printf(sc->fc.dev,
400 1.89 kiyohara "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
401 1.89 kiyohara
402 1.89 kiyohara return(bm);
403 1.89 kiyohara }
404 1.89 kiyohara
405 1.89 kiyohara static uint32_t
406 1.89 kiyohara fwphy_rddata(struct fwohci_softc *sc, u_int addr)
407 1.89 kiyohara {
408 1.89 kiyohara uint32_t fun, stat;
409 1.89 kiyohara u_int i, retry = 0;
410 1.89 kiyohara
411 1.89 kiyohara addr &= 0xf;
412 1.89 kiyohara #define MAX_RETRY 100
413 1.89 kiyohara again:
414 1.89 kiyohara OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
415 1.89 kiyohara fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
416 1.89 kiyohara OWRITE(sc, OHCI_PHYACCESS, fun);
417 1.89 kiyohara for ( i = 0 ; i < MAX_RETRY ; i ++ ){
418 1.89 kiyohara fun = OREAD(sc, OHCI_PHYACCESS);
419 1.89 kiyohara if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
420 1.3 onoe break;
421 1.89 kiyohara DELAY(100);
422 1.89 kiyohara }
423 1.89 kiyohara if(i >= MAX_RETRY) {
424 1.89 kiyohara if (firewire_debug)
425 1.110 kiyohara fw_printf(sc->fc.dev, "phy read failed(1).\n");
426 1.89 kiyohara if (++retry < MAX_RETRY) {
427 1.89 kiyohara DELAY(100);
428 1.89 kiyohara goto again;
429 1.89 kiyohara }
430 1.89 kiyohara }
431 1.89 kiyohara /* Make sure that SCLK is started */
432 1.89 kiyohara stat = OREAD(sc, FWOHCI_INTSTAT);
433 1.89 kiyohara if ((stat & OHCI_INT_REG_FAIL) != 0 ||
434 1.89 kiyohara ((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
435 1.89 kiyohara if (firewire_debug)
436 1.110 kiyohara fw_printf(sc->fc.dev, "phy read failed(2).\n");
437 1.89 kiyohara if (++retry < MAX_RETRY) {
438 1.89 kiyohara DELAY(100);
439 1.89 kiyohara goto again;
440 1.89 kiyohara }
441 1.89 kiyohara }
442 1.89 kiyohara if (firewire_debug || retry >= MAX_RETRY)
443 1.110 kiyohara fw_printf(sc->fc.dev,
444 1.89 kiyohara "fwphy_rddata: 0x%x loop=%d, retry=%d\n", addr, i, retry);
445 1.89 kiyohara #undef MAX_RETRY
446 1.89 kiyohara return((fun >> PHYDEV_RDDATA )& 0xff);
447 1.89 kiyohara }
448 1.89 kiyohara /* Device specific ioctl. */
449 1.89 kiyohara FW_IOCTL(fwohci)
450 1.89 kiyohara {
451 1.89 kiyohara FW_IOCTL_START;
452 1.89 kiyohara struct fwohci_softc *fc;
453 1.89 kiyohara int err = 0;
454 1.89 kiyohara struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data;
455 1.89 kiyohara uint32_t *dmach = (uint32_t *) data;
456 1.89 kiyohara
457 1.89 kiyohara if(sc == NULL){
458 1.89 kiyohara return(EINVAL);
459 1.89 kiyohara }
460 1.89 kiyohara fc = (struct fwohci_softc *)sc->fc;
461 1.89 kiyohara
462 1.89 kiyohara if (!data)
463 1.89 kiyohara return(EINVAL);
464 1.89 kiyohara
465 1.89 kiyohara switch (cmd) {
466 1.89 kiyohara case FWOHCI_WRREG:
467 1.89 kiyohara #define OHCI_MAX_REG 0x800
468 1.89 kiyohara if(reg->addr <= OHCI_MAX_REG){
469 1.89 kiyohara OWRITE(fc, reg->addr, reg->data);
470 1.89 kiyohara reg->data = OREAD(fc, reg->addr);
471 1.89 kiyohara }else{
472 1.89 kiyohara err = EINVAL;
473 1.89 kiyohara }
474 1.89 kiyohara break;
475 1.89 kiyohara case FWOHCI_RDREG:
476 1.89 kiyohara if(reg->addr <= OHCI_MAX_REG){
477 1.89 kiyohara reg->data = OREAD(fc, reg->addr);
478 1.89 kiyohara }else{
479 1.89 kiyohara err = EINVAL;
480 1.89 kiyohara }
481 1.89 kiyohara break;
482 1.89 kiyohara /* Read DMA descriptors for debug */
483 1.89 kiyohara case DUMPDMA:
484 1.89 kiyohara if(*dmach <= OHCI_MAX_DMA_CH ){
485 1.89 kiyohara dump_dma(fc, *dmach);
486 1.89 kiyohara dump_db(fc, *dmach);
487 1.89 kiyohara }else{
488 1.89 kiyohara err = EINVAL;
489 1.89 kiyohara }
490 1.89 kiyohara break;
491 1.89 kiyohara /* Read/Write Phy registers */
492 1.89 kiyohara #define OHCI_MAX_PHY_REG 0xf
493 1.89 kiyohara case FWOHCI_RDPHYREG:
494 1.89 kiyohara if (reg->addr <= OHCI_MAX_PHY_REG)
495 1.89 kiyohara reg->data = fwphy_rddata(fc, reg->addr);
496 1.89 kiyohara else
497 1.89 kiyohara err = EINVAL;
498 1.89 kiyohara break;
499 1.89 kiyohara case FWOHCI_WRPHYREG:
500 1.89 kiyohara if (reg->addr <= OHCI_MAX_PHY_REG)
501 1.89 kiyohara reg->data = fwphy_wrdata(fc, reg->addr, reg->data);
502 1.89 kiyohara else
503 1.89 kiyohara err = EINVAL;
504 1.89 kiyohara break;
505 1.89 kiyohara default:
506 1.89 kiyohara err = EINVAL;
507 1.89 kiyohara break;
508 1.3 onoe }
509 1.89 kiyohara return err;
510 1.89 kiyohara }
511 1.3 onoe
512 1.89 kiyohara static int
513 1.89 kiyohara fwohci_probe_phy(struct fwohci_softc *sc, device_t dev)
514 1.89 kiyohara {
515 1.89 kiyohara uint32_t reg, reg2;
516 1.89 kiyohara int e1394a = 1;
517 1.89 kiyohara /*
518 1.89 kiyohara * probe PHY parameters
519 1.89 kiyohara * 0. to prove PHY version, whether compliance of 1394a.
520 1.100 blymn * 1. to probe maximum speed supported by the PHY and
521 1.89 kiyohara * number of port supported by core-logic.
522 1.89 kiyohara * It is not actually available port on your PC .
523 1.89 kiyohara */
524 1.89 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
525 1.107 kiyohara DELAY(500);
526 1.107 kiyohara
527 1.89 kiyohara reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
528 1.89 kiyohara
529 1.89 kiyohara if((reg >> 5) != 7 ){
530 1.89 kiyohara sc->fc.mode &= ~FWPHYASYST;
531 1.89 kiyohara sc->fc.nport = reg & FW_PHY_NP;
532 1.89 kiyohara sc->fc.speed = reg & FW_PHY_SPD >> 6;
533 1.89 kiyohara if (sc->fc.speed > MAX_SPEED) {
534 1.110 kiyohara fw_printf(dev, "invalid speed %d (fixed to %d).\n",
535 1.89 kiyohara sc->fc.speed, MAX_SPEED);
536 1.89 kiyohara sc->fc.speed = MAX_SPEED;
537 1.89 kiyohara }
538 1.110 kiyohara fw_printf(dev, "Phy 1394 only %s, %d ports.\n",
539 1.90 drochner fw_linkspeed[sc->fc.speed], sc->fc.nport);
540 1.89 kiyohara }else{
541 1.89 kiyohara reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
542 1.89 kiyohara sc->fc.mode |= FWPHYASYST;
543 1.89 kiyohara sc->fc.nport = reg & FW_PHY_NP;
544 1.89 kiyohara sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
545 1.89 kiyohara if (sc->fc.speed > MAX_SPEED) {
546 1.110 kiyohara fw_printf(dev, "invalid speed %d (fixed to %d).\n",
547 1.89 kiyohara sc->fc.speed, MAX_SPEED);
548 1.89 kiyohara sc->fc.speed = MAX_SPEED;
549 1.89 kiyohara }
550 1.110 kiyohara fw_printf(dev, "Phy 1394a available %s, %d ports.\n",
551 1.90 drochner fw_linkspeed[sc->fc.speed], sc->fc.nport);
552 1.1 matt
553 1.89 kiyohara /* check programPhyEnable */
554 1.89 kiyohara reg2 = fwphy_rddata(sc, 5);
555 1.89 kiyohara #if 0
556 1.89 kiyohara if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
557 1.89 kiyohara #else /* XXX force to enable 1394a */
558 1.89 kiyohara if (e1394a) {
559 1.89 kiyohara #endif
560 1.89 kiyohara if (firewire_debug)
561 1.110 kiyohara fw_printf(dev, "Enable 1394a Enhancements\n");
562 1.89 kiyohara /* enable EAA EMC */
563 1.89 kiyohara reg2 |= 0x03;
564 1.89 kiyohara /* set aPhyEnhanceEnable */
565 1.89 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
566 1.89 kiyohara OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
567 1.92 christos }
568 1.92 christos #if 0
569 1.92 christos else {
570 1.89 kiyohara /* for safe */
571 1.89 kiyohara reg2 &= ~0x83;
572 1.89 kiyohara }
573 1.92 christos #endif
574 1.89 kiyohara reg2 = fwphy_wrdata(sc, 5, reg2);
575 1.89 kiyohara }
576 1.26 enami
577 1.89 kiyohara reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
578 1.89 kiyohara if((reg >> 5) == 7 ){
579 1.89 kiyohara reg = fwphy_rddata(sc, 4);
580 1.89 kiyohara reg |= 1 << 6;
581 1.89 kiyohara fwphy_wrdata(sc, 4, reg);
582 1.89 kiyohara reg = fwphy_rddata(sc, 4);
583 1.1 matt }
584 1.89 kiyohara return 0;
585 1.89 kiyohara }
586 1.1 matt
587 1.1 matt
588 1.89 kiyohara void
589 1.89 kiyohara fwohci_reset(struct fwohci_softc *sc, device_t dev)
590 1.89 kiyohara {
591 1.89 kiyohara int i, max_rec, speed;
592 1.89 kiyohara uint32_t reg, reg2;
593 1.89 kiyohara struct fwohcidb_tr *db_tr;
594 1.89 kiyohara
595 1.100 blymn /* Disable interrupts */
596 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
597 1.89 kiyohara
598 1.89 kiyohara /* Now stopping all DMA channels */
599 1.89 kiyohara OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
600 1.89 kiyohara OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
601 1.89 kiyohara OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
602 1.89 kiyohara OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
603 1.89 kiyohara
604 1.89 kiyohara OWRITE(sc, OHCI_IR_MASKCLR, ~0);
605 1.89 kiyohara for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
606 1.89 kiyohara OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
607 1.89 kiyohara OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
608 1.89 kiyohara }
609 1.89 kiyohara
610 1.89 kiyohara /* FLUSH FIFO and reset Transmitter/Reciever */
611 1.89 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
612 1.89 kiyohara if (firewire_debug)
613 1.110 kiyohara fw_printf(dev, "resetting OHCI...");
614 1.89 kiyohara i = 0;
615 1.89 kiyohara while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
616 1.89 kiyohara if (i++ > 100) break;
617 1.89 kiyohara DELAY(1000);
618 1.89 kiyohara }
619 1.89 kiyohara if (firewire_debug)
620 1.89 kiyohara printf("done (loop=%d)\n", i);
621 1.89 kiyohara
622 1.89 kiyohara /* Probe phy */
623 1.89 kiyohara fwohci_probe_phy(sc, dev);
624 1.89 kiyohara
625 1.89 kiyohara /* Probe link */
626 1.89 kiyohara reg = OREAD(sc, OHCI_BUS_OPT);
627 1.89 kiyohara reg2 = reg | OHCI_BUSFNC;
628 1.89 kiyohara max_rec = (reg & 0x0000f000) >> 12;
629 1.89 kiyohara speed = (reg & 0x00000007);
630 1.110 kiyohara fw_printf(dev, "Link %s, max_rec %d bytes.\n",
631 1.90 drochner fw_linkspeed[speed], MAXREC(max_rec));
632 1.89 kiyohara /* XXX fix max_rec */
633 1.89 kiyohara sc->fc.maxrec = sc->fc.speed + 8;
634 1.89 kiyohara if (max_rec != sc->fc.maxrec) {
635 1.89 kiyohara reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
636 1.110 kiyohara fw_printf(dev, "max_rec %d -> %d\n",
637 1.89 kiyohara MAXREC(max_rec), MAXREC(sc->fc.maxrec));
638 1.89 kiyohara }
639 1.89 kiyohara if (firewire_debug)
640 1.110 kiyohara fw_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
641 1.89 kiyohara OWRITE(sc, OHCI_BUS_OPT, reg2);
642 1.89 kiyohara
643 1.89 kiyohara /* Initialize registers */
644 1.89 kiyohara OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
645 1.89 kiyohara OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr);
646 1.89 kiyohara OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
647 1.89 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
648 1.89 kiyohara OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr);
649 1.89 kiyohara OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
650 1.89 kiyohara
651 1.89 kiyohara /* Enable link */
652 1.89 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
653 1.89 kiyohara
654 1.89 kiyohara /* Force to start async RX DMA */
655 1.89 kiyohara sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
656 1.89 kiyohara sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
657 1.89 kiyohara fwohci_rx_enable(sc, &sc->arrq);
658 1.89 kiyohara fwohci_rx_enable(sc, &sc->arrs);
659 1.89 kiyohara
660 1.89 kiyohara /* Initialize async TX */
661 1.89 kiyohara OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
662 1.89 kiyohara OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
663 1.89 kiyohara
664 1.89 kiyohara /* AT Retries */
665 1.89 kiyohara OWRITE(sc, FWOHCI_RETRY,
666 1.89 kiyohara /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
667 1.89 kiyohara (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ;
668 1.89 kiyohara
669 1.89 kiyohara sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
670 1.89 kiyohara sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
671 1.89 kiyohara sc->atrq.bottom = sc->atrq.top;
672 1.89 kiyohara sc->atrs.bottom = sc->atrs.top;
673 1.89 kiyohara
674 1.89 kiyohara for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ;
675 1.89 kiyohara i ++, db_tr = STAILQ_NEXT(db_tr, link)){
676 1.89 kiyohara db_tr->xfer = NULL;
677 1.89 kiyohara }
678 1.89 kiyohara for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ;
679 1.89 kiyohara i ++, db_tr = STAILQ_NEXT(db_tr, link)){
680 1.89 kiyohara db_tr->xfer = NULL;
681 1.89 kiyohara }
682 1.89 kiyohara
683 1.89 kiyohara
684 1.89 kiyohara /* Enable interrupts */
685 1.110 kiyohara sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID
686 1.100 blymn | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
687 1.89 kiyohara | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
688 1.89 kiyohara | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
689 1.110 kiyohara sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT;
690 1.110 kiyohara sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT;
691 1.110 kiyohara OWRITE(sc, FWOHCI_INTMASK, sc->intmask);
692 1.89 kiyohara fwohci_set_intr(&sc->fc, 1);
693 1.89 kiyohara }
694 1.3 onoe
695 1.89 kiyohara int
696 1.89 kiyohara fwohci_init(struct fwohci_softc *sc, device_t dev)
697 1.89 kiyohara {
698 1.89 kiyohara int i, mver;
699 1.89 kiyohara uint32_t reg;
700 1.89 kiyohara uint8_t ui[8];
701 1.89 kiyohara
702 1.89 kiyohara /* OHCI version */
703 1.89 kiyohara reg = OREAD(sc, OHCI_VERSION);
704 1.89 kiyohara mver = (reg >> 16) & 0xff;
705 1.110 kiyohara fw_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
706 1.89 kiyohara mver, reg & 0xff, (reg>>24) & 1);
707 1.89 kiyohara if (mver < 1 || mver > 9) {
708 1.110 kiyohara fw_printf(dev, "invalid OHCI version\n");
709 1.89 kiyohara return (ENXIO);
710 1.89 kiyohara }
711 1.89 kiyohara
712 1.89 kiyohara /* Available Isochronous DMA channel probe */
713 1.89 kiyohara OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
714 1.89 kiyohara OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
715 1.89 kiyohara reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
716 1.89 kiyohara OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
717 1.89 kiyohara OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
718 1.89 kiyohara for (i = 0; i < 0x20; i++)
719 1.89 kiyohara if ((reg & (1 << i)) == 0)
720 1.89 kiyohara break;
721 1.89 kiyohara sc->fc.nisodma = i;
722 1.110 kiyohara fw_printf(dev, "No. of Isochronous channels is %d.\n", i);
723 1.89 kiyohara if (i == 0)
724 1.89 kiyohara return (ENXIO);
725 1.89 kiyohara
726 1.89 kiyohara sc->fc.arq = &sc->arrq.xferq;
727 1.89 kiyohara sc->fc.ars = &sc->arrs.xferq;
728 1.89 kiyohara sc->fc.atq = &sc->atrq.xferq;
729 1.89 kiyohara sc->fc.ats = &sc->atrs.xferq;
730 1.89 kiyohara
731 1.89 kiyohara sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
732 1.89 kiyohara sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
733 1.89 kiyohara sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
734 1.89 kiyohara sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
735 1.89 kiyohara
736 1.89 kiyohara sc->arrq.xferq.start = NULL;
737 1.89 kiyohara sc->arrs.xferq.start = NULL;
738 1.89 kiyohara sc->atrq.xferq.start = fwohci_start_atq;
739 1.89 kiyohara sc->atrs.xferq.start = fwohci_start_ats;
740 1.89 kiyohara
741 1.89 kiyohara sc->arrq.xferq.buf = NULL;
742 1.89 kiyohara sc->arrs.xferq.buf = NULL;
743 1.89 kiyohara sc->atrq.xferq.buf = NULL;
744 1.89 kiyohara sc->atrs.xferq.buf = NULL;
745 1.89 kiyohara
746 1.89 kiyohara sc->arrq.xferq.dmach = -1;
747 1.89 kiyohara sc->arrs.xferq.dmach = -1;
748 1.89 kiyohara sc->atrq.xferq.dmach = -1;
749 1.89 kiyohara sc->atrs.xferq.dmach = -1;
750 1.89 kiyohara
751 1.89 kiyohara sc->arrq.ndesc = 1;
752 1.89 kiyohara sc->arrs.ndesc = 1;
753 1.89 kiyohara sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */
754 1.89 kiyohara sc->atrs.ndesc = 2;
755 1.89 kiyohara
756 1.89 kiyohara sc->arrq.ndb = NDB;
757 1.89 kiyohara sc->arrs.ndb = NDB / 2;
758 1.89 kiyohara sc->atrq.ndb = NDB;
759 1.89 kiyohara sc->atrs.ndb = NDB / 2;
760 1.89 kiyohara
761 1.89 kiyohara for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
762 1.89 kiyohara sc->fc.it[i] = &sc->it[i].xferq;
763 1.89 kiyohara sc->fc.ir[i] = &sc->ir[i].xferq;
764 1.89 kiyohara sc->it[i].xferq.dmach = i;
765 1.89 kiyohara sc->ir[i].xferq.dmach = i;
766 1.89 kiyohara sc->it[i].ndb = 0;
767 1.89 kiyohara sc->ir[i].ndb = 0;
768 1.89 kiyohara }
769 1.89 kiyohara
770 1.89 kiyohara sc->fc.tcode = tinfo;
771 1.89 kiyohara sc->fc.dev = dev;
772 1.89 kiyohara
773 1.89 kiyohara sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE,
774 1.89 kiyohara &sc->crom_dma, BUS_DMA_WAITOK);
775 1.89 kiyohara if(sc->fc.config_rom == NULL){
776 1.110 kiyohara fw_printf(dev, "config_rom alloc failed.");
777 1.89 kiyohara return ENOMEM;
778 1.3 onoe }
779 1.62 haya
780 1.89 kiyohara #if 0
781 1.89 kiyohara bzero(&sc->fc.config_rom[0], CROMSIZE);
782 1.89 kiyohara sc->fc.config_rom[1] = 0x31333934;
783 1.89 kiyohara sc->fc.config_rom[2] = 0xf000a002;
784 1.89 kiyohara sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
785 1.89 kiyohara sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
786 1.89 kiyohara sc->fc.config_rom[5] = 0;
787 1.89 kiyohara sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
788 1.89 kiyohara
789 1.89 kiyohara sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
790 1.89 kiyohara #endif
791 1.62 haya
792 1.89 kiyohara /* SID recieve buffer must align 2^11 */
793 1.89 kiyohara #define OHCI_SIDSIZE (1 << 11)
794 1.89 kiyohara sc->sid_buf = fwdma_malloc(&sc->fc, OHCI_SIDSIZE, OHCI_SIDSIZE,
795 1.89 kiyohara &sc->sid_dma, BUS_DMA_WAITOK);
796 1.89 kiyohara if (sc->sid_buf == NULL) {
797 1.110 kiyohara fw_printf(dev, "sid_buf alloc failed.");
798 1.89 kiyohara return ENOMEM;
799 1.89 kiyohara }
800 1.89 kiyohara
801 1.89 kiyohara fwdma_malloc(&sc->fc, sizeof(uint32_t), sizeof(uint32_t),
802 1.89 kiyohara &sc->dummy_dma, BUS_DMA_WAITOK);
803 1.89 kiyohara
804 1.89 kiyohara if (sc->dummy_dma.v_addr == NULL) {
805 1.110 kiyohara fw_printf(dev, "dummy_dma alloc failed.");
806 1.89 kiyohara return ENOMEM;
807 1.89 kiyohara }
808 1.89 kiyohara
809 1.89 kiyohara fwohci_db_init(sc, &sc->arrq);
810 1.89 kiyohara if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
811 1.89 kiyohara return ENOMEM;
812 1.89 kiyohara
813 1.89 kiyohara fwohci_db_init(sc, &sc->arrs);
814 1.89 kiyohara if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0)
815 1.89 kiyohara return ENOMEM;
816 1.89 kiyohara
817 1.89 kiyohara fwohci_db_init(sc, &sc->atrq);
818 1.89 kiyohara if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0)
819 1.89 kiyohara return ENOMEM;
820 1.89 kiyohara
821 1.89 kiyohara fwohci_db_init(sc, &sc->atrs);
822 1.89 kiyohara if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0)
823 1.89 kiyohara return ENOMEM;
824 1.89 kiyohara
825 1.89 kiyohara sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H);
826 1.89 kiyohara sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L);
827 1.89 kiyohara for( i = 0 ; i < 8 ; i ++)
828 1.89 kiyohara ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i);
829 1.110 kiyohara fw_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
830 1.89 kiyohara ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
831 1.89 kiyohara
832 1.89 kiyohara sc->fc.ioctl = fwohci_ioctl;
833 1.89 kiyohara sc->fc.cyctimer = fwohci_cyctimer;
834 1.89 kiyohara sc->fc.set_bmr = fwohci_set_bus_manager;
835 1.89 kiyohara sc->fc.ibr = fwohci_ibr;
836 1.89 kiyohara sc->fc.irx_enable = fwohci_irx_enable;
837 1.89 kiyohara sc->fc.irx_disable = fwohci_irx_disable;
838 1.3 onoe
839 1.89 kiyohara sc->fc.itx_enable = fwohci_itxbuf_enable;
840 1.89 kiyohara sc->fc.itx_disable = fwohci_itx_disable;
841 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
842 1.89 kiyohara sc->fc.irx_post = fwohci_irx_post;
843 1.89 kiyohara #else
844 1.89 kiyohara sc->fc.irx_post = NULL;
845 1.5 matt #endif
846 1.89 kiyohara sc->fc.itx_post = NULL;
847 1.89 kiyohara sc->fc.timeout = fwohci_timeout;
848 1.89 kiyohara sc->fc.poll = fwohci_poll;
849 1.89 kiyohara sc->fc.set_intr = fwohci_set_intr;
850 1.89 kiyohara
851 1.89 kiyohara sc->intmask = sc->irstat = sc->itstat = 0;
852 1.89 kiyohara
853 1.110 kiyohara /* Init task queue */
854 1.110 kiyohara sc->fc.taskqueue = fw_taskqueue_create_fast("fw_taskq", M_WAITOK,
855 1.110 kiyohara fw_taskqueue_thread_enqueue, &sc->fc.taskqueue);
856 1.110 kiyohara fw_taskqueue_start_threads(&sc->fc.taskqueue, 1, PI_NET, "fw%d_taskq",
857 1.110 kiyohara fw_get_unit(dev));
858 1.110 kiyohara FW_TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc);
859 1.110 kiyohara FW_TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc);
860 1.110 kiyohara FW_TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc);
861 1.110 kiyohara
862 1.89 kiyohara fw_init(&sc->fc);
863 1.89 kiyohara fwohci_reset(sc, dev);
864 1.89 kiyohara FWOHCI_INIT_END;
865 1.5 matt
866 1.1 matt return 0;
867 1.1 matt }
868 1.1 matt
869 1.89 kiyohara void
870 1.89 kiyohara fwohci_timeout(void *arg)
871 1.40 haya {
872 1.89 kiyohara struct fwohci_softc *sc;
873 1.40 haya
874 1.89 kiyohara sc = (struct fwohci_softc *)arg;
875 1.89 kiyohara }
876 1.40 haya
877 1.89 kiyohara uint32_t
878 1.89 kiyohara fwohci_cyctimer(struct firewire_comm *fc)
879 1.89 kiyohara {
880 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
881 1.89 kiyohara return(OREAD(sc, OHCI_CYCLETIMER));
882 1.40 haya }
883 1.40 haya
884 1.89 kiyohara FWOHCI_DETACH()
885 1.1 matt {
886 1.89 kiyohara int i;
887 1.62 haya
888 1.89 kiyohara FWOHCI_DETACH_START;
889 1.89 kiyohara if (sc->sid_buf != NULL)
890 1.89 kiyohara fwdma_free(&sc->fc, &sc->sid_dma);
891 1.89 kiyohara if (sc->fc.config_rom != NULL)
892 1.89 kiyohara fwdma_free(&sc->fc, &sc->crom_dma);
893 1.40 haya
894 1.89 kiyohara fwohci_db_free(&sc->arrq);
895 1.89 kiyohara fwohci_db_free(&sc->arrs);
896 1.62 haya
897 1.89 kiyohara fwohci_db_free(&sc->atrq);
898 1.89 kiyohara fwohci_db_free(&sc->atrs);
899 1.3 onoe
900 1.89 kiyohara for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
901 1.89 kiyohara fwohci_db_free(&sc->it[i]);
902 1.89 kiyohara fwohci_db_free(&sc->ir[i]);
903 1.1 matt }
904 1.89 kiyohara FWOHCI_DETACH_END;
905 1.89 kiyohara
906 1.89 kiyohara return 0;
907 1.3 onoe }
908 1.3 onoe
909 1.89 kiyohara #define LAST_DB(dbtr, db) do { \
910 1.89 kiyohara struct fwohcidb_tr *_dbtr = (dbtr); \
911 1.89 kiyohara int _cnt = _dbtr->dbcnt; \
912 1.89 kiyohara db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \
913 1.89 kiyohara } while (0)
914 1.100 blymn
915 1.24 jmc static void
916 1.89 kiyohara fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error)
917 1.24 jmc {
918 1.89 kiyohara struct fwohcidb_tr *db_tr;
919 1.89 kiyohara struct fwohcidb *db;
920 1.89 kiyohara bus_dma_segment_t *s;
921 1.89 kiyohara int i;
922 1.24 jmc
923 1.89 kiyohara db_tr = (struct fwohcidb_tr *)arg;
924 1.89 kiyohara db = &db_tr->db[db_tr->dbcnt];
925 1.89 kiyohara if (error) {
926 1.89 kiyohara if (firewire_debug || error != EFBIG)
927 1.89 kiyohara printf("fwohci_execute_db: error=%d\n", error);
928 1.89 kiyohara return;
929 1.89 kiyohara }
930 1.89 kiyohara for (i = 0; i < nseg; i++) {
931 1.89 kiyohara s = &segs[i];
932 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr);
933 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len);
934 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.res, 0);
935 1.89 kiyohara db++;
936 1.89 kiyohara db_tr->dbcnt++;
937 1.26 enami }
938 1.24 jmc }
939 1.24 jmc
940 1.24 jmc static void
941 1.89 kiyohara fwohci_execute_db2(void *arg, bus_dma_segment_t *segs, int nseg,
942 1.103 christos bus_size_t size, int error)
943 1.24 jmc {
944 1.89 kiyohara fwohci_execute_db(arg, segs, nseg, error);
945 1.89 kiyohara }
946 1.26 enami
947 1.89 kiyohara static void
948 1.89 kiyohara fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
949 1.89 kiyohara {
950 1.89 kiyohara int i, s;
951 1.89 kiyohara int tcode, hdr_len, pl_off;
952 1.89 kiyohara int fsegment = -1;
953 1.89 kiyohara uint32_t off;
954 1.89 kiyohara struct fw_xfer *xfer;
955 1.89 kiyohara struct fw_pkt *fp;
956 1.89 kiyohara struct fwohci_txpkthdr *ohcifp;
957 1.89 kiyohara struct fwohcidb_tr *db_tr;
958 1.89 kiyohara struct fwohcidb *db;
959 1.89 kiyohara uint32_t *ld;
960 1.90 drochner const struct tcode_info *info;
961 1.89 kiyohara static int maxdesc=0;
962 1.89 kiyohara
963 1.110 kiyohara FW_GLOCK_ASSERT(&sc->fc);
964 1.110 kiyohara
965 1.89 kiyohara if(&sc->atrq == dbch){
966 1.89 kiyohara off = OHCI_ATQOFF;
967 1.89 kiyohara }else if(&sc->atrs == dbch){
968 1.89 kiyohara off = OHCI_ATSOFF;
969 1.89 kiyohara }else{
970 1.89 kiyohara return;
971 1.26 enami }
972 1.24 jmc
973 1.89 kiyohara if (dbch->flags & FWOHCI_DBCH_FULL)
974 1.89 kiyohara return;
975 1.24 jmc
976 1.89 kiyohara s = splfw();
977 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
978 1.99 kiyohara BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
979 1.89 kiyohara db_tr = dbch->top;
980 1.89 kiyohara txloop:
981 1.89 kiyohara xfer = STAILQ_FIRST(&dbch->xferq.q);
982 1.89 kiyohara if(xfer == NULL){
983 1.89 kiyohara goto kick;
984 1.89 kiyohara }
985 1.110 kiyohara #if 0
986 1.89 kiyohara if(dbch->xferq.queued == 0 ){
987 1.110 kiyohara fw_printf(sc->fc.dev, "TX queue empty\n");
988 1.89 kiyohara }
989 1.110 kiyohara #endif
990 1.89 kiyohara STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
991 1.89 kiyohara db_tr->xfer = xfer;
992 1.110 kiyohara xfer->flag = FWXF_START;
993 1.89 kiyohara
994 1.89 kiyohara fp = &xfer->send.hdr;
995 1.89 kiyohara tcode = fp->mode.common.tcode;
996 1.89 kiyohara
997 1.89 kiyohara ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
998 1.89 kiyohara info = &tinfo[tcode];
999 1.89 kiyohara hdr_len = pl_off = info->hdr_len;
1000 1.89 kiyohara
1001 1.89 kiyohara ld = &ohcifp->mode.ld[0];
1002 1.89 kiyohara ld[0] = ld[1] = ld[2] = ld[3] = 0;
1003 1.89 kiyohara for( i = 0 ; i < pl_off ; i+= 4)
1004 1.89 kiyohara ld[i/4] = fp->mode.ld[i/4];
1005 1.89 kiyohara
1006 1.89 kiyohara ohcifp->mode.common.spd = xfer->send.spd & 0x7;
1007 1.89 kiyohara if (tcode == FWTCODE_STREAM ){
1008 1.89 kiyohara hdr_len = 8;
1009 1.89 kiyohara ohcifp->mode.stream.len = fp->mode.stream.len;
1010 1.89 kiyohara } else if (tcode == FWTCODE_PHY) {
1011 1.89 kiyohara hdr_len = 12;
1012 1.89 kiyohara ld[1] = fp->mode.ld[1];
1013 1.89 kiyohara ld[2] = fp->mode.ld[2];
1014 1.89 kiyohara ohcifp->mode.common.spd = 0;
1015 1.89 kiyohara ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
1016 1.89 kiyohara } else {
1017 1.89 kiyohara ohcifp->mode.asycomm.dst = fp->mode.hdr.dst;
1018 1.89 kiyohara ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
1019 1.89 kiyohara ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
1020 1.89 kiyohara }
1021 1.89 kiyohara db = &db_tr->db[0];
1022 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.cmd,
1023 1.89 kiyohara OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len);
1024 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.addr, 0);
1025 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1026 1.89 kiyohara /* Specify bound timer of asy. responce */
1027 1.89 kiyohara if(&sc->atrs == dbch){
1028 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.res,
1029 1.89 kiyohara (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13));
1030 1.89 kiyohara }
1031 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
1032 1.89 kiyohara if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ)
1033 1.89 kiyohara hdr_len = 12;
1034 1.89 kiyohara for (i = 0; i < hdr_len/4; i ++)
1035 1.89 kiyohara FWOHCI_DMA_WRITE(ld[i], ld[i]);
1036 1.89 kiyohara #endif
1037 1.89 kiyohara
1038 1.89 kiyohara again:
1039 1.89 kiyohara db_tr->dbcnt = 2;
1040 1.89 kiyohara db = &db_tr->db[db_tr->dbcnt];
1041 1.89 kiyohara if (xfer->send.pay_len > 0) {
1042 1.89 kiyohara int err;
1043 1.89 kiyohara /* handle payload */
1044 1.89 kiyohara if (xfer->mbuf == NULL) {
1045 1.89 kiyohara err = fw_bus_dmamap_load(dbch->dmat, db_tr->dma_map,
1046 1.89 kiyohara &xfer->send.payload[0], xfer->send.pay_len,
1047 1.89 kiyohara fwohci_execute_db, db_tr,
1048 1.89 kiyohara BUS_DMA_WAITOK);
1049 1.89 kiyohara } else {
1050 1.89 kiyohara /* XXX we can handle only 6 (=8-2) mbuf chains */
1051 1.89 kiyohara err = fw_bus_dmamap_load_mbuf(dbch->dmat,
1052 1.89 kiyohara db_tr->dma_map, xfer->mbuf,
1053 1.89 kiyohara fwohci_execute_db2, db_tr,
1054 1.89 kiyohara BUS_DMA_WAITOK);
1055 1.89 kiyohara if (err == EFBIG) {
1056 1.89 kiyohara struct mbuf *m0;
1057 1.89 kiyohara
1058 1.89 kiyohara if (firewire_debug)
1059 1.110 kiyohara fw_printf(sc->fc.dev, "EFBIG.\n");
1060 1.89 kiyohara m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1061 1.89 kiyohara if (m0 != NULL) {
1062 1.89 kiyohara m_copydata(xfer->mbuf, 0,
1063 1.89 kiyohara xfer->mbuf->m_pkthdr.len,
1064 1.106 christos mtod(m0, void *));
1065 1.100 blymn m0->m_len = m0->m_pkthdr.len =
1066 1.89 kiyohara xfer->mbuf->m_pkthdr.len;
1067 1.89 kiyohara m_freem(xfer->mbuf);
1068 1.89 kiyohara xfer->mbuf = m0;
1069 1.89 kiyohara goto again;
1070 1.89 kiyohara }
1071 1.110 kiyohara fw_printf(sc->fc.dev, "m_getcl failed.\n");
1072 1.89 kiyohara }
1073 1.89 kiyohara }
1074 1.89 kiyohara if (err)
1075 1.89 kiyohara printf("dmamap_load: err=%d\n", err);
1076 1.89 kiyohara fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
1077 1.89 kiyohara BUS_DMASYNC_PREWRITE);
1078 1.89 kiyohara #if 0 /* OHCI_OUTPUT_MODE == 0 */
1079 1.89 kiyohara for (i = 2; i < db_tr->dbcnt; i++)
1080 1.89 kiyohara FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd,
1081 1.89 kiyohara OHCI_OUTPUT_MORE);
1082 1.89 kiyohara #endif
1083 1.89 kiyohara }
1084 1.89 kiyohara if (maxdesc < db_tr->dbcnt) {
1085 1.89 kiyohara maxdesc = db_tr->dbcnt;
1086 1.89 kiyohara if (firewire_debug)
1087 1.110 kiyohara fw_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc);
1088 1.89 kiyohara }
1089 1.89 kiyohara /* last db */
1090 1.89 kiyohara LAST_DB(db_tr, db);
1091 1.89 kiyohara FWOHCI_DMA_SET(db->db.desc.cmd,
1092 1.89 kiyohara OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1093 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.depend,
1094 1.89 kiyohara STAILQ_NEXT(db_tr, link)->bus_addr);
1095 1.89 kiyohara
1096 1.89 kiyohara if(fsegment == -1 )
1097 1.89 kiyohara fsegment = db_tr->dbcnt;
1098 1.89 kiyohara if (dbch->pdb_tr != NULL) {
1099 1.89 kiyohara LAST_DB(dbch->pdb_tr, db);
1100 1.89 kiyohara FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt);
1101 1.89 kiyohara }
1102 1.110 kiyohara dbch->xferq.queued ++;
1103 1.89 kiyohara dbch->pdb_tr = db_tr;
1104 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link);
1105 1.89 kiyohara if(db_tr != dbch->bottom){
1106 1.89 kiyohara goto txloop;
1107 1.89 kiyohara } else {
1108 1.110 kiyohara fw_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n");
1109 1.89 kiyohara dbch->flags |= FWOHCI_DBCH_FULL;
1110 1.89 kiyohara }
1111 1.89 kiyohara kick:
1112 1.89 kiyohara /* kick asy q */
1113 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
1114 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1115 1.99 kiyohara
1116 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_RUNNING) {
1117 1.89 kiyohara OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
1118 1.89 kiyohara } else {
1119 1.89 kiyohara if (firewire_debug)
1120 1.110 kiyohara fw_printf(sc->fc.dev, "start AT DMA status=%x\n",
1121 1.89 kiyohara OREAD(sc, OHCI_DMACTL(off)));
1122 1.89 kiyohara OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | fsegment);
1123 1.89 kiyohara OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1124 1.89 kiyohara dbch->xferq.flag |= FWXFERQ_RUNNING;
1125 1.62 haya }
1126 1.89 kiyohara CTR0(KTR_DEV, "start kick done");
1127 1.89 kiyohara CTR0(KTR_DEV, "start kick done2");
1128 1.24 jmc
1129 1.89 kiyohara dbch->top = db_tr;
1130 1.89 kiyohara splx(s);
1131 1.89 kiyohara return;
1132 1.89 kiyohara }
1133 1.24 jmc
1134 1.89 kiyohara static void
1135 1.89 kiyohara fwohci_start_atq(struct firewire_comm *fc)
1136 1.89 kiyohara {
1137 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1138 1.110 kiyohara FW_GLOCK(&sc->fc);
1139 1.89 kiyohara fwohci_start( sc, &(sc->atrq));
1140 1.110 kiyohara FW_GUNLOCK(&sc->fc);
1141 1.89 kiyohara return;
1142 1.89 kiyohara }
1143 1.24 jmc
1144 1.89 kiyohara static void
1145 1.89 kiyohara fwohci_start_ats(struct firewire_comm *fc)
1146 1.89 kiyohara {
1147 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1148 1.110 kiyohara FW_GLOCK(&sc->fc);
1149 1.89 kiyohara fwohci_start( sc, &(sc->atrs));
1150 1.110 kiyohara FW_GUNLOCK(&sc->fc);
1151 1.89 kiyohara return;
1152 1.89 kiyohara }
1153 1.62 haya
1154 1.89 kiyohara void
1155 1.89 kiyohara fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1156 1.89 kiyohara {
1157 1.89 kiyohara int s, ch, err = 0;
1158 1.89 kiyohara struct fwohcidb_tr *tr;
1159 1.89 kiyohara struct fwohcidb *db;
1160 1.89 kiyohara struct fw_xfer *xfer;
1161 1.89 kiyohara uint32_t off;
1162 1.89 kiyohara u_int stat, status;
1163 1.89 kiyohara int packets;
1164 1.89 kiyohara struct firewire_comm *fc = (struct firewire_comm *)sc;
1165 1.89 kiyohara
1166 1.89 kiyohara if(&sc->atrq == dbch){
1167 1.89 kiyohara off = OHCI_ATQOFF;
1168 1.89 kiyohara ch = ATRQ_CH;
1169 1.89 kiyohara }else if(&sc->atrs == dbch){
1170 1.89 kiyohara off = OHCI_ATSOFF;
1171 1.89 kiyohara ch = ATRS_CH;
1172 1.89 kiyohara }else{
1173 1.89 kiyohara return;
1174 1.89 kiyohara }
1175 1.89 kiyohara s = splfw();
1176 1.89 kiyohara tr = dbch->bottom;
1177 1.89 kiyohara packets = 0;
1178 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
1179 1.99 kiyohara BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1180 1.89 kiyohara while(dbch->xferq.queued > 0){
1181 1.89 kiyohara LAST_DB(tr, db);
1182 1.89 kiyohara status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT;
1183 1.89 kiyohara if(!(status & OHCI_CNTL_DMA_ACTIVE)){
1184 1.110 kiyohara if (fc->status != FWBUSINIT)
1185 1.89 kiyohara /* maybe out of order?? */
1186 1.89 kiyohara goto out;
1187 1.89 kiyohara }
1188 1.89 kiyohara if (tr->xfer->send.pay_len > 0) {
1189 1.89 kiyohara fw_bus_dmamap_sync(dbch->dmat, tr->dma_map,
1190 1.89 kiyohara BUS_DMASYNC_POSTWRITE);
1191 1.89 kiyohara fw_bus_dmamap_unload(dbch->dmat, tr->dma_map);
1192 1.89 kiyohara }
1193 1.89 kiyohara #if 1
1194 1.89 kiyohara if (firewire_debug > 1)
1195 1.89 kiyohara dump_db(sc, ch);
1196 1.89 kiyohara #endif
1197 1.89 kiyohara if(status & OHCI_CNTL_DMA_DEAD) {
1198 1.89 kiyohara /* Stop DMA */
1199 1.89 kiyohara OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
1200 1.110 kiyohara fw_printf(sc->fc.dev, "force reset AT FIFO\n");
1201 1.89 kiyohara OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
1202 1.89 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
1203 1.89 kiyohara OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
1204 1.89 kiyohara }
1205 1.89 kiyohara stat = status & FWOHCIEV_MASK;
1206 1.89 kiyohara switch(stat){
1207 1.89 kiyohara case FWOHCIEV_ACKPEND:
1208 1.89 kiyohara CTR0(KTR_DEV, "txd: ack pending");
1209 1.89 kiyohara /* fall through */
1210 1.89 kiyohara case FWOHCIEV_ACKCOMPL:
1211 1.89 kiyohara err = 0;
1212 1.89 kiyohara break;
1213 1.89 kiyohara case FWOHCIEV_ACKBSA:
1214 1.89 kiyohara case FWOHCIEV_ACKBSB:
1215 1.89 kiyohara case FWOHCIEV_ACKBSX:
1216 1.110 kiyohara fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat,
1217 1.110 kiyohara fwohcicode[stat]);
1218 1.89 kiyohara err = EBUSY;
1219 1.89 kiyohara break;
1220 1.89 kiyohara case FWOHCIEV_FLUSHED:
1221 1.89 kiyohara case FWOHCIEV_ACKTARD:
1222 1.110 kiyohara fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat,
1223 1.110 kiyohara fwohcicode[stat]);
1224 1.89 kiyohara err = EAGAIN;
1225 1.89 kiyohara break;
1226 1.89 kiyohara case FWOHCIEV_MISSACK:
1227 1.89 kiyohara case FWOHCIEV_UNDRRUN:
1228 1.89 kiyohara case FWOHCIEV_OVRRUN:
1229 1.89 kiyohara case FWOHCIEV_DESCERR:
1230 1.89 kiyohara case FWOHCIEV_DTRDERR:
1231 1.89 kiyohara case FWOHCIEV_TIMEOUT:
1232 1.89 kiyohara case FWOHCIEV_TCODERR:
1233 1.89 kiyohara case FWOHCIEV_UNKNOWN:
1234 1.89 kiyohara case FWOHCIEV_ACKDERR:
1235 1.89 kiyohara case FWOHCIEV_ACKTERR:
1236 1.89 kiyohara default:
1237 1.110 kiyohara fw_printf(sc->fc.dev, "txd err=%2x %s\n",
1238 1.89 kiyohara stat, fwohcicode[stat]);
1239 1.89 kiyohara err = EINVAL;
1240 1.89 kiyohara break;
1241 1.89 kiyohara }
1242 1.89 kiyohara if (tr->xfer != NULL) {
1243 1.89 kiyohara xfer = tr->xfer;
1244 1.89 kiyohara CTR0(KTR_DEV, "txd");
1245 1.110 kiyohara if (xfer->flag & FWXF_RCVD) {
1246 1.62 haya #if 0
1247 1.89 kiyohara if (firewire_debug)
1248 1.89 kiyohara printf("already rcvd\n");
1249 1.62 haya #endif
1250 1.89 kiyohara fw_xfer_done(xfer);
1251 1.89 kiyohara } else {
1252 1.110 kiyohara microtime(&xfer->tv);
1253 1.110 kiyohara xfer->flag = FWXF_SENT;
1254 1.110 kiyohara if (err == EBUSY) {
1255 1.110 kiyohara xfer->flag = FWXF_BUSY;
1256 1.89 kiyohara xfer->resp = err;
1257 1.89 kiyohara xfer->recv.pay_len = 0;
1258 1.89 kiyohara fw_xfer_done(xfer);
1259 1.89 kiyohara } else if (stat != FWOHCIEV_ACKPEND) {
1260 1.89 kiyohara if (stat != FWOHCIEV_ACKCOMPL)
1261 1.110 kiyohara xfer->flag = FWXF_SENTERR;
1262 1.89 kiyohara xfer->resp = err;
1263 1.89 kiyohara xfer->recv.pay_len = 0;
1264 1.89 kiyohara fw_xfer_done(xfer);
1265 1.89 kiyohara }
1266 1.89 kiyohara }
1267 1.89 kiyohara /*
1268 1.89 kiyohara * The watchdog timer takes care of split
1269 1.89 kiyohara * transcation timeout for ACKPEND case.
1270 1.89 kiyohara */
1271 1.89 kiyohara } else {
1272 1.89 kiyohara printf("this shouldn't happen\n");
1273 1.89 kiyohara }
1274 1.110 kiyohara FW_GLOCK(fc);
1275 1.89 kiyohara dbch->xferq.queued --;
1276 1.110 kiyohara FW_GUNLOCK(fc);
1277 1.89 kiyohara tr->xfer = NULL;
1278 1.62 haya
1279 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1280 1.89 kiyohara packets ++;
1281 1.89 kiyohara tr = STAILQ_NEXT(tr, link);
1282 1.89 kiyohara dbch->bottom = tr;
1283 1.89 kiyohara if (dbch->bottom == dbch->top) {
1284 1.89 kiyohara /* we reaches the end of context program */
1285 1.89 kiyohara if (firewire_debug && dbch->xferq.queued > 0)
1286 1.89 kiyohara printf("queued > 0\n");
1287 1.89 kiyohara break;
1288 1.89 kiyohara }
1289 1.89 kiyohara }
1290 1.89 kiyohara out:
1291 1.89 kiyohara if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1292 1.89 kiyohara printf("make free slot\n");
1293 1.89 kiyohara dbch->flags &= ~FWOHCI_DBCH_FULL;
1294 1.110 kiyohara FW_GLOCK(fc);
1295 1.89 kiyohara fwohci_start(sc, dbch);
1296 1.110 kiyohara FW_GUNLOCK(fc);
1297 1.89 kiyohara }
1298 1.99 kiyohara fwdma_sync_multiseg_all(
1299 1.99 kiyohara dbch->am, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1300 1.89 kiyohara splx(s);
1301 1.24 jmc }
1302 1.24 jmc
1303 1.24 jmc static void
1304 1.89 kiyohara fwohci_db_free(struct fwohci_dbch *dbch)
1305 1.24 jmc {
1306 1.89 kiyohara struct fwohcidb_tr *db_tr;
1307 1.89 kiyohara int idb;
1308 1.26 enami
1309 1.89 kiyohara if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1310 1.89 kiyohara return;
1311 1.26 enami
1312 1.89 kiyohara for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; idb < dbch->ndb;
1313 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link), idb++){
1314 1.89 kiyohara if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 &&
1315 1.89 kiyohara db_tr->buf != NULL) {
1316 1.89 kiyohara fwdma_free_size(dbch->dmat, db_tr->dma_map,
1317 1.89 kiyohara db_tr->buf, dbch->xferq.psize);
1318 1.89 kiyohara db_tr->buf = NULL;
1319 1.89 kiyohara } else if (db_tr->dma_map != NULL)
1320 1.89 kiyohara fw_bus_dmamap_destroy(dbch->dmat, db_tr->dma_map);
1321 1.89 kiyohara }
1322 1.89 kiyohara dbch->ndb = 0;
1323 1.89 kiyohara db_tr = STAILQ_FIRST(&dbch->db_trq);
1324 1.89 kiyohara fwdma_free_multiseg(dbch->am);
1325 1.89 kiyohara free(db_tr, M_FW);
1326 1.89 kiyohara STAILQ_INIT(&dbch->db_trq);
1327 1.89 kiyohara dbch->flags &= ~FWOHCI_DBCH_INIT;
1328 1.108 ad seldestroy(&dbch->xferq.rsel);
1329 1.89 kiyohara }
1330 1.26 enami
1331 1.89 kiyohara static void
1332 1.89 kiyohara fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1333 1.89 kiyohara {
1334 1.89 kiyohara int idb;
1335 1.89 kiyohara struct fwohcidb_tr *db_tr;
1336 1.89 kiyohara
1337 1.89 kiyohara if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1338 1.89 kiyohara goto out;
1339 1.89 kiyohara
1340 1.89 kiyohara /* create dma_tag for buffers */
1341 1.89 kiyohara #define MAX_REQCOUNT 0xffff
1342 1.89 kiyohara if (fw_bus_dma_tag_create(/*parent*/ sc->fc.dmat,
1343 1.89 kiyohara /*alignment*/ 1, /*boundary*/ 0,
1344 1.89 kiyohara /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT,
1345 1.89 kiyohara /*highaddr*/ BUS_SPACE_MAXADDR,
1346 1.89 kiyohara /*filter*/NULL, /*filterarg*/NULL,
1347 1.89 kiyohara /*maxsize*/ dbch->xferq.psize,
1348 1.89 kiyohara /*nsegments*/ dbch->ndesc > 3 ? dbch->ndesc - 2 : 1,
1349 1.89 kiyohara /*maxsegsz*/ MAX_REQCOUNT,
1350 1.89 kiyohara /*flags*/ 0,
1351 1.89 kiyohara /*lockfunc*/busdma_lock_mutex,
1352 1.110 kiyohara /*lockarg*/FW_GMTX(&sc->fc),
1353 1.89 kiyohara &dbch->dmat))
1354 1.89 kiyohara return;
1355 1.26 enami
1356 1.89 kiyohara /* allocate DB entries and attach one to each DMA channels */
1357 1.89 kiyohara /* DB entry must start at 16 bytes bounary. */
1358 1.89 kiyohara STAILQ_INIT(&dbch->db_trq);
1359 1.89 kiyohara db_tr = (struct fwohcidb_tr *)
1360 1.89 kiyohara malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
1361 1.89 kiyohara M_FW, M_WAITOK | M_ZERO);
1362 1.89 kiyohara if(db_tr == NULL){
1363 1.89 kiyohara printf("fwohci_db_init: malloc(1) failed\n");
1364 1.89 kiyohara return;
1365 1.89 kiyohara }
1366 1.26 enami
1367 1.89 kiyohara #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1368 1.89 kiyohara dbch->am = fwdma_malloc_multiseg(&sc->fc, DB_SIZE(dbch),
1369 1.97 kiyohara DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
1370 1.89 kiyohara if (dbch->am == NULL) {
1371 1.89 kiyohara printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1372 1.89 kiyohara free(db_tr, M_FW);
1373 1.89 kiyohara return;
1374 1.89 kiyohara }
1375 1.89 kiyohara /* Attach DB to DMA ch. */
1376 1.89 kiyohara for(idb = 0 ; idb < dbch->ndb ; idb++){
1377 1.89 kiyohara db_tr->dbcnt = 0;
1378 1.89 kiyohara db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1379 1.89 kiyohara db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1380 1.89 kiyohara /* create dmamap for buffers */
1381 1.89 kiyohara /* XXX do we need 4bytes alignment tag? */
1382 1.89 kiyohara /* XXX don't alloc dma_map for AR */
1383 1.96 kiyohara if (fw_bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) {
1384 1.96 kiyohara printf("fw_bus_dmamap_create failed\n");
1385 1.89 kiyohara dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1386 1.89 kiyohara fwohci_db_free(dbch);
1387 1.89 kiyohara return;
1388 1.35 onoe }
1389 1.89 kiyohara STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1390 1.89 kiyohara if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1391 1.89 kiyohara if (idb % dbch->xferq.bnpacket == 0)
1392 1.89 kiyohara dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1393 1.106 christos ].start = (void *)db_tr;
1394 1.89 kiyohara if ((idb + 1) % dbch->xferq.bnpacket == 0)
1395 1.89 kiyohara dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1396 1.106 christos ].end = (void *)db_tr;
1397 1.26 enami }
1398 1.89 kiyohara db_tr++;
1399 1.26 enami }
1400 1.89 kiyohara STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1401 1.89 kiyohara = STAILQ_FIRST(&dbch->db_trq);
1402 1.89 kiyohara out:
1403 1.89 kiyohara dbch->xferq.queued = 0;
1404 1.89 kiyohara dbch->pdb_tr = NULL;
1405 1.89 kiyohara dbch->top = STAILQ_FIRST(&dbch->db_trq);
1406 1.89 kiyohara dbch->bottom = dbch->top;
1407 1.89 kiyohara dbch->flags = FWOHCI_DBCH_INIT;
1408 1.108 ad selinit(&dbch->xferq.rsel);
1409 1.24 jmc }
1410 1.24 jmc
1411 1.5 matt static int
1412 1.89 kiyohara fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1413 1.5 matt {
1414 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1415 1.89 kiyohara int sleepch;
1416 1.5 matt
1417 1.100 blymn OWRITE(sc, OHCI_ITCTLCLR(dmach),
1418 1.89 kiyohara OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1419 1.89 kiyohara OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1420 1.89 kiyohara OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1421 1.89 kiyohara /* XXX we cannot free buffers until the DMA really stops */
1422 1.89 kiyohara tsleep((void *)&sleepch, FWPRI, "fwitxd", hz);
1423 1.89 kiyohara fwohci_db_free(&sc->it[dmach]);
1424 1.89 kiyohara sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1425 1.89 kiyohara return 0;
1426 1.5 matt }
1427 1.5 matt
1428 1.89 kiyohara static int
1429 1.89 kiyohara fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1430 1.3 onoe {
1431 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1432 1.89 kiyohara int sleepch;
1433 1.3 onoe
1434 1.89 kiyohara OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1435 1.89 kiyohara OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1436 1.89 kiyohara OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1437 1.89 kiyohara /* XXX we cannot free buffers until the DMA really stops */
1438 1.89 kiyohara tsleep((void *)&sleepch, FWPRI, "fwirxd", hz);
1439 1.89 kiyohara fwohci_db_free(&sc->ir[dmach]);
1440 1.89 kiyohara sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1441 1.89 kiyohara return 0;
1442 1.89 kiyohara }
1443 1.3 onoe
1444 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
1445 1.89 kiyohara static void
1446 1.89 kiyohara fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld)
1447 1.89 kiyohara {
1448 1.89 kiyohara qld[0] = FWOHCI_DMA_READ(qld[0]);
1449 1.89 kiyohara return;
1450 1.3 onoe }
1451 1.89 kiyohara #endif
1452 1.3 onoe
1453 1.89 kiyohara static int
1454 1.89 kiyohara fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1455 1.7 onoe {
1456 1.89 kiyohara int err = 0;
1457 1.89 kiyohara int idb, z, i, dmach = 0, ldesc;
1458 1.89 kiyohara uint32_t off = 0;
1459 1.89 kiyohara struct fwohcidb_tr *db_tr;
1460 1.89 kiyohara struct fwohcidb *db;
1461 1.7 onoe
1462 1.89 kiyohara if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1463 1.89 kiyohara err = EINVAL;
1464 1.89 kiyohara return err;
1465 1.89 kiyohara }
1466 1.89 kiyohara z = dbch->ndesc;
1467 1.89 kiyohara for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1468 1.89 kiyohara if( &sc->it[dmach] == dbch){
1469 1.89 kiyohara off = OHCI_ITOFF(dmach);
1470 1.7 onoe break;
1471 1.89 kiyohara }
1472 1.7 onoe }
1473 1.89 kiyohara if(off == 0){
1474 1.89 kiyohara err = EINVAL;
1475 1.89 kiyohara return err;
1476 1.89 kiyohara }
1477 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_RUNNING)
1478 1.89 kiyohara return err;
1479 1.89 kiyohara dbch->xferq.flag |= FWXFERQ_RUNNING;
1480 1.89 kiyohara for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1481 1.89 kiyohara dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1482 1.89 kiyohara }
1483 1.89 kiyohara db_tr = dbch->top;
1484 1.89 kiyohara for (idb = 0; idb < dbch->ndb; idb ++) {
1485 1.89 kiyohara fwohci_add_tx_buf(dbch, db_tr, idb);
1486 1.89 kiyohara if(STAILQ_NEXT(db_tr, link) == NULL){
1487 1.89 kiyohara break;
1488 1.89 kiyohara }
1489 1.89 kiyohara db = db_tr->db;
1490 1.89 kiyohara ldesc = db_tr->dbcnt - 1;
1491 1.89 kiyohara FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1492 1.89 kiyohara STAILQ_NEXT(db_tr, link)->bus_addr | z);
1493 1.89 kiyohara db[ldesc].db.desc.depend = db[0].db.desc.depend;
1494 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1495 1.89 kiyohara if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1496 1.89 kiyohara FWOHCI_DMA_SET(
1497 1.89 kiyohara db[ldesc].db.desc.cmd,
1498 1.89 kiyohara OHCI_INTERRUPT_ALWAYS);
1499 1.89 kiyohara /* OHCI 1.1 and above */
1500 1.89 kiyohara FWOHCI_DMA_SET(
1501 1.89 kiyohara db[0].db.desc.cmd,
1502 1.89 kiyohara OHCI_INTERRUPT_ALWAYS);
1503 1.89 kiyohara }
1504 1.89 kiyohara }
1505 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link);
1506 1.89 kiyohara }
1507 1.89 kiyohara FWOHCI_DMA_CLEAR(
1508 1.89 kiyohara dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1509 1.89 kiyohara return err;
1510 1.89 kiyohara }
1511 1.7 onoe
1512 1.89 kiyohara static int
1513 1.89 kiyohara fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1514 1.89 kiyohara {
1515 1.89 kiyohara int err = 0;
1516 1.89 kiyohara int idb, z, i, dmach = 0, ldesc;
1517 1.89 kiyohara uint32_t off = 0;
1518 1.89 kiyohara struct fwohcidb_tr *db_tr;
1519 1.89 kiyohara struct fwohcidb *db;
1520 1.89 kiyohara
1521 1.89 kiyohara z = dbch->ndesc;
1522 1.89 kiyohara if(&sc->arrq == dbch){
1523 1.89 kiyohara off = OHCI_ARQOFF;
1524 1.89 kiyohara }else if(&sc->arrs == dbch){
1525 1.89 kiyohara off = OHCI_ARSOFF;
1526 1.89 kiyohara }else{
1527 1.89 kiyohara for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1528 1.89 kiyohara if( &sc->ir[dmach] == dbch){
1529 1.89 kiyohara off = OHCI_IROFF(dmach);
1530 1.89 kiyohara break;
1531 1.89 kiyohara }
1532 1.89 kiyohara }
1533 1.89 kiyohara }
1534 1.89 kiyohara if(off == 0){
1535 1.89 kiyohara err = EINVAL;
1536 1.89 kiyohara return err;
1537 1.89 kiyohara }
1538 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_STREAM){
1539 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_RUNNING)
1540 1.89 kiyohara return err;
1541 1.89 kiyohara }else{
1542 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_RUNNING){
1543 1.89 kiyohara err = EBUSY;
1544 1.89 kiyohara return err;
1545 1.89 kiyohara }
1546 1.89 kiyohara }
1547 1.89 kiyohara dbch->xferq.flag |= FWXFERQ_RUNNING;
1548 1.89 kiyohara dbch->top = STAILQ_FIRST(&dbch->db_trq);
1549 1.89 kiyohara for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1550 1.89 kiyohara dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1551 1.89 kiyohara }
1552 1.89 kiyohara db_tr = dbch->top;
1553 1.110 kiyohara if (db_tr->dbcnt != 0)
1554 1.110 kiyohara goto run;
1555 1.89 kiyohara for (idb = 0; idb < dbch->ndb; idb ++) {
1556 1.89 kiyohara fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1557 1.89 kiyohara if (STAILQ_NEXT(db_tr, link) == NULL)
1558 1.89 kiyohara break;
1559 1.89 kiyohara db = db_tr->db;
1560 1.89 kiyohara ldesc = db_tr->dbcnt - 1;
1561 1.89 kiyohara FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1562 1.89 kiyohara STAILQ_NEXT(db_tr, link)->bus_addr | z);
1563 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1564 1.89 kiyohara if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1565 1.89 kiyohara FWOHCI_DMA_SET(
1566 1.89 kiyohara db[ldesc].db.desc.cmd,
1567 1.89 kiyohara OHCI_INTERRUPT_ALWAYS);
1568 1.89 kiyohara FWOHCI_DMA_CLEAR(
1569 1.89 kiyohara db[ldesc].db.desc.depend,
1570 1.89 kiyohara 0xf);
1571 1.89 kiyohara }
1572 1.89 kiyohara }
1573 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link);
1574 1.89 kiyohara }
1575 1.89 kiyohara FWOHCI_DMA_CLEAR(
1576 1.89 kiyohara dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf);
1577 1.89 kiyohara dbch->buf_offset = 0;
1578 1.110 kiyohara run:
1579 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
1580 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1581 1.89 kiyohara if(dbch->xferq.flag & FWXFERQ_STREAM){
1582 1.89 kiyohara return err;
1583 1.89 kiyohara }else{
1584 1.89 kiyohara OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z);
1585 1.89 kiyohara }
1586 1.89 kiyohara OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1587 1.89 kiyohara return err;
1588 1.89 kiyohara }
1589 1.7 onoe
1590 1.89 kiyohara static int
1591 1.103 christos fwohci_next_cycle(struct firewire_comm *fc, int cycle_now)
1592 1.89 kiyohara {
1593 1.89 kiyohara int sec, cycle, cycle_match;
1594 1.89 kiyohara
1595 1.89 kiyohara cycle = cycle_now & 0x1fff;
1596 1.89 kiyohara sec = cycle_now >> 13;
1597 1.89 kiyohara #define CYCLE_MOD 0x10
1598 1.89 kiyohara #if 1
1599 1.89 kiyohara #define CYCLE_DELAY 8 /* min delay to start DMA */
1600 1.7 onoe #else
1601 1.89 kiyohara #define CYCLE_DELAY 7000 /* min delay to start DMA */
1602 1.7 onoe #endif
1603 1.89 kiyohara cycle = cycle + CYCLE_DELAY;
1604 1.89 kiyohara if (cycle >= 8000) {
1605 1.89 kiyohara sec ++;
1606 1.89 kiyohara cycle -= 8000;
1607 1.89 kiyohara }
1608 1.89 kiyohara cycle = roundup2(cycle, CYCLE_MOD);
1609 1.89 kiyohara if (cycle >= 8000) {
1610 1.89 kiyohara sec ++;
1611 1.89 kiyohara if (cycle == 8000)
1612 1.89 kiyohara cycle = 0;
1613 1.89 kiyohara else
1614 1.89 kiyohara cycle = CYCLE_MOD;
1615 1.89 kiyohara }
1616 1.89 kiyohara cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1617 1.89 kiyohara
1618 1.89 kiyohara return(cycle_match);
1619 1.89 kiyohara }
1620 1.89 kiyohara
1621 1.89 kiyohara static int
1622 1.89 kiyohara fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1623 1.89 kiyohara {
1624 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1625 1.89 kiyohara int err = 0;
1626 1.89 kiyohara unsigned short tag, ich;
1627 1.89 kiyohara struct fwohci_dbch *dbch;
1628 1.89 kiyohara int cycle_match, cycle_now, s, ldesc;
1629 1.89 kiyohara uint32_t stat;
1630 1.89 kiyohara struct fw_bulkxfer *first, *chunk, *prev;
1631 1.89 kiyohara struct fw_xferq *it;
1632 1.89 kiyohara
1633 1.89 kiyohara dbch = &sc->it[dmach];
1634 1.89 kiyohara it = &dbch->xferq;
1635 1.89 kiyohara
1636 1.89 kiyohara tag = (it->flag >> 6) & 3;
1637 1.89 kiyohara ich = it->flag & 0x3f;
1638 1.89 kiyohara if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1639 1.89 kiyohara dbch->ndb = it->bnpacket * it->bnchunk;
1640 1.89 kiyohara dbch->ndesc = 3;
1641 1.89 kiyohara fwohci_db_init(sc, dbch);
1642 1.89 kiyohara if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1643 1.89 kiyohara return ENOMEM;
1644 1.110 kiyohara
1645 1.89 kiyohara err = fwohci_tx_enable(sc, dbch);
1646 1.89 kiyohara }
1647 1.89 kiyohara if(err)
1648 1.89 kiyohara return err;
1649 1.89 kiyohara
1650 1.89 kiyohara ldesc = dbch->ndesc - 1;
1651 1.89 kiyohara s = splfw();
1652 1.110 kiyohara FW_GLOCK(fc);
1653 1.89 kiyohara prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1654 1.89 kiyohara while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1655 1.89 kiyohara struct fwohcidb *db;
1656 1.89 kiyohara
1657 1.89 kiyohara fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1658 1.89 kiyohara BUS_DMASYNC_PREWRITE);
1659 1.89 kiyohara fwohci_txbufdb(sc, dmach, chunk);
1660 1.89 kiyohara if (prev != NULL) {
1661 1.89 kiyohara db = ((struct fwohcidb_tr *)(prev->end))->db;
1662 1.89 kiyohara #if 0 /* XXX necessary? */
1663 1.89 kiyohara FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1664 1.89 kiyohara OHCI_BRANCH_ALWAYS);
1665 1.89 kiyohara #endif
1666 1.89 kiyohara #if 0 /* if bulkxfer->npacket changes */
1667 1.100 blymn db[ldesc].db.desc.depend = db[0].db.desc.depend =
1668 1.89 kiyohara ((struct fwohcidb_tr *)
1669 1.89 kiyohara (chunk->start))->bus_addr | dbch->ndesc;
1670 1.89 kiyohara #else
1671 1.89 kiyohara FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1672 1.89 kiyohara FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1673 1.89 kiyohara #endif
1674 1.89 kiyohara }
1675 1.89 kiyohara STAILQ_REMOVE_HEAD(&it->stvalid, link);
1676 1.89 kiyohara STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1677 1.89 kiyohara prev = chunk;
1678 1.89 kiyohara }
1679 1.110 kiyohara FW_GUNLOCK(fc);
1680 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
1681 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1682 1.89 kiyohara splx(s);
1683 1.89 kiyohara stat = OREAD(sc, OHCI_ITCTL(dmach));
1684 1.89 kiyohara if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1685 1.89 kiyohara printf("stat 0x%x\n", stat);
1686 1.89 kiyohara
1687 1.89 kiyohara if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1688 1.89 kiyohara return 0;
1689 1.89 kiyohara
1690 1.89 kiyohara #if 0
1691 1.89 kiyohara OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1692 1.89 kiyohara #endif
1693 1.89 kiyohara OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1694 1.89 kiyohara OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1695 1.89 kiyohara OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1696 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1697 1.89 kiyohara
1698 1.89 kiyohara first = STAILQ_FIRST(&it->stdma);
1699 1.89 kiyohara OWRITE(sc, OHCI_ITCMD(dmach),
1700 1.89 kiyohara ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1701 1.89 kiyohara if (firewire_debug > 1) {
1702 1.89 kiyohara printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1703 1.89 kiyohara #if 1
1704 1.89 kiyohara dump_dma(sc, ITX_CH + dmach);
1705 1.89 kiyohara #endif
1706 1.89 kiyohara }
1707 1.89 kiyohara if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1708 1.89 kiyohara #if 1
1709 1.89 kiyohara /* Don't start until all chunks are buffered */
1710 1.89 kiyohara if (STAILQ_FIRST(&it->stfree) != NULL)
1711 1.89 kiyohara goto out;
1712 1.89 kiyohara #endif
1713 1.89 kiyohara #if 1
1714 1.89 kiyohara /* Clear cycle match counter bits */
1715 1.89 kiyohara OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1716 1.89 kiyohara
1717 1.89 kiyohara /* 2bit second + 13bit cycle */
1718 1.89 kiyohara cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1719 1.89 kiyohara cycle_match = fwohci_next_cycle(fc, cycle_now);
1720 1.89 kiyohara
1721 1.89 kiyohara OWRITE(sc, OHCI_ITCTL(dmach),
1722 1.89 kiyohara OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1723 1.89 kiyohara | OHCI_CNTL_DMA_RUN);
1724 1.89 kiyohara #else
1725 1.89 kiyohara OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1726 1.89 kiyohara #endif
1727 1.89 kiyohara if (firewire_debug > 1) {
1728 1.89 kiyohara printf("cycle_match: 0x%04x->0x%04x\n",
1729 1.89 kiyohara cycle_now, cycle_match);
1730 1.89 kiyohara dump_dma(sc, ITX_CH + dmach);
1731 1.89 kiyohara dump_db(sc, ITX_CH + dmach);
1732 1.89 kiyohara }
1733 1.89 kiyohara } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1734 1.110 kiyohara fw_printf(sc->fc.dev, "IT DMA underrun (0x%08x)\n", stat);
1735 1.89 kiyohara OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1736 1.89 kiyohara }
1737 1.89 kiyohara out:
1738 1.89 kiyohara return err;
1739 1.89 kiyohara }
1740 1.7 onoe
1741 1.89 kiyohara static int
1742 1.89 kiyohara fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1743 1.89 kiyohara {
1744 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1745 1.89 kiyohara int err = 0, s, ldesc;
1746 1.89 kiyohara unsigned short tag, ich;
1747 1.89 kiyohara uint32_t stat;
1748 1.89 kiyohara struct fwohci_dbch *dbch;
1749 1.89 kiyohara struct fwohcidb_tr *db_tr;
1750 1.89 kiyohara struct fw_bulkxfer *first, *prev, *chunk;
1751 1.89 kiyohara struct fw_xferq *ir;
1752 1.89 kiyohara
1753 1.89 kiyohara dbch = &sc->ir[dmach];
1754 1.89 kiyohara ir = &dbch->xferq;
1755 1.89 kiyohara
1756 1.89 kiyohara if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1757 1.89 kiyohara tag = (ir->flag >> 6) & 3;
1758 1.89 kiyohara ich = ir->flag & 0x3f;
1759 1.89 kiyohara OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1760 1.89 kiyohara
1761 1.89 kiyohara ir->queued = 0;
1762 1.89 kiyohara dbch->ndb = ir->bnpacket * ir->bnchunk;
1763 1.89 kiyohara dbch->ndesc = 2;
1764 1.89 kiyohara fwohci_db_init(sc, dbch);
1765 1.89 kiyohara if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1766 1.89 kiyohara return ENOMEM;
1767 1.89 kiyohara err = fwohci_rx_enable(sc, dbch);
1768 1.89 kiyohara }
1769 1.89 kiyohara if(err)
1770 1.89 kiyohara return err;
1771 1.89 kiyohara
1772 1.89 kiyohara first = STAILQ_FIRST(&ir->stfree);
1773 1.89 kiyohara if (first == NULL) {
1774 1.110 kiyohara fw_printf(fc->dev, "IR DMA no free chunk\n");
1775 1.89 kiyohara return 0;
1776 1.89 kiyohara }
1777 1.7 onoe
1778 1.89 kiyohara ldesc = dbch->ndesc - 1;
1779 1.89 kiyohara s = splfw();
1780 1.110 kiyohara if ((ir->flag & FWXFERQ_HANDLER) == 0)
1781 1.110 kiyohara FW_GLOCK(fc);
1782 1.89 kiyohara prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1783 1.89 kiyohara while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1784 1.89 kiyohara struct fwohcidb *db;
1785 1.89 kiyohara
1786 1.89 kiyohara #if 1 /* XXX for if_fwe */
1787 1.89 kiyohara if (chunk->mbuf != NULL) {
1788 1.89 kiyohara db_tr = (struct fwohcidb_tr *)(chunk->start);
1789 1.89 kiyohara db_tr->dbcnt = 1;
1790 1.89 kiyohara err = fw_bus_dmamap_load_mbuf(
1791 1.89 kiyohara dbch->dmat, db_tr->dma_map,
1792 1.89 kiyohara chunk->mbuf, fwohci_execute_db2, db_tr,
1793 1.89 kiyohara BUS_DMA_WAITOK);
1794 1.89 kiyohara FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1795 1.89 kiyohara OHCI_UPDATE | OHCI_INPUT_LAST |
1796 1.89 kiyohara OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1797 1.89 kiyohara }
1798 1.89 kiyohara #endif
1799 1.89 kiyohara db = ((struct fwohcidb_tr *)(chunk->end))->db;
1800 1.89 kiyohara FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1801 1.89 kiyohara FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1802 1.89 kiyohara if (prev != NULL) {
1803 1.89 kiyohara db = ((struct fwohcidb_tr *)(prev->end))->db;
1804 1.89 kiyohara FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1805 1.89 kiyohara }
1806 1.89 kiyohara STAILQ_REMOVE_HEAD(&ir->stfree, link);
1807 1.89 kiyohara STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1808 1.89 kiyohara prev = chunk;
1809 1.89 kiyohara }
1810 1.110 kiyohara if ((ir->flag & FWXFERQ_HANDLER) == 0)
1811 1.110 kiyohara FW_GUNLOCK(fc);
1812 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
1813 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1814 1.89 kiyohara splx(s);
1815 1.89 kiyohara stat = OREAD(sc, OHCI_IRCTL(dmach));
1816 1.89 kiyohara if (stat & OHCI_CNTL_DMA_ACTIVE)
1817 1.89 kiyohara return 0;
1818 1.89 kiyohara if (stat & OHCI_CNTL_DMA_RUN) {
1819 1.89 kiyohara OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1820 1.110 kiyohara fw_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1821 1.89 kiyohara }
1822 1.89 kiyohara
1823 1.89 kiyohara if (firewire_debug)
1824 1.89 kiyohara printf("start IR DMA 0x%x\n", stat);
1825 1.89 kiyohara OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1826 1.89 kiyohara OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1827 1.89 kiyohara OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1828 1.89 kiyohara OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1829 1.89 kiyohara OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1830 1.89 kiyohara OWRITE(sc, OHCI_IRCMD(dmach),
1831 1.89 kiyohara ((struct fwohcidb_tr *)(first->start))->bus_addr
1832 1.89 kiyohara | dbch->ndesc);
1833 1.89 kiyohara OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1834 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1835 1.89 kiyohara #if 0
1836 1.89 kiyohara dump_db(sc, IRX_CH + dmach);
1837 1.22 enami #endif
1838 1.89 kiyohara return err;
1839 1.89 kiyohara }
1840 1.89 kiyohara
1841 1.110 kiyohara int
1842 1.110 kiyohara fwohci_stop(struct fwohci_softc *sc, device_t dev)
1843 1.89 kiyohara {
1844 1.89 kiyohara u_int i;
1845 1.89 kiyohara
1846 1.89 kiyohara /* Now stopping all DMA channel */
1847 1.89 kiyohara OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1848 1.89 kiyohara OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1849 1.89 kiyohara OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1850 1.89 kiyohara OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1851 1.89 kiyohara
1852 1.89 kiyohara for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
1853 1.89 kiyohara OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1854 1.89 kiyohara OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1855 1.89 kiyohara }
1856 1.89 kiyohara
1857 1.110 kiyohara if (sc->fc.arq !=0 && sc->fc.arq->maxq > 0)
1858 1.110 kiyohara fw_drain_txq(&sc->fc);
1859 1.7 onoe
1860 1.110 kiyohara #if 0 /* Let dcons(4) be accessed */
1861 1.89 kiyohara /* Stop interrupt */
1862 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASKCLR,
1863 1.89 kiyohara OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1864 1.89 kiyohara | OHCI_INT_PHY_INT
1865 1.100 blymn | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1866 1.89 kiyohara | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1867 1.100 blymn | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1868 1.89 kiyohara | OHCI_INT_PHY_BUS_R);
1869 1.7 onoe
1870 1.110 kiyohara /* FLUSH FIFO and reset Transmitter/Reciever */
1871 1.110 kiyohara OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1872 1.110 kiyohara #endif
1873 1.7 onoe
1874 1.89 kiyohara /* XXX Link down? Bus reset? */
1875 1.110 kiyohara return 0;
1876 1.7 onoe }
1877 1.7 onoe
1878 1.89 kiyohara int
1879 1.89 kiyohara fwohci_resume(struct fwohci_softc *sc, device_t dev)
1880 1.7 onoe {
1881 1.89 kiyohara int i;
1882 1.89 kiyohara struct fw_xferq *ir;
1883 1.89 kiyohara struct fw_bulkxfer *chunk;
1884 1.7 onoe
1885 1.89 kiyohara fwohci_reset(sc, dev);
1886 1.89 kiyohara /* XXX resume isochronous receive automatically. (how about TX?) */
1887 1.89 kiyohara for(i = 0; i < sc->fc.nisodma; i ++) {
1888 1.89 kiyohara ir = &sc->ir[i].xferq;
1889 1.89 kiyohara if((ir->flag & FWXFERQ_RUNNING) != 0) {
1890 1.110 kiyohara fw_printf(sc->fc.dev,
1891 1.89 kiyohara "resume iso receive ch: %d\n", i);
1892 1.89 kiyohara ir->flag &= ~FWXFERQ_RUNNING;
1893 1.89 kiyohara /* requeue stdma to stfree */
1894 1.89 kiyohara while((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1895 1.89 kiyohara STAILQ_REMOVE_HEAD(&ir->stdma, link);
1896 1.89 kiyohara STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1897 1.89 kiyohara }
1898 1.89 kiyohara sc->fc.irx_enable(&sc->fc, i);
1899 1.89 kiyohara }
1900 1.89 kiyohara }
1901 1.89 kiyohara
1902 1.89 kiyohara #if defined(__FreeBSD__)
1903 1.89 kiyohara bus_generic_resume(dev);
1904 1.110 kiyohara #elif defined(__NetBSD__)
1905 1.110 kiyohara {
1906 1.110 kiyohara extern int firewire_resume(struct firewire_comm *);
1907 1.110 kiyohara firewire_resume(&sc->fc);
1908 1.110 kiyohara }
1909 1.89 kiyohara #endif
1910 1.89 kiyohara sc->fc.ibr(&sc->fc);
1911 1.89 kiyohara return 0;
1912 1.89 kiyohara }
1913 1.89 kiyohara
1914 1.110 kiyohara #ifdef OHCI_DEBUG
1915 1.89 kiyohara static void
1916 1.110 kiyohara fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1917 1.89 kiyohara {
1918 1.89 kiyohara if(stat & OREAD(sc, FWOHCI_INTMASK))
1919 1.110 kiyohara fw_printf(fc->dev, "INTERRUPT < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s> 0x%08x, 0x%08x\n",
1920 1.89 kiyohara stat & OHCI_INT_EN ? "DMA_EN ":"",
1921 1.89 kiyohara stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1922 1.89 kiyohara stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1923 1.89 kiyohara stat & OHCI_INT_ERR ? "INT_ERR ":"",
1924 1.89 kiyohara stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1925 1.89 kiyohara stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1926 1.89 kiyohara stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1927 1.89 kiyohara stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1928 1.89 kiyohara stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1929 1.89 kiyohara stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1930 1.89 kiyohara stat & OHCI_INT_PHY_SID ? "SID ":"",
1931 1.89 kiyohara stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1932 1.89 kiyohara stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1933 1.89 kiyohara stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1934 1.89 kiyohara stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1935 1.89 kiyohara stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1936 1.89 kiyohara stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1937 1.89 kiyohara stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1938 1.89 kiyohara stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1939 1.89 kiyohara stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1940 1.89 kiyohara stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1941 1.100 blymn stat, OREAD(sc, FWOHCI_INTMASK)
1942 1.89 kiyohara );
1943 1.110 kiyohara }
1944 1.89 kiyohara #endif
1945 1.110 kiyohara static void
1946 1.110 kiyohara fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1947 1.110 kiyohara {
1948 1.110 kiyohara struct firewire_comm *fc = (struct firewire_comm *)sc;
1949 1.110 kiyohara uint32_t node_id, plen;
1950 1.110 kiyohara
1951 1.110 kiyohara CTR0(KTR_DEV, "fwohci_intr_core");
1952 1.110 kiyohara
1953 1.110 kiyohara if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1954 1.110 kiyohara fc->status = FWBUSRESET;
1955 1.89 kiyohara /* Disable bus reset interrupt until sid recv. */
1956 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1957 1.100 blymn
1958 1.110 kiyohara fw_printf(fc->dev, "BUS reset\n");
1959 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1960 1.89 kiyohara OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1961 1.89 kiyohara
1962 1.89 kiyohara OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1963 1.89 kiyohara sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1964 1.89 kiyohara OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1965 1.89 kiyohara sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1966 1.89 kiyohara
1967 1.110 kiyohara if (!kdb_active)
1968 1.110 kiyohara fw_taskqueue_enqueue(sc->fc.taskqueue,
1969 1.110 kiyohara &sc->fwohci_task_busreset);
1970 1.110 kiyohara }
1971 1.110 kiyohara if (stat & OHCI_INT_PHY_SID) {
1972 1.110 kiyohara /* Enable bus reset interrupt */
1973 1.89 kiyohara OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1974 1.110 kiyohara OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1975 1.110 kiyohara
1976 1.110 kiyohara /* Allow async. request to us */
1977 1.110 kiyohara OWRITE(sc, OHCI_AREQHI, 1 << 31);
1978 1.110 kiyohara if (firewire_phydma_enable) {
1979 1.110 kiyohara /* allow from all nodes */
1980 1.110 kiyohara OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1981 1.110 kiyohara OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1982 1.110 kiyohara /* 0 to 4GB regison */
1983 1.110 kiyohara OWRITE(sc, OHCI_PREQUPPER, 0x10000);
1984 1.110 kiyohara }
1985 1.110 kiyohara /* Set ATRetries register */
1986 1.110 kiyohara OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff);
1987 1.110 kiyohara
1988 1.110 kiyohara /*
1989 1.110 kiyohara * Checking whether the node is root or not. If root, turn on
1990 1.110 kiyohara * cycle master.
1991 1.110 kiyohara */
1992 1.110 kiyohara node_id = OREAD(sc, FWOHCI_NODEID);
1993 1.110 kiyohara plen = OREAD(sc, OHCI_SID_CNT);
1994 1.110 kiyohara
1995 1.110 kiyohara fc->nodeid = node_id & 0x3f;
1996 1.110 kiyohara fw_printf(fc->dev, "node_id=0x%08x, gen=%d, ",
1997 1.110 kiyohara node_id, (plen >> 16) & 0xff);
1998 1.110 kiyohara if (!(node_id & OHCI_NODE_VALID)) {
1999 1.110 kiyohara printf("Bus reset failure\n");
2000 1.110 kiyohara goto sidout;
2001 1.110 kiyohara }
2002 1.110 kiyohara
2003 1.110 kiyohara /* cycle timer */
2004 1.110 kiyohara sc->cycle_lost = 0;
2005 1.110 kiyohara OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
2006 1.110 kiyohara if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
2007 1.110 kiyohara printf("CYCLEMASTER mode\n");
2008 1.110 kiyohara OWRITE(sc, OHCI_LNKCTL,
2009 1.110 kiyohara OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
2010 1.110 kiyohara } else {
2011 1.110 kiyohara printf("non CYCLEMASTER mode\n");
2012 1.110 kiyohara OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
2013 1.110 kiyohara OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
2014 1.110 kiyohara }
2015 1.110 kiyohara
2016 1.110 kiyohara fc->status = FWBUSINIT;
2017 1.110 kiyohara
2018 1.110 kiyohara if (!kdb_active)
2019 1.110 kiyohara fw_taskqueue_enqueue(sc->fc.taskqueue,
2020 1.110 kiyohara &sc->fwohci_task_sid);
2021 1.110 kiyohara }
2022 1.110 kiyohara sidout:
2023 1.110 kiyohara if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
2024 1.110 kiyohara fw_taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
2025 1.110 kiyohara
2026 1.110 kiyohara CTR0(KTR_DEV, "fwohci_intr_core done");
2027 1.110 kiyohara }
2028 1.110 kiyohara
2029 1.110 kiyohara static void
2030 1.110 kiyohara fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
2031 1.110 kiyohara {
2032 1.110 kiyohara uint32_t irstat, itstat;
2033 1.110 kiyohara u_int i;
2034 1.110 kiyohara struct firewire_comm *fc = (struct firewire_comm *)sc;
2035 1.110 kiyohara
2036 1.110 kiyohara CTR0(KTR_DEV, "fwohci_intr_dma");
2037 1.110 kiyohara if (stat & OHCI_INT_DMA_IR) {
2038 1.110 kiyohara irstat = fw_atomic_readandclear_int(&sc->irstat);
2039 1.89 kiyohara for(i = 0; i < fc->nisodma ; i++){
2040 1.89 kiyohara struct fwohci_dbch *dbch;
2041 1.7 onoe
2042 1.89 kiyohara if((irstat & (1 << i)) != 0){
2043 1.89 kiyohara dbch = &sc->ir[i];
2044 1.89 kiyohara if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
2045 1.110 kiyohara fw_printf(sc->fc.dev,
2046 1.89 kiyohara "dma(%d) not active\n", i);
2047 1.89 kiyohara continue;
2048 1.89 kiyohara }
2049 1.89 kiyohara fwohci_rbuf_update(sc, i);
2050 1.89 kiyohara }
2051 1.89 kiyohara }
2052 1.89 kiyohara }
2053 1.110 kiyohara if (stat & OHCI_INT_DMA_IT) {
2054 1.110 kiyohara itstat = fw_atomic_readandclear_int(&sc->itstat);
2055 1.89 kiyohara for(i = 0; i < fc->nisodma ; i++){
2056 1.89 kiyohara if((itstat & (1 << i)) != 0){
2057 1.89 kiyohara fwohci_tbuf_update(sc, i);
2058 1.89 kiyohara }
2059 1.89 kiyohara }
2060 1.89 kiyohara }
2061 1.110 kiyohara if (stat & OHCI_INT_DMA_PRRS) {
2062 1.89 kiyohara #if 0
2063 1.89 kiyohara dump_dma(sc, ARRS_CH);
2064 1.89 kiyohara dump_db(sc, ARRS_CH);
2065 1.89 kiyohara #endif
2066 1.89 kiyohara fwohci_arcv(sc, &sc->arrs, count);
2067 1.89 kiyohara }
2068 1.110 kiyohara if (stat & OHCI_INT_DMA_PRRQ) {
2069 1.89 kiyohara #if 0
2070 1.89 kiyohara dump_dma(sc, ARRQ_CH);
2071 1.89 kiyohara dump_db(sc, ARRQ_CH);
2072 1.89 kiyohara #endif
2073 1.89 kiyohara fwohci_arcv(sc, &sc->arrq, count);
2074 1.89 kiyohara }
2075 1.89 kiyohara if (stat & OHCI_INT_CYC_LOST) {
2076 1.89 kiyohara if (sc->cycle_lost >= 0)
2077 1.89 kiyohara sc->cycle_lost ++;
2078 1.89 kiyohara if (sc->cycle_lost > 10) {
2079 1.89 kiyohara sc->cycle_lost = -1;
2080 1.89 kiyohara #if 0
2081 1.89 kiyohara OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
2082 1.89 kiyohara #endif
2083 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
2084 1.110 kiyohara fw_printf(fc->dev, "too many cycle lost, "
2085 1.89 kiyohara "no cycle master presents?\n");
2086 1.89 kiyohara }
2087 1.89 kiyohara }
2088 1.110 kiyohara if (stat & OHCI_INT_DMA_ATRQ) {
2089 1.110 kiyohara fwohci_txd(sc, &(sc->atrq));
2090 1.110 kiyohara }
2091 1.110 kiyohara if (stat & OHCI_INT_DMA_ATRS) {
2092 1.110 kiyohara fwohci_txd(sc, &(sc->atrs));
2093 1.110 kiyohara }
2094 1.110 kiyohara if (stat & OHCI_INT_PW_ERR) {
2095 1.110 kiyohara fw_printf(fc->dev, "posted write error\n");
2096 1.110 kiyohara }
2097 1.110 kiyohara if (stat & OHCI_INT_ERR) {
2098 1.110 kiyohara fw_printf(fc->dev, "unrecoverable error\n");
2099 1.110 kiyohara }
2100 1.110 kiyohara if (stat & OHCI_INT_PHY_INT) {
2101 1.110 kiyohara fw_printf(fc->dev, "phy int\n");
2102 1.110 kiyohara }
2103 1.110 kiyohara
2104 1.110 kiyohara CTR0(KTR_DEV, "fwohci_intr_dma done");
2105 1.110 kiyohara return;
2106 1.110 kiyohara }
2107 1.89 kiyohara
2108 1.110 kiyohara static void
2109 1.110 kiyohara fwohci_task_busreset(void *arg, int pending)
2110 1.110 kiyohara {
2111 1.110 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2112 1.89 kiyohara
2113 1.110 kiyohara fw_busreset(&sc->fc, FWBUSRESET);
2114 1.110 kiyohara OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2115 1.110 kiyohara OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2116 1.110 kiyohara }
2117 1.89 kiyohara
2118 1.110 kiyohara static void
2119 1.110 kiyohara fwohci_task_sid(void *arg, int pending)
2120 1.110 kiyohara {
2121 1.110 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2122 1.110 kiyohara struct firewire_comm *fc = &sc->fc;
2123 1.110 kiyohara uint32_t *buf;
2124 1.110 kiyohara int i, plen;
2125 1.3 onoe
2126 1.110 kiyohara plen = OREAD(sc, OHCI_SID_CNT);
2127 1.3 onoe
2128 1.110 kiyohara if (plen & OHCI_SID_ERR) {
2129 1.110 kiyohara fw_printf(fc->dev, "SID Error\n");
2130 1.110 kiyohara return;
2131 1.89 kiyohara }
2132 1.110 kiyohara plen &= OHCI_SID_CNT_MASK;
2133 1.110 kiyohara if (plen < 4 || plen > OHCI_SIDSIZE) {
2134 1.110 kiyohara fw_printf(fc->dev, "invalid SID len = %d\n", plen);
2135 1.110 kiyohara return;
2136 1.89 kiyohara }
2137 1.110 kiyohara plen -= 4; /* chop control info */
2138 1.110 kiyohara buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2139 1.110 kiyohara if (buf == NULL) {
2140 1.110 kiyohara fw_printf(fc->dev, "malloc failed\n");
2141 1.110 kiyohara return;
2142 1.89 kiyohara }
2143 1.110 kiyohara for (i = 0; i < plen / 4; i ++)
2144 1.110 kiyohara buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]);
2145 1.110 kiyohara #if 1 /* XXX needed?? */
2146 1.110 kiyohara /* pending all pre-bus_reset packets */
2147 1.110 kiyohara fwohci_txd(sc, &sc->atrq);
2148 1.110 kiyohara fwohci_txd(sc, &sc->atrs);
2149 1.110 kiyohara fwohci_arcv(sc, &sc->arrs, -1);
2150 1.110 kiyohara fwohci_arcv(sc, &sc->arrq, -1);
2151 1.110 kiyohara fw_drain_txq(fc);
2152 1.89 kiyohara #endif
2153 1.110 kiyohara fw_sidrcv(fc, buf, plen);
2154 1.110 kiyohara free(buf, M_FW);
2155 1.3 onoe }
2156 1.3 onoe
2157 1.7 onoe static void
2158 1.110 kiyohara fwohci_task_dma(void *arg, int pending)
2159 1.7 onoe {
2160 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2161 1.89 kiyohara uint32_t stat;
2162 1.7 onoe
2163 1.89 kiyohara again:
2164 1.110 kiyohara stat = fw_atomic_readandclear_int(&sc->intstat);
2165 1.110 kiyohara if (stat)
2166 1.110 kiyohara fwohci_intr_dma(sc, stat, -1);
2167 1.110 kiyohara else
2168 1.89 kiyohara return;
2169 1.89 kiyohara goto again;
2170 1.7 onoe }
2171 1.7 onoe
2172 1.110 kiyohara static int
2173 1.110 kiyohara fwohci_check_stat(struct fwohci_softc *sc)
2174 1.7 onoe {
2175 1.89 kiyohara uint32_t stat, irstat, itstat;
2176 1.7 onoe
2177 1.89 kiyohara stat = OREAD(sc, FWOHCI_INTSTAT);
2178 1.89 kiyohara CTR1(KTR_DEV, "fwoch_check_stat 0x%08x", stat);
2179 1.89 kiyohara if (stat == 0xffffffff) {
2180 1.110 kiyohara fw_printf(sc->fc.dev,
2181 1.89 kiyohara "device physically ejected?\n");
2182 1.110 kiyohara return (FILTER_STRAY);
2183 1.7 onoe }
2184 1.89 kiyohara if (stat)
2185 1.110 kiyohara OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2186 1.110 kiyohara
2187 1.110 kiyohara stat &= sc->intmask;
2188 1.110 kiyohara if (stat == 0)
2189 1.110 kiyohara return (FILTER_STRAY);
2190 1.110 kiyohara
2191 1.110 kiyohara fw_atomic_set_int(&sc->intstat, stat);
2192 1.89 kiyohara if (stat & OHCI_INT_DMA_IR) {
2193 1.89 kiyohara irstat = OREAD(sc, OHCI_IR_STAT);
2194 1.89 kiyohara OWRITE(sc, OHCI_IR_STATCLR, irstat);
2195 1.110 kiyohara fw_atomic_set_int(&sc->irstat, irstat);
2196 1.89 kiyohara }
2197 1.89 kiyohara if (stat & OHCI_INT_DMA_IT) {
2198 1.89 kiyohara itstat = OREAD(sc, OHCI_IT_STAT);
2199 1.89 kiyohara OWRITE(sc, OHCI_IT_STATCLR, itstat);
2200 1.110 kiyohara fw_atomic_set_int(&sc->itstat, itstat);
2201 1.89 kiyohara }
2202 1.110 kiyohara
2203 1.110 kiyohara fwohci_intr_core(sc, stat, -1);
2204 1.110 kiyohara return (FILTER_HANDLED);
2205 1.7 onoe }
2206 1.7 onoe
2207 1.110 kiyohara int
2208 1.110 kiyohara fwohci_filt(void *arg)
2209 1.3 onoe {
2210 1.89 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2211 1.3 onoe
2212 1.89 kiyohara if (!(sc->intmask & OHCI_INT_EN)) {
2213 1.89 kiyohara /* polling mode */
2214 1.110 kiyohara return (FILTER_STRAY);
2215 1.3 onoe }
2216 1.110 kiyohara return (fwohci_check_stat(sc));
2217 1.110 kiyohara }
2218 1.110 kiyohara
2219 1.111 dogcow int
2220 1.110 kiyohara fwohci_intr(void *arg)
2221 1.110 kiyohara {
2222 1.3 onoe
2223 1.110 kiyohara fwohci_filt(arg);
2224 1.89 kiyohara CTR0(KTR_DEV, "fwohci_intr end");
2225 1.111 dogcow return 0;
2226 1.9 onoe }
2227 1.9 onoe
2228 1.89 kiyohara void
2229 1.103 christos fwohci_poll(struct firewire_comm *fc, int quick, int count)
2230 1.9 onoe {
2231 1.110 kiyohara struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2232 1.9 onoe
2233 1.110 kiyohara fwohci_check_stat(sc);
2234 1.3 onoe }
2235 1.3 onoe
2236 1.3 onoe static void
2237 1.89 kiyohara fwohci_set_intr(struct firewire_comm *fc, int enable)
2238 1.9 onoe {
2239 1.89 kiyohara struct fwohci_softc *sc;
2240 1.9 onoe
2241 1.89 kiyohara sc = (struct fwohci_softc *)fc;
2242 1.89 kiyohara if (firewire_debug)
2243 1.110 kiyohara fw_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2244 1.89 kiyohara if (enable) {
2245 1.89 kiyohara sc->intmask |= OHCI_INT_EN;
2246 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2247 1.89 kiyohara } else {
2248 1.89 kiyohara sc->intmask &= ~OHCI_INT_EN;
2249 1.89 kiyohara OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2250 1.89 kiyohara }
2251 1.9 onoe }
2252 1.9 onoe
2253 1.9 onoe static void
2254 1.89 kiyohara fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2255 1.89 kiyohara {
2256 1.89 kiyohara struct firewire_comm *fc = &sc->fc;
2257 1.89 kiyohara struct fwohcidb *db;
2258 1.89 kiyohara struct fw_bulkxfer *chunk;
2259 1.89 kiyohara struct fw_xferq *it;
2260 1.89 kiyohara uint32_t stat, count;
2261 1.89 kiyohara int s, w=0, ldesc;
2262 1.89 kiyohara
2263 1.89 kiyohara it = fc->it[dmach];
2264 1.89 kiyohara ldesc = sc->it[dmach].ndesc - 1;
2265 1.89 kiyohara s = splfw(); /* unnecessary ? */
2266 1.110 kiyohara FW_GLOCK(fc);
2267 1.99 kiyohara fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2268 1.89 kiyohara if (firewire_debug)
2269 1.89 kiyohara dump_db(sc, ITX_CH + dmach);
2270 1.89 kiyohara while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2271 1.89 kiyohara db = ((struct fwohcidb_tr *)(chunk->end))->db;
2272 1.100 blymn stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2273 1.89 kiyohara >> OHCI_STATUS_SHIFT;
2274 1.89 kiyohara db = ((struct fwohcidb_tr *)(chunk->start))->db;
2275 1.89 kiyohara /* timestamp */
2276 1.89 kiyohara count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2277 1.89 kiyohara & OHCI_COUNT_MASK;
2278 1.89 kiyohara if (stat == 0)
2279 1.89 kiyohara break;
2280 1.89 kiyohara STAILQ_REMOVE_HEAD(&it->stdma, link);
2281 1.89 kiyohara switch (stat & FWOHCIEV_MASK){
2282 1.89 kiyohara case FWOHCIEV_ACKCOMPL:
2283 1.89 kiyohara #if 0
2284 1.110 kiyohara fw_printf(fc->dev, "0x%08x\n", count);
2285 1.89 kiyohara #endif
2286 1.89 kiyohara break;
2287 1.89 kiyohara default:
2288 1.110 kiyohara fw_printf(fc->dev,
2289 1.89 kiyohara "Isochronous transmit err %02x(%s)\n",
2290 1.89 kiyohara stat, fwohcicode[stat & 0x1f]);
2291 1.89 kiyohara }
2292 1.89 kiyohara STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2293 1.89 kiyohara w++;
2294 1.9 onoe }
2295 1.110 kiyohara FW_GUNLOCK(fc);
2296 1.89 kiyohara splx(s);
2297 1.89 kiyohara if (w)
2298 1.89 kiyohara wakeup(it);
2299 1.3 onoe }
2300 1.3 onoe
2301 1.89 kiyohara static void
2302 1.89 kiyohara fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2303 1.3 onoe {
2304 1.89 kiyohara struct firewire_comm *fc = &sc->fc;
2305 1.89 kiyohara struct fwohcidb_tr *db_tr;
2306 1.89 kiyohara struct fw_bulkxfer *chunk;
2307 1.89 kiyohara struct fw_xferq *ir;
2308 1.89 kiyohara uint32_t stat;
2309 1.110 kiyohara int s, w = 0, ldesc;
2310 1.3 onoe
2311 1.89 kiyohara ir = fc->ir[dmach];
2312 1.89 kiyohara ldesc = sc->ir[dmach].ndesc - 1;
2313 1.110 kiyohara
2314 1.89 kiyohara #if 0
2315 1.89 kiyohara dump_db(sc, dmach);
2316 1.89 kiyohara #endif
2317 1.89 kiyohara s = splfw();
2318 1.110 kiyohara if ((ir->flag & FWXFERQ_HANDLER) == 0)
2319 1.110 kiyohara FW_GLOCK(fc);
2320 1.99 kiyohara fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2321 1.89 kiyohara while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2322 1.89 kiyohara db_tr = (struct fwohcidb_tr *)chunk->end;
2323 1.89 kiyohara stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2324 1.89 kiyohara >> OHCI_STATUS_SHIFT;
2325 1.89 kiyohara if (stat == 0)
2326 1.89 kiyohara break;
2327 1.3 onoe
2328 1.89 kiyohara if (chunk->mbuf != NULL) {
2329 1.89 kiyohara fw_bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2330 1.89 kiyohara BUS_DMASYNC_POSTREAD);
2331 1.89 kiyohara fw_bus_dmamap_unload(
2332 1.89 kiyohara sc->ir[dmach].dmat, db_tr->dma_map);
2333 1.89 kiyohara } else if (ir->buf != NULL) {
2334 1.89 kiyohara fwdma_sync_multiseg(ir->buf, chunk->poffset,
2335 1.89 kiyohara ir->bnpacket, BUS_DMASYNC_POSTREAD);
2336 1.89 kiyohara } else {
2337 1.89 kiyohara /* XXX */
2338 1.89 kiyohara printf("fwohci_rbuf_update: this shouldn't happend\n");
2339 1.89 kiyohara }
2340 1.3 onoe
2341 1.89 kiyohara STAILQ_REMOVE_HEAD(&ir->stdma, link);
2342 1.89 kiyohara STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2343 1.89 kiyohara switch (stat & FWOHCIEV_MASK) {
2344 1.89 kiyohara case FWOHCIEV_ACKCOMPL:
2345 1.89 kiyohara chunk->resp = 0;
2346 1.89 kiyohara break;
2347 1.89 kiyohara default:
2348 1.89 kiyohara chunk->resp = EINVAL;
2349 1.110 kiyohara fw_printf(fc->dev, "Isochronous receive err %02x(%s)\n",
2350 1.89 kiyohara stat, fwohcicode[stat & 0x1f]);
2351 1.89 kiyohara }
2352 1.89 kiyohara w++;
2353 1.89 kiyohara }
2354 1.110 kiyohara if ((ir->flag & FWXFERQ_HANDLER) == 0)
2355 1.110 kiyohara FW_GUNLOCK(fc);
2356 1.89 kiyohara splx(s);
2357 1.110 kiyohara if (w == 0)
2358 1.110 kiyohara return;
2359 1.110 kiyohara if (ir->flag & FWXFERQ_HANDLER)
2360 1.110 kiyohara ir->hand(ir);
2361 1.110 kiyohara else
2362 1.110 kiyohara wakeup(ir);
2363 1.3 onoe }
2364 1.3 onoe
2365 1.89 kiyohara void
2366 1.89 kiyohara dump_dma(struct fwohci_softc *sc, uint32_t ch)
2367 1.3 onoe {
2368 1.89 kiyohara uint32_t off, cntl, stat, cmd, match;
2369 1.3 onoe
2370 1.89 kiyohara if(ch == 0){
2371 1.89 kiyohara off = OHCI_ATQOFF;
2372 1.89 kiyohara }else if(ch == 1){
2373 1.89 kiyohara off = OHCI_ATSOFF;
2374 1.89 kiyohara }else if(ch == 2){
2375 1.89 kiyohara off = OHCI_ARQOFF;
2376 1.89 kiyohara }else if(ch == 3){
2377 1.89 kiyohara off = OHCI_ARSOFF;
2378 1.89 kiyohara }else if(ch < IRX_CH){
2379 1.89 kiyohara off = OHCI_ITCTL(ch - ITX_CH);
2380 1.89 kiyohara }else{
2381 1.89 kiyohara off = OHCI_IRCTL(ch - IRX_CH);
2382 1.89 kiyohara }
2383 1.89 kiyohara cntl = stat = OREAD(sc, off);
2384 1.89 kiyohara cmd = OREAD(sc, off + 0xc);
2385 1.89 kiyohara match = OREAD(sc, off + 0x10);
2386 1.89 kiyohara
2387 1.110 kiyohara fw_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2388 1.89 kiyohara ch,
2389 1.100 blymn cntl,
2390 1.100 blymn cmd,
2391 1.89 kiyohara match);
2392 1.89 kiyohara stat &= 0xffff ;
2393 1.89 kiyohara if (stat) {
2394 1.110 kiyohara fw_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2395 1.89 kiyohara ch,
2396 1.89 kiyohara stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2397 1.89 kiyohara stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2398 1.89 kiyohara stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2399 1.89 kiyohara stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2400 1.89 kiyohara stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2401 1.89 kiyohara stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2402 1.89 kiyohara fwohcicode[stat & 0x1f],
2403 1.89 kiyohara stat & 0x1f
2404 1.89 kiyohara );
2405 1.89 kiyohara }else{
2406 1.110 kiyohara fw_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2407 1.89 kiyohara }
2408 1.3 onoe }
2409 1.3 onoe
2410 1.89 kiyohara void
2411 1.89 kiyohara dump_db(struct fwohci_softc *sc, uint32_t ch)
2412 1.3 onoe {
2413 1.89 kiyohara struct fwohci_dbch *dbch;
2414 1.89 kiyohara struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2415 1.89 kiyohara struct fwohcidb *curr = NULL, *prev, *next = NULL;
2416 1.89 kiyohara int idb, jdb;
2417 1.89 kiyohara uint32_t cmd, off;
2418 1.89 kiyohara if(ch == 0){
2419 1.89 kiyohara off = OHCI_ATQOFF;
2420 1.89 kiyohara dbch = &sc->atrq;
2421 1.89 kiyohara }else if(ch == 1){
2422 1.89 kiyohara off = OHCI_ATSOFF;
2423 1.89 kiyohara dbch = &sc->atrs;
2424 1.89 kiyohara }else if(ch == 2){
2425 1.89 kiyohara off = OHCI_ARQOFF;
2426 1.89 kiyohara dbch = &sc->arrq;
2427 1.89 kiyohara }else if(ch == 3){
2428 1.89 kiyohara off = OHCI_ARSOFF;
2429 1.89 kiyohara dbch = &sc->arrs;
2430 1.89 kiyohara }else if(ch < IRX_CH){
2431 1.89 kiyohara off = OHCI_ITCTL(ch - ITX_CH);
2432 1.89 kiyohara dbch = &sc->it[ch - ITX_CH];
2433 1.89 kiyohara }else {
2434 1.89 kiyohara off = OHCI_IRCTL(ch - IRX_CH);
2435 1.89 kiyohara dbch = &sc->ir[ch - IRX_CH];
2436 1.89 kiyohara }
2437 1.89 kiyohara cmd = OREAD(sc, off + 0xc);
2438 1.3 onoe
2439 1.89 kiyohara if( dbch->ndb == 0 ){
2440 1.110 kiyohara fw_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2441 1.89 kiyohara return;
2442 1.89 kiyohara }
2443 1.89 kiyohara pp = dbch->top;
2444 1.89 kiyohara prev = pp->db;
2445 1.89 kiyohara for(idb = 0 ; idb < dbch->ndb ; idb ++ ){
2446 1.89 kiyohara cp = STAILQ_NEXT(pp, link);
2447 1.89 kiyohara if(cp == NULL){
2448 1.89 kiyohara curr = NULL;
2449 1.89 kiyohara goto outdb;
2450 1.89 kiyohara }
2451 1.89 kiyohara np = STAILQ_NEXT(cp, link);
2452 1.89 kiyohara for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){
2453 1.89 kiyohara if ((cmd & 0xfffffff0) == cp->bus_addr) {
2454 1.89 kiyohara curr = cp->db;
2455 1.89 kiyohara if(np != NULL){
2456 1.89 kiyohara next = np->db;
2457 1.89 kiyohara }else{
2458 1.89 kiyohara next = NULL;
2459 1.89 kiyohara }
2460 1.89 kiyohara goto outdb;
2461 1.89 kiyohara }
2462 1.89 kiyohara }
2463 1.89 kiyohara pp = STAILQ_NEXT(pp, link);
2464 1.89 kiyohara if(pp == NULL){
2465 1.89 kiyohara curr = NULL;
2466 1.89 kiyohara goto outdb;
2467 1.62 haya }
2468 1.89 kiyohara prev = pp->db;
2469 1.89 kiyohara }
2470 1.89 kiyohara outdb:
2471 1.89 kiyohara if( curr != NULL){
2472 1.89 kiyohara #if 0
2473 1.89 kiyohara printf("Prev DB %d\n", ch);
2474 1.89 kiyohara print_db(pp, prev, ch, dbch->ndesc);
2475 1.89 kiyohara #endif
2476 1.89 kiyohara printf("Current DB %d\n", ch);
2477 1.89 kiyohara print_db(cp, curr, ch, dbch->ndesc);
2478 1.89 kiyohara #if 0
2479 1.89 kiyohara printf("Next DB %d\n", ch);
2480 1.89 kiyohara print_db(np, next, ch, dbch->ndesc);
2481 1.89 kiyohara #endif
2482 1.89 kiyohara }else{
2483 1.89 kiyohara printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2484 1.7 onoe }
2485 1.89 kiyohara return;
2486 1.7 onoe }
2487 1.7 onoe
2488 1.89 kiyohara void
2489 1.89 kiyohara print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2490 1.89 kiyohara uint32_t ch, uint32_t hogemax)
2491 1.7 onoe {
2492 1.89 kiyohara fwohcireg_t stat;
2493 1.89 kiyohara int i, key;
2494 1.89 kiyohara uint32_t cmd, res;
2495 1.89 kiyohara
2496 1.89 kiyohara if(db == NULL){
2497 1.89 kiyohara printf("No Descriptor is found\n");
2498 1.89 kiyohara return;
2499 1.89 kiyohara }
2500 1.7 onoe
2501 1.89 kiyohara printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2502 1.89 kiyohara ch,
2503 1.89 kiyohara "Current",
2504 1.89 kiyohara "OP ",
2505 1.89 kiyohara "KEY",
2506 1.89 kiyohara "INT",
2507 1.89 kiyohara "BR ",
2508 1.89 kiyohara "len",
2509 1.89 kiyohara "Addr",
2510 1.89 kiyohara "Depend",
2511 1.89 kiyohara "Stat",
2512 1.89 kiyohara "Cnt");
2513 1.89 kiyohara for( i = 0 ; i <= hogemax ; i ++){
2514 1.89 kiyohara cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2515 1.89 kiyohara res = FWOHCI_DMA_READ(db[i].db.desc.res);
2516 1.89 kiyohara key = cmd & OHCI_KEY_MASK;
2517 1.89 kiyohara stat = res >> OHCI_STATUS_SHIFT;
2518 1.89 kiyohara #if defined(__DragonFly__) || \
2519 1.89 kiyohara (defined(__FreeBSD__) && __FreeBSD_version < 500000)
2520 1.89 kiyohara printf("%08x %s %s %s %s %5d %08x %08x %04x:%04x",
2521 1.89 kiyohara db_tr->bus_addr,
2522 1.89 kiyohara #else
2523 1.89 kiyohara printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2524 1.89 kiyohara (uintmax_t)db_tr->bus_addr,
2525 1.89 kiyohara #endif
2526 1.89 kiyohara dbcode[(cmd >> 28) & 0xf],
2527 1.89 kiyohara dbkey[(cmd >> 24) & 0x7],
2528 1.89 kiyohara dbcond[(cmd >> 20) & 0x3],
2529 1.89 kiyohara dbcond[(cmd >> 18) & 0x3],
2530 1.89 kiyohara cmd & OHCI_COUNT_MASK,
2531 1.89 kiyohara FWOHCI_DMA_READ(db[i].db.desc.addr),
2532 1.89 kiyohara FWOHCI_DMA_READ(db[i].db.desc.depend),
2533 1.89 kiyohara stat,
2534 1.89 kiyohara res & OHCI_COUNT_MASK);
2535 1.89 kiyohara if(stat & 0xff00){
2536 1.89 kiyohara printf(" %s%s%s%s%s%s %s(%x)\n",
2537 1.89 kiyohara stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2538 1.89 kiyohara stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2539 1.89 kiyohara stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2540 1.89 kiyohara stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2541 1.89 kiyohara stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2542 1.89 kiyohara stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2543 1.89 kiyohara fwohcicode[stat & 0x1f],
2544 1.89 kiyohara stat & 0x1f
2545 1.89 kiyohara );
2546 1.89 kiyohara }else{
2547 1.89 kiyohara printf(" Nostat\n");
2548 1.89 kiyohara }
2549 1.89 kiyohara if(key == OHCI_KEY_ST2 ){
2550 1.100 blymn printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2551 1.89 kiyohara FWOHCI_DMA_READ(db[i+1].db.immed[0]),
2552 1.89 kiyohara FWOHCI_DMA_READ(db[i+1].db.immed[1]),
2553 1.89 kiyohara FWOHCI_DMA_READ(db[i+1].db.immed[2]),
2554 1.89 kiyohara FWOHCI_DMA_READ(db[i+1].db.immed[3]));
2555 1.89 kiyohara }
2556 1.89 kiyohara if(key == OHCI_KEY_DEVICE){
2557 1.89 kiyohara return;
2558 1.89 kiyohara }
2559 1.100 blymn if((cmd & OHCI_BRANCH_MASK)
2560 1.89 kiyohara == OHCI_BRANCH_ALWAYS){
2561 1.89 kiyohara return;
2562 1.89 kiyohara }
2563 1.100 blymn if((cmd & OHCI_CMD_MASK)
2564 1.89 kiyohara == OHCI_OUTPUT_LAST){
2565 1.89 kiyohara return;
2566 1.89 kiyohara }
2567 1.100 blymn if((cmd & OHCI_CMD_MASK)
2568 1.89 kiyohara == OHCI_INPUT_LAST){
2569 1.89 kiyohara return;
2570 1.89 kiyohara }
2571 1.89 kiyohara if(key == OHCI_KEY_ST2 ){
2572 1.89 kiyohara i++;
2573 1.62 haya }
2574 1.3 onoe }
2575 1.89 kiyohara return;
2576 1.3 onoe }
2577 1.3 onoe
2578 1.89 kiyohara void
2579 1.89 kiyohara fwohci_ibr(struct firewire_comm *fc)
2580 1.7 onoe {
2581 1.89 kiyohara struct fwohci_softc *sc;
2582 1.89 kiyohara uint32_t fun;
2583 1.7 onoe
2584 1.110 kiyohara fw_printf(fc->dev, "Initiate bus reset\n");
2585 1.89 kiyohara sc = (struct fwohci_softc *)fc;
2586 1.7 onoe
2587 1.7 onoe /*
2588 1.89 kiyohara * Make sure our cached values from the config rom are
2589 1.89 kiyohara * initialised.
2590 1.7 onoe */
2591 1.89 kiyohara OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2592 1.89 kiyohara OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2593 1.36 onoe
2594 1.36 onoe /*
2595 1.89 kiyohara * Set root hold-off bit so that non cyclemaster capable node
2596 1.89 kiyohara * shouldn't became the root node.
2597 1.36 onoe */
2598 1.89 kiyohara #if 1
2599 1.89 kiyohara fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2600 1.89 kiyohara fun |= FW_PHY_IBR | FW_PHY_RHB;
2601 1.89 kiyohara fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2602 1.89 kiyohara #else /* Short bus reset */
2603 1.89 kiyohara fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2604 1.89 kiyohara fun |= FW_PHY_ISBR | FW_PHY_RHB;
2605 1.89 kiyohara fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2606 1.89 kiyohara #endif
2607 1.36 onoe }
2608 1.36 onoe
2609 1.89 kiyohara void
2610 1.89 kiyohara fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2611 1.36 onoe {
2612 1.89 kiyohara struct fwohcidb_tr *db_tr, *fdb_tr;
2613 1.89 kiyohara struct fwohci_dbch *dbch;
2614 1.89 kiyohara struct fwohcidb *db;
2615 1.89 kiyohara struct fw_pkt *fp;
2616 1.89 kiyohara struct fwohci_txpkthdr *ohcifp;
2617 1.89 kiyohara unsigned short chtag;
2618 1.89 kiyohara int idb;
2619 1.89 kiyohara
2620 1.110 kiyohara FW_GLOCK_ASSERT(&sc->fc);
2621 1.110 kiyohara
2622 1.89 kiyohara dbch = &sc->it[dmach];
2623 1.89 kiyohara chtag = sc->it[dmach].xferq.flag & 0xff;
2624 1.89 kiyohara
2625 1.89 kiyohara db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2626 1.89 kiyohara fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2627 1.89 kiyohara /*
2628 1.110 kiyohara fw_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2629 1.89 kiyohara */
2630 1.89 kiyohara for (idb = 0; idb < dbch->xferq.bnpacket; idb ++) {
2631 1.89 kiyohara db = db_tr->db;
2632 1.89 kiyohara fp = (struct fw_pkt *)db_tr->buf;
2633 1.89 kiyohara ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2634 1.89 kiyohara ohcifp->mode.ld[0] = fp->mode.ld[0];
2635 1.89 kiyohara ohcifp->mode.common.spd = 0 & 0x7;
2636 1.89 kiyohara ohcifp->mode.stream.len = fp->mode.stream.len;
2637 1.89 kiyohara ohcifp->mode.stream.chtag = chtag;
2638 1.89 kiyohara ohcifp->mode.stream.tcode = 0xa;
2639 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
2640 1.100 blymn FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2641 1.100 blymn FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2642 1.89 kiyohara #endif
2643 1.36 onoe
2644 1.89 kiyohara FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2645 1.89 kiyohara FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2646 1.89 kiyohara FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2647 1.89 kiyohara #if 0 /* if bulkxfer->npackets changes */
2648 1.89 kiyohara db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2649 1.89 kiyohara | OHCI_UPDATE
2650 1.89 kiyohara | OHCI_BRANCH_ALWAYS;
2651 1.89 kiyohara db[0].db.desc.depend =
2652 1.89 kiyohara = db[dbch->ndesc - 1].db.desc.depend
2653 1.89 kiyohara = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2654 1.89 kiyohara #else
2655 1.89 kiyohara FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2656 1.89 kiyohara FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2657 1.89 kiyohara #endif
2658 1.106 christos bulkxfer->end = (void *)db_tr;
2659 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link);
2660 1.36 onoe }
2661 1.89 kiyohara db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2662 1.89 kiyohara FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2663 1.89 kiyohara FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2664 1.89 kiyohara #if 0 /* if bulkxfer->npackets changes */
2665 1.89 kiyohara db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2666 1.89 kiyohara /* OHCI 1.1 and above */
2667 1.89 kiyohara db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2668 1.89 kiyohara #endif
2669 1.89 kiyohara /*
2670 1.89 kiyohara db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2671 1.89 kiyohara fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2672 1.110 kiyohara fw_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2673 1.89 kiyohara */
2674 1.89 kiyohara return;
2675 1.7 onoe }
2676 1.7 onoe
2677 1.89 kiyohara static int
2678 1.89 kiyohara fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2679 1.89 kiyohara int poffset)
2680 1.3 onoe {
2681 1.89 kiyohara struct fwohcidb *db = db_tr->db;
2682 1.89 kiyohara struct fw_xferq *it;
2683 1.89 kiyohara int err = 0;
2684 1.3 onoe
2685 1.89 kiyohara it = &dbch->xferq;
2686 1.89 kiyohara if(it->buf == 0){
2687 1.89 kiyohara err = EINVAL;
2688 1.89 kiyohara return err;
2689 1.89 kiyohara }
2690 1.89 kiyohara db_tr->buf = fwdma_v_addr(it->buf, poffset);
2691 1.89 kiyohara db_tr->dbcnt = 3;
2692 1.40 haya
2693 1.89 kiyohara FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2694 1.89 kiyohara OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2695 1.89 kiyohara FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2696 1.89 kiyohara bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2697 1.89 kiyohara FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2698 1.95 kiyohara fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2699 1.62 haya
2700 1.89 kiyohara FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2701 1.89 kiyohara OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2702 1.62 haya #if 1
2703 1.89 kiyohara FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2704 1.89 kiyohara FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2705 1.62 haya #endif
2706 1.89 kiyohara return 0;
2707 1.62 haya }
2708 1.62 haya
2709 1.62 haya int
2710 1.89 kiyohara fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2711 1.89 kiyohara int poffset, struct fwdma_alloc *dummy_dma)
2712 1.62 haya {
2713 1.89 kiyohara struct fwohcidb *db = db_tr->db;
2714 1.89 kiyohara struct fw_xferq *ir;
2715 1.89 kiyohara int i, ldesc;
2716 1.89 kiyohara bus_addr_t dbuf[2];
2717 1.89 kiyohara int dsiz[2];
2718 1.62 haya
2719 1.89 kiyohara ir = &dbch->xferq;
2720 1.104 kiyohara if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2721 1.104 kiyohara if (db_tr->buf == NULL)
2722 1.104 kiyohara db_tr->buf = fwdma_malloc_size(
2723 1.104 kiyohara dbch->dmat, &db_tr->dma_map,
2724 1.104 kiyohara ir->psize, &dbuf[0], BUS_DMA_NOWAIT);
2725 1.89 kiyohara if (db_tr->buf == NULL)
2726 1.89 kiyohara return(ENOMEM);
2727 1.89 kiyohara db_tr->dbcnt = 1;
2728 1.89 kiyohara dsiz[0] = ir->psize;
2729 1.89 kiyohara fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2730 1.89 kiyohara BUS_DMASYNC_PREREAD);
2731 1.62 haya } else {
2732 1.89 kiyohara db_tr->dbcnt = 0;
2733 1.89 kiyohara if (dummy_dma != NULL) {
2734 1.89 kiyohara dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2735 1.89 kiyohara dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2736 1.89 kiyohara }
2737 1.89 kiyohara dsiz[db_tr->dbcnt] = ir->psize;
2738 1.104 kiyohara if (ir->buf != NULL) {
2739 1.89 kiyohara db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2740 1.89 kiyohara dbuf[db_tr->dbcnt] = fwdma_bus_addr( ir->buf, poffset);
2741 1.62 haya }
2742 1.89 kiyohara db_tr->dbcnt++;
2743 1.62 haya }
2744 1.89 kiyohara for(i = 0 ; i < db_tr->dbcnt ; i++){
2745 1.89 kiyohara FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2746 1.89 kiyohara FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2747 1.89 kiyohara if (ir->flag & FWXFERQ_STREAM) {
2748 1.89 kiyohara FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2749 1.62 haya }
2750 1.89 kiyohara FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2751 1.62 haya }
2752 1.89 kiyohara ldesc = db_tr->dbcnt - 1;
2753 1.89 kiyohara if (ir->flag & FWXFERQ_STREAM) {
2754 1.89 kiyohara FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2755 1.62 haya }
2756 1.89 kiyohara FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2757 1.89 kiyohara return 0;
2758 1.62 haya }
2759 1.62 haya
2760 1.62 haya
2761 1.89 kiyohara static int
2762 1.89 kiyohara fwohci_arcv_swap(struct fw_pkt *fp, int len)
2763 1.89 kiyohara {
2764 1.89 kiyohara struct fw_pkt *fp0;
2765 1.89 kiyohara uint32_t ld0;
2766 1.89 kiyohara int slen, hlen;
2767 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
2768 1.89 kiyohara int i;
2769 1.89 kiyohara #endif
2770 1.62 haya
2771 1.89 kiyohara ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2772 1.62 haya #if 0
2773 1.89 kiyohara printf("ld0: x%08x\n", ld0);
2774 1.62 haya #endif
2775 1.89 kiyohara fp0 = (struct fw_pkt *)&ld0;
2776 1.89 kiyohara /* determine length to swap */
2777 1.89 kiyohara switch (fp0->mode.common.tcode) {
2778 1.89 kiyohara case FWTCODE_WRES:
2779 1.89 kiyohara CTR0(KTR_DEV, "WRES");
2780 1.89 kiyohara case FWTCODE_RREQQ:
2781 1.89 kiyohara case FWTCODE_WREQQ:
2782 1.89 kiyohara case FWTCODE_RRESQ:
2783 1.89 kiyohara case FWOHCITCODE_PHY:
2784 1.89 kiyohara slen = 12;
2785 1.89 kiyohara break;
2786 1.89 kiyohara case FWTCODE_RREQB:
2787 1.89 kiyohara case FWTCODE_WREQB:
2788 1.89 kiyohara case FWTCODE_LREQ:
2789 1.89 kiyohara case FWTCODE_RRESB:
2790 1.89 kiyohara case FWTCODE_LRES:
2791 1.89 kiyohara slen = 16;
2792 1.89 kiyohara break;
2793 1.89 kiyohara default:
2794 1.89 kiyohara printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2795 1.89 kiyohara return(0);
2796 1.62 haya }
2797 1.89 kiyohara hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2798 1.89 kiyohara if (hlen > len) {
2799 1.89 kiyohara if (firewire_debug)
2800 1.89 kiyohara printf("splitted header\n");
2801 1.89 kiyohara return(-hlen);
2802 1.62 haya }
2803 1.89 kiyohara #if BYTE_ORDER == BIG_ENDIAN
2804 1.89 kiyohara for(i = 0; i < slen/4; i ++)
2805 1.89 kiyohara fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2806 1.62 haya #endif
2807 1.89 kiyohara return(hlen);
2808 1.62 haya }
2809 1.62 haya
2810 1.62 haya static int
2811 1.89 kiyohara fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2812 1.62 haya {
2813 1.90 drochner const struct tcode_info *info;
2814 1.89 kiyohara int r;
2815 1.62 haya
2816 1.89 kiyohara info = &tinfo[fp->mode.common.tcode];
2817 1.89 kiyohara r = info->hdr_len + sizeof(uint32_t);
2818 1.89 kiyohara if ((info->flag & FWTI_BLOCK_ASY) != 0)
2819 1.89 kiyohara r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2820 1.62 haya
2821 1.89 kiyohara if (r == sizeof(uint32_t)) {
2822 1.89 kiyohara /* XXX */
2823 1.110 kiyohara fw_printf(sc->fc.dev, "Unknown tcode %d\n",
2824 1.89 kiyohara fp->mode.common.tcode);
2825 1.89 kiyohara return (-1);
2826 1.62 haya }
2827 1.62 haya
2828 1.89 kiyohara if (r > dbch->xferq.psize) {
2829 1.110 kiyohara fw_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2830 1.89 kiyohara return (-1);
2831 1.89 kiyohara /* panic ? */
2832 1.62 haya }
2833 1.62 haya
2834 1.89 kiyohara return r;
2835 1.62 haya }
2836 1.62 haya
2837 1.62 haya static void
2838 1.89 kiyohara fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2839 1.89 kiyohara struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2840 1.62 haya {
2841 1.89 kiyohara struct fwohcidb *db = &db_tr->db[0];
2842 1.62 haya
2843 1.89 kiyohara FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2844 1.89 kiyohara FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2845 1.89 kiyohara FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2846 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
2847 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2848 1.89 kiyohara dbch->bottom = db_tr;
2849 1.62 haya
2850 1.89 kiyohara if (wake)
2851 1.89 kiyohara OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2852 1.62 haya }
2853 1.62 haya
2854 1.89 kiyohara static void
2855 1.89 kiyohara fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2856 1.62 haya {
2857 1.89 kiyohara struct fwohcidb_tr *db_tr;
2858 1.89 kiyohara struct iovec vec[2];
2859 1.89 kiyohara struct fw_pkt pktbuf;
2860 1.89 kiyohara int nvec;
2861 1.89 kiyohara struct fw_pkt *fp;
2862 1.89 kiyohara uint8_t *ld;
2863 1.89 kiyohara uint32_t stat, off, status, event;
2864 1.89 kiyohara u_int spd;
2865 1.89 kiyohara int len, plen, hlen, pcnt, offset;
2866 1.89 kiyohara int s;
2867 1.106 christos void *buf;
2868 1.89 kiyohara int resCount;
2869 1.62 haya
2870 1.89 kiyohara CTR0(KTR_DEV, "fwohci_arv");
2871 1.62 haya
2872 1.89 kiyohara if(&sc->arrq == dbch){
2873 1.89 kiyohara off = OHCI_ARQOFF;
2874 1.89 kiyohara }else if(&sc->arrs == dbch){
2875 1.89 kiyohara off = OHCI_ARSOFF;
2876 1.89 kiyohara }else{
2877 1.89 kiyohara return;
2878 1.62 haya }
2879 1.62 haya
2880 1.89 kiyohara s = splfw();
2881 1.89 kiyohara db_tr = dbch->top;
2882 1.89 kiyohara pcnt = 0;
2883 1.89 kiyohara /* XXX we cannot handle a packet which lies in more than two buf */
2884 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
2885 1.99 kiyohara BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2886 1.89 kiyohara status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2887 1.89 kiyohara resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2888 1.89 kiyohara while (status & OHCI_CNTL_DMA_ACTIVE) {
2889 1.89 kiyohara #if 0
2890 1.62 haya
2891 1.89 kiyohara if (off == OHCI_ARQOFF)
2892 1.89 kiyohara printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2893 1.89 kiyohara db_tr->bus_addr, status, resCount);
2894 1.89 kiyohara #endif
2895 1.89 kiyohara len = dbch->xferq.psize - resCount;
2896 1.89 kiyohara ld = (uint8_t *)db_tr->buf;
2897 1.89 kiyohara if (dbch->pdb_tr == NULL) {
2898 1.89 kiyohara len -= dbch->buf_offset;
2899 1.89 kiyohara ld += dbch->buf_offset;
2900 1.89 kiyohara }
2901 1.89 kiyohara if (len > 0)
2902 1.89 kiyohara fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2903 1.89 kiyohara BUS_DMASYNC_POSTREAD);
2904 1.89 kiyohara while (len > 0 ) {
2905 1.89 kiyohara if (count >= 0 && count-- == 0)
2906 1.89 kiyohara goto out;
2907 1.89 kiyohara if(dbch->pdb_tr != NULL){
2908 1.89 kiyohara /* we have a fragment in previous buffer */
2909 1.89 kiyohara int rlen;
2910 1.89 kiyohara
2911 1.89 kiyohara offset = dbch->buf_offset;
2912 1.89 kiyohara if (offset < 0)
2913 1.89 kiyohara offset = - offset;
2914 1.106 christos buf = (char *)dbch->pdb_tr->buf + offset;
2915 1.89 kiyohara rlen = dbch->xferq.psize - offset;
2916 1.89 kiyohara if (firewire_debug)
2917 1.89 kiyohara printf("rlen=%d, offset=%d\n",
2918 1.89 kiyohara rlen, dbch->buf_offset);
2919 1.89 kiyohara if (dbch->buf_offset < 0) {
2920 1.89 kiyohara /* splitted in header, pull up */
2921 1.89 kiyohara char *p;
2922 1.89 kiyohara
2923 1.89 kiyohara p = (char *)&pktbuf;
2924 1.89 kiyohara bcopy(buf, p, rlen);
2925 1.89 kiyohara p += rlen;
2926 1.89 kiyohara /* this must be too long but harmless */
2927 1.89 kiyohara rlen = sizeof(pktbuf) - rlen;
2928 1.89 kiyohara if (rlen < 0)
2929 1.89 kiyohara printf("why rlen < 0\n");
2930 1.89 kiyohara bcopy(db_tr->buf, p, rlen);
2931 1.89 kiyohara ld += rlen;
2932 1.89 kiyohara len -= rlen;
2933 1.89 kiyohara hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2934 1.89 kiyohara if (hlen <= 0) {
2935 1.110 kiyohara printf("hlen should be positive.");
2936 1.89 kiyohara goto err;
2937 1.89 kiyohara }
2938 1.89 kiyohara offset = sizeof(pktbuf);
2939 1.89 kiyohara vec[0].iov_base = (char *)&pktbuf;
2940 1.89 kiyohara vec[0].iov_len = offset;
2941 1.89 kiyohara } else {
2942 1.89 kiyohara /* splitted in payload */
2943 1.89 kiyohara offset = rlen;
2944 1.89 kiyohara vec[0].iov_base = buf;
2945 1.89 kiyohara vec[0].iov_len = rlen;
2946 1.89 kiyohara }
2947 1.89 kiyohara fp=(struct fw_pkt *)vec[0].iov_base;
2948 1.89 kiyohara nvec = 1;
2949 1.89 kiyohara } else {
2950 1.89 kiyohara /* no fragment in previous buffer */
2951 1.89 kiyohara fp=(struct fw_pkt *)ld;
2952 1.89 kiyohara hlen = fwohci_arcv_swap(fp, len);
2953 1.89 kiyohara if (hlen == 0)
2954 1.89 kiyohara goto err;
2955 1.89 kiyohara if (hlen < 0) {
2956 1.89 kiyohara dbch->pdb_tr = db_tr;
2957 1.89 kiyohara dbch->buf_offset = - dbch->buf_offset;
2958 1.89 kiyohara /* sanity check */
2959 1.89 kiyohara if (resCount != 0) {
2960 1.89 kiyohara printf("resCount=%d hlen=%d\n",
2961 1.89 kiyohara resCount, hlen);
2962 1.89 kiyohara goto err;
2963 1.89 kiyohara }
2964 1.89 kiyohara goto out;
2965 1.89 kiyohara }
2966 1.89 kiyohara offset = 0;
2967 1.89 kiyohara nvec = 0;
2968 1.89 kiyohara }
2969 1.89 kiyohara plen = fwohci_get_plen(sc, dbch, fp) - offset;
2970 1.89 kiyohara if (plen < 0) {
2971 1.89 kiyohara /* minimum header size + trailer
2972 1.89 kiyohara = sizeof(fw_pkt) so this shouldn't happens */
2973 1.89 kiyohara printf("plen(%d) is negative! offset=%d\n",
2974 1.89 kiyohara plen, offset);
2975 1.89 kiyohara goto err;
2976 1.89 kiyohara }
2977 1.89 kiyohara if (plen > 0) {
2978 1.89 kiyohara len -= plen;
2979 1.89 kiyohara if (len < 0) {
2980 1.89 kiyohara dbch->pdb_tr = db_tr;
2981 1.89 kiyohara if (firewire_debug)
2982 1.89 kiyohara printf("splitted payload\n");
2983 1.89 kiyohara /* sanity check */
2984 1.89 kiyohara if (resCount != 0) {
2985 1.89 kiyohara printf("resCount=%d plen=%d"
2986 1.89 kiyohara " len=%d\n",
2987 1.89 kiyohara resCount, plen, len);
2988 1.89 kiyohara goto err;
2989 1.89 kiyohara }
2990 1.89 kiyohara goto out;
2991 1.89 kiyohara }
2992 1.89 kiyohara vec[nvec].iov_base = ld;
2993 1.89 kiyohara vec[nvec].iov_len = plen;
2994 1.89 kiyohara nvec ++;
2995 1.89 kiyohara ld += plen;
2996 1.89 kiyohara }
2997 1.89 kiyohara dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2998 1.89 kiyohara if (nvec == 0)
2999 1.89 kiyohara printf("nvec == 0\n");
3000 1.62 haya
3001 1.89 kiyohara /* DMA result-code will be written at the tail of packet */
3002 1.89 kiyohara stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
3003 1.89 kiyohara #if 0
3004 1.89 kiyohara printf("plen: %d, stat %x\n",
3005 1.89 kiyohara plen ,stat);
3006 1.89 kiyohara #endif
3007 1.89 kiyohara spd = (stat >> 21) & 0x3;
3008 1.89 kiyohara event = (stat >> 16) & 0x1f;
3009 1.89 kiyohara switch (event) {
3010 1.89 kiyohara case FWOHCIEV_ACKPEND:
3011 1.89 kiyohara #if 0
3012 1.89 kiyohara printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
3013 1.89 kiyohara #endif
3014 1.89 kiyohara /* fall through */
3015 1.89 kiyohara case FWOHCIEV_ACKCOMPL:
3016 1.89 kiyohara {
3017 1.89 kiyohara struct fw_rcv_buf rb;
3018 1.89 kiyohara
3019 1.89 kiyohara if ((vec[nvec-1].iov_len -=
3020 1.89 kiyohara sizeof(struct fwohci_trailer)) == 0)
3021 1.100 blymn nvec--;
3022 1.89 kiyohara rb.fc = &sc->fc;
3023 1.89 kiyohara rb.vec = vec;
3024 1.89 kiyohara rb.nvec = nvec;
3025 1.89 kiyohara rb.spd = spd;
3026 1.89 kiyohara fw_rcv(&rb);
3027 1.62 haya break;
3028 1.89 kiyohara }
3029 1.89 kiyohara case FWOHCIEV_BUSRST:
3030 1.110 kiyohara if ((sc->fc.status != FWBUSRESET) &&
3031 1.110 kiyohara (sc->fc.status != FWBUSINIT))
3032 1.89 kiyohara printf("got BUSRST packet!?\n");
3033 1.62 haya break;
3034 1.62 haya default:
3035 1.110 kiyohara fw_printf(sc->fc.dev,
3036 1.89 kiyohara "Async DMA Receive error err=%02x %s"
3037 1.89 kiyohara " plen=%d offset=%d len=%d status=0x%08x"
3038 1.89 kiyohara " tcode=0x%x, stat=0x%08x\n",
3039 1.89 kiyohara event, fwohcicode[event], plen,
3040 1.89 kiyohara dbch->buf_offset, len,
3041 1.89 kiyohara OREAD(sc, OHCI_DMACTL(off)),
3042 1.89 kiyohara fp->mode.common.tcode, stat);
3043 1.89 kiyohara #if 1 /* XXX */
3044 1.89 kiyohara goto err;
3045 1.89 kiyohara #endif
3046 1.62 haya break;
3047 1.62 haya }
3048 1.89 kiyohara pcnt ++;
3049 1.89 kiyohara if (dbch->pdb_tr != NULL) {
3050 1.89 kiyohara fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
3051 1.89 kiyohara off, 1);
3052 1.89 kiyohara dbch->pdb_tr = NULL;
3053 1.89 kiyohara }
3054 1.62 haya
3055 1.62 haya }
3056 1.89 kiyohara out:
3057 1.89 kiyohara if (resCount == 0) {
3058 1.89 kiyohara /* done on this buffer */
3059 1.89 kiyohara if (dbch->pdb_tr == NULL) {
3060 1.89 kiyohara fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
3061 1.89 kiyohara dbch->buf_offset = 0;
3062 1.89 kiyohara } else
3063 1.89 kiyohara if (dbch->pdb_tr != db_tr)
3064 1.89 kiyohara printf("pdb_tr != db_tr\n");
3065 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link);
3066 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
3067 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3068 1.89 kiyohara status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
3069 1.89 kiyohara >> OHCI_STATUS_SHIFT;
3070 1.89 kiyohara resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
3071 1.89 kiyohara & OHCI_COUNT_MASK;
3072 1.89 kiyohara /* XXX check buffer overrun */
3073 1.89 kiyohara dbch->top = db_tr;
3074 1.62 haya } else {
3075 1.89 kiyohara dbch->buf_offset = dbch->xferq.psize - resCount;
3076 1.89 kiyohara fw_bus_dmamap_sync(
3077 1.89 kiyohara dbch->dmat, db_tr->dma_map, BUS_DMASYNC_PREREAD);
3078 1.62 haya break;
3079 1.62 haya }
3080 1.89 kiyohara /* XXX make sure DMA is not dead */
3081 1.62 haya }
3082 1.89 kiyohara #if 0
3083 1.89 kiyohara if (pcnt < 1)
3084 1.89 kiyohara printf("fwohci_arcv: no packets\n");
3085 1.89 kiyohara #endif
3086 1.99 kiyohara fwdma_sync_multiseg_all(dbch->am,
3087 1.99 kiyohara BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3088 1.89 kiyohara splx(s);
3089 1.89 kiyohara return;
3090 1.62 haya
3091 1.89 kiyohara err:
3092 1.110 kiyohara fw_printf(sc->fc.dev, "AR DMA status=%x, ",
3093 1.89 kiyohara OREAD(sc, OHCI_DMACTL(off)));
3094 1.89 kiyohara dbch->pdb_tr = NULL;
3095 1.89 kiyohara /* skip until resCount != 0 */
3096 1.89 kiyohara printf(" skip buffer");
3097 1.89 kiyohara while (resCount == 0) {
3098 1.89 kiyohara printf(" #");
3099 1.89 kiyohara fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
3100 1.89 kiyohara db_tr = STAILQ_NEXT(db_tr, link);
3101 1.89 kiyohara resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
3102 1.89 kiyohara & OHCI_COUNT_MASK;
3103 1.89 kiyohara }
3104 1.89 kiyohara printf(" done\n");
3105 1.89 kiyohara dbch->top = db_tr;
3106 1.89 kiyohara dbch->buf_offset = dbch->xferq.psize - resCount;
3107 1.89 kiyohara OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
3108 1.99 kiyohara fwdma_sync_multiseg_all(
3109 1.99 kiyohara dbch->am, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3110 1.89 kiyohara fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map, BUS_DMASYNC_PREREAD);
3111 1.89 kiyohara splx(s);
3112 1.62 haya }
3113 1.89 kiyohara #if defined(__NetBSD__)
3114 1.62 haya
3115 1.89 kiyohara int
3116 1.89 kiyohara fwohci_print(void *aux, const char *pnp)
3117 1.100 blymn {
3118 1.101 kiyohara struct fw_attach_args *fwa = (struct fw_attach_args *)aux;
3119 1.62 haya
3120 1.89 kiyohara if (pnp)
3121 1.101 kiyohara aprint_normal("%s at %s", fwa->name, pnp);
3122 1.62 haya
3123 1.89 kiyohara return UNCONF;
3124 1.62 haya }
3125 1.89 kiyohara #endif
3126