Annotation of sys/dev/ic/sili.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sili.c,v 1.33 2007/04/22 00:06:51 dlg Exp $ */
2:
3: /*
4: * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/buf.h>
22: #include <sys/device.h>
23: #include <sys/proc.h>
24: #include <sys/malloc.h>
25: #include <sys/kernel.h>
26:
27: #include <machine/bus.h>
28:
29: #include <dev/ata/atascsi.h>
30:
31: #include <dev/ic/silireg.h>
32: #include <dev/ic/silivar.h>
33:
34: /* use SILI_DEBUG for dmesg spam */
35: #define NO_SILI_DEBUG
36:
37: #ifdef SILI_DEBUG
38: #define SILI_D_VERBOSE (1<<0)
39: #define SILI_D_INTR (1<<1)
40:
41: int silidebug = SILI_D_VERBOSE;
42:
43: #define DPRINTF(m, a...) do { if ((m) & silidebug) printf(a); } while (0)
44: #else
45: #define DPRINTF(m, a...)
46: #endif
47:
48: struct cfdriver sili_cd = {
49: NULL, "sili", DV_DULL
50: };
51:
52: /* wrapper around dma memory */
53: struct sili_dmamem {
54: bus_dmamap_t sdm_map;
55: bus_dma_segment_t sdm_seg;
56: size_t sdm_size;
57: caddr_t sdm_kva;
58: };
59: #define SILI_DMA_MAP(_sdm) ((_sdm)->sdm_map)
60: #define SILI_DMA_DVA(_sdm) ((_sdm)->sdm_map->dm_segs[0].ds_addr)
61: #define SILI_DMA_KVA(_sdm) ((void *)(_sdm)->sdm_kva)
62:
63: struct sili_dmamem *sili_dmamem_alloc(struct sili_softc *, bus_size_t,
64: bus_size_t);
65: void sili_dmamem_free(struct sili_softc *,
66: struct sili_dmamem *);
67:
68: /* per port goo */
69: struct sili_ccb;
70:
71: /* size of scratch space for use in error recovery. */
72: #define SILI_SCRATCH_LEN 512 /* must be at least 1 sector */
73:
74: struct sili_port {
75: struct sili_softc *sp_sc;
76: bus_space_handle_t sp_ioh;
77:
78: struct sili_ccb *sp_ccbs;
79: struct sili_dmamem *sp_cmds;
80: struct sili_dmamem *sp_scratch;
81:
82: TAILQ_HEAD(, sili_ccb) sp_free_ccbs;
83:
84: volatile u_int32_t sp_active;
85: TAILQ_HEAD(, sili_ccb) sp_active_ccbs;
86: TAILQ_HEAD(, sili_ccb) sp_deferred_ccbs;
87:
88: #ifdef SILI_DEBUG
89: char sp_name[16];
90: #define PORTNAME(_sp) ((_sp)->sp_name)
91: #else
92: #define PORTNAME(_sp) DEVNAME((_sp)->sp_sc)
93: #endif
94: };
95:
96: int sili_ports_alloc(struct sili_softc *);
97: void sili_ports_free(struct sili_softc *);
98:
99: /* ccb shizz */
100:
101: /*
102: * the dma memory for each command will be made up of a prb followed by
103: * 7 sgts, this is a neat 512 bytes.
104: */
105: #define SILI_CMD_LEN 512
106:
107: /*
108: * you can fit 22 sge's into 7 sgts and a prb:
109: * there's 1 sgl in an atapi prb (two in the ata one, but we cant over
110: * advertise), but that's needed for the chain element. you get three sges
111: * per sgt cos you lose the 4th sge for the chaining, but you keep it in
112: * the last sgt. so 3 x 6 + 4 is 22.
113: */
114: #define SILI_DMA_SEGS 22
115:
116: struct sili_ccb {
117: struct ata_xfer ccb_xa;
118:
119: void *ccb_cmd;
120: u_int64_t ccb_cmd_dva;
121: bus_dmamap_t ccb_dmamap;
122:
123: struct sili_port *ccb_port;
124:
125: TAILQ_ENTRY(sili_ccb) ccb_entry;
126: };
127:
128: int sili_ccb_alloc(struct sili_port *);
129: void sili_ccb_free(struct sili_port *);
130: struct sili_ccb *sili_get_ccb(struct sili_port *);
131: void sili_put_ccb(struct sili_ccb *);
132:
133: /* bus space ops */
134: u_int32_t sili_read(struct sili_softc *, bus_size_t);
135: void sili_write(struct sili_softc *, bus_size_t, u_int32_t);
136: u_int32_t sili_pread(struct sili_port *, bus_size_t);
137: void sili_pwrite(struct sili_port *, bus_size_t, u_int32_t);
138: int sili_pwait_eq(struct sili_port *, bus_size_t,
139: u_int32_t, u_int32_t, int);
140: int sili_pwait_ne(struct sili_port *, bus_size_t,
141: u_int32_t, u_int32_t, int);
142:
143: /* command handling */
144: void sili_post_direct(struct sili_port *, u_int,
145: void *, size_t buflen);
146: void sili_post_indirect(struct sili_port *,
147: struct sili_ccb *);
148: void sili_pread_fis(struct sili_port *, u_int,
149: struct ata_fis_d2h *);
150: u_int32_t sili_signature(struct sili_port *, u_int);
151: int sili_load(struct sili_ccb *, struct sili_sge *, int);
152: void sili_unload(struct sili_ccb *);
153: int sili_poll(struct sili_ccb *, int, void (*)(void *));
154: void sili_start(struct sili_port *, struct sili_ccb *);
155: int sili_read_ncq_error(struct sili_port *, int *);
156:
157: /* port interrupt handler */
158: u_int32_t sili_port_intr(struct sili_port *, int);
159:
160: /* atascsi interface */
161: int sili_ata_probe(void *, int);
162: struct ata_xfer *sili_ata_get_xfer(void *, int);
163: void sili_ata_put_xfer(struct ata_xfer *);
164: int sili_ata_cmd(struct ata_xfer *);
165:
166: struct atascsi_methods sili_atascsi_methods = {
167: sili_ata_probe,
168: sili_ata_get_xfer,
169: sili_ata_cmd
170: };
171:
172: /* completion paths */
173: void sili_ata_cmd_done(struct sili_ccb *, int);
174: void sili_ata_cmd_timeout(void *);
175:
176: int
177: sili_attach(struct sili_softc *sc)
178: {
179: struct atascsi_attach_args aaa;
180:
181: printf("\n");
182:
183: if (sili_ports_alloc(sc) != 0) {
184: /* error already printed by sili_port_alloc */
185: return (1);
186: }
187:
188: /* bounce the controller */
189: sili_write(sc, SILI_REG_GC, SILI_REG_GC_GR);
190: sili_write(sc, SILI_REG_GC, 0x0);
191:
192: bzero(&aaa, sizeof(aaa));
193: aaa.aaa_cookie = sc;
194: aaa.aaa_methods = &sili_atascsi_methods;
195: aaa.aaa_minphys = minphys;
196: aaa.aaa_nports = sc->sc_nports;
197: aaa.aaa_ncmds = SILI_MAX_CMDS;
198: aaa.aaa_capability = ASAA_CAP_NCQ;
199:
200: sc->sc_atascsi = atascsi_attach(&sc->sc_dev, &aaa);
201:
202: return (0);
203: }
204:
205: int
206: sili_detach(struct sili_softc *sc, int flags)
207: {
208: return (0);
209: }
210:
211: u_int32_t
212: sili_port_intr(struct sili_port *sp, int timeout_slot)
213: {
214: u_int32_t is, pss_saved, pss_masked;
215: u_int32_t processed = 0, need_restart = 0;
216: int slot;
217: struct sili_ccb *ccb;
218:
219: is = sili_pread(sp, SILI_PREG_IS);
220: pss_saved = sili_pread(sp, SILI_PREG_PSS); /* reading acks CMDCOMP */
221:
222: #ifdef SILI_DEBUG
223: if ((pss_saved & SILI_PREG_PSS_ALL_SLOTS) != sp->sp_active ||
224: ((is >> 16) & ~SILI_PREG_IS_CMDCOMP)) {
225: DPRINTF(SILI_D_INTR, "%s: IS: 0x%08x (0x%b), PSS: %08x, "
226: "active: %08x\n", PORTNAME(sp), is, is >> 16, SILI_PFMT_IS,
227: pss_saved, sp->sp_active);
228: }
229: #endif
230:
231: /* Only interested in slot status bits. */
232: pss_saved &= SILI_PREG_PSS_ALL_SLOTS;
233:
234: if (is & SILI_PREG_IS_CMDERR) {
235: int err_slot, err_code;
236: u_int32_t sactive = 0;
237:
238: sili_pwrite(sp, SILI_PREG_IS, SILI_PREG_IS_CMDERR);
239: err_slot = SILI_PREG_PCS_ACTIVE(sili_pread(sp, SILI_PREG_PCS));
240: err_code = sili_pread(sp, SILI_PREG_CE);
241: ccb = &sp->sp_ccbs[err_slot];
242:
243: switch (err_code) {
244: case SILI_PREG_CE_DEVICEERROR:
245: case SILI_PREG_CE_DATAFISERROR:
246: /* Extract error from command slot in LRAM. */
247: sili_pread_fis(sp, err_slot, &ccb->ccb_xa.rfis);
248: break;
249:
250: case SILI_PREG_CE_SDBERROR:
251: /* No NCQ commands active? Treat as a normal error. */
252: sactive = sili_pread(sp, SILI_PREG_SACT);/* XXX Pmult */
253: if (sactive == 0)
254: break;
255:
256: /* Extract real NCQ error slot & RFIS from log page. */
257: if (!sili_read_ncq_error(sp, &err_slot)) {
258: /* got real err_slot */
259: ccb = &sp->sp_ccbs[err_slot];
260: break;
261: }
262:
263: /* failed to get error or not NCQ */
264:
265: /* FALLTHROUGH */
266: default:
267: /* All other error types are fatal. */
268: printf("%s: fatal error (%d), aborting active slots "
269: "(%08x) and resetting device.\n", PORTNAME(sp),
270: err_code, pss_saved);
271: while (pss_saved) {
272: slot = ffs(pss_saved) - 1;
273: pss_saved &= ~(1 << slot);
274:
275: ccb = &sp->sp_ccbs[slot];
276: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
277: ccb->ccb_xa.state = ATA_S_ERROR;
278: }
279: need_restart = SILI_PREG_PCS_DEVRESET;
280: goto fatal;
281: }
282:
283: DPRINTF(SILI_D_VERBOSE, "%s: %serror, code %d, slot %d, "
284: "active %08x\n", PORTNAME(sp), sactive ? "NCQ " : "",
285: err_code, err_slot, sp->sp_active);
286:
287: /* Clear the failed commmand in saved PSS so cmd_done runs. */
288: pss_saved &= ~(1 << err_slot);
289:
290: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
291: ccb->ccb_xa.state = ATA_S_ERROR;
292:
293: need_restart = SILI_PREG_PCS_PORTINIT;
294: }
295: fatal:
296:
297: /* Process command timeout request only if command is still active. */
298: if (timeout_slot >= 0 && (pss_saved & (1 << timeout_slot))) {
299: DPRINTF(SILI_D_VERBOSE, "%s: timing out slot %d, active %08x\n",
300: PORTNAME(sp), timeout_slot, sp->sp_active);
301:
302: /* Clear the failed commmand in saved PSS so cmd_done runs. */
303: pss_saved &= ~(1 << timeout_slot);
304:
305: ccb = &sp->sp_ccbs[timeout_slot];
306: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
307: ccb->ccb_xa.state = ATA_S_TIMEOUT;
308:
309: /* Reset device to abort all commands (including this one). */
310: need_restart = SILI_PREG_PCS_DEVRESET;
311: }
312:
313: /* Command slot is complete if its bit in PSS is 0 but 1 in active. */
314: pss_masked = ~pss_saved & sp->sp_active;
315: while (pss_masked) {
316: slot = ffs(pss_masked) - 1;
317: ccb = &sp->sp_ccbs[slot];
318: pss_masked &= ~(1 << slot);
319:
320: DPRINTF(SILI_D_INTR, "%s: slot %d is complete%s\n",
321: PORTNAME(sp), slot, ccb->ccb_xa.state == ATA_S_ERROR ?
322: " (error)" : (ccb->ccb_xa.state == ATA_S_TIMEOUT ?
323: " (timeout)" : ""));
324:
325: sili_ata_cmd_done(ccb, need_restart);
326:
327: processed |= 1 << slot;
328: }
329:
330: if (need_restart) {
331: /* Re-enable transfers on port. */
332: sili_pwrite(sp, SILI_PREG_PCS, need_restart);
333: if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
334: SILI_PREG_PCS_PORTRDY, 1000)) {
335: printf("%s: couldn't restart port after error\n",
336: PORTNAME(sp));
337: }
338:
339: /* Restart CCBs in the order they were originally queued. */
340: pss_masked = pss_saved;
341: TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
342: DPRINTF(SILI_D_VERBOSE, "%s: restarting slot %d "
343: "after error, state %02x\n", PORTNAME(sp),
344: ccb->ccb_xa.tag, ccb->ccb_xa.state);
345: if (!(pss_masked & (1 << ccb->ccb_xa.tag))) {
346: panic("sili_intr: slot %d not active in "
347: "pss_masked: %08x, state %02x",
348: ccb->ccb_xa.tag, pss_masked,
349: ccb->ccb_xa.state);
350: }
351: pss_masked &= ~(1 << ccb->ccb_xa.tag);
352:
353: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
354: sili_post_indirect(sp, ccb);
355: }
356: KASSERT(pss_masked == 0);
357:
358: /*
359: * Finally, run atascsi completion for any finished CCBs. If
360: * we had run these during cmd_done above, any ccbs that their
361: * completion generated would have been activated out of order.
362: */
363: while ((ccb = TAILQ_FIRST(&sp->sp_deferred_ccbs)) != NULL) {
364: TAILQ_REMOVE(&sp->sp_deferred_ccbs, ccb, ccb_entry);
365:
366: KASSERT(ccb->ccb_xa.state == ATA_S_COMPLETE ||
367: ccb->ccb_xa.state == ATA_S_ERROR ||
368: ccb->ccb_xa.state == ATA_S_TIMEOUT);
369: ccb->ccb_xa.complete(&ccb->ccb_xa);
370: }
371: }
372:
373: return (processed);
374: }
375:
376: int
377: sili_intr(void *arg)
378: {
379: struct sili_softc *sc = arg;
380: u_int32_t is;
381: int port;
382:
383: is = sili_read(sc, SILI_REG_GIS);
384: if (is == 0)
385: return (0);
386: sili_write(sc, SILI_REG_GIS, is);
387: DPRINTF(SILI_D_INTR, "sili_intr, GIS: %08x\n", is);
388:
389: while (is & SILI_REG_GIS_PIS_MASK) {
390: port = ffs(is) - 1;
391: sili_port_intr(&sc->sc_ports[port], -1);
392: is &= ~(1 << port);
393: }
394:
395: return (1);
396: }
397:
398: int
399: sili_ports_alloc(struct sili_softc *sc)
400: {
401: struct sili_port *sp;
402: int i;
403:
404: sc->sc_ports = malloc(sizeof(struct sili_port) * sc->sc_nports,
405: M_DEVBUF, M_WAITOK);
406: bzero(sc->sc_ports, sizeof(struct sili_port) * sc->sc_nports);
407:
408: for (i = 0; i < sc->sc_nports; i++) {
409: sp = &sc->sc_ports[i];
410:
411: sp->sp_sc = sc;
412: #ifdef SILI_DEBUG
413: snprintf(sp->sp_name, sizeof(sp->sp_name), "%s.%d",
414: DEVNAME(sc), i);
415: #endif
416: if (bus_space_subregion(sc->sc_iot_port, sc->sc_ioh_port,
417: SILI_PORT_OFFSET(i), SILI_PORT_SIZE, &sp->sp_ioh) != 0) {
418: printf("%s: unable to create register window "
419: "for port %d\n", DEVNAME(sc), i);
420: goto freeports;
421: }
422: }
423:
424: return (0);
425:
426: freeports:
427: /* bus_space(9) says subregions dont have to be freed */
428: free(sp, M_DEVBUF);
429: sc->sc_ports = NULL;
430: return (1);
431: }
432:
433: void
434: sili_ports_free(struct sili_softc *sc)
435: {
436: struct sili_port *sp;
437: int i;
438:
439: for (i = 0; i < sc->sc_nports; i++) {
440: sp = &sc->sc_ports[i];
441:
442: if (sp->sp_ccbs != NULL)
443: sili_ccb_free(sp);
444: }
445:
446: /* bus_space(9) says subregions dont have to be freed */
447: free(sc->sc_ports, M_DEVBUF);
448: sc->sc_ports = NULL;
449: }
450:
451: int
452: sili_ccb_alloc(struct sili_port *sp)
453: {
454: struct sili_softc *sc = sp->sp_sc;
455: struct sili_ccb *ccb;
456: struct sili_prb *prb;
457: int i;
458:
459: TAILQ_INIT(&sp->sp_free_ccbs);
460: TAILQ_INIT(&sp->sp_active_ccbs);
461: TAILQ_INIT(&sp->sp_deferred_ccbs);
462:
463: sp->sp_ccbs = malloc(sizeof(struct sili_ccb) * SILI_MAX_CMDS,
464: M_DEVBUF, M_WAITOK);
465: sp->sp_cmds = sili_dmamem_alloc(sc, SILI_CMD_LEN * SILI_MAX_CMDS,
466: SILI_PRB_ALIGN);
467: if (sp->sp_cmds == NULL)
468: goto free_ccbs;
469: sp->sp_scratch = sili_dmamem_alloc(sc, SILI_SCRATCH_LEN, PAGE_SIZE);
470: if (sp->sp_scratch == NULL)
471: goto free_cmds;
472:
473: bzero(sp->sp_ccbs, sizeof(struct sili_ccb) * SILI_MAX_CMDS);
474:
475: for (i = 0; i < SILI_MAX_CMDS; i++) {
476: ccb = &sp->sp_ccbs[i];
477: ccb->ccb_port = sp;
478: ccb->ccb_cmd = SILI_DMA_KVA(sp->sp_cmds) + i * SILI_CMD_LEN;
479: ccb->ccb_cmd_dva = SILI_DMA_DVA(sp->sp_cmds) + i * SILI_CMD_LEN;
480: if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, SILI_DMA_SEGS,
481: MAXPHYS, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
482: &ccb->ccb_dmamap) != 0)
483: goto free_scratch;
484:
485: prb = ccb->ccb_cmd;
486: ccb->ccb_xa.fis = (struct ata_fis_h2d *)&prb->fis;
487: ccb->ccb_xa.packetcmd = ((struct sili_prb_packet *)prb)->cdb;
488: ccb->ccb_xa.tag = i;
489: ccb->ccb_xa.ata_put_xfer = sili_ata_put_xfer;
490: ccb->ccb_xa.state = ATA_S_COMPLETE;
491:
492: sili_put_ccb(ccb);
493: }
494:
495: return (0);
496:
497: free_scratch:
498: sili_dmamem_free(sc, sp->sp_scratch);
499: free_cmds:
500: sili_dmamem_free(sc, sp->sp_cmds);
501: free_ccbs:
502: sili_ccb_free(sp);
503: return (1);
504: }
505:
506: void
507: sili_ccb_free(struct sili_port *sp)
508: {
509: struct sili_softc *sc = sp->sp_sc;
510: struct sili_ccb *ccb;
511:
512: while ((ccb = sili_get_ccb(sp)) != NULL)
513: bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
514:
515: free(sp->sp_ccbs, M_DEVBUF);
516: sp->sp_ccbs = NULL;
517: }
518:
519: struct sili_ccb *
520: sili_get_ccb(struct sili_port *sp)
521: {
522: struct sili_ccb *ccb;
523:
524: ccb = TAILQ_FIRST(&sp->sp_free_ccbs);
525: if (ccb != NULL) {
526: KASSERT(ccb->ccb_xa.state == ATA_S_PUT);
527: TAILQ_REMOVE(&sp->sp_free_ccbs, ccb, ccb_entry);
528: ccb->ccb_xa.state = ATA_S_SETUP;
529: }
530:
531: return (ccb);
532: }
533:
534: void
535: sili_put_ccb(struct sili_ccb *ccb)
536: {
537: struct sili_port *sp = ccb->ccb_port;
538:
539: #ifdef DIAGNOSTIC
540: if (ccb->ccb_xa.state != ATA_S_COMPLETE &&
541: ccb->ccb_xa.state != ATA_S_TIMEOUT &&
542: ccb->ccb_xa.state != ATA_S_ERROR) {
543: printf("%s: invalid ata_xfer state %02x in sili_put_ccb, "
544: "slot %d\n", PORTNAME(sp), ccb->ccb_xa.state,
545: ccb->ccb_xa.tag);
546: }
547: #endif
548:
549: ccb->ccb_xa.state = ATA_S_PUT;
550: TAILQ_INSERT_TAIL(&sp->sp_free_ccbs, ccb, ccb_entry);
551: }
552:
553: struct sili_dmamem *
554: sili_dmamem_alloc(struct sili_softc *sc, bus_size_t size, bus_size_t align)
555: {
556: struct sili_dmamem *sdm;
557: int nsegs;
558:
559: sdm = malloc(sizeof(struct sili_dmamem), M_DEVBUF, M_WAITOK);
560: bzero(sdm, sizeof(struct sili_dmamem));
561: sdm->sdm_size = size;
562:
563: if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
564: BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &sdm->sdm_map) != 0)
565: goto sdmfree;
566:
567: if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &sdm->sdm_seg,
568: 1, &nsegs, BUS_DMA_NOWAIT) != 0)
569: goto destroy;
570:
571: if (bus_dmamem_map(sc->sc_dmat, &sdm->sdm_seg, nsegs, size,
572: &sdm->sdm_kva, BUS_DMA_NOWAIT) != 0)
573: goto free;
574:
575: if (bus_dmamap_load(sc->sc_dmat, sdm->sdm_map, sdm->sdm_kva, size,
576: NULL, BUS_DMA_NOWAIT) != 0)
577: goto unmap;
578:
579: bzero(sdm->sdm_kva, size);
580:
581: return (sdm);
582:
583: unmap:
584: bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, size);
585: free:
586: bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
587: destroy:
588: bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
589: sdmfree:
590: free(sdm, M_DEVBUF);
591:
592: return (NULL);
593: }
594:
595: void
596: sili_dmamem_free(struct sili_softc *sc, struct sili_dmamem *sdm)
597: {
598: bus_dmamap_unload(sc->sc_dmat, sdm->sdm_map);
599: bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, sdm->sdm_size);
600: bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
601: bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
602: free(sdm, M_DEVBUF);
603: }
604:
605: u_int32_t
606: sili_read(struct sili_softc *sc, bus_size_t r)
607: {
608: u_int32_t rv;
609:
610: bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
611: BUS_SPACE_BARRIER_READ);
612: rv = bus_space_read_4(sc->sc_iot_global, sc->sc_ioh_global, r);
613:
614: return (rv);
615: }
616:
617: void
618: sili_write(struct sili_softc *sc, bus_size_t r, u_int32_t v)
619: {
620: bus_space_write_4(sc->sc_iot_global, sc->sc_ioh_global, r, v);
621: bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
622: BUS_SPACE_BARRIER_WRITE);
623: }
624:
625: u_int32_t
626: sili_pread(struct sili_port *sp, bus_size_t r)
627: {
628: u_int32_t rv;
629:
630: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
631: BUS_SPACE_BARRIER_READ);
632: rv = bus_space_read_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r);
633:
634: return (rv);
635: }
636:
637: void
638: sili_pwrite(struct sili_port *sp, bus_size_t r, u_int32_t v)
639: {
640: bus_space_write_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, v);
641: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
642: BUS_SPACE_BARRIER_WRITE);
643: }
644:
645: int
646: sili_pwait_eq(struct sili_port *sp, bus_size_t r, u_int32_t mask,
647: u_int32_t value, int timeout)
648: {
649: while ((sili_pread(sp, r) & mask) != value) {
650: if (timeout == 0)
651: return (0);
652:
653: delay(1000);
654: timeout--;
655: }
656:
657: return (1);
658: }
659:
660: int
661: sili_pwait_ne(struct sili_port *sp, bus_size_t r, u_int32_t mask,
662: u_int32_t value, int timeout)
663: {
664: while ((sili_pread(sp, r) & mask) == value) {
665: if (timeout == 0)
666: return (0);
667:
668: delay(1000);
669: timeout--;
670: }
671:
672: return (1);
673: }
674:
675: void
676: sili_post_direct(struct sili_port *sp, u_int slot, void *buf, size_t buflen)
677: {
678: bus_size_t r = SILI_PREG_SLOT(slot);
679:
680: #ifdef DIAGNOSTIC
681: if (buflen != 64 && buflen != 128)
682: panic("sili_pcopy: buflen of %d is not 64 or 128", buflen);
683: #endif
684:
685: bus_space_write_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
686: buf, buflen);
687: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, buflen,
688: BUS_SPACE_BARRIER_WRITE);
689:
690: sili_pwrite(sp, SILI_PREG_FIFO, slot);
691: }
692:
693: void
694: sili_pread_fis(struct sili_port *sp, u_int slot, struct ata_fis_d2h *fis)
695: {
696: bus_size_t r = SILI_PREG_SLOT(slot) + 8;
697:
698: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
699: sizeof(struct ata_fis_d2h), BUS_SPACE_BARRIER_READ);
700: bus_space_read_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
701: fis, sizeof(struct ata_fis_d2h));
702: }
703:
704: void
705: sili_post_indirect(struct sili_port *sp, struct sili_ccb *ccb)
706: {
707: sili_pwrite(sp, SILI_PREG_CAR_LO(ccb->ccb_xa.tag),
708: (u_int32_t)ccb->ccb_cmd_dva);
709: sili_pwrite(sp, SILI_PREG_CAR_HI(ccb->ccb_xa.tag),
710: (u_int32_t)(ccb->ccb_cmd_dva >> 32));
711: }
712:
713: u_int32_t
714: sili_signature(struct sili_port *sp, u_int slot)
715: {
716: u_int32_t sig_hi, sig_lo;
717:
718: sig_hi = sili_pread(sp, SILI_PREG_SIG_HI(slot));
719: sig_hi <<= SILI_PREG_SIG_HI_SHIFT;
720: sig_lo = sili_pread(sp, SILI_PREG_SIG_LO(slot));
721: sig_lo &= SILI_PREG_SIG_LO_MASK;
722:
723: return (sig_hi | sig_lo);
724: }
725:
726: int
727: sili_ata_probe(void *xsc, int port)
728: {
729: struct sili_softc *sc = xsc;
730: struct sili_port *sp = &sc->sc_ports[port];
731: struct sili_prb_softreset sreset;
732: u_int32_t signature;
733: int port_type;
734:
735: sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_PORTRESET);
736: sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_A32B);
737:
738: if (!sili_pwait_eq(sp, SILI_PREG_SSTS, SATA_SStatus_DET,
739: SATA_SStatus_DET_DEV, 1000))
740: return (ATA_PORT_T_NONE);
741:
742: DPRINTF(SILI_D_VERBOSE, "%s: SSTS 0x%08x\n", PORTNAME(sp),
743: sili_pread(sp, SILI_PREG_SSTS));
744:
745: bzero(&sreset, sizeof(sreset));
746: sreset.control = htole16(SILI_PRB_SOFT_RESET | SILI_PRB_INTERRUPT_MASK);
747: /* XXX sreset fis pmp field */
748:
749: /* we use slot 0 */
750: sili_post_direct(sp, 0, &sreset, sizeof(sreset));
751: if (!sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000)) {
752: DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for soft "
753: "reset\n", PORTNAME(sp));
754: return (ATA_PORT_T_NONE);
755: }
756:
757: /* Read device signature from command slot. */
758: signature = sili_signature(sp, 0);
759:
760: DPRINTF(SILI_D_VERBOSE, "%s: signature 0x%08x\n", PORTNAME(sp),
761: signature);
762:
763: switch (signature) {
764: case SATA_SIGNATURE_DISK:
765: port_type = ATA_PORT_T_DISK;
766: break;
767: case SATA_SIGNATURE_ATAPI:
768: port_type = ATA_PORT_T_ATAPI;
769: break;
770: case SATA_SIGNATURE_PORT_MULTIPLIER:
771: default:
772: return (ATA_PORT_T_NONE);
773: }
774:
775: /* allocate port resources */
776: if (sili_ccb_alloc(sp) != 0)
777: return (ATA_PORT_T_NONE);
778:
779: /* enable port interrupts */
780: sili_write(sc, SILI_REG_GC, sili_read(sc, SILI_REG_GC) | 1 << port);
781: sili_pwrite(sp, SILI_PREG_IES, SILI_PREG_IE_CMDERR |
782: SILI_PREG_IE_CMDCOMP);
783:
784: return (port_type);
785: }
786:
787: int
788: sili_ata_cmd(struct ata_xfer *xa)
789: {
790: struct sili_ccb *ccb = (struct sili_ccb *)xa;
791: struct sili_port *sp = ccb->ccb_port;
792: struct sili_softc *sc = sp->sp_sc;
793: struct sili_prb_ata *ata;
794: struct sili_prb_packet *atapi;
795: struct sili_sge *sgl;
796: int sgllen;
797: int s;
798:
799: KASSERT(xa->state == ATA_S_SETUP);
800:
801: if (xa->flags & ATA_F_PACKET) {
802: atapi = ccb->ccb_cmd;
803:
804: if (xa->flags & ATA_F_WRITE)
805: atapi->control = htole16(SILI_PRB_PACKET_WRITE);
806: else
807: atapi->control = htole16(SILI_PRB_PACKET_READ);
808:
809: sgl = atapi->sgl;
810: sgllen = sizeofa(atapi->sgl);
811: } else {
812: ata = ccb->ccb_cmd;
813:
814: ata->control = 0;
815:
816: sgl = ata->sgl;
817: sgllen = sizeofa(ata->sgl);
818: }
819:
820: if (sili_load(ccb, sgl, sgllen) != 0)
821: goto failcmd;
822:
823: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
824: xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_PREWRITE);
825:
826: timeout_set(&xa->stimeout, sili_ata_cmd_timeout, ccb);
827:
828: xa->state = ATA_S_PENDING;
829:
830: if (xa->flags & ATA_F_POLL) {
831: sili_poll(ccb, xa->timeout, sili_ata_cmd_timeout);
832: return (ATA_COMPLETE);
833: }
834:
835: timeout_add(&xa->stimeout, (xa->timeout * hz) / 1000);
836:
837: s = splbio();
838: sili_start(sp, ccb);
839: splx(s);
840: return (ATA_QUEUED);
841:
842: failcmd:
843: s = splbio();
844: xa->state = ATA_S_ERROR;
845: xa->complete(xa);
846: splx(s);
847: return (ATA_ERROR);
848: }
849:
850: void
851: sili_ata_cmd_done(struct sili_ccb *ccb, int defer_completion)
852: {
853: struct sili_port *sp = ccb->ccb_port;
854: struct sili_softc *sc = sp->sp_sc;
855: struct ata_xfer *xa = &ccb->ccb_xa;
856:
857: splassert(IPL_BIO);
858:
859: timeout_del(&xa->stimeout);
860:
861: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
862: xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_POSTWRITE);
863:
864: sili_unload(ccb);
865:
866: TAILQ_REMOVE(&sp->sp_active_ccbs, ccb, ccb_entry);
867: sp->sp_active &= ~(1 << xa->tag);
868:
869: if (xa->state == ATA_S_ONCHIP)
870: xa->state = ATA_S_COMPLETE;
871: #ifdef DIAGNOSTIC
872: else if (xa->state != ATA_S_ERROR && xa->state != ATA_S_TIMEOUT)
873: printf("%s: invalid ata_xfer state %02x in sili_ata_cmd_done, "
874: "slot %d\n", PORTNAME(sp), xa->state, xa->tag);
875: #endif
876: if (defer_completion)
877: TAILQ_INSERT_TAIL(&sp->sp_deferred_ccbs, ccb, ccb_entry);
878: else if (xa->state == ATA_S_COMPLETE)
879: xa->complete(xa);
880: #ifdef DIAGNOSTIC
881: else
882: printf("%s: completion not deferred, but xa->state is %02x?\n",
883: PORTNAME(sp), xa->state);
884: #endif
885: }
886:
887: void
888: sili_ata_cmd_timeout(void *xccb)
889: {
890: struct sili_ccb *ccb = xccb;
891: struct sili_port *sp = ccb->ccb_port;
892: int s;
893:
894: s = splbio();
895: sili_port_intr(sp, ccb->ccb_xa.tag);
896: splx(s);
897: }
898:
899: int
900: sili_load(struct sili_ccb *ccb, struct sili_sge *sgl, int sgllen)
901: {
902: struct sili_port *sp = ccb->ccb_port;
903: struct sili_softc *sc = sp->sp_sc;
904: struct ata_xfer *xa = &ccb->ccb_xa;
905: struct sili_sge *nsge = sgl, *ce = NULL;
906: bus_dmamap_t dmap = ccb->ccb_dmamap;
907: u_int64_t addr;
908: int error;
909: int i;
910:
911: if (xa->datalen == 0)
912: return (0);
913:
914: error = bus_dmamap_load(sc->sc_dmat, dmap, xa->data, xa->datalen, NULL,
915: (xa->flags & ATA_F_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
916: if (error != 0) {
917: printf("%s: error %d loading dmamap\n", PORTNAME(sp), error);
918: return (1);
919: }
920:
921: if (dmap->dm_nsegs > sgllen)
922: ce = &sgl[sgllen - 1];
923:
924: for (i = 0; i < dmap->dm_nsegs; i++) {
925: if (nsge == ce) {
926: nsge++;
927:
928: addr = ccb->ccb_cmd_dva;
929: addr += ((u_int8_t *)nsge - (u_int8_t *)ccb->ccb_cmd);
930:
931: ce->addr_lo = htole32((u_int32_t)addr);
932: ce->addr_hi = htole32((u_int32_t)(addr >> 32));
933: ce->flags = htole32(SILI_SGE_LNK);
934:
935: if ((dmap->dm_nsegs - i) > SILI_SGT_SGLLEN)
936: ce += SILI_SGT_SGLLEN;
937: else
938: ce = NULL;
939: }
940:
941: sgl = nsge;
942:
943: addr = dmap->dm_segs[i].ds_addr;
944: sgl->addr_lo = htole32((u_int32_t)addr);
945: sgl->addr_hi = htole32((u_int32_t)(addr >> 32));
946: sgl->data_count = htole32(dmap->dm_segs[i].ds_len);
947: sgl->flags = 0;
948:
949: nsge++;
950: }
951: sgl->flags |= htole32(SILI_SGE_TRM);
952:
953: bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
954: (xa->flags & ATA_F_READ) ? BUS_DMASYNC_PREREAD :
955: BUS_DMASYNC_PREWRITE);
956:
957: return (0);
958: }
959:
960: void
961: sili_unload(struct sili_ccb *ccb)
962: {
963: struct sili_port *sp = ccb->ccb_port;
964: struct sili_softc *sc = sp->sp_sc;
965: struct ata_xfer *xa = &ccb->ccb_xa;
966: bus_dmamap_t dmap = ccb->ccb_dmamap;
967:
968: if (xa->datalen == 0)
969: return;
970:
971: bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
972: (xa->flags & ATA_F_READ) ? BUS_DMASYNC_POSTREAD :
973: BUS_DMASYNC_POSTWRITE);
974: bus_dmamap_unload(sc->sc_dmat, dmap);
975:
976: if (xa->flags & ATA_F_READ)
977: xa->resid = xa->datalen - sili_pread(sp,
978: SILI_PREG_RX_COUNT(xa->tag));
979: else
980: xa->resid = 0;
981: }
982:
983: int
984: sili_poll(struct sili_ccb *ccb, int timeout, void (*timeout_fn)(void *))
985: {
986: struct sili_port *sp = ccb->ccb_port;
987: int s;
988:
989: s = splbio();
990: sili_start(sp, ccb);
991: do {
992: if (sili_port_intr(sp, -1) & (1 << ccb->ccb_xa.tag)) {
993: splx(s);
994: return (0);
995: }
996:
997: delay(1000);
998: } while (--timeout > 0);
999:
1000: /* Run timeout while at splbio, otherwise sili_intr could interfere. */
1001: if (timeout_fn != NULL)
1002: timeout_fn(ccb);
1003:
1004: splx(s);
1005:
1006: return (1);
1007: }
1008:
1009: void
1010: sili_start(struct sili_port *sp, struct sili_ccb *ccb)
1011: {
1012: int slot = ccb->ccb_xa.tag;
1013:
1014: splassert(IPL_BIO);
1015: KASSERT(ccb->ccb_xa.state == ATA_S_PENDING);
1016:
1017: TAILQ_INSERT_TAIL(&sp->sp_active_ccbs, ccb, ccb_entry);
1018: sp->sp_active |= 1 << slot;
1019: ccb->ccb_xa.state = ATA_S_ONCHIP;
1020:
1021: sili_post_indirect(sp, ccb);
1022: }
1023:
1024: int
1025: sili_read_ncq_error(struct sili_port *sp, int *err_slotp)
1026: {
1027: struct sili_softc *sc = sp->sp_sc;
1028: struct sili_prb_ata read_10h;
1029: u_int64_t addr;
1030: struct ata_fis_h2d *fis;
1031: struct ata_log_page_10h *log;
1032: struct sili_ccb *ccb;
1033: int rc;
1034:
1035: sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTINIT);
1036: if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
1037: SILI_PREG_PCS_PORTRDY, 1000)) {
1038: printf("%s: couldn't ready port during log page read\n",
1039: PORTNAME(sp));
1040: return (1);
1041: }
1042:
1043: /* READ LOG EXT 10h into scratch space */
1044: bzero(&read_10h, sizeof(read_10h));
1045: read_10h.control = htole16(SILI_PRB_INTERRUPT_MASK);
1046:
1047: addr = SILI_DMA_DVA(sp->sp_scratch);
1048: read_10h.sgl[0].addr_lo = htole32((u_int32_t)addr);
1049: read_10h.sgl[0].addr_hi = htole32((u_int32_t)(addr >> 32));
1050: read_10h.sgl[0].data_count = htole32(512);
1051: read_10h.sgl[0].flags = htole32(SILI_SGE_TRM);
1052:
1053: fis = (struct ata_fis_h2d *)read_10h.fis;
1054: fis->type = ATA_FIS_TYPE_H2D;
1055: fis->flags = ATA_H2D_FLAGS_CMD; /* XXX fis pmp field */
1056: fis->command = ATA_C_READ_LOG_EXT;
1057: fis->lba_low = 0x10; /* queued error log page (10h) */
1058: fis->sector_count = 1; /* number of sectors (1) */
1059: fis->sector_count_exp = 0;
1060: fis->lba_mid = 0; /* starting offset */
1061: fis->lba_mid_exp = 0;
1062: fis->device = 0;
1063:
1064: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
1065: 512, BUS_DMASYNC_PREREAD);
1066:
1067: /* issue read and poll for completion */
1068: sili_post_direct(sp, 0, &read_10h, sizeof(read_10h));
1069: rc = sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000);
1070:
1071: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
1072: 512, BUS_DMASYNC_POSTREAD);
1073:
1074: if (!rc) {
1075: DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for log "
1076: "page read\n", PORTNAME(sp));
1077: return (1);
1078: }
1079:
1080: /* Extract failed register set and tags from the scratch space. */
1081: log = (struct ata_log_page_10h *)SILI_DMA_KVA(sp->sp_scratch);
1082: if (ISSET(log->err_regs.type, ATA_LOG_10H_TYPE_NOTQUEUED)) {
1083: /* Not queued bit was set - wasn't an NCQ error? */
1084: printf("%s: read NCQ error page, but not an NCQ error?\n",
1085: PORTNAME(sp));
1086: return (1);
1087: }
1088:
1089: /* Copy back the log record as a D2H register FIS. */
1090: *err_slotp = log->err_regs.type & ATA_LOG_10H_TYPE_TAG_MASK;
1091:
1092: ccb = &sp->sp_ccbs[*err_slotp];
1093: memcpy(&ccb->ccb_xa.rfis, &log->err_regs, sizeof(struct ata_fis_d2h));
1094: ccb->ccb_xa.rfis.type = ATA_FIS_TYPE_D2H;
1095: ccb->ccb_xa.rfis.flags = 0;
1096:
1097: return (0);
1098: }
1099:
1100: struct ata_xfer *
1101: sili_ata_get_xfer(void *xsc, int port)
1102: {
1103: struct sili_softc *sc = xsc;
1104: struct sili_port *sp = &sc->sc_ports[port];
1105: struct sili_ccb *ccb;
1106:
1107: ccb = sili_get_ccb(sp);
1108: if (ccb == NULL) {
1109: printf("sili_ata_get_xfer: NULL ccb\n");
1110: return (NULL);
1111: }
1112:
1113: bzero(ccb->ccb_cmd, SILI_CMD_LEN);
1114:
1115: return ((struct ata_xfer *)ccb);
1116: }
1117:
1118: void
1119: sili_ata_put_xfer(struct ata_xfer *xa)
1120: {
1121: struct sili_ccb *ccb = (struct sili_ccb *)xa;
1122:
1123: sili_put_ccb(ccb);
1124: }
CVSweb