hptmv(4): Save some unneeded variables in the locking functions.
[dragonfly.git] / sys / dev / raid / hptmv / hptproc.c
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: src/sys/dev/hptmv/hptproc.c,v 1.8 2009/04/07 16:38:25 delphij Exp $
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/raid/hptmv/global.h>
43 #include <dev/raid/hptmv/hptintf.h>
44 #include <dev/raid/hptmv/osbsd.h>
45 #include <dev/raid/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 #define FORMAL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, int arg2, \
55         struct sysctl_req *req
56 #define REAL_HANDLER_ARGS oidp, arg1, arg2, req
57 typedef struct sysctl_req HPT_GET_INFO;
58
59 static int
60 hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length)
61 {
62         int orig_length = length+4;
63         PVBus _vbus_p = &pAdapter->VBus;
64         PVDevice         pArray;
65         PVDevice pSubArray, pVDev;
66         UINT    i, iarray, ichan;
67         struct cam_periph *periph = NULL;
68
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                         lock_driver();
77                         for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
78                                 if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
79                                         continue;
80                                 else{
81                                         if (pArray->u.array.rf_need_rebuild && !pArray->u.array.rf_rebuilding)
82                             hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
83                                                         (UCHAR)((pArray->u.array.CriticalMembers || pArray->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
84                                 }
85                         unlock_driver();
86                         return orig_length;
87                 }
88                 else if (length>=4 && strncmp(buffer, "stop", 4)==0)
89                 {
90                         lock_driver();
91                         for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
92                                 if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
93                                         continue;
94                                 else{
95                                         if (pArray->u.array.rf_rebuilding)
96                                             pArray->u.array.rf_abort_rebuild = 1;
97                                 }
98                         unlock_driver();
99                         return orig_length;
100                 }
101                 else if (length>=3 && buffer[1]==','&& buffer[0]>='1'&& buffer[2]>='1')
102                 {
103                         iarray = buffer[0]-'1';
104                 ichan = buffer[2]-'1';
105
106             if(iarray >= MAX_VDEVICE_PER_VBUS || ichan >= MV_SATA_CHANNELS_NUM) return -EINVAL;
107
108                         pArray = _vbus_p->pVDevice[iarray];
109                 if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
110
111             for (i=0;i<MV_SATA_CHANNELS_NUM;i++)
112                                 if(i == ichan)
113                                     goto rebuild;
114
115                 return -EINVAL;
116
117 rebuild:
118                 pVDev = &pAdapter->VDevices[ichan];
119                 if(!pVDev->u.disk.df_on_line || pVDev->pParent) return -EINVAL;
120
121                 /* Not allow to use a mounted disk ??? test*/
122                         for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
123                             if(pVDev == _vbus_p->pVDevice[i])
124                             {
125                                         periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i);
126                                         if (periph != NULL && periph->refcount >= 1)
127                                         {
128                                                 hpt_printk(("Can not use disk used by OS!\n"));
129                             return -EINVAL;
130                                         }
131                                         /* the Mounted Disk isn't delete */
132                                 }
133
134                         switch(pArray->VDeviceType)
135                         {
136                                 case VD_RAID_1:
137                                 case VD_RAID_5:
138                                 {
139                                         pSubArray = pArray;
140 loop:
141                                         lock_driver();
142                                         if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) {
143                                                 unlock_driver();
144                                                 return -EINVAL;
145                                         }
146                                         pSubArray->u.array.rf_auto_rebuild = 0;
147                                         pSubArray->u.array.rf_abort_rebuild = 0;
148                                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pSubArray, DUPLICATE);
149                                         unlock_driver();
150                                         break;
151                                 }
152                                 case VD_RAID_0:
153                                         for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
154                                                 if(pArray->u.array.pMember[i] && mIsArray(pArray->u.array.pMember[i]) &&
155                                                    (pArray->u.array.pMember[i]->u.array.rf_broken == 1))
156                                                 {
157                                                           pSubArray = pArray->u.array.pMember[i];
158                                                           goto loop;
159                                                 }
160                                 default:
161                                         return -EINVAL;
162                         }
163                         return orig_length;
164                 }
165         }
166         else if (length>=7 && strncmp(buffer, "verify ", 7)==0)
167         {
168                 buffer+=7;
169                 length-=7;
170         if (length>=6 && strncmp(buffer, "start ", 6)==0)
171                 {
172             buffer+=6;
173                     length-=6;
174             if (length>=1 && *buffer>='1')
175                         {
176                                 iarray = *buffer-'1';
177                                 if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL;
178
179                                 pArray = _vbus_p->pVDevice[iarray];
180                                 if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
181
182                                 if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
183                                         return -EINVAL;
184
185                                 if (!(pArray->u.array.rf_need_rebuild ||
186                                         pArray->u.array.rf_rebuilding ||
187                                         pArray->u.array.rf_verifying ||
188                                         pArray->u.array.rf_initializing))
189                                 {
190                                         lock_driver();
191                                         pArray->u.array.RebuildSectors = 0;
192                                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY);
193                                         unlock_driver();
194                                 }
195                 return orig_length;
196                         }
197                 }
198                 else if (length>=5 && strncmp(buffer, "stop ", 5)==0)
199                 {
200                         buffer+=5;
201                     length-=5;
202             if (length>=1 && *buffer>='1')
203                         {
204                                 iarray = *buffer-'1';
205                                 if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL;
206
207                                 pArray = _vbus_p->pVDevice[iarray];
208                                 if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
209                                 if(pArray->u.array.rf_verifying)
210                                 {
211                                         lock_driver();
212                                     pArray->u.array.rf_abort_rebuild = 1;
213                                     unlock_driver();
214                                 }
215                             return orig_length;
216                         }
217                 }
218         }
219         else
220 #ifdef _RAID5N_
221         if (length>=10 && strncmp(buffer, "writeback ", 10)==0) {
222                 buffer+=10;
223                 length-=10;
224                 if (length>=1 && *buffer>='0' && *buffer<='1') {
225                         _vbus_(r5.enable_write_back) = *buffer-'0';
226                         if (_vbus_(r5.enable_write_back))
227                                 hpt_printk(("RAID5 write back enabled"));
228                         return orig_length;
229                 }
230         }
231         else
232 #endif
233 #endif
234         if (0) {} /* just to compile */
235 #ifdef DEBUG
236         else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) {
237                 buffer+=9;
238                 length-=9;
239                 if (length>=1 && *buffer>='0' && *buffer<='3') {
240                         hpt_dbg_level = *buffer-'0';
241                         return orig_length;
242                 }
243         }
244         else if (length>=8 && strncmp(buffer, "disable ", 8)==0) {
245                 /* TO DO */
246         }
247 #endif
248
249         return -EINVAL;
250 }
251
252 /*
253  * Since we have only one sysctl node, add adapter ID in the command
254  * line string: e.g. "hpt 0 rebuild start"
255  */
256 static int
257 hpt_set_info(int length)
258 {
259         int retval;
260
261 #ifdef SUPPORT_IOCTL
262         PUCHAR ke_area;
263         int err;
264         DWORD dwRet;
265         PHPT_IOCTL_PARAM piop;
266 #endif
267         char *buffer = hptproc_buffer;
268         if (length >= 6) {
269                 if (strncmp(buffer,"hpt ",4) == 0) {
270                         IAL_ADAPTER_T *pAdapter;
271                         retval = buffer[4]-'0';
272                         for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
273                                 if (pAdapter->mvSataAdapter.adapterId==retval)
274                                         return (retval = hpt_set_asc_info(pAdapter, buffer+6, length-6)) >= 0? retval : -EINVAL;
275                         }
276                         return -EINVAL;
277                 }
278 #ifdef SUPPORT_IOCTL
279                 piop = (PHPT_IOCTL_PARAM)buffer;
280                 if (piop->Magic == HPT_IOCTL_MAGIC ||
281                         piop->Magic == HPT_IOCTL_MAGIC32)       {
282                         KdPrintE(("ioctl=%d in=%p len=%d out=%p len=%d\n",
283                                 piop->dwIoControlCode,
284                                 piop->lpInBuffer,
285                                 piop->nInBufferSize,
286                                 piop->lpOutBuffer,
287                                 piop->nOutBufferSize));
288
289                         /*
290                          * map buffer to kernel.
291                          */
292                         if (piop->nInBufferSize+piop->nOutBufferSize > PAGE_SIZE) {
293                                 KdPrintE(("User buffer too large\n"));
294                                 return -EINVAL;
295                         }
296
297                         ke_area = kmalloc(piop->nInBufferSize+piop->nOutBufferSize, M_DEVBUF, M_NOWAIT);
298                                 if (ke_area == NULL) {
299                                         KdPrintE(("Couldn't allocate kernel mem.\n"));
300                                         return -EINVAL;
301                                 }
302
303                         if (piop->nInBufferSize)
304                                 copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize);
305
306                         /*
307                           * call kernel handler.
308                           */
309                         err = Kernel_DeviceIoControl(&gIal_Adapter->VBus,
310                                 piop->dwIoControlCode, ke_area, piop->nInBufferSize,
311                                 ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet);
312
313                         if (err==0) {
314                                 if (piop->nOutBufferSize)
315                                         copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize);
316
317                                 if (piop->lpBytesReturned)
318                                         copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD));
319
320                                 kfree(ke_area, M_DEVBUF);
321                                 return length;
322                         }
323                         else  KdPrintW(("Kernel_ioctl(): return %d\n", err));
324
325                         kfree(ke_area, M_DEVBUF);
326                         return -EINVAL;
327                 } else  {
328                         KdPrintW(("Wrong signature: %x\n", piop->Magic));
329                         return -EINVAL;
330                 }
331 #endif
332         }
333
334         return -EINVAL;
335 }
336
337 #define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8))
338
339 static void
340 get_disk_name(char *name, PDevice pDev)
341 {
342         int i;
343         MV_SATA_CHANNEL *pMvSataChannel = pDev->mv;
344         IDENTIFY_DATA2 *pIdentifyData = (IDENTIFY_DATA2 *)pMvSataChannel->identifyDevice;
345
346         for (i = 0; i < 10; i++)
347                 ((WORD*)name)[i] = shortswap(pIdentifyData->ModelNumber[i]);
348         name[20] = '\0';
349 }
350
351 static int
352 hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...)
353 {
354         int printfretval;
355         __va_list ap;
356
357         if(fmt == NULL) {
358                 *hptproc_buffer = 0;
359                 return (SYSCTL_OUT(pinfo, hptproc_buffer, 1));
360         }
361         else
362         {
363                 __va_start(ap, fmt);
364                 printfretval = kvsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap);
365                 __va_end(ap);
366                 return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer)));
367         }
368 }
369
370 static void
371 hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan)
372 {
373         char name[32], arrayname[16], *status;
374
375         get_disk_name(name, &pVDev->u.disk);
376
377         if (!pVDev->u.disk.df_on_line)
378                 status = "Disabled";
379         else if (pVDev->VDeviceType==VD_SPARE)
380                 status = "Spare   ";
381         else
382                 status = "Normal  ";
383
384 #ifdef SUPPORT_ARRAY
385         if(pVDev->pParent) {
386                 memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME);
387                 if (pVDev->pParent->u.array.CriticalMembers & (1<<pVDev->bSerialNumber))
388                         status = "Degraded";
389         }
390         else
391 #endif
392                 arrayname[0]=0;
393
394         hpt_copy_info(pinfo, "Channel %d  %s  %5dMB  %s %s\n",
395                 iChan+1,
396                 name, pVDev->VDeviceCapacity>>11, status, arrayname);
397 }
398
399 #ifdef SUPPORT_ARRAY
400 static void
401 hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray)
402 {
403         int i;
404         char *sType=0, *sStatus=0;
405         char buf[32];
406     PVDevice pTmpArray;
407
408         switch (pArray->VDeviceType) {
409                 case VD_RAID_0:
410                         for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
411                                 if(pArray->u.array.pMember[i])  {
412                                         if(mIsArray(pArray->u.array.pMember[i]))
413                                                 sType = "RAID 1/0   ";
414                                                 /* TO DO */
415                                         else
416                                                 sType = "RAID 0     ";
417                                         break;
418                                 }
419                         break;
420
421                 case VD_RAID_1:
422                         sType = "RAID 1     ";
423                         break;
424
425                 case VD_JBOD:
426                         sType = "JBOD       ";
427                         break;
428
429                 case VD_RAID_5:
430                         sType = "RAID 5     ";
431                         break;
432
433                 default:
434                         sType = "N/A        ";
435                         break;
436         }
437
438         if (pArray->vf_online == 0)
439                 sStatus = "Disabled";
440         else if (pArray->u.array.rf_broken)
441                 sStatus = "Critical";
442         for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
443         {
444                 if (!sStatus)
445                 {
446                         if(mIsArray(pArray->u.array.pMember[i]))
447                                 pTmpArray = pArray->u.array.pMember[i];
448                         else
449                                 pTmpArray = pArray;
450
451                         if (pTmpArray->u.array.rf_rebuilding) {
452 #ifdef DEBUG
453                                 ksprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11));
454 #else
455                                 ksprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
456 #endif
457                                 sStatus = buf;
458                         }
459                         else if (pTmpArray->u.array.rf_verifying) {
460                                 ksprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
461                                 sStatus = buf;
462                         }
463                         else if (pTmpArray->u.array.rf_need_rebuild)
464                                 sStatus = "Critical";
465                         else if (pTmpArray->u.array.rf_broken)
466                                 sStatus = "Critical";
467
468                         if(pTmpArray == pArray) goto out;
469                 }
470                 else
471                         goto out;
472         }
473 out:
474         if (!sStatus) sStatus = "Normal";
475         hpt_copy_info(pinfo, "%2d  %11s  %-20s  %5lldMB  %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus);
476 }
477 #endif
478
479 static int
480 hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo)
481 {
482         PVBus _vbus_p = &pAdapter->VBus;
483         struct cam_periph *periph = NULL;
484         UINT channel,j,i;
485         PVDevice pVDev;
486
487 #ifndef FOR_DEMO
488         if (pAdapter->beeping) {
489                 lock_driver();
490                 pAdapter->beeping = 0;
491                 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
492                 unlock_driver();
493         }
494 #endif
495
496         hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId);
497
498         hpt_copy_info(pinfo, "Physical device list\n");
499         hpt_copy_info(pinfo, "Channel    Model                Capacity  Status   Array\n");
500         hpt_copy_info(pinfo, "-------------------------------------------------------------------\n");
501
502     for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
503         {
504                 pVDev = &(pAdapter->VDevices[channel]);
505                 if(pVDev->u.disk.df_on_line)
506                          hpt_copy_disk_info(pinfo, pVDev, channel);
507         }
508
509         hpt_copy_info(pinfo, "\nLogical device list\n");
510         hpt_copy_info(pinfo, "No. Type         Name                 Capacity  Status            OsDisk\n");
511         hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n");
512
513         j=1;
514         for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){
515         pVDev = _vbus_p->pVDevice[i];
516                 if(pVDev){
517                         j=i+1;
518 #ifdef SUPPORT_ARRAY
519                         if (mIsArray(pVDev))
520                         {
521                 is_array:
522                                 hpt_copy_array_info(pinfo, j, pVDev);
523                         }
524                         else
525 #endif
526                         {
527                                 char name[32];
528                                 /* it may be add to an array after driver loaded, check it */
529 #ifdef SUPPORT_ARRAY
530                                 if (pVDev->pParent)
531                                         /* in this case, pVDev can only be a RAID 1 source disk. */
532                                         if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0])
533                                                 goto is_array;
534 #endif
535                                 get_disk_name(name, &pVDev->u.disk);
536
537                                 hpt_copy_info(pinfo, "%2d  %s  %s  %5dMB  %-16s",
538                                         j, "Single disk", name, pVDev->VDeviceCapacity>>11,
539                                         /* gmm 2001-6-19: Check if pDev has been added to an array. */
540                                         ((pVDev->pParent) ? "Unavailable" : "Normal"));
541                         }
542                         periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
543                         if (periph == NULL)
544                                 hpt_copy_info(pinfo,"  %s\n","not registered");
545                         else
546                                 hpt_copy_info(pinfo,"  %s%d\n", periph->periph_name, periph->unit_number);
547                  }
548         }
549         return 0;
550 }
551
552 static __inline int
553 hpt_proc_in(FORMAL_HANDLER_ARGS, int *len)
554 {
555         int i, error=0;
556
557         *len = 0;
558         if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) {
559                 error = EINVAL;
560         } else {
561                 i = (req->newlen - req->newidx);
562                 error = SYSCTL_IN(req, hptproc_buffer, i);
563                 if (!error)
564                         *len = i;
565                 (hptproc_buffer)[i] = '\0';
566         }
567         return (error);
568 }
569
570 static int
571 hpt_status(FORMAL_HANDLER_ARGS)
572 {
573         int length, error=0, retval=0;
574         IAL_ADAPTER_T *pAdapter;
575
576         error = hpt_proc_in(REAL_HANDLER_ARGS, &length);
577
578     if (req->newptr != NULL)
579         {
580                 if (error || length == 0)
581                 {
582                         KdPrint(("error!\n"));
583                         retval = EINVAL;
584                         goto out;
585                 }
586
587                 if (hpt_set_info(length) >= 0)
588                         retval = 0;
589                 else
590                         retval = EINVAL;
591                 goto out;
592     }
593
594         hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION);
595         for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
596                 if (hpt_get_info(pAdapter, req) < 0) {
597                         retval = EINVAL;
598                         break;
599                 }
600         }
601
602         hpt_copy_info(req, NULL);
603         goto out;
604
605 out:
606         return (retval);
607 }
608
609
610 #define xhptregister_node(name) hptregister_node(name)
611
612 #define hptregister_node(name) \
613         SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \
614         SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \
615         NULL, 0, hpt_status, "A", "Get/Set " #name " state");
616
617 xhptregister_node(PROC_DIR_NAME);