135878b55SSascha Wildner /*
235878b55SSascha Wildner * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
335878b55SSascha Wildner * All rights reserved.
435878b55SSascha Wildner *
535878b55SSascha Wildner * Redistribution and use in source and binary forms, with or without
635878b55SSascha Wildner * modification, are permitted provided that the following conditions
735878b55SSascha Wildner * are met:
835878b55SSascha Wildner * 1. Redistributions of source code must retain the above copyright
935878b55SSascha Wildner * notice, this list of conditions and the following disclaimer.
1035878b55SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
1135878b55SSascha Wildner * notice, this list of conditions and the following disclaimer in the
1235878b55SSascha Wildner * documentation and/or other materials provided with the distribution.
1335878b55SSascha Wildner *
1435878b55SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1535878b55SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1635878b55SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1735878b55SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1835878b55SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1935878b55SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2035878b55SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2135878b55SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2235878b55SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2335878b55SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2435878b55SSascha Wildner * SUCH DAMAGE.
2535878b55SSascha Wildner *
2635878b55SSascha Wildner * $FreeBSD: src/sys/dev/hptmv/hptproc.c,v 1.8 2009/04/07 16:38:25 delphij Exp $
2735878b55SSascha Wildner */
2835878b55SSascha Wildner /*
2935878b55SSascha Wildner * hptproc.c sysctl support
3035878b55SSascha Wildner */
3135878b55SSascha Wildner #include <sys/param.h>
3235878b55SSascha Wildner #include <sys/systm.h>
3335878b55SSascha Wildner #include <sys/kernel.h>
3435878b55SSascha Wildner #include <sys/malloc.h>
3535878b55SSascha Wildner #include <sys/sysctl.h>
3635878b55SSascha Wildner #include <machine/stdarg.h>
3735878b55SSascha Wildner
3835878b55SSascha Wildner #ifndef __KERNEL__
3935878b55SSascha Wildner #define __KERNEL__
4035878b55SSascha Wildner #endif
4135878b55SSascha Wildner
4235878b55SSascha Wildner #include <dev/raid/hptmv/global.h>
4335878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h>
4435878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h>
4535878b55SSascha Wildner #include <dev/raid/hptmv/access601.h>
4635878b55SSascha Wildner
4735878b55SSascha Wildner int hpt_rescan_all(void);
4835878b55SSascha Wildner
4935878b55SSascha Wildner /***************************************************************************/
5035878b55SSascha Wildner
5135878b55SSascha Wildner static char hptproc_buffer[256];
5235878b55SSascha Wildner extern char DRIVER_VERSION[];
5335878b55SSascha Wildner
5435878b55SSascha Wildner #define FORMAL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, int arg2, \
5535878b55SSascha Wildner struct sysctl_req *req
5635878b55SSascha Wildner #define REAL_HANDLER_ARGS oidp, arg1, arg2, req
5735878b55SSascha Wildner typedef struct sysctl_req HPT_GET_INFO;
5835878b55SSascha Wildner
5935878b55SSascha Wildner static int
hpt_set_asc_info(IAL_ADAPTER_T * pAdapter,char * buffer,int length)6035878b55SSascha Wildner hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length)
6135878b55SSascha Wildner {
6235878b55SSascha Wildner int orig_length = length+4;
6335878b55SSascha Wildner PVBus _vbus_p = &pAdapter->VBus;
6435878b55SSascha Wildner PVDevice pArray;
6535878b55SSascha Wildner PVDevice pSubArray, pVDev;
6635878b55SSascha Wildner UINT i, iarray, ichan;
6735878b55SSascha Wildner struct cam_periph *periph = NULL;
6835878b55SSascha Wildner
6935878b55SSascha Wildner #ifdef SUPPORT_ARRAY
7035878b55SSascha Wildner if (length>=8 && strncmp(buffer, "rebuild ", 8)==0)
7135878b55SSascha Wildner {
7235878b55SSascha Wildner buffer+=8;
7335878b55SSascha Wildner length-=8;
7435878b55SSascha Wildner if (length>=5 && strncmp(buffer, "start", 5)==0)
7535878b55SSascha Wildner {
76c898d682SSascha Wildner lock_driver();
7735878b55SSascha Wildner for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
7835878b55SSascha Wildner if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
7935878b55SSascha Wildner continue;
8035878b55SSascha Wildner else{
8135878b55SSascha Wildner if (pArray->u.array.rf_need_rebuild && !pArray->u.array.rf_rebuilding)
8235878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
8335878b55SSascha Wildner (UCHAR)((pArray->u.array.CriticalMembers || pArray->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
8435878b55SSascha Wildner }
85c898d682SSascha Wildner unlock_driver();
8635878b55SSascha Wildner return orig_length;
8735878b55SSascha Wildner }
8835878b55SSascha Wildner else if (length>=4 && strncmp(buffer, "stop", 4)==0)
8935878b55SSascha Wildner {
90c898d682SSascha Wildner lock_driver();
9135878b55SSascha Wildner for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
9235878b55SSascha Wildner if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
9335878b55SSascha Wildner continue;
9435878b55SSascha Wildner else{
9535878b55SSascha Wildner if (pArray->u.array.rf_rebuilding)
9635878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 1;
9735878b55SSascha Wildner }
98c898d682SSascha Wildner unlock_driver();
9935878b55SSascha Wildner return orig_length;
10035878b55SSascha Wildner }
10135878b55SSascha Wildner else if (length>=3 && buffer[1]==','&& buffer[0]>='1'&& buffer[2]>='1')
10235878b55SSascha Wildner {
10335878b55SSascha Wildner iarray = buffer[0]-'1';
10435878b55SSascha Wildner ichan = buffer[2]-'1';
10535878b55SSascha Wildner
10635878b55SSascha Wildner if(iarray >= MAX_VDEVICE_PER_VBUS || ichan >= MV_SATA_CHANNELS_NUM) return -EINVAL;
10735878b55SSascha Wildner
10835878b55SSascha Wildner pArray = _vbus_p->pVDevice[iarray];
10935878b55SSascha Wildner if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
11035878b55SSascha Wildner
11135878b55SSascha Wildner for (i=0;i<MV_SATA_CHANNELS_NUM;i++)
11235878b55SSascha Wildner if(i == ichan)
11335878b55SSascha Wildner goto rebuild;
11435878b55SSascha Wildner
11535878b55SSascha Wildner return -EINVAL;
11635878b55SSascha Wildner
11735878b55SSascha Wildner rebuild:
11835878b55SSascha Wildner pVDev = &pAdapter->VDevices[ichan];
11935878b55SSascha Wildner if(!pVDev->u.disk.df_on_line || pVDev->pParent) return -EINVAL;
12035878b55SSascha Wildner
12135878b55SSascha Wildner /* Not allow to use a mounted disk ??? test*/
12235878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
12335878b55SSascha Wildner if(pVDev == _vbus_p->pVDevice[i])
12435878b55SSascha Wildner {
12535878b55SSascha Wildner periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i);
12635878b55SSascha Wildner if (periph != NULL && periph->refcount >= 1)
12735878b55SSascha Wildner {
12835878b55SSascha Wildner hpt_printk(("Can not use disk used by OS!\n"));
12935878b55SSascha Wildner return -EINVAL;
13035878b55SSascha Wildner }
13135878b55SSascha Wildner /* the Mounted Disk isn't delete */
13235878b55SSascha Wildner }
13335878b55SSascha Wildner
13435878b55SSascha Wildner switch(pArray->VDeviceType)
13535878b55SSascha Wildner {
13635878b55SSascha Wildner case VD_RAID_1:
13735878b55SSascha Wildner case VD_RAID_5:
13835878b55SSascha Wildner {
13935878b55SSascha Wildner pSubArray = pArray;
14035878b55SSascha Wildner loop:
141c898d682SSascha Wildner lock_driver();
14235878b55SSascha Wildner if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) {
143c898d682SSascha Wildner unlock_driver();
14435878b55SSascha Wildner return -EINVAL;
14535878b55SSascha Wildner }
14635878b55SSascha Wildner pSubArray->u.array.rf_auto_rebuild = 0;
14735878b55SSascha Wildner pSubArray->u.array.rf_abort_rebuild = 0;
14835878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pSubArray, DUPLICATE);
149c898d682SSascha Wildner unlock_driver();
15035878b55SSascha Wildner break;
15135878b55SSascha Wildner }
15235878b55SSascha Wildner case VD_RAID_0:
15335878b55SSascha Wildner for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
15435878b55SSascha Wildner if(pArray->u.array.pMember[i] && mIsArray(pArray->u.array.pMember[i]) &&
15535878b55SSascha Wildner (pArray->u.array.pMember[i]->u.array.rf_broken == 1))
15635878b55SSascha Wildner {
15735878b55SSascha Wildner pSubArray = pArray->u.array.pMember[i];
15835878b55SSascha Wildner goto loop;
15935878b55SSascha Wildner }
16035878b55SSascha Wildner default:
16135878b55SSascha Wildner return -EINVAL;
16235878b55SSascha Wildner }
16335878b55SSascha Wildner return orig_length;
16435878b55SSascha Wildner }
16535878b55SSascha Wildner }
16635878b55SSascha Wildner else if (length>=7 && strncmp(buffer, "verify ", 7)==0)
16735878b55SSascha Wildner {
16835878b55SSascha Wildner buffer+=7;
16935878b55SSascha Wildner length-=7;
17035878b55SSascha Wildner if (length>=6 && strncmp(buffer, "start ", 6)==0)
17135878b55SSascha Wildner {
17235878b55SSascha Wildner buffer+=6;
17335878b55SSascha Wildner length-=6;
17435878b55SSascha Wildner if (length>=1 && *buffer>='1')
17535878b55SSascha Wildner {
17635878b55SSascha Wildner iarray = *buffer-'1';
17735878b55SSascha Wildner if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL;
17835878b55SSascha Wildner
17935878b55SSascha Wildner pArray = _vbus_p->pVDevice[iarray];
18035878b55SSascha Wildner if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
18135878b55SSascha Wildner
18235878b55SSascha Wildner if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
18335878b55SSascha Wildner return -EINVAL;
18435878b55SSascha Wildner
18535878b55SSascha Wildner if (!(pArray->u.array.rf_need_rebuild ||
18635878b55SSascha Wildner pArray->u.array.rf_rebuilding ||
18735878b55SSascha Wildner pArray->u.array.rf_verifying ||
18835878b55SSascha Wildner pArray->u.array.rf_initializing))
18935878b55SSascha Wildner {
190c898d682SSascha Wildner lock_driver();
19135878b55SSascha Wildner pArray->u.array.RebuildSectors = 0;
19235878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY);
193c898d682SSascha Wildner unlock_driver();
19435878b55SSascha Wildner }
19535878b55SSascha Wildner return orig_length;
19635878b55SSascha Wildner }
19735878b55SSascha Wildner }
19835878b55SSascha Wildner else if (length>=5 && strncmp(buffer, "stop ", 5)==0)
19935878b55SSascha Wildner {
20035878b55SSascha Wildner buffer+=5;
20135878b55SSascha Wildner length-=5;
20235878b55SSascha Wildner if (length>=1 && *buffer>='1')
20335878b55SSascha Wildner {
20435878b55SSascha Wildner iarray = *buffer-'1';
20535878b55SSascha Wildner if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL;
20635878b55SSascha Wildner
20735878b55SSascha Wildner pArray = _vbus_p->pVDevice[iarray];
20835878b55SSascha Wildner if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
20935878b55SSascha Wildner if(pArray->u.array.rf_verifying)
21035878b55SSascha Wildner {
211c898d682SSascha Wildner lock_driver();
21235878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 1;
213c898d682SSascha Wildner unlock_driver();
21435878b55SSascha Wildner }
21535878b55SSascha Wildner return orig_length;
21635878b55SSascha Wildner }
21735878b55SSascha Wildner }
21835878b55SSascha Wildner }
21935878b55SSascha Wildner else
22035878b55SSascha Wildner #ifdef _RAID5N_
22135878b55SSascha Wildner if (length>=10 && strncmp(buffer, "writeback ", 10)==0) {
22235878b55SSascha Wildner buffer+=10;
22335878b55SSascha Wildner length-=10;
22435878b55SSascha Wildner if (length>=1 && *buffer>='0' && *buffer<='1') {
22535878b55SSascha Wildner _vbus_(r5.enable_write_back) = *buffer-'0';
22635878b55SSascha Wildner if (_vbus_(r5.enable_write_back))
22735878b55SSascha Wildner hpt_printk(("RAID5 write back enabled"));
22835878b55SSascha Wildner return orig_length;
22935878b55SSascha Wildner }
23035878b55SSascha Wildner }
23135878b55SSascha Wildner else
23235878b55SSascha Wildner #endif
23335878b55SSascha Wildner #endif
23435878b55SSascha Wildner if (0) {} /* just to compile */
23535878b55SSascha Wildner #ifdef DEBUG
23635878b55SSascha Wildner else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) {
23735878b55SSascha Wildner buffer+=9;
23835878b55SSascha Wildner length-=9;
23935878b55SSascha Wildner if (length>=1 && *buffer>='0' && *buffer<='3') {
24035878b55SSascha Wildner hpt_dbg_level = *buffer-'0';
24135878b55SSascha Wildner return orig_length;
24235878b55SSascha Wildner }
24335878b55SSascha Wildner }
24435878b55SSascha Wildner else if (length>=8 && strncmp(buffer, "disable ", 8)==0) {
24535878b55SSascha Wildner /* TO DO */
24635878b55SSascha Wildner }
24735878b55SSascha Wildner #endif
24835878b55SSascha Wildner
24935878b55SSascha Wildner return -EINVAL;
25035878b55SSascha Wildner }
25135878b55SSascha Wildner
25235878b55SSascha Wildner /*
25335878b55SSascha Wildner * Since we have only one sysctl node, add adapter ID in the command
25435878b55SSascha Wildner * line string: e.g. "hpt 0 rebuild start"
25535878b55SSascha Wildner */
25635878b55SSascha Wildner static int
hpt_set_info(int length)25735878b55SSascha Wildner hpt_set_info(int length)
25835878b55SSascha Wildner {
25935878b55SSascha Wildner int retval;
26035878b55SSascha Wildner
26135878b55SSascha Wildner #ifdef SUPPORT_IOCTL
26235878b55SSascha Wildner PUCHAR ke_area;
26335878b55SSascha Wildner int err;
26435878b55SSascha Wildner DWORD dwRet;
26535878b55SSascha Wildner PHPT_IOCTL_PARAM piop;
26635878b55SSascha Wildner #endif
26735878b55SSascha Wildner char *buffer = hptproc_buffer;
26835878b55SSascha Wildner if (length >= 6) {
26935878b55SSascha Wildner if (strncmp(buffer,"hpt ",4) == 0) {
27035878b55SSascha Wildner IAL_ADAPTER_T *pAdapter;
27135878b55SSascha Wildner retval = buffer[4]-'0';
27235878b55SSascha Wildner for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
27335878b55SSascha Wildner if (pAdapter->mvSataAdapter.adapterId==retval)
27435878b55SSascha Wildner return (retval = hpt_set_asc_info(pAdapter, buffer+6, length-6)) >= 0? retval : -EINVAL;
27535878b55SSascha Wildner }
27635878b55SSascha Wildner return -EINVAL;
27735878b55SSascha Wildner }
27835878b55SSascha Wildner #ifdef SUPPORT_IOCTL
27935878b55SSascha Wildner piop = (PHPT_IOCTL_PARAM)buffer;
28035878b55SSascha Wildner if (piop->Magic == HPT_IOCTL_MAGIC ||
28135878b55SSascha Wildner piop->Magic == HPT_IOCTL_MAGIC32) {
28235878b55SSascha Wildner KdPrintE(("ioctl=%d in=%p len=%d out=%p len=%d\n",
28335878b55SSascha Wildner piop->dwIoControlCode,
28435878b55SSascha Wildner piop->lpInBuffer,
28535878b55SSascha Wildner piop->nInBufferSize,
28635878b55SSascha Wildner piop->lpOutBuffer,
28735878b55SSascha Wildner piop->nOutBufferSize));
28835878b55SSascha Wildner
28935878b55SSascha Wildner /*
29035878b55SSascha Wildner * map buffer to kernel.
29135878b55SSascha Wildner */
29235878b55SSascha Wildner if (piop->nInBufferSize+piop->nOutBufferSize > PAGE_SIZE) {
29335878b55SSascha Wildner KdPrintE(("User buffer too large\n"));
29435878b55SSascha Wildner return -EINVAL;
29535878b55SSascha Wildner }
29635878b55SSascha Wildner
29735878b55SSascha Wildner ke_area = kmalloc(piop->nInBufferSize+piop->nOutBufferSize, M_DEVBUF, M_NOWAIT);
29835878b55SSascha Wildner if (ke_area == NULL) {
29935878b55SSascha Wildner KdPrintE(("Couldn't allocate kernel mem.\n"));
30035878b55SSascha Wildner return -EINVAL;
30135878b55SSascha Wildner }
30235878b55SSascha Wildner
30335878b55SSascha Wildner if (piop->nInBufferSize)
30435878b55SSascha Wildner copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize);
30535878b55SSascha Wildner
30635878b55SSascha Wildner /*
30735878b55SSascha Wildner * call kernel handler.
30835878b55SSascha Wildner */
30935878b55SSascha Wildner err = Kernel_DeviceIoControl(&gIal_Adapter->VBus,
31035878b55SSascha Wildner piop->dwIoControlCode, ke_area, piop->nInBufferSize,
31135878b55SSascha Wildner ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet);
31235878b55SSascha Wildner
31335878b55SSascha Wildner if (err==0) {
31435878b55SSascha Wildner if (piop->nOutBufferSize)
31535878b55SSascha Wildner copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize);
31635878b55SSascha Wildner
31735878b55SSascha Wildner if (piop->lpBytesReturned)
31835878b55SSascha Wildner copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD));
31935878b55SSascha Wildner
32035878b55SSascha Wildner kfree(ke_area, M_DEVBUF);
32135878b55SSascha Wildner return length;
32235878b55SSascha Wildner }
32335878b55SSascha Wildner else KdPrintW(("Kernel_ioctl(): return %d\n", err));
32435878b55SSascha Wildner
32535878b55SSascha Wildner kfree(ke_area, M_DEVBUF);
32635878b55SSascha Wildner return -EINVAL;
32735878b55SSascha Wildner } else {
32835878b55SSascha Wildner KdPrintW(("Wrong signature: %x\n", piop->Magic));
32935878b55SSascha Wildner return -EINVAL;
33035878b55SSascha Wildner }
33135878b55SSascha Wildner #endif
33235878b55SSascha Wildner }
33335878b55SSascha Wildner
33435878b55SSascha Wildner return -EINVAL;
33535878b55SSascha Wildner }
33635878b55SSascha Wildner
33735878b55SSascha Wildner #define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8))
33835878b55SSascha Wildner
33935878b55SSascha Wildner static void
get_disk_name(char * name,PDevice pDev)34035878b55SSascha Wildner get_disk_name(char *name, PDevice pDev)
34135878b55SSascha Wildner {
34235878b55SSascha Wildner int i;
34335878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pDev->mv;
34435878b55SSascha Wildner IDENTIFY_DATA2 *pIdentifyData = (IDENTIFY_DATA2 *)pMvSataChannel->identifyDevice;
34535878b55SSascha Wildner
34635878b55SSascha Wildner for (i = 0; i < 10; i++)
34735878b55SSascha Wildner ((WORD*)name)[i] = shortswap(pIdentifyData->ModelNumber[i]);
34835878b55SSascha Wildner name[20] = '\0';
34935878b55SSascha Wildner }
35035878b55SSascha Wildner
351b58f1e66SSascha Wildner static int hpt_copy_info(HPT_GET_INFO *, char *, ...) __printf0like(2, 3);
352b58f1e66SSascha Wildner
35335878b55SSascha Wildner static int
hpt_copy_info(HPT_GET_INFO * pinfo,char * fmt,...)35435878b55SSascha Wildner hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...)
35535878b55SSascha Wildner {
35635878b55SSascha Wildner int printfretval;
35735878b55SSascha Wildner __va_list ap;
35835878b55SSascha Wildner
35935878b55SSascha Wildner if(fmt == NULL) {
36035878b55SSascha Wildner *hptproc_buffer = 0;
36135878b55SSascha Wildner return (SYSCTL_OUT(pinfo, hptproc_buffer, 1));
36235878b55SSascha Wildner }
36335878b55SSascha Wildner else
36435878b55SSascha Wildner {
36535878b55SSascha Wildner __va_start(ap, fmt);
36635878b55SSascha Wildner printfretval = kvsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap);
36735878b55SSascha Wildner __va_end(ap);
36835878b55SSascha Wildner return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer)));
36935878b55SSascha Wildner }
37035878b55SSascha Wildner }
37135878b55SSascha Wildner
37235878b55SSascha Wildner static void
hpt_copy_disk_info(HPT_GET_INFO * pinfo,PVDevice pVDev,UINT iChan)37335878b55SSascha Wildner hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan)
37435878b55SSascha Wildner {
37535878b55SSascha Wildner char name[32], arrayname[16], *status;
37635878b55SSascha Wildner
37735878b55SSascha Wildner get_disk_name(name, &pVDev->u.disk);
37835878b55SSascha Wildner
37935878b55SSascha Wildner if (!pVDev->u.disk.df_on_line)
38035878b55SSascha Wildner status = "Disabled";
38135878b55SSascha Wildner else if (pVDev->VDeviceType==VD_SPARE)
38235878b55SSascha Wildner status = "Spare ";
38335878b55SSascha Wildner else
38435878b55SSascha Wildner status = "Normal ";
38535878b55SSascha Wildner
38635878b55SSascha Wildner #ifdef SUPPORT_ARRAY
38735878b55SSascha Wildner if(pVDev->pParent) {
38835878b55SSascha Wildner memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME);
38935878b55SSascha Wildner if (pVDev->pParent->u.array.CriticalMembers & (1<<pVDev->bSerialNumber))
39035878b55SSascha Wildner status = "Degraded";
39135878b55SSascha Wildner }
39235878b55SSascha Wildner else
39335878b55SSascha Wildner #endif
39435878b55SSascha Wildner arrayname[0]=0;
39535878b55SSascha Wildner
396b58f1e66SSascha Wildner hpt_copy_info(pinfo, "Channel %d %s %5lluMB %s %s\n",
39735878b55SSascha Wildner iChan+1,
39835878b55SSascha Wildner name, pVDev->VDeviceCapacity>>11, status, arrayname);
39935878b55SSascha Wildner }
40035878b55SSascha Wildner
40135878b55SSascha Wildner #ifdef SUPPORT_ARRAY
40235878b55SSascha Wildner static void
hpt_copy_array_info(HPT_GET_INFO * pinfo,int nld,PVDevice pArray)40335878b55SSascha Wildner hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray)
40435878b55SSascha Wildner {
40535878b55SSascha Wildner int i;
4064090d6ffSSascha Wildner char *sType=NULL, *sStatus=NULL;
40735878b55SSascha Wildner char buf[32];
40835878b55SSascha Wildner PVDevice pTmpArray;
40935878b55SSascha Wildner
41035878b55SSascha Wildner switch (pArray->VDeviceType) {
41135878b55SSascha Wildner case VD_RAID_0:
41235878b55SSascha Wildner for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
41335878b55SSascha Wildner if(pArray->u.array.pMember[i]) {
41435878b55SSascha Wildner if(mIsArray(pArray->u.array.pMember[i]))
41535878b55SSascha Wildner sType = "RAID 1/0 ";
41635878b55SSascha Wildner /* TO DO */
41735878b55SSascha Wildner else
41835878b55SSascha Wildner sType = "RAID 0 ";
41935878b55SSascha Wildner break;
42035878b55SSascha Wildner }
42135878b55SSascha Wildner break;
42235878b55SSascha Wildner
42335878b55SSascha Wildner case VD_RAID_1:
42435878b55SSascha Wildner sType = "RAID 1 ";
42535878b55SSascha Wildner break;
42635878b55SSascha Wildner
42735878b55SSascha Wildner case VD_JBOD:
42835878b55SSascha Wildner sType = "JBOD ";
42935878b55SSascha Wildner break;
43035878b55SSascha Wildner
43135878b55SSascha Wildner case VD_RAID_5:
43235878b55SSascha Wildner sType = "RAID 5 ";
43335878b55SSascha Wildner break;
43435878b55SSascha Wildner
43535878b55SSascha Wildner default:
43635878b55SSascha Wildner sType = "N/A ";
43735878b55SSascha Wildner break;
43835878b55SSascha Wildner }
43935878b55SSascha Wildner
44035878b55SSascha Wildner if (pArray->vf_online == 0)
44135878b55SSascha Wildner sStatus = "Disabled";
44235878b55SSascha Wildner else if (pArray->u.array.rf_broken)
44335878b55SSascha Wildner sStatus = "Critical";
44435878b55SSascha Wildner for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
44535878b55SSascha Wildner {
44635878b55SSascha Wildner if (!sStatus)
44735878b55SSascha Wildner {
44835878b55SSascha Wildner if(mIsArray(pArray->u.array.pMember[i]))
44935878b55SSascha Wildner pTmpArray = pArray->u.array.pMember[i];
45035878b55SSascha Wildner else
45135878b55SSascha Wildner pTmpArray = pArray;
45235878b55SSascha Wildner
45335878b55SSascha Wildner if (pTmpArray->u.array.rf_rebuilding) {
45435878b55SSascha Wildner #ifdef DEBUG
45535878b55SSascha Wildner ksprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11));
45635878b55SSascha Wildner #else
45735878b55SSascha Wildner ksprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
45835878b55SSascha Wildner #endif
45935878b55SSascha Wildner sStatus = buf;
46035878b55SSascha Wildner }
46135878b55SSascha Wildner else if (pTmpArray->u.array.rf_verifying) {
46235878b55SSascha Wildner ksprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
46335878b55SSascha Wildner sStatus = buf;
46435878b55SSascha Wildner }
46535878b55SSascha Wildner else if (pTmpArray->u.array.rf_need_rebuild)
46635878b55SSascha Wildner sStatus = "Critical";
46735878b55SSascha Wildner else if (pTmpArray->u.array.rf_broken)
46835878b55SSascha Wildner sStatus = "Critical";
46935878b55SSascha Wildner
47035878b55SSascha Wildner if(pTmpArray == pArray) goto out;
47135878b55SSascha Wildner }
47235878b55SSascha Wildner else
47335878b55SSascha Wildner goto out;
47435878b55SSascha Wildner }
47535878b55SSascha Wildner out:
47635878b55SSascha Wildner if (!sStatus) sStatus = "Normal";
47735878b55SSascha Wildner hpt_copy_info(pinfo, "%2d %11s %-20s %5lldMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus);
47835878b55SSascha Wildner }
47935878b55SSascha Wildner #endif
48035878b55SSascha Wildner
48135878b55SSascha Wildner static int
hpt_get_info(IAL_ADAPTER_T * pAdapter,HPT_GET_INFO * pinfo)48235878b55SSascha Wildner hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo)
48335878b55SSascha Wildner {
48435878b55SSascha Wildner PVBus _vbus_p = &pAdapter->VBus;
48535878b55SSascha Wildner struct cam_periph *periph = NULL;
48635878b55SSascha Wildner UINT channel,j,i;
48735878b55SSascha Wildner PVDevice pVDev;
48835878b55SSascha Wildner
48935878b55SSascha Wildner #ifndef FOR_DEMO
49035878b55SSascha Wildner if (pAdapter->beeping) {
491c898d682SSascha Wildner lock_driver();
49235878b55SSascha Wildner pAdapter->beeping = 0;
49335878b55SSascha Wildner BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
494c898d682SSascha Wildner unlock_driver();
49535878b55SSascha Wildner }
49635878b55SSascha Wildner #endif
49735878b55SSascha Wildner
49835878b55SSascha Wildner hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId);
49935878b55SSascha Wildner
50035878b55SSascha Wildner hpt_copy_info(pinfo, "Physical device list\n");
50135878b55SSascha Wildner hpt_copy_info(pinfo, "Channel Model Capacity Status Array\n");
50235878b55SSascha Wildner hpt_copy_info(pinfo, "-------------------------------------------------------------------\n");
50335878b55SSascha Wildner
50435878b55SSascha Wildner for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
50535878b55SSascha Wildner {
50635878b55SSascha Wildner pVDev = &(pAdapter->VDevices[channel]);
50735878b55SSascha Wildner if(pVDev->u.disk.df_on_line)
50835878b55SSascha Wildner hpt_copy_disk_info(pinfo, pVDev, channel);
50935878b55SSascha Wildner }
51035878b55SSascha Wildner
51135878b55SSascha Wildner hpt_copy_info(pinfo, "\nLogical device list\n");
51235878b55SSascha Wildner hpt_copy_info(pinfo, "No. Type Name Capacity Status OsDisk\n");
51335878b55SSascha Wildner hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n");
51435878b55SSascha Wildner
51535878b55SSascha Wildner j=1;
51635878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){
51735878b55SSascha Wildner pVDev = _vbus_p->pVDevice[i];
51835878b55SSascha Wildner if(pVDev){
51935878b55SSascha Wildner j=i+1;
52035878b55SSascha Wildner #ifdef SUPPORT_ARRAY
52135878b55SSascha Wildner if (mIsArray(pVDev))
52235878b55SSascha Wildner {
52335878b55SSascha Wildner is_array:
52435878b55SSascha Wildner hpt_copy_array_info(pinfo, j, pVDev);
52535878b55SSascha Wildner }
52635878b55SSascha Wildner else
52735878b55SSascha Wildner #endif
52835878b55SSascha Wildner {
52935878b55SSascha Wildner char name[32];
53035878b55SSascha Wildner /* it may be add to an array after driver loaded, check it */
53135878b55SSascha Wildner #ifdef SUPPORT_ARRAY
53235878b55SSascha Wildner if (pVDev->pParent)
53335878b55SSascha Wildner /* in this case, pVDev can only be a RAID 1 source disk. */
53435878b55SSascha Wildner if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0])
53535878b55SSascha Wildner goto is_array;
53635878b55SSascha Wildner #endif
53735878b55SSascha Wildner get_disk_name(name, &pVDev->u.disk);
53835878b55SSascha Wildner
539b58f1e66SSascha Wildner hpt_copy_info(pinfo, "%2d %s %s %5lluMB %-16s",
54035878b55SSascha Wildner j, "Single disk", name, pVDev->VDeviceCapacity>>11,
54135878b55SSascha Wildner /* gmm 2001-6-19: Check if pDev has been added to an array. */
54235878b55SSascha Wildner ((pVDev->pParent) ? "Unavailable" : "Normal"));
54335878b55SSascha Wildner }
54435878b55SSascha Wildner periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
54535878b55SSascha Wildner if (periph == NULL)
54635878b55SSascha Wildner hpt_copy_info(pinfo," %s\n","not registered");
54735878b55SSascha Wildner else
54835878b55SSascha Wildner hpt_copy_info(pinfo," %s%d\n", periph->periph_name, periph->unit_number);
54935878b55SSascha Wildner }
55035878b55SSascha Wildner }
55135878b55SSascha Wildner return 0;
55235878b55SSascha Wildner }
55335878b55SSascha Wildner
55435878b55SSascha Wildner static __inline int
hpt_proc_in(FORMAL_HANDLER_ARGS,int * len)55535878b55SSascha Wildner hpt_proc_in(FORMAL_HANDLER_ARGS, int *len)
55635878b55SSascha Wildner {
55735878b55SSascha Wildner int i, error=0;
55835878b55SSascha Wildner
55935878b55SSascha Wildner *len = 0;
56035878b55SSascha Wildner if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) {
56135878b55SSascha Wildner error = EINVAL;
56235878b55SSascha Wildner } else {
56335878b55SSascha Wildner i = (req->newlen - req->newidx);
56435878b55SSascha Wildner error = SYSCTL_IN(req, hptproc_buffer, i);
56535878b55SSascha Wildner if (!error)
56635878b55SSascha Wildner *len = i;
56735878b55SSascha Wildner (hptproc_buffer)[i] = '\0';
56835878b55SSascha Wildner }
56935878b55SSascha Wildner return (error);
57035878b55SSascha Wildner }
57135878b55SSascha Wildner
57235878b55SSascha Wildner static int
hpt_status(FORMAL_HANDLER_ARGS)57335878b55SSascha Wildner hpt_status(FORMAL_HANDLER_ARGS)
57435878b55SSascha Wildner {
57535878b55SSascha Wildner int length, error=0, retval=0;
57635878b55SSascha Wildner IAL_ADAPTER_T *pAdapter;
57735878b55SSascha Wildner
57835878b55SSascha Wildner error = hpt_proc_in(REAL_HANDLER_ARGS, &length);
57935878b55SSascha Wildner
58035878b55SSascha Wildner if (req->newptr != NULL)
58135878b55SSascha Wildner {
58235878b55SSascha Wildner if (error || length == 0)
58335878b55SSascha Wildner {
58435878b55SSascha Wildner KdPrint(("error!\n"));
58535878b55SSascha Wildner retval = EINVAL;
58635878b55SSascha Wildner goto out;
58735878b55SSascha Wildner }
58835878b55SSascha Wildner
58935878b55SSascha Wildner if (hpt_set_info(length) >= 0)
59035878b55SSascha Wildner retval = 0;
59135878b55SSascha Wildner else
59235878b55SSascha Wildner retval = EINVAL;
59335878b55SSascha Wildner goto out;
59435878b55SSascha Wildner }
59535878b55SSascha Wildner
59635878b55SSascha Wildner hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION);
59735878b55SSascha Wildner for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
59835878b55SSascha Wildner if (hpt_get_info(pAdapter, req) < 0) {
59935878b55SSascha Wildner retval = EINVAL;
60035878b55SSascha Wildner break;
60135878b55SSascha Wildner }
60235878b55SSascha Wildner }
60335878b55SSascha Wildner
60435878b55SSascha Wildner hpt_copy_info(req, NULL);
60535878b55SSascha Wildner goto out;
60635878b55SSascha Wildner
60735878b55SSascha Wildner out:
60835878b55SSascha Wildner return (retval);
60935878b55SSascha Wildner }
61035878b55SSascha Wildner
61135878b55SSascha Wildner
61235878b55SSascha Wildner #define xhptregister_node(name) hptregister_node(name)
61335878b55SSascha Wildner
61435878b55SSascha Wildner #define hptregister_node(name) \
61535878b55SSascha Wildner SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \
61635878b55SSascha Wildner SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \
617*e8b301fbSSascha Wildner NULL, 0, hpt_status, "A", "Get/Set " #name " state")
61835878b55SSascha Wildner
61935878b55SSascha Wildner xhptregister_node(PROC_DIR_NAME);
620