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