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 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 { 76*c898d682SSascha 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 } 85*c898d682SSascha Wildner unlock_driver(); 8635878b55SSascha Wildner return orig_length; 8735878b55SSascha Wildner } 8835878b55SSascha Wildner else if (length>=4 && strncmp(buffer, "stop", 4)==0) 8935878b55SSascha Wildner { 90*c898d682SSascha 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 } 98*c898d682SSascha 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: 141*c898d682SSascha Wildner lock_driver(); 14235878b55SSascha Wildner if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) { 143*c898d682SSascha 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); 149*c898d682SSascha 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 { 190*c898d682SSascha Wildner lock_driver(); 19135878b55SSascha Wildner pArray->u.array.RebuildSectors = 0; 19235878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY); 193*c898d682SSascha 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 { 211*c898d682SSascha Wildner lock_driver(); 21235878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 1; 213*c898d682SSascha 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 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 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 35135878b55SSascha Wildner static int 35235878b55SSascha Wildner hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...) 35335878b55SSascha Wildner { 35435878b55SSascha Wildner int printfretval; 35535878b55SSascha Wildner __va_list ap; 35635878b55SSascha Wildner 35735878b55SSascha Wildner if(fmt == NULL) { 35835878b55SSascha Wildner *hptproc_buffer = 0; 35935878b55SSascha Wildner return (SYSCTL_OUT(pinfo, hptproc_buffer, 1)); 36035878b55SSascha Wildner } 36135878b55SSascha Wildner else 36235878b55SSascha Wildner { 36335878b55SSascha Wildner __va_start(ap, fmt); 36435878b55SSascha Wildner printfretval = kvsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap); 36535878b55SSascha Wildner __va_end(ap); 36635878b55SSascha Wildner return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer))); 36735878b55SSascha Wildner } 36835878b55SSascha Wildner } 36935878b55SSascha Wildner 37035878b55SSascha Wildner static void 37135878b55SSascha Wildner hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan) 37235878b55SSascha Wildner { 37335878b55SSascha Wildner char name[32], arrayname[16], *status; 37435878b55SSascha Wildner 37535878b55SSascha Wildner get_disk_name(name, &pVDev->u.disk); 37635878b55SSascha Wildner 37735878b55SSascha Wildner if (!pVDev->u.disk.df_on_line) 37835878b55SSascha Wildner status = "Disabled"; 37935878b55SSascha Wildner else if (pVDev->VDeviceType==VD_SPARE) 38035878b55SSascha Wildner status = "Spare "; 38135878b55SSascha Wildner else 38235878b55SSascha Wildner status = "Normal "; 38335878b55SSascha Wildner 38435878b55SSascha Wildner #ifdef SUPPORT_ARRAY 38535878b55SSascha Wildner if(pVDev->pParent) { 38635878b55SSascha Wildner memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME); 38735878b55SSascha Wildner if (pVDev->pParent->u.array.CriticalMembers & (1<<pVDev->bSerialNumber)) 38835878b55SSascha Wildner status = "Degraded"; 38935878b55SSascha Wildner } 39035878b55SSascha Wildner else 39135878b55SSascha Wildner #endif 39235878b55SSascha Wildner arrayname[0]=0; 39335878b55SSascha Wildner 39435878b55SSascha Wildner hpt_copy_info(pinfo, "Channel %d %s %5dMB %s %s\n", 39535878b55SSascha Wildner iChan+1, 39635878b55SSascha Wildner name, pVDev->VDeviceCapacity>>11, status, arrayname); 39735878b55SSascha Wildner } 39835878b55SSascha Wildner 39935878b55SSascha Wildner #ifdef SUPPORT_ARRAY 40035878b55SSascha Wildner static void 40135878b55SSascha Wildner hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray) 40235878b55SSascha Wildner { 40335878b55SSascha Wildner int i; 40435878b55SSascha Wildner char *sType=0, *sStatus=0; 40535878b55SSascha Wildner char buf[32]; 40635878b55SSascha Wildner PVDevice pTmpArray; 40735878b55SSascha Wildner 40835878b55SSascha Wildner switch (pArray->VDeviceType) { 40935878b55SSascha Wildner case VD_RAID_0: 41035878b55SSascha Wildner for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) 41135878b55SSascha Wildner if(pArray->u.array.pMember[i]) { 41235878b55SSascha Wildner if(mIsArray(pArray->u.array.pMember[i])) 41335878b55SSascha Wildner sType = "RAID 1/0 "; 41435878b55SSascha Wildner /* TO DO */ 41535878b55SSascha Wildner else 41635878b55SSascha Wildner sType = "RAID 0 "; 41735878b55SSascha Wildner break; 41835878b55SSascha Wildner } 41935878b55SSascha Wildner break; 42035878b55SSascha Wildner 42135878b55SSascha Wildner case VD_RAID_1: 42235878b55SSascha Wildner sType = "RAID 1 "; 42335878b55SSascha Wildner break; 42435878b55SSascha Wildner 42535878b55SSascha Wildner case VD_JBOD: 42635878b55SSascha Wildner sType = "JBOD "; 42735878b55SSascha Wildner break; 42835878b55SSascha Wildner 42935878b55SSascha Wildner case VD_RAID_5: 43035878b55SSascha Wildner sType = "RAID 5 "; 43135878b55SSascha Wildner break; 43235878b55SSascha Wildner 43335878b55SSascha Wildner default: 43435878b55SSascha Wildner sType = "N/A "; 43535878b55SSascha Wildner break; 43635878b55SSascha Wildner } 43735878b55SSascha Wildner 43835878b55SSascha Wildner if (pArray->vf_online == 0) 43935878b55SSascha Wildner sStatus = "Disabled"; 44035878b55SSascha Wildner else if (pArray->u.array.rf_broken) 44135878b55SSascha Wildner sStatus = "Critical"; 44235878b55SSascha Wildner for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) 44335878b55SSascha Wildner { 44435878b55SSascha Wildner if (!sStatus) 44535878b55SSascha Wildner { 44635878b55SSascha Wildner if(mIsArray(pArray->u.array.pMember[i])) 44735878b55SSascha Wildner pTmpArray = pArray->u.array.pMember[i]; 44835878b55SSascha Wildner else 44935878b55SSascha Wildner pTmpArray = pArray; 45035878b55SSascha Wildner 45135878b55SSascha Wildner if (pTmpArray->u.array.rf_rebuilding) { 45235878b55SSascha Wildner #ifdef DEBUG 45335878b55SSascha Wildner ksprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11)); 45435878b55SSascha Wildner #else 45535878b55SSascha Wildner ksprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11))); 45635878b55SSascha Wildner #endif 45735878b55SSascha Wildner sStatus = buf; 45835878b55SSascha Wildner } 45935878b55SSascha Wildner else if (pTmpArray->u.array.rf_verifying) { 46035878b55SSascha Wildner ksprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11))); 46135878b55SSascha Wildner sStatus = buf; 46235878b55SSascha Wildner } 46335878b55SSascha Wildner else if (pTmpArray->u.array.rf_need_rebuild) 46435878b55SSascha Wildner sStatus = "Critical"; 46535878b55SSascha Wildner else if (pTmpArray->u.array.rf_broken) 46635878b55SSascha Wildner sStatus = "Critical"; 46735878b55SSascha Wildner 46835878b55SSascha Wildner if(pTmpArray == pArray) goto out; 46935878b55SSascha Wildner } 47035878b55SSascha Wildner else 47135878b55SSascha Wildner goto out; 47235878b55SSascha Wildner } 47335878b55SSascha Wildner out: 47435878b55SSascha Wildner if (!sStatus) sStatus = "Normal"; 47535878b55SSascha Wildner hpt_copy_info(pinfo, "%2d %11s %-20s %5lldMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus); 47635878b55SSascha Wildner } 47735878b55SSascha Wildner #endif 47835878b55SSascha Wildner 47935878b55SSascha Wildner static int 48035878b55SSascha Wildner hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo) 48135878b55SSascha Wildner { 48235878b55SSascha Wildner PVBus _vbus_p = &pAdapter->VBus; 48335878b55SSascha Wildner struct cam_periph *periph = NULL; 48435878b55SSascha Wildner UINT channel,j,i; 48535878b55SSascha Wildner PVDevice pVDev; 48635878b55SSascha Wildner 48735878b55SSascha Wildner #ifndef FOR_DEMO 48835878b55SSascha Wildner if (pAdapter->beeping) { 489*c898d682SSascha Wildner lock_driver(); 49035878b55SSascha Wildner pAdapter->beeping = 0; 49135878b55SSascha Wildner BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 492*c898d682SSascha Wildner unlock_driver(); 49335878b55SSascha Wildner } 49435878b55SSascha Wildner #endif 49535878b55SSascha Wildner 49635878b55SSascha Wildner hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId); 49735878b55SSascha Wildner 49835878b55SSascha Wildner hpt_copy_info(pinfo, "Physical device list\n"); 49935878b55SSascha Wildner hpt_copy_info(pinfo, "Channel Model Capacity Status Array\n"); 50035878b55SSascha Wildner hpt_copy_info(pinfo, "-------------------------------------------------------------------\n"); 50135878b55SSascha Wildner 50235878b55SSascha Wildner for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 50335878b55SSascha Wildner { 50435878b55SSascha Wildner pVDev = &(pAdapter->VDevices[channel]); 50535878b55SSascha Wildner if(pVDev->u.disk.df_on_line) 50635878b55SSascha Wildner hpt_copy_disk_info(pinfo, pVDev, channel); 50735878b55SSascha Wildner } 50835878b55SSascha Wildner 50935878b55SSascha Wildner hpt_copy_info(pinfo, "\nLogical device list\n"); 51035878b55SSascha Wildner hpt_copy_info(pinfo, "No. Type Name Capacity Status OsDisk\n"); 51135878b55SSascha Wildner hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n"); 51235878b55SSascha Wildner 51335878b55SSascha Wildner j=1; 51435878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){ 51535878b55SSascha Wildner pVDev = _vbus_p->pVDevice[i]; 51635878b55SSascha Wildner if(pVDev){ 51735878b55SSascha Wildner j=i+1; 51835878b55SSascha Wildner #ifdef SUPPORT_ARRAY 51935878b55SSascha Wildner if (mIsArray(pVDev)) 52035878b55SSascha Wildner { 52135878b55SSascha Wildner is_array: 52235878b55SSascha Wildner hpt_copy_array_info(pinfo, j, pVDev); 52335878b55SSascha Wildner } 52435878b55SSascha Wildner else 52535878b55SSascha Wildner #endif 52635878b55SSascha Wildner { 52735878b55SSascha Wildner char name[32]; 52835878b55SSascha Wildner /* it may be add to an array after driver loaded, check it */ 52935878b55SSascha Wildner #ifdef SUPPORT_ARRAY 53035878b55SSascha Wildner if (pVDev->pParent) 53135878b55SSascha Wildner /* in this case, pVDev can only be a RAID 1 source disk. */ 53235878b55SSascha Wildner if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0]) 53335878b55SSascha Wildner goto is_array; 53435878b55SSascha Wildner #endif 53535878b55SSascha Wildner get_disk_name(name, &pVDev->u.disk); 53635878b55SSascha Wildner 53735878b55SSascha Wildner hpt_copy_info(pinfo, "%2d %s %s %5dMB %-16s", 53835878b55SSascha Wildner j, "Single disk", name, pVDev->VDeviceCapacity>>11, 53935878b55SSascha Wildner /* gmm 2001-6-19: Check if pDev has been added to an array. */ 54035878b55SSascha Wildner ((pVDev->pParent) ? "Unavailable" : "Normal")); 54135878b55SSascha Wildner } 54235878b55SSascha Wildner periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 54335878b55SSascha Wildner if (periph == NULL) 54435878b55SSascha Wildner hpt_copy_info(pinfo," %s\n","not registered"); 54535878b55SSascha Wildner else 54635878b55SSascha Wildner hpt_copy_info(pinfo," %s%d\n", periph->periph_name, periph->unit_number); 54735878b55SSascha Wildner } 54835878b55SSascha Wildner } 54935878b55SSascha Wildner return 0; 55035878b55SSascha Wildner } 55135878b55SSascha Wildner 55235878b55SSascha Wildner static __inline int 55335878b55SSascha Wildner hpt_proc_in(FORMAL_HANDLER_ARGS, int *len) 55435878b55SSascha Wildner { 55535878b55SSascha Wildner int i, error=0; 55635878b55SSascha Wildner 55735878b55SSascha Wildner *len = 0; 55835878b55SSascha Wildner if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) { 55935878b55SSascha Wildner error = EINVAL; 56035878b55SSascha Wildner } else { 56135878b55SSascha Wildner i = (req->newlen - req->newidx); 56235878b55SSascha Wildner error = SYSCTL_IN(req, hptproc_buffer, i); 56335878b55SSascha Wildner if (!error) 56435878b55SSascha Wildner *len = i; 56535878b55SSascha Wildner (hptproc_buffer)[i] = '\0'; 56635878b55SSascha Wildner } 56735878b55SSascha Wildner return (error); 56835878b55SSascha Wildner } 56935878b55SSascha Wildner 57035878b55SSascha Wildner static int 57135878b55SSascha Wildner hpt_status(FORMAL_HANDLER_ARGS) 57235878b55SSascha Wildner { 57335878b55SSascha Wildner int length, error=0, retval=0; 57435878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 57535878b55SSascha Wildner 57635878b55SSascha Wildner error = hpt_proc_in(REAL_HANDLER_ARGS, &length); 57735878b55SSascha Wildner 57835878b55SSascha Wildner if (req->newptr != NULL) 57935878b55SSascha Wildner { 58035878b55SSascha Wildner if (error || length == 0) 58135878b55SSascha Wildner { 58235878b55SSascha Wildner KdPrint(("error!\n")); 58335878b55SSascha Wildner retval = EINVAL; 58435878b55SSascha Wildner goto out; 58535878b55SSascha Wildner } 58635878b55SSascha Wildner 58735878b55SSascha Wildner if (hpt_set_info(length) >= 0) 58835878b55SSascha Wildner retval = 0; 58935878b55SSascha Wildner else 59035878b55SSascha Wildner retval = EINVAL; 59135878b55SSascha Wildner goto out; 59235878b55SSascha Wildner } 59335878b55SSascha Wildner 59435878b55SSascha Wildner hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION); 59535878b55SSascha Wildner for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 59635878b55SSascha Wildner if (hpt_get_info(pAdapter, req) < 0) { 59735878b55SSascha Wildner retval = EINVAL; 59835878b55SSascha Wildner break; 59935878b55SSascha Wildner } 60035878b55SSascha Wildner } 60135878b55SSascha Wildner 60235878b55SSascha Wildner hpt_copy_info(req, NULL); 60335878b55SSascha Wildner goto out; 60435878b55SSascha Wildner 60535878b55SSascha Wildner out: 60635878b55SSascha Wildner return (retval); 60735878b55SSascha Wildner } 60835878b55SSascha Wildner 60935878b55SSascha Wildner 61035878b55SSascha Wildner #define xhptregister_node(name) hptregister_node(name) 61135878b55SSascha Wildner 61235878b55SSascha Wildner #define hptregister_node(name) \ 61335878b55SSascha Wildner SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \ 61435878b55SSascha Wildner SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ 61535878b55SSascha Wildner NULL, 0, hpt_status, "A", "Get/Set " #name " state"); 61635878b55SSascha Wildner 61735878b55SSascha Wildner xhptregister_node(PROC_DIR_NAME); 618