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