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