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