Line data Source code
1 : /* $OpenBSD: sili.c,v 1.58 2015/12/19 20:05:32 tb Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
5 : * Copyright (c) 2010 Conformal Systems LLC <info@conformal.com>
6 : * Copyright (c) 2010 Jonathan Matthew <jonathan@d14n.org>
7 : *
8 : * Permission to use, copy, modify, and distribute this software for any
9 : * purpose with or without fee is hereby granted, provided that the above
10 : * copyright notice and this permission notice appear in all copies.
11 : *
12 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 : */
20 :
21 : #include <sys/param.h>
22 : #include <sys/systm.h>
23 : #include <sys/device.h>
24 : #include <sys/timeout.h>
25 : #include <sys/malloc.h>
26 : #include <sys/kernel.h>
27 : #include <sys/mutex.h>
28 :
29 : #include <machine/bus.h>
30 :
31 : #include <dev/ata/atascsi.h>
32 : #include <dev/ata/pmreg.h>
33 :
34 : #include <dev/ic/silireg.h>
35 : #include <dev/ic/silivar.h>
36 :
37 : /* use SILI_DEBUG for dmesg spam */
38 : #define NO_SILI_DEBUG
39 :
40 : #ifdef SILI_DEBUG
41 : #define SILI_D_VERBOSE (1<<0)
42 : #define SILI_D_INTR (1<<1)
43 :
44 : int silidebug = SILI_D_VERBOSE;
45 :
46 : #define DPRINTF(m, a...) do { if ((m) & silidebug) printf(a); } while (0)
47 : #else
48 : #define DPRINTF(m, a...)
49 : #endif
50 :
51 : /* these can be used to simulate read and write errors on specific PMP ports */
52 : #undef SILI_ERROR_TEST
53 : int sili_error_pmp_ports = 0; /* bitmask containing ports to fail*/
54 : int sili_error_test_inv_p = 500; /* 1/P(error) */
55 : int sili_error_restart_type = SILI_PREG_PCS_PORTINIT; /* or _DEVRESET */
56 :
57 : struct cfdriver sili_cd = {
58 : NULL, "sili", DV_DULL
59 : };
60 :
61 : /* wrapper around dma memory */
62 : struct sili_dmamem {
63 : bus_dmamap_t sdm_map;
64 : bus_dma_segment_t sdm_seg;
65 : size_t sdm_size;
66 : caddr_t sdm_kva;
67 : };
68 : #define SILI_DMA_MAP(_sdm) ((_sdm)->sdm_map)
69 : #define SILI_DMA_DVA(_sdm) ((_sdm)->sdm_map->dm_segs[0].ds_addr)
70 : #define SILI_DMA_KVA(_sdm) ((_sdm)->sdm_kva)
71 :
72 : struct sili_dmamem *sili_dmamem_alloc(struct sili_softc *, bus_size_t,
73 : bus_size_t);
74 : void sili_dmamem_free(struct sili_softc *,
75 : struct sili_dmamem *);
76 :
77 : /* per port goo */
78 : struct sili_ccb;
79 :
80 : /* size of scratch space for use in error recovery. */
81 : #define SILI_SCRATCH_LEN 512 /* must be at least 1 sector */
82 :
83 : struct sili_port {
84 : struct sili_softc *sp_sc;
85 : bus_space_handle_t sp_ioh;
86 :
87 : struct sili_ccb *sp_ccbs;
88 : struct sili_dmamem *sp_cmds;
89 : struct sili_dmamem *sp_scratch;
90 :
91 : TAILQ_HEAD(, sili_ccb) sp_free_ccbs;
92 : struct mutex sp_free_ccb_mtx;
93 :
94 : volatile u_int32_t sp_active;
95 : TAILQ_HEAD(, sili_ccb) sp_active_ccbs;
96 : TAILQ_HEAD(, sili_ccb) sp_deferred_ccbs;
97 :
98 : int sp_port;
99 : int sp_pmp_ports;
100 : int sp_active_pmp_ports;
101 : int sp_pmp_error_recovery; /* port bitmask */
102 : volatile u_int32_t sp_err_active; /* cmd bitmask */
103 : volatile u_int32_t sp_err_cmds; /* cmd bitmask */
104 :
105 : #ifdef SILI_DEBUG
106 : char sp_name[16];
107 : #define PORTNAME(_sp) ((_sp)->sp_name)
108 : #else
109 : #define PORTNAME(_sp) DEVNAME((_sp)->sp_sc)
110 : #endif
111 : };
112 :
113 : int sili_ports_alloc(struct sili_softc *);
114 : void sili_ports_free(struct sili_softc *);
115 :
116 : /* ccb shizz */
117 :
118 : /*
119 : * the dma memory for each command will be made up of a prb followed by
120 : * 7 sgts, this is a neat 512 bytes.
121 : */
122 : #define SILI_CMD_LEN 512
123 :
124 : /*
125 : * you can fit 22 sge's into 7 sgts and a prb:
126 : * there's 1 sgl in an atapi prb (two in the ata one, but we cant over
127 : * advertise), but that's needed for the chain element. you get three sges
128 : * per sgt cos you lose the 4th sge for the chaining, but you keep it in
129 : * the last sgt. so 3 x 6 + 4 is 22.
130 : */
131 : #define SILI_DMA_SEGS 22
132 :
133 : struct sili_ccb {
134 : struct ata_xfer ccb_xa;
135 :
136 : void *ccb_cmd;
137 : u_int64_t ccb_cmd_dva;
138 : bus_dmamap_t ccb_dmamap;
139 :
140 : struct sili_port *ccb_port;
141 :
142 : TAILQ_ENTRY(sili_ccb) ccb_entry;
143 : };
144 :
145 : int sili_ccb_alloc(struct sili_port *);
146 : void sili_ccb_free(struct sili_port *);
147 : struct sili_ccb *sili_get_ccb(struct sili_port *);
148 : void sili_put_ccb(struct sili_ccb *);
149 :
150 : /* bus space ops */
151 : u_int32_t sili_read(struct sili_softc *, bus_size_t);
152 : void sili_write(struct sili_softc *, bus_size_t, u_int32_t);
153 : u_int32_t sili_pread(struct sili_port *, bus_size_t);
154 : void sili_pwrite(struct sili_port *, bus_size_t, u_int32_t);
155 : int sili_pwait_eq(struct sili_port *, bus_size_t,
156 : u_int32_t, u_int32_t, int);
157 : int sili_pwait_ne(struct sili_port *, bus_size_t,
158 : u_int32_t, u_int32_t, int);
159 :
160 : /* command handling */
161 : void sili_post_direct(struct sili_port *, u_int,
162 : void *, size_t buflen);
163 : void sili_post_indirect(struct sili_port *,
164 : struct sili_ccb *);
165 : void sili_pread_fis(struct sili_port *, u_int,
166 : struct ata_fis_d2h *);
167 : u_int32_t sili_signature(struct sili_port *, u_int);
168 : u_int32_t sili_port_softreset(struct sili_port *sp);
169 : int sili_load(struct sili_ccb *, struct sili_sge *, int);
170 : void sili_unload(struct sili_ccb *);
171 : int sili_poll(struct sili_ccb *, int, void (*)(void *));
172 : void sili_start(struct sili_port *, struct sili_ccb *);
173 : int sili_read_ncq_error(struct sili_port *, int *, int);
174 : int sili_pmp_port_start_error_recovery(struct sili_port *,
175 : int);
176 : void sili_pmp_port_do_error_recovery(struct sili_port *,
177 : int, u_int32_t *);
178 : void sili_port_clear_commands(struct sili_port *sp);
179 :
180 : /* pmp operations */
181 : int sili_pmp_read(struct sili_port *, int, int,
182 : u_int32_t *);
183 : int sili_pmp_write(struct sili_port *, int, int, u_int32_t);
184 : int sili_pmp_phy_status(struct sili_port *, int,
185 : u_int32_t *);
186 : int sili_pmp_identify(struct sili_port *, int *);
187 :
188 : /* port interrupt handler */
189 : u_int32_t sili_port_intr(struct sili_port *, int);
190 :
191 : /* atascsi interface */
192 : int sili_ata_probe(void *, int, int);
193 : void sili_ata_free(void *, int, int);
194 : struct ata_xfer *sili_ata_get_xfer(void *, int);
195 : void sili_ata_put_xfer(struct ata_xfer *);
196 : void sili_ata_cmd(struct ata_xfer *);
197 : int sili_pmp_portreset(struct sili_softc *, int, int);
198 : int sili_pmp_softreset(struct sili_softc *, int, int);
199 :
200 : #ifdef SILI_ERROR_TEST
201 : void sili_simulate_error(struct sili_ccb *ccb,
202 : int *need_restart, int *err_port);
203 : #endif
204 :
205 : struct atascsi_methods sili_atascsi_methods = {
206 : sili_ata_probe,
207 : sili_ata_free,
208 : sili_ata_get_xfer,
209 : sili_ata_put_xfer,
210 : sili_ata_cmd
211 : };
212 :
213 : /* completion paths */
214 : void sili_ata_cmd_done(struct sili_ccb *, int);
215 : void sili_ata_cmd_timeout(void *);
216 : void sili_dummy_done(struct ata_xfer *);
217 :
218 : void sili_pmp_op_timeout(void *);
219 :
220 : int
221 0 : sili_attach(struct sili_softc *sc)
222 : {
223 0 : struct atascsi_attach_args aaa;
224 :
225 0 : printf("\n");
226 :
227 0 : if (sili_ports_alloc(sc) != 0) {
228 : /* error already printed by sili_port_alloc */
229 0 : return (1);
230 : }
231 :
232 : /* bounce the controller */
233 0 : sili_write(sc, SILI_REG_GC, SILI_REG_GC_GR);
234 0 : sili_write(sc, SILI_REG_GC, 0x0);
235 :
236 0 : bzero(&aaa, sizeof(aaa));
237 0 : aaa.aaa_cookie = sc;
238 0 : aaa.aaa_methods = &sili_atascsi_methods;
239 0 : aaa.aaa_minphys = NULL;
240 0 : aaa.aaa_nports = sc->sc_nports;
241 0 : aaa.aaa_ncmds = SILI_MAX_CMDS;
242 0 : aaa.aaa_capability = ASAA_CAP_NCQ | ASAA_CAP_PMP_NCQ;
243 :
244 0 : sc->sc_atascsi = atascsi_attach(&sc->sc_dev, &aaa);
245 :
246 0 : return (0);
247 0 : }
248 :
249 : int
250 0 : sili_detach(struct sili_softc *sc, int flags)
251 : {
252 : int rv;
253 :
254 0 : if (sc->sc_atascsi != NULL) {
255 0 : rv = atascsi_detach(sc->sc_atascsi, flags);
256 0 : if (rv != 0)
257 0 : return (rv);
258 : }
259 :
260 0 : if (sc->sc_ports != NULL)
261 0 : sili_ports_free(sc);
262 :
263 0 : return (0);
264 0 : }
265 :
266 : void
267 0 : sili_resume(struct sili_softc *sc)
268 : {
269 : int i, j;
270 :
271 : /* bounce the controller */
272 0 : sili_write(sc, SILI_REG_GC, SILI_REG_GC_GR);
273 0 : sili_write(sc, SILI_REG_GC, 0x0);
274 :
275 0 : for (i = 0; i < sc->sc_nports; i++) {
276 0 : if (sili_ata_probe(sc, i, 0) == ATA_PORT_T_PM) {
277 0 : struct sili_port *sp = &sc->sc_ports[i];
278 0 : for (j = 0; j < sp->sp_pmp_ports; j++) {
279 0 : sili_ata_probe(sc, i, j);
280 : }
281 0 : }
282 : }
283 0 : }
284 :
285 : int
286 0 : sili_pmp_port_start_error_recovery(struct sili_port *sp, int err_port)
287 : {
288 : struct sili_ccb *ccb;
289 :
290 0 : sp->sp_pmp_error_recovery |= (1 << err_port);
291 :
292 : /* create a bitmask of active commands on non-error ports */
293 0 : sp->sp_err_active = 0;
294 0 : TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
295 0 : int bit = (1 << ccb->ccb_xa.pmp_port);
296 0 : if ((sp->sp_pmp_error_recovery & bit) == 0) {
297 : DPRINTF(SILI_D_VERBOSE, "%s: slot %d active on port "
298 : "%d\n", PORTNAME(sp), ccb->ccb_xa.tag,
299 : ccb->ccb_xa.pmp_port);
300 0 : sp->sp_err_active |= (1 << ccb->ccb_xa.tag);
301 0 : }
302 : }
303 :
304 0 : if (sp->sp_err_active == 0) {
305 : DPRINTF(SILI_D_VERBOSE, "%s: no other PMP ports active\n",
306 : PORTNAME(sp));
307 0 : sp->sp_pmp_error_recovery = 0;
308 0 : return (0);
309 : }
310 :
311 : /* set port resume */
312 0 : sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_RESUME);
313 :
314 : DPRINTF(SILI_D_VERBOSE, "%s: beginning error recovery (port %d); "
315 : "error port mask %x, active slot mask %x\n", PORTNAME(sp), err_port,
316 : sp->sp_pmp_error_recovery, sp->sp_err_active);
317 0 : return (1);
318 0 : }
319 :
320 : void
321 0 : sili_port_clear_commands(struct sili_port *sp)
322 : {
323 : int port;
324 :
325 : DPRINTF(SILI_D_VERBOSE, "%s: clearing active commands\n",
326 : PORTNAME(sp));
327 :
328 : /* clear port resume */
329 0 : sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_RESUME);
330 0 : delay(10000);
331 :
332 : /* clear port status and port active for all ports */
333 0 : for (port = 0; port < 16; port++) {
334 0 : sili_pwrite(sp, SILI_PREG_PMP_STATUS(port), 0);
335 0 : sili_pwrite(sp, SILI_PREG_PMP_QACTIVE(port), 0);
336 : }
337 0 : }
338 :
339 : void
340 0 : sili_pmp_port_do_error_recovery(struct sili_port *sp, int slot,
341 : u_int32_t *need_restart)
342 : {
343 0 : if (sp->sp_pmp_error_recovery == 0) {
344 : return;
345 : }
346 :
347 : /* have all outstanding commands finished yet? */
348 0 : if (sp->sp_err_active != 0) {
349 : DPRINTF(SILI_D_VERBOSE, "%s: PMP error recovery still waiting "
350 : "for %x\n", PORTNAME(sp), sp->sp_err_active);
351 0 : *need_restart = 0;
352 0 : return;
353 : }
354 :
355 0 : sili_port_clear_commands(sp);
356 :
357 : /* get the main error recovery code to reset the port and
358 : * resubmit commands. it will also reset the error recovery flags.
359 : */
360 0 : *need_restart = SILI_PREG_PCS_PORTINIT;
361 : DPRINTF(SILI_D_VERBOSE, "%s: PMP error recovery complete\n",
362 : PORTNAME(sp));
363 0 : }
364 :
365 : #ifdef SILI_ERROR_TEST
366 : void
367 : sili_simulate_error(struct sili_ccb *ccb, int *need_restart, int *err_port)
368 : {
369 : struct sili_port *sp = ccb->ccb_port;
370 :
371 : if (*need_restart == 0 &&
372 : ((1 << ccb->ccb_xa.pmp_port) & sili_error_pmp_ports)) {
373 : switch (ccb->ccb_xa.fis->command) {
374 : case ATA_C_WRITE_FPDMA:
375 : case ATA_C_READ_FPDMA:
376 : case ATA_C_WRITEDMA_EXT:
377 : case ATA_C_READDMA_EXT:
378 : case ATA_C_WRITEDMA:
379 : case ATA_C_READDMA:
380 : if (arc4random_uniform(sili_error_test_inv_p) == 0) {
381 : printf("%s: faking error on slot %d\n",
382 : PORTNAME(sp), ccb->ccb_xa.tag);
383 : ccb->ccb_xa.state = ATA_S_ERROR;
384 : *need_restart = sili_error_restart_type;
385 : *err_port = ccb->ccb_xa.pmp_port;
386 :
387 : ccb->ccb_port->sp_err_cmds |=
388 : (1 << ccb->ccb_xa.tag);
389 : }
390 : break;
391 :
392 : default:
393 : /* leave other commands alone, we only want to mess
394 : * with normal read/write ops
395 : */
396 : break;
397 : }
398 : }
399 : }
400 : #endif
401 :
402 : u_int32_t
403 0 : sili_port_intr(struct sili_port *sp, int timeout_slot)
404 : {
405 : u_int32_t is, pss_saved, pss_masked;
406 0 : u_int32_t processed = 0, need_restart = 0;
407 : u_int32_t err_port = 0;
408 : int slot;
409 : struct sili_ccb *ccb;
410 :
411 0 : is = sili_pread(sp, SILI_PREG_IS);
412 0 : pss_saved = sili_pread(sp, SILI_PREG_PSS); /* reading acks CMDCOMP */
413 :
414 : #ifdef SILI_DEBUG
415 : if ((pss_saved & SILI_PREG_PSS_ALL_SLOTS) != sp->sp_active ||
416 : ((is >> 16) & ~SILI_PREG_IS_CMDCOMP)) {
417 : DPRINTF(SILI_D_INTR, "%s: IS: 0x%08x (0x%b), PSS: %08x, "
418 : "active: %08x\n", PORTNAME(sp), is, is >> 16, SILI_PFMT_IS,
419 : pss_saved, sp->sp_active);
420 : }
421 : #endif
422 :
423 : /* Only interested in slot status bits. */
424 0 : pss_saved &= SILI_PREG_PSS_ALL_SLOTS;
425 :
426 0 : if (is & SILI_PREG_IS_CMDERR) {
427 0 : int err_slot, err_code;
428 : u_int32_t sactive = 0;
429 :
430 0 : sili_pwrite(sp, SILI_PREG_IS, SILI_PREG_IS_CMDERR);
431 0 : err_slot = SILI_PREG_PCS_ACTIVE(sili_pread(sp, SILI_PREG_PCS));
432 0 : err_code = sili_pread(sp, SILI_PREG_CE);
433 0 : ccb = &sp->sp_ccbs[err_slot];
434 :
435 0 : switch (err_code) {
436 : case SILI_PREG_CE_DEVICEERROR:
437 : case SILI_PREG_CE_DATAFISERROR:
438 : /* Extract error from command slot in LRAM. */
439 0 : sili_pread_fis(sp, err_slot, &ccb->ccb_xa.rfis);
440 0 : err_port = ccb->ccb_xa.pmp_port;
441 0 : break;
442 :
443 : case SILI_PREG_CE_SDBERROR:
444 :
445 0 : if (sp->sp_pmp_ports > 0) {
446 : /* get the PMP port number for the error */
447 0 : err_port = (sili_pread(sp, SILI_PREG_CONTEXT)
448 0 : >> SILI_PREG_CONTEXT_PMPORT_SHIFT) &
449 : SILI_PREG_CONTEXT_PMPORT_MASK;
450 : DPRINTF(SILI_D_VERBOSE, "%s: error port is "
451 : "%d\n", PORTNAME(sp), err_port);
452 :
453 : /* were there any NCQ commands active for
454 : * the port?
455 : */
456 0 : sactive = sili_pread(sp,
457 0 : SILI_PREG_PMP_QACTIVE(err_port));
458 : DPRINTF(SILI_D_VERBOSE, "%s: error SActive "
459 : "%x\n", PORTNAME(sp), sactive);
460 0 : if (sactive == 0)
461 : break;
462 : } else {
463 : /* No NCQ commands active? Treat as a normal
464 : * error.
465 : */
466 0 : sactive = sili_pread(sp, SILI_PREG_SACT);
467 0 : if (sactive == 0)
468 : break;
469 : }
470 :
471 : /* Extract real NCQ error slot & RFIS from
472 : * log page.
473 : */
474 0 : if (!sili_read_ncq_error(sp, &err_slot, err_port)) {
475 : /* got real err_slot */
476 : DPRINTF(SILI_D_VERBOSE, "%s.%d: error slot "
477 : "%d\n", PORTNAME(sp), err_port, err_slot);
478 0 : ccb = &sp->sp_ccbs[err_slot];
479 0 : break;
480 : }
481 : DPRINTF(SILI_D_VERBOSE, "%s.%d: failed to get error "
482 : "slot\n", PORTNAME(sp), err_port);
483 :
484 : /* failed to get error or not NCQ */
485 :
486 : /* FALLTHROUGH */
487 : default:
488 : /* All other error types are fatal. */
489 0 : if (err_code != SILI_PREG_CE_SDBERROR) {
490 0 : err_port = (sili_pread(sp, SILI_PREG_CONTEXT)
491 0 : >> SILI_PREG_CONTEXT_PMPORT_SHIFT) &
492 : SILI_PREG_CONTEXT_PMPORT_MASK;
493 0 : }
494 0 : printf("%s.%d: fatal error (%d), aborting active slots "
495 0 : "(%08x) and resetting device.\n", PORTNAME(sp),
496 : err_port, err_code, pss_saved);
497 0 : while (pss_saved) {
498 0 : slot = ffs(pss_saved) - 1;
499 0 : pss_saved &= ~(1 << slot);
500 :
501 0 : ccb = &sp->sp_ccbs[slot];
502 0 : KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
503 0 : ccb->ccb_xa.state = ATA_S_ERROR;
504 : }
505 0 : need_restart = SILI_PREG_PCS_DEVRESET;
506 0 : goto fatal;
507 : }
508 :
509 : DPRINTF(SILI_D_VERBOSE, "%s.%d: %serror, code %d, slot %d, "
510 : "active %08x\n", PORTNAME(sp), err_port,
511 : sactive ? "NCQ " : "", err_code, err_slot, sp->sp_active);
512 :
513 : /* Clear the failed commmand in saved PSS so cmd_done runs. */
514 0 : pss_saved &= ~(1 << err_slot);
515 : /* Track errored commands until we finish recovery */
516 0 : sp->sp_err_cmds |= (1 << err_slot);
517 :
518 0 : KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
519 0 : ccb->ccb_xa.state = ATA_S_ERROR;
520 :
521 0 : need_restart = SILI_PREG_PCS_PORTINIT;
522 0 : }
523 : fatal:
524 :
525 : /* Process command timeout request only if command is still active. */
526 0 : if (timeout_slot >= 0 && (pss_saved & (1 << timeout_slot))) {
527 : DPRINTF(SILI_D_VERBOSE, "%s: timing out slot %d, active %08x\n",
528 : PORTNAME(sp), timeout_slot, sp->sp_active);
529 :
530 : /* Clear the failed commmand in saved PSS so cmd_done runs. */
531 0 : pss_saved &= ~(1 << timeout_slot);
532 :
533 0 : ccb = &sp->sp_ccbs[timeout_slot];
534 0 : KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
535 0 : ccb->ccb_xa.state = ATA_S_TIMEOUT;
536 :
537 : /* Reinitialise the port and clear all active commands */
538 0 : need_restart = SILI_PREG_PCS_PORTINIT;
539 :
540 0 : err_port = ccb->ccb_xa.pmp_port;
541 0 : sp->sp_err_cmds |= (1 << timeout_slot);
542 :
543 0 : sili_port_clear_commands(sp);
544 0 : }
545 :
546 : /* Command slot is complete if its bit in PSS is 0 but 1 in active. */
547 0 : pss_masked = ~pss_saved & sp->sp_active;
548 0 : while (pss_masked) {
549 0 : slot = ffs(pss_masked) - 1;
550 0 : ccb = &sp->sp_ccbs[slot];
551 0 : pss_masked &= ~(1 << slot);
552 :
553 : /* copy the rfis into the ccb if we were asked for it */
554 0 : if (ccb->ccb_xa.state == ATA_S_ONCHIP &&
555 0 : ccb->ccb_xa.flags & ATA_F_GET_RFIS) {
556 0 : sili_pread_fis(sp, slot, &ccb->ccb_xa.rfis);
557 0 : }
558 :
559 : #ifdef SILI_ERROR_TEST
560 : /* introduce random errors on reads and writes for testing */
561 : sili_simulate_error(ccb, &need_restart, &err_port);
562 : #endif
563 :
564 : DPRINTF(SILI_D_INTR, "%s: slot %d is complete%s%s\n",
565 : PORTNAME(sp), slot, ccb->ccb_xa.state == ATA_S_ERROR ?
566 : " (error)" : (ccb->ccb_xa.state == ATA_S_TIMEOUT ?
567 : " (timeout)" : ""),
568 : ccb->ccb_xa.flags & ATA_F_NCQ ? " (ncq)" : "");
569 :
570 0 : sili_ata_cmd_done(ccb, need_restart);
571 :
572 0 : processed |= 1 << slot;
573 :
574 0 : sili_pmp_port_do_error_recovery(sp, slot, &need_restart);
575 : }
576 :
577 0 : if (need_restart) {
578 :
579 0 : if (sp->sp_pmp_error_recovery) {
580 0 : if (sp->sp_err_active != 0) {
581 : DPRINTF(SILI_D_VERBOSE, "%s: still waiting for "
582 : "non-error commands to finish; port mask "
583 : "%x, slot mask %x\n", PORTNAME(sp),
584 : sp->sp_pmp_error_recovery,
585 : sp->sp_err_active);
586 0 : return (processed);
587 : }
588 0 : } else if (timeout_slot < 0 && sp->sp_pmp_ports > 0) {
589 : /* wait until all other commands have finished before
590 : * attempting to reinit the port.
591 : */
592 : DPRINTF(SILI_D_VERBOSE, "%s: error on port with PMP "
593 : "attached, error port %d\n", PORTNAME(sp),
594 : err_port);
595 0 : if (sili_pmp_port_start_error_recovery(sp, err_port)) {
596 : DPRINTF(SILI_D_VERBOSE, "%s: need to wait for "
597 : "other commands to finish\n", PORTNAME(sp));
598 0 : return (processed);
599 : }
600 : } else if (sp->sp_pmp_ports > 0) {
601 : DPRINTF(SILI_D_VERBOSE, "%s: timeout on PMP port\n",
602 : PORTNAME(sp));
603 : } else {
604 : DPRINTF(SILI_D_VERBOSE, "%s: error on non-PMP port\n",
605 : PORTNAME(sp));
606 : }
607 :
608 : /* Re-enable transfers on port. */
609 0 : sili_pwrite(sp, SILI_PREG_PCS, need_restart);
610 0 : if (!sili_pwait_eq(sp, SILI_PREG_PCS, need_restart, 0, 5000)) {
611 0 : printf("%s: port reset bit didn't clear after error\n",
612 0 : PORTNAME(sp));
613 0 : }
614 0 : if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
615 : SILI_PREG_PCS_PORTRDY, 1000)) {
616 0 : printf("%s: couldn't restart port after error\n",
617 0 : PORTNAME(sp));
618 0 : }
619 0 : sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_RESUME);
620 :
621 : /* check that our active CCB list matches the restart mask */
622 0 : pss_masked = pss_saved & ~(sp->sp_err_cmds);
623 : DPRINTF(SILI_D_VERBOSE, "%s: restart mask %x\n",
624 : PORTNAME(sp), pss_masked);
625 0 : TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
626 0 : if (!(pss_masked & (1 << ccb->ccb_xa.tag))) {
627 0 : panic("sili_intr: slot %d not active in "
628 : "pss_masked: %08x, state %02x",
629 : ccb->ccb_xa.tag, pss_masked,
630 0 : ccb->ccb_xa.state);
631 : }
632 0 : pss_masked &= ~(1 << ccb->ccb_xa.tag);
633 : }
634 0 : if (pss_masked != 0) {
635 0 : printf("%s: mask excluding active slots: %x\n",
636 0 : PORTNAME(sp), pss_masked);
637 0 : }
638 0 : KASSERT(pss_masked == 0);
639 :
640 : /* if we had a timeout on a PMP port, do a portreset.
641 : * exclude the control port here as there isn't a real
642 : * device there to reset.
643 : */
644 0 : if (timeout_slot >= 0 && sp->sp_pmp_ports > 0 &&
645 0 : err_port != 15) {
646 :
647 : DPRINTF(SILI_D_VERBOSE,
648 : "%s.%d: doing portreset after timeout\n",
649 : PORTNAME(sp), err_port);
650 0 : sili_pmp_portreset(sp->sp_sc, sp->sp_port, err_port);
651 :
652 : /* wait a bit to let the port settle down */
653 0 : delay(2000000);
654 0 : }
655 :
656 : /* if we sent a device reset to a PMP, we need to reset the
657 : * devices behind it too.
658 : */
659 0 : if (need_restart == SILI_PREG_PCS_DEVRESET &&
660 0 : sp->sp_pmp_ports > 0) {
661 : int port_type;
662 : int i;
663 :
664 0 : port_type = sili_port_softreset(sp);
665 0 : if (port_type != ATA_PORT_T_PM) {
666 : /* device disappeared or changed type? */
667 0 : printf("%s: expected to find a port multiplier,"
668 0 : " got %d\n", PORTNAME(sp), port_type);
669 0 : }
670 :
671 : /* and now portreset all active ports */
672 0 : for (i = 0; i < sp->sp_pmp_ports; i++) {
673 0 : struct sili_softc *sc = sp->sp_sc;
674 :
675 0 : if ((sp->sp_active_pmp_ports & (1 << i)) == 0)
676 0 : continue;
677 :
678 0 : if (sili_pmp_portreset(sc, sp->sp_port, i)) {
679 0 : printf("%s.%d: failed to portreset "
680 0 : "after error\n", PORTNAME(sp), i);
681 0 : }
682 0 : }
683 0 : }
684 :
685 : /* Restart CCBs in the order they were originally queued. */
686 0 : TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
687 : DPRINTF(SILI_D_VERBOSE, "%s: restarting slot %d "
688 : "after error, state %02x\n", PORTNAME(sp),
689 : ccb->ccb_xa.tag, ccb->ccb_xa.state);
690 0 : KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
691 0 : sili_post_indirect(sp, ccb);
692 : }
693 0 : sp->sp_err_cmds = 0;
694 0 : sp->sp_pmp_error_recovery = 0;
695 :
696 : /*
697 : * Finally, run atascsi completion for any finished CCBs. If
698 : * we had run these during cmd_done above, any ccbs that their
699 : * completion generated would have been activated out of order.
700 : */
701 0 : while ((ccb = TAILQ_FIRST(&sp->sp_deferred_ccbs)) != NULL) {
702 0 : TAILQ_REMOVE(&sp->sp_deferred_ccbs, ccb, ccb_entry);
703 :
704 : DPRINTF(SILI_D_VERBOSE, "%s: running deferred "
705 : "completion for slot %d, state %02x\n",
706 : PORTNAME(sp), ccb->ccb_xa.tag, ccb->ccb_xa.state);
707 0 : KASSERT(ccb->ccb_xa.state == ATA_S_COMPLETE ||
708 : ccb->ccb_xa.state == ATA_S_ERROR ||
709 : ccb->ccb_xa.state == ATA_S_TIMEOUT);
710 0 : ata_complete(&ccb->ccb_xa);
711 : }
712 : }
713 :
714 0 : return (processed);
715 0 : }
716 :
717 : int
718 0 : sili_intr(void *arg)
719 : {
720 0 : struct sili_softc *sc = arg;
721 : u_int32_t is;
722 : int port;
723 :
724 : /* If the card has gone away, this will return 0xffffffff. */
725 0 : is = sili_read(sc, SILI_REG_GIS);
726 0 : if (is == 0 || is == 0xffffffff)
727 0 : return (0);
728 0 : sili_write(sc, SILI_REG_GIS, is);
729 : DPRINTF(SILI_D_INTR, "sili_intr, GIS: %08x\n", is);
730 :
731 0 : while (is & SILI_REG_GIS_PIS_MASK) {
732 0 : port = ffs(is) - 1;
733 0 : sili_port_intr(&sc->sc_ports[port], -1);
734 0 : is &= ~(1 << port);
735 : }
736 :
737 0 : return (1);
738 0 : }
739 :
740 : int
741 0 : sili_ports_alloc(struct sili_softc *sc)
742 : {
743 : struct sili_port *sp;
744 : int i;
745 :
746 0 : sc->sc_ports = mallocarray(sc->sc_nports, sizeof(struct sili_port),
747 : M_DEVBUF, M_WAITOK | M_ZERO);
748 :
749 0 : for (i = 0; i < sc->sc_nports; i++) {
750 0 : sp = &sc->sc_ports[i];
751 :
752 0 : sp->sp_sc = sc;
753 0 : sp->sp_port = i;
754 : #ifdef SILI_DEBUG
755 : snprintf(sp->sp_name, sizeof(sp->sp_name), "%s.%d",
756 : DEVNAME(sc), i);
757 : #endif
758 0 : if (bus_space_subregion(sc->sc_iot_port, sc->sc_ioh_port,
759 0 : SILI_PORT_OFFSET(i), SILI_PORT_SIZE, &sp->sp_ioh) != 0) {
760 0 : printf("%s: unable to create register window "
761 0 : "for port %d\n", DEVNAME(sc), i);
762 : goto freeports;
763 : }
764 : }
765 :
766 0 : return (0);
767 :
768 : freeports:
769 : /* bus_space(9) says subregions dont have to be freed */
770 0 : free(sp, M_DEVBUF, sc->sc_nports * sizeof(struct sili_port));
771 0 : sc->sc_ports = NULL;
772 0 : return (1);
773 0 : }
774 :
775 : void
776 0 : sili_ports_free(struct sili_softc *sc)
777 : {
778 : struct sili_port *sp;
779 : int i;
780 :
781 0 : for (i = 0; i < sc->sc_nports; i++) {
782 0 : sp = &sc->sc_ports[i];
783 :
784 0 : if (sp->sp_ccbs != NULL)
785 0 : sili_ccb_free(sp);
786 : }
787 :
788 : /* bus_space(9) says subregions dont have to be freed */
789 0 : free(sc->sc_ports, M_DEVBUF, sc->sc_nports * sizeof(struct sili_port));
790 0 : sc->sc_ports = NULL;
791 0 : }
792 :
793 : int
794 0 : sili_ccb_alloc(struct sili_port *sp)
795 : {
796 0 : struct sili_softc *sc = sp->sp_sc;
797 : struct sili_ccb *ccb;
798 : struct sili_prb *prb;
799 : int i;
800 :
801 0 : TAILQ_INIT(&sp->sp_free_ccbs);
802 0 : mtx_init(&sp->sp_free_ccb_mtx, IPL_BIO);
803 0 : TAILQ_INIT(&sp->sp_active_ccbs);
804 0 : TAILQ_INIT(&sp->sp_deferred_ccbs);
805 :
806 0 : sp->sp_ccbs = mallocarray(SILI_MAX_CMDS, sizeof(struct sili_ccb),
807 : M_DEVBUF, M_WAITOK);
808 0 : sp->sp_cmds = sili_dmamem_alloc(sc, SILI_CMD_LEN * SILI_MAX_CMDS,
809 : SILI_PRB_ALIGN);
810 0 : if (sp->sp_cmds == NULL)
811 : goto free_ccbs;
812 0 : sp->sp_scratch = sili_dmamem_alloc(sc, SILI_SCRATCH_LEN, PAGE_SIZE);
813 0 : if (sp->sp_scratch == NULL)
814 : goto free_cmds;
815 :
816 0 : bzero(sp->sp_ccbs, sizeof(struct sili_ccb) * SILI_MAX_CMDS);
817 :
818 0 : for (i = 0; i < SILI_MAX_CMDS; i++) {
819 0 : ccb = &sp->sp_ccbs[i];
820 0 : ccb->ccb_port = sp;
821 0 : ccb->ccb_cmd = SILI_DMA_KVA(sp->sp_cmds) + i * SILI_CMD_LEN;
822 0 : ccb->ccb_cmd_dva = SILI_DMA_DVA(sp->sp_cmds) + i * SILI_CMD_LEN;
823 0 : if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, SILI_DMA_SEGS,
824 : MAXPHYS, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
825 0 : &ccb->ccb_dmamap) != 0)
826 : goto free_scratch;
827 :
828 0 : prb = ccb->ccb_cmd;
829 0 : ccb->ccb_xa.fis = (struct ata_fis_h2d *)&prb->fis;
830 0 : ccb->ccb_xa.packetcmd = ((struct sili_prb_packet *)prb)->cdb;
831 0 : ccb->ccb_xa.tag = i;
832 0 : ccb->ccb_xa.state = ATA_S_COMPLETE;
833 :
834 0 : sili_put_ccb(ccb);
835 : }
836 :
837 0 : return (0);
838 :
839 : free_scratch:
840 0 : sili_dmamem_free(sc, sp->sp_scratch);
841 : free_cmds:
842 0 : sili_dmamem_free(sc, sp->sp_cmds);
843 : free_ccbs:
844 0 : sili_ccb_free(sp);
845 0 : return (1);
846 0 : }
847 :
848 : void
849 0 : sili_ccb_free(struct sili_port *sp)
850 : {
851 0 : struct sili_softc *sc = sp->sp_sc;
852 : struct sili_ccb *ccb;
853 :
854 0 : while ((ccb = sili_get_ccb(sp)) != NULL)
855 0 : bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
856 :
857 0 : free(sp->sp_ccbs, M_DEVBUF, 0);
858 0 : sp->sp_ccbs = NULL;
859 0 : }
860 :
861 : struct sili_ccb *
862 0 : sili_get_ccb(struct sili_port *sp)
863 : {
864 : struct sili_ccb *ccb;
865 :
866 : /*
867 : * Don't allow new commands to start while doing PMP error
868 : * recovery
869 : */
870 0 : if (sp->sp_pmp_error_recovery != 0) {
871 0 : return (NULL);
872 : }
873 :
874 0 : mtx_enter(&sp->sp_free_ccb_mtx);
875 0 : ccb = TAILQ_FIRST(&sp->sp_free_ccbs);
876 0 : if (ccb != NULL) {
877 0 : KASSERT(ccb->ccb_xa.state == ATA_S_PUT);
878 0 : TAILQ_REMOVE(&sp->sp_free_ccbs, ccb, ccb_entry);
879 0 : ccb->ccb_xa.state = ATA_S_SETUP;
880 0 : }
881 0 : mtx_leave(&sp->sp_free_ccb_mtx);
882 :
883 0 : return (ccb);
884 0 : }
885 :
886 : void
887 0 : sili_put_ccb(struct sili_ccb *ccb)
888 : {
889 0 : struct sili_port *sp = ccb->ccb_port;
890 :
891 : #ifdef DIAGNOSTIC
892 0 : if (ccb->ccb_xa.state != ATA_S_COMPLETE &&
893 0 : ccb->ccb_xa.state != ATA_S_TIMEOUT &&
894 0 : ccb->ccb_xa.state != ATA_S_ERROR) {
895 0 : printf("%s: invalid ata_xfer state %02x in sili_put_ccb, "
896 0 : "slot %d\n", PORTNAME(sp), ccb->ccb_xa.state,
897 0 : ccb->ccb_xa.tag);
898 0 : }
899 : #endif
900 :
901 0 : ccb->ccb_xa.state = ATA_S_PUT;
902 0 : mtx_enter(&sp->sp_free_ccb_mtx);
903 0 : TAILQ_INSERT_TAIL(&sp->sp_free_ccbs, ccb, ccb_entry);
904 0 : mtx_leave(&sp->sp_free_ccb_mtx);
905 0 : }
906 :
907 : struct sili_dmamem *
908 0 : sili_dmamem_alloc(struct sili_softc *sc, bus_size_t size, bus_size_t align)
909 : {
910 : struct sili_dmamem *sdm;
911 0 : int nsegs;
912 :
913 0 : sdm = malloc(sizeof(*sdm), M_DEVBUF, M_WAITOK | M_ZERO);
914 0 : sdm->sdm_size = size;
915 :
916 0 : if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
917 0 : BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &sdm->sdm_map) != 0)
918 : goto sdmfree;
919 :
920 0 : if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &sdm->sdm_seg,
921 0 : 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
922 : goto destroy;
923 :
924 0 : if (bus_dmamem_map(sc->sc_dmat, &sdm->sdm_seg, nsegs, size,
925 0 : &sdm->sdm_kva, BUS_DMA_NOWAIT) != 0)
926 : goto free;
927 :
928 0 : if (bus_dmamap_load(sc->sc_dmat, sdm->sdm_map, sdm->sdm_kva, size,
929 0 : NULL, BUS_DMA_NOWAIT) != 0)
930 : goto unmap;
931 :
932 0 : return (sdm);
933 :
934 : unmap:
935 0 : bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, size);
936 : free:
937 0 : bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
938 : destroy:
939 0 : bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
940 : sdmfree:
941 0 : free(sdm, M_DEVBUF, sizeof *sdm);
942 :
943 0 : return (NULL);
944 0 : }
945 :
946 : void
947 0 : sili_dmamem_free(struct sili_softc *sc, struct sili_dmamem *sdm)
948 : {
949 0 : bus_dmamap_unload(sc->sc_dmat, sdm->sdm_map);
950 0 : bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, sdm->sdm_size);
951 0 : bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
952 0 : bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
953 0 : free(sdm, M_DEVBUF, sizeof *sdm);
954 0 : }
955 :
956 : u_int32_t
957 0 : sili_read(struct sili_softc *sc, bus_size_t r)
958 : {
959 : u_int32_t rv;
960 :
961 0 : bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
962 : BUS_SPACE_BARRIER_READ);
963 0 : rv = bus_space_read_4(sc->sc_iot_global, sc->sc_ioh_global, r);
964 :
965 0 : return (rv);
966 : }
967 :
968 : void
969 0 : sili_write(struct sili_softc *sc, bus_size_t r, u_int32_t v)
970 : {
971 0 : bus_space_write_4(sc->sc_iot_global, sc->sc_ioh_global, r, v);
972 0 : bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
973 : BUS_SPACE_BARRIER_WRITE);
974 0 : }
975 :
976 : u_int32_t
977 0 : sili_pread(struct sili_port *sp, bus_size_t r)
978 : {
979 : u_int32_t rv;
980 :
981 0 : bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
982 : BUS_SPACE_BARRIER_READ);
983 0 : rv = bus_space_read_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r);
984 :
985 0 : return (rv);
986 : }
987 :
988 : void
989 0 : sili_pwrite(struct sili_port *sp, bus_size_t r, u_int32_t v)
990 : {
991 0 : bus_space_write_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, v);
992 0 : bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
993 : BUS_SPACE_BARRIER_WRITE);
994 0 : }
995 :
996 : int
997 0 : sili_pwait_eq(struct sili_port *sp, bus_size_t r, u_int32_t mask,
998 : u_int32_t value, int timeout)
999 : {
1000 0 : while ((sili_pread(sp, r) & mask) != value) {
1001 0 : if (timeout == 0)
1002 0 : return (0);
1003 :
1004 0 : delay(1000);
1005 0 : timeout--;
1006 : }
1007 :
1008 0 : return (1);
1009 0 : }
1010 :
1011 : int
1012 0 : sili_pwait_ne(struct sili_port *sp, bus_size_t r, u_int32_t mask,
1013 : u_int32_t value, int timeout)
1014 : {
1015 0 : while ((sili_pread(sp, r) & mask) == value) {
1016 0 : if (timeout == 0)
1017 0 : return (0);
1018 :
1019 0 : delay(1000);
1020 0 : timeout--;
1021 : }
1022 :
1023 0 : return (1);
1024 0 : }
1025 :
1026 : void
1027 0 : sili_post_direct(struct sili_port *sp, u_int slot, void *buf, size_t buflen)
1028 : {
1029 0 : bus_size_t r = SILI_PREG_SLOT(slot);
1030 :
1031 : #ifdef DIAGNOSTIC
1032 0 : if (buflen != 64 && buflen != 128)
1033 0 : panic("sili_pcopy: buflen of %lu is not 64 or 128", buflen);
1034 : #endif
1035 :
1036 0 : bus_space_write_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
1037 : buf, buflen);
1038 0 : bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, buflen,
1039 : BUS_SPACE_BARRIER_WRITE);
1040 :
1041 0 : sili_pwrite(sp, SILI_PREG_FIFO, slot);
1042 0 : }
1043 :
1044 : void
1045 0 : sili_pread_fis(struct sili_port *sp, u_int slot, struct ata_fis_d2h *fis)
1046 : {
1047 0 : bus_size_t r = SILI_PREG_SLOT(slot) + 8;
1048 :
1049 0 : bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
1050 : sizeof(struct ata_fis_d2h), BUS_SPACE_BARRIER_READ);
1051 0 : bus_space_read_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
1052 : fis, sizeof(struct ata_fis_d2h));
1053 0 : }
1054 :
1055 : void
1056 0 : sili_post_indirect(struct sili_port *sp, struct sili_ccb *ccb)
1057 : {
1058 0 : sili_pwrite(sp, SILI_PREG_CAR_LO(ccb->ccb_xa.tag),
1059 0 : (u_int32_t)ccb->ccb_cmd_dva);
1060 0 : sili_pwrite(sp, SILI_PREG_CAR_HI(ccb->ccb_xa.tag),
1061 0 : (u_int32_t)(ccb->ccb_cmd_dva >> 32));
1062 0 : }
1063 :
1064 : u_int32_t
1065 0 : sili_signature(struct sili_port *sp, u_int slot)
1066 : {
1067 : u_int32_t sig_hi, sig_lo;
1068 :
1069 0 : sig_hi = sili_pread(sp, SILI_PREG_SIG_HI(slot));
1070 0 : sig_hi <<= SILI_PREG_SIG_HI_SHIFT;
1071 0 : sig_lo = sili_pread(sp, SILI_PREG_SIG_LO(slot));
1072 0 : sig_lo &= SILI_PREG_SIG_LO_MASK;
1073 :
1074 0 : return (sig_hi | sig_lo);
1075 : }
1076 :
1077 : void
1078 0 : sili_dummy_done(struct ata_xfer *xa)
1079 : {
1080 0 : }
1081 :
1082 : int
1083 0 : sili_pmp_portreset(struct sili_softc *sc, int port, int pmp_port)
1084 : {
1085 : struct sili_port *sp;
1086 0 : u_int32_t data;
1087 : int loop;
1088 :
1089 0 : sp = &sc->sc_ports[port];
1090 : DPRINTF(SILI_D_VERBOSE, "%s: resetting pmp port %d\n", PORTNAME(sp),
1091 : pmp_port);
1092 :
1093 0 : if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1))
1094 : goto err;
1095 0 : if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SCTL,
1096 : SATA_PM_SCTL_IPM_DISABLED))
1097 : goto err;
1098 0 : delay(10000);
1099 :
1100 : /* enable PHY by writing 1 then 0 to Scontrol DET field, using
1101 : * Write Port Multiplier commands
1102 : */
1103 0 : data = SATA_PM_SCTL_IPM_DISABLED | SATA_PM_SCTL_DET_INIT |
1104 : SATA_PM_SCTL_SPD_ANY;
1105 0 : if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SCTL, data))
1106 : goto err;
1107 0 : delay(100000);
1108 :
1109 0 : if (sili_pmp_phy_status(sp, pmp_port, &data)) {
1110 0 : printf("%s: cannot clear phy status for PMP probe\n",
1111 0 : PORTNAME(sp));
1112 0 : goto err;
1113 : }
1114 :
1115 0 : sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
1116 0 : data = SATA_PM_SCTL_IPM_DISABLED | SATA_PM_SCTL_DET_NONE;
1117 0 : if (sili_pmp_write(sp, pmp_port, SATA_PMREG_SCTL, data))
1118 : goto err;
1119 0 : delay(100000);
1120 :
1121 : /* wait for PHYRDY by polling SStatus */
1122 0 : for (loop = 3; loop; loop--) {
1123 0 : if (sili_pmp_read(sp, pmp_port, SATA_PMREG_SSTS, &data))
1124 : goto err;
1125 0 : if (data & SATA_PM_SSTS_DET)
1126 : break;
1127 0 : delay(100000);
1128 : }
1129 0 : if (loop == 0) {
1130 : DPRINTF(SILI_D_VERBOSE, "%s.%d: port appears to be unplugged\n",
1131 : PORTNAME(sp), pmp_port);
1132 : goto err;
1133 : }
1134 :
1135 : /* give it a bit more time to complete negotiation */
1136 0 : for (loop = 30; loop; loop--) {
1137 0 : if (sili_pmp_read(sp, pmp_port, SATA_PMREG_SSTS, &data))
1138 : goto err;
1139 0 : if ((data & SATA_PM_SSTS_DET) == SATA_PM_SSTS_DET_DEV)
1140 : break;
1141 0 : delay(10000);
1142 : }
1143 0 : if (loop == 0) {
1144 0 : printf("%s.%d: device may be powered down\n", PORTNAME(sp),
1145 : pmp_port);
1146 0 : goto err;
1147 : }
1148 :
1149 : DPRINTF(SILI_D_VERBOSE, "%s.%d: device detected; SStatus=%08x\n",
1150 : PORTNAME(sp), pmp_port, data);
1151 :
1152 : /* clear the X-bit and all other error bits in Serror (PCSR[1]) */
1153 0 : sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
1154 0 : return (0);
1155 :
1156 : err:
1157 : DPRINTF(SILI_D_VERBOSE, "%s.%d: port reset failed\n", PORTNAME(sp),
1158 : pmp_port);
1159 0 : sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
1160 0 : return (1);
1161 0 : }
1162 :
1163 : void
1164 0 : sili_pmp_op_timeout(void *cookie)
1165 : {
1166 0 : struct sili_ccb *ccb = cookie;
1167 0 : struct sili_port *sp = ccb->ccb_port;
1168 : int s;
1169 :
1170 0 : switch (ccb->ccb_xa.state) {
1171 : case ATA_S_PENDING:
1172 0 : TAILQ_REMOVE(&sp->sp_active_ccbs, ccb, ccb_entry);
1173 0 : ccb->ccb_xa.state = ATA_S_TIMEOUT;
1174 0 : break;
1175 : case ATA_S_ONCHIP:
1176 0 : KASSERT(sp->sp_active == (1 << ccb->ccb_xa.tag));
1177 0 : s = splbio();
1178 0 : sili_port_intr(sp, ccb->ccb_xa.tag);
1179 0 : splx(s);
1180 0 : break;
1181 : case ATA_S_ERROR:
1182 : /* don't do anything? */
1183 : break;
1184 : default:
1185 0 : panic("%s: sili_pmp_op_timeout: ccb in bad state %d",
1186 0 : PORTNAME(sp), ccb->ccb_xa.state);
1187 : }
1188 0 : }
1189 :
1190 : int
1191 0 : sili_pmp_softreset(struct sili_softc *sc, int port, int pmp_port)
1192 : {
1193 : struct sili_ccb *ccb;
1194 : struct sili_prb *prb;
1195 : struct sili_port *sp;
1196 : struct ata_fis_h2d *fis;
1197 0 : u_int32_t data;
1198 : u_int32_t signature;
1199 :
1200 0 : sp = &sc->sc_ports[port];
1201 :
1202 0 : ccb = sili_get_ccb(sp);
1203 0 : if (ccb == NULL) {
1204 0 : printf("%s: sili_pmp_softreset NULL ccb!\n", PORTNAME(sp));
1205 0 : return (-1);
1206 : }
1207 :
1208 0 : ccb->ccb_xa.flags = ATA_F_POLL | ATA_F_GET_RFIS;
1209 0 : ccb->ccb_xa.complete = sili_dummy_done;
1210 0 : ccb->ccb_xa.pmp_port = pmp_port;
1211 :
1212 0 : prb = ccb->ccb_cmd;
1213 0 : bzero(prb, sizeof(*prb));
1214 0 : fis = (struct ata_fis_h2d *)&prb->fis;
1215 0 : fis->flags = pmp_port;
1216 0 : prb->control = SILI_PRB_SOFT_RESET;
1217 :
1218 0 : ccb->ccb_xa.state = ATA_S_PENDING;
1219 :
1220 0 : if (sili_poll(ccb, 8000, sili_pmp_op_timeout) != 0) {
1221 : DPRINTF(SILI_D_VERBOSE, "%s.%d: softreset FIS failed\n",
1222 : PORTNAME(sp), pmp_port);
1223 :
1224 0 : sili_put_ccb(ccb);
1225 : /* don't return a valid device type here so the caller knows
1226 : * it can retry if it wants to
1227 : */
1228 0 : return (-1);
1229 : }
1230 :
1231 0 : signature = ccb->ccb_xa.rfis.sector_count |
1232 0 : (ccb->ccb_xa.rfis.lba_low << 8) |
1233 0 : (ccb->ccb_xa.rfis.lba_mid << 16) |
1234 0 : (ccb->ccb_xa.rfis.lba_high << 24);
1235 : DPRINTF(SILI_D_VERBOSE, "%s.%d: signature: %08x\n", PORTNAME(sp),
1236 : pmp_port, signature);
1237 :
1238 0 : sili_put_ccb(ccb);
1239 :
1240 : /* clear phy status and error bits */
1241 0 : if (sili_pmp_phy_status(sp, pmp_port, &data)) {
1242 0 : printf("%s.%d: cannot clear phy status after softreset\n",
1243 0 : PORTNAME(sp), pmp_port);
1244 0 : }
1245 0 : sili_pmp_write(sp, pmp_port, SATA_PMREG_SERR, -1);
1246 :
1247 : /* classify the device based on its signature */
1248 0 : switch (signature) {
1249 : case SATA_SIGNATURE_DISK:
1250 0 : return (ATA_PORT_T_DISK);
1251 : case SATA_SIGNATURE_ATAPI:
1252 0 : return (ATA_PORT_T_ATAPI);
1253 : case SATA_SIGNATURE_PORT_MULTIPLIER:
1254 0 : return (ATA_PORT_T_NONE);
1255 : default:
1256 0 : return (ATA_PORT_T_NONE);
1257 : }
1258 0 : }
1259 :
1260 : u_int32_t
1261 0 : sili_port_softreset(struct sili_port *sp)
1262 : {
1263 0 : struct sili_prb_softreset sreset;
1264 : u_int32_t signature;
1265 :
1266 0 : bzero(&sreset, sizeof(sreset));
1267 0 : sreset.control = htole16(SILI_PRB_SOFT_RESET | SILI_PRB_INTERRUPT_MASK);
1268 0 : sreset.fis[1] = SATA_PMP_CONTROL_PORT;
1269 :
1270 : /* we use slot 0 */
1271 0 : sili_post_direct(sp, 0, &sreset, sizeof(sreset));
1272 0 : if (!sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000)) {
1273 : DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for soft "
1274 : "reset\n", PORTNAME(sp));
1275 0 : return (ATA_PORT_T_NONE);
1276 : }
1277 :
1278 : /* Read device signature from command slot. */
1279 0 : signature = sili_signature(sp, 0);
1280 :
1281 : DPRINTF(SILI_D_VERBOSE, "%s: signature 0x%08x\n", PORTNAME(sp),
1282 : signature);
1283 :
1284 0 : switch (signature) {
1285 : case SATA_SIGNATURE_DISK:
1286 0 : return (ATA_PORT_T_DISK);
1287 : case SATA_SIGNATURE_ATAPI:
1288 0 : return (ATA_PORT_T_ATAPI);
1289 : case SATA_SIGNATURE_PORT_MULTIPLIER:
1290 0 : return (ATA_PORT_T_PM);
1291 : default:
1292 0 : return (ATA_PORT_T_NONE);
1293 : }
1294 0 : }
1295 :
1296 : int
1297 0 : sili_ata_probe(void *xsc, int port, int lun)
1298 : {
1299 0 : struct sili_softc *sc = xsc;
1300 0 : struct sili_port *sp = &sc->sc_ports[port];
1301 : int port_type;
1302 :
1303 : /* handle pmp port probes */
1304 0 : if (lun != 0) {
1305 : int i;
1306 : int rc;
1307 0 : int pmp_port = lun - 1;
1308 :
1309 0 : if (lun > sp->sp_pmp_ports)
1310 0 : return (ATA_PORT_T_NONE);
1311 :
1312 0 : for (i = 0; i < 2; i++) {
1313 0 : if (sili_pmp_portreset(sc, port, pmp_port)) {
1314 : continue;
1315 : }
1316 :
1317 : /* small delay between attempts to allow error
1318 : * conditions to settle down. this doesn't seem
1319 : * to affect portreset operations, just
1320 : * commands sent to the device.
1321 : */
1322 0 : if (i != 0) {
1323 0 : delay(5000000);
1324 0 : }
1325 :
1326 0 : rc = sili_pmp_softreset(sc, port, pmp_port);
1327 0 : switch (rc) {
1328 : case -1:
1329 : /* possibly try again */
1330 : break;
1331 : case ATA_PORT_T_DISK:
1332 : case ATA_PORT_T_ATAPI:
1333 : /* mark this port as active */
1334 0 : sp->sp_active_pmp_ports |= (1 << pmp_port);
1335 : default:
1336 0 : return (rc);
1337 : }
1338 : }
1339 : DPRINTF(SILI_D_VERBOSE, "%s.%d: probe failed\n", PORTNAME(sp),
1340 : pmp_port);
1341 0 : return (ATA_PORT_T_NONE);
1342 : }
1343 :
1344 0 : sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRESET);
1345 0 : delay(10000);
1346 0 : sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_PORTRESET);
1347 :
1348 0 : sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTINIT);
1349 0 : if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
1350 : SILI_PREG_PCS_PORTRDY, 1000)) {
1351 0 : printf("%s: couldn't initialize port\n", PORTNAME(sp));
1352 0 : return (ATA_PORT_T_NONE);
1353 : }
1354 :
1355 0 : sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_A32B);
1356 :
1357 0 : if (!sili_pwait_eq(sp, SILI_PREG_SSTS, SATA_SStatus_DET,
1358 : SATA_SStatus_DET_DEV, 2000)) {
1359 : DPRINTF(SILI_D_VERBOSE, "%s: unattached\n", PORTNAME(sp));
1360 0 : return (ATA_PORT_T_NONE);
1361 : }
1362 :
1363 : DPRINTF(SILI_D_VERBOSE, "%s: SSTS 0x%08x\n", PORTNAME(sp),
1364 : sili_pread(sp, SILI_PREG_SSTS));
1365 :
1366 0 : port_type = sili_port_softreset(sp);
1367 0 : if (port_type == ATA_PORT_T_NONE)
1368 0 : return (port_type);
1369 :
1370 : /* allocate port resources */
1371 0 : if (sili_ccb_alloc(sp) != 0)
1372 0 : return (ATA_PORT_T_NONE);
1373 :
1374 : /* do PMP probe now that we can talk to the device */
1375 0 : if (port_type == ATA_PORT_T_PM) {
1376 : int i;
1377 :
1378 0 : sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PMEN);
1379 :
1380 0 : if (sili_pmp_identify(sp, &sp->sp_pmp_ports)) {
1381 0 : return (ATA_PORT_T_NONE);
1382 : }
1383 :
1384 : /* reset all the PMP ports to wake devices up */
1385 0 : for (i = 0; i < sp->sp_pmp_ports; i++) {
1386 0 : sili_pmp_portreset(sp->sp_sc, sp->sp_port, i);
1387 : }
1388 0 : }
1389 :
1390 : /* enable port interrupts */
1391 0 : sili_write(sc, SILI_REG_GC, sili_read(sc, SILI_REG_GC) | 1 << port);
1392 0 : sili_pwrite(sp, SILI_PREG_IES, SILI_PREG_IE_CMDERR |
1393 : SILI_PREG_IE_CMDCOMP);
1394 :
1395 0 : return (port_type);
1396 0 : }
1397 :
1398 : void
1399 0 : sili_ata_free(void *xsc, int port, int lun)
1400 : {
1401 0 : struct sili_softc *sc = xsc;
1402 0 : struct sili_port *sp = &sc->sc_ports[port];
1403 :
1404 0 : if (lun == 0) {
1405 0 : if (sp->sp_ccbs != NULL)
1406 0 : sili_ccb_free(sp);
1407 :
1408 : /* XXX we should do more here */
1409 : }
1410 0 : }
1411 :
1412 : void
1413 0 : sili_ata_cmd(struct ata_xfer *xa)
1414 : {
1415 0 : struct sili_ccb *ccb = (struct sili_ccb *)xa;
1416 0 : struct sili_port *sp = ccb->ccb_port;
1417 0 : struct sili_softc *sc = sp->sp_sc;
1418 : struct sili_prb_ata *ata;
1419 : struct sili_prb_packet *atapi;
1420 : struct sili_sge *sgl;
1421 : int sgllen;
1422 : int s;
1423 :
1424 0 : KASSERT(xa->state == ATA_S_SETUP || xa->state == ATA_S_TIMEOUT);
1425 :
1426 0 : if (xa->flags & ATA_F_PACKET) {
1427 0 : atapi = ccb->ccb_cmd;
1428 :
1429 0 : if (xa->flags & ATA_F_WRITE)
1430 0 : atapi->control = htole16(SILI_PRB_PACKET_WRITE);
1431 : else
1432 0 : atapi->control = htole16(SILI_PRB_PACKET_READ);
1433 :
1434 0 : sgl = atapi->sgl;
1435 : sgllen = nitems(atapi->sgl);
1436 0 : } else {
1437 0 : ata = ccb->ccb_cmd;
1438 :
1439 0 : ata->control = 0;
1440 :
1441 0 : sgl = ata->sgl;
1442 : sgllen = nitems(ata->sgl);
1443 : }
1444 :
1445 0 : if (sili_load(ccb, sgl, sgllen) != 0)
1446 : goto failcmd;
1447 :
1448 0 : bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
1449 : xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_PREWRITE);
1450 :
1451 0 : timeout_set(&xa->stimeout, sili_ata_cmd_timeout, ccb);
1452 :
1453 0 : xa->state = ATA_S_PENDING;
1454 :
1455 0 : if (xa->flags & ATA_F_POLL)
1456 0 : sili_poll(ccb, xa->timeout, sili_ata_cmd_timeout);
1457 : else {
1458 0 : s = splbio();
1459 0 : timeout_add_msec(&xa->stimeout, xa->timeout);
1460 0 : sili_start(sp, ccb);
1461 0 : splx(s);
1462 : }
1463 :
1464 0 : return;
1465 :
1466 : failcmd:
1467 0 : s = splbio();
1468 0 : xa->state = ATA_S_ERROR;
1469 0 : ata_complete(xa);
1470 0 : splx(s);
1471 0 : }
1472 :
1473 : void
1474 0 : sili_ata_cmd_done(struct sili_ccb *ccb, int defer_completion)
1475 : {
1476 0 : struct sili_port *sp = ccb->ccb_port;
1477 0 : struct sili_softc *sc = sp->sp_sc;
1478 0 : struct ata_xfer *xa = &ccb->ccb_xa;
1479 :
1480 0 : splassert(IPL_BIO);
1481 :
1482 0 : timeout_del(&xa->stimeout);
1483 :
1484 0 : bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
1485 : xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_POSTWRITE);
1486 :
1487 0 : sili_unload(ccb);
1488 :
1489 0 : TAILQ_REMOVE(&sp->sp_active_ccbs, ccb, ccb_entry);
1490 0 : sp->sp_active &= ~(1 << xa->tag);
1491 0 : if (sp->sp_err_active & (1 << xa->tag)) {
1492 0 : sp->sp_err_active &= ~(1 << xa->tag);
1493 : DPRINTF(SILI_D_VERBOSE, "%s: slot %d complete, error mask now "
1494 : "%x\n", PORTNAME(sp), xa->tag, sp->sp_err_active);
1495 0 : }
1496 :
1497 0 : if (xa->state == ATA_S_ONCHIP)
1498 0 : xa->state = ATA_S_COMPLETE;
1499 : #ifdef DIAGNOSTIC
1500 0 : else if (xa->state != ATA_S_ERROR && xa->state != ATA_S_TIMEOUT)
1501 0 : printf("%s: invalid ata_xfer state %02x in sili_ata_cmd_done, "
1502 0 : "slot %d\n", PORTNAME(sp), xa->state, xa->tag);
1503 : #endif
1504 0 : if (defer_completion)
1505 0 : TAILQ_INSERT_TAIL(&sp->sp_deferred_ccbs, ccb, ccb_entry);
1506 0 : else if (xa->state == ATA_S_COMPLETE)
1507 0 : ata_complete(xa);
1508 : #ifdef DIAGNOSTIC
1509 : else
1510 0 : printf("%s: completion not deferred, but xa->state is %02x?\n",
1511 0 : PORTNAME(sp), xa->state);
1512 : #endif
1513 0 : }
1514 :
1515 : void
1516 0 : sili_ata_cmd_timeout(void *xccb)
1517 : {
1518 0 : struct sili_ccb *ccb = xccb;
1519 0 : struct sili_port *sp = ccb->ccb_port;
1520 : int s;
1521 :
1522 0 : s = splbio();
1523 0 : sili_port_intr(sp, ccb->ccb_xa.tag);
1524 0 : splx(s);
1525 0 : }
1526 :
1527 : int
1528 0 : sili_load(struct sili_ccb *ccb, struct sili_sge *sgl, int sgllen)
1529 : {
1530 0 : struct sili_port *sp = ccb->ccb_port;
1531 0 : struct sili_softc *sc = sp->sp_sc;
1532 0 : struct ata_xfer *xa = &ccb->ccb_xa;
1533 : struct sili_sge *nsge = sgl, *ce = NULL;
1534 0 : bus_dmamap_t dmap = ccb->ccb_dmamap;
1535 : u_int64_t addr;
1536 : int error;
1537 : int i;
1538 :
1539 0 : if (xa->datalen == 0)
1540 0 : return (0);
1541 :
1542 0 : error = bus_dmamap_load(sc->sc_dmat, dmap, xa->data, xa->datalen, NULL,
1543 : (xa->flags & ATA_F_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1544 0 : if (error != 0) {
1545 0 : printf("%s: error %d loading dmamap\n", PORTNAME(sp), error);
1546 0 : return (1);
1547 : }
1548 :
1549 0 : if (dmap->dm_nsegs > sgllen)
1550 0 : ce = &sgl[sgllen - 1];
1551 :
1552 0 : for (i = 0; i < dmap->dm_nsegs; i++) {
1553 0 : if (nsge == ce) {
1554 0 : nsge++;
1555 :
1556 0 : addr = ccb->ccb_cmd_dva;
1557 0 : addr += ((u_int8_t *)nsge - (u_int8_t *)ccb->ccb_cmd);
1558 :
1559 0 : ce->addr_lo = htole32((u_int32_t)addr);
1560 0 : ce->addr_hi = htole32((u_int32_t)(addr >> 32));
1561 0 : ce->flags = htole32(SILI_SGE_LNK);
1562 :
1563 0 : if ((dmap->dm_nsegs - i) > SILI_SGT_SGLLEN)
1564 0 : ce += SILI_SGT_SGLLEN;
1565 : else
1566 : ce = NULL;
1567 : }
1568 :
1569 : sgl = nsge;
1570 :
1571 0 : addr = dmap->dm_segs[i].ds_addr;
1572 0 : sgl->addr_lo = htole32((u_int32_t)addr);
1573 0 : sgl->addr_hi = htole32((u_int32_t)(addr >> 32));
1574 0 : sgl->data_count = htole32(dmap->dm_segs[i].ds_len);
1575 0 : sgl->flags = 0;
1576 :
1577 0 : nsge++;
1578 : }
1579 0 : sgl->flags |= htole32(SILI_SGE_TRM);
1580 :
1581 0 : bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1582 : (xa->flags & ATA_F_READ) ? BUS_DMASYNC_PREREAD :
1583 : BUS_DMASYNC_PREWRITE);
1584 :
1585 0 : return (0);
1586 0 : }
1587 :
1588 : void
1589 0 : sili_unload(struct sili_ccb *ccb)
1590 : {
1591 0 : struct sili_port *sp = ccb->ccb_port;
1592 0 : struct sili_softc *sc = sp->sp_sc;
1593 0 : struct ata_xfer *xa = &ccb->ccb_xa;
1594 0 : bus_dmamap_t dmap = ccb->ccb_dmamap;
1595 :
1596 0 : if (xa->datalen == 0)
1597 0 : return;
1598 :
1599 0 : bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1600 : (xa->flags & ATA_F_READ) ? BUS_DMASYNC_POSTREAD :
1601 : BUS_DMASYNC_POSTWRITE);
1602 0 : bus_dmamap_unload(sc->sc_dmat, dmap);
1603 :
1604 0 : if (xa->flags & ATA_F_READ)
1605 0 : xa->resid = xa->datalen - sili_pread(sp,
1606 0 : SILI_PREG_RX_COUNT(xa->tag));
1607 : else
1608 0 : xa->resid = 0;
1609 0 : }
1610 :
1611 : int
1612 0 : sili_poll(struct sili_ccb *ccb, int timeout, void (*timeout_fn)(void *))
1613 : {
1614 0 : struct sili_port *sp = ccb->ccb_port;
1615 : int s;
1616 :
1617 0 : s = splbio();
1618 0 : sili_start(sp, ccb);
1619 0 : do {
1620 0 : if (sili_port_intr(sp, -1) & (1 << ccb->ccb_xa.tag)) {
1621 0 : splx(s);
1622 0 : return (ccb->ccb_xa.state != ATA_S_COMPLETE);
1623 : }
1624 :
1625 0 : delay(1000);
1626 0 : } while (--timeout > 0);
1627 :
1628 : /* Run timeout while at splbio, otherwise sili_intr could interfere. */
1629 0 : if (timeout_fn != NULL)
1630 0 : timeout_fn(ccb);
1631 :
1632 0 : splx(s);
1633 :
1634 0 : return (1);
1635 0 : }
1636 :
1637 : void
1638 0 : sili_start(struct sili_port *sp, struct sili_ccb *ccb)
1639 : {
1640 0 : int slot = ccb->ccb_xa.tag;
1641 :
1642 0 : splassert(IPL_BIO);
1643 0 : KASSERT(ccb->ccb_xa.state == ATA_S_PENDING);
1644 0 : KASSERT(sp->sp_pmp_error_recovery == 0);
1645 :
1646 0 : TAILQ_INSERT_TAIL(&sp->sp_active_ccbs, ccb, ccb_entry);
1647 0 : sp->sp_active |= 1 << slot;
1648 0 : ccb->ccb_xa.state = ATA_S_ONCHIP;
1649 :
1650 0 : sili_post_indirect(sp, ccb);
1651 0 : }
1652 :
1653 : int
1654 0 : sili_read_ncq_error(struct sili_port *sp, int *err_slotp, int pmp_port)
1655 : {
1656 0 : struct sili_softc *sc = sp->sp_sc;
1657 0 : struct sili_prb_ata read_10h;
1658 : u_int64_t addr;
1659 : struct ata_fis_h2d *fis;
1660 : struct ata_log_page_10h *log;
1661 : struct sili_ccb *ccb;
1662 : int rc;
1663 :
1664 0 : sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTINIT);
1665 0 : if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
1666 : SILI_PREG_PCS_PORTRDY, 1000)) {
1667 0 : printf("%s: couldn't ready port during log page read\n",
1668 0 : PORTNAME(sp));
1669 0 : return (1);
1670 : }
1671 :
1672 : /* READ LOG EXT 10h into scratch space */
1673 0 : bzero(&read_10h, sizeof(read_10h));
1674 0 : read_10h.control = htole16(SILI_PRB_INTERRUPT_MASK);
1675 :
1676 0 : addr = SILI_DMA_DVA(sp->sp_scratch);
1677 0 : read_10h.sgl[0].addr_lo = htole32((u_int32_t)addr);
1678 0 : read_10h.sgl[0].addr_hi = htole32((u_int32_t)(addr >> 32));
1679 0 : read_10h.sgl[0].data_count = htole32(512);
1680 0 : read_10h.sgl[0].flags = htole32(SILI_SGE_TRM);
1681 :
1682 0 : fis = (struct ata_fis_h2d *)read_10h.fis;
1683 0 : fis->type = ATA_FIS_TYPE_H2D;
1684 0 : fis->flags = ATA_H2D_FLAGS_CMD | pmp_port;
1685 0 : fis->command = ATA_C_READ_LOG_EXT;
1686 0 : fis->lba_low = 0x10; /* queued error log page (10h) */
1687 0 : fis->sector_count = 1; /* number of sectors (1) */
1688 0 : fis->sector_count_exp = 0;
1689 0 : fis->lba_mid = 0; /* starting offset */
1690 0 : fis->lba_mid_exp = 0;
1691 0 : fis->device = 0;
1692 :
1693 0 : bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
1694 : 512, BUS_DMASYNC_PREREAD);
1695 :
1696 : /* issue read and poll for completion */
1697 0 : sili_post_direct(sp, 0, &read_10h, sizeof(read_10h));
1698 0 : rc = sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000);
1699 :
1700 0 : bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
1701 : 512, BUS_DMASYNC_POSTREAD);
1702 :
1703 0 : if (!rc) {
1704 : DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for log "
1705 : "page read\n", PORTNAME(sp));
1706 0 : return (1);
1707 : }
1708 :
1709 : /* Extract failed register set and tags from the scratch space. */
1710 0 : log = (struct ata_log_page_10h *)SILI_DMA_KVA(sp->sp_scratch);
1711 0 : if (ISSET(log->err_regs.type, ATA_LOG_10H_TYPE_NOTQUEUED)) {
1712 : /* Not queued bit was set - wasn't an NCQ error? */
1713 0 : printf("%s: read NCQ error page, but not an NCQ error?\n",
1714 0 : PORTNAME(sp));
1715 0 : return (1);
1716 : }
1717 :
1718 : /* Copy back the log record as a D2H register FIS. */
1719 0 : *err_slotp = log->err_regs.type & ATA_LOG_10H_TYPE_TAG_MASK;
1720 :
1721 0 : ccb = &sp->sp_ccbs[*err_slotp];
1722 0 : memcpy(&ccb->ccb_xa.rfis, &log->err_regs, sizeof(struct ata_fis_d2h));
1723 0 : ccb->ccb_xa.rfis.type = ATA_FIS_TYPE_D2H;
1724 0 : ccb->ccb_xa.rfis.flags = 0;
1725 :
1726 0 : return (0);
1727 0 : }
1728 :
1729 : struct ata_xfer *
1730 0 : sili_ata_get_xfer(void *xsc, int port)
1731 : {
1732 0 : struct sili_softc *sc = xsc;
1733 0 : struct sili_port *sp = &sc->sc_ports[port];
1734 : struct sili_ccb *ccb;
1735 :
1736 0 : ccb = sili_get_ccb(sp);
1737 0 : if (ccb == NULL) {
1738 0 : printf("%s: sili_ata_get_xfer NULL ccb!\n", PORTNAME(sp));
1739 0 : return (NULL);
1740 : }
1741 :
1742 0 : bzero(ccb->ccb_cmd, SILI_CMD_LEN);
1743 :
1744 0 : return ((struct ata_xfer *)ccb);
1745 0 : }
1746 :
1747 : void
1748 0 : sili_ata_put_xfer(struct ata_xfer *xa)
1749 : {
1750 0 : struct sili_ccb *ccb = (struct sili_ccb *)xa;
1751 :
1752 0 : sili_put_ccb(ccb);
1753 0 : }
1754 :
1755 : /* PMP register ops */
1756 : int
1757 0 : sili_pmp_read(struct sili_port *sp, int target, int which, u_int32_t *datap)
1758 : {
1759 : struct sili_ccb *ccb;
1760 : struct sili_prb *prb;
1761 : struct ata_fis_h2d *fis;
1762 : int error;
1763 :
1764 0 : ccb = sili_get_ccb(sp);
1765 0 : if (ccb == NULL) {
1766 0 : printf("%s: sili_pmp_read NULL ccb!\n", PORTNAME(sp));
1767 0 : return (1);
1768 : }
1769 0 : ccb->ccb_xa.flags = ATA_F_POLL | ATA_F_GET_RFIS;
1770 0 : ccb->ccb_xa.complete = sili_dummy_done;
1771 0 : ccb->ccb_xa.pmp_port = SATA_PMP_CONTROL_PORT;
1772 0 : ccb->ccb_xa.state = ATA_S_PENDING;
1773 :
1774 0 : prb = ccb->ccb_cmd;
1775 0 : bzero(prb, sizeof(*prb));
1776 0 : fis = (struct ata_fis_h2d *)&prb->fis;
1777 0 : fis->type = ATA_FIS_TYPE_H2D;
1778 0 : fis->flags = ATA_H2D_FLAGS_CMD | SATA_PMP_CONTROL_PORT;
1779 0 : fis->command = ATA_C_READ_PM;
1780 0 : fis->features = which;
1781 0 : fis->device = target | ATA_H2D_DEVICE_LBA;
1782 0 : fis->control = ATA_FIS_CONTROL_4BIT;
1783 :
1784 0 : if (sili_poll(ccb, 1000, sili_pmp_op_timeout) != 0) {
1785 0 : printf("sili_pmp_read(%d, %d) failed\n", target, which);
1786 : error = 1;
1787 0 : } else {
1788 0 : *datap = ccb->ccb_xa.rfis.sector_count |
1789 0 : (ccb->ccb_xa.rfis.lba_low << 8) |
1790 0 : (ccb->ccb_xa.rfis.lba_mid << 16) |
1791 0 : (ccb->ccb_xa.rfis.lba_high << 24);
1792 : error = 0;
1793 : }
1794 0 : sili_put_ccb(ccb);
1795 0 : return (error);
1796 0 : }
1797 :
1798 : int
1799 0 : sili_pmp_write(struct sili_port *sp, int target, int which, u_int32_t data)
1800 : {
1801 : struct sili_ccb *ccb;
1802 : struct sili_prb *prb;
1803 : struct ata_fis_h2d *fis;
1804 : int error;
1805 :
1806 0 : ccb = sili_get_ccb(sp);
1807 0 : if (ccb == NULL) {
1808 0 : printf("%s: sili_pmp_write NULL ccb!\n", PORTNAME(sp));
1809 0 : return (1);
1810 : }
1811 0 : ccb->ccb_xa.complete = sili_dummy_done;
1812 0 : ccb->ccb_xa.flags = ATA_F_POLL;
1813 0 : ccb->ccb_xa.pmp_port = SATA_PMP_CONTROL_PORT;
1814 0 : ccb->ccb_xa.state = ATA_S_PENDING;
1815 :
1816 0 : prb = ccb->ccb_cmd;
1817 0 : bzero(prb, sizeof(*prb));
1818 0 : fis = (struct ata_fis_h2d *)&prb->fis;
1819 0 : fis->type = ATA_FIS_TYPE_H2D;
1820 0 : fis->flags = ATA_H2D_FLAGS_CMD | SATA_PMP_CONTROL_PORT;
1821 0 : fis->command = ATA_C_WRITE_PM;
1822 0 : fis->features = which;
1823 0 : fis->device = target | ATA_H2D_DEVICE_LBA;
1824 0 : fis->sector_count = (u_int8_t)data;
1825 0 : fis->lba_low = (u_int8_t)(data >> 8);
1826 0 : fis->lba_mid = (u_int8_t)(data >> 16);
1827 0 : fis->lba_high = (u_int8_t)(data >> 24);
1828 0 : fis->control = ATA_FIS_CONTROL_4BIT;
1829 :
1830 0 : error = sili_poll(ccb, 1000, sili_pmp_op_timeout);
1831 0 : sili_put_ccb(ccb);
1832 0 : return (error);
1833 0 : }
1834 :
1835 : int
1836 0 : sili_pmp_phy_status(struct sili_port *sp, int target, u_int32_t *datap)
1837 : {
1838 : int error;
1839 :
1840 0 : error = sili_pmp_read(sp, target, SATA_PMREG_SSTS, datap);
1841 0 : if (error == 0)
1842 0 : error = sili_pmp_write(sp, target, SATA_PMREG_SERR, -1);
1843 0 : if (error)
1844 0 : *datap = 0;
1845 :
1846 0 : return (error);
1847 : }
1848 :
1849 : int
1850 0 : sili_pmp_identify(struct sili_port *sp, int *ret_nports)
1851 : {
1852 0 : u_int32_t chipid;
1853 0 : u_int32_t rev;
1854 0 : u_int32_t nports;
1855 0 : u_int32_t features;
1856 0 : u_int32_t enabled;
1857 :
1858 0 : if (sili_pmp_read(sp, 15, 0, &chipid) ||
1859 0 : sili_pmp_read(sp, 15, 1, &rev) ||
1860 0 : sili_pmp_read(sp, 15, 2, &nports) ||
1861 0 : sili_pmp_read(sp, 15, SATA_PMREG_FEA, &features) ||
1862 0 : sili_pmp_read(sp, 15, SATA_PMREG_FEAEN, &enabled)) {
1863 0 : printf("%s: port multiplier identification failed\n",
1864 0 : PORTNAME(sp));
1865 0 : return (1);
1866 : }
1867 :
1868 0 : nports &= 0x0F;
1869 :
1870 : /* ignore SEMB port on SiI3726 port multiplier chips */
1871 0 : if (chipid == 0x37261095) {
1872 0 : nports--;
1873 0 : }
1874 :
1875 0 : printf("%s: port multiplier found: chip=%08x rev=0x%b nports=%d, "
1876 0 : "features: 0x%b, enabled: 0x%b\n", PORTNAME(sp), chipid, rev,
1877 0 : SATA_PFMT_PM_REV, nports, features, SATA_PFMT_PM_FEA, enabled,
1878 : SATA_PFMT_PM_FEA);
1879 :
1880 0 : *ret_nports = nports;
1881 0 : return (0);
1882 0 : }
|