xref: /dragonfly/sys/dev/raid/hptmv/hptproc.c (revision e8b301fb)
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