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