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