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