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