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/ioctl.c,v 1.9 2009/04/07 16:38:25 delphij Exp $
2735878b55SSascha Wildner */
2835878b55SSascha Wildner /*
2935878b55SSascha Wildner * ioctl.c ioctl interface implementation
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
3635878b55SSascha Wildner #ifndef __KERNEL__
3735878b55SSascha Wildner #define __KERNEL__
3835878b55SSascha Wildner #endif
3935878b55SSascha Wildner
4035878b55SSascha Wildner #include <dev/raid/hptmv/global.h>
4135878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h>
4235878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h>
4335878b55SSascha Wildner #include <dev/raid/hptmv/access601.h>
4435878b55SSascha Wildner
4535878b55SSascha Wildner #pragma pack(1)
4635878b55SSascha Wildner
4735878b55SSascha Wildner typedef struct _HPT_REBUILD_PARAM
4835878b55SSascha Wildner {
4935878b55SSascha Wildner DEVICEID idMirror;
5035878b55SSascha Wildner DWORD Lba;
5135878b55SSascha Wildner UCHAR nSector;
5235878b55SSascha Wildner } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
5335878b55SSascha Wildner
5435878b55SSascha Wildner #pragma pack()
5535878b55SSascha Wildner
5635878b55SSascha Wildner #define MAX_EVENTS 10
5735878b55SSascha Wildner static HPT_EVENT hpt_event_queue[MAX_EVENTS];
5835878b55SSascha Wildner static int event_queue_head=0, event_queue_tail=0;
5935878b55SSascha Wildner
6035878b55SSascha Wildner static int hpt_get_event(PHPT_EVENT pEvent);
6135878b55SSascha Wildner static int hpt_set_array_state(DEVICEID idArray, DWORD state);
62c898d682SSascha Wildner static void lock_driver_idle(IAL_ADAPTER_T *pAdapter);
6335878b55SSascha Wildner static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
6435878b55SSascha Wildner static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
6535878b55SSascha Wildner FPSCAT_GATH pSgTable, int logical);
6635878b55SSascha Wildner
6735878b55SSascha Wildner static void
get_disk_location(PDevice pDev,int * controller,int * channel)6835878b55SSascha Wildner get_disk_location(PDevice pDev, int *controller, int *channel)
6935878b55SSascha Wildner {
7035878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp;
7135878b55SSascha Wildner int i, j;
7235878b55SSascha Wildner
7335878b55SSascha Wildner *controller = *channel = 0;
7435878b55SSascha Wildner
7535878b55SSascha Wildner for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
7635878b55SSascha Wildner for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
7735878b55SSascha Wildner if (pDev == &pAdapTemp->VDevices[j].u.disk) {
7835878b55SSascha Wildner *controller = i;
7935878b55SSascha Wildner *channel = j;
8035878b55SSascha Wildner return;
8135878b55SSascha Wildner }
8235878b55SSascha Wildner }
8335878b55SSascha Wildner }
8435878b55SSascha Wildner }
8535878b55SSascha Wildner
8635878b55SSascha Wildner static int
event_queue_add(PHPT_EVENT pEvent)8735878b55SSascha Wildner event_queue_add(PHPT_EVENT pEvent)
8835878b55SSascha Wildner {
8935878b55SSascha Wildner int p;
9035878b55SSascha Wildner p = (event_queue_tail + 1) % MAX_EVENTS;
9135878b55SSascha Wildner if (p==event_queue_head)
9235878b55SSascha Wildner {
9335878b55SSascha Wildner return -1;
9435878b55SSascha Wildner }
9535878b55SSascha Wildner hpt_event_queue[event_queue_tail] = *pEvent;
9635878b55SSascha Wildner event_queue_tail = p;
9735878b55SSascha Wildner return 0;
9835878b55SSascha Wildner }
9935878b55SSascha Wildner
10035878b55SSascha Wildner static int
event_queue_remove(PHPT_EVENT pEvent)10135878b55SSascha Wildner event_queue_remove(PHPT_EVENT pEvent)
10235878b55SSascha Wildner {
10335878b55SSascha Wildner if (event_queue_head != event_queue_tail)
10435878b55SSascha Wildner {
10535878b55SSascha Wildner *pEvent = hpt_event_queue[event_queue_head];
10635878b55SSascha Wildner event_queue_head++;
10735878b55SSascha Wildner event_queue_head %= MAX_EVENTS;
10835878b55SSascha Wildner return 0;
10935878b55SSascha Wildner }
11035878b55SSascha Wildner return -1;
11135878b55SSascha Wildner }
11235878b55SSascha Wildner
11335878b55SSascha Wildner void HPTLIBAPI
ioctl_ReportEvent(UCHAR event,PVOID param)11435878b55SSascha Wildner ioctl_ReportEvent(UCHAR event, PVOID param)
11535878b55SSascha Wildner {
11635878b55SSascha Wildner HPT_EVENT e;
11735878b55SSascha Wildner ZeroMemory(&e, sizeof(e));
11835878b55SSascha Wildner e.EventType = event;
11935878b55SSascha Wildner switch(event)
12035878b55SSascha Wildner {
12135878b55SSascha Wildner case ET_INITIALIZE_ABORTED:
12235878b55SSascha Wildner case ET_INITIALIZE_FAILED:
12335878b55SSascha Wildner memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
12435878b55SSascha Wildner case ET_INITIALIZE_STARTED:
12535878b55SSascha Wildner case ET_INITIALIZE_FINISHED:
12635878b55SSascha Wildner
12735878b55SSascha Wildner case ET_REBUILD_STARTED:
12835878b55SSascha Wildner case ET_REBUILD_ABORTED:
12935878b55SSascha Wildner case ET_REBUILD_FAILED:
13035878b55SSascha Wildner case ET_REBUILD_FINISHED:
13135878b55SSascha Wildner
13235878b55SSascha Wildner case ET_VERIFY_STARTED:
13335878b55SSascha Wildner case ET_VERIFY_ABORTED:
13435878b55SSascha Wildner case ET_VERIFY_FAILED:
13535878b55SSascha Wildner case ET_VERIFY_FINISHED:
13635878b55SSascha Wildner case ET_VERIFY_DATA_ERROR:
13735878b55SSascha Wildner
13835878b55SSascha Wildner case ET_SPARE_TOOK_OVER:
13935878b55SSascha Wildner case ET_DEVICE_REMOVED:
14035878b55SSascha Wildner case ET_DEVICE_PLUGGED:
14135878b55SSascha Wildner case ET_DEVICE_ERROR:
14235878b55SSascha Wildner e.DeviceID = VDEV_TO_ID((PVDevice)param);
14335878b55SSascha Wildner break;
14435878b55SSascha Wildner
14535878b55SSascha Wildner default:
14635878b55SSascha Wildner break;
14735878b55SSascha Wildner }
14835878b55SSascha Wildner event_queue_add(&e);
14935878b55SSascha Wildner if (event==ET_DEVICE_REMOVED) {
15035878b55SSascha Wildner int controller, channel;
15135878b55SSascha Wildner get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
15235878b55SSascha Wildner hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
15335878b55SSascha Wildner }
15435878b55SSascha Wildner }
15535878b55SSascha Wildner
15635878b55SSascha Wildner static int
hpt_delete_array(_VBUS_ARG DEVICEID id,DWORD options)15735878b55SSascha Wildner hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
15835878b55SSascha Wildner {
15935878b55SSascha Wildner PVDevice pArray = ID_TO_VDEV(id);
16035878b55SSascha Wildner BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
16135878b55SSascha Wildner int i;
16235878b55SSascha Wildner PVDevice pa;
16335878b55SSascha Wildner
16435878b55SSascha Wildner if ((id==0) || check_VDevice_valid(pArray))
16535878b55SSascha Wildner return -1;
16635878b55SSascha Wildner
16735878b55SSascha Wildner if(!mIsArray(pArray)) return -1;
16835878b55SSascha Wildner
16935878b55SSascha Wildner if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
17035878b55SSascha Wildner pArray->u.array.rf_initializing)
17135878b55SSascha Wildner return -1;
17235878b55SSascha Wildner
17335878b55SSascha Wildner for(i=0; i<pArray->u.array.bArnMember; i++) {
17435878b55SSascha Wildner pa = pArray->u.array.pMember[i];
17535878b55SSascha Wildner if (pa && mIsArray(pa)) {
17635878b55SSascha Wildner if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
17735878b55SSascha Wildner pa->u.array.rf_initializing)
17835878b55SSascha Wildner return -1;
17935878b55SSascha Wildner }
18035878b55SSascha Wildner }
18135878b55SSascha Wildner
18235878b55SSascha Wildner if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
18335878b55SSascha Wildner fDeleteArray(_VBUS_P pArray, del_block0);
18435878b55SSascha Wildner return 0;
18535878b55SSascha Wildner
18635878b55SSascha Wildner }
18735878b55SSascha Wildner
18835878b55SSascha Wildner /* just to prevent driver from sending more commands */
nothing(_VBUS_ARG void * notused)18935878b55SSascha Wildner static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
19035878b55SSascha Wildner
191*8406cf70SSascha Wildner static void
lock_driver_idle(IAL_ADAPTER_T * pAdapter)19235878b55SSascha Wildner lock_driver_idle(IAL_ADAPTER_T *pAdapter)
19335878b55SSascha Wildner {
19435878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus)
195c898d682SSascha Wildner lock_driver();
19635878b55SSascha Wildner while (pAdapter->outstandingCommands) {
19735878b55SSascha Wildner KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
19835878b55SSascha Wildner if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
199c898d682SSascha Wildner unlock_driver();
20035878b55SSascha Wildner /*Schedule out*/
20135878b55SSascha Wildner tsleep(lock_driver_idle, 0, "switch", 1);
202c898d682SSascha Wildner lock_driver();
20335878b55SSascha Wildner }
20435878b55SSascha Wildner CheckIdleCall(_VBUS_P0);
20535878b55SSascha Wildner }
20635878b55SSascha Wildner
Kernel_DeviceIoControl(_VBUS_ARG DWORD dwIoControlCode,PVOID lpInBuffer,DWORD nInBufferSize,PVOID lpOutBuffer,DWORD nOutBufferSize,PDWORD lpBytesReturned)20735878b55SSascha Wildner int Kernel_DeviceIoControl(_VBUS_ARG
20835878b55SSascha Wildner DWORD dwIoControlCode, /* operation control code */
20935878b55SSascha Wildner PVOID lpInBuffer, /* input data buffer */
21035878b55SSascha Wildner DWORD nInBufferSize, /* size of input data buffer */
21135878b55SSascha Wildner PVOID lpOutBuffer, /* output data buffer */
21235878b55SSascha Wildner DWORD nOutBufferSize, /* size of output data buffer */
21335878b55SSascha Wildner PDWORD lpBytesReturned /* byte count */
21435878b55SSascha Wildner )
21535878b55SSascha Wildner {
21635878b55SSascha Wildner IAL_ADAPTER_T *pAdapter;
21735878b55SSascha Wildner
21835878b55SSascha Wildner switch(dwIoControlCode) {
21935878b55SSascha Wildner case HPT_IOCTL_DELETE_ARRAY:
22035878b55SSascha Wildner {
22135878b55SSascha Wildner DEVICEID idArray;
22235878b55SSascha Wildner int iSuccess;
22335878b55SSascha Wildner int i;
22435878b55SSascha Wildner PVDevice pArray;
22535878b55SSascha Wildner PVBus _vbus_p;
22635878b55SSascha Wildner struct cam_periph *periph = NULL;
22735878b55SSascha Wildner
22835878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
22935878b55SSascha Wildner if (nOutBufferSize!=sizeof(int)) return -1;
23035878b55SSascha Wildner idArray = *(DEVICEID *)lpInBuffer;
23135878b55SSascha Wildner
23235878b55SSascha Wildner pArray = ID_TO_VDEV(idArray);
23335878b55SSascha Wildner
23435878b55SSascha Wildner if((idArray == 0) || check_VDevice_valid(pArray))
23535878b55SSascha Wildner return -1;
23635878b55SSascha Wildner
23735878b55SSascha Wildner if(!mIsArray(pArray))
23835878b55SSascha Wildner return -1;
23935878b55SSascha Wildner
24035878b55SSascha Wildner _vbus_p=pArray->pVBus;
24135878b55SSascha Wildner pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
24235878b55SSascha Wildner
24335878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
24435878b55SSascha Wildner if(pArray == _vbus_p->pVDevice[i])
24535878b55SSascha Wildner {
24635878b55SSascha Wildner periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
24735878b55SSascha Wildner if (periph != NULL && periph->refcount >= 1)
24835878b55SSascha Wildner {
24935878b55SSascha Wildner hpt_printk(("Can not delete a mounted device.\n"));
25035878b55SSascha Wildner return -1;
25135878b55SSascha Wildner }
25235878b55SSascha Wildner }
25335878b55SSascha Wildner /* the Mounted Disk isn't delete */
25435878b55SSascha Wildner }
25535878b55SSascha Wildner
25635878b55SSascha Wildner iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
25735878b55SSascha Wildner
25835878b55SSascha Wildner *(int*)lpOutBuffer = iSuccess;
25935878b55SSascha Wildner
26035878b55SSascha Wildner if(iSuccess != 0)
26135878b55SSascha Wildner return -1;
26235878b55SSascha Wildner break;
26335878b55SSascha Wildner }
26435878b55SSascha Wildner
26535878b55SSascha Wildner case HPT_IOCTL_GET_EVENT:
26635878b55SSascha Wildner {
26735878b55SSascha Wildner PHPT_EVENT pInfo;
26835878b55SSascha Wildner
26935878b55SSascha Wildner if (nInBufferSize!=0) return -1;
27035878b55SSascha Wildner if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
27135878b55SSascha Wildner
27235878b55SSascha Wildner pInfo = (PHPT_EVENT)lpOutBuffer;
27335878b55SSascha Wildner
27435878b55SSascha Wildner if (hpt_get_event(pInfo)!=0)
27535878b55SSascha Wildner return -1;
27635878b55SSascha Wildner }
27735878b55SSascha Wildner break;
27835878b55SSascha Wildner
27935878b55SSascha Wildner case HPT_IOCTL_SET_ARRAY_STATE:
28035878b55SSascha Wildner {
28135878b55SSascha Wildner DEVICEID idArray;
28235878b55SSascha Wildner DWORD state;
28335878b55SSascha Wildner
28435878b55SSascha Wildner if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
28535878b55SSascha Wildner if (nOutBufferSize!=0) return -1;
28635878b55SSascha Wildner
28735878b55SSascha Wildner idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
28835878b55SSascha Wildner state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
28935878b55SSascha Wildner
29035878b55SSascha Wildner if(hpt_set_array_state(idArray, state)!=0)
29135878b55SSascha Wildner return -1;
29235878b55SSascha Wildner }
29335878b55SSascha Wildner break;
29435878b55SSascha Wildner
29535878b55SSascha Wildner case HPT_IOCTL_RESCAN_DEVICES:
29635878b55SSascha Wildner {
29735878b55SSascha Wildner if (nInBufferSize!=0) return -1;
29835878b55SSascha Wildner if (nOutBufferSize!=0) return -1;
29935878b55SSascha Wildner
30035878b55SSascha Wildner #ifndef FOR_DEMO
30135878b55SSascha Wildner /* stop buzzer if user perform rescan */
30235878b55SSascha Wildner for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
30335878b55SSascha Wildner if (pAdapter->beeping) {
30435878b55SSascha Wildner pAdapter->beeping = 0;
30535878b55SSascha Wildner BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
30635878b55SSascha Wildner }
30735878b55SSascha Wildner }
30835878b55SSascha Wildner #endif
30935878b55SSascha Wildner }
31035878b55SSascha Wildner break;
31135878b55SSascha Wildner
31235878b55SSascha Wildner default:
31335878b55SSascha Wildner {
31435878b55SSascha Wildner PVDevice pVDev;
31535878b55SSascha Wildner switch(dwIoControlCode) {
31635878b55SSascha Wildner /* read-only ioctl functions can be called directly. */
31735878b55SSascha Wildner case HPT_IOCTL_GET_VERSION:
31835878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_IDS:
31935878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_COUNT:
32035878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_INFO:
32135878b55SSascha Wildner case HPT_IOCTL_GET_CHANNEL_INFO:
32235878b55SSascha Wildner case HPT_IOCTL_GET_LOGICAL_DEVICES:
32335878b55SSascha Wildner case HPT_IOCTL_GET_DEVICE_INFO:
32435878b55SSascha Wildner case HPT_IOCTL_GET_DEVICE_INFO_V2:
32535878b55SSascha Wildner case HPT_IOCTL_GET_EVENT:
32635878b55SSascha Wildner case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
32735878b55SSascha Wildner if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
32835878b55SSascha Wildner lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
32935878b55SSascha Wildner break;
33035878b55SSascha Wildner
33135878b55SSascha Wildner default:
33235878b55SSascha Wildner /*
33335878b55SSascha Wildner * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
33435878b55SSascha Wildner * wrong for second controller.
33535878b55SSascha Wildner */
33635878b55SSascha Wildner switch(dwIoControlCode) {
33735878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY:
33835878b55SSascha Wildner pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
33935878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY_V2:
34035878b55SSascha Wildner pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
34135878b55SSascha Wildner case HPT_IOCTL_SET_ARRAY_INFO:
34235878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
34335878b55SSascha Wildner case HPT_IOCTL_SET_DEVICE_INFO:
34435878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
34535878b55SSascha Wildner case HPT_IOCTL_SET_DEVICE_INFO_V2:
34635878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
34735878b55SSascha Wildner case HPT_IOCTL_SET_BOOT_MARK:
34835878b55SSascha Wildner case HPT_IOCTL_ADD_SPARE_DISK:
34935878b55SSascha Wildner case HPT_IOCTL_REMOVE_SPARE_DISK:
35035878b55SSascha Wildner pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
35135878b55SSascha Wildner case HPT_IOCTL_ADD_DISK_TO_ARRAY:
35235878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
35335878b55SSascha Wildner default:
35435878b55SSascha Wildner pVDev = 0;
35535878b55SSascha Wildner }
35635878b55SSascha Wildner
35735878b55SSascha Wildner if (pVDev && !check_VDevice_valid(pVDev)){
35835878b55SSascha Wildner _vbus_p = pVDev->pVBus;
35935878b55SSascha Wildner
36035878b55SSascha Wildner pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
36135878b55SSascha Wildner /*
36235878b55SSascha Wildner * create_array, and other functions can't be executed while channel is
36335878b55SSascha Wildner * perform I/O commands. Wait until driver is idle.
36435878b55SSascha Wildner */
365c898d682SSascha Wildner lock_driver_idle(pAdapter);
36635878b55SSascha Wildner if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
36735878b55SSascha Wildner lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
368c898d682SSascha Wildner unlock_driver();
36935878b55SSascha Wildner return -1;
37035878b55SSascha Wildner }
371c898d682SSascha Wildner unlock_driver();
37235878b55SSascha Wildner }
37335878b55SSascha Wildner else
37435878b55SSascha Wildner return -1;
37535878b55SSascha Wildner break;
37635878b55SSascha Wildner }
37735878b55SSascha Wildner
37835878b55SSascha Wildner #ifdef SUPPORT_ARRAY
37935878b55SSascha Wildner switch(dwIoControlCode)
38035878b55SSascha Wildner {
38135878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY:
38235878b55SSascha Wildner {
38335878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
384c898d682SSascha Wildner lock_driver();
38535878b55SSascha Wildner if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
38635878b55SSascha Wildner {
38735878b55SSascha Wildner (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
38835878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
38935878b55SSascha Wildner }
39035878b55SSascha Wildner else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
39135878b55SSascha Wildner {
39235878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
39335878b55SSascha Wildner }
39435878b55SSascha Wildner else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
39535878b55SSascha Wildner {
39635878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
39735878b55SSascha Wildner }
398c898d682SSascha Wildner unlock_driver();
39935878b55SSascha Wildner break;
40035878b55SSascha Wildner }
40135878b55SSascha Wildner
40235878b55SSascha Wildner
40335878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY_V2:
40435878b55SSascha Wildner {
40535878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
406c898d682SSascha Wildner lock_driver();
40735878b55SSascha Wildner if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
40835878b55SSascha Wildner (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
40935878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
41035878b55SSascha Wildner } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
41135878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
41235878b55SSascha Wildner } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
41335878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
41435878b55SSascha Wildner }
415c898d682SSascha Wildner unlock_driver();
41635878b55SSascha Wildner break;
41735878b55SSascha Wildner }
41835878b55SSascha Wildner case HPT_IOCTL_ADD_DISK_TO_ARRAY:
41935878b55SSascha Wildner {
42035878b55SSascha Wildner PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
42135878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
42235878b55SSascha Wildner if(pArray->u.array.rf_rebuilding == 0)
42335878b55SSascha Wildner {
42435878b55SSascha Wildner DWORD timeout = 0;
425c898d682SSascha Wildner lock_driver();
42635878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 0;
42735878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0;
42835878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
429c898d682SSascha Wildner unlock_driver();
43035878b55SSascha Wildner while (!pArray->u.array.rf_rebuilding)
43135878b55SSascha Wildner {
43235878b55SSascha Wildner tsleep((caddr_t)Kernel_DeviceIoControl, 0, "pause", 1);
43335878b55SSascha Wildner if ( timeout >= hz*3)
43435878b55SSascha Wildner break;
43535878b55SSascha Wildner timeout ++;
43635878b55SSascha Wildner }
43735878b55SSascha Wildner }
43835878b55SSascha Wildner break;
43935878b55SSascha Wildner }
44035878b55SSascha Wildner }
44135878b55SSascha Wildner #endif
44235878b55SSascha Wildner return 0;
44335878b55SSascha Wildner }
44435878b55SSascha Wildner }
44535878b55SSascha Wildner
44635878b55SSascha Wildner if (lpBytesReturned)
44735878b55SSascha Wildner *lpBytesReturned = nOutBufferSize;
44835878b55SSascha Wildner return 0;
44935878b55SSascha Wildner }
45035878b55SSascha Wildner
45135878b55SSascha Wildner static int
hpt_get_event(PHPT_EVENT pEvent)45235878b55SSascha Wildner hpt_get_event(PHPT_EVENT pEvent)
45335878b55SSascha Wildner {
454c898d682SSascha Wildner lock_driver();
45535878b55SSascha Wildner int ret = event_queue_remove(pEvent);
456c898d682SSascha Wildner unlock_driver();
45735878b55SSascha Wildner return ret;
45835878b55SSascha Wildner }
45935878b55SSascha Wildner
46035878b55SSascha Wildner static int
hpt_set_array_state(DEVICEID idArray,DWORD state)46135878b55SSascha Wildner hpt_set_array_state(DEVICEID idArray, DWORD state)
46235878b55SSascha Wildner {
46335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter;
46435878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idArray);
46535878b55SSascha Wildner int i;
46635878b55SSascha Wildner DWORD timeout = 0;
46735878b55SSascha Wildner
46835878b55SSascha Wildner if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
46935878b55SSascha Wildner if(!mIsArray(pVDevice))
47035878b55SSascha Wildner return -1;
47135878b55SSascha Wildner if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
47235878b55SSascha Wildner
47335878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
47435878b55SSascha Wildner
47535878b55SSascha Wildner switch(state)
47635878b55SSascha Wildner {
47735878b55SSascha Wildner case MIRROR_REBUILD_START:
47835878b55SSascha Wildner {
47935878b55SSascha Wildner if (pVDevice->u.array.rf_rebuilding ||
48035878b55SSascha Wildner pVDevice->u.array.rf_verifying ||
48135878b55SSascha Wildner pVDevice->u.array.rf_initializing)
48235878b55SSascha Wildner return -1;
48335878b55SSascha Wildner
484c898d682SSascha Wildner lock_driver();
48535878b55SSascha Wildner
48635878b55SSascha Wildner pVDevice->u.array.rf_auto_rebuild = 0;
48735878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 0;
48835878b55SSascha Wildner
48935878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
49035878b55SSascha Wildner (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
49135878b55SSascha Wildner
492c898d682SSascha Wildner unlock_driver();
49335878b55SSascha Wildner
49435878b55SSascha Wildner while (!pVDevice->u.array.rf_rebuilding)
49535878b55SSascha Wildner {
49635878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
49735878b55SSascha Wildner if ( timeout >= hz*20)
49835878b55SSascha Wildner break;
49935878b55SSascha Wildner timeout ++;
50035878b55SSascha Wildner }
50135878b55SSascha Wildner }
50235878b55SSascha Wildner
50335878b55SSascha Wildner break;
50435878b55SSascha Wildner
50535878b55SSascha Wildner case MIRROR_REBUILD_ABORT:
50635878b55SSascha Wildner {
50735878b55SSascha Wildner for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
50835878b55SSascha Wildner if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
50935878b55SSascha Wildner hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
51035878b55SSascha Wildner }
51135878b55SSascha Wildner
51235878b55SSascha Wildner if(pVDevice->u.array.rf_rebuilding != 1)
51335878b55SSascha Wildner return -1;
51435878b55SSascha Wildner
515c898d682SSascha Wildner lock_driver();
51635878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 1;
517c898d682SSascha Wildner unlock_driver();
51835878b55SSascha Wildner
51935878b55SSascha Wildner while (pVDevice->u.array.rf_abort_rebuild)
52035878b55SSascha Wildner {
52135878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
52235878b55SSascha Wildner if ( timeout >= hz*20)
52335878b55SSascha Wildner break;
52435878b55SSascha Wildner timeout ++;
52535878b55SSascha Wildner }
52635878b55SSascha Wildner }
52735878b55SSascha Wildner break;
52835878b55SSascha Wildner
52935878b55SSascha Wildner case AS_VERIFY_START:
53035878b55SSascha Wildner {
53135878b55SSascha Wildner /*if(pVDevice->u.array.rf_verifying)
53235878b55SSascha Wildner return -1;*/
53335878b55SSascha Wildner if (pVDevice->u.array.rf_rebuilding ||
53435878b55SSascha Wildner pVDevice->u.array.rf_verifying ||
53535878b55SSascha Wildner pVDevice->u.array.rf_initializing)
53635878b55SSascha Wildner return -1;
53735878b55SSascha Wildner
538c898d682SSascha Wildner lock_driver();
53935878b55SSascha Wildner pVDevice->u.array.RebuildSectors = 0;
54035878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
541c898d682SSascha Wildner unlock_driver();
54235878b55SSascha Wildner
54335878b55SSascha Wildner while (!pVDevice->u.array.rf_verifying)
54435878b55SSascha Wildner {
54535878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
54635878b55SSascha Wildner if ( timeout >= hz*20)
54735878b55SSascha Wildner break;
54835878b55SSascha Wildner timeout ++;
54935878b55SSascha Wildner }
55035878b55SSascha Wildner }
55135878b55SSascha Wildner break;
55235878b55SSascha Wildner
55335878b55SSascha Wildner case AS_VERIFY_ABORT:
55435878b55SSascha Wildner {
55535878b55SSascha Wildner if(pVDevice->u.array.rf_verifying != 1)
55635878b55SSascha Wildner return -1;
55735878b55SSascha Wildner
558c898d682SSascha Wildner lock_driver();
55935878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 1;
560c898d682SSascha Wildner unlock_driver();
56135878b55SSascha Wildner
56235878b55SSascha Wildner while (pVDevice->u.array.rf_abort_rebuild)
56335878b55SSascha Wildner {
56435878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
56535878b55SSascha Wildner if ( timeout >= hz*80)
56635878b55SSascha Wildner break;
56735878b55SSascha Wildner timeout ++;
56835878b55SSascha Wildner }
56935878b55SSascha Wildner }
57035878b55SSascha Wildner break;
57135878b55SSascha Wildner
57235878b55SSascha Wildner case AS_INITIALIZE_START:
57335878b55SSascha Wildner {
57435878b55SSascha Wildner if (pVDevice->u.array.rf_rebuilding ||
57535878b55SSascha Wildner pVDevice->u.array.rf_verifying ||
57635878b55SSascha Wildner pVDevice->u.array.rf_initializing)
57735878b55SSascha Wildner return -1;
57835878b55SSascha Wildner
579c898d682SSascha Wildner lock_driver();
58035878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
581c898d682SSascha Wildner unlock_driver();
58235878b55SSascha Wildner
58335878b55SSascha Wildner while (!pVDevice->u.array.rf_initializing)
58435878b55SSascha Wildner {
58535878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
58635878b55SSascha Wildner if ( timeout >= hz*80)
58735878b55SSascha Wildner break;
58835878b55SSascha Wildner timeout ++;
58935878b55SSascha Wildner }
59035878b55SSascha Wildner }
59135878b55SSascha Wildner break;
59235878b55SSascha Wildner
59335878b55SSascha Wildner case AS_INITIALIZE_ABORT:
59435878b55SSascha Wildner {
59535878b55SSascha Wildner if(pVDevice->u.array.rf_initializing != 1)
59635878b55SSascha Wildner return -1;
59735878b55SSascha Wildner
598c898d682SSascha Wildner lock_driver();
59935878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 1;
600c898d682SSascha Wildner unlock_driver();
60135878b55SSascha Wildner
60235878b55SSascha Wildner while (pVDevice->u.array.rf_abort_rebuild)
60335878b55SSascha Wildner {
60435878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
60535878b55SSascha Wildner if ( timeout >= hz*80)
60635878b55SSascha Wildner break;
60735878b55SSascha Wildner timeout ++;
60835878b55SSascha Wildner }
60935878b55SSascha Wildner }
61035878b55SSascha Wildner break;
61135878b55SSascha Wildner
61235878b55SSascha Wildner default:
61335878b55SSascha Wildner return -1;
61435878b55SSascha Wildner }
61535878b55SSascha Wildner
61635878b55SSascha Wildner return 0;
61735878b55SSascha Wildner }
61835878b55SSascha Wildner
619*8406cf70SSascha Wildner static int HPTLIBAPI
R1ControlSgl(_VBUS_ARG PCommand pCmd,FPSCAT_GATH pSgTable,int logical)62035878b55SSascha Wildner R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
62135878b55SSascha Wildner {
62235878b55SSascha Wildner ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
62335878b55SSascha Wildner if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
62435878b55SSascha Wildner bufferSize<<=1;
62535878b55SSascha Wildner if (logical) {
62635878b55SSascha Wildner pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
62735878b55SSascha Wildner pSgTable->wSgSize = (USHORT)bufferSize;
62835878b55SSascha Wildner pSgTable->wSgFlag = SG_FLAG_EOT;
62935878b55SSascha Wildner }
63035878b55SSascha Wildner else {
63135878b55SSascha Wildner /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
63235878b55SSascha Wildner ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
63335878b55SSascha Wildner ULONG length;
63435878b55SSascha Wildner int idx = 0;
63535878b55SSascha Wildner
63635878b55SSascha Wildner v = pCmd->uCmd.R1Control.Buffer;
63735878b55SSascha Wildner dataPointer = (ADDRESS)fOsPhysicalAddress(v);
63835878b55SSascha Wildner
63935878b55SSascha Wildner if ((ULONG_PTR)dataPointer & 0x1)
64035878b55SSascha Wildner return FALSE;
64135878b55SSascha Wildner
64235878b55SSascha Wildner #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
64335878b55SSascha Wildner #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
64435878b55SSascha Wildner
64535878b55SSascha Wildner do {
64635878b55SSascha Wildner if (idx >= MAX_SG_DESCRIPTORS) return FALSE;
64735878b55SSascha Wildner
64835878b55SSascha Wildner pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
64935878b55SSascha Wildner currvaddr = v;
65035878b55SSascha Wildner currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
65135878b55SSascha Wildner
65235878b55SSascha Wildner
65335878b55SSascha Wildner do {
65435878b55SSascha Wildner nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
65535878b55SSascha Wildner nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
65635878b55SSascha Wildner
65735878b55SSascha Wildner if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
65835878b55SSascha Wildner nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
65935878b55SSascha Wildner
66035878b55SSascha Wildner if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
66135878b55SSascha Wildner nextvaddr = nextpage;
66235878b55SSascha Wildner break;
66335878b55SSascha Wildner }
66435878b55SSascha Wildner
66535878b55SSascha Wildner currvaddr = nextvaddr;
66635878b55SSascha Wildner currphypage = nextphypage;
66735878b55SSascha Wildner }while (1);
66835878b55SSascha Wildner
66935878b55SSascha Wildner length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
67035878b55SSascha Wildner v = nextvaddr;
67135878b55SSascha Wildner bufferSize -= length;
67235878b55SSascha Wildner
67335878b55SSascha Wildner pSgTable[idx].wSgSize = (USHORT)length;
67435878b55SSascha Wildner pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
67535878b55SSascha Wildner idx++;
67635878b55SSascha Wildner
67735878b55SSascha Wildner }while (bufferSize);
67835878b55SSascha Wildner }
67935878b55SSascha Wildner return 1;
68035878b55SSascha Wildner }
68135878b55SSascha Wildner
68235878b55SSascha Wildner static int End_Job=0;
683*8406cf70SSascha Wildner static void HPTLIBAPI
thread_io_done(_VBUS_ARG PCommand pCmd)68435878b55SSascha Wildner thread_io_done(_VBUS_ARG PCommand pCmd)
68535878b55SSascha Wildner {
68635878b55SSascha Wildner End_Job = 1;
68735878b55SSascha Wildner wakeup((caddr_t)pCmd);
68835878b55SSascha Wildner }
68935878b55SSascha Wildner
69035878b55SSascha Wildner void
hpt_rebuild_data_block(IAL_ADAPTER_T * pAdapter,PVDevice pArray,UCHAR flags)69135878b55SSascha Wildner hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
69235878b55SSascha Wildner {
69335878b55SSascha Wildner DWORD timeout = 0;
69435878b55SSascha Wildner ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
69535878b55SSascha Wildner PCommand pCmd;
69635878b55SSascha Wildner UINT result;
69735878b55SSascha Wildner int needsync=0, retry=0, needdelete=0;
6984090d6ffSSascha Wildner void *buffer = NULL;
69935878b55SSascha Wildner
70035878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus)
70135878b55SSascha Wildner
70235878b55SSascha Wildner if (pArray->u.array.rf_broken==1 ||
70335878b55SSascha Wildner pArray->u.array.RebuildSectors>=capacity)
70435878b55SSascha Wildner return;
70535878b55SSascha Wildner
706c898d682SSascha Wildner lock_driver();
70735878b55SSascha Wildner
70835878b55SSascha Wildner switch(flags)
70935878b55SSascha Wildner {
71035878b55SSascha Wildner case DUPLICATE:
71135878b55SSascha Wildner case REBUILD_PARITY:
71235878b55SSascha Wildner if(pArray->u.array.rf_rebuilding == 0)
71335878b55SSascha Wildner {
71435878b55SSascha Wildner pArray->u.array.rf_rebuilding = 1;
71535878b55SSascha Wildner hpt_printk(("Rebuilding started.\n"));
71635878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
71735878b55SSascha Wildner }
71835878b55SSascha Wildner break;
71935878b55SSascha Wildner
72035878b55SSascha Wildner case INITIALIZE:
72135878b55SSascha Wildner if(pArray->u.array.rf_initializing == 0)
72235878b55SSascha Wildner {
72335878b55SSascha Wildner pArray->u.array.rf_initializing = 1;
72435878b55SSascha Wildner hpt_printk(("Initializing started.\n"));
72535878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
72635878b55SSascha Wildner }
72735878b55SSascha Wildner break;
72835878b55SSascha Wildner
72935878b55SSascha Wildner case VERIFY:
73035878b55SSascha Wildner if(pArray->u.array.rf_verifying == 0)
73135878b55SSascha Wildner {
73235878b55SSascha Wildner pArray->u.array.rf_verifying = 1;
73335878b55SSascha Wildner hpt_printk(("Verifying started.\n"));
73435878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
73535878b55SSascha Wildner }
73635878b55SSascha Wildner break;
73735878b55SSascha Wildner }
73835878b55SSascha Wildner
73935878b55SSascha Wildner retry_cmd:
74035878b55SSascha Wildner pCmd = AllocateCommand(_VBUS_P0);
74135878b55SSascha Wildner HPT_ASSERT(pCmd);
74235878b55SSascha Wildner pCmd->cf_control = 1;
74335878b55SSascha Wildner End_Job = 0;
74435878b55SSascha Wildner
74535878b55SSascha Wildner if (pArray->VDeviceType==VD_RAID_1)
74635878b55SSascha Wildner {
74735878b55SSascha Wildner #define MAX_REBUILD_SECTORS 0x40
74835878b55SSascha Wildner
74935878b55SSascha Wildner /* take care for discontinuous buffer in R1ControlSgl */
750c898d682SSascha Wildner unlock_driver();
75135878b55SSascha Wildner buffer = kmalloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
752c898d682SSascha Wildner lock_driver();
75335878b55SSascha Wildner if(!buffer) {
75435878b55SSascha Wildner FreeCommand(_VBUS_P pCmd);
75535878b55SSascha Wildner hpt_printk(("can't allocate rebuild buffer\n"));
75635878b55SSascha Wildner goto fail;
75735878b55SSascha Wildner }
75835878b55SSascha Wildner switch(flags)
75935878b55SSascha Wildner {
76035878b55SSascha Wildner case DUPLICATE:
76135878b55SSascha Wildner pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
76235878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
76335878b55SSascha Wildner break;
76435878b55SSascha Wildner
76535878b55SSascha Wildner case VERIFY:
76635878b55SSascha Wildner pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
76735878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
76835878b55SSascha Wildner break;
76935878b55SSascha Wildner
77035878b55SSascha Wildner case INITIALIZE:
77135878b55SSascha Wildner pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
77235878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
77335878b55SSascha Wildner break;
77435878b55SSascha Wildner }
77535878b55SSascha Wildner
77635878b55SSascha Wildner pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
77735878b55SSascha Wildner
77835878b55SSascha Wildner if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
77935878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
78035878b55SSascha Wildner
78135878b55SSascha Wildner pCmd->uCmd.R1Control.Buffer = buffer;
78235878b55SSascha Wildner pCmd->pfnBuildSgl = R1ControlSgl;
78335878b55SSascha Wildner }
78435878b55SSascha Wildner else if (pArray->VDeviceType==VD_RAID_5)
78535878b55SSascha Wildner {
78635878b55SSascha Wildner switch(flags)
78735878b55SSascha Wildner {
78835878b55SSascha Wildner case DUPLICATE:
78935878b55SSascha Wildner case REBUILD_PARITY:
79035878b55SSascha Wildner pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
79135878b55SSascha Wildner case VERIFY:
79235878b55SSascha Wildner pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
79335878b55SSascha Wildner case INITIALIZE:
79435878b55SSascha Wildner pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
79535878b55SSascha Wildner }
79635878b55SSascha Wildner pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
79735878b55SSascha Wildner }
79835878b55SSascha Wildner else
79935878b55SSascha Wildner HPT_ASSERT(0);
80035878b55SSascha Wildner
80135878b55SSascha Wildner pCmd->pVDevice = pArray;
80235878b55SSascha Wildner pCmd->pfnCompletion = thread_io_done;
80335878b55SSascha Wildner pArray->pfnSendCommand(_VBUS_P pCmd);
80435878b55SSascha Wildner CheckPendingCall(_VBUS_P0);
80535878b55SSascha Wildner
80635878b55SSascha Wildner if (!End_Job) {
807c898d682SSascha Wildner unlock_driver();
80835878b55SSascha Wildner while (!End_Job) {
80935878b55SSascha Wildner tsleep((caddr_t)pCmd, 0, "pause", hz);
81035878b55SSascha Wildner if (timeout++>60) break;
81135878b55SSascha Wildner }
812c898d682SSascha Wildner lock_driver();
81335878b55SSascha Wildner if (!End_Job) {
81435878b55SSascha Wildner hpt_printk(("timeout, reset\n"));
81535878b55SSascha Wildner fResetVBus(_VBUS_P0);
81635878b55SSascha Wildner }
81735878b55SSascha Wildner }
81835878b55SSascha Wildner
81935878b55SSascha Wildner result = pCmd->Result;
82035878b55SSascha Wildner FreeCommand(_VBUS_P pCmd);
821c898d682SSascha Wildner unlock_driver();
82235878b55SSascha Wildner if (buffer) kfree(buffer, M_DEVBUF);
823c898d682SSascha Wildner lock_driver();
82435878b55SSascha Wildner KdPrintI(("cmd finished %d", result));
82535878b55SSascha Wildner
82635878b55SSascha Wildner switch(result)
82735878b55SSascha Wildner {
82835878b55SSascha Wildner case RETURN_SUCCESS:
82935878b55SSascha Wildner if (!pArray->u.array.rf_abort_rebuild)
83035878b55SSascha Wildner {
83135878b55SSascha Wildner if(pArray->u.array.RebuildSectors < capacity)
83235878b55SSascha Wildner {
83335878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
83435878b55SSascha Wildner }
83535878b55SSascha Wildner else
83635878b55SSascha Wildner {
83735878b55SSascha Wildner switch (flags)
83835878b55SSascha Wildner {
83935878b55SSascha Wildner case DUPLICATE:
84035878b55SSascha Wildner case REBUILD_PARITY:
84135878b55SSascha Wildner needsync = 1;
84235878b55SSascha Wildner pArray->u.array.rf_rebuilding = 0;
84335878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 0;
84435878b55SSascha Wildner pArray->u.array.CriticalMembers = 0;
84535878b55SSascha Wildner pArray->u.array.RebuildSectors = MAX_LBA_T;
84635878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 0;
84735878b55SSascha Wildner hpt_printk(("Rebuilding finished.\n"));
84835878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
84935878b55SSascha Wildner break;
85035878b55SSascha Wildner case INITIALIZE:
85135878b55SSascha Wildner needsync = 1;
85235878b55SSascha Wildner pArray->u.array.rf_initializing = 0;
85335878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 0;
85435878b55SSascha Wildner pArray->u.array.RebuildSectors = MAX_LBA_T;
85535878b55SSascha Wildner hpt_printk(("Initializing finished.\n"));
85635878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
85735878b55SSascha Wildner break;
85835878b55SSascha Wildner case VERIFY:
85935878b55SSascha Wildner pArray->u.array.rf_verifying = 0;
86035878b55SSascha Wildner hpt_printk(("Verifying finished.\n"));
86135878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
86235878b55SSascha Wildner break;
86335878b55SSascha Wildner }
86435878b55SSascha Wildner }
86535878b55SSascha Wildner }
86635878b55SSascha Wildner else
86735878b55SSascha Wildner {
86835878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0;
86935878b55SSascha Wildner if (pArray->u.array.rf_rebuilding)
87035878b55SSascha Wildner {
87135878b55SSascha Wildner hpt_printk(("Abort rebuilding.\n"));
87235878b55SSascha Wildner pArray->u.array.rf_rebuilding = 0;
87335878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 0;
87435878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
87535878b55SSascha Wildner }
87635878b55SSascha Wildner else if (pArray->u.array.rf_verifying)
87735878b55SSascha Wildner {
87835878b55SSascha Wildner hpt_printk(("Abort verifying.\n"));
87935878b55SSascha Wildner pArray->u.array.rf_verifying = 0;
88035878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
88135878b55SSascha Wildner }
88235878b55SSascha Wildner else if (pArray->u.array.rf_initializing)
88335878b55SSascha Wildner {
88435878b55SSascha Wildner hpt_printk(("Abort initializing.\n"));
88535878b55SSascha Wildner pArray->u.array.rf_initializing = 0;
88635878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
88735878b55SSascha Wildner }
88835878b55SSascha Wildner needdelete=1;
88935878b55SSascha Wildner }
89035878b55SSascha Wildner break;
89135878b55SSascha Wildner
89235878b55SSascha Wildner case RETURN_DATA_ERROR:
89335878b55SSascha Wildner if (flags==VERIFY)
89435878b55SSascha Wildner {
89535878b55SSascha Wildner needsync = 1;
89635878b55SSascha Wildner pArray->u.array.rf_verifying = 0;
89735878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 1;
89835878b55SSascha Wildner hpt_printk(("Verifying failed: found inconsistency\n"));
89935878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
90035878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
90135878b55SSascha Wildner
90235878b55SSascha Wildner if (!pArray->vf_online || pArray->u.array.rf_broken) break;
90335878b55SSascha Wildner
90435878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 0;
90535878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0;
90635878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
90735878b55SSascha Wildner (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
90835878b55SSascha Wildner }
90935878b55SSascha Wildner break;
91035878b55SSascha Wildner
91135878b55SSascha Wildner default:
91235878b55SSascha Wildner hpt_printk(("command failed with error %d\n", result));
91335878b55SSascha Wildner if (++retry<3)
91435878b55SSascha Wildner {
91535878b55SSascha Wildner hpt_printk(("retry (%d)\n", retry));
91635878b55SSascha Wildner goto retry_cmd;
91735878b55SSascha Wildner }
91835878b55SSascha Wildner fail:
91935878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0;
92035878b55SSascha Wildner switch (flags)
92135878b55SSascha Wildner {
92235878b55SSascha Wildner case DUPLICATE:
92335878b55SSascha Wildner case REBUILD_PARITY:
92435878b55SSascha Wildner needsync = 1;
92535878b55SSascha Wildner pArray->u.array.rf_rebuilding = 0;
92635878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 0;
92735878b55SSascha Wildner hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
92835878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
92935878b55SSascha Wildner break;
93035878b55SSascha Wildner
93135878b55SSascha Wildner case INITIALIZE:
93235878b55SSascha Wildner needsync = 1;
93335878b55SSascha Wildner pArray->u.array.rf_initializing = 0;
93435878b55SSascha Wildner hpt_printk(("Initializing failed.\n"));
93535878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
93635878b55SSascha Wildner break;
93735878b55SSascha Wildner
93835878b55SSascha Wildner case VERIFY:
93935878b55SSascha Wildner needsync = 1;
94035878b55SSascha Wildner pArray->u.array.rf_verifying = 0;
94135878b55SSascha Wildner hpt_printk(("Verifying failed.\n"));
94235878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
94335878b55SSascha Wildner break;
94435878b55SSascha Wildner }
94535878b55SSascha Wildner needdelete=1;
94635878b55SSascha Wildner }
94735878b55SSascha Wildner
94835878b55SSascha Wildner while (pAdapter->outstandingCommands)
94935878b55SSascha Wildner {
95035878b55SSascha Wildner KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
95135878b55SSascha Wildner /* put this to have driver stop processing system commands quickly */
95235878b55SSascha Wildner if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
953c898d682SSascha Wildner unlock_driver();
95435878b55SSascha Wildner /*Schedule out*/
95535878b55SSascha Wildner tsleep(hpt_rebuild_data_block, 0, "switch", 1);
956c898d682SSascha Wildner lock_driver();
95735878b55SSascha Wildner }
95835878b55SSascha Wildner
95935878b55SSascha Wildner if (needsync) SyncArrayInfo(pArray);
96035878b55SSascha Wildner if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
96135878b55SSascha Wildner fDeleteArray(_VBUS_P pArray, TRUE);
96235878b55SSascha Wildner
96335878b55SSascha Wildner Check_Idle_Call(pAdapter);
964c898d682SSascha Wildner unlock_driver();
96535878b55SSascha Wildner }
966