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