1331722Seadler/*
2149871Sscottl * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
3136849Sscottl * All rights reserved.
4136849Sscottl *
5136849Sscottl * Redistribution and use in source and binary forms, with or without
6136849Sscottl * modification, are permitted provided that the following conditions
7136849Sscottl * are met:
8136849Sscottl * 1. Redistributions of source code must retain the above copyright
9136849Sscottl *    notice, this list of conditions and the following disclaimer.
10136849Sscottl * 2. Redistributions in binary form must reproduce the above copyright
11136849Sscottl *    notice, this list of conditions and the following disclaimer in the
12136849Sscottl *    documentation and/or other materials provided with the distribution.
13136849Sscottl *
14136849Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15136849Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16136849Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17136849Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18136849Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19136849Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20136849Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21136849Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22136849Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23136849Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24136849Sscottl * SUCH DAMAGE.
25142988Sscottl *
26142988Sscottl * $FreeBSD: stable/11/sys/dev/hptmv/hptproc.c 315221 2017-03-14 02:06:03Z pfg $
27136849Sscottl */
28136849Sscottl/*
29136849Sscottl * hptproc.c  sysctl support
30136849Sscottl */
31136849Sscottl#include <sys/param.h>
32136849Sscottl#include <sys/systm.h>
33136849Sscottl#include <sys/kernel.h>
34136849Sscottl#include <sys/malloc.h>
35136849Sscottl#include <sys/sysctl.h>
36136849Sscottl#include <machine/stdarg.h>
37136849Sscottl
38149871Sscottl#ifndef __KERNEL__
39149871Sscottl#define __KERNEL__
40149871Sscottl#endif
41149871Sscottl
42136849Sscottl#include <dev/hptmv/global.h>
43136849Sscottl#include <dev/hptmv/hptintf.h>
44136849Sscottl#include <dev/hptmv/osbsd.h>
45143039Sscottl#include <dev/hptmv/access601.h>
46136849Sscottl
47136849Sscottlint hpt_rescan_all(void);
48136849Sscottl
49136849Sscottl/***************************************************************************/
50136849Sscottl
51136849Sscottlstatic char hptproc_buffer[256];
52149871Sscottlextern char DRIVER_VERSION[];
53136849Sscottl
54136849Sscottltypedef struct sysctl_req HPT_GET_INFO;
55136849Sscottl
56149871Sscottlstatic int
57149871Sscottlhpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length)
58136849Sscottl{
59136849Sscottl	int orig_length = length+4;
60136849Sscottl	PVBus _vbus_p = &pAdapter->VBus;
61136849Sscottl	PVDevice	 pArray;
62136849Sscottl	PVDevice pSubArray, pVDev;
63136849Sscottl	UINT	i, iarray, ichan;
64136849Sscottl	struct cam_periph *periph = NULL;
65136849Sscottl
66269617Sjhb	mtx_lock(&pAdapter->lock);
67136849Sscottl#ifdef SUPPORT_ARRAY
68136849Sscottl	if (length>=8 && strncmp(buffer, "rebuild ", 8)==0)
69136849Sscottl	{
70136849Sscottl		buffer+=8;
71136849Sscottl		length-=8;
72136849Sscottl		if (length>=5 && strncmp(buffer, "start", 5)==0)
73136849Sscottl		{
74136849Sscottl			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
75136849Sscottl				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
76136849Sscottl					continue;
77136849Sscottl				else{
78136849Sscottl					if (pArray->u.array.rf_need_rebuild && !pArray->u.array.rf_rebuilding)
79136849Sscottl	                    hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
80136849Sscottl							(UCHAR)((pArray->u.array.CriticalMembers || pArray->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
81136849Sscottl				}
82269617Sjhb			mtx_unlock(&pAdapter->lock);
83136849Sscottl			return orig_length;
84136849Sscottl		}
85136849Sscottl		else if (length>=4 && strncmp(buffer, "stop", 4)==0)
86136849Sscottl		{
87136849Sscottl			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
88136849Sscottl				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
89136849Sscottl					continue;
90136849Sscottl				else{
91136849Sscottl					if (pArray->u.array.rf_rebuilding)
92136849Sscottl					    pArray->u.array.rf_abort_rebuild = 1;
93136849Sscottl				}
94269617Sjhb			mtx_unlock(&pAdapter->lock);
95136849Sscottl			return orig_length;
96136849Sscottl		}
97136849Sscottl		else if (length>=3 && buffer[1]==','&& buffer[0]>='1'&& buffer[2]>='1')
98136849Sscottl		{
99136849Sscottl			iarray = buffer[0]-'1';
100136849Sscottl	        ichan = buffer[2]-'1';
101136849Sscottl
102136849Sscottl            if(iarray >= MAX_VDEVICE_PER_VBUS || ichan >= MV_SATA_CHANNELS_NUM) return -EINVAL;
103136849Sscottl
104136849Sscottl			pArray = _vbus_p->pVDevice[iarray];
105269617Sjhb			if (!pArray || (pArray->vf_online == 0)) {
106269617Sjhb				mtx_unlock(&pAdapter->lock);
107269617Sjhb				return -EINVAL;
108269617Sjhb			}
109136849Sscottl
110136849Sscottl            for (i=0;i<MV_SATA_CHANNELS_NUM;i++)
111136849Sscottl				if(i == ichan)
112136849Sscottl				    goto rebuild;
113136849Sscottl
114269617Sjhb	        mtx_unlock(&pAdapter->lock);
115136849Sscottl	        return -EINVAL;
116136849Sscottl
117136849Sscottlrebuild:
118136849Sscottl	        pVDev = &pAdapter->VDevices[ichan];
119269617Sjhb	        if(!pVDev->u.disk.df_on_line || pVDev->pParent) {
120269617Sjhb			mtx_unlock(&pAdapter->lock);
121269617Sjhb			return -EINVAL;
122269617Sjhb		}
123136849Sscottl
124136849Sscottl	        /* Not allow to use a mounted disk ??? test*/
125136849Sscottl			for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
126136849Sscottl			    if(pVDev == _vbus_p->pVDevice[i])
127136849Sscottl			    {
128136849Sscottl					periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i);
129149871Sscottl					if (periph != NULL && periph->refcount >= 1)
130136849Sscottl					{
131136849Sscottl						hpt_printk(("Can not use disk used by OS!\n"));
132269617Sjhb			    mtx_unlock(&pAdapter->lock);
133136849Sscottl	                    return -EINVAL;
134136849Sscottl					}
135136849Sscottl					/* the Mounted Disk isn't delete */
136136849Sscottl				}
137136849Sscottl
138136849Sscottl			switch(pArray->VDeviceType)
139136849Sscottl			{
140136849Sscottl				case VD_RAID_1:
141136849Sscottl				case VD_RAID_5:
142136849Sscottl				{
143136849Sscottl					pSubArray = pArray;
144136849Sscottlloop:
145136849Sscottl					if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) {
146269617Sjhb						mtx_unlock(&pAdapter->lock);
147136849Sscottl						return -EINVAL;
148136849Sscottl					}
149149871Sscottl					pSubArray->u.array.rf_auto_rebuild = 0;
150149871Sscottl					pSubArray->u.array.rf_abort_rebuild = 0;
151149871Sscottl					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pSubArray, DUPLICATE);
152136849Sscottl					break;
153136849Sscottl				}
154136849Sscottl				case VD_RAID_0:
155136849Sscottl					for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
156136849Sscottl						if(pArray->u.array.pMember[i] && mIsArray(pArray->u.array.pMember[i]) &&
157136849Sscottl						   (pArray->u.array.pMember[i]->u.array.rf_broken == 1))
158136849Sscottl						{
159136849Sscottl							  pSubArray = pArray->u.array.pMember[i];
160136849Sscottl							  goto loop;
161136849Sscottl						}
162136849Sscottl				default:
163269617Sjhb					mtx_unlock(&pAdapter->lock);
164136849Sscottl					return -EINVAL;
165136849Sscottl			}
166269617Sjhb			mtx_unlock(&pAdapter->lock);
167136849Sscottl			return orig_length;
168136849Sscottl		}
169136849Sscottl	}
170136849Sscottl	else if (length>=7 && strncmp(buffer, "verify ", 7)==0)
171136849Sscottl	{
172136849Sscottl		buffer+=7;
173136849Sscottl		length-=7;
174136849Sscottl        if (length>=6 && strncmp(buffer, "start ", 6)==0)
175136849Sscottl		{
176136849Sscottl            buffer+=6;
177136849Sscottl		    length-=6;
178136849Sscottl            if (length>=1 && *buffer>='1')
179136849Sscottl			{
180136849Sscottl				iarray = *buffer-'1';
181269617Sjhb				if(iarray >= MAX_VDEVICE_PER_VBUS) {
182269617Sjhb					mtx_unlock(&pAdapter->lock);
183269617Sjhb					return -EINVAL;
184269617Sjhb				}
185136849Sscottl
186136849Sscottl				pArray = _vbus_p->pVDevice[iarray];
187269617Sjhb				if (!pArray || (pArray->vf_online == 0)) {
188269617Sjhb					mtx_unlock(&pAdapter->lock);
189269617Sjhb					return -EINVAL;
190269617Sjhb				}
191136849Sscottl
192269617Sjhb				if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) {
193269617Sjhb					mtx_unlock(&pAdapter->lock);
194136849Sscottl					return -EINVAL;
195269617Sjhb				}
196136849Sscottl
197136849Sscottl				if (!(pArray->u.array.rf_need_rebuild ||
198136849Sscottl					pArray->u.array.rf_rebuilding ||
199136849Sscottl					pArray->u.array.rf_verifying ||
200136849Sscottl					pArray->u.array.rf_initializing))
201136849Sscottl				{
202136849Sscottl					pArray->u.array.RebuildSectors = 0;
203136849Sscottl					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY);
204136849Sscottl				}
205269617Sjhb		mtx_unlock(&pAdapter->lock);
206136849Sscottl                return orig_length;
207136849Sscottl			}
208136849Sscottl		}
209136849Sscottl		else if (length>=5 && strncmp(buffer, "stop ", 5)==0)
210136849Sscottl		{
211136849Sscottl			buffer+=5;
212136849Sscottl		    length-=5;
213136849Sscottl            if (length>=1 && *buffer>='1')
214136849Sscottl			{
215136849Sscottl				iarray = *buffer-'1';
216269617Sjhb				if(iarray >= MAX_VDEVICE_PER_VBUS) {
217269617Sjhb					mtx_unlock(&pAdapter->lock);
218269617Sjhb					return -EINVAL;
219269617Sjhb				}
220136849Sscottl
221136849Sscottl				pArray = _vbus_p->pVDevice[iarray];
222269617Sjhb				if (!pArray || (pArray->vf_online == 0)) {
223269617Sjhb					mtx_unlock(&pAdapter->lock);
224269617Sjhb					return -EINVAL;
225269617Sjhb				}
226136849Sscottl				if(pArray->u.array.rf_verifying)
227136849Sscottl				{
228136849Sscottl				    pArray->u.array.rf_abort_rebuild = 1;
229136849Sscottl				}
230269617Sjhb			    mtx_unlock(&pAdapter->lock);
231136849Sscottl			    return orig_length;
232136849Sscottl			}
233136849Sscottl		}
234136849Sscottl	}
235136849Sscottl	else
236136849Sscottl#ifdef _RAID5N_
237136849Sscottl	if (length>=10 && strncmp(buffer, "writeback ", 10)==0) {
238136849Sscottl	    	buffer+=10;
239136849Sscottl		length-=10;
240136849Sscottl		if (length>=1 && *buffer>='0' && *buffer<='1') {
241136849Sscottl			_vbus_(r5.enable_write_back) = *buffer-'0';
242136849Sscottl			if (_vbus_(r5.enable_write_back))
243136849Sscottl				hpt_printk(("RAID5 write back enabled"));
244269617Sjhb			mtx_unlock(&pAdapter->lock);
245136849Sscottl			return orig_length;
246136849Sscottl		}
247136849Sscottl	}
248136849Sscottl	else
249136849Sscottl#endif
250149871Sscottl#endif
251136849Sscottl	if (0) {} /* just to compile */
252153072Sru#ifdef DEBUG
253136849Sscottl	else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) {
254136849Sscottl	    	buffer+=9;
255136849Sscottl		length-=9;
256136849Sscottl		if (length>=1 && *buffer>='0' && *buffer<='3') {
257136849Sscottl			hpt_dbg_level = *buffer-'0';
258269617Sjhb			mtx_unlock(&pAdapter->lock);
259136849Sscottl			return orig_length;
260136849Sscottl		}
261136849Sscottl	}
262136849Sscottl	else if (length>=8 && strncmp(buffer, "disable ", 8)==0) {
263136849Sscottl		/* TO DO */
264136849Sscottl	}
265149871Sscottl#endif
266269617Sjhb	mtx_unlock(&pAdapter->lock);
267136849Sscottl
268136849Sscottl	return -EINVAL;
269136849Sscottl}
270136849Sscottl
271136849Sscottl/*
272136849Sscottl * Since we have only one sysctl node, add adapter ID in the command
273136849Sscottl * line string: e.g. "hpt 0 rebuild start"
274136849Sscottl */
275149871Sscottlstatic int
276149871Sscottlhpt_set_info(int length)
277136849Sscottl{
278136849Sscottl	int retval;
279136849Sscottl
280136849Sscottl#ifdef SUPPORT_IOCTL
281136849Sscottl	PUCHAR ke_area;
282136849Sscottl	int err;
283136849Sscottl	DWORD dwRet;
284149871Sscottl	PHPT_IOCTL_PARAM piop;
285136849Sscottl#endif
286136849Sscottl	char *buffer = hptproc_buffer;
287136849Sscottl	if (length >= 6) {
288136849Sscottl		if (strncmp(buffer,"hpt ",4) == 0) {
289136849Sscottl			IAL_ADAPTER_T *pAdapter;
290136849Sscottl			retval = buffer[4]-'0';
291136849Sscottl			for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
292136849Sscottl				if (pAdapter->mvSataAdapter.adapterId==retval)
293136849Sscottl					return (retval = hpt_set_asc_info(pAdapter, buffer+6, length-6)) >= 0? retval : -EINVAL;
294136849Sscottl			}
295136849Sscottl			return -EINVAL;
296136849Sscottl		}
297136849Sscottl#ifdef SUPPORT_IOCTL
298149871Sscottl		piop = (PHPT_IOCTL_PARAM)buffer;
299190809Sdelphij		if (piop->Magic == HPT_IOCTL_MAGIC ||
300190809Sdelphij			piop->Magic == HPT_IOCTL_MAGIC32) 	{
301149871Sscottl			KdPrintE(("ioctl=%d in=%p len=%d out=%p len=%d\n",
302136849Sscottl				piop->dwIoControlCode,
303136849Sscottl        			piop->lpInBuffer,
304136849Sscottl        			piop->nInBufferSize,
305136849Sscottl        			piop->lpOutBuffer,
306149871Sscottl	        		piop->nOutBufferSize));
307136849Sscottl
308136849Sscottl			/*
309136849Sscottl        	 	 * map buffer to kernel.
310136849Sscottl        	 	 */
311298231Ssbruno        		if (piop->nInBufferSize > PAGE_SIZE ||
312298231Ssbruno        			piop->nOutBufferSize > PAGE_SIZE ||
313298231Ssbruno        			piop->nInBufferSize+piop->nOutBufferSize > PAGE_SIZE) {
314136849Sscottl        			KdPrintE(("User buffer too large\n"));
315136849Sscottl        			return -EINVAL;
316136849Sscottl        		}
317136849Sscottl
318136849Sscottl        		ke_area = malloc(piop->nInBufferSize+piop->nOutBufferSize, M_DEVBUF, M_NOWAIT);
319136849Sscottl				if (ke_area == NULL) {
320136849Sscottl					KdPrintE(("Couldn't allocate kernel mem.\n"));
321136849Sscottl					return -EINVAL;
322136849Sscottl				}
323136849Sscottl
324298231Ssbruno			if (piop->nInBufferSize) {
325298231Ssbruno				if (copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize) != 0) {
326298231Ssbruno					KdPrintE(("Failed to copyin from lpInBuffer\n"));
327298231Ssbruno					free(ke_area, M_DEVBUF);
328298231Ssbruno					return -EFAULT;
329298231Ssbruno				}
330298231Ssbruno			}
331136849Sscottl
332136849Sscottl			/*
333136849Sscottl			  * call kernel handler.
334136849Sscottl			  */
335149871Sscottl			err = Kernel_DeviceIoControl(&gIal_Adapter->VBus,
336149871Sscottl				piop->dwIoControlCode, ke_area, piop->nInBufferSize,
337149871Sscottl				ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet);
338136849Sscottl
339136849Sscottl			if (err==0) {
340149871Sscottl				if (piop->nOutBufferSize)
341149871Sscottl					copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize);
342136849Sscottl
343149871Sscottl				if (piop->lpBytesReturned)
344149871Sscottl					copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD));
345136849Sscottl
346136849Sscottl				free(ke_area, M_DEVBUF);
347136849Sscottl				return length;
348136849Sscottl			}
349136849Sscottl			else  KdPrintW(("Kernel_ioctl(): return %d\n", err));
350136849Sscottl
351136849Sscottl			free(ke_area, M_DEVBUF);
352298231Ssbruno			return -EINVAL;
353136849Sscottl		} else 	{
354136849Sscottl    		KdPrintW(("Wrong signature: %x\n", piop->Magic));
355136849Sscottl    		return -EINVAL;
356136849Sscottl		}
357136849Sscottl#endif
358136849Sscottl	}
359136849Sscottl
360136849Sscottl	return -EINVAL;
361136849Sscottl}
362136849Sscottl
363136849Sscottl#define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8))
364136849Sscottl
365149871Sscottlstatic void
366149871Sscottlget_disk_name(char *name, PDevice pDev)
367136849Sscottl{
368136849Sscottl	int i;
369136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pDev->mv;
370136849Sscottl	IDENTIFY_DATA2 *pIdentifyData = (IDENTIFY_DATA2 *)pMvSataChannel->identifyDevice;
371136849Sscottl
372136849Sscottl	for (i = 0; i < 10; i++)
373136849Sscottl		((WORD*)name)[i] = shortswap(pIdentifyData->ModelNumber[i]);
374136849Sscottl	name[20] = '\0';
375136849Sscottl}
376136849Sscottl
377149871Sscottlstatic int
378149871Sscottlhpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...)
379136849Sscottl{
380136849Sscottl	int printfretval;
381136849Sscottl	va_list ap;
382136849Sscottl
383136849Sscottl	if(fmt == NULL) {
384136849Sscottl		*hptproc_buffer = 0;
385136849Sscottl		return (SYSCTL_OUT(pinfo, hptproc_buffer, 1));
386136849Sscottl	}
387136849Sscottl	else
388136849Sscottl	{
389136849Sscottl		va_start(ap, fmt);
390136849Sscottl		printfretval = vsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap);
391136849Sscottl		va_end(ap);
392136849Sscottl		return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer)));
393136849Sscottl	}
394136849Sscottl}
395136849Sscottl
396149871Sscottlstatic void
397149871Sscottlhpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan)
398136849Sscottl{
399149871Sscottl	char name[32], arrayname[16], *status;
400149871Sscottl
401149871Sscottl	get_disk_name(name, &pVDev->u.disk);
402136849Sscottl
403149871Sscottl	if (!pVDev->u.disk.df_on_line)
404149871Sscottl		status = "Disabled";
405149871Sscottl	else if (pVDev->VDeviceType==VD_SPARE)
406149871Sscottl		status = "Spare   ";
407149871Sscottl	else
408149871Sscottl		status = "Normal  ";
409136849Sscottl
410149871Sscottl#ifdef SUPPORT_ARRAY
411149871Sscottl	if(pVDev->pParent) {
412136849Sscottl		memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME);
413149871Sscottl		if (pVDev->pParent->u.array.CriticalMembers & (1<<pVDev->bSerialNumber))
414149871Sscottl			status = "Degraded";
415149871Sscottl	}
416136849Sscottl	else
417136849Sscottl#endif
418149871Sscottl		arrayname[0]=0;
419136849Sscottl
420136849Sscottl	hpt_copy_info(pinfo, "Channel %d  %s  %5dMB  %s %s\n",
421136849Sscottl		iChan+1,
422149871Sscottl		name, pVDev->VDeviceCapacity>>11, status, arrayname);
423136849Sscottl}
424136849Sscottl
425136849Sscottl#ifdef SUPPORT_ARRAY
426149871Sscottlstatic void
427149871Sscottlhpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray)
428136849Sscottl{
429136849Sscottl	int i;
430315221Spfg	char *sType = NULL, *sStatus = NULL;
431136849Sscottl	char buf[32];
432136849Sscottl    PVDevice pTmpArray;
433136849Sscottl
434136849Sscottl	switch (pArray->VDeviceType) {
435136849Sscottl		case VD_RAID_0:
436136849Sscottl			for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
437136849Sscottl		  		if(pArray->u.array.pMember[i])	{
438136849Sscottl			  		if(mIsArray(pArray->u.array.pMember[i]))
439136849Sscottl				 		sType = "RAID 1/0   ";
440136849Sscottl			  			/* TO DO */
441136849Sscottl			  		else
442136849Sscottl				 		sType = "RAID 0     ";
443136849Sscottl			  		break;
444136849Sscottl		  		}
445136849Sscottl			break;
446136849Sscottl
447136849Sscottl		case VD_RAID_1:
448136849Sscottl			sType = "RAID 1     ";
449136849Sscottl			break;
450136849Sscottl
451136849Sscottl		case VD_JBOD:
452136849Sscottl			sType = "JBOD       ";
453136849Sscottl			break;
454136849Sscottl
455136849Sscottl		case VD_RAID_5:
456136849Sscottl       		sType = "RAID 5     ";
457136849Sscottl			break;
458136849Sscottl
459136849Sscottl		default:
460136849Sscottl			sType = "N/A        ";
461136849Sscottl			break;
462136849Sscottl	}
463136849Sscottl
464136849Sscottl	if (pArray->vf_online == 0)
465136849Sscottl		sStatus = "Disabled";
466136849Sscottl	else if (pArray->u.array.rf_broken)
467136849Sscottl		sStatus = "Critical";
468136849Sscottl	for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++)
469136849Sscottl	{
470136849Sscottl		if (!sStatus)
471136849Sscottl		{
472136849Sscottl			if(mIsArray(pArray->u.array.pMember[i]))
473136849Sscottl                		pTmpArray = pArray->u.array.pMember[i];
474136849Sscottl			else
475136849Sscottl			   	pTmpArray = pArray;
476136849Sscottl
477136849Sscottl			if (pTmpArray->u.array.rf_rebuilding) {
478136849Sscottl#ifdef DEBUG
479190809Sdelphij				sprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11));
480149871Sscottl#else
481190809Sdelphij				sprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
482136849Sscottl#endif
483136849Sscottl				sStatus = buf;
484136849Sscottl			}
485136849Sscottl			else if (pTmpArray->u.array.rf_verifying) {
486190809Sdelphij				sprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
487136849Sscottl				sStatus = buf;
488136849Sscottl			}
489136849Sscottl			else if (pTmpArray->u.array.rf_need_rebuild)
490136849Sscottl				sStatus = "Critical";
491136849Sscottl			else if (pTmpArray->u.array.rf_broken)
492136849Sscottl				sStatus = "Critical";
493136849Sscottl
494136849Sscottl			if(pTmpArray == pArray) goto out;
495136849Sscottl		}
496136849Sscottl		else
497136849Sscottl			goto out;
498136849Sscottl	}
499136849Sscottlout:
500136849Sscottl	if (!sStatus) sStatus = "Normal";
501190809Sdelphij	hpt_copy_info(pinfo, "%2d  %11s  %-20s  %5lldMB  %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus);
502136849Sscottl}
503136849Sscottl#endif
504136849Sscottl
505149871Sscottlstatic int
506149871Sscottlhpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo)
507136849Sscottl{
508136849Sscottl	PVBus _vbus_p = &pAdapter->VBus;
509136849Sscottl	struct cam_periph *periph = NULL;
510136849Sscottl	UINT channel,j,i;
511136849Sscottl	PVDevice pVDev;
512136849Sscottl
513136849Sscottl#ifndef FOR_DEMO
514269617Sjhb	mtx_lock(&pAdapter->lock);
515136849Sscottl	if (pAdapter->beeping) {
516136849Sscottl		pAdapter->beeping = 0;
517136849Sscottl		BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
518136849Sscottl	}
519269617Sjhb	mtx_unlock(&pAdapter->lock);
520136849Sscottl#endif
521136849Sscottl
522136849Sscottl	hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId);
523136849Sscottl
524136849Sscottl	hpt_copy_info(pinfo, "Physical device list\n");
525136849Sscottl	hpt_copy_info(pinfo, "Channel    Model                Capacity  Status   Array\n");
526136849Sscottl	hpt_copy_info(pinfo, "-------------------------------------------------------------------\n");
527136849Sscottl
528136849Sscottl    for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
529136849Sscottl	{
530136849Sscottl		pVDev = &(pAdapter->VDevices[channel]);
531136849Sscottl		if(pVDev->u.disk.df_on_line)
532136849Sscottl			 hpt_copy_disk_info(pinfo, pVDev, channel);
533136849Sscottl	}
534136849Sscottl
535136849Sscottl	hpt_copy_info(pinfo, "\nLogical device list\n");
536136849Sscottl	hpt_copy_info(pinfo, "No. Type         Name                 Capacity  Status            OsDisk\n");
537136849Sscottl	hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n");
538136849Sscottl
539136849Sscottl	j=1;
540136849Sscottl	for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){
541136849Sscottl        pVDev = _vbus_p->pVDevice[i];
542136849Sscottl		if(pVDev){
543136849Sscottl			j=i+1;
544136849Sscottl#ifdef SUPPORT_ARRAY
545136849Sscottl			if (mIsArray(pVDev))
546136849Sscottl			{
547136849Sscottl		is_array:
548136849Sscottl				hpt_copy_array_info(pinfo, j, pVDev);
549136849Sscottl			}
550136849Sscottl			else
551136849Sscottl#endif
552136849Sscottl			{
553136849Sscottl				char name[32];
554136849Sscottl				/* it may be add to an array after driver loaded, check it */
555136849Sscottl#ifdef SUPPORT_ARRAY
556136849Sscottl				if (pVDev->pParent)
557136849Sscottl					/* in this case, pVDev can only be a RAID 1 source disk. */
558136849Sscottl					if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0])
559136849Sscottl						goto is_array;
560136849Sscottl#endif
561136849Sscottl				get_disk_name(name, &pVDev->u.disk);
562136849Sscottl
563136849Sscottl				hpt_copy_info(pinfo, "%2d  %s  %s  %5dMB  %-16s",
564136849Sscottl					j, "Single disk", name, pVDev->VDeviceCapacity>>11,
565136849Sscottl					/* gmm 2001-6-19: Check if pDev has been added to an array. */
566136849Sscottl					((pVDev->pParent) ? "Unavailable" : "Normal"));
567136849Sscottl			}
568136849Sscottl			periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
569136849Sscottl			if (periph == NULL)
570136849Sscottl				hpt_copy_info(pinfo,"  %s\n","not registered");
571136849Sscottl			else
572136849Sscottl				hpt_copy_info(pinfo,"  %s%d\n", periph->periph_name, periph->unit_number);
573136849Sscottl		 }
574136849Sscottl	}
575136849Sscottl	return 0;
576136849Sscottl}
577136849Sscottl
578149871Sscottlstatic __inline int
579290519Scemhpt_proc_in(SYSCTL_HANDLER_ARGS, int *len)
580136849Sscottl{
581136849Sscottl	int i, error=0;
582136849Sscottl
583136849Sscottl	*len = 0;
584136849Sscottl	if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) {
585136849Sscottl		error = EINVAL;
586136849Sscottl	} else {
587136849Sscottl		i = (req->newlen - req->newidx);
588136849Sscottl		error = SYSCTL_IN(req, hptproc_buffer, i);
589136849Sscottl		if (!error)
590136849Sscottl			*len = i;
591136849Sscottl		(hptproc_buffer)[i] = '\0';
592136849Sscottl	}
593136849Sscottl	return (error);
594136849Sscottl}
595136849Sscottl
596149871Sscottlstatic int
597290519Scemhpt_status(SYSCTL_HANDLER_ARGS)
598136849Sscottl{
599136849Sscottl	int length, error=0, retval=0;
600136849Sscottl	IAL_ADAPTER_T *pAdapter;
601136849Sscottl
602290519Scem	error = hpt_proc_in(oidp, arg1, arg2, req, &length);
603136849Sscottl
604136849Sscottl    if (req->newptr != NULL)
605136849Sscottl	{
606136849Sscottl		if (error || length == 0)
607136849Sscottl		{
608136849Sscottl    		KdPrint(("error!\n"));
609136849Sscottl    		retval = EINVAL;
610136849Sscottl    		goto out;
611136849Sscottl		}
612136849Sscottl
613136849Sscottl		if (hpt_set_info(length) >= 0)
614136849Sscottl			retval = 0;
615136849Sscottl		else
616136849Sscottl			retval = EINVAL;
617136849Sscottl		goto out;
618136849Sscottl    }
619136849Sscottl
620136849Sscottl	hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION);
621136849Sscottl	for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
622136849Sscottl		if (hpt_get_info(pAdapter, req) < 0) {
623136849Sscottl			retval = EINVAL;
624136849Sscottl			break;
625136849Sscottl		}
626136849Sscottl	}
627136849Sscottl
628136849Sscottl	hpt_copy_info(req, NULL);
629136849Sscottl	goto out;
630136849Sscottl
631136849Sscottlout:
632136849Sscottl	return (retval);
633136849Sscottl}
634136849Sscottl
635136849Sscottl
636136849Sscottl#define xhptregister_node(name) hptregister_node(name)
637136849Sscottl
638269617Sjhb#if __FreeBSD_version >= 1100024
639136849Sscottl#define hptregister_node(name) \
640269617Sjhb	SYSCTL_ROOT_NODE(OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \
641136849Sscottl	SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \
642136849Sscottl	NULL, 0, hpt_status, "A", "Get/Set " #name " state")
643269617Sjhb#else
644136849Sscottl#define hptregister_node(name) \
645269617Sjhb	SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \
646136849Sscottl	SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \
647269617Sjhb	NULL, 0, hpt_status, "A", "Get/Set " #name " state")
648136849Sscottl#endif
649136849Sscottl
650136849Sscottlxhptregister_node(PROC_DIR_NAME);
651