1718cf2ccSPedro F. Giffuni /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4d2bd3ab9SScott Long * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
51713e81bSScott Long * All rights reserved.
61713e81bSScott Long *
71713e81bSScott Long * Redistribution and use in source and binary forms, with or without
81713e81bSScott Long * modification, are permitted provided that the following conditions
91713e81bSScott Long * are met:
101713e81bSScott Long * 1. Redistributions of source code must retain the above copyright
111713e81bSScott Long * notice, this list of conditions and the following disclaimer.
121713e81bSScott Long * 2. Redistributions in binary form must reproduce the above copyright
131713e81bSScott Long * notice, this list of conditions and the following disclaimer in the
141713e81bSScott Long * documentation and/or other materials provided with the distribution.
151713e81bSScott Long *
161713e81bSScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171713e81bSScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181713e81bSScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191713e81bSScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201713e81bSScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211713e81bSScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221713e81bSScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231713e81bSScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241713e81bSScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251713e81bSScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261713e81bSScott Long * SUCH DAMAGE.
271713e81bSScott Long */
281713e81bSScott Long /*
291713e81bSScott Long * ioctl.c ioctl interface implementation
301713e81bSScott Long */
311713e81bSScott Long #include <sys/param.h>
321713e81bSScott Long #include <sys/systm.h>
331713e81bSScott Long #include <sys/kernel.h>
341713e81bSScott Long #include <sys/malloc.h>
351713e81bSScott Long
36d2bd3ab9SScott Long #ifndef __KERNEL__
37d2bd3ab9SScott Long #define __KERNEL__
38d2bd3ab9SScott Long #endif
39d2bd3ab9SScott Long
401713e81bSScott Long #include <dev/hptmv/global.h>
411713e81bSScott Long #include <dev/hptmv/hptintf.h>
421713e81bSScott Long #include <dev/hptmv/osbsd.h>
43f7f3900bSScott Long #include <dev/hptmv/access601.h>
441713e81bSScott Long
451713e81bSScott Long #pragma pack(1)
461713e81bSScott Long
471713e81bSScott Long typedef struct _HPT_REBUILD_PARAM
481713e81bSScott Long {
491713e81bSScott Long DEVICEID idMirror;
501713e81bSScott Long DWORD Lba;
511713e81bSScott Long UCHAR nSector;
521713e81bSScott Long } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
531713e81bSScott Long
541713e81bSScott Long #pragma pack()
551713e81bSScott Long
561713e81bSScott Long #define MAX_EVENTS 10
571713e81bSScott Long static HPT_EVENT hpt_event_queue[MAX_EVENTS];
581713e81bSScott Long static int event_queue_head=0, event_queue_tail=0;
591713e81bSScott Long
601713e81bSScott Long static int hpt_get_event(PHPT_EVENT pEvent);
611713e81bSScott Long static int hpt_set_array_state(DEVICEID idArray, DWORD state);
6249b3fc40SJohn Baldwin static void lock_driver_idle(IAL_ADAPTER_T *pAdapter);
631713e81bSScott Long static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
641713e81bSScott Long static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
651713e81bSScott Long FPSCAT_GATH pSgTable, int logical);
661713e81bSScott Long
67d2bd3ab9SScott Long static void
get_disk_location(PDevice pDev,int * controller,int * channel)68d2bd3ab9SScott Long get_disk_location(PDevice pDev, int *controller, int *channel)
691713e81bSScott Long {
701713e81bSScott Long IAL_ADAPTER_T *pAdapTemp;
711713e81bSScott Long int i, j;
721713e81bSScott Long
73b8fdb7f9SMatt Jacob *controller = *channel = 0;
74b8fdb7f9SMatt Jacob
751713e81bSScott Long for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
76b8fdb7f9SMatt Jacob for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
771713e81bSScott Long if (pDev == &pAdapTemp->VDevices[j].u.disk) {
781713e81bSScott Long *controller = i;
791713e81bSScott Long *channel = j;
801713e81bSScott Long return;
811713e81bSScott Long }
821713e81bSScott Long }
831713e81bSScott Long }
84b8fdb7f9SMatt Jacob }
851713e81bSScott Long
86d2bd3ab9SScott Long static int
event_queue_add(PHPT_EVENT pEvent)87d2bd3ab9SScott Long event_queue_add(PHPT_EVENT pEvent)
881713e81bSScott Long {
891713e81bSScott Long int p;
901713e81bSScott Long p = (event_queue_tail + 1) % MAX_EVENTS;
911713e81bSScott Long if (p==event_queue_head)
921713e81bSScott Long {
931713e81bSScott Long return -1;
941713e81bSScott Long }
951713e81bSScott Long hpt_event_queue[event_queue_tail] = *pEvent;
961713e81bSScott Long event_queue_tail = p;
971713e81bSScott Long return 0;
981713e81bSScott Long }
991713e81bSScott Long
100d2bd3ab9SScott Long static int
event_queue_remove(PHPT_EVENT pEvent)101d2bd3ab9SScott Long event_queue_remove(PHPT_EVENT pEvent)
1021713e81bSScott Long {
1031713e81bSScott Long if (event_queue_head != event_queue_tail)
1041713e81bSScott Long {
1051713e81bSScott Long *pEvent = hpt_event_queue[event_queue_head];
1061713e81bSScott Long event_queue_head++;
1071713e81bSScott Long event_queue_head %= MAX_EVENTS;
1081713e81bSScott Long return 0;
1091713e81bSScott Long }
1101713e81bSScott Long return -1;
1111713e81bSScott Long }
1121713e81bSScott Long
113d2bd3ab9SScott Long void HPTLIBAPI
ioctl_ReportEvent(UCHAR event,PVOID param)114d2bd3ab9SScott Long ioctl_ReportEvent(UCHAR event, PVOID param)
1151713e81bSScott Long {
1161713e81bSScott Long HPT_EVENT e;
1171713e81bSScott Long ZeroMemory(&e, sizeof(e));
1181713e81bSScott Long e.EventType = event;
1191713e81bSScott Long switch(event)
1201713e81bSScott Long {
1211713e81bSScott Long case ET_INITIALIZE_ABORTED:
1221713e81bSScott Long case ET_INITIALIZE_FAILED:
1231713e81bSScott Long memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
1241713e81bSScott Long case ET_INITIALIZE_STARTED:
1251713e81bSScott Long case ET_INITIALIZE_FINISHED:
1261713e81bSScott Long
1271713e81bSScott Long case ET_REBUILD_STARTED:
1281713e81bSScott Long case ET_REBUILD_ABORTED:
1291713e81bSScott Long case ET_REBUILD_FAILED:
1301713e81bSScott Long case ET_REBUILD_FINISHED:
1311713e81bSScott Long
1321713e81bSScott Long case ET_VERIFY_STARTED:
1331713e81bSScott Long case ET_VERIFY_ABORTED:
1341713e81bSScott Long case ET_VERIFY_FAILED:
1351713e81bSScott Long case ET_VERIFY_FINISHED:
1361713e81bSScott Long case ET_VERIFY_DATA_ERROR:
1371713e81bSScott Long
1381713e81bSScott Long case ET_SPARE_TOOK_OVER:
1391713e81bSScott Long case ET_DEVICE_REMOVED:
1401713e81bSScott Long case ET_DEVICE_PLUGGED:
1411713e81bSScott Long case ET_DEVICE_ERROR:
1421713e81bSScott Long e.DeviceID = VDEV_TO_ID((PVDevice)param);
1431713e81bSScott Long break;
1441713e81bSScott Long
1451713e81bSScott Long default:
1461713e81bSScott Long break;
1471713e81bSScott Long }
1481713e81bSScott Long event_queue_add(&e);
1491713e81bSScott Long if (event==ET_DEVICE_REMOVED) {
150b8fdb7f9SMatt Jacob int controller, channel;
1511713e81bSScott Long get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
1521713e81bSScott Long hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
1531713e81bSScott Long }
15449b3fc40SJohn Baldwin wakeup(param);
1551713e81bSScott Long }
1561713e81bSScott Long
157d2bd3ab9SScott Long static int
hpt_delete_array(_VBUS_ARG DEVICEID id,DWORD options)158d2bd3ab9SScott Long hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
1591713e81bSScott Long {
1601713e81bSScott Long PVDevice pArray = ID_TO_VDEV(id);
1611713e81bSScott Long BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
1621713e81bSScott Long int i;
1631713e81bSScott Long PVDevice pa;
1641713e81bSScott Long
165d2bd3ab9SScott Long if ((id==0) || check_VDevice_valid(pArray))
1661713e81bSScott Long return -1;
1671713e81bSScott Long
1681713e81bSScott Long if(!mIsArray(pArray)) return -1;
1691713e81bSScott Long
1701713e81bSScott Long if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
1711713e81bSScott Long pArray->u.array.rf_initializing)
1721713e81bSScott Long return -1;
1731713e81bSScott Long
1741713e81bSScott Long for(i=0; i<pArray->u.array.bArnMember; i++) {
1751713e81bSScott Long pa = pArray->u.array.pMember[i];
1761713e81bSScott Long if (pa && mIsArray(pa)) {
1771713e81bSScott Long if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
1781713e81bSScott Long pa->u.array.rf_initializing)
1791713e81bSScott Long return -1;
1801713e81bSScott Long }
1811713e81bSScott Long }
1821713e81bSScott Long
1831713e81bSScott Long if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
1841713e81bSScott Long fDeleteArray(_VBUS_P pArray, del_block0);
1851713e81bSScott Long return 0;
1861713e81bSScott Long
1871713e81bSScott Long }
1881713e81bSScott Long
1891713e81bSScott Long /* just to prevent driver from sending more commands */
nothing(_VBUS_ARG void * notused)1901713e81bSScott Long static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
1911713e81bSScott Long
19249b3fc40SJohn Baldwin void
lock_driver_idle(IAL_ADAPTER_T * pAdapter)193d2bd3ab9SScott Long lock_driver_idle(IAL_ADAPTER_T *pAdapter)
1941713e81bSScott Long {
1951713e81bSScott Long _VBUS_INST(&pAdapter->VBus)
19649b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
1971713e81bSScott Long while (pAdapter->outstandingCommands) {
1981713e81bSScott Long KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
1991713e81bSScott Long if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
20049b3fc40SJohn Baldwin mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
2011713e81bSScott Long }
2021713e81bSScott Long CheckIdleCall(_VBUS_P0);
2031713e81bSScott Long }
2041713e81bSScott Long
Kernel_DeviceIoControl(_VBUS_ARG DWORD dwIoControlCode,PVOID lpInBuffer,DWORD nInBufferSize,PVOID lpOutBuffer,DWORD nOutBufferSize,PDWORD lpBytesReturned)2051713e81bSScott Long int Kernel_DeviceIoControl(_VBUS_ARG
2061713e81bSScott Long DWORD dwIoControlCode, /* operation control code */
2071713e81bSScott Long PVOID lpInBuffer, /* input data buffer */
2081713e81bSScott Long DWORD nInBufferSize, /* size of input data buffer */
2091713e81bSScott Long PVOID lpOutBuffer, /* output data buffer */
2101713e81bSScott Long DWORD nOutBufferSize, /* size of output data buffer */
2111713e81bSScott Long PDWORD lpBytesReturned /* byte count */
2121713e81bSScott Long )
2131713e81bSScott Long {
2141713e81bSScott Long IAL_ADAPTER_T *pAdapter;
2151713e81bSScott Long
2161713e81bSScott Long switch(dwIoControlCode) {
2171713e81bSScott Long case HPT_IOCTL_DELETE_ARRAY:
2181713e81bSScott Long {
2191713e81bSScott Long DEVICEID idArray;
2201713e81bSScott Long int iSuccess;
2211713e81bSScott Long int i;
2221713e81bSScott Long PVDevice pArray;
2231713e81bSScott Long PVBus _vbus_p;
2241713e81bSScott Long struct cam_periph *periph = NULL;
2251713e81bSScott Long
2261713e81bSScott Long if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
2271713e81bSScott Long if (nOutBufferSize!=sizeof(int)) return -1;
2281713e81bSScott Long idArray = *(DEVICEID *)lpInBuffer;
2291713e81bSScott Long
2301713e81bSScott Long pArray = ID_TO_VDEV(idArray);
2311713e81bSScott Long
232d2bd3ab9SScott Long if((idArray == 0) || check_VDevice_valid(pArray))
2331713e81bSScott Long return -1;
2341713e81bSScott Long
2351713e81bSScott Long if(!mIsArray(pArray))
2361713e81bSScott Long return -1;
2371713e81bSScott Long
2381713e81bSScott Long _vbus_p=pArray->pVBus;
2391713e81bSScott Long pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
2401713e81bSScott Long
2411713e81bSScott Long for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
2421713e81bSScott Long if(pArray == _vbus_p->pVDevice[i])
2431713e81bSScott Long {
2441713e81bSScott Long periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
245d2bd3ab9SScott Long if (periph != NULL && periph->refcount >= 1)
2461713e81bSScott Long {
2471713e81bSScott Long hpt_printk(("Can not delete a mounted device.\n"));
2481713e81bSScott Long return -1;
2491713e81bSScott Long }
2501713e81bSScott Long }
2511713e81bSScott Long /* the Mounted Disk isn't delete */
2521713e81bSScott Long }
2531713e81bSScott Long
2541713e81bSScott Long iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
2551713e81bSScott Long
2561713e81bSScott Long *(int*)lpOutBuffer = iSuccess;
2571713e81bSScott Long
2581713e81bSScott Long if(iSuccess != 0)
2591713e81bSScott Long return -1;
2601713e81bSScott Long break;
2611713e81bSScott Long }
2621713e81bSScott Long
2631713e81bSScott Long case HPT_IOCTL_GET_EVENT:
2641713e81bSScott Long {
2651713e81bSScott Long PHPT_EVENT pInfo;
2661713e81bSScott Long
2671713e81bSScott Long if (nInBufferSize!=0) return -1;
2681713e81bSScott Long if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
2691713e81bSScott Long
2701713e81bSScott Long pInfo = (PHPT_EVENT)lpOutBuffer;
2711713e81bSScott Long
2721713e81bSScott Long if (hpt_get_event(pInfo)!=0)
2731713e81bSScott Long return -1;
2741713e81bSScott Long }
2751713e81bSScott Long break;
2761713e81bSScott Long
2771713e81bSScott Long case HPT_IOCTL_SET_ARRAY_STATE:
2781713e81bSScott Long {
2791713e81bSScott Long DEVICEID idArray;
2801713e81bSScott Long DWORD state;
2811713e81bSScott Long
2821713e81bSScott Long if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
2831713e81bSScott Long if (nOutBufferSize!=0) return -1;
2841713e81bSScott Long
2851713e81bSScott Long idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
2861713e81bSScott Long state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
2871713e81bSScott Long
2881713e81bSScott Long if(hpt_set_array_state(idArray, state)!=0)
2891713e81bSScott Long return -1;
2901713e81bSScott Long }
2911713e81bSScott Long break;
2921713e81bSScott Long
2931713e81bSScott Long case HPT_IOCTL_RESCAN_DEVICES:
2941713e81bSScott Long {
2951713e81bSScott Long if (nInBufferSize!=0) return -1;
2961713e81bSScott Long if (nOutBufferSize!=0) return -1;
2971713e81bSScott Long
2981713e81bSScott Long #ifndef FOR_DEMO
2991713e81bSScott Long /* stop buzzer if user perform rescan */
3001713e81bSScott Long for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
3011713e81bSScott Long if (pAdapter->beeping) {
3021713e81bSScott Long pAdapter->beeping = 0;
3031713e81bSScott Long BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
3041713e81bSScott Long }
3051713e81bSScott Long }
3061713e81bSScott Long #endif
3071713e81bSScott Long }
3081713e81bSScott Long break;
3091713e81bSScott Long
3101713e81bSScott Long default:
3111713e81bSScott Long {
3121713e81bSScott Long PVDevice pVDev;
31349b3fc40SJohn Baldwin
3141713e81bSScott Long switch(dwIoControlCode) {
3151713e81bSScott Long /* read-only ioctl functions can be called directly. */
3161713e81bSScott Long case HPT_IOCTL_GET_VERSION:
3171713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_IDS:
3181713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_COUNT:
3191713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_INFO:
3201713e81bSScott Long case HPT_IOCTL_GET_CHANNEL_INFO:
3211713e81bSScott Long case HPT_IOCTL_GET_LOGICAL_DEVICES:
3221713e81bSScott Long case HPT_IOCTL_GET_DEVICE_INFO:
32364470755SXin LI case HPT_IOCTL_GET_DEVICE_INFO_V2:
3241713e81bSScott Long case HPT_IOCTL_GET_EVENT:
3251713e81bSScott Long case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
3261713e81bSScott Long if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
3271713e81bSScott Long lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
3281713e81bSScott Long break;
3291713e81bSScott Long
3301713e81bSScott Long default:
3311713e81bSScott Long /*
3321713e81bSScott Long * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
3331713e81bSScott Long * wrong for second controller.
3341713e81bSScott Long */
3351713e81bSScott Long switch(dwIoControlCode) {
3361713e81bSScott Long case HPT_IOCTL_CREATE_ARRAY:
3371713e81bSScott Long pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
33864470755SXin LI case HPT_IOCTL_CREATE_ARRAY_V2:
33964470755SXin LI pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
3401713e81bSScott Long case HPT_IOCTL_SET_ARRAY_INFO:
3411713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
3421713e81bSScott Long case HPT_IOCTL_SET_DEVICE_INFO:
3431713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
34464470755SXin LI case HPT_IOCTL_SET_DEVICE_INFO_V2:
34564470755SXin LI pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
3461713e81bSScott Long case HPT_IOCTL_SET_BOOT_MARK:
3471713e81bSScott Long case HPT_IOCTL_ADD_SPARE_DISK:
3481713e81bSScott Long case HPT_IOCTL_REMOVE_SPARE_DISK:
3491713e81bSScott Long pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
3501713e81bSScott Long case HPT_IOCTL_ADD_DISK_TO_ARRAY:
3511713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
3521713e81bSScott Long default:
3531713e81bSScott Long pVDev = 0;
3541713e81bSScott Long }
3551713e81bSScott Long
3561713e81bSScott Long if (pVDev && !check_VDevice_valid(pVDev)){
3571713e81bSScott Long _vbus_p = pVDev->pVBus;
3581713e81bSScott Long
3591713e81bSScott Long pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
3601713e81bSScott Long /*
3611713e81bSScott Long * create_array, and other functions can't be executed while channel is
3621713e81bSScott Long * perform I/O commands. Wait until driver is idle.
3631713e81bSScott Long */
36449b3fc40SJohn Baldwin lock_driver_idle(pAdapter);
3651713e81bSScott Long if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
3661713e81bSScott Long lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
36749b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
3681713e81bSScott Long return -1;
3691713e81bSScott Long }
37049b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
3711713e81bSScott Long }
3721713e81bSScott Long else
3731713e81bSScott Long return -1;
3741713e81bSScott Long break;
3751713e81bSScott Long }
3761713e81bSScott Long
3771713e81bSScott Long #ifdef SUPPORT_ARRAY
3781713e81bSScott Long switch(dwIoControlCode)
3791713e81bSScott Long {
3801713e81bSScott Long case HPT_IOCTL_CREATE_ARRAY:
3811713e81bSScott Long {
3821713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
38349b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
3841713e81bSScott Long if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
3851713e81bSScott Long {
3861713e81bSScott Long (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
3871713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
3881713e81bSScott Long }
3891713e81bSScott Long else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
3901713e81bSScott Long {
3911713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
3921713e81bSScott Long }
3931713e81bSScott Long else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
3941713e81bSScott Long {
3951713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
3961713e81bSScott Long }
39749b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
3981713e81bSScott Long break;
3991713e81bSScott Long }
4001713e81bSScott Long
40164470755SXin LI
40264470755SXin LI case HPT_IOCTL_CREATE_ARRAY_V2:
40364470755SXin LI {
40464470755SXin LI pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
40549b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
40664470755SXin LI if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
40764470755SXin LI (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
40864470755SXin LI hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
40964470755SXin LI } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
41064470755SXin LI hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
41164470755SXin LI } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
41264470755SXin LI hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
41364470755SXin LI }
41449b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
41564470755SXin LI break;
41664470755SXin LI }
4171713e81bSScott Long case HPT_IOCTL_ADD_DISK_TO_ARRAY:
4181713e81bSScott Long {
4191713e81bSScott Long PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
4201713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
421d2bd3ab9SScott Long if(pArray->u.array.rf_rebuilding == 0)
4221713e81bSScott Long {
42349b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
4241713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0;
4251713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0;
4261713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
4271713e81bSScott Long while (!pArray->u.array.rf_rebuilding)
4281713e81bSScott Long {
42949b3fc40SJohn Baldwin if (mtx_sleep(pArray, &pAdapter->lock, 0, "hptwait", hz * 3) != 0)
4301713e81bSScott Long break;
4311713e81bSScott Long }
43249b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
4331713e81bSScott Long }
4341713e81bSScott Long break;
4351713e81bSScott Long }
4361713e81bSScott Long }
4371713e81bSScott Long #endif
4381713e81bSScott Long return 0;
4391713e81bSScott Long }
4401713e81bSScott Long }
4411713e81bSScott Long
4421713e81bSScott Long if (lpBytesReturned)
4431713e81bSScott Long *lpBytesReturned = nOutBufferSize;
4441713e81bSScott Long return 0;
4451713e81bSScott Long }
4461713e81bSScott Long
447d2bd3ab9SScott Long static int
hpt_get_event(PHPT_EVENT pEvent)448d2bd3ab9SScott Long hpt_get_event(PHPT_EVENT pEvent)
4491713e81bSScott Long {
4501713e81bSScott Long int ret = event_queue_remove(pEvent);
4511713e81bSScott Long return ret;
4521713e81bSScott Long }
4531713e81bSScott Long
454d2bd3ab9SScott Long static int
hpt_set_array_state(DEVICEID idArray,DWORD state)455d2bd3ab9SScott Long hpt_set_array_state(DEVICEID idArray, DWORD state)
4561713e81bSScott Long {
4571713e81bSScott Long IAL_ADAPTER_T *pAdapter;
4581713e81bSScott Long PVDevice pVDevice = ID_TO_VDEV(idArray);
4591713e81bSScott Long int i;
4601713e81bSScott Long
461d2bd3ab9SScott Long if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
4621713e81bSScott Long if(!mIsArray(pVDevice))
4631713e81bSScott Long return -1;
4641713e81bSScott Long if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
4651713e81bSScott Long
4661713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
4671713e81bSScott Long
4681713e81bSScott Long switch(state)
4691713e81bSScott Long {
4701713e81bSScott Long case MIRROR_REBUILD_START:
4711713e81bSScott Long {
47249b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
4731713e81bSScott Long if (pVDevice->u.array.rf_rebuilding ||
4741713e81bSScott Long pVDevice->u.array.rf_verifying ||
47549b3fc40SJohn Baldwin pVDevice->u.array.rf_initializing) {
47649b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
4771713e81bSScott Long return -1;
47849b3fc40SJohn Baldwin }
4791713e81bSScott Long
4801713e81bSScott Long pVDevice->u.array.rf_auto_rebuild = 0;
4811713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 0;
4821713e81bSScott Long
4831713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
4841713e81bSScott Long (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
4851713e81bSScott Long
4861713e81bSScott Long while (!pVDevice->u.array.rf_rebuilding)
4871713e81bSScott Long {
48849b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
48949b3fc40SJohn Baldwin "hptwait", hz * 20) != 0)
4901713e81bSScott Long break;
4911713e81bSScott Long }
49249b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
4931713e81bSScott Long }
4941713e81bSScott Long
4951713e81bSScott Long break;
4961713e81bSScott Long
4971713e81bSScott Long case MIRROR_REBUILD_ABORT:
4981713e81bSScott Long {
4991713e81bSScott Long for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
500d2bd3ab9SScott Long if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
5011713e81bSScott Long hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
5021713e81bSScott Long }
5031713e81bSScott Long
50449b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
50549b3fc40SJohn Baldwin if(pVDevice->u.array.rf_rebuilding != 1) {
50649b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5071713e81bSScott Long return -1;
50849b3fc40SJohn Baldwin }
5091713e81bSScott Long
5101713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1;
5111713e81bSScott Long
5121713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild)
5131713e81bSScott Long {
51449b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
51549b3fc40SJohn Baldwin "hptabrt", hz * 20) != 0)
5161713e81bSScott Long break;
5171713e81bSScott Long }
51849b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5191713e81bSScott Long }
5201713e81bSScott Long break;
5211713e81bSScott Long
5221713e81bSScott Long case AS_VERIFY_START:
5231713e81bSScott Long {
5241713e81bSScott Long /*if(pVDevice->u.array.rf_verifying)
5251713e81bSScott Long return -1;*/
52649b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
5271713e81bSScott Long if (pVDevice->u.array.rf_rebuilding ||
5281713e81bSScott Long pVDevice->u.array.rf_verifying ||
52949b3fc40SJohn Baldwin pVDevice->u.array.rf_initializing) {
53049b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5311713e81bSScott Long return -1;
53249b3fc40SJohn Baldwin }
5331713e81bSScott Long
5341713e81bSScott Long pVDevice->u.array.RebuildSectors = 0;
5351713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
5361713e81bSScott Long
5371713e81bSScott Long while (!pVDevice->u.array.rf_verifying)
5381713e81bSScott Long {
53949b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
54049b3fc40SJohn Baldwin "hptvrfy", hz * 20) != 0)
5411713e81bSScott Long break;
5421713e81bSScott Long }
54349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5441713e81bSScott Long }
5451713e81bSScott Long break;
5461713e81bSScott Long
5471713e81bSScott Long case AS_VERIFY_ABORT:
5481713e81bSScott Long {
54949b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
55049b3fc40SJohn Baldwin if(pVDevice->u.array.rf_verifying != 1) {
55149b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5521713e81bSScott Long return -1;
55349b3fc40SJohn Baldwin }
5541713e81bSScott Long
5551713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1;
5561713e81bSScott Long
5571713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild)
5581713e81bSScott Long {
55949b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
56049b3fc40SJohn Baldwin "hptvrfy", hz * 80) != 0)
5611713e81bSScott Long break;
5621713e81bSScott Long }
56349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5641713e81bSScott Long }
5651713e81bSScott Long break;
5661713e81bSScott Long
5671713e81bSScott Long case AS_INITIALIZE_START:
5681713e81bSScott Long {
56949b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
5701713e81bSScott Long if (pVDevice->u.array.rf_rebuilding ||
5711713e81bSScott Long pVDevice->u.array.rf_verifying ||
57249b3fc40SJohn Baldwin pVDevice->u.array.rf_initializing) {
57349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5741713e81bSScott Long return -1;
57549b3fc40SJohn Baldwin }
5761713e81bSScott Long
5771713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
5781713e81bSScott Long
5791713e81bSScott Long while (!pVDevice->u.array.rf_initializing)
5801713e81bSScott Long {
58149b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
58249b3fc40SJohn Baldwin "hptinit", hz * 80) != 0)
5831713e81bSScott Long break;
5841713e81bSScott Long }
58549b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5861713e81bSScott Long }
5871713e81bSScott Long break;
5881713e81bSScott Long
5891713e81bSScott Long case AS_INITIALIZE_ABORT:
5901713e81bSScott Long {
59149b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
59249b3fc40SJohn Baldwin if(pVDevice->u.array.rf_initializing != 1) {
59349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
5941713e81bSScott Long return -1;
59549b3fc40SJohn Baldwin }
5961713e81bSScott Long
5971713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1;
5981713e81bSScott Long
5991713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild)
6001713e81bSScott Long {
60149b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
60249b3fc40SJohn Baldwin "hptinit", hz * 80) != 0)
6031713e81bSScott Long break;
6041713e81bSScott Long }
60549b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
6061713e81bSScott Long }
6071713e81bSScott Long break;
6081713e81bSScott Long
6091713e81bSScott Long default:
6101713e81bSScott Long return -1;
6111713e81bSScott Long }
6121713e81bSScott Long
6131713e81bSScott Long return 0;
6141713e81bSScott Long }
6151713e81bSScott Long
616d2bd3ab9SScott Long int HPTLIBAPI
R1ControlSgl(_VBUS_ARG PCommand pCmd,FPSCAT_GATH pSgTable,int logical)617d2bd3ab9SScott Long R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
6181713e81bSScott Long {
6191713e81bSScott Long ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
6201713e81bSScott Long if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
6211713e81bSScott Long bufferSize<<=1;
6221713e81bSScott Long if (logical) {
6231713e81bSScott Long pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
6241713e81bSScott Long pSgTable->wSgSize = (USHORT)bufferSize;
6251713e81bSScott Long pSgTable->wSgFlag = SG_FLAG_EOT;
6261713e81bSScott Long }
6271713e81bSScott Long else {
6281713e81bSScott Long /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
6291713e81bSScott Long ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
6301713e81bSScott Long ULONG length;
6311713e81bSScott Long int idx = 0;
6321713e81bSScott Long
6331713e81bSScott Long v = pCmd->uCmd.R1Control.Buffer;
6341713e81bSScott Long dataPointer = (ADDRESS)fOsPhysicalAddress(v);
6351713e81bSScott Long
6361713e81bSScott Long if ((ULONG_PTR)dataPointer & 0x1)
6371713e81bSScott Long return FALSE;
6381713e81bSScott Long
6391713e81bSScott Long #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
6401713e81bSScott Long #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
6411713e81bSScott Long
6421713e81bSScott Long do {
6431713e81bSScott Long if (idx >= MAX_SG_DESCRIPTORS) return FALSE;
6441713e81bSScott Long
6451713e81bSScott Long pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
6461713e81bSScott Long currvaddr = v;
6471713e81bSScott Long currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
6481713e81bSScott Long
6491713e81bSScott Long
6501713e81bSScott Long do {
6511713e81bSScott Long nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
6521713e81bSScott Long nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
6531713e81bSScott Long
6541713e81bSScott Long if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
6551713e81bSScott Long nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
6561713e81bSScott Long
6571713e81bSScott Long if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
6581713e81bSScott Long nextvaddr = nextpage;
6591713e81bSScott Long break;
6601713e81bSScott Long }
6611713e81bSScott Long
6621713e81bSScott Long currvaddr = nextvaddr;
6631713e81bSScott Long currphypage = nextphypage;
6641713e81bSScott Long }while (1);
6651713e81bSScott Long
6661713e81bSScott Long length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
6671713e81bSScott Long v = nextvaddr;
6681713e81bSScott Long bufferSize -= length;
6691713e81bSScott Long
6701713e81bSScott Long pSgTable[idx].wSgSize = (USHORT)length;
6711713e81bSScott Long pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
6721713e81bSScott Long idx++;
6731713e81bSScott Long
6741713e81bSScott Long }while (bufferSize);
6751713e81bSScott Long }
6761713e81bSScott Long return 1;
6771713e81bSScott Long }
6781713e81bSScott Long
6791713e81bSScott Long static int End_Job=0;
680d2bd3ab9SScott Long void HPTLIBAPI
thread_io_done(_VBUS_ARG PCommand pCmd)681d2bd3ab9SScott Long thread_io_done(_VBUS_ARG PCommand pCmd)
6821713e81bSScott Long {
6831713e81bSScott Long End_Job = 1;
6841713e81bSScott Long wakeup((caddr_t)pCmd);
6851713e81bSScott Long }
6861713e81bSScott Long
687d2bd3ab9SScott Long void
hpt_rebuild_data_block(IAL_ADAPTER_T * pAdapter,PVDevice pArray,UCHAR flags)688d2bd3ab9SScott Long hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
6891713e81bSScott Long {
6901713e81bSScott Long ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
6911713e81bSScott Long PCommand pCmd;
6921713e81bSScott Long UINT result;
6931713e81bSScott Long int needsync=0, retry=0, needdelete=0;
6944d24901aSPedro F. Giffuni void *buffer = NULL;
6951713e81bSScott Long
6961713e81bSScott Long _VBUS_INST(&pAdapter->VBus)
6971713e81bSScott Long
6981713e81bSScott Long if (pArray->u.array.rf_broken==1 ||
6991713e81bSScott Long pArray->u.array.RebuildSectors>=capacity)
7001713e81bSScott Long return;
7011713e81bSScott Long
70249b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock);
7031713e81bSScott Long
7041713e81bSScott Long switch(flags)
7051713e81bSScott Long {
7061713e81bSScott Long case DUPLICATE:
7071713e81bSScott Long case REBUILD_PARITY:
7081713e81bSScott Long if(pArray->u.array.rf_rebuilding == 0)
7091713e81bSScott Long {
7101713e81bSScott Long pArray->u.array.rf_rebuilding = 1;
7111713e81bSScott Long hpt_printk(("Rebuilding started.\n"));
7121713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
7131713e81bSScott Long }
7141713e81bSScott Long break;
7151713e81bSScott Long
7161713e81bSScott Long case INITIALIZE:
7171713e81bSScott Long if(pArray->u.array.rf_initializing == 0)
7181713e81bSScott Long {
7191713e81bSScott Long pArray->u.array.rf_initializing = 1;
7201713e81bSScott Long hpt_printk(("Initializing started.\n"));
7211713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
7221713e81bSScott Long }
7231713e81bSScott Long break;
7241713e81bSScott Long
7251713e81bSScott Long case VERIFY:
7261713e81bSScott Long if(pArray->u.array.rf_verifying == 0)
7271713e81bSScott Long {
7281713e81bSScott Long pArray->u.array.rf_verifying = 1;
7291713e81bSScott Long hpt_printk(("Verifying started.\n"));
7301713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
7311713e81bSScott Long }
7321713e81bSScott Long break;
7331713e81bSScott Long }
7341713e81bSScott Long
7351713e81bSScott Long retry_cmd:
7361713e81bSScott Long pCmd = AllocateCommand(_VBUS_P0);
7371713e81bSScott Long HPT_ASSERT(pCmd);
7381713e81bSScott Long pCmd->cf_control = 1;
7391713e81bSScott Long End_Job = 0;
7401713e81bSScott Long
7411713e81bSScott Long if (pArray->VDeviceType==VD_RAID_1)
7421713e81bSScott Long {
7431713e81bSScott Long #define MAX_REBUILD_SECTORS 0x40
7441713e81bSScott Long
7451713e81bSScott Long /* take care for discontinuous buffer in R1ControlSgl */
7461713e81bSScott Long buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
7471713e81bSScott Long if(!buffer) {
7481713e81bSScott Long FreeCommand(_VBUS_P pCmd);
7491713e81bSScott Long hpt_printk(("can't allocate rebuild buffer\n"));
7501713e81bSScott Long goto fail;
7511713e81bSScott Long }
7521713e81bSScott Long switch(flags)
7531713e81bSScott Long {
7541713e81bSScott Long case DUPLICATE:
7551713e81bSScott Long pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
7561713e81bSScott Long pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
7571713e81bSScott Long break;
7581713e81bSScott Long
7591713e81bSScott Long case VERIFY:
7601713e81bSScott Long pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
7611713e81bSScott Long pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
7621713e81bSScott Long break;
7631713e81bSScott Long
7641713e81bSScott Long case INITIALIZE:
7651713e81bSScott Long pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
7661713e81bSScott Long pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
7671713e81bSScott Long break;
7681713e81bSScott Long }
7691713e81bSScott Long
7701713e81bSScott Long pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
7711713e81bSScott Long
7721713e81bSScott Long if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
7731713e81bSScott Long pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
7741713e81bSScott Long
7751713e81bSScott Long pCmd->uCmd.R1Control.Buffer = buffer;
7761713e81bSScott Long pCmd->pfnBuildSgl = R1ControlSgl;
7771713e81bSScott Long }
7781713e81bSScott Long else if (pArray->VDeviceType==VD_RAID_5)
7791713e81bSScott Long {
7801713e81bSScott Long switch(flags)
7811713e81bSScott Long {
7821713e81bSScott Long case DUPLICATE:
7831713e81bSScott Long case REBUILD_PARITY:
7841713e81bSScott Long pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
7851713e81bSScott Long case VERIFY:
7861713e81bSScott Long pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
7871713e81bSScott Long case INITIALIZE:
7881713e81bSScott Long pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
7891713e81bSScott Long }
7901713e81bSScott Long pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
7911713e81bSScott Long }
7921713e81bSScott Long else
7931713e81bSScott Long HPT_ASSERT(0);
7941713e81bSScott Long
7951713e81bSScott Long pCmd->pVDevice = pArray;
7961713e81bSScott Long pCmd->pfnCompletion = thread_io_done;
7971713e81bSScott Long pArray->pfnSendCommand(_VBUS_P pCmd);
7981713e81bSScott Long CheckPendingCall(_VBUS_P0);
7991713e81bSScott Long
8001713e81bSScott Long if (!End_Job) {
80149b3fc40SJohn Baldwin mtx_sleep(pCmd, &pAdapter->lock, 0, "hptrbld", hz * 60);
8021713e81bSScott Long if (!End_Job) {
8031713e81bSScott Long hpt_printk(("timeout, reset\n"));
8041713e81bSScott Long fResetVBus(_VBUS_P0);
8051713e81bSScott Long }
8061713e81bSScott Long }
8071713e81bSScott Long
8081713e81bSScott Long result = pCmd->Result;
8091713e81bSScott Long FreeCommand(_VBUS_P pCmd);
810d2bd3ab9SScott Long if (buffer) free(buffer, M_DEVBUF);
8111713e81bSScott Long KdPrintI(("cmd finished %d", result));
8121713e81bSScott Long
8131713e81bSScott Long switch(result)
8141713e81bSScott Long {
8151713e81bSScott Long case RETURN_SUCCESS:
8161713e81bSScott Long if (!pArray->u.array.rf_abort_rebuild)
8171713e81bSScott Long {
8181713e81bSScott Long if(pArray->u.array.RebuildSectors < capacity)
8191713e81bSScott Long {
8201713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
8211713e81bSScott Long }
8221713e81bSScott Long else
8231713e81bSScott Long {
8241713e81bSScott Long switch (flags)
8251713e81bSScott Long {
8261713e81bSScott Long case DUPLICATE:
8271713e81bSScott Long case REBUILD_PARITY:
8281713e81bSScott Long needsync = 1;
8291713e81bSScott Long pArray->u.array.rf_rebuilding = 0;
8301713e81bSScott Long pArray->u.array.rf_need_rebuild = 0;
8311713e81bSScott Long pArray->u.array.CriticalMembers = 0;
8321713e81bSScott Long pArray->u.array.RebuildSectors = MAX_LBA_T;
8331713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0;
8341713e81bSScott Long hpt_printk(("Rebuilding finished.\n"));
8351713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
8361713e81bSScott Long break;
8371713e81bSScott Long case INITIALIZE:
8381713e81bSScott Long needsync = 1;
8391713e81bSScott Long pArray->u.array.rf_initializing = 0;
8401713e81bSScott Long pArray->u.array.rf_need_rebuild = 0;
8411713e81bSScott Long pArray->u.array.RebuildSectors = MAX_LBA_T;
8421713e81bSScott Long hpt_printk(("Initializing finished.\n"));
8431713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
8441713e81bSScott Long break;
8451713e81bSScott Long case VERIFY:
8461713e81bSScott Long pArray->u.array.rf_verifying = 0;
8471713e81bSScott Long hpt_printk(("Verifying finished.\n"));
8481713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
8491713e81bSScott Long break;
8501713e81bSScott Long }
8511713e81bSScott Long }
8521713e81bSScott Long }
8531713e81bSScott Long else
8541713e81bSScott Long {
8551713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0;
8561713e81bSScott Long if (pArray->u.array.rf_rebuilding)
8571713e81bSScott Long {
8581713e81bSScott Long hpt_printk(("Abort rebuilding.\n"));
8591713e81bSScott Long pArray->u.array.rf_rebuilding = 0;
8601713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0;
8611713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
8621713e81bSScott Long }
8631713e81bSScott Long else if (pArray->u.array.rf_verifying)
8641713e81bSScott Long {
8651713e81bSScott Long hpt_printk(("Abort verifying.\n"));
8661713e81bSScott Long pArray->u.array.rf_verifying = 0;
8671713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
8681713e81bSScott Long }
8691713e81bSScott Long else if (pArray->u.array.rf_initializing)
8701713e81bSScott Long {
8711713e81bSScott Long hpt_printk(("Abort initializing.\n"));
8721713e81bSScott Long pArray->u.array.rf_initializing = 0;
8731713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
8741713e81bSScott Long }
8751713e81bSScott Long needdelete=1;
8761713e81bSScott Long }
8771713e81bSScott Long break;
8781713e81bSScott Long
8791713e81bSScott Long case RETURN_DATA_ERROR:
8801713e81bSScott Long if (flags==VERIFY)
8811713e81bSScott Long {
8821713e81bSScott Long needsync = 1;
8831713e81bSScott Long pArray->u.array.rf_verifying = 0;
8841713e81bSScott Long pArray->u.array.rf_need_rebuild = 1;
8851713e81bSScott Long hpt_printk(("Verifying failed: found inconsistency\n"));
8861713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
8871713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
8881713e81bSScott Long
8891713e81bSScott Long if (!pArray->vf_online || pArray->u.array.rf_broken) break;
8901713e81bSScott Long
8911713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0;
8921713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0;
8931713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
8941713e81bSScott Long (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
8951713e81bSScott Long }
8961713e81bSScott Long break;
8971713e81bSScott Long
8981713e81bSScott Long default:
8991713e81bSScott Long hpt_printk(("command failed with error %d\n", result));
9001713e81bSScott Long if (++retry<3)
9011713e81bSScott Long {
9021713e81bSScott Long hpt_printk(("retry (%d)\n", retry));
9031713e81bSScott Long goto retry_cmd;
9041713e81bSScott Long }
9051713e81bSScott Long fail:
9061713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0;
9071713e81bSScott Long switch (flags)
9081713e81bSScott Long {
9091713e81bSScott Long case DUPLICATE:
9101713e81bSScott Long case REBUILD_PARITY:
9111713e81bSScott Long needsync = 1;
9121713e81bSScott Long pArray->u.array.rf_rebuilding = 0;
9131713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0;
9141713e81bSScott Long hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
9151713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
9161713e81bSScott Long break;
9171713e81bSScott Long
9181713e81bSScott Long case INITIALIZE:
9191713e81bSScott Long needsync = 1;
9201713e81bSScott Long pArray->u.array.rf_initializing = 0;
9211713e81bSScott Long hpt_printk(("Initializing failed.\n"));
9221713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
9231713e81bSScott Long break;
9241713e81bSScott Long
9251713e81bSScott Long case VERIFY:
9261713e81bSScott Long needsync = 1;
9271713e81bSScott Long pArray->u.array.rf_verifying = 0;
9281713e81bSScott Long hpt_printk(("Verifying failed.\n"));
9291713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
9301713e81bSScott Long break;
9311713e81bSScott Long }
9321713e81bSScott Long needdelete=1;
9331713e81bSScott Long }
9341713e81bSScott Long
9351713e81bSScott Long while (pAdapter->outstandingCommands)
9361713e81bSScott Long {
9371713e81bSScott Long KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
9381713e81bSScott Long /* put this to have driver stop processing system commands quickly */
9391713e81bSScott Long if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
94049b3fc40SJohn Baldwin mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
9411713e81bSScott Long }
9421713e81bSScott Long
9431713e81bSScott Long if (needsync) SyncArrayInfo(pArray);
9441713e81bSScott Long if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
9451713e81bSScott Long fDeleteArray(_VBUS_P pArray, TRUE);
9461713e81bSScott Long
9471713e81bSScott Long Check_Idle_Call(pAdapter);
94849b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock);
9491713e81bSScott Long }
950