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 __unused;
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 struct fwohci_dbch *dbch;
1506 int cycle_match, cycle_now, s, ldesc;
1507 uint32_t stat;
1508 struct fw_bulkxfer *first, *chunk, *prev;
1509 struct fw_xferq *it;
1510
1511 dbch = &sc->it[dmach];
1512 it = &dbch->xferq;
1513
1514 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1515 dbch->ndb = it->bnpacket * it->bnchunk;
1516 dbch->ndesc = 3;
1517 fwohci_db_init(sc, dbch);
1518 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1519 return ENOMEM;
1520
1521 err = fwohci_tx_enable(sc, dbch);
1522 }
1523 if (err)
1524 return err;
1525
1526 ldesc = dbch->ndesc - 1;
1527 s = splfw();
1528 FW_GLOCK(fc);
1529 prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1530 while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1531 struct fwohcidb *db;
1532
1533 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1534 BUS_DMASYNC_PREWRITE);
1535 fwohci_txbufdb(sc, dmach, chunk);
1536 if (prev != NULL) {
1537 db = ((struct fwohcidb_tr *)(prev->end))->db;
1538 #if 0 /* XXX necessary? */
1539 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1540 OHCI_BRANCH_ALWAYS);
1541 #endif
1542 #if 0 /* if bulkxfer->npacket changes */
1543 db[ldesc].db.desc.depend = db[0].db.desc.depend =
1544 ((struct fwohcidb_tr *)
1545 (chunk->start))->bus_addr | dbch->ndesc;
1546 #else
1547 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1548 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1549 #endif
1550 }
1551 STAILQ_REMOVE_HEAD(&it->stvalid, link);
1552 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1553 prev = chunk;
1554 }
1555 FW_GUNLOCK(fc);
1556 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1557 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1558 splx(s);
1559 stat = OREAD(sc, OHCI_ITCTL(dmach));
1560 if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1561 printf("stat 0x%x\n", stat);
1562
1563 if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1564 return 0;
1565
1566 #if 0
1567 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1568 #endif
1569 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1570 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1571 OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1572 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1573
1574 first = STAILQ_FIRST(&it->stdma);
1575 OWRITE(sc, OHCI_ITCMD(dmach),
1576 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1577 if (firewire_debug > 1) {
1578 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1579 #if 1
1580 dump_dma(sc, ITX_CH + dmach);
1581 #endif
1582 }
1583 if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1584 #if 1
1585 /* Don't start until all chunks are buffered */
1586 if (STAILQ_FIRST(&it->stfree) != NULL)
1587 goto out;
1588 #endif
1589 #if 1
1590 /* Clear cycle match counter bits */
1591 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1592
1593 /* 2bit second + 13bit cycle */
1594 cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1595 cycle_match = fwohci_next_cycle(fc, cycle_now);
1596
1597 OWRITE(sc, OHCI_ITCTL(dmach),
1598 OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1599 | OHCI_CNTL_DMA_RUN);
1600 #else
1601 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1602 #endif
1603 if (firewire_debug > 1) {
1604 printf("cycle_match: 0x%04x->0x%04x\n",
1605 cycle_now, cycle_match);
1606 dump_dma(sc, ITX_CH + dmach);
1607 dump_db(sc, ITX_CH + dmach);
1608 }
1609 } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1610 device_printf(sc->fc.dev,
1611 "IT DMA underrun (0x%08x)\n", stat);
1612 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1613 }
1614 out:
1615 return err;
1616 }
1617
1618 static int
1619 fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1620 {
1621 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1622 int err = 0, s, ldesc;
1623 unsigned short tag, ich;
1624 uint32_t stat;
1625 struct fwohci_dbch *dbch;
1626 struct fwohcidb_tr *db_tr;
1627 struct fw_bulkxfer *first, *prev, *chunk;
1628 struct fw_xferq *ir;
1629
1630 dbch = &sc->ir[dmach];
1631 ir = &dbch->xferq;
1632
1633 if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1634 tag = (ir->flag >> 6) & 3;
1635 ich = ir->flag & 0x3f;
1636 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1637
1638 ir->queued = 0;
1639 dbch->ndb = ir->bnpacket * ir->bnchunk;
1640 dbch->ndesc = 2;
1641 fwohci_db_init(sc, dbch);
1642 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1643 return ENOMEM;
1644 err = fwohci_rx_enable(sc, dbch);
1645 }
1646 if (err)
1647 return err;
1648
1649 first = STAILQ_FIRST(&ir->stfree);
1650 if (first == NULL) {
1651 device_printf(fc->dev, "IR DMA no free chunk\n");
1652 return 0;
1653 }
1654
1655 ldesc = dbch->ndesc - 1;
1656 s = splfw();
1657 if ((ir->flag & FWXFERQ_HANDLER) == 0)
1658 FW_GLOCK(fc);
1659 prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1660 while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1661 struct fwohcidb *db;
1662
1663 #if 1 /* XXX for if_fwe */
1664 if (chunk->mbuf != NULL) {
1665 db_tr = (struct fwohcidb_tr *)(chunk->start);
1666 db_tr->dbcnt = 1;
1667 err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1668 chunk->mbuf, fwohci_execute_db2, db_tr,
1669 /* flags */0);
1670 FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1671 OHCI_UPDATE | OHCI_INPUT_LAST |
1672 OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1673 }
1674 #endif
1675 db = ((struct fwohcidb_tr *)(chunk->end))->db;
1676 FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1677 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1678 if (prev != NULL) {
1679 db = ((struct fwohcidb_tr *)(prev->end))->db;
1680 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1681 }
1682 STAILQ_REMOVE_HEAD(&ir->stfree, link);
1683 STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1684 prev = chunk;
1685 }
1686 if ((ir->flag & FWXFERQ_HANDLER) == 0)
1687 FW_GUNLOCK(fc);
1688 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1689 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1690 splx(s);
1691 stat = OREAD(sc, OHCI_IRCTL(dmach));
1692 if (stat & OHCI_CNTL_DMA_ACTIVE)
1693 return 0;
1694 if (stat & OHCI_CNTL_DMA_RUN) {
1695 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1696 device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1697 }
1698
1699 if (firewire_debug)
1700 printf("start IR DMA 0x%x\n", stat);
1701 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1702 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1703 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1704 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1705 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1706 OWRITE(sc, OHCI_IRCMD(dmach),
1707 ((struct fwohcidb_tr *)(first->start))->bus_addr
1708 | dbch->ndesc);
1709 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1710 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1711 #if 0
1712 dump_db(sc, IRX_CH + dmach);
1713 #endif
1714 return err;
1715 }
1716
1717 int
1718 fwohci_stop(struct fwohci_softc *sc, device_t dev)
1719 {
1720 u_int i;
1721
1722 fwohci_set_intr(&sc->fc, 0);
1723
1724 /* Now stopping all DMA channel */
1725 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1726 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1727 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1728 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1729
1730 for (i = 0; i < sc->fc.nisodma; i++) {
1731 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1732 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1733 }
1734
1735 #if 0 /* Let dcons(4) be accessed */
1736 /* Stop interrupt */
1737 OWRITE(sc, FWOHCI_INTMASKCLR,
1738 OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1739 | OHCI_INT_PHY_INT
1740 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1741 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1742 | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1743 | OHCI_INT_PHY_BUS_R);
1744
1745 /* FLUSH FIFO and reset Transmitter/Receiver */
1746 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1747 #endif
1748
1749 /* XXX Link down? Bus reset? */
1750 return 0;
1751 }
1752
1753 int
1754 fwohci_resume(struct fwohci_softc *sc, device_t dev)
1755 {
1756 int i;
1757 struct fw_xferq *ir;
1758 struct fw_bulkxfer *chunk;
1759
1760 fwohci_reset(sc, dev);
1761 /* XXX resume isochronous receive automatically. (how about TX?) */
1762 for (i = 0; i < sc->fc.nisodma; i++) {
1763 ir = &sc->ir[i].xferq;
1764 if ((ir->flag & FWXFERQ_RUNNING) != 0) {
1765 device_printf(sc->fc.dev,
1766 "resume iso receive ch: %d\n", i);
1767 ir->flag &= ~FWXFERQ_RUNNING;
1768 /* requeue stdma to stfree */
1769 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1770 STAILQ_REMOVE_HEAD(&ir->stdma, link);
1771 STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1772 }
1773 sc->fc.irx_enable(&sc->fc, i);
1774 }
1775 }
1776
1777 bus_generic_resume(dev);
1778 sc->fc.ibr(&sc->fc);
1779 return 0;
1780 }
1781
1782 #ifdef OHCI_DEBUG
1783 static void
1784 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1785 {
1786 if (stat & OREAD(sc, FWOHCI_INTMASK))
1787 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",
1788 stat & OHCI_INT_EN ? "DMA_EN ":"",
1789 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1790 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1791 stat & OHCI_INT_ERR ? "INT_ERR ":"",
1792 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1793 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1794 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1795 stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1796 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1797 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1798 stat & OHCI_INT_PHY_SID ? "SID ":"",
1799 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1800 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1801 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1802 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1803 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1804 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1805 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1806 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1807 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1808 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1809 stat, OREAD(sc, FWOHCI_INTMASK)
1810 );
1811 }
1812 #endif
1813
1814 static void
1815 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1816 {
1817 struct firewire_comm *fc = (struct firewire_comm *)sc;
1818 uintmax_t prequpper;
1819 uint32_t node_id, plen;
1820
1821 FW_GLOCK_ASSERT(fc);
1822 if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1823 fc->status = FWBUSRESET;
1824 /* Disable bus reset interrupt until sid recv. */
1825 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1826
1827 device_printf(fc->dev, "%s: BUS reset\n", __func__);
1828 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1829 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1830
1831 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1832 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1833 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1834 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1835
1836 if (!kdb_active)
1837 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
1838 }
1839 if (stat & OHCI_INT_PHY_SID) {
1840 /* Enable bus reset interrupt */
1841 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1842 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1843
1844 /* Allow async. request to us */
1845 OWRITE(sc, OHCI_AREQHI, 1 << 31);
1846 if (firewire_phydma_enable) {
1847 /* allow from all nodes */
1848 OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1849 OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1850 prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16;
1851 if (prequpper > OHCI_PREQUPPER_MAX) {
1852 device_printf(fc->dev,
1853 "Physical memory size of 0x%jx exceeds "
1854 "fire wire address space. Limiting dma "
1855 "to memory below 0x%jx\n",
1856 (uintmax_t)Maxmem << PAGE_SHIFT,
1857 (uintmax_t)OHCI_PREQUPPER_MAX << 16);
1858 prequpper = OHCI_PREQUPPER_MAX;
1859 }
1860 OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff);
1861 if (OREAD(sc, OHCI_PREQUPPER) !=
1862 (prequpper & 0xffffffff)) {
1863 device_printf(fc->dev,
1864 "PhysicalUpperBound register is not "
1865 "implemented. Physical memory access "
1866 "is limited to the first 4GB\n");
1867 device_printf(fc->dev,
1868 "PhysicalUpperBound = 0x%08x\n",
1869 OREAD(sc, OHCI_PREQUPPER));
1870 }
1871 }
1872 /* Set ATRetries register */
1873 OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1874
1875 /*
1876 * Checking whether the node is root or not. If root, turn on
1877 * cycle master.
1878 */
1879 node_id = OREAD(sc, FWOHCI_NODEID);
1880 plen = OREAD(sc, OHCI_SID_CNT);
1881
1882 fc->nodeid = node_id & 0x3f;
1883 device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1884 __func__, fc->nodeid, (plen >> 16) & 0xff);
1885 if (!(node_id & OHCI_NODE_VALID)) {
1886 device_printf(fc->dev, "%s: Bus reset failure\n",
1887 __func__);
1888 goto sidout;
1889 }
1890
1891 /* cycle timer */
1892 sc->cycle_lost = 0;
1893 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1894 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1895 printf("CYCLEMASTER mode\n");
1896 OWRITE(sc, OHCI_LNKCTL,
1897 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1898 } else {
1899 printf("non CYCLEMASTER mode\n");
1900 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1901 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1902 }
1903
1904 fc->status = FWBUSINIT;
1905
1906 if (!kdb_active)
1907 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1908 }
1909 sidout:
1910 if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1911 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1912 }
1913
1914 static void
1915 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1916 {
1917 uint32_t irstat, itstat;
1918 u_int i;
1919 struct firewire_comm *fc = (struct firewire_comm *)sc;
1920
1921 if (stat & OHCI_INT_DMA_IR) {
1922 irstat = atomic_readandclear_int(&sc->irstat);
1923 for (i = 0; i < fc->nisodma; i++) {
1924 struct fwohci_dbch *dbch;
1925
1926 if ((irstat & (1 << i)) != 0) {
1927 dbch = &sc->ir[i];
1928 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1929 device_printf(sc->fc.dev,
1930 "dma(%d) not active\n", i);
1931 continue;
1932 }
1933 fwohci_rbuf_update(sc, i);
1934 }
1935 }
1936 }
1937 if (stat & OHCI_INT_DMA_IT) {
1938 itstat = atomic_readandclear_int(&sc->itstat);
1939 for (i = 0; i < fc->nisodma; i++) {
1940 if ((itstat & (1 << i)) != 0) {
1941 fwohci_tbuf_update(sc, i);
1942 }
1943 }
1944 }
1945 if (stat & OHCI_INT_DMA_PRRS) {
1946 #if 0
1947 dump_dma(sc, ARRS_CH);
1948 dump_db(sc, ARRS_CH);
1949 #endif
1950 fwohci_arcv(sc, &sc->arrs, count);
1951 }
1952 if (stat & OHCI_INT_DMA_PRRQ) {
1953 #if 0
1954 dump_dma(sc, ARRQ_CH);
1955 dump_db(sc, ARRQ_CH);
1956 #endif
1957 fwohci_arcv(sc, &sc->arrq, count);
1958 }
1959 if (stat & OHCI_INT_CYC_LOST) {
1960 if (sc->cycle_lost >= 0)
1961 sc->cycle_lost++;
1962 if (sc->cycle_lost > 10) {
1963 sc->cycle_lost = -1;
1964 #if 0
1965 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1966 #endif
1967 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1968 device_printf(fc->dev, "too many cycles lost, "
1969 "no cycle master present?\n");
1970 }
1971 }
1972 if (stat & OHCI_INT_DMA_ATRQ) {
1973 fwohci_txd(sc, &(sc->atrq));
1974 }
1975 if (stat & OHCI_INT_DMA_ATRS) {
1976 fwohci_txd(sc, &(sc->atrs));
1977 }
1978 if (stat & OHCI_INT_PW_ERR) {
1979 device_printf(fc->dev, "posted write error\n");
1980 }
1981 if (stat & OHCI_INT_ERR) {
1982 device_printf(fc->dev, "unrecoverable error\n");
1983 }
1984 if (stat & OHCI_INT_PHY_INT) {
1985 device_printf(fc->dev, "phy int\n");
1986 }
1987 }
1988
1989 static void
1990 fwohci_task_busreset(void *arg, int pending)
1991 {
1992 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1993
1994 FW_GLOCK(&sc->fc);
1995 fw_busreset(&sc->fc, FWBUSRESET);
1996 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
1997 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
1998 FW_GUNLOCK(&sc->fc);
1999 }
2000
2001 static void
2002 fwohci_task_sid(void *arg, int pending)
2003 {
2004 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2005 struct firewire_comm *fc = &sc->fc;
2006 uint32_t *buf;
2007 int i, plen;
2008
2009
2010 /*
2011 * We really should have locking
2012 * here. Not sure why it's not
2013 */
2014 plen = OREAD(sc, OHCI_SID_CNT);
2015
2016 if (plen & OHCI_SID_ERR) {
2017 device_printf(fc->dev, "SID Error\n");
2018 return;
2019 }
2020 plen &= OHCI_SID_CNT_MASK;
2021 if (plen < 4 || plen > OHCI_SIDSIZE) {
2022 device_printf(fc->dev, "invalid SID len = %d\n", plen);
2023 return;
2024 }
2025 plen -= 4; /* chop control info */
2026 buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2027 if (buf == NULL) {
2028 device_printf(fc->dev, "malloc failed\n");
2029 return;
2030 }
2031 for (i = 0; i < plen / 4; i++)
2032 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2033
2034 /* pending all pre-bus_reset packets */
2035 fwohci_txd(sc, &sc->atrq);
2036 fwohci_txd(sc, &sc->atrs);
2037 fwohci_arcv(sc, &sc->arrs, -1);
2038 fwohci_arcv(sc, &sc->arrq, -1);
2039 fw_drain_txq(fc);
2040 fw_sidrcv(fc, buf, plen);
2041 free(buf, M_FW);
2042 }
2043
2044 static void
2045 fwohci_task_dma(void *arg, int pending)
2046 {
2047 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2048 uint32_t stat;
2049
2050 again:
2051 stat = atomic_readandclear_int(&sc->intstat);
2052 if (stat)
2053 fwohci_intr_dma(sc, stat, -1);
2054 else
2055 return;
2056 goto again;
2057 }
2058
2059 static int
2060 fwohci_check_stat(struct fwohci_softc *sc)
2061 {
2062 uint32_t stat, irstat, itstat;
2063
2064 FW_GLOCK_ASSERT(&sc->fc);
2065 stat = OREAD(sc, FWOHCI_INTSTAT);
2066 if (stat == 0xffffffff) {
2067 if (!bus_child_present(sc->fc.dev))
2068 return (FILTER_HANDLED);
2069 device_printf(sc->fc.dev, "device physically ejected?\n");
2070 return (FILTER_STRAY);
2071 }
2072 if (stat)
2073 OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2074
2075 stat &= sc->intmask;
2076 if (stat == 0)
2077 return (FILTER_STRAY);
2078
2079 atomic_set_int(&sc->intstat, stat);
2080 if (stat & OHCI_INT_DMA_IR) {
2081 irstat = OREAD(sc, OHCI_IR_STAT);
2082 OWRITE(sc, OHCI_IR_STATCLR, irstat);
2083 atomic_set_int(&sc->irstat, irstat);
2084 }
2085 if (stat & OHCI_INT_DMA_IT) {
2086 itstat = OREAD(sc, OHCI_IT_STAT);
2087 OWRITE(sc, OHCI_IT_STATCLR, itstat);
2088 atomic_set_int(&sc->itstat, itstat);
2089 }
2090
2091 fwohci_intr_core(sc, stat, -1);
2092 return (FILTER_HANDLED);
2093 }
2094
2095 void
2096 fwohci_intr(void *arg)
2097 {
2098 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2099
2100 FW_GLOCK(&sc->fc);
2101 fwohci_check_stat(sc);
2102 FW_GUNLOCK(&sc->fc);
2103 }
2104
2105 void
2106 fwohci_poll(struct firewire_comm *fc, int quick, int count)
2107 {
2108 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2109
2110 FW_GLOCK(fc);
2111 fwohci_check_stat(sc);
2112 FW_GUNLOCK(fc);
2113 }
2114
2115 static void
2116 fwohci_set_intr(struct firewire_comm *fc, int enable)
2117 {
2118 struct fwohci_softc *sc;
2119
2120 sc = (struct fwohci_softc *)fc;
2121 if (firewire_debug)
2122 device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2123 if (enable) {
2124 sc->intmask |= OHCI_INT_EN;
2125 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2126 } else {
2127 sc->intmask &= ~OHCI_INT_EN;
2128 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2129 }
2130 }
2131
2132 static void
2133 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2134 {
2135 struct firewire_comm *fc = &sc->fc;
2136 struct fwohcidb *db;
2137 struct fw_bulkxfer *chunk;
2138 struct fw_xferq *it;
2139 uint32_t stat, count __unused;
2140 int s, w=0, ldesc;
2141
2142 it = fc->it[dmach];
2143 ldesc = sc->it[dmach].ndesc - 1;
2144 s = splfw(); /* unnecessary ? */
2145 FW_GLOCK(fc);
2146 fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2147 if (firewire_debug)
2148 dump_db(sc, ITX_CH + dmach);
2149 while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2150 db = ((struct fwohcidb_tr *)(chunk->end))->db;
2151 stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2152 >> OHCI_STATUS_SHIFT;
2153 db = ((struct fwohcidb_tr *)(chunk->start))->db;
2154 /* timestamp */
2155 count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2156 & OHCI_COUNT_MASK;
2157 if (stat == 0)
2158 break;
2159 STAILQ_REMOVE_HEAD(&it->stdma, link);
2160 switch (stat & FWOHCIEV_MASK) {
2161 case FWOHCIEV_ACKCOMPL:
2162 #if 0
2163 device_printf(fc->dev, "0x%08x\n", count);
2164 #endif
2165 break;
2166 default:
2167 device_printf(fc->dev,
2168 "Isochronous transmit err %02x(%s)\n",
2169 stat, fwohcicode[stat & 0x1f]);
2170 }
2171 STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2172 w++;
2173 }
2174 FW_GUNLOCK(fc);
2175 splx(s);
2176 if (w)
2177 wakeup(it);
2178 }
2179
2180 static void
2181 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2182 {
2183 struct firewire_comm *fc = &sc->fc;
2184 struct fwohcidb_tr *db_tr;
2185 struct fw_bulkxfer *chunk;
2186 struct fw_xferq *ir;
2187 uint32_t stat;
2188 int w = 0, ldesc;
2189
2190 ir = fc->ir[dmach];
2191 ldesc = sc->ir[dmach].ndesc - 1;
2192
2193 #if 0
2194 dump_db(sc, dmach);
2195 #endif
2196 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2197 FW_GLOCK(fc);
2198 fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2199 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2200 db_tr = (struct fwohcidb_tr *)chunk->end;
2201 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2202 >> OHCI_STATUS_SHIFT;
2203 if (stat == 0)
2204 break;
2205
2206 if (chunk->mbuf != NULL) {
2207 bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2208 BUS_DMASYNC_POSTREAD);
2209 bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2210 } else if (ir->buf != NULL) {
2211 fwdma_sync_multiseg(ir->buf, chunk->poffset,
2212 ir->bnpacket, BUS_DMASYNC_POSTREAD);
2213 } else {
2214 /* XXX */
2215 printf("fwohci_rbuf_update: this shouldn't happened\n");
2216 }
2217
2218 STAILQ_REMOVE_HEAD(&ir->stdma, link);
2219 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2220 switch (stat & FWOHCIEV_MASK) {
2221 case FWOHCIEV_ACKCOMPL:
2222 chunk->resp = 0;
2223 break;
2224 default:
2225 chunk->resp = EINVAL;
2226 device_printf(fc->dev,
2227 "Isochronous receive err %02x(%s)\n",
2228 stat, fwohcicode[stat & 0x1f]);
2229 }
2230 w++;
2231 }
2232 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2233 FW_GUNLOCK(fc);
2234 if (w == 0)
2235 return;
2236
2237 if (ir->flag & FWXFERQ_HANDLER)
2238 ir->hand(ir);
2239 else
2240 wakeup(ir);
2241 }
2242
2243 void
2244 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2245 {
2246 uint32_t off, cntl, stat, cmd, match;
2247
2248 if (ch == 0) {
2249 off = OHCI_ATQOFF;
2250 } else if (ch == 1) {
2251 off = OHCI_ATSOFF;
2252 } else if (ch == 2) {
2253 off = OHCI_ARQOFF;
2254 } else if (ch == 3) {
2255 off = OHCI_ARSOFF;
2256 } else if (ch < IRX_CH) {
2257 off = OHCI_ITCTL(ch - ITX_CH);
2258 } else {
2259 off = OHCI_IRCTL(ch - IRX_CH);
2260 }
2261 cntl = stat = OREAD(sc, off);
2262 cmd = OREAD(sc, off + 0xc);
2263 match = OREAD(sc, off + 0x10);
2264
2265 device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2266 ch,
2267 cntl,
2268 cmd,
2269 match);
2270 stat &= 0xffff;
2271 if (stat) {
2272 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2273 ch,
2274 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2275 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2276 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2277 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2278 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2279 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2280 fwohcicode[stat & 0x1f],
2281 stat & 0x1f
2282 );
2283 } else {
2284 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2285 }
2286 }
2287
2288 void
2289 dump_db(struct fwohci_softc *sc, uint32_t ch)
2290 {
2291 struct fwohci_dbch *dbch;
2292 struct fwohcidb_tr *cp = NULL, *pp;
2293 struct fwohcidb *curr = NULL;
2294 #if 0
2295 struct fwohcidb *prev
2296 struct fwohcidb *next = NULL;
2297 struct fwohcidb_tr *np = NULL;
2298 #endif
2299 int idb, jdb;
2300 uint32_t cmd, off;
2301
2302 if (ch == 0) {
2303 off = OHCI_ATQOFF;
2304 dbch = &sc->atrq;
2305 } else if (ch == 1) {
2306 off = OHCI_ATSOFF;
2307 dbch = &sc->atrs;
2308 } else if (ch == 2) {
2309 off = OHCI_ARQOFF;
2310 dbch = &sc->arrq;
2311 } else if (ch == 3) {
2312 off = OHCI_ARSOFF;
2313 dbch = &sc->arrs;
2314 } else if (ch < IRX_CH) {
2315 off = OHCI_ITCTL(ch - ITX_CH);
2316 dbch = &sc->it[ch - ITX_CH];
2317 } else {
2318 off = OHCI_IRCTL(ch - IRX_CH);
2319 dbch = &sc->ir[ch - IRX_CH];
2320 }
2321 cmd = OREAD(sc, off + 0xc);
2322
2323 if (dbch->ndb == 0) {
2324 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2325 return;
2326 }
2327 pp = dbch->top;
2328 #if 0
2329 prev = pp->db;
2330 #endif
2331 for (idb = 0; idb < dbch->ndb; idb++) {
2332 cp = STAILQ_NEXT(pp, link);
2333 if (cp == NULL) {
2334 curr = NULL;
2335 goto outdb;
2336 }
2337 #if 0
2338 np = STAILQ_NEXT(cp, link);
2339 #endif
2340 for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2341 if ((cmd & 0xfffffff0) == cp->bus_addr) {
2342 curr = cp->db;
2343 #if 0
2344 if (np != NULL) {
2345 next = np->db;
2346 } else {
2347 next = NULL;
2348 }
2349 #endif
2350 goto outdb;
2351 }
2352 }
2353 pp = STAILQ_NEXT(pp, link);
2354 if (pp == NULL) {
2355 curr = NULL;
2356 goto outdb;
2357 }
2358 #if 0
2359 prev = pp->db;
2360 #endif
2361 }
2362 outdb:
2363 if (curr != NULL) {
2364 #if 0
2365 printf("Prev DB %d\n", ch);
2366 print_db(pp, prev, ch, dbch->ndesc);
2367 #endif
2368 printf("Current DB %d\n", ch);
2369 print_db(cp, curr, ch, dbch->ndesc);
2370 #if 0
2371 printf("Next DB %d\n", ch);
2372 print_db(np, next, ch, dbch->ndesc);
2373 #endif
2374 } else {
2375 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2376 }
2377 return;
2378 }
2379
2380 void
2381 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2382 uint32_t ch, uint32_t max)
2383 {
2384 fwohcireg_t stat;
2385 int i, key;
2386 uint32_t cmd, res;
2387
2388 if (db == NULL) {
2389 printf("No Descriptor is found\n");
2390 return;
2391 }
2392
2393 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2394 ch,
2395 "Current",
2396 "OP ",
2397 "KEY",
2398 "INT",
2399 "BR ",
2400 "len",
2401 "Addr",
2402 "Depend",
2403 "Stat",
2404 "Cnt");
2405 for (i = 0; i <= max; i++) {
2406 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2407 res = FWOHCI_DMA_READ(db[i].db.desc.res);
2408 key = cmd & OHCI_KEY_MASK;
2409 stat = res >> OHCI_STATUS_SHIFT;
2410 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2411 (uintmax_t)db_tr->bus_addr,
2412 dbcode[(cmd >> 28) & 0xf],
2413 dbkey[(cmd >> 24) & 0x7],
2414 dbcond[(cmd >> 20) & 0x3],
2415 dbcond[(cmd >> 18) & 0x3],
2416 cmd & OHCI_COUNT_MASK,
2417 FWOHCI_DMA_READ(db[i].db.desc.addr),
2418 FWOHCI_DMA_READ(db[i].db.desc.depend),
2419 stat,
2420 res & OHCI_COUNT_MASK);
2421 if (stat & 0xff00) {
2422 printf(" %s%s%s%s%s%s %s(%x)\n",
2423 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2424 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2425 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2426 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2427 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2428 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2429 fwohcicode[stat & 0x1f],
2430 stat & 0x1f
2431 );
2432 } else {
2433 printf(" Nostat\n");
2434 }
2435 if (key == OHCI_KEY_ST2) {
2436 printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2437 FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2438 FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2439 FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2440 FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2441 }
2442 if (key == OHCI_KEY_DEVICE) {
2443 return;
2444 }
2445 if ((cmd & OHCI_BRANCH_MASK)
2446 == OHCI_BRANCH_ALWAYS) {
2447 return;
2448 }
2449 if ((cmd & OHCI_CMD_MASK)
2450 == OHCI_OUTPUT_LAST) {
2451 return;
2452 }
2453 if ((cmd & OHCI_CMD_MASK)
2454 == OHCI_INPUT_LAST) {
2455 return;
2456 }
2457 if (key == OHCI_KEY_ST2) {
2458 i++;
2459 }
2460 }
2461 return;
2462 }
2463
2464 void
2465 fwohci_ibr(struct firewire_comm *fc)
2466 {
2467 struct fwohci_softc *sc;
2468 uint32_t fun;
2469
2470 device_printf(fc->dev, "Initiate bus reset\n");
2471 sc = (struct fwohci_softc *)fc;
2472
2473 FW_GLOCK(fc);
2474 /*
2475 * Make sure our cached values from the config rom are
2476 * initialised.
2477 */
2478 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2479 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2480
2481 /*
2482 * Set root hold-off bit so that non cyclemaster capable node
2483 * shouldn't became the root node.
2484 */
2485 #if 1
2486 fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2487 fun |= FW_PHY_IBR | FW_PHY_RHB;
2488 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2489 #else /* Short bus reset */
2490 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2491 fun |= FW_PHY_ISBR | FW_PHY_RHB;
2492 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2493 #endif
2494 FW_GUNLOCK(fc);
2495 }
2496
2497 void
2498 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2499 {
2500 struct fwohcidb_tr *db_tr;
2501 #if 0
2502 struct fwohcidb_tr *fdb_tr;
2503 #endif
2504 struct fwohci_dbch *dbch;
2505 struct fwohcidb *db;
2506 struct fw_pkt *fp;
2507 struct fwohci_txpkthdr *ohcifp;
2508 unsigned short chtag;
2509 int idb;
2510
2511 FW_GLOCK_ASSERT(&sc->fc);
2512
2513 dbch = &sc->it[dmach];
2514 chtag = sc->it[dmach].xferq.flag & 0xff;
2515
2516 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2517 #if 0
2518 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2519 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2520 #endif
2521 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2522 db = db_tr->db;
2523 fp = (struct fw_pkt *)db_tr->buf;
2524 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2525 ohcifp->mode.ld[0] = fp->mode.ld[0];
2526 ohcifp->mode.common.spd = 0 & 0x7;
2527 ohcifp->mode.stream.len = fp->mode.stream.len;
2528 ohcifp->mode.stream.chtag = chtag;
2529 ohcifp->mode.stream.tcode = 0xa;
2530 #if BYTE_ORDER == BIG_ENDIAN
2531 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2532 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2533 #endif
2534
2535 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2536 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2537 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2538 #if 0 /* if bulkxfer->npackets changes */
2539 db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2540 | OHCI_UPDATE
2541 | OHCI_BRANCH_ALWAYS;
2542 db[0].db.desc.depend =
2543 = db[dbch->ndesc - 1].db.desc.depend
2544 = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2545 #else
2546 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2547 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2548 #endif
2549 bulkxfer->end = (caddr_t)db_tr;
2550 db_tr = STAILQ_NEXT(db_tr, link);
2551 }
2552 db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2553 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2554 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2555 #if 0 /* if bulkxfer->npackets changes */
2556 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2557 /* OHCI 1.1 and above */
2558 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2559 #endif
2560 #if 0
2561 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2562 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2563 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2564 #endif
2565 return;
2566 }
2567
2568 static int
2569 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2570 int poffset)
2571 {
2572 struct fwohcidb *db = db_tr->db;
2573 struct fw_xferq *it;
2574 int err = 0;
2575
2576 it = &dbch->xferq;
2577 if (it->buf == 0) {
2578 err = EINVAL;
2579 return err;
2580 }
2581 db_tr->buf = fwdma_v_addr(it->buf, poffset);
2582 db_tr->dbcnt = 3;
2583
2584 FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2585 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2586 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2587 bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2588 FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2589 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2590
2591 FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2592 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2593 #if 1
2594 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2595 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2596 #endif
2597 return 0;
2598 }
2599
2600 int
2601 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2602 int poffset, struct fwdma_alloc *dummy_dma)
2603 {
2604 struct fwohcidb *db = db_tr->db;
2605 struct fw_xferq *ir;
2606 int i, ldesc;
2607 bus_addr_t dbuf[2];
2608 int dsiz[2];
2609
2610 ir = &dbch->xferq;
2611 if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2612 if (db_tr->buf == NULL) {
2613 db_tr->buf = fwdma_malloc_size(dbch->dmat,
2614 &db_tr->dma_map, ir->psize, &dbuf[0],
2615 BUS_DMA_NOWAIT);
2616 if (db_tr->buf == NULL)
2617 return (ENOMEM);
2618 }
2619 db_tr->dbcnt = 1;
2620 dsiz[0] = ir->psize;
2621 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2622 BUS_DMASYNC_PREREAD);
2623 } else {
2624 db_tr->dbcnt = 0;
2625 if (dummy_dma != NULL) {
2626 dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2627 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2628 }
2629 dsiz[db_tr->dbcnt] = ir->psize;
2630 if (ir->buf != NULL) {
2631 db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2632 dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2633 }
2634 db_tr->dbcnt++;
2635 }
2636 for (i = 0; i < db_tr->dbcnt; i++) {
2637 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2638 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2639 if (ir->flag & FWXFERQ_STREAM) {
2640 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2641 }
2642 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2643 }
2644 ldesc = db_tr->dbcnt - 1;
2645 if (ir->flag & FWXFERQ_STREAM) {
2646 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2647 }
2648 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2649 return 0;
2650 }
2651
2652
2653 static int
2654 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2655 {
2656 struct fw_pkt *fp0;
2657 uint32_t ld0;
2658 int hlen;
2659 #if BYTE_ORDER == BIG_ENDIAN
2660 int slen;
2661 int i;
2662 #endif
2663
2664 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2665 #if 0
2666 printf("ld0: x%08x\n", ld0);
2667 #endif
2668 fp0 = (struct fw_pkt *)&ld0;
2669 /* determine length to swap */
2670 switch (fp0->mode.common.tcode) {
2671 case FWTCODE_RREQQ:
2672 case FWTCODE_WRES:
2673 case FWTCODE_WREQQ:
2674 case FWTCODE_RRESQ:
2675 case FWOHCITCODE_PHY:
2676 #if BYTE_ORDER == BIG_ENDIAN
2677 slen = 12;
2678 #endif
2679 break;
2680 case FWTCODE_RREQB:
2681 case FWTCODE_WREQB:
2682 case FWTCODE_LREQ:
2683 case FWTCODE_RRESB:
2684 case FWTCODE_LRES:
2685 #if BYTE_ORDER == BIG_ENDIAN
2686 slen = 16;
2687 #endif
2688 break;
2689 default:
2690 printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2691 return (0);
2692 }
2693 hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2694 if (hlen > len) {
2695 if (firewire_debug)
2696 printf("splitted header\n");
2697 return (-hlen);
2698 }
2699 #if BYTE_ORDER == BIG_ENDIAN
2700 for (i = 0; i < slen/4; i++)
2701 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2702 #endif
2703 return (hlen);
2704 }
2705
2706 static int
2707 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2708 {
2709 struct tcode_info *info;
2710 int r;
2711
2712 info = &tinfo[fp->mode.common.tcode];
2713 r = info->hdr_len + sizeof(uint32_t);
2714 if ((info->flag & FWTI_BLOCK_ASY) != 0)
2715 r += roundup2((uint32_t)fp->mode.wreqb.len, sizeof(uint32_t));
2716
2717 if (r == sizeof(uint32_t)) {
2718 /* XXX */
2719 device_printf(sc->fc.dev, "Unknown tcode %d\n",
2720 fp->mode.common.tcode);
2721 return (-1);
2722 }
2723
2724 if (r > dbch->xferq.psize) {
2725 device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2726 return (-1);
2727 /* panic ? */
2728 }
2729
2730 return r;
2731 }
2732
2733 static void
2734 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2735 struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2736 {
2737 struct fwohcidb *db = &db_tr->db[0];
2738
2739 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2740 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2741 FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2742 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2743 dbch->bottom = db_tr;
2744
2745 if (wake)
2746 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2747 }
2748
2749 static void
2750 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2751 {
2752 struct fwohcidb_tr *db_tr;
2753 struct iovec vec[2];
2754 struct fw_pkt pktbuf;
2755 int nvec;
2756 struct fw_pkt *fp;
2757 uint8_t *ld;
2758 uint32_t stat, off, status, event;
2759 u_int spd;
2760 #ifdef COUNT_PACKETS
2761 int pcnt;
2762 #endif
2763 int len, plen, hlen, offset;
2764 int s;
2765 caddr_t buf;
2766 int resCount;
2767
2768 if (&sc->arrq == dbch) {
2769 off = OHCI_ARQOFF;
2770 } else if (&sc->arrs == dbch) {
2771 off = OHCI_ARSOFF;
2772 } else {
2773 return;
2774 }
2775
2776 s = splfw();
2777 db_tr = dbch->top;
2778 #ifdef COUNT_PACKETS
2779 pcnt = 0;
2780 #endif
2781 /* XXX we cannot handle a packet which lies in more than two buf */
2782 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2783 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2784 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2785 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2786 while (status & OHCI_CNTL_DMA_ACTIVE) {
2787 #if 0
2788
2789 if (off == OHCI_ARQOFF)
2790 printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2791 db_tr->bus_addr, status, resCount);
2792 #endif
2793 len = dbch->xferq.psize - resCount;
2794 ld = (uint8_t *)db_tr->buf;
2795 if (dbch->pdb_tr == NULL) {
2796 len -= dbch->buf_offset;
2797 ld += dbch->buf_offset;
2798 }
2799 if (len > 0)
2800 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2801 BUS_DMASYNC_POSTREAD);
2802 while (len > 0) {
2803 if (count >= 0 && count-- == 0)
2804 goto out;
2805 if (dbch->pdb_tr != NULL) {
2806 /* we have a fragment in previous buffer */
2807 int rlen;
2808
2809 offset = dbch->buf_offset;
2810 if (offset < 0)
2811 offset = - offset;
2812 buf = dbch->pdb_tr->buf + offset;
2813 rlen = dbch->xferq.psize - offset;
2814 if (firewire_debug)
2815 printf("rlen=%d, offset=%d\n",
2816 rlen, dbch->buf_offset);
2817 if (dbch->buf_offset < 0) {
2818 /* splitted in header, pull up */
2819 char *p;
2820
2821 p = (char *)&pktbuf;
2822 bcopy(buf, p, rlen);
2823 p += rlen;
2824 /* this must be too long but harmless */
2825 rlen = sizeof(pktbuf) - rlen;
2826 if (rlen < 0)
2827 printf("why rlen < 0\n");
2828 bcopy(db_tr->buf, p, rlen);
2829 ld += rlen;
2830 len -= rlen;
2831 hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2832 if (hlen <= 0) {
2833 printf("hlen should be positive.");
2834 goto err;
2835 }
2836 offset = sizeof(pktbuf);
2837 vec[0].iov_base = (char *)&pktbuf;
2838 vec[0].iov_len = offset;
2839 } else {
2840 /* splitted in payload */
2841 offset = rlen;
2842 vec[0].iov_base = buf;
2843 vec[0].iov_len = rlen;
2844 }
2845 fp=(struct fw_pkt *)vec[0].iov_base;
2846 nvec = 1;
2847 } else {
2848 /* no fragment in previous buffer */
2849 fp=(struct fw_pkt *)ld;
2850 hlen = fwohci_arcv_swap(fp, len);
2851 if (hlen == 0)
2852 goto err;
2853 if (hlen < 0) {
2854 dbch->pdb_tr = db_tr;
2855 dbch->buf_offset = - dbch->buf_offset;
2856 /* sanity check */
2857 if (resCount != 0) {
2858 printf("resCount=%d hlen=%d\n",
2859 resCount, hlen);
2860 goto err;
2861 }
2862 goto out;
2863 }
2864 offset = 0;
2865 nvec = 0;
2866 }
2867 plen = fwohci_get_plen(sc, dbch, fp) - offset;
2868 if (plen < 0) {
2869 /* minimum header size + trailer
2870 = sizeof(fw_pkt) so this shouldn't happens */
2871 printf("plen(%d) is negative! offset=%d\n",
2872 plen, offset);
2873 goto err;
2874 }
2875 if (plen > 0) {
2876 len -= plen;
2877 if (len < 0) {
2878 dbch->pdb_tr = db_tr;
2879 if (firewire_debug)
2880 printf("splitted payload\n");
2881 /* sanity check */
2882 if (resCount != 0) {
2883 printf("resCount=%d plen=%d"
2884 " len=%d\n",
2885 resCount, plen, len);
2886 goto err;
2887 }
2888 goto out;
2889 }
2890 vec[nvec].iov_base = ld;
2891 vec[nvec].iov_len = plen;
2892 nvec++;
2893 ld += plen;
2894 }
2895 dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2896 if (nvec == 0)
2897 printf("nvec == 0\n");
2898
2899 /* DMA result-code will be written at the tail of packet */
2900 stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2901 #if 0
2902 printf("plen: %d, stat %x\n",
2903 plen ,stat);
2904 #endif
2905 spd = (stat >> 21) & 0x3;
2906 event = (stat >> 16) & 0x1f;
2907 switch (event) {
2908 case FWOHCIEV_ACKPEND:
2909 #if 0
2910 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2911 #endif
2912 /* fall through */
2913 case FWOHCIEV_ACKCOMPL:
2914 {
2915 struct fw_rcv_buf rb;
2916
2917 if ((vec[nvec-1].iov_len -=
2918 sizeof(struct fwohci_trailer)) == 0)
2919 nvec--;
2920 rb.fc = &sc->fc;
2921 rb.vec = vec;
2922 rb.nvec = nvec;
2923 rb.spd = spd;
2924 fw_rcv(&rb);
2925 break;
2926 }
2927 case FWOHCIEV_BUSRST:
2928 if ((sc->fc.status != FWBUSRESET) &&
2929 (sc->fc.status != FWBUSINIT))
2930 printf("got BUSRST packet!?\n");
2931 break;
2932 default:
2933 device_printf(sc->fc.dev,
2934 "Async DMA Receive error err=%02x %s"
2935 " plen=%d offset=%d len=%d status=0x%08x"
2936 " tcode=0x%x, stat=0x%08x\n",
2937 event, fwohcicode[event], plen,
2938 dbch->buf_offset, len,
2939 OREAD(sc, OHCI_DMACTL(off)),
2940 fp->mode.common.tcode, stat);
2941 #if 1 /* XXX */
2942 goto err;
2943 #endif
2944 break;
2945 }
2946 #ifdef COUNT_PACKETS
2947 pcnt++;
2948 #endif
2949 if (dbch->pdb_tr != NULL) {
2950 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2951 off, 1);
2952 dbch->pdb_tr = NULL;
2953 }
2954
2955 }
2956 out:
2957 if (resCount == 0) {
2958 /* done on this buffer */
2959 if (dbch->pdb_tr == NULL) {
2960 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2961 dbch->buf_offset = 0;
2962 } else
2963 if (dbch->pdb_tr != db_tr)
2964 printf("pdb_tr != db_tr\n");
2965 db_tr = STAILQ_NEXT(db_tr, link);
2966 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2967 >> OHCI_STATUS_SHIFT;
2968 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2969 & OHCI_COUNT_MASK;
2970 /* XXX check buffer overrun */
2971 dbch->top = db_tr;
2972 } else {
2973 dbch->buf_offset = dbch->xferq.psize - resCount;
2974 break;
2975 }
2976 /* XXX make sure DMA is not dead */
2977 }
2978 #ifdef COUNT_PACKETS
2979 if (pcnt < 1)
2980 printf("fwohci_arcv: no packets\n");
2981 #endif
2982 splx(s);
2983 return;
2984
2985 err:
2986 device_printf(sc->fc.dev, "AR DMA status=%x, ",
2987 OREAD(sc, OHCI_DMACTL(off)));
2988 dbch->pdb_tr = NULL;
2989 /* skip until resCount != 0 */
2990 printf(" skip buffer");
2991 while (resCount == 0) {
2992 printf(" #");
2993 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2994 db_tr = STAILQ_NEXT(db_tr, link);
2995 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2996 & OHCI_COUNT_MASK;
2997 }
2998 printf(" done\n");
2999 dbch->top = db_tr;
3000 dbch->buf_offset = dbch->xferq.psize - resCount;
3001 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
3002 splx(s);
3003 }
3004