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