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