1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 /* 31 * hptproc.c sysctl support 32 */ 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/malloc.h> 37 #include <sys/sysctl.h> 38 #include <machine/stdarg.h> 39 40 #ifndef __KERNEL__ 41 #define __KERNEL__ 42 #endif 43 44 #include <dev/hptmv/global.h> 45 #include <dev/hptmv/hptintf.h> 46 #include <dev/hptmv/osbsd.h> 47 #include <dev/hptmv/access601.h> 48 49 int hpt_rescan_all(void); 50 51 /***************************************************************************/ 52 53 static char hptproc_buffer[256]; 54 extern char DRIVER_VERSION[]; 55 56 typedef struct sysctl_req HPT_GET_INFO; 57 58 static int 59 hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length) 60 { 61 int orig_length = length+4; 62 PVBus _vbus_p = &pAdapter->VBus; 63 PVDevice pArray; 64 PVDevice pSubArray, pVDev; 65 UINT i, iarray, ichan; 66 struct cam_periph *periph = NULL; 67 68 mtx_lock(&pAdapter->lock); 69 #ifdef SUPPORT_ARRAY 70 if (length>=8 && strncmp(buffer, "rebuild ", 8)==0) 71 { 72 buffer+=8; 73 length-=8; 74 if (length>=5 && strncmp(buffer, "start", 5)==0) 75 { 76 for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 77 if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 78 continue; 79 else{ 80 if (pArray->u.array.rf_need_rebuild && !pArray->u.array.rf_rebuilding) 81 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 82 (UCHAR)((pArray->u.array.CriticalMembers || pArray->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 83 } 84 mtx_unlock(&pAdapter->lock); 85 return orig_length; 86 } 87 else if (length>=4 && strncmp(buffer, "stop", 4)==0) 88 { 89 for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 90 if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 91 continue; 92 else{ 93 if (pArray->u.array.rf_rebuilding) 94 pArray->u.array.rf_abort_rebuild = 1; 95 } 96 mtx_unlock(&pAdapter->lock); 97 return orig_length; 98 } 99 else if (length>=3 && buffer[1]==','&& buffer[0]>='1'&& buffer[2]>='1') 100 { 101 iarray = buffer[0]-'1'; 102 ichan = buffer[2]-'1'; 103 104 if(iarray >= MAX_VDEVICE_PER_VBUS || ichan >= MV_SATA_CHANNELS_NUM) return -EINVAL; 105 106 pArray = _vbus_p->pVDevice[iarray]; 107 if (!pArray || (pArray->vf_online == 0)) { 108 mtx_unlock(&pAdapter->lock); 109 return -EINVAL; 110 } 111 112 for (i=0;i<MV_SATA_CHANNELS_NUM;i++) 113 if(i == ichan) 114 goto rebuild; 115 116 mtx_unlock(&pAdapter->lock); 117 return -EINVAL; 118 119 rebuild: 120 pVDev = &pAdapter->VDevices[ichan]; 121 if(!pVDev->u.disk.df_on_line || pVDev->pParent) { 122 mtx_unlock(&pAdapter->lock); 123 return -EINVAL; 124 } 125 126 /* Not allow to use a mounted disk ??? test*/ 127 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) 128 if(pVDev == _vbus_p->pVDevice[i]) 129 { 130 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i); 131 if (periph != NULL && periph->refcount >= 1) 132 { 133 hpt_printk(("Can not use disk used by OS!\n")); 134 mtx_unlock(&pAdapter->lock); 135 return -EINVAL; 136 } 137 /* the Mounted Disk isn't delete */ 138 } 139 140 switch(pArray->VDeviceType) 141 { 142 case VD_RAID_1: 143 case VD_RAID_5: 144 { 145 pSubArray = pArray; 146 loop: 147 if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) { 148 mtx_unlock(&pAdapter->lock); 149 return -EINVAL; 150 } 151 pSubArray->u.array.rf_auto_rebuild = 0; 152 pSubArray->u.array.rf_abort_rebuild = 0; 153 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pSubArray, DUPLICATE); 154 break; 155 } 156 case VD_RAID_0: 157 for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) 158 if(pArray->u.array.pMember[i] && mIsArray(pArray->u.array.pMember[i]) && 159 (pArray->u.array.pMember[i]->u.array.rf_broken == 1)) 160 { 161 pSubArray = pArray->u.array.pMember[i]; 162 goto loop; 163 } 164 default: 165 mtx_unlock(&pAdapter->lock); 166 return -EINVAL; 167 } 168 mtx_unlock(&pAdapter->lock); 169 return orig_length; 170 } 171 } 172 else if (length>=7 && strncmp(buffer, "verify ", 7)==0) 173 { 174 buffer+=7; 175 length-=7; 176 if (length>=6 && strncmp(buffer, "start ", 6)==0) 177 { 178 buffer+=6; 179 length-=6; 180 if (length>=1 && *buffer>='1') 181 { 182 iarray = *buffer-'1'; 183 if(iarray >= MAX_VDEVICE_PER_VBUS) { 184 mtx_unlock(&pAdapter->lock); 185 return -EINVAL; 186 } 187 188 pArray = _vbus_p->pVDevice[iarray]; 189 if (!pArray || (pArray->vf_online == 0)) { 190 mtx_unlock(&pAdapter->lock); 191 return -EINVAL; 192 } 193 194 if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) { 195 mtx_unlock(&pAdapter->lock); 196 return -EINVAL; 197 } 198 199 if (!(pArray->u.array.rf_need_rebuild || 200 pArray->u.array.rf_rebuilding || 201 pArray->u.array.rf_verifying || 202 pArray->u.array.rf_initializing)) 203 { 204 pArray->u.array.RebuildSectors = 0; 205 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY); 206 } 207 mtx_unlock(&pAdapter->lock); 208 return orig_length; 209 } 210 } 211 else if (length>=5 && strncmp(buffer, "stop ", 5)==0) 212 { 213 buffer+=5; 214 length-=5; 215 if (length>=1 && *buffer>='1') 216 { 217 iarray = *buffer-'1'; 218 if(iarray >= MAX_VDEVICE_PER_VBUS) { 219 mtx_unlock(&pAdapter->lock); 220 return -EINVAL; 221 } 222 223 pArray = _vbus_p->pVDevice[iarray]; 224 if (!pArray || (pArray->vf_online == 0)) { 225 mtx_unlock(&pAdapter->lock); 226 return -EINVAL; 227 } 228 if(pArray->u.array.rf_verifying) 229 { 230 pArray->u.array.rf_abort_rebuild = 1; 231 } 232 mtx_unlock(&pAdapter->lock); 233 return orig_length; 234 } 235 } 236 } 237 else 238 #ifdef _RAID5N_ 239 if (length>=10 && strncmp(buffer, "writeback ", 10)==0) { 240 buffer+=10; 241 length-=10; 242 if (length>=1 && *buffer>='0' && *buffer<='1') { 243 _vbus_(r5.enable_write_back) = *buffer-'0'; 244 if (_vbus_(r5.enable_write_back)) 245 hpt_printk(("RAID5 write back enabled")); 246 mtx_unlock(&pAdapter->lock); 247 return orig_length; 248 } 249 } 250 else 251 #endif 252 #endif 253 if (0) {} /* just to compile */ 254 #ifdef DEBUG 255 else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) { 256 buffer+=9; 257 length-=9; 258 if (length>=1 && *buffer>='0' && *buffer<='3') { 259 hpt_dbg_level = *buffer-'0'; 260 mtx_unlock(&pAdapter->lock); 261 return orig_length; 262 } 263 } 264 else if (length>=8 && strncmp(buffer, "disable ", 8)==0) { 265 /* TO DO */ 266 } 267 #endif 268 mtx_unlock(&pAdapter->lock); 269 270 return -EINVAL; 271 } 272 273 /* 274 * Since we have only one sysctl node, add adapter ID in the command 275 * line string: e.g. "hpt 0 rebuild start" 276 */ 277 static int 278 hpt_set_info(int length) 279 { 280 int retval; 281 282 #ifdef SUPPORT_IOCTL 283 PUCHAR ke_area; 284 int err; 285 DWORD dwRet; 286 PHPT_IOCTL_PARAM piop; 287 #endif 288 char *buffer = hptproc_buffer; 289 if (length >= 6) { 290 if (strncmp(buffer,"hpt ",4) == 0) { 291 IAL_ADAPTER_T *pAdapter; 292 retval = buffer[4]-'0'; 293 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 294 if (pAdapter->mvSataAdapter.adapterId==retval) 295 return (retval = hpt_set_asc_info(pAdapter, buffer+6, length-6)) >= 0? retval : -EINVAL; 296 } 297 return -EINVAL; 298 } 299 #ifdef SUPPORT_IOCTL 300 piop = (PHPT_IOCTL_PARAM)buffer; 301 if (piop->Magic == HPT_IOCTL_MAGIC || 302 piop->Magic == HPT_IOCTL_MAGIC32) { 303 KdPrintE(("ioctl=%d in=%p len=%d out=%p len=%d\n", 304 piop->dwIoControlCode, 305 piop->lpInBuffer, 306 piop->nInBufferSize, 307 piop->lpOutBuffer, 308 piop->nOutBufferSize)); 309 310 /* 311 * map buffer to kernel. 312 */ 313 if (piop->nInBufferSize > PAGE_SIZE || 314 piop->nOutBufferSize > PAGE_SIZE || 315 piop->nInBufferSize+piop->nOutBufferSize > PAGE_SIZE) { 316 KdPrintE(("User buffer too large\n")); 317 return -EINVAL; 318 } 319 320 ke_area = malloc(piop->nInBufferSize+piop->nOutBufferSize, M_DEVBUF, M_NOWAIT); 321 if (ke_area == NULL) { 322 KdPrintE(("Couldn't allocate kernel mem.\n")); 323 return -EINVAL; 324 } 325 326 if (piop->nInBufferSize) { 327 if (copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize) != 0) { 328 KdPrintE(("Failed to copyin from lpInBuffer\n")); 329 free(ke_area, M_DEVBUF); 330 return -EFAULT; 331 } 332 } 333 334 /* 335 * call kernel handler. 336 */ 337 err = Kernel_DeviceIoControl(&gIal_Adapter->VBus, 338 piop->dwIoControlCode, ke_area, piop->nInBufferSize, 339 ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet); 340 341 if (err==0) { 342 if (piop->nOutBufferSize) 343 copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize); 344 345 if (piop->lpBytesReturned) 346 copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD)); 347 348 free(ke_area, M_DEVBUF); 349 return length; 350 } 351 else KdPrintW(("Kernel_ioctl(): return %d\n", err)); 352 353 free(ke_area, M_DEVBUF); 354 return -EINVAL; 355 } else { 356 KdPrintW(("Wrong signature: %x\n", piop->Magic)); 357 return -EINVAL; 358 } 359 #endif 360 } 361 362 return -EINVAL; 363 } 364 365 #define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8)) 366 367 static void 368 get_disk_name(char *name, PDevice pDev) 369 { 370 int i; 371 MV_SATA_CHANNEL *pMvSataChannel = pDev->mv; 372 IDENTIFY_DATA2 *pIdentifyData = (IDENTIFY_DATA2 *)pMvSataChannel->identifyDevice; 373 374 for (i = 0; i < 10; i++) 375 ((WORD*)name)[i] = shortswap(pIdentifyData->ModelNumber[i]); 376 name[20] = '\0'; 377 } 378 379 static int 380 hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...) 381 { 382 int printfretval; 383 va_list ap; 384 385 if(fmt == NULL) { 386 *hptproc_buffer = 0; 387 return (SYSCTL_OUT(pinfo, hptproc_buffer, 1)); 388 } 389 else 390 { 391 va_start(ap, fmt); 392 printfretval = vsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap); 393 va_end(ap); 394 return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer))); 395 } 396 } 397 398 static void 399 hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan) 400 { 401 char name[32], arrayname[16], *status; 402 403 get_disk_name(name, &pVDev->u.disk); 404 405 if (!pVDev->u.disk.df_on_line) 406 status = "Disabled"; 407 else if (pVDev->VDeviceType==VD_SPARE) 408 status = "Spare "; 409 else 410 status = "Normal "; 411 412 #ifdef SUPPORT_ARRAY 413 if(pVDev->pParent) { 414 memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME); 415 if (pVDev->pParent->u.array.CriticalMembers & (1<<pVDev->bSerialNumber)) 416 status = "Degraded"; 417 } 418 else 419 #endif 420 arrayname[0]=0; 421 422 hpt_copy_info(pinfo, "Channel %d %s %5dMB %s %s\n", 423 iChan+1, 424 name, pVDev->VDeviceCapacity>>11, status, arrayname); 425 } 426 427 #ifdef SUPPORT_ARRAY 428 static void 429 hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray) 430 { 431 int i; 432 char *sType = NULL, *sStatus = NULL; 433 char buf[32]; 434 PVDevice pTmpArray; 435 436 switch (pArray->VDeviceType) { 437 case VD_RAID_0: 438 for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) 439 if(pArray->u.array.pMember[i]) { 440 if(mIsArray(pArray->u.array.pMember[i])) 441 sType = "RAID 1/0 "; 442 /* TO DO */ 443 else 444 sType = "RAID 0 "; 445 break; 446 } 447 break; 448 449 case VD_RAID_1: 450 sType = "RAID 1 "; 451 break; 452 453 case VD_JBOD: 454 sType = "JBOD "; 455 break; 456 457 case VD_RAID_5: 458 sType = "RAID 5 "; 459 break; 460 461 default: 462 sType = "N/A "; 463 break; 464 } 465 466 if (pArray->vf_online == 0) 467 sStatus = "Disabled"; 468 else if (pArray->u.array.rf_broken) 469 sStatus = "Critical"; 470 for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) 471 { 472 if (!sStatus) 473 { 474 if(mIsArray(pArray->u.array.pMember[i])) 475 pTmpArray = pArray->u.array.pMember[i]; 476 else 477 pTmpArray = pArray; 478 479 if (pTmpArray->u.array.rf_rebuilding) { 480 #ifdef DEBUG 481 sprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11)); 482 #else 483 sprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11))); 484 #endif 485 sStatus = buf; 486 } 487 else if (pTmpArray->u.array.rf_verifying) { 488 sprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11))); 489 sStatus = buf; 490 } 491 else if (pTmpArray->u.array.rf_need_rebuild) 492 sStatus = "Critical"; 493 else if (pTmpArray->u.array.rf_broken) 494 sStatus = "Critical"; 495 496 if(pTmpArray == pArray) goto out; 497 } 498 else 499 goto out; 500 } 501 out: 502 if (!sStatus) sStatus = "Normal"; 503 hpt_copy_info(pinfo, "%2d %11s %-20s %5lldMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus); 504 } 505 #endif 506 507 static int 508 hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo) 509 { 510 PVBus _vbus_p = &pAdapter->VBus; 511 struct cam_periph *periph = NULL; 512 UINT channel,j,i; 513 PVDevice pVDev; 514 515 #ifndef FOR_DEMO 516 mtx_lock(&pAdapter->lock); 517 if (pAdapter->beeping) { 518 pAdapter->beeping = 0; 519 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 520 } 521 mtx_unlock(&pAdapter->lock); 522 #endif 523 524 hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId); 525 526 hpt_copy_info(pinfo, "Physical device list\n"); 527 hpt_copy_info(pinfo, "Channel Model Capacity Status Array\n"); 528 hpt_copy_info(pinfo, "-------------------------------------------------------------------\n"); 529 530 for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 531 { 532 pVDev = &(pAdapter->VDevices[channel]); 533 if(pVDev->u.disk.df_on_line) 534 hpt_copy_disk_info(pinfo, pVDev, channel); 535 } 536 537 hpt_copy_info(pinfo, "\nLogical device list\n"); 538 hpt_copy_info(pinfo, "No. Type Name Capacity Status OsDisk\n"); 539 hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n"); 540 541 j=1; 542 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){ 543 pVDev = _vbus_p->pVDevice[i]; 544 if(pVDev){ 545 j=i+1; 546 #ifdef SUPPORT_ARRAY 547 if (mIsArray(pVDev)) 548 { 549 is_array: 550 hpt_copy_array_info(pinfo, j, pVDev); 551 } 552 else 553 #endif 554 { 555 char name[32]; 556 /* it may be add to an array after driver loaded, check it */ 557 #ifdef SUPPORT_ARRAY 558 if (pVDev->pParent) 559 /* in this case, pVDev can only be a RAID 1 source disk. */ 560 if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0]) 561 goto is_array; 562 #endif 563 get_disk_name(name, &pVDev->u.disk); 564 565 hpt_copy_info(pinfo, "%2d %s %s %5dMB %-16s", 566 j, "Single disk", name, pVDev->VDeviceCapacity>>11, 567 /* gmm 2001-6-19: Check if pDev has been added to an array. */ 568 ((pVDev->pParent) ? "Unavailable" : "Normal")); 569 } 570 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 571 if (periph == NULL) 572 hpt_copy_info(pinfo," %s\n","not registered"); 573 else 574 hpt_copy_info(pinfo," %s%d\n", periph->periph_name, periph->unit_number); 575 } 576 } 577 return 0; 578 } 579 580 static __inline int 581 hpt_proc_in(SYSCTL_HANDLER_ARGS, int *len) 582 { 583 int i, error=0; 584 585 *len = 0; 586 if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) { 587 error = EINVAL; 588 } else { 589 i = (req->newlen - req->newidx); 590 error = SYSCTL_IN(req, hptproc_buffer, i); 591 if (!error) 592 *len = i; 593 (hptproc_buffer)[i] = '\0'; 594 } 595 return (error); 596 } 597 598 static int 599 hpt_status(SYSCTL_HANDLER_ARGS) 600 { 601 int length, error=0, retval=0; 602 IAL_ADAPTER_T *pAdapter; 603 604 error = hpt_proc_in(oidp, arg1, arg2, req, &length); 605 606 if (req->newptr != NULL) 607 { 608 if (error || length == 0) 609 { 610 KdPrint(("error!\n")); 611 retval = EINVAL; 612 goto out; 613 } 614 615 if (hpt_set_info(length) >= 0) 616 retval = 0; 617 else 618 retval = EINVAL; 619 goto out; 620 } 621 622 hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION); 623 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 624 if (hpt_get_info(pAdapter, req) < 0) { 625 retval = EINVAL; 626 break; 627 } 628 } 629 630 hpt_copy_info(req, NULL); 631 goto out; 632 633 out: 634 return (retval); 635 } 636 637 638 #define xhptregister_node(name) hptregister_node(name) 639 640 #if __FreeBSD_version >= 1100024 641 #define hptregister_node(name) \ 642 SYSCTL_ROOT_NODE(OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \ 643 SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ 644 NULL, 0, hpt_status, "A", "Get/Set " #name " state") 645 #else 646 #define hptregister_node(name) \ 647 SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \ 648 SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ 649 NULL, 0, hpt_status, "A", "Get/Set " #name " state") 650 #endif 651 652 xhptregister_node(PROC_DIR_NAME); 653