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>='' && *buffer<='1') {
243 _vbus_(r5.enable_write_back) = *buffer-'';
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>='' && *buffer<='3') {
259 hpt_dbg_level = *buffer-'';
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]-'';
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 va_list ap;
383
384 if(fmt == NULL) {
385 *hptproc_buffer = 0;
386 return (SYSCTL_OUT(pinfo, hptproc_buffer, 1));
387 }
388 else
389 {
390 va_start(ap, fmt);
391 vsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap);
392 va_end(ap);
393 return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer)));
394 }
395 }
396
397 static void
398 hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan)
399 {
400 char name[32], arrayname[16], *status;
401
402 get_disk_name(name, &pVDev->u.disk);
403
404 if (!pVDev->u.disk.df_on_line)
405 status = "Disabled";
406 else if (pVDev->VDeviceType==VD_SPARE)
407 status = "Spare ";
408 else
409 status = "Normal ";
410
411 #ifdef SUPPORT_ARRAY
412 if(pVDev->pParent) {
413 memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME);
414 if (pVDev->pParent->u.array.CriticalMembers & (1<<pVDev->bSerialNumber))
415 status = "Degraded";
416 }
417 else
418 #endif
419 arrayname[0]=0;
420
421 hpt_copy_info(pinfo, "Channel %d %s %5dMB %s %s\n",
422 iChan+1,
423 name, pVDev->VDeviceCapacity>>11, status, arrayname);
424 }
425
426 #ifdef SUPPORT_ARRAY
427 static void
428 hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray)
429 {
430 int i;
431 char *sType = NULL, *sStatus = NULL;
432 char buf[32];
433 PVDevice pTmpArray;
434
435 switch (pArray->VDeviceType) {
436 case VD_RAID_0:
437 for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
438 if(pArray->u.array.pMember[i]) {
439 if(mIsArray(pArray->u.array.pMember[i]))
440 sType = "RAID 1/0 ";
441 /* TO DO */
442 else
443 sType = "RAID 0 ";
444 break;
445 }
446 break;
447
448 case VD_RAID_1:
449 sType = "RAID 1 ";
450 break;
451
452 case VD_JBOD:
453 sType = "JBOD ";
454 break;
455
456 case VD_RAID_5:
457 sType = "RAID 5 ";
458 break;
459
460 default:
461 sType = "N/A ";
462 break;
463 }
464
465 if (pArray->vf_online == 0)
466 sStatus = "Disabled";
467 else if (pArray->u.array.rf_broken)
468 sStatus = "Critical";
469 for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
470 {
471 if (!sStatus)
472 {
473 if(mIsArray(pArray->u.array.pMember[i]))
474 pTmpArray = pArray->u.array.pMember[i];
475 else
476 pTmpArray = pArray;
477
478 if (pTmpArray->u.array.rf_rebuilding) {
479 #ifdef DEBUG
480 sprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11));
481 #else
482 sprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
483 #endif
484 sStatus = buf;
485 }
486 else if (pTmpArray->u.array.rf_verifying) {
487 sprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
488 sStatus = buf;
489 }
490 else if (pTmpArray->u.array.rf_need_rebuild)
491 sStatus = "Critical";
492 else if (pTmpArray->u.array.rf_broken)
493 sStatus = "Critical";
494
495 if(pTmpArray == pArray) goto out;
496 }
497 else
498 goto out;
499 }
500 out:
501 if (!sStatus) sStatus = "Normal";
502 hpt_copy_info(pinfo, "%2d %11s %-20s %5lldMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus);
503 }
504 #endif
505
506 static int
507 hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo)
508 {
509 PVBus _vbus_p = &pAdapter->VBus;
510 struct cam_periph *periph = NULL;
511 UINT channel,j,i;
512 PVDevice pVDev;
513
514 #ifndef FOR_DEMO
515 mtx_lock(&pAdapter->lock);
516 if (pAdapter->beeping) {
517 pAdapter->beeping = 0;
518 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
519 }
520 mtx_unlock(&pAdapter->lock);
521 #endif
522
523 hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId);
524
525 hpt_copy_info(pinfo, "Physical device list\n");
526 hpt_copy_info(pinfo, "Channel Model Capacity Status Array\n");
527 hpt_copy_info(pinfo, "-------------------------------------------------------------------\n");
528
529 for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
530 {
531 pVDev = &(pAdapter->VDevices[channel]);
532 if(pVDev->u.disk.df_on_line)
533 hpt_copy_disk_info(pinfo, pVDev, channel);
534 }
535
536 hpt_copy_info(pinfo, "\nLogical device list\n");
537 hpt_copy_info(pinfo, "No. Type Name Capacity Status OsDisk\n");
538 hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n");
539
540 j=1;
541 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){
542 pVDev = _vbus_p->pVDevice[i];
543 if(pVDev){
544 j=i+1;
545 #ifdef SUPPORT_ARRAY
546 if (mIsArray(pVDev))
547 {
548 is_array:
549 hpt_copy_array_info(pinfo, j, pVDev);
550 }
551 else
552 #endif
553 {
554 char name[32];
555 /* it may be add to an array after driver loaded, check it */
556 #ifdef SUPPORT_ARRAY
557 if (pVDev->pParent)
558 /* in this case, pVDev can only be a RAID 1 source disk. */
559 if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0])
560 goto is_array;
561 #endif
562 get_disk_name(name, &pVDev->u.disk);
563
564 hpt_copy_info(pinfo, "%2d %s %s %5dMB %-16s",
565 j, "Single disk", name, pVDev->VDeviceCapacity>>11,
566 /* gmm 2001-6-19: Check if pDev has been added to an array. */
567 ((pVDev->pParent) ? "Unavailable" : "Normal"));
568 }
569 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
570 if (periph == NULL)
571 hpt_copy_info(pinfo," %s\n","not registered");
572 else
573 hpt_copy_info(pinfo," %s%d\n", periph->periph_name, periph->unit_number);
574 }
575 }
576 return 0;
577 }
578
579 static __inline int
580 hpt_proc_in(SYSCTL_HANDLER_ARGS, int *len)
581 {
582 int i, error=0;
583
584 *len = 0;
585 if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) {
586 error = EINVAL;
587 } else {
588 i = (req->newlen - req->newidx);
589 error = SYSCTL_IN(req, hptproc_buffer, i);
590 if (!error)
591 *len = i;
592 (hptproc_buffer)[i] = '\0';
593 }
594 return (error);
595 }
596
597 static int
598 hpt_status(SYSCTL_HANDLER_ARGS)
599 {
600 int length, error=0, retval=0;
601 IAL_ADAPTER_T *pAdapter;
602
603 error = hpt_proc_in(oidp, arg1, arg2, req, &length);
604
605 if (req->newptr != NULL)
606 {
607 if (error || length == 0)
608 {
609 KdPrint(("error!\n"));
610 retval = EINVAL;
611 goto out;
612 }
613
614 if (hpt_set_info(length) >= 0)
615 retval = 0;
616 else
617 retval = EINVAL;
618 goto out;
619 }
620
621 hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION);
622 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
623 if (hpt_get_info(pAdapter, req) < 0) {
624 retval = EINVAL;
625 break;
626 }
627 }
628
629 hpt_copy_info(req, NULL);
630 goto out;
631
632 out:
633 return (retval);
634 }
635
636
637 #define xhptregister_node(name) hptregister_node(name)
638
639 #if __FreeBSD_version >= 1100024
640 #define hptregister_node(name) \
641 SYSCTL_ROOT_NODE(OID_AUTO, name, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, \
642 "Get/Set " #name " state root node"); \
643 SYSCTL_OID(_ ## name, OID_AUTO, status, \
644 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT, \
645 NULL, 0, hpt_status, "A", "Get/Set " #name " state")
646 #else
647 #define hptregister_node(name) \
648 SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \
649 SYSCTL_OID(_ ## name, OID_AUTO, status, \
650 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, \
651 NULL, 0, hpt_status, "A", "Get/Set " #name " state")
652 #endif
653
654 xhptregister_node(PROC_DIR_NAME);
Cache object: 52ebbb80af922b3b0a2f5ac3db84b909
|