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