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