xref: /titanic_44/usr/src/uts/common/io/chxge/glue.c (revision 55553f719b521a0bb4deab6efc944cd30c1a56aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * This file is part of the Chelsio T1 Ethernet driver.
29  *
30  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
31  */
32 
33 /*
34  * Solaris support routines for common code part of
35  * Chelsio PCI Ethernet Driver.
36  */
37 
38 #pragma ident	"%Z%%M%	%I%	%E% SMI"
39 
40 #include <sys/types.h>
41 #include <sys/conf.h>
42 #include <sys/stropts.h>
43 #include <sys/stream.h>
44 #include <sys/strlog.h>
45 #include <sys/kmem.h>
46 #include <sys/stat.h>
47 #include <sys/kstat.h>
48 #include <sys/modctl.h>
49 #include <sys/errno.h>
50 #include <sys/varargs.h>
51 #include <sys/ddi.h>
52 #include <sys/sunddi.h>
53 #include <sys/dlpi.h>
54 #include <sys/ethernet.h>
55 #include <sys/strsun.h>
56 #include "ostypes.h"
57 #undef OFFSET
58 #include "common.h"
59 #include <sys/gld.h>
60 #include "oschtoe.h"
61 #include "ch.h"			/* Chelsio Driver specific parameters */
62 #include "sge.h"
63 #include "regs.h"
64 
65 /*
66  * Device specific.
67  */
68 struct pe_reg {
69 	uint32_t cmd;
70 	uint32_t addr;
71 	union {
72 		uint32_t v32;
73 		uint64_t v64;
74 	}vv;
75 	union {
76 		uint32_t m32;
77 		uint64_t m64;
78 	}mm;
79 };
80 #define	pe_reg_val vv.v32
81 #define	pe_opt_val vv.v64
82 #define	pe_mask32  mm.m32
83 #define	pe_mask64  mm.m64
84 
85 struct toetool_reg {
86 	uint32_t cmd;
87 	uint32_t addr;
88 	uint32_t val;
89 };
90 
91 uint32_t
92 t1_read_reg_4(ch_t *obj, uint32_t reg_val)
93 {
94 	return (ddi_get32(obj->ch_hbar0, (uint32_t *)(obj->ch_bar0 + reg_val)));
95 }
96 
97 void
98 t1_write_reg_4(ch_t *obj, uint32_t reg_val, uint32_t write_val)
99 {
100 	ddi_put32(obj->ch_hbar0, (uint32_t *)(obj->ch_bar0+reg_val), write_val);
101 }
102 
103 uint32_t
104 t1_os_pci_read_config_2(ch_t *obj, uint32_t reg, uint16_t *val)
105 {
106 	*val = pci_config_get16(obj->ch_hpci, reg);
107 	return (0);
108 }
109 
110 int
111 t1_os_pci_write_config_2(ch_t *obj, uint32_t reg, uint16_t val)
112 {
113 	pci_config_put16(obj->ch_hpci, reg, val);
114 	return (0);
115 }
116 
117 uint32_t
118 t1_os_pci_read_config_4(ch_t *obj, uint32_t reg, uint32_t *val)
119 {
120 	*val = pci_config_get32(obj->ch_hpci, reg);
121 	return (0);
122 }
123 
124 int
125 t1_os_pci_write_config_4(ch_t *obj, uint32_t reg, uint32_t val)
126 {
127 	pci_config_put32(obj->ch_hpci, reg, val);
128 	return (0);
129 }
130 
131 void *
132 t1_os_malloc_wait_zero(size_t len)
133 {
134 	return (kmem_zalloc(len, KM_SLEEP));
135 }
136 
137 void
138 t1_os_free(void *adr, size_t len)
139 {
140 	kmem_free(adr, len);
141 }
142 
143 int
144 t1_num_of_ports(ch_t *obj)
145 {
146 	return (obj->config_data.num_of_ports);
147 }
148 
149 /* ARGSUSED */
150 int
151 pe_os_mem_copy(ch_t *obj, void *dst, void *src, size_t len)
152 {
153 	bcopy(src, dst, len);
154 	return (0);
155 }
156 
157 int
158 pe_is_ring_buffer_enabled(ch_t *obj)
159 {
160 	return (obj->config & CFGMD_RINGB);
161 }
162 
163 #define	PE_READ_REG  _IOR('i', 0xAB, 0x18)
164 #define	PE_WRITE_REG _IOW('i', 0xAB, 0x18)
165 #define	PE_READ_PCI  _IOR('i', 0xAC, 0x18)
166 #define	PE_WRITE_PCI _IOW('i', 0xAC, 0x18)
167 #define	PE_READ_INTR _IOR('i', 0xAD, 0x20)
168 #define	TOETOOL_GETTPI _IOR('i', 0xAE, 0xc)
169 #define	TOETOOL_SETTPI _IOW('i', 0xAE, 0xc)
170 
171 void
172 pe_ioctl(ch_t *chp, queue_t *q, mblk_t *mp)
173 {
174 	struct iocblk *iocp;
175 	mblk_t *dmp;
176 	struct pe_reg *pe;
177 	struct toetool_reg *te;
178 	uint32_t reg;
179 	struct sge_intr_counts *se, *sep;
180 
181 	iocp = (struct iocblk *)mp->b_rptr;
182 
183 	/* don't support TRASPARENT ioctls */
184 	if (iocp->ioc_count == TRANSPARENT) {
185 		iocp->ioc_error = ENOTTY;
186 		goto bad;
187 	}
188 
189 	/*
190 	 * sanity checks. There should be a M_DATA mblk following
191 	 * the initial M_IOCTL mblk
192 	 */
193 	if ((dmp = mp->b_cont) == NULL) {
194 		iocp->ioc_error = ENOTTY;
195 		goto bad;
196 	}
197 
198 	if (dmp->b_datap->db_type != M_DATA) {
199 		iocp->ioc_error = ENOTTY;
200 		goto bad;
201 	}
202 
203 	pe = (struct pe_reg *)dmp->b_rptr;
204 	se = (struct sge_intr_counts *)dmp->b_rptr;
205 	te = (struct toetool_reg *)dmp->b_rptr;
206 
207 	/* now process the ioctl */
208 	switch (iocp->ioc_cmd) {
209 	case PE_READ_REG:
210 
211 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
212 			iocp->ioc_error = ENOTTY;
213 			goto bad;
214 		}
215 
216 		/* protect against bad addr values */
217 		pe->addr &= (uint32_t)~3;
218 
219 		pe->pe_mask32 = 0xFFFFFFFF;
220 
221 		if (pe->addr == 0x950)
222 			pe->pe_reg_val = reg = t1_sge_get_ptimeout(chp);
223 		else
224 			pe->pe_reg_val = reg = t1_read_reg_4(chp, pe->addr);
225 
226 		mp->b_datap->db_type = M_IOCACK;
227 		iocp->ioc_count = sizeof (*pe);
228 
229 		break;
230 
231 	case PE_WRITE_REG:
232 
233 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
234 			iocp->ioc_error = ENOTTY;
235 			goto bad;
236 		}
237 
238 		if (pe->addr == 0x950)
239 			t1_sge_set_ptimeout(chp, pe->pe_reg_val);
240 		else {
241 			if (pe->pe_mask32 != 0xffffffff) {
242 				reg = t1_read_reg_4(chp, pe->addr);
243 				pe->pe_reg_val |= (reg & ~pe->pe_mask32);
244 			}
245 
246 			t1_write_reg_4(chp, pe->addr,  pe->pe_reg_val);
247 		}
248 
249 		if (mp->b_cont)
250 			freemsg(mp->b_cont);
251 		mp->b_cont = NULL;
252 		mp->b_datap->db_type = M_IOCACK;
253 		break;
254 
255 	case PE_READ_PCI:
256 
257 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
258 			iocp->ioc_error = ENOTTY;
259 			goto bad;
260 		}
261 
262 		/* protect against bad addr values */
263 		pe->addr &= (uint32_t)~3;
264 
265 		pe->pe_mask32 = 0xFFFFFFFF;
266 		pe->pe_reg_val = reg = pci_config_get32(chp->ch_hpci, pe->addr);
267 		mp->b_datap->db_type = M_IOCACK;
268 		iocp->ioc_count = sizeof (*pe);
269 
270 		break;
271 
272 	case PE_WRITE_PCI:
273 
274 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
275 			iocp->ioc_error = ENOTTY;
276 			goto bad;
277 		}
278 
279 		if (pe->pe_mask32 != 0xffffffff) {
280 			reg = pci_config_get32(chp->ch_hpci, pe->addr);
281 			pe->pe_reg_val |= (reg & ~pe->pe_mask32);
282 		}
283 
284 		pci_config_put32(chp->ch_hpci, pe->addr,  pe->pe_reg_val);
285 
286 		if (mp->b_cont)
287 			freemsg(mp->b_cont);
288 		mp->b_cont = NULL;
289 		mp->b_datap->db_type = M_IOCACK;
290 		break;
291 
292 	case PE_READ_INTR:
293 
294 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*se)) {
295 			iocp->ioc_error = ENOTTY;
296 			goto bad;
297 		}
298 
299 		sep = sge_get_stat(chp->sge);
300 		bcopy(sep, se, sizeof (*se));
301 		mp->b_datap->db_type = M_IOCACK;
302 		iocp->ioc_count = sizeof (*se);
303 		break;
304 
305 	case TOETOOL_GETTPI:
306 
307 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*te)) {
308 			iocp->ioc_error = ENOTTY;
309 			goto bad;
310 		}
311 
312 		/* protect against bad addr values */
313 		if ((te->addr & 3) != 0) {
314 			iocp->ioc_error = ENOTTY;
315 			goto bad;
316 		}
317 
318 		(void) t1_tpi_read(chp, te->addr, &te->val);
319 		mp->b_datap->db_type = M_IOCACK;
320 		iocp->ioc_count = sizeof (*te);
321 
322 		break;
323 
324 	case TOETOOL_SETTPI:
325 
326 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*te)) {
327 			iocp->ioc_error = ENOTTY;
328 			goto bad;
329 		}
330 
331 		/* protect against bad addr values */
332 		if ((te->addr & 3) != 0) {
333 			iocp->ioc_error = ENOTTY;
334 			goto bad;
335 		}
336 
337 		(void) t1_tpi_write(chp, te->addr, te->val);
338 
339 		mp->b_datap->db_type = M_IOCACK;
340 		iocp->ioc_count = sizeof (*te);
341 
342 		break;
343 
344 	default:
345 		iocp->ioc_error = ENOTTY;
346 		goto bad;
347 	}
348 
349 	qreply(q, mp);
350 
351 	return;
352 
353 bad:
354 	if (mp->b_cont)
355 		freemsg(mp->b_cont);
356 	mp->b_cont = NULL;
357 	mp->b_datap->db_type = M_IOCNAK;
358 
359 	qreply(q, mp);
360 }
361 
362 /*
363  * Can't wait for memory here, since we have to use the Solaris dma
364  * mechanisms to determine the physical address.
365  * flg is either 0 (read) or DMA_OUT (write).
366  */
367 void *
368 pe_os_malloc_contig_wait_zero(ch_t *chp, size_t len, uint64_t *dma_addr,
369 	ulong_t *dh, ulong_t *ah, uint32_t flg)
370 {
371 	void *mem = NULL;
372 	uint64_t pa;
373 
374 	/*
375 	 * byte swap, consistant mapping & 4k aligned
376 	 */
377 	mem = ch_alloc_dma_mem(chp, 1, DMA_4KALN|flg, len, &pa, dh, ah);
378 	if (mem == NULL) {
379 		return (0);
380 	}
381 
382 	if (dma_addr)
383 		*dma_addr = pa;
384 
385 	bzero(mem, len);
386 
387 	return ((void *)mem);
388 }
389 
390 /* ARGSUSED */
391 void
392 pe_os_free_contig(ch_t *obj, size_t len, void *addr, uint64_t dma_addr,
393 			ulong_t dh, ulong_t ah)
394 {
395 	ch_free_dma_mem(dh, ah);
396 }
397 
398 void
399 t1_fatal_err(ch_t *adapter)
400 {
401 	if (adapter->ch_flags & PEINITDONE) {
402 		(void) sge_stop(adapter->sge);
403 		t1_interrupts_disable(adapter);
404 	}
405 	CH_ALERT("%s: encountered fatal error, operation suspended\n",
406 		adapter_name(adapter));
407 }
408 
409 void
410 CH_ALERT(const char *fmt, ...)
411 {
412 	va_list	ap;
413 	char	buf[128];
414 
415 	/* format buf using fmt and arguments contained in ap */
416 
417 	va_start(ap, fmt);
418 	(void) vsprintf(buf, fmt, ap);
419 	va_end(ap);
420 
421 	/* pass formatted string to cmn_err(9F) */
422 	cmn_err(CE_WARN, "%s", buf);
423 }
424 
425 void
426 CH_WARN(const char *fmt, ...)
427 {
428 	va_list	ap;
429 	char	buf[128];
430 
431 	/* format buf using fmt and arguments contained in ap */
432 
433 	va_start(ap, fmt);
434 	(void) vsprintf(buf, fmt, ap);
435 	va_end(ap);
436 
437 	/* pass formatted string to cmn_err(9F) */
438 	cmn_err(CE_WARN, "%s", buf);
439 }
440 
441 void
442 CH_ERR(const char *fmt, ...)
443 {
444 	va_list	ap;
445 	char	buf[128];
446 
447 	/* format buf using fmt and arguments contained in ap */
448 
449 	va_start(ap, fmt);
450 	(void) vsprintf(buf, fmt, ap);
451 	va_end(ap);
452 
453 	/* pass formatted string to cmn_err(9F) */
454 	cmn_err(CE_WARN, "%s", buf);
455 }
456 
457 u32
458 le32_to_cpu(u32 data)
459 {
460 #if BYTE_ORDER == BIG_ENDIAN
461 	uint8_t *in, t;
462 	in = (uint8_t *)&data;
463 	t = in[0];
464 	in[0] = in[3];
465 	in[3] = t;
466 	t = in[1];
467 	in[1] = in[2];
468 	in[2] = t;
469 #endif
470 	return (data);
471 }
472 
473 /*
474  * This function initializes a polling routine, Poll_func
475  * which will be polled ever N Microsecond, where N is
476  * provided in the cyclic start routine.
477  */
478 /* ARGSUSED */
479 void
480 ch_init_cyclic(void *adapter, p_ch_cyclic_t cyclic,
481 		void (*poll_func)(void *), void *arg)
482 {
483 	cyclic->func = poll_func;
484 	cyclic->arg = arg;
485 	cyclic->timer = 0;
486 }
487 
488 /*
489  * Cyclic function which provides a periodic polling
490  * capability to Solaris. The poll function provided by
491  * the 'ch_init_cyclic' function is called from this
492  * here, and this routine launches a new one-shot
493  * timer to bring it back in some period later.
494  */
495 void
496 ch_cyclic(p_ch_cyclic_t cyclic)
497 {
498 	if (cyclic->timer != 0) {
499 		cyclic->func(cyclic->arg);
500 		cyclic->timer = timeout((void(*)(void  *))ch_cyclic,
501 			(void *)cyclic, cyclic->period);
502 	}
503 }
504 
505 /*
506  * The 'ch_start_cyclic' starts the polling.
507  */
508 void
509 ch_start_cyclic(p_ch_cyclic_t cyclic, unsigned long period)
510 {
511 	cyclic->period = drv_usectohz(period * 1000);
512 	if (cyclic->timer == 0) {
513 		cyclic->timer = timeout((void(*)(void  *))ch_cyclic,
514 			(void *)cyclic, cyclic->period);
515 	}
516 }
517 
518 /*
519  * The 'ch_stop_cyclic' stops the polling.
520  */
521 void
522 ch_stop_cyclic(p_ch_cyclic_t cyclic)
523 {
524 	timeout_id_t timer;
525 	clock_t value;
526 
527 	do {
528 		timer = cyclic->timer;
529 		cyclic->timer = 0;
530 		value = untimeout(timer);
531 		if (value == 0)
532 			delay(2 * cyclic->period);
533 	} while ((timer != 0) && (value == 0));
534 }
535