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