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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* Copyright (c) 1990 Mentat Inc. */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <inet/common.h> /* for various inet/mi.h and inet/nd.h needs */ 31 #include <sys/stream.h> 32 #include <sys/stropts.h> 33 #include <sys/strsun.h> 34 #include <sys/sysmacros.h> 35 #include <inet/nd.h> 36 #include <inet/mi.h> 37 #define _SUN_TPI_VERSION 2 38 #include <sys/tihdr.h> 39 #include <sys/timod.h> 40 #include <sys/vtrace.h> 41 #include <sys/kmem.h> 42 #include <sys/mkdev.h> 43 #include <sys/strlog.h> 44 #include <sys/ddi.h> 45 #include <sys/suntpi.h> 46 #include <sys/cmn_err.h> 47 #include <sys/debug.h> 48 #include <sys/kobj.h> 49 50 #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') 51 #define ISUPPER(ch) ((ch) >= 'A' && (ch) <= 'Z') 52 #define tolower(ch) ('a' + ((ch) - 'A')) 53 54 #define MI_IS_TRANSPARENT(mp) (mp->b_cont && \ 55 (mp->b_cont->b_rptr != mp->b_cont->b_wptr)) 56 57 /* 58 * NOTE: Whenever anything is allocated by mi_alloc or mi_alloc_sleep (below), 59 * the size of the requested allocation is increased by one word. This extra 60 * word is used to store the size of the object being allocated, and is located 61 * at the beginning of the allocated block. The pointer returned to the caller 62 * is a pointer to the *second* word in the newly-allocated block. The IP 63 * module of mdb is aware of this, and will need to be changed if this 64 * allocation strategy is changed. 65 */ 66 67 typedef struct stroptions *STROPTP; 68 typedef union T_primitives *TPRIMP; 69 70 /* Timer block states. */ 71 #define TB_RUNNING 1 72 #define TB_IDLE 2 73 /* 74 * Could not stop/free before putq 75 */ 76 #define TB_RESCHED 3 /* mtb_time_left contains tick count */ 77 #define TB_CANCELLED 4 78 #define TB_TO_BE_FREED 5 79 80 typedef struct mtb_s { 81 int mtb_state; 82 timeout_id_t mtb_tid; 83 queue_t *mtb_q; 84 MBLKP mtb_mp; 85 clock_t mtb_time_left; 86 } MTB, *MTBP; 87 88 static int mi_timer_fire(MTBP); 89 static int mi_iprintf(char *, va_list, pfi_t, char *); 90 static void mi_tpi_addr_and_opt(MBLKP, char *, t_scalar_t, char *, t_scalar_t); 91 static MBLKP mi_tpi_trailer_alloc(MBLKP, size_t, t_scalar_t); 92 93 /* ARGSUSED1 */ 94 void * 95 mi_alloc(size_t size, uint_t pri) 96 { 97 size_t *ptr; 98 99 size += sizeof (size); 100 if (ptr = kmem_alloc(size, KM_NOSLEEP)) { 101 *ptr = size; 102 return (ptr + 1); 103 } 104 return (NULL); 105 } 106 107 /* ARGSUSED1 */ 108 void * 109 mi_alloc_sleep(size_t size, uint_t pri) 110 { 111 size_t *ptr; 112 113 size += sizeof (size); 114 ptr = kmem_alloc(size, KM_SLEEP); 115 *ptr = size; 116 return (ptr + 1); 117 } 118 119 int 120 mi_close_comm(void **mi_headp, queue_t *q) 121 { 122 IDP ptr; 123 124 ptr = q->q_ptr; 125 mi_close_unlink(mi_headp, ptr); 126 mi_close_free(ptr); 127 q->q_ptr = WR(q)->q_ptr = NULL; 128 return (0); 129 } 130 131 void 132 mi_close_unlink(void **mi_headp, IDP ptr) 133 { 134 mi_head_t *mi_head = *(mi_head_t **)mi_headp; 135 MI_OP mi_o; 136 dev_t dev; 137 138 mi_o = (MI_OP)ptr; 139 if (!mi_o) 140 return; 141 mi_o--; 142 143 if (mi_o->mi_o_next == NULL) { 144 /* Not in list */ 145 ASSERT(mi_o->mi_o_prev == NULL); 146 return; 147 } 148 149 /* Free minor number */ 150 dev = mi_o->mi_o_dev; 151 if ((dev != OPENFAIL) && (dev != 0) && (dev <= MAXMIN)) 152 inet_minor_free(mi_head->mh_arena, dev); 153 154 /* Unlink from list */ 155 ASSERT(mi_o->mi_o_next != NULL); 156 ASSERT(mi_o->mi_o_prev != NULL); 157 ASSERT(mi_o->mi_o_next->mi_o_prev == mi_o); 158 ASSERT(mi_o->mi_o_prev->mi_o_next == mi_o); 159 160 mi_o->mi_o_next->mi_o_prev = mi_o->mi_o_prev; 161 mi_o->mi_o_prev->mi_o_next = mi_o->mi_o_next; 162 mi_o->mi_o_next = mi_o->mi_o_prev = NULL; 163 164 mi_o->mi_o_dev = (dev_t)OPENFAIL; 165 166 /* If list now empty free the list head */ 167 if (mi_head->mh_o.mi_o_next == &mi_head->mh_o) { 168 ASSERT(mi_head->mh_o.mi_o_prev == &mi_head->mh_o); 169 if (mi_head->mh_arena != NULL) 170 inet_minor_destroy(mi_head->mh_arena); 171 mi_free((IDP)mi_head); 172 *mi_headp = NULL; 173 } 174 } 175 176 void 177 mi_close_free(IDP ptr) 178 { 179 MI_OP mi_o; 180 181 mi_o = (MI_OP)ptr; 182 if (!mi_o) 183 return; 184 mi_o--; 185 186 ASSERT(mi_o->mi_o_next == NULL && mi_o->mi_o_prev == NULL); 187 mi_free((IDP)mi_o); 188 } 189 190 /* 191 * mi_copyin - takes care of transparent or non-transparent ioctl for the 192 * calling function so that they have to deal with just M_IOCDATA type 193 * and not worry about M_COPYIN. 194 * 195 * mi_copyin checks to see if the ioctl is transparent or non transparent. 196 * In case of a non_transparent ioctl, it packs the data into a M_IOCDATA 197 * message and puts it back onto the current queue for further processing. 198 * In case of transparent ioctl, it sends a M_COPYIN message up to the 199 * streamhead so that a M_IOCDATA with the information comes back down. 200 */ 201 void 202 mi_copyin(queue_t *q, MBLKP mp, char *uaddr, size_t len) 203 { 204 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 205 struct copyreq *cq = (struct copyreq *)mp->b_rptr; 206 struct copyresp *cp = (struct copyresp *)mp->b_rptr; 207 int err; 208 MBLKP mp1; 209 210 ASSERT(mp->b_datap->db_type == M_IOCTL && !uaddr); 211 212 /* A transparent ioctl. Send a M_COPYIN message to the streamhead. */ 213 if (iocp->ioc_count == TRANSPARENT) { 214 MI_COPY_COUNT(mp) = 1; 215 MI_COPY_DIRECTION(mp) = MI_COPY_IN; 216 cq->cq_private = mp->b_cont; 217 cq->cq_size = len; 218 cq->cq_flag = 0; 219 bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr)); 220 mp->b_cont = NULL; 221 mp->b_datap->db_type = M_COPYIN; 222 qreply(q, mp); 223 return; 224 } 225 226 /* 227 * A non-transparent ioctl. Need to convert into M_IOCDATA message. 228 * 229 * We allocate a 0 byte message block and put its address in 230 * cp_private. It also makes the b_prev field = 1 and b_next 231 * field = MI_COPY_IN for this 0 byte block. This is done to 232 * maintain compatibility with old code in mi_copy_state 233 * (which removes the empty block). 234 */ 235 err = miocpullup(mp, len); 236 if (err != 0) 237 goto err_ret; 238 239 mp1 = allocb(0, BPRI_MED); 240 if (mp1 == NULL) { 241 err = ENOMEM; 242 goto err_ret; 243 } 244 245 /* 246 * Temporarily insert mp1 between the M_IOCTL and M_DATA blocks so 247 * that we can use the MI_COPY_COUNT & MI_COPY_DIRECTION macros. 248 */ 249 mp1->b_cont = mp->b_cont; 250 mp->b_cont = mp1; 251 MI_COPY_COUNT(mp) = 1; 252 MI_COPY_DIRECTION(mp) = MI_COPY_IN; 253 mp->b_cont = mp1->b_cont; 254 mp1->b_cont = NULL; 255 256 /* 257 * Leave a pointer to the 0 byte block in cp_private field for 258 * future use by the mi_copy_* routines. 259 */ 260 mp->b_datap->db_type = M_IOCDATA; 261 cp->cp_private = mp1; 262 cp->cp_rval = NULL; 263 put(q, mp); 264 return; 265 266 err_ret: 267 iocp->ioc_error = err; 268 iocp->ioc_count = 0; 269 if (mp->b_cont) { 270 freemsg(mp->b_cont); 271 mp->b_cont = NULL; 272 } 273 mp->b_datap->db_type = M_IOCACK; 274 qreply(q, mp); 275 } 276 277 /* 278 * Allows transparent IOCTLs to have multiple copyins. This is needed 279 * for some variable-length structures, where the total size is only known 280 * after the first part is copied in. Rather than setting MI_COPY_COUNT to 281 * 1, as in mi_coypin(), it is simply incremented here. This value can 282 * then be checked in the returned IOCBLK. 283 * 284 * As this deals with copyins that follow the initial copyin, the byte 285 * offset into the user buffer from which copying should begin must be 286 * passed in in the offset parameter. 287 * 288 * Unlike mi_coypin(), this function expects to be passed an mblk chain 289 * headed by an M_IOCBLK, as that's the chain that will be in use for 290 * copies after the first one (copies where n != 1). 291 */ 292 void 293 mi_copyin_n(queue_t *q, MBLKP mp, size_t offset, size_t len) 294 { 295 struct copyreq *cq = (struct copyreq *)mp->b_rptr; 296 297 ASSERT(mp->b_datap->db_type == M_IOCDATA); 298 299 MI_COPY_COUNT(mp)++; 300 MI_COPY_DIRECTION(mp) = MI_COPY_IN; 301 cq->cq_private = mp->b_cont; 302 cq->cq_size = len; 303 cq->cq_flag = 0; 304 bcopy(mp->b_cont->b_rptr, &cq->cq_addr, sizeof (cq->cq_addr)); 305 cq->cq_addr += offset; 306 mp->b_cont = NULL; 307 mp->b_datap->db_type = M_COPYIN; 308 qreply(q, mp); 309 } 310 311 void 312 mi_copyout(queue_t *q, MBLKP mp) 313 { 314 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 315 struct copyreq *cq = (struct copyreq *)iocp; 316 struct copyresp *cp = (struct copyresp *)cq; 317 MBLKP mp1; 318 MBLKP mp2; 319 320 if (mp->b_datap->db_type != M_IOCDATA || !mp->b_cont) { 321 mi_copy_done(q, mp, EPROTO); 322 return; 323 } 324 /* Check completion of previous copyout operation. */ 325 mp1 = mp->b_cont; 326 if ((int)(uintptr_t)cp->cp_rval || !mp1->b_cont) { 327 mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval); 328 return; 329 } 330 if (!mp1->b_cont->b_cont && !MI_IS_TRANSPARENT(mp)) { 331 mp1->b_next = NULL; 332 mp1->b_prev = NULL; 333 mp->b_cont = mp1->b_cont; 334 freeb(mp1); 335 mp1 = mp->b_cont; 336 mp1->b_next = NULL; 337 mp1->b_prev = NULL; 338 iocp->ioc_count = mp1->b_wptr - mp1->b_rptr; 339 iocp->ioc_error = 0; 340 mp->b_datap->db_type = M_IOCACK; 341 qreply(q, mp); 342 return; 343 } 344 if (MI_COPY_DIRECTION(mp) == MI_COPY_IN) { 345 /* Set up for first copyout. */ 346 MI_COPY_DIRECTION(mp) = MI_COPY_OUT; 347 MI_COPY_COUNT(mp) = 1; 348 } else { 349 ++MI_COPY_COUNT(mp); 350 } 351 cq->cq_private = mp1; 352 /* Find message preceding last. */ 353 for (mp2 = mp1; mp2->b_cont->b_cont; mp2 = mp2->b_cont) 354 ; 355 if (mp2 == mp1) 356 bcopy((char *)mp1->b_rptr, (char *)&cq->cq_addr, 357 sizeof (cq->cq_addr)); 358 else 359 cq->cq_addr = (char *)mp2->b_cont->b_next; 360 mp1 = mp2->b_cont; 361 mp->b_datap->db_type = M_COPYOUT; 362 mp->b_cont = mp1; 363 mp2->b_cont = NULL; 364 mp1->b_next = NULL; 365 cq->cq_size = mp1->b_wptr - mp1->b_rptr; 366 cq->cq_flag = 0; 367 qreply(q, mp); 368 } 369 370 MBLKP 371 mi_copyout_alloc(queue_t *q, MBLKP mp, char *uaddr, size_t len, 372 boolean_t free_on_error) 373 { 374 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 375 MBLKP mp1; 376 377 if (mp->b_datap->db_type == M_IOCTL) { 378 if (iocp->ioc_count != TRANSPARENT) { 379 mp1 = allocb(0, BPRI_MED); 380 if (mp1 == NULL) { 381 if (free_on_error) { 382 iocp->ioc_error = ENOMEM; 383 iocp->ioc_count = 0; 384 freemsg(mp->b_cont); 385 mp->b_cont = NULL; 386 mp->b_datap->db_type = M_IOCACK; 387 qreply(q, mp); 388 } 389 return (NULL); 390 } 391 mp1->b_cont = mp->b_cont; 392 mp->b_cont = mp1; 393 } 394 MI_COPY_COUNT(mp) = 0; 395 MI_COPY_DIRECTION(mp) = MI_COPY_OUT; 396 /* Make sure it looks clean to mi_copyout. */ 397 mp->b_datap->db_type = M_IOCDATA; 398 ((struct copyresp *)iocp)->cp_rval = NULL; 399 } 400 mp1 = allocb(len, BPRI_MED); 401 if (mp1 == NULL) { 402 if (free_on_error) 403 mi_copy_done(q, mp, ENOMEM); 404 return (NULL); 405 } 406 linkb(mp, mp1); 407 mp1->b_next = (MBLKP)uaddr; 408 return (mp1); 409 } 410 411 void 412 mi_copy_done(queue_t *q, MBLKP mp, int err) 413 { 414 struct iocblk *iocp; 415 MBLKP mp1; 416 417 if (!mp) 418 return; 419 if (!q || (mp->b_wptr - mp->b_rptr) < sizeof (struct iocblk)) { 420 freemsg(mp); 421 return; 422 } 423 iocp = (struct iocblk *)mp->b_rptr; 424 mp->b_datap->db_type = M_IOCACK; 425 iocp->ioc_error = err; 426 427 iocp->ioc_count = 0; 428 if ((mp1 = mp->b_cont) != NULL) { 429 for (; mp1; mp1 = mp1->b_cont) { 430 mp1->b_prev = NULL; 431 mp1->b_next = NULL; 432 } 433 freemsg(mp->b_cont); 434 mp->b_cont = NULL; 435 } 436 qreply(q, mp); 437 } 438 439 int 440 mi_copy_state(queue_t *q, MBLKP mp, MBLKP *mpp) 441 { 442 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 443 struct copyresp *cp = (struct copyresp *)iocp; 444 MBLKP mp1; 445 446 mp1 = mp->b_cont; 447 mp->b_cont = cp->cp_private; 448 if (mp1) { 449 if (mp1->b_cont && !pullupmsg(mp1, -1)) { 450 mi_copy_done(q, mp, ENOMEM); 451 return (-1); 452 } 453 linkb(mp->b_cont, mp1); 454 } 455 if ((int)(uintptr_t)cp->cp_rval) { 456 mi_copy_done(q, mp, (int)(uintptr_t)cp->cp_rval); 457 return (-1); 458 } 459 if (mpp && MI_COPY_DIRECTION(mp) == MI_COPY_IN) 460 *mpp = mp1; 461 return (MI_COPY_STATE(mp)); 462 } 463 464 void 465 mi_free(void *ptr) 466 { 467 size_t size; 468 469 if (!ptr) 470 return; 471 if ((size = ((size_t *)ptr)[-1]) <= 0) 472 cmn_err(CE_PANIC, "mi_free"); 473 474 kmem_free((void *) ((size_t *)ptr - 1), size); 475 } 476 477 static int 478 mi_iprintf(char *fmt, va_list ap, pfi_t putc_func, char *cookie) 479 { 480 int base; 481 char buf[(sizeof (long) * 3) + 1]; 482 static char hex_val[] = "0123456789abcdef"; 483 int ch; 484 int count; 485 char *cp1; 486 int digits; 487 char *fcp; 488 boolean_t is_long; 489 ulong_t uval; 490 long val; 491 boolean_t zero_filled; 492 493 if (!fmt) 494 return (-1); 495 count = 0; 496 while (*fmt) { 497 if (*fmt != '%' || *++fmt == '%') { 498 count += (*putc_func)(cookie, *fmt++); 499 continue; 500 } 501 if (*fmt == '0') { 502 zero_filled = B_TRUE; 503 fmt++; 504 if (!*fmt) 505 break; 506 } else 507 zero_filled = B_FALSE; 508 base = 0; 509 for (digits = 0; ISDIGIT(*fmt); fmt++) { 510 digits *= 10; 511 digits += (*fmt - '0'); 512 } 513 if (!*fmt) 514 break; 515 is_long = B_FALSE; 516 if (*fmt == 'l') { 517 is_long = B_TRUE; 518 fmt++; 519 } 520 if (!*fmt) 521 break; 522 ch = *fmt++; 523 if (ISUPPER(ch)) { 524 ch = tolower(ch); 525 is_long = B_TRUE; 526 } 527 switch (ch) { 528 case 'c': 529 count += (*putc_func)(cookie, va_arg(ap, int *)); 530 continue; 531 case 'd': 532 base = 10; 533 break; 534 case 'm': /* Print out memory, 2 hex chars per byte */ 535 if (is_long) 536 fcp = va_arg(ap, char *); 537 else { 538 if ((cp1 = va_arg(ap, char *)) != NULL) 539 fcp = (char *)cp1; 540 else 541 fcp = NULL; 542 } 543 if (!fcp) { 544 for (fcp = (char *)"(NULL)"; *fcp; fcp++) 545 count += (*putc_func)(cookie, *fcp); 546 } else { 547 while (digits--) { 548 int u1 = *fcp++ & 0xFF; 549 count += (*putc_func)(cookie, 550 hex_val[(u1>>4)& 0xF]); 551 count += (*putc_func)(cookie, 552 hex_val[u1& 0xF]); 553 } 554 } 555 continue; 556 case 'o': 557 base = 8; 558 break; 559 case 'p': 560 is_long = B_TRUE; 561 /* FALLTHRU */ 562 case 'x': 563 base = 16; 564 break; 565 case 's': 566 if (is_long) 567 fcp = va_arg(ap, char *); 568 else { 569 if ((cp1 = va_arg(ap, char *)) != NULL) 570 fcp = (char *)cp1; 571 else 572 fcp = NULL; 573 } 574 if (!fcp) 575 fcp = (char *)"(NULL)"; 576 while (*fcp) { 577 count += (*putc_func)(cookie, *fcp++); 578 if (digits && --digits == 0) 579 break; 580 } 581 while (digits > 0) { 582 count += (*putc_func)(cookie, ' '); 583 digits--; 584 } 585 continue; 586 case 'u': 587 base = 10; 588 break; 589 default: 590 return (count); 591 } 592 if (is_long) 593 val = va_arg(ap, long); 594 else 595 val = va_arg(ap, int); 596 if (base == 10 && ch != 'u') { 597 if (val < 0) { 598 count += (*putc_func)(cookie, '-'); 599 val = -val; 600 } 601 uval = val; 602 } else { 603 if (is_long) 604 uval = val; 605 else 606 uval = (uint_t)val; 607 } 608 /* Hand overload/restore the register variable 'fmt' */ 609 cp1 = fmt; 610 fmt = A_END(buf); 611 *--fmt = '\0'; 612 do { 613 if (fmt > buf) 614 *--fmt = hex_val[uval % base]; 615 if (digits && --digits == 0) 616 break; 617 } while (uval /= base); 618 if (zero_filled) { 619 while (digits > 0 && fmt > buf) { 620 *--fmt = '0'; 621 digits--; 622 } 623 } 624 while (*fmt) 625 count += (*putc_func)(cookie, *fmt++); 626 fmt = cp1; 627 } 628 return (count); 629 } 630 631 /* PRINTFLIKE2 */ 632 int 633 mi_mpprintf(MBLKP mp, char *fmt, ...) 634 { 635 va_list ap; 636 int count = -1; 637 638 va_start(ap, fmt); 639 if (mp) { 640 count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc, 641 (char *)mp); 642 if (count != -1) 643 (void) mi_mpprintf_putc((char *)mp, '\0'); 644 } 645 va_end(ap); 646 return (count); 647 } 648 649 /* PRINTFLIKE2 */ 650 int 651 mi_mpprintf_nr(MBLKP mp, char *fmt, ...) 652 { 653 va_list ap; 654 int count = -1; 655 656 va_start(ap, fmt); 657 if (mp) { 658 (void) adjmsg(mp, -1); 659 count = mi_iprintf(fmt, ap, (pfi_t)mi_mpprintf_putc, 660 (char *)mp); 661 if (count != -1) 662 (void) mi_mpprintf_putc((char *)mp, '\0'); 663 } 664 va_end(ap); 665 return (count); 666 } 667 668 int 669 mi_mpprintf_putc(char *cookie, int ch) 670 { 671 MBLKP mp = (MBLKP)cookie; 672 673 while (mp->b_cont) 674 mp = mp->b_cont; 675 if (mp->b_wptr >= mp->b_datap->db_lim) { 676 mp->b_cont = allocb(1024, BPRI_HI); 677 mp = mp->b_cont; 678 if (!mp) 679 return (0); 680 } 681 *mp->b_wptr++ = (unsigned char)ch; 682 return (1); 683 } 684 685 IDP 686 mi_first_ptr(void **mi_headp) 687 { 688 mi_head_t *mi_head = *(mi_head_t **)mi_headp; 689 MI_OP mi_op; 690 691 mi_op = mi_head->mh_o.mi_o_next; 692 if (mi_op && mi_op != &mi_head->mh_o) 693 return ((IDP)&mi_op[1]); 694 return (NULL); 695 } 696 697 /* 698 * Clients can choose to have both module instances and device instances 699 * in the same list. Return the first device instance in the list. 700 */ 701 IDP 702 mi_first_dev_ptr(void **mi_headp) 703 { 704 mi_head_t *mi_head = *(mi_head_t **)mi_headp; 705 MI_OP mi_op; 706 707 mi_op = mi_head->mh_o.mi_o_next; 708 while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) { 709 if (mi_op->mi_o_isdev) 710 return ((IDP)&mi_op[1]); 711 mi_op = mi_op->mi_o_next; 712 } 713 return (NULL); 714 } 715 716 IDP 717 mi_next_ptr(void **mi_headp, IDP ptr) 718 { 719 mi_head_t *mi_head = *(mi_head_t **)mi_headp; 720 MI_OP mi_op = ((MI_OP)ptr) - 1; 721 722 if ((mi_op = mi_op->mi_o_next) != NULL && mi_op != &mi_head->mh_o) 723 return ((IDP)&mi_op[1]); 724 return (NULL); 725 } 726 727 /* 728 * Clients can choose to have both module instances and device instances 729 * in the same list. Return the next device instance in the list. 730 */ 731 IDP 732 mi_next_dev_ptr(void **mi_headp, IDP ptr) 733 { 734 mi_head_t *mi_head = *(mi_head_t **)mi_headp; 735 MI_OP mi_op = ((MI_OP)ptr) - 1; 736 737 mi_op = mi_op->mi_o_next; 738 while ((mi_op != NULL) && (mi_op != &mi_head->mh_o)) { 739 if (mi_op->mi_o_isdev) 740 return ((IDP)&mi_op[1]); 741 mi_op = mi_op->mi_o_next; 742 } 743 return (NULL); 744 } 745 746 /* 747 * Self clone the device 748 * XXX - should we still support clone device 749 */ 750 /* ARGSUSED4 */ 751 int 752 mi_open_comm(void **mi_headp, size_t size, queue_t *q, dev_t *devp, 753 int flag, int sflag, cred_t *credp) 754 { 755 int error; 756 IDP ptr; 757 758 if (q->q_ptr != NULL) 759 return (0); 760 761 ptr = mi_open_alloc_sleep(size); 762 q->q_ptr = WR(q)->q_ptr = ptr; 763 error = mi_open_link(mi_headp, ptr, devp, flag, sflag, credp); 764 if (error != 0) { 765 q->q_ptr = WR(q)->q_ptr = NULL; 766 mi_close_free(ptr); 767 } 768 return (error); 769 } 770 771 IDP 772 mi_open_alloc_sleep(size_t size) 773 { 774 MI_OP mi_o; 775 776 if (size > (UINT_MAX - sizeof (MI_O))) 777 return (NULL); 778 779 mi_o = (MI_OP)mi_zalloc_sleep(size + sizeof (MI_O)); 780 mi_o++; 781 return ((IDP)mi_o); 782 } 783 784 IDP 785 mi_open_alloc(size_t size) 786 { 787 MI_OP mi_o; 788 789 if (size > (UINT_MAX - sizeof (MI_O))) 790 return (NULL); 791 792 if ((mi_o = (MI_OP)mi_zalloc(size + sizeof (MI_O))) == NULL) 793 return (NULL); 794 mi_o++; 795 return ((IDP)mi_o); 796 } 797 798 /* 799 * MODOPEN means just link in without respect of mi_o_dev. 800 * A NULL devp can be used to create a detached instance 801 * Otherwise self-clone the device. 802 */ 803 /* ARGSUSED3 */ 804 int 805 mi_open_link(void **mi_headp, IDP ptr, dev_t *devp, int flag, int sflag, 806 cred_t *credp) 807 { 808 mi_head_t *mi_head = *(mi_head_t **)mi_headp; 809 MI_OP insert; 810 MI_OP mi_o; 811 dev_t dev; 812 813 if (mi_head == NULL) { 814 char arena_name[50]; 815 char *head_name; 816 ulong_t offset; 817 818 head_name = kobj_getsymname((uintptr_t)mi_headp, &offset); 819 if (head_name != NULL && offset == 0) { 820 (void) sprintf(arena_name, "%s_", head_name); 821 } else { 822 (void) sprintf(arena_name, "Hex0x%p_", 823 (void *)mi_headp); 824 } 825 (void) sprintf(strchr(arena_name, '_') + 1, "minor"); 826 mi_head = (mi_head_t *)mi_zalloc_sleep(sizeof (mi_head_t)); 827 *mi_headp = (void *)mi_head; 828 /* Setup doubly linked list */ 829 mi_head->mh_o.mi_o_next = &mi_head->mh_o; 830 mi_head->mh_o.mi_o_prev = &mi_head->mh_o; 831 mi_head->mh_o.mi_o_dev = 0; /* For asserts only */ 832 mi_head->mh_arena = (vmem_t *)inet_minor_create(arena_name, 833 INET_MIN_DEV, KM_SLEEP); 834 } 835 ASSERT(ptr != NULL); 836 mi_o = (MI_OP)ptr; 837 mi_o--; 838 839 if (sflag == MODOPEN) { 840 devp = NULL; 841 /* 842 * Set device number to MAXMIN + incrementing number. 843 */ 844 dev = MAXMIN + ++mi_head->mh_module_dev; 845 /* check for wraparound */ 846 if (dev <= MAXMIN) { 847 dev = MAXMIN + 1; 848 mi_head->mh_module_dev = 1; 849 } 850 } else if (devp == NULL) { 851 /* Detached open */ 852 dev = (dev_t)OPENFAIL; 853 } else if ((dev = inet_minor_alloc(mi_head->mh_arena)) == 0) { 854 return (EBUSY); 855 } 856 857 mi_o->mi_o_dev = dev; 858 insert = (&mi_head->mh_o); 859 mi_o->mi_o_next = insert; 860 insert->mi_o_prev->mi_o_next = mi_o; 861 mi_o->mi_o_prev = insert->mi_o_prev; 862 insert->mi_o_prev = mi_o; 863 864 if (sflag == MODOPEN) 865 mi_o->mi_o_isdev = B_FALSE; 866 else 867 mi_o->mi_o_isdev = B_TRUE; 868 869 if (devp) 870 *devp = makedevice(getemajor(*devp), (minor_t)dev); 871 return (0); 872 } 873 874 uint8_t * 875 mi_offset_param(mblk_t *mp, size_t offset, size_t len) 876 { 877 size_t msg_len; 878 879 if (!mp) 880 return (NULL); 881 msg_len = mp->b_wptr - mp->b_rptr; 882 if (msg_len == 0 || offset > msg_len || len > msg_len || 883 (offset + len) > msg_len || len == 0) 884 return (NULL); 885 return (&mp->b_rptr[offset]); 886 } 887 888 uint8_t * 889 mi_offset_paramc(mblk_t *mp, size_t offset, size_t len) 890 { 891 uint8_t *param; 892 893 for (; mp; mp = mp->b_cont) { 894 int type = mp->b_datap->db_type; 895 if (datamsg(type)) { 896 if (param = mi_offset_param(mp, offset, len)) 897 return (param); 898 if (offset < mp->b_wptr - mp->b_rptr) 899 break; 900 offset -= mp->b_wptr - mp->b_rptr; 901 } 902 } 903 return (NULL); 904 } 905 906 907 boolean_t 908 mi_set_sth_hiwat(queue_t *q, size_t size) 909 { 910 MBLKP mp; 911 STROPTP stropt; 912 913 if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 914 return (B_FALSE); 915 mp->b_datap->db_type = M_SETOPTS; 916 mp->b_wptr += sizeof (*stropt); 917 stropt = (STROPTP)mp->b_rptr; 918 stropt->so_flags = SO_HIWAT; 919 stropt->so_hiwat = size; 920 putnext(q, mp); 921 return (B_TRUE); 922 } 923 924 boolean_t 925 mi_set_sth_lowat(queue_t *q, size_t size) 926 { 927 MBLKP mp; 928 STROPTP stropt; 929 930 if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 931 return (B_FALSE); 932 mp->b_datap->db_type = M_SETOPTS; 933 mp->b_wptr += sizeof (*stropt); 934 stropt = (STROPTP)mp->b_rptr; 935 stropt->so_flags = SO_LOWAT; 936 stropt->so_lowat = size; 937 putnext(q, mp); 938 return (B_TRUE); 939 } 940 941 /* ARGSUSED */ 942 boolean_t 943 mi_set_sth_maxblk(queue_t *q, ssize_t size) 944 { 945 MBLKP mp; 946 STROPTP stropt; 947 948 if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 949 return (B_FALSE); 950 mp->b_datap->db_type = M_SETOPTS; 951 mp->b_wptr += sizeof (*stropt); 952 stropt = (STROPTP)mp->b_rptr; 953 stropt->so_flags = SO_MAXBLK; 954 stropt->so_maxblk = size; 955 putnext(q, mp); 956 return (B_TRUE); 957 } 958 959 boolean_t 960 mi_set_sth_copyopt(queue_t *q, int copyopt) 961 { 962 MBLKP mp; 963 STROPTP stropt; 964 965 if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 966 return (B_FALSE); 967 mp->b_datap->db_type = M_SETOPTS; 968 mp->b_wptr += sizeof (*stropt); 969 stropt = (STROPTP)mp->b_rptr; 970 stropt->so_flags = SO_COPYOPT; 971 stropt->so_copyopt = (ushort_t)copyopt; 972 putnext(q, mp); 973 return (B_TRUE); 974 } 975 976 boolean_t 977 mi_set_sth_wroff(queue_t *q, size_t size) 978 { 979 MBLKP mp; 980 STROPTP stropt; 981 982 if (!(mp = allocb(sizeof (*stropt), BPRI_LO))) 983 return (B_FALSE); 984 mp->b_datap->db_type = M_SETOPTS; 985 mp->b_wptr += sizeof (*stropt); 986 stropt = (STROPTP)mp->b_rptr; 987 stropt->so_flags = SO_WROFF; 988 stropt->so_wroff = (ushort_t)size; 989 putnext(q, mp); 990 return (B_TRUE); 991 } 992 993 int 994 mi_sprintf(char *buf, char *fmt, ...) 995 { 996 va_list ap; 997 int count = -1; 998 va_start(ap, fmt); 999 if (buf) { 1000 count = mi_iprintf(fmt, ap, (pfi_t)mi_sprintf_putc, 1001 (char *)&buf); 1002 if (count != -1) 1003 (void) mi_sprintf_putc((char *)&buf, '\0'); 1004 } 1005 va_end(ap); 1006 return (count); 1007 } 1008 1009 /* Used to count without writing data */ 1010 /* ARGSUSED1 */ 1011 static int 1012 mi_sprintf_noop(char *cookie, int ch) 1013 { 1014 char **cpp = (char **)cookie; 1015 1016 (*cpp)++; 1017 return (1); 1018 } 1019 1020 int 1021 mi_sprintf_putc(char *cookie, int ch) 1022 { 1023 char **cpp = (char **)cookie; 1024 1025 **cpp = (char)ch; 1026 (*cpp)++; 1027 return (1); 1028 } 1029 1030 int 1031 mi_strcmp(const char *cp1, const char *cp2) 1032 { 1033 while (*cp1++ == *cp2++) { 1034 if (!cp2[-1]) 1035 return (0); 1036 } 1037 return ((uint_t)cp2[-1] & 0xFF) - ((uint_t)cp1[-1] & 0xFF); 1038 } 1039 1040 size_t 1041 mi_strlen(const char *str) 1042 { 1043 const char *cp = str; 1044 1045 while (*cp != '\0') 1046 cp++; 1047 return ((int)(cp - str)); 1048 } 1049 1050 int 1051 mi_strlog(queue_t *q, char level, ushort_t flags, char *fmt, ...) 1052 { 1053 va_list ap; 1054 char buf[200]; 1055 char *alloc_buf = buf; 1056 int count = -1; 1057 char *cp; 1058 short mid; 1059 int ret; 1060 short sid; 1061 1062 sid = 0; 1063 mid = 0; 1064 if (q != NULL) { 1065 mid = q->q_qinfo->qi_minfo->mi_idnum; 1066 } 1067 1068 /* Find out how many bytes we need and allocate if necesary */ 1069 va_start(ap, fmt); 1070 cp = buf; 1071 count = mi_iprintf(fmt, ap, mi_sprintf_noop, (char *)&cp); 1072 if (count > sizeof (buf) && 1073 !(alloc_buf = mi_alloc((uint_t)count + 2, BPRI_MED))) { 1074 va_end(ap); 1075 return (-1); 1076 } 1077 va_end(ap); 1078 1079 va_start(ap, fmt); 1080 cp = alloc_buf; 1081 count = mi_iprintf(fmt, ap, mi_sprintf_putc, (char *)&cp); 1082 if (count != -1) 1083 (void) mi_sprintf_putc((char *)&cp, '\0'); 1084 else 1085 alloc_buf[0] = '\0'; 1086 va_end(ap); 1087 1088 ret = strlog(mid, sid, level, flags, alloc_buf); 1089 if (alloc_buf != buf) 1090 mi_free(alloc_buf); 1091 return (ret); 1092 } 1093 1094 long 1095 mi_strtol(const char *str, char **ptr, int base) 1096 { 1097 const char *cp; 1098 int digits; 1099 long value; 1100 boolean_t is_negative; 1101 1102 cp = str; 1103 while (*cp == ' ' || *cp == '\t' || *cp == '\n') 1104 cp++; 1105 is_negative = (*cp == '-'); 1106 if (is_negative) 1107 cp++; 1108 if (base == 0) { 1109 base = 10; 1110 if (*cp == '0') { 1111 base = 8; 1112 cp++; 1113 if (*cp == 'x' || *cp == 'X') { 1114 base = 16; 1115 cp++; 1116 } 1117 } 1118 } 1119 value = 0; 1120 for (; *cp != '\0'; cp++) { 1121 if (*cp >= '0' && *cp <= '9') 1122 digits = *cp - '0'; 1123 else if (*cp >= 'a' && *cp <= 'f') 1124 digits = *cp - 'a' + 10; 1125 else if (*cp >= 'A' && *cp <= 'F') 1126 digits = *cp - 'A' + 10; 1127 else 1128 break; 1129 if (digits >= base) 1130 break; 1131 value = (value * base) + digits; 1132 } 1133 /* Note: we cast away const here deliberately */ 1134 if (ptr != NULL) 1135 *ptr = (char *)cp; 1136 if (is_negative) 1137 value = -value; 1138 return (value); 1139 } 1140 1141 /* 1142 * mi_timer mechanism. 1143 * 1144 * Each timer is represented by a timer mblk and a (streams) queue. When the 1145 * timer fires the timer mblk will be put on the associated streams queue 1146 * so that the streams module can process the timer even in its service 1147 * procedure. 1148 * 1149 * The interface consists of 4 entry points: 1150 * mi_timer_alloc - create a timer mblk 1151 * mi_timer_free - free a timer mblk 1152 * mi_timer - start, restart, stop, or move the 1153 * timer to a different queue 1154 * mi_timer_valid - called by streams module to verify that 1155 * the timer did indeed fire. 1156 */ 1157 1158 1159 1160 1161 /* 1162 * Start, restart, stop, or move the timer to a new queue. 1163 * If "tim" is -2 the timer is moved to a different queue. 1164 * If "tim" is -1 the timer is stopped. 1165 * Otherwise, the timer is stopped if it is already running, and 1166 * set to fire tim milliseconds from now. 1167 */ 1168 1169 void 1170 mi_timer(queue_t *q, MBLKP mp, clock_t tim) 1171 { 1172 MTBP mtb; 1173 int state; 1174 1175 ASSERT(tim >= -2); 1176 if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1177 return; 1178 mtb = (MTBP)mp->b_datap->db_base; 1179 ASSERT(mp->b_datap->db_type == M_PCSIG); 1180 if (tim >= 0) { 1181 mtb->mtb_q = q; 1182 state = mtb->mtb_state; 1183 tim = MSEC_TO_TICK(tim); 1184 if (state == TB_RUNNING) { 1185 if (untimeout(mtb->mtb_tid) < 0) { 1186 /* Message has already been putq */ 1187 ASSERT(mtb->mtb_q->q_first == mp || 1188 mp->b_prev || mp->b_next); 1189 mtb->mtb_state = TB_RESCHED; 1190 mtb->mtb_time_left = tim; 1191 /* mi_timer_valid will start timer */ 1192 return; 1193 } 1194 } else if (state != TB_IDLE) { 1195 ASSERT(state != TB_TO_BE_FREED); 1196 if (state == TB_CANCELLED) { 1197 ASSERT(mtb->mtb_q->q_first == mp || 1198 mp->b_prev || mp->b_next); 1199 mtb->mtb_state = TB_RESCHED; 1200 mtb->mtb_time_left = tim; 1201 /* mi_timer_valid will start timer */ 1202 return; 1203 } 1204 if (state == TB_RESCHED) { 1205 ASSERT(mtb->mtb_q->q_first == mp || 1206 mp->b_prev || mp->b_next); 1207 mtb->mtb_time_left = tim; 1208 /* mi_timer_valid will start timer */ 1209 return; 1210 } 1211 } 1212 mtb->mtb_state = TB_RUNNING; 1213 mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim); 1214 return; 1215 } 1216 switch (tim) { 1217 case -1: 1218 mi_timer_stop(mp); 1219 break; 1220 case -2: 1221 mi_timer_move(q, mp); 1222 break; 1223 } 1224 } 1225 1226 /* 1227 * Allocate an M_PCSIG timer message. The space between db_base and 1228 * b_rptr is used by the mi_timer mechanism, and after b_rptr there are 1229 * "size" bytes that the caller can use for its own purposes. 1230 * 1231 * Note that db_type has to be a priority message since otherwise 1232 * the putq will not cause the service procedure to run when 1233 * there is flow control. 1234 */ 1235 MBLKP 1236 mi_timer_alloc(size_t size) 1237 { 1238 MBLKP mp; 1239 MTBP mtb; 1240 1241 if ((mp = allocb(size + sizeof (MTB), BPRI_HI)) != NULL) { 1242 mp->b_datap->db_type = M_PCSIG; 1243 mtb = (MTBP)mp->b_datap->db_base; 1244 mp->b_rptr = (uchar_t *)&mtb[1]; 1245 mp->b_wptr = mp->b_rptr + size; 1246 mtb->mtb_state = TB_IDLE; 1247 mtb->mtb_mp = mp; 1248 mtb->mtb_q = NULL; 1249 return (mp); 1250 } 1251 return (NULL); 1252 } 1253 1254 /* 1255 * timeout() callback function. 1256 * Put the message on the current queue. 1257 * If the timer is stopped or moved to a different queue after 1258 * it has fired then mi_timer() and mi_timer_valid() will clean 1259 * things up. 1260 */ 1261 static int 1262 mi_timer_fire(MTBP mtb) 1263 { 1264 ASSERT(mtb == (MTBP)mtb->mtb_mp->b_datap->db_base); 1265 ASSERT(mtb->mtb_mp->b_datap->db_type == M_PCSIG); 1266 return (putq(mtb->mtb_q, mtb->mtb_mp)); 1267 } 1268 1269 /* 1270 * Logically free a timer mblk (that might have a pending timeout().) 1271 * If the timer has fired and the mblk has been put on the queue then 1272 * mi_timer_valid will free the mblk. 1273 */ 1274 1275 void 1276 mi_timer_free(MBLKP mp) 1277 { 1278 MTBP mtb; 1279 int state; 1280 1281 if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1282 return; 1283 mtb = (MTBP)mp->b_datap->db_base; 1284 state = mtb->mtb_state; 1285 if (state == TB_RUNNING) { 1286 if (untimeout(mtb->mtb_tid) < 0) { 1287 /* Message has already been putq */ 1288 ASSERT(mtb->mtb_q->q_first == mp || 1289 mp->b_prev || mp->b_next); 1290 mtb->mtb_state = TB_TO_BE_FREED; 1291 /* mi_timer_valid will free the mblk */ 1292 return; 1293 } 1294 } else if (state != TB_IDLE) { 1295 /* Message has already been putq */ 1296 ASSERT(mtb->mtb_q->q_first == mp || 1297 mp->b_prev || mp->b_next); 1298 ASSERT(state != TB_TO_BE_FREED); 1299 mtb->mtb_state = TB_TO_BE_FREED; 1300 /* mi_timer_valid will free the mblk */ 1301 return; 1302 } 1303 ASSERT(mtb->mtb_q == NULL || mtb->mtb_q->q_first != mp); 1304 freemsg(mp); 1305 } 1306 1307 /* 1308 * Called from mi_timer(,,-2) 1309 */ 1310 void 1311 mi_timer_move(queue_t *q, MBLKP mp) 1312 { 1313 MTBP mtb; 1314 clock_t tim; 1315 1316 if (!q || !mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1317 return; 1318 1319 mtb = (MTBP)mp->b_datap->db_base; 1320 /* 1321 * Need to untimeout and restart to make 1322 * sure that the mblk is not about to be putq on the old queue 1323 * by mi_timer_fire. 1324 */ 1325 if (mtb->mtb_state == TB_RUNNING) { 1326 if ((tim = untimeout(mtb->mtb_tid)) < 0) { 1327 /* 1328 * Message has already been putq. Move from old queue 1329 * to new queue. 1330 */ 1331 ASSERT(mtb->mtb_q->q_first == mp || 1332 mp->b_prev || mp->b_next); 1333 rmvq(mtb->mtb_q, mp); 1334 ASSERT(mtb->mtb_q->q_first != mp && 1335 mp->b_prev == NULL && mp->b_next == NULL); 1336 mtb->mtb_q = q; 1337 (void) putq(mtb->mtb_q, mp); 1338 return; 1339 } 1340 mtb->mtb_q = q; 1341 mtb->mtb_state = TB_RUNNING; 1342 mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, mtb, tim); 1343 } else if (mtb->mtb_state != TB_IDLE) { 1344 ASSERT(mtb->mtb_state != TB_TO_BE_FREED); 1345 /* 1346 * Message is already sitting on queue. Move to new queue. 1347 */ 1348 ASSERT(mtb->mtb_q->q_first == mp || 1349 mp->b_prev || mp->b_next); 1350 rmvq(mtb->mtb_q, mp); 1351 ASSERT(mtb->mtb_q->q_first != mp && 1352 mp->b_prev == NULL && mp->b_next == NULL); 1353 mtb->mtb_q = q; 1354 (void) putq(mtb->mtb_q, mp); 1355 } else 1356 mtb->mtb_q = q; 1357 } 1358 1359 /* 1360 * Called from mi_timer(,,-1) 1361 */ 1362 void 1363 mi_timer_stop(MBLKP mp) 1364 { 1365 MTBP mtb; 1366 int state; 1367 1368 if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB)) 1369 return; 1370 1371 mtb = (MTBP)mp->b_datap->db_base; 1372 state = mtb->mtb_state; 1373 if (state == TB_RUNNING) { 1374 if (untimeout(mtb->mtb_tid) < 0) { 1375 /* Message has already been putq */ 1376 ASSERT(mtb->mtb_q->q_first == mp || 1377 mp->b_prev || mp->b_next); 1378 mtb->mtb_state = TB_CANCELLED; 1379 } else { 1380 mtb->mtb_state = TB_IDLE; 1381 } 1382 } else if (state == TB_RESCHED) { 1383 ASSERT(mtb->mtb_q->q_first == mp || 1384 mp->b_prev || mp->b_next); 1385 mtb->mtb_state = TB_CANCELLED; 1386 } 1387 } 1388 1389 /* 1390 * The user of the mi_timer mechanism is required to call mi_timer_valid() for 1391 * each M_PCSIG message processed in the service procedures. 1392 * mi_timer_valid will return "true" if the timer actually did fire. 1393 */ 1394 1395 boolean_t 1396 mi_timer_valid(MBLKP mp) 1397 { 1398 MTBP mtb; 1399 int state; 1400 1401 if (!mp || (mp->b_rptr - mp->b_datap->db_base) != sizeof (MTB) || 1402 mp->b_datap->db_type != M_PCSIG) 1403 return (B_FALSE); 1404 mtb = (MTBP)mp->b_datap->db_base; 1405 state = mtb->mtb_state; 1406 if (state != TB_RUNNING) { 1407 ASSERT(state != TB_IDLE); 1408 if (state == TB_TO_BE_FREED) { 1409 /* 1410 * mi_timer_free was called after the message 1411 * was putq'ed. 1412 */ 1413 freemsg(mp); 1414 return (B_FALSE); 1415 } 1416 if (state == TB_CANCELLED) { 1417 /* The timer was stopped after the mblk was putq'ed */ 1418 mtb->mtb_state = TB_IDLE; 1419 return (B_FALSE); 1420 } 1421 if (state == TB_RESCHED) { 1422 /* 1423 * The timer was stopped and then restarted after 1424 * the mblk was putq'ed. 1425 * mtb_time_left contains the number of ticks that 1426 * the timer was restarted with. 1427 */ 1428 mtb->mtb_state = TB_RUNNING; 1429 mtb->mtb_tid = timeout((pfv_t)mi_timer_fire, 1430 mtb, mtb->mtb_time_left); 1431 return (B_FALSE); 1432 } 1433 } 1434 mtb->mtb_state = TB_IDLE; 1435 return (B_TRUE); 1436 } 1437 1438 static void 1439 mi_tpi_addr_and_opt(MBLKP mp, char *addr, t_scalar_t addr_length, 1440 char *opt, t_scalar_t opt_length) 1441 { 1442 struct T_unitdata_ind *tudi; 1443 1444 /* 1445 * This code is used more than just for unitdata ind 1446 * (also for T_CONN_IND and T_CONN_CON) and 1447 * relies on correct functioning on the happy 1448 * coincidence that the the address and option buffers 1449 * represented by length/offset in all these primitives 1450 * are isomorphic in terms of offset from start of data 1451 * structure 1452 */ 1453 tudi = (struct T_unitdata_ind *)mp->b_rptr; 1454 tudi->SRC_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr); 1455 tudi->SRC_length = addr_length; 1456 if (addr_length > 0) { 1457 bcopy(addr, (char *)mp->b_wptr, addr_length); 1458 mp->b_wptr += addr_length; 1459 } 1460 tudi->OPT_offset = (t_scalar_t)(mp->b_wptr - mp->b_rptr); 1461 tudi->OPT_length = opt_length; 1462 if (opt_length > 0) { 1463 bcopy(opt, (char *)mp->b_wptr, opt_length); 1464 mp->b_wptr += opt_length; 1465 } 1466 } 1467 1468 MBLKP 1469 mi_tpi_conn_con(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt, 1470 t_scalar_t opt_length) 1471 { 1472 size_t len; 1473 MBLKP mp; 1474 1475 len = sizeof (struct T_conn_con) + src_length + opt_length; 1476 if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_CON)) != NULL) { 1477 mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_con)]; 1478 mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 1479 } 1480 return (mp); 1481 } 1482 1483 MBLKP 1484 mi_tpi_conn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, char *opt, 1485 t_scalar_t opt_length, t_scalar_t seqnum) 1486 { 1487 size_t len; 1488 MBLKP mp; 1489 1490 len = sizeof (struct T_conn_ind) + src_length + opt_length; 1491 if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_CONN_IND)) != NULL) { 1492 mp->b_wptr = &mp->b_rptr[sizeof (struct T_conn_ind)]; 1493 mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 1494 ((struct T_conn_ind *)mp->b_rptr)->SEQ_number = seqnum; 1495 mp->b_datap->db_type = M_PROTO; 1496 } 1497 return (mp); 1498 } 1499 1500 MBLKP 1501 mi_tpi_extconn_ind(MBLKP trailer_mp, char *src, t_scalar_t src_length, 1502 char *opt, t_scalar_t opt_length, char *dst, t_scalar_t dst_length, 1503 t_scalar_t seqnum) 1504 { 1505 size_t len; 1506 MBLKP mp; 1507 1508 len = sizeof (struct T_extconn_ind) + src_length + opt_length + 1509 dst_length; 1510 if ((mp = mi_tpi_trailer_alloc(trailer_mp, len, T_EXTCONN_IND)) != 1511 NULL) { 1512 mp->b_wptr = &mp->b_rptr[sizeof (struct T_extconn_ind)]; 1513 mi_tpi_addr_and_opt(mp, src, src_length, opt, opt_length); 1514 ((struct T_extconn_ind *)mp->b_rptr)->DEST_length = dst_length; 1515 ((struct T_extconn_ind *)mp->b_rptr)->DEST_offset = 1516 (t_scalar_t)(mp->b_wptr - mp->b_rptr); 1517 if (dst_length > 0) { 1518 bcopy(dst, (char *)mp->b_wptr, dst_length); 1519 mp->b_wptr += dst_length; 1520 } 1521 ((struct T_extconn_ind *)mp->b_rptr)->SEQ_number = seqnum; 1522 mp->b_datap->db_type = M_PROTO; 1523 } 1524 return (mp); 1525 } 1526 1527 MBLKP 1528 mi_tpi_discon_ind(MBLKP trailer_mp, t_scalar_t reason, t_scalar_t seqnum) 1529 { 1530 MBLKP mp; 1531 struct T_discon_ind *tdi; 1532 1533 if ((mp = mi_tpi_trailer_alloc(trailer_mp, 1534 sizeof (struct T_discon_ind), T_DISCON_IND)) != NULL) { 1535 tdi = (struct T_discon_ind *)mp->b_rptr; 1536 tdi->DISCON_reason = reason; 1537 tdi->SEQ_number = seqnum; 1538 } 1539 return (mp); 1540 } 1541 1542 /* 1543 * Allocate and fill in a TPI err ack packet using the 'mp' passed in 1544 * for the 'error_prim' context as well as sacrifice. 1545 */ 1546 MBLKP 1547 mi_tpi_err_ack_alloc(MBLKP mp, t_scalar_t tlierr, int unixerr) 1548 { 1549 struct T_error_ack *teackp; 1550 t_scalar_t error_prim; 1551 1552 if (!mp) 1553 return (NULL); 1554 error_prim = ((TPRIMP)mp->b_rptr)->type; 1555 if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack), 1556 M_PCPROTO, T_ERROR_ACK)) != NULL) { 1557 teackp = (struct T_error_ack *)mp->b_rptr; 1558 teackp->ERROR_prim = error_prim; 1559 teackp->TLI_error = tlierr; 1560 teackp->UNIX_error = unixerr; 1561 } 1562 return (mp); 1563 } 1564 1565 MBLKP 1566 mi_tpi_ok_ack_alloc_extra(MBLKP mp, int extra) 1567 { 1568 t_scalar_t correct_prim; 1569 1570 if (!mp) 1571 return (NULL); 1572 correct_prim = ((TPRIMP)mp->b_rptr)->type; 1573 if ((mp = tpi_ack_alloc(mp, sizeof (struct T_ok_ack) + extra, 1574 M_PCPROTO, T_OK_ACK)) != NULL) { 1575 ((struct T_ok_ack *)mp->b_rptr)->CORRECT_prim = correct_prim; 1576 mp->b_wptr -= extra; 1577 } 1578 return (mp); 1579 } 1580 1581 MBLKP 1582 mi_tpi_ok_ack_alloc(MBLKP mp) 1583 { 1584 return (mi_tpi_ok_ack_alloc_extra(mp, 0)); 1585 } 1586 1587 MBLKP 1588 mi_tpi_ordrel_ind(void) 1589 { 1590 MBLKP mp; 1591 1592 if ((mp = allocb(sizeof (struct T_ordrel_ind), BPRI_HI)) != NULL) { 1593 mp->b_datap->db_type = M_PROTO; 1594 ((struct T_ordrel_ind *)mp->b_rptr)->PRIM_type = T_ORDREL_IND; 1595 mp->b_wptr += sizeof (struct T_ordrel_ind); 1596 } 1597 return (mp); 1598 } 1599 1600 static MBLKP 1601 mi_tpi_trailer_alloc(MBLKP trailer_mp, size_t size, t_scalar_t type) 1602 { 1603 MBLKP mp; 1604 1605 if ((mp = allocb(size, BPRI_MED)) != NULL) { 1606 mp->b_cont = trailer_mp; 1607 mp->b_datap->db_type = M_PROTO; 1608 ((union T_primitives *)mp->b_rptr)->type = type; 1609 mp->b_wptr += size; 1610 } 1611 return (mp); 1612 } 1613 1614 MBLKP 1615 mi_tpi_uderror_ind(char *dest, t_scalar_t dest_length, char *opt, 1616 t_scalar_t opt_length, t_scalar_t error) 1617 { 1618 size_t len; 1619 MBLKP mp; 1620 struct T_uderror_ind *tudei; 1621 1622 len = sizeof (struct T_uderror_ind) + dest_length + opt_length; 1623 if ((mp = allocb(len, BPRI_HI)) != NULL) { 1624 mp->b_datap->db_type = M_PROTO; 1625 tudei = (struct T_uderror_ind *)mp->b_rptr; 1626 tudei->PRIM_type = T_UDERROR_IND; 1627 tudei->ERROR_type = error; 1628 mp->b_wptr = &mp->b_rptr[sizeof (struct T_uderror_ind)]; 1629 mi_tpi_addr_and_opt(mp, dest, dest_length, opt, opt_length); 1630 } 1631 return (mp); 1632 } 1633 1634 IDP 1635 mi_zalloc(size_t size) 1636 { 1637 IDP ptr; 1638 1639 if (ptr = mi_alloc(size, BPRI_LO)) 1640 bzero(ptr, size); 1641 return (ptr); 1642 } 1643 1644 IDP 1645 mi_zalloc_sleep(size_t size) 1646 { 1647 IDP ptr; 1648 1649 if (ptr = mi_alloc_sleep(size, BPRI_LO)) 1650 bzero(ptr, size); 1651 return (ptr); 1652 } 1653