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