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