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