xref: /freebsd/sys/dev/hptmv/gui_lib.c (revision 0050289464fa56ec79e060b8d8378b9ff7145a0e)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /*
29  * gui_lib.c
30  * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved.
31  *
32  *  Platform independent ioctl interface implementation.
33  *  The platform dependent part may reuse this function and/or use it own
34  *  implementation for each ioctl function.
35  *
36  *  This implementation doesn't use any synchronization; the caller must
37  *  assure the proper context when calling these functions.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 
45 #ifndef __KERNEL__
46 #define __KERNEL__
47 #endif
48 
49 #include <dev/hptmv/global.h>
50 #include <dev/hptmv/hptintf.h>
51 #include <dev/hptmv/osbsd.h>
52 #include <dev/hptmv/access601.h>
53 
54 static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap);
55 static int hpt_get_controller_count(void);
56 static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
57 static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
58 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
59 static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
60 static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo);
61 static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
62 static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam);
63 static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
64 static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
65 static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
66 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
67 static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo);
68 
69 int
check_VDevice_valid(PVDevice p)70 check_VDevice_valid(PVDevice p)
71 {
72 	int i;
73 	PVDevice pVDevice;
74 	PVBus    _vbus_p;
75 	IAL_ADAPTER_T *pAdapter = gIal_Adapter;
76 
77 	while(pAdapter != NULL)
78 	{
79 		for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
80 			if(&(pAdapter->VDevices[i]) == p)  return 0;
81 		pAdapter = pAdapter->next;
82 	}
83 
84 #ifdef SUPPORT_ARRAY
85 	pAdapter = gIal_Adapter;
86 	while(pAdapter != NULL)
87 	{
88 		_vbus_p = &pAdapter->VBus;
89 		for (i = 0; i<MAX_ARRAY_PER_VBUS; i++) {
90 			pVDevice=ArrayTables(i);
91 			if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
92 				return 0;
93 		}
94 		pAdapter = pAdapter->next;
95 	}
96 #endif
97 
98 	return -1;
99 }
100 
101 #ifdef SUPPORT_ARRAY
102 
get_vdev_type(PVDevice pVDevice)103 static UCHAR get_vdev_type(PVDevice pVDevice)
104 	{
105 	switch (pVDevice->VDeviceType) {
106 		case VD_RAID_0: return AT_RAID0;
107 		case VD_RAID_1: return AT_RAID1;
108 		case VD_JBOD:   return AT_JBOD;
109 		case VD_RAID_5: return AT_RAID5;
110 		default:        return AT_UNKNOWN;
111 	}
112 	}
113 
get_array_flag(PVDevice pVDevice)114 static DWORD get_array_flag(PVDevice pVDevice)
115 {
116 	int i;
117 	DWORD f = 0;
118 
119 	/* The array is disabled */
120 	if(!pVDevice->vf_online)	{
121 		f |= ARRAY_FLAG_DISABLED;
122 		/* Ignore other info */
123 		return f;
124 	}
125 
126 	/* array need synchronizing */
127 	if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
128 		f |= ARRAY_FLAG_NEEDBUILDING;
129 
130 	/* array is in rebuilding process */
131 	if(pVDevice->u.array.rf_rebuilding)
132 		f |= ARRAY_FLAG_REBUILDING;
133 
134 	/* array is being verified */
135 	if(pVDevice->u.array.rf_verifying)
136 		f |= ARRAY_FLAG_VERIFYING;
137 
138 	/* array is being initialized */
139 	if(pVDevice->u.array.rf_initializing)
140 		f |= ARRAY_FLAG_INITIALIZING;
141 
142 	/* broken but may still working */
143 	if(pVDevice->u.array.rf_broken)
144 		f |= ARRAY_FLAG_BROKEN;
145 
146 	/* array has a active partition */
147 	if(pVDevice->vf_bootable)
148 		f |= ARRAY_FLAG_BOOTDISK;
149 
150 	/* a newly created array */
151 	if(pVDevice->u.array.rf_newly_created)
152 		f |= ARRAY_FLAG_NEWLY_CREATED;
153 
154 	/* array has boot mark set */
155 	if(pVDevice->vf_bootmark)
156 		f |= ARRAY_FLAG_BOOTMARK;
157 
158 	/* auto-rebuild should start */
159 	if(pVDevice->u.array.rf_auto_rebuild)
160 		f |= ARRAY_FLAG_NEED_AUTOREBUILD;
161 
162 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
163 	{
164 		PVDevice pMember = pVDevice->u.array.pMember[i];
165 		if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
166 			continue;
167 
168 		/* array need synchronizing */
169 		if(pMember->u.array.rf_need_rebuild &&
170 		   !pMember->u.array.rf_duplicate_and_create)
171 			f |= ARRAY_FLAG_NEEDBUILDING;
172 
173 		/* array is in rebuilding process */
174 		if(pMember->u.array.rf_rebuilding)
175 			f |= ARRAY_FLAG_REBUILDING;
176 
177 		/* array is being verified */
178 		if(pMember->u.array.rf_verifying)
179 			f |= ARRAY_FLAG_VERIFYING;
180 
181 		/* array is being initialized */
182 		if(pMember->u.array.rf_initializing)
183 			f |= ARRAY_FLAG_INITIALIZING;
184 
185 		/* broken but may still working */
186 		if(pMember->u.array.rf_broken)
187 			f |= ARRAY_FLAG_BROKEN;
188 
189 		/* a newly created array */
190 		if(pMember->u.array.rf_newly_created)
191 			f |= ARRAY_FLAG_NEWLY_CREATED;
192 
193 		/* auto-rebuild should start */
194 		if(pMember->u.array.rf_auto_rebuild)
195 			f |= ARRAY_FLAG_NEED_AUTOREBUILD;
196 	}
197 
198 	return f;
199 }
200 
calc_rebuild_progress(PVDevice pVDevice)201 static DWORD calc_rebuild_progress(PVDevice pVDevice)
202 {
203 	int i;
204 	DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 /
205 		(ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
206 
207 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
208 	{
209 		PVDevice pMember = pVDevice->u.array.pMember[i];
210 		if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
211 			continue;
212 
213 		/* for RAID1/0 case */
214 		if (pMember->u.array.rf_rebuilding ||
215 			pMember->u.array.rf_verifying ||
216 			pMember->u.array.rf_initializing)
217 		{
218 			DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 /
219 				(ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
220 			if (result==0 || result>percent)
221 				result = percent;
222 		}
223 		}
224 
225 	if (result>10000) result = 10000;
226 	return result;
227 	}
228 
get_array_info(PVDevice pVDevice,PHPT_ARRAY_INFO pArrayInfo)229 static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo)
230 {
231 	int	i;
232 
233 	memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
234 	pArrayInfo->ArrayType = get_vdev_type(pVDevice);
235 	pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
236 	pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors;
237 	pArrayInfo->Flags = get_array_flag(pVDevice);
238 	pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
239 
240 	pArrayInfo->nDisk = 0;
241 
242 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
243 		if(pVDevice->u.array.pMember[i] != NULL)
244 			pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
245 
246 	for (i = pArrayInfo->nDisk; i < MAX_ARRAY_MEMBERS; i++)
247 		pArrayInfo->Members[i] = INVALID_DEVICEID;
248 }
249 
get_array_info_v2(PVDevice pVDevice,PHPT_ARRAY_INFO_V2 pArrayInfo)250 static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
251 {
252 	int	i;
253 
254 	memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN);
255 	pArrayInfo->ArrayType = get_vdev_type(pVDevice);
256 	pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
257 	pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors;
258 	pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0;
259 	pArrayInfo->Flags = get_array_flag(pVDevice);
260 	pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
261 
262 	pArrayInfo->nDisk = 0;
263 
264 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
265 		if(pVDevice->u.array.pMember[i] != NULL)
266 			pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
267 
268 	for (i = pArrayInfo->nDisk; i < MAX_ARRAY_MEMBERS_V2; i++)
269 		pArrayInfo->Members[i] = INVALID_DEVICEID;
270 }
271 #endif
272 
get_disk_info(PVDevice pVDevice,PDEVICE_INFO pDiskInfo)273 static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo)
274 {
275 	MV_SATA_ADAPTER *pSataAdapter;
276 	MV_SATA_CHANNEL *pSataChannel;
277 	IAL_ADAPTER_T   *pAdapter;
278 	MV_CHANNEL		*channelInfo;
279 	char *p;
280 	int i;
281 
282 	/* device location */
283 	pSataChannel = pVDevice->u.disk.mv;
284 	if(pSataChannel == NULL)	return -1;
285 	pDiskInfo->TargetId = 0;
286 	pSataAdapter = pSataChannel->mvSataAdapter;
287 	if(pSataAdapter == NULL)	return -1;
288 
289 	pAdapter = pSataAdapter->IALData;
290 
291 	pDiskInfo->PathId = pSataChannel->channelNumber;
292 	pDiskInfo->ControllerId = (UCHAR)pSataAdapter->adapterId;
293 
294 /*GUI uses DeviceModeSetting to display to users
295 (1) if users select a mode, GUI/BIOS should display that mode.
296 (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied.
297 (3) display real mode if case (1)&&(2) not satisfied.
298 */
299 	if (pVDevice->u.disk.df_user_mode_set)
300 		pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
301 	else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2)
302 		pDiskInfo->DeviceModeSetting = 15;
303 	else {
304 		p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
305 		if (*(WORD*)p==(0x5354) /*'ST'*/ &&
306 			(*(WORD*)(p+8)==(0x4153)/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
307 			pDiskInfo->DeviceModeSetting = 15;
308 		else
309 			pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
310 	}
311 
312 	pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode;
313 
314 	pDiskInfo->DeviceType = PDT_HARDDISK;
315 
316 	pDiskInfo->Flags = 0x0;
317 
318 	/* device is disabled */
319 	if(!pVDevice->u.disk.df_on_line)
320 		pDiskInfo->Flags |= DEVICE_FLAG_DISABLED;
321 
322 	/* disk has a active partition */
323 	if(pVDevice->vf_bootable)
324 		pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK;
325 
326 	/* disk has boot mark set */
327 	if(pVDevice->vf_bootmark)
328 		pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK;
329 
330 	pDiskInfo->Flags |= DEVICE_FLAG_SATA;
331 
332 	/* is a spare disk */
333 	if(pVDevice->VDeviceType == VD_SPARE)
334 		pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE;
335 
336 	memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
337 	p = (char *)&pDiskInfo->IdentifyData.ModelNumber;
338 	for (i = 0; i < 20; i++)
339 		((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
340 	p[39] = '\0';
341 
342 	channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber];
343 	pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported;
344 	pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled;
345 	pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported;
346 	pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled;
347 	pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0;
348 	pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED;
349 	pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) &&
350 		(pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100));
351 	pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING;
352 	return 0;
353 }
354 
hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)355 int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)
356 {
357 	ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES));
358 	cap->dwSize = sizeof(DRIVER_CAPABILITIES);
359 	cap->MaximumControllers = MAX_VBUS;
360 
361 	/* cap->SupportCrossControllerRAID = 0; */
362 	/* take care for various OSes! */
363 	cap->SupportCrossControllerRAID = 0;
364 
365 
366 	cap->MinimumBlockSizeShift = MinBlockSizeShift;
367 	cap->MaximumBlockSizeShift = MaxBlockSizeShift;
368 	cap->SupportDiskModeSetting = 0;
369 	cap->SupportSparePool = 1;
370 	cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1;
371 	cap->SupportDedicatedSpare = 0;
372 
373 
374 #ifdef SUPPORT_ARRAY
375 	/* Stripe */
376 	cap->SupportedRAIDTypes[0] = AT_RAID0;
377 	cap->MaximumArrayMembers[0] = MAX_MEMBERS;
378 	/* Mirror */
379 	cap->SupportedRAIDTypes[1] = AT_RAID1;
380 	cap->MaximumArrayMembers[1] = 2;
381 	/* Mirror + Stripe */
382 #ifdef ARRAY_V2_ONLY
383 	cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */
384 #else
385 	cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */
386 #endif
387 	cap->MaximumArrayMembers[2] = MAX_MEMBERS;
388 	/* Jbod */
389 	cap->SupportedRAIDTypes[3] = AT_JBOD;
390 	cap->MaximumArrayMembers[3] = MAX_MEMBERS;
391 	/* RAID5 */
392 #if SUPPORT_RAID5
393 	cap->SupportedRAIDTypes[4] = AT_RAID5;
394 	cap->MaximumArrayMembers[4] = MAX_MEMBERS;
395 #endif
396 #endif
397 	return 0;
398 }
399 
hpt_get_controller_count(void)400 int hpt_get_controller_count(void)
401 {
402 	IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
403 	int iControllerCount = 0;
404 
405 	while(pAdapTemp != NULL)
406 	{
407 		iControllerCount++;
408 		pAdapTemp = pAdapTemp->next;
409 	}
410 
411 	return iControllerCount;
412 }
413 
hpt_get_controller_info(int id,PCONTROLLER_INFO pInfo)414 int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
415 {
416 	IAL_ADAPTER_T    *pAdapTemp;
417 	int iControllerCount = 0;
418 
419 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
420 		if (iControllerCount++==id) {
421 			pInfo->InterruptLevel = 0;
422 			pInfo->ChipType = 0;
423 			pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100;
424 			strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc.");
425 #ifdef GUI_CONTROLLER_NAME
426 #ifdef FORCE_ATA150_DISPLAY
427 			/* show "Bus Type: ATA/150" in GUI for SATA controllers */
428 			pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150;
429 #endif
430 			strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME);
431 #define _set_product_id(x)
432 #else
433 #define _set_product_id(x) strcpy(pInfo->szProductID, x)
434 #endif
435 			_set_product_id("RocketRAID 18xx SATA Controller");
436 			pInfo->NumBuses = 8;
437 			pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
438 			return 0;
439 		}
440 	}
441 	return -1;
442 }
443 
444 
hpt_get_channel_info(int id,int bus,PCHANNEL_INFO pInfo)445 int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo)
446 {
447 	IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
448 	int i,iControllerCount = 0;
449 
450 	while(pAdapTemp != NULL)
451 	{
452 		if (iControllerCount++==id)
453 			goto found;
454 		pAdapTemp = pAdapTemp->next;
455 	}
456 	return -1;
457 
458 found:
459 
460 	pInfo->IoPort = 0;
461 	pInfo->ControlPort = 0;
462 
463 	for (i = 0; i < 2; i++) {
464 		pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
465 	}
466 
467 	if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
468 		pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
469 	else
470 		pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
471 
472 	return 0;
473 
474 
475 }
476 
hpt_get_logical_devices(DEVICEID * pIds,int nMaxCount)477 int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
478 {
479 	int count = 0;
480 	int	i,j;
481 	PVDevice pPhysical, pLogical;
482 	IAL_ADAPTER_T    *pAdapTemp;
483 
484 	for(i = 0; i < nMaxCount; i++)
485 		pIds[i] = INVALID_DEVICEID;
486 
487 	/* append the arrays not registered on VBus */
488 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
489 		for(i = 0; i < MV_SATA_CHANNELS_NUM; i++)
490 		{
491 			pPhysical = &pAdapTemp->VDevices[i];
492 			pLogical = pPhysical;
493 
494 			while (pLogical->pParent) pLogical = pLogical->pParent;
495 			if (pLogical->VDeviceType==VD_SPARE)
496 				continue;
497 
498 			for (j=0; j<count; j++)
499 				if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
500 			pIds[count++] = VDEV_TO_ID(pLogical);
501 			if (count>=nMaxCount) goto done;
502 			next:;
503 		}
504 	}
505 
506 done:
507 	return count;
508 }
509 
hpt_get_device_info(DEVICEID id,PLOGICAL_DEVICE_INFO pInfo)510 int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
511 {
512 	PVDevice pVDevice = ID_TO_VDEV(id);
513 
514 	if((id == 0) || check_VDevice_valid(pVDevice))
515 		return -1;
516 
517 #ifdef SUPPORT_ARRAY
518 	if (mIsArray(pVDevice)) {
519 		pInfo->Type = LDT_ARRAY;
520 		pInfo->Capacity = pVDevice->VDeviceCapacity;
521 		pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
522 		get_array_info(pVDevice, &pInfo->u.array);
523 		return 0;
524 	}
525 #endif
526 
527 	pInfo->Type = LDT_DEVICE;
528 	pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
529 	/* report real capacity to be compatible with old arrays */
530 	pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
531 	return get_disk_info(pVDevice, &pInfo->u.device);
532 }
533 
hpt_get_device_info_v2(DEVICEID id,PLOGICAL_DEVICE_INFO_V2 pInfo)534 int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo)
535 {
536 	PVDevice pVDevice = ID_TO_VDEV(id);
537 
538 	if((id == 0) || check_VDevice_valid(pVDevice))
539 		return -1;
540 
541 #ifdef SUPPORT_ARRAY
542 	if (mIsArray(pVDevice)) {
543 		pInfo->Type = LDT_ARRAY;
544 		pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity;
545 		pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0;
546 		pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
547 		get_array_info_v2(pVDevice, &pInfo->u.array);
548 	return 0;
549 }
550 #endif
551 
552 	pInfo->Type = LDT_DEVICE;
553 	pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
554 	/* report real capacity to be compatible with old arrays */
555 	pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity;
556 	pInfo->Capacity.hi32 = 0;
557 	return get_disk_info(pVDevice, &pInfo->u.device);
558 }
559 
560 #ifdef SUPPORT_ARRAY
hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)561 DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)
562 {
563 	ULONG Stamp = GetStamp();
564 	int	i,j;
565 	LBA_T  capacity = MAX_LBA_T;
566 	PVDevice pArray,pChild;
567 	int		Loca = -1;
568 
569 	if (pParam->nDisk > MAX_MEMBERS)
570 		return INVALID_DEVICEID;
571 /* check in verify_vd
572 	for(i = 0; i < pParam->nDisk; i++)
573 	{
574 		PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
575 		if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID;
576 		if (mIsArray(pVDev)) return INVALID_DEVICEID;
577 		if (!pVDev->vf_online) return INVALID_DEVICEID;
578 		if (!_vbus_p)
579 			_vbus_p = pVDev->u.disk.pVBus;
580 		else if (_vbus_p != pVDev->u.disk.pVBus)
581 			return INVALID_DEVICEID;
582 	}
583 */
584 	_vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus;
585 	if (!_vbus_p) return INVALID_DEVICEID;
586 
587 	mArGetArrayTable(pArray);
588 	if(!pArray)	return INVALID_DEVICEID;
589 
590 	switch (pParam->ArrayType)
591 	{
592 		case AT_JBOD:
593 			pArray->VDeviceType = VD_JBOD;
594 			goto simple;
595 
596 		case AT_RAID0:
597 			if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
598 				goto error;
599 			pArray->VDeviceType = VD_RAID_0;
600 			goto simple;
601 
602 		case AT_RAID5:
603 			if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
604 				goto error;
605 			pArray->VDeviceType = VD_RAID_5;
606 			/* only "no build" R5 is not critical after creation. */
607 			if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0)
608 				pArray->u.array.rf_need_rebuild = 1;
609 			goto simple;
610 
611 		case AT_RAID1:
612 			if(pParam->nDisk <= 2)
613 			{
614 				pArray->VDeviceType = VD_RAID_1;
615 simple:
616 				pArray->u.array.bArnMember = pParam->nDisk;
617 				pArray->u.array.bArRealnMember = pParam->nDisk;
618 				pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
619 				pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
620 				pArray->u.array.dArStamp = Stamp;
621 
622 				pArray->u.array.rf_need_sync = 1;
623 				pArray->u.array.rf_newly_created = 1;
624 
625 				if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
626 					(pArray->VDeviceType == VD_RAID_1))
627 				{
628 					pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */
629 					pArray->u.array.rf_need_rebuild = 1;
630 					pArray->u.array.rf_auto_rebuild = 1;
631 					pArray->u.array.rf_duplicate_and_create = 1;
632 
633 					for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
634 						if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0]))
635 							Loca = i;
636 				}
637 
638 				pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T;
639 
640 				memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
641 
642 				for(i = 0; i < pParam->nDisk; i++)
643 				{
644 					pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]);
645 					pArray->u.array.pMember[i]->bSerialNumber = i;
646 					pArray->u.array.pMember[i]->pParent = pArray;
647 
648 					/* don't unregister source disk for duplicate RAID1 */
649 					if (i ||
650 						pArray->VDeviceType!=VD_RAID_1 ||
651 						(pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0)
652 						UnregisterVDevice(pArray->u.array.pMember[i]);
653 
654 					if(pArray->VDeviceType == VD_RAID_5)
655 						pArray->u.array.pMember[i]->vf_cache_disk = 1;
656 				}
657 			}
658 			else
659 			{
660 				for(i = 0; i < (pParam->nDisk / 2); i++)
661 				{
662 					mArGetArrayTable(pChild);
663 					pChild->VDeviceType = VD_RAID_1;
664 
665 					pChild->u.array.bArnMember = 2;
666 					pChild->u.array.bArRealnMember = 2;
667 					pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
668 					pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
669 					pChild->u.array.dArStamp = Stamp;
670 
671 					pChild->u.array.rf_need_sync = 1;
672 					pChild->u.array.rf_newly_created = 1;
673 
674 					pChild->u.array.RebuildSectors = MAX_LBA_T;
675 
676 					memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
677 
678 					for(j = 0; j < 2; j++)
679 					{
680 						pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]);
681 						pChild->u.array.pMember[j]->bSerialNumber = j;
682 						pChild->u.array.pMember[j]->pParent = pChild;
683 						pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType];
684 						UnregisterVDevice(pChild->u.array.pMember[j]);
685 					}
686 
687 					pArray->u.array.pMember[i] = pChild;
688 
689 					pChild->vf_online = 1;
690 					pChild->bSerialNumber = i;
691 					pChild->pParent = pArray;
692 					pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity,
693 						pChild->u.array.pMember[1]->VDeviceCapacity);
694 
695 					pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType];
696 					pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0];
697 				}
698 
699 				pArray->VDeviceType = VD_RAID_0;
700 
701 				pArray->u.array.bArnMember = pParam->nDisk / 2;
702 				pArray->u.array.bArRealnMember = pParam->nDisk / 2;
703 				pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
704 				pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
705 				pArray->u.array.dArStamp = Stamp;
706 
707 				pArray->u.array.rf_need_sync = 1;
708 				pArray->u.array.rf_newly_created = 1;
709 
710 				memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
711 			}
712 			break;
713 
714 		default:
715 			goto error;
716 	}
717 
718 	for(i = 0; i < pArray->u.array.bArnMember; i++)
719 		pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
720 
721 	if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
722 		(pArray->VDeviceType == VD_RAID_1))
723 	{
724 		pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark;
725 		pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable;
726 		pArray->u.array.pMember[0]->vf_bootable = 0;
727 		pArray->u.array.pMember[0]->vf_bootmark = 0;
728 		if (Loca>=0) {
729 			_vbus_p->pVDevice[Loca] = pArray;
730 			/* to comfort OS */
731 			pArray->u.array.rf_duplicate_and_created = 1;
732 			pArray->pVBus = _vbus_p;
733 		}
734 	}
735 	else {
736 		UCHAR TempBuffer[512];
737 		ZeroMemory(TempBuffer, 512);
738 		for(i = 0; i < pParam->nDisk; i++)
739 		{
740 			PVDevice	pDisk = ID_TO_VDEV(pParam->Members[i]);
741 			pDisk->vf_bootmark = pDisk->vf_bootable = 0;
742 			fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer);
743 		}
744 	}
745 
746 	pArray->vf_online = 1;
747 	pArray->pParent = NULL;
748 
749 	switch(pArray->VDeviceType)
750 	{
751 		case VD_RAID_0:
752 			for(i = 0; i < pArray->u.array.bArnMember; i++)
753 				if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
754 					capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
755 #ifdef ARRAY_V2_ONLY
756 			capacity -= 10;
757 #endif
758 			capacity &= ~(pArray->u.array.bStripeWitch - 1);
759 			/* shrink member capacity for RAID 1/0 */
760 			for(i = 0; i < pArray->u.array.bArnMember; i++)
761 				if (mIsArray(pArray->u.array.pMember[i]))
762 					pArray->u.array.pMember[i]->VDeviceCapacity = capacity;
763 			pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember;
764 			break;
765 
766 		case VD_RAID_1:
767 			pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity,
768 						pArray->u.array.pMember[1]->VDeviceCapacity);
769 			break;
770 
771 		case VD_JBOD:
772 			for(i = 0; i < pArray->u.array.bArnMember; i++)
773 				pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity
774 #ifdef ARRAY_V2_ONLY
775 				-10
776 #endif
777 				;
778 			break;
779 
780 		case VD_RAID_5:
781 			for(i = 0; i < pArray->u.array.bArnMember; i++)
782 				if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
783 					capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
784 			pArray->VDeviceCapacity = rounddown2(capacity, pArray->u.array.bStripeWitch) *
785 			    (pArray->u.array.bArnMember - 1);
786 			break;
787 
788 		default:
789 			goto error;
790 	}
791 
792 	pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
793 	pArray->pfnDeviceFailed = fOsDiskFailed;
794 	SyncArrayInfo(pArray);
795 
796 	if (!pArray->u.array.rf_duplicate_and_created)
797 		RegisterVDevice(pArray);
798 	return VDEV_TO_ID(pArray);
799 
800 error:
801 	for(i = 0; i < pArray->u.array.bArnMember; i++)
802 	{
803 		pChild = pArray->u.array.pMember[i];
804 		if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
805 			mArFreeArrayTable(pChild);
806 	}
807 	mArFreeArrayTable(pArray);
808 	return INVALID_DEVICEID;
809 }
810 
hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)811 DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
812 {
813 	CREATE_ARRAY_PARAMS_V2 param2;
814 	param2.ArrayType = pParam->ArrayType;
815 	param2.nDisk = pParam->nDisk;
816 	param2.BlockSizeShift = pParam->BlockSizeShift;
817 	param2.CreateFlags = pParam->CreateFlags;
818 	param2.CreateTime = pParam->CreateTime;
819 	memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName));
820 	memcpy(param2.Description, pParam->Description, sizeof(param2.Description));
821 	memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager));
822 	param2.Capacity.lo32 = param2.Capacity.hi32 = 0;
823 	memcpy(param2.Members, pParam->Members, sizeof(pParam->Members));
824 	return hpt_create_array_v2(_VBUS_P &param2);
825 }
826 
827 #ifdef SUPPORT_OLD_ARRAY
828 /* this is only for old RAID 0/1 */
old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray,DEVICEID idDisk)829 int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
830 {
831 	PVDevice pArray1 = ID_TO_VDEV(idArray);
832 	PVDevice pArray2 = 0;
833 	PVDevice pDisk	= ID_TO_VDEV(idDisk);
834 	int	i;
835 	IAL_ADAPTER_T *pAdapter = gIal_Adapter;
836 
837 	if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
838 
839 	if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2))
840 		return -1;
841 
842 	pArray2 = pArray1->u.array.pMember[1];
843 	if(pArray2 == NULL)	{
844 		/* create a Stripe */
845 		mArGetArrayTable(pArray2);
846 		pArray2->VDeviceType = VD_RAID_0;
847 		pArray2->u.array.dArStamp = GetStamp();
848 		pArray2->vf_format_v2 = 1;
849 		pArray2->u.array.rf_broken = 1;
850 		pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift;
851 		pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift);
852 		pArray2->u.array.bArnMember = 2;
853 		pArray2->VDeviceCapacity = pArray1->VDeviceCapacity;
854 		pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType];
855 		pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType];
856 		memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME);
857 		pArray2->pParent = pArray1;
858 		pArray2->bSerialNumber = 1;
859 		pArray1->u.array.pMember[1] = pArray2;
860 		pArray1->u.array.bArRealnMember++;
861 	}
862 
863 	for(i = 0; i < pArray2->u.array.bArnMember; i++)
864 		if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online)
865 		{
866 			if(pArray2->u.array.pMember[i] != NULL)
867 				pArray2->u.array.pMember[i]->pParent = NULL;
868 			pArray2->u.array.pMember[i] = pDisk;
869 			goto find;
870 		}
871 	return -1;
872 
873 find:
874 	UnregisterVDevice(pDisk);
875 	pDisk->VDeviceType = VD_SINGLE_DISK;
876 	pDisk->bSerialNumber = i;
877 	pDisk->pParent = pArray2;
878 	pDisk->vf_format_v2 = 1;
879 	pDisk->u.disk.dDeHiddenLba = i? 10 : 0;
880 	pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
881 	pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType];
882 
883 	pArray2->u.array.bArRealnMember++;
884 	if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){
885 		pArray2->vf_online = 1;
886 		pArray2->u.array.rf_broken = 0;
887 	}
888 
889 	if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){
890 		pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember;
891 		pArray1->u.array.rf_broken = 0;
892 		pArray1->u.array.rf_need_rebuild = 1;
893 		pArray1->u.array.rf_auto_rebuild = 1;
894 
895 	}
896 	pArray1->u.array.RebuildSectors = 0;
897 	pArray1->u.array.dArStamp = GetStamp();
898 	SyncArrayInfo(pArray1);
899 	return 1;
900 }
901 #endif
902 
hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray,DEVICEID idDisk)903 int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
904 {
905 	int	i;
906 
907 	LBA_T Capacity;
908 	PVDevice pArray = ID_TO_VDEV(idArray);
909 	PVDevice pDisk	= ID_TO_VDEV(idDisk);
910 
911 	if((idArray == 0) || (idDisk == 0))	return -1;
912 	if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk))	return -1;
913 	if(!pArray->u.array.rf_broken)	return -1;
914 
915 	if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
916 		return -1;
917 	if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE))
918 		return -1;
919 
920 #ifdef SUPPORT_OLD_ARRAY
921 	/* RAID 0 + 1 */
922 	if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 &&
923 		pArray->u.array.pMember[0] &&
924 		mIsArray(pArray->u.array.pMember[0]))
925 	{
926 		if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk))
927 			return 0;
928 		else
929 			return -1;
930 	}
931 #endif
932 
933 	Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
934 
935 	if (pArray->vf_format_v2) {
936 		if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1;
937 	}
938 	else
939 		if(pDisk->VDeviceCapacity < Capacity) return -1;
940 
941 	if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
942 
943 	for(i = 0; i < pArray->u.array.bArnMember; i++)
944 		if((pArray->u.array.pMember[i] == 0) || !pArray->u.array.pMember[i]->vf_online)
945 		{
946 			if(pArray->u.array.pMember[i] != NULL)
947 				pArray->u.array.pMember[i]->pParent = NULL;
948 			pArray->u.array.pMember[i] = pDisk;
949 			goto find;
950 		}
951 	return -1;
952 
953 find:
954 	UnregisterVDevice(pDisk);
955 	pDisk->VDeviceType = VD_SINGLE_DISK;
956 	pDisk->bSerialNumber = i;
957 	pDisk->pParent = pArray;
958 	if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1;
959 	pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
960 	if (pArray->vf_format_v2) {
961 		pDisk->vf_format_v2 = 1;
962 		pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
963 	}
964 
965 	pArray->u.array.bArRealnMember++;
966 	if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember)
967 	{
968 		pArray->u.array.rf_need_rebuild = 1;
969 		pArray->u.array.RebuildSectors = 0;
970 		pArray->u.array.rf_auto_rebuild = 1;
971 		pArray->u.array.rf_broken = 0;
972 	}
973 	pArray->u.array.RebuildSectors = 0;
974 
975 	/* sync the whole array */
976 	while (pArray->pParent) pArray = pArray->pParent;
977 	pArray->u.array.dArStamp = GetStamp();
978 	SyncArrayInfo(pArray);
979 	return 0;
980 }
981 
hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)982 int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)
983 {
984 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
985 	DECLARE_BUFFER(PUCHAR, pbuffer);
986 
987 	if(idDisk == 0 || check_VDevice_valid(pVDevice))	return -1;
988 	if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent)
989 		return -1;
990 
991 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
992 
993 	UnregisterVDevice(pVDevice);
994 	pVDevice->VDeviceType = VD_SPARE;
995 	pVDevice->vf_bootmark = 0;
996 
997 	ZeroMemory((char *)pbuffer, 512);
998 	fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer);
999 	SyncArrayInfo(pVDevice);
1000 	return 0;
1001 }
1002 
hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)1003 int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)
1004 {
1005 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
1006 
1007 	if(idDisk == 0 || check_VDevice_valid(pVDevice))	return -1;
1008 
1009 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1010 
1011 	pVDevice->VDeviceType = VD_SINGLE_DISK;
1012 
1013 	SyncArrayInfo(pVDevice);
1014 	RegisterVDevice(pVDevice);
1015 	return 0;
1016 }
1017 
hpt_set_array_info(_VBUS_ARG DEVICEID idArray,PALTERABLE_ARRAY_INFO pInfo)1018 int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
1019 {
1020 	PVDevice pVDevice = ID_TO_VDEV(idArray);
1021 
1022 	if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
1023 	if (!mIsArray(pVDevice)) return -1;
1024 
1025 	/* if the pVDevice isn't a top level, return -1; */
1026 	if(pVDevice->pParent != NULL) return -1;
1027 
1028 	if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
1029 
1030 	if (pInfo->ValidFields & AAIF_NAME) {
1031 		memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME);
1032 		memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name));
1033 		pVDevice->u.array.rf_need_sync = 1;
1034 	}
1035 
1036 	if (pInfo->ValidFields & AAIF_DESCRIPTION) {
1037 		memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description));
1038 		pVDevice->u.array.rf_need_sync = 1;
1039 	}
1040 
1041 	if (pVDevice->u.array.rf_need_sync)
1042 		SyncArrayInfo(pVDevice);
1043 	return 0;
1044 }
1045 
hpt_set_device_info(_VBUS_ARG DEVICEID idDisk,PALTERABLE_DEVICE_INFO pInfo)1046 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
1047 {
1048 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
1049 
1050 	if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
1051 	if (mIsArray(pVDevice))
1052 		return -1;
1053 
1054 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1055 
1056 	/* TODO */
1057 		return 0;
1058 	}
1059 
hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk,PALTERABLE_DEVICE_INFO_V2 pInfo)1060 static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo)
1061 {
1062 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
1063 	int sync = 0;
1064 
1065 	if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1;
1066 	if (mIsArray(pVDevice))
1067 		return -1;
1068 
1069 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1070 
1071 	if (pInfo->ValidFields & ADIF_MODE) {
1072 		pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
1073 		pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
1074 		pVDevice->u.disk.df_user_mode_set = 1;
1075 		fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
1076 		sync = 1;
1077 }
1078 
1079 	if (pInfo->ValidFields & ADIF_TCQ) {
1080 		if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) {
1081 			pVDevice->u.disk.df_tcq_set = 1;
1082 			pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0;
1083 			sync = 1;
1084 }
1085 	}
1086 
1087 	if (pInfo->ValidFields & ADIF_NCQ) {
1088 		if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) {
1089 			pVDevice->u.disk.df_ncq_set = 1;
1090 			pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0;
1091 			sync = 1;
1092 	}
1093 	}
1094 
1095 	if (pInfo->ValidFields & ADIF_WRITE_CACHE) {
1096 		if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) {
1097 			pVDevice->u.disk.df_write_cache_set = 1;
1098 			pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0;
1099 			sync = 1;
1100 	}
1101 	}
1102 
1103 	if (pInfo->ValidFields & ADIF_READ_AHEAD) {
1104 		if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) {
1105 			pVDevice->u.disk.df_read_ahead_set = 1;
1106 			pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0;
1107 			sync = 1;
1108 		}
1109 	}
1110 
1111 	if (sync)
1112 		SyncArrayInfo(pVDevice);
1113 	return 0;
1114 }
1115 
1116 #endif
1117 
1118 /* hpt_default_ioctl()
1119  *  This is a default implementation. The platform dependent part
1120  *  may reuse this function and/or use it own implementation for
1121  *  each ioctl function.
1122  */
hpt_default_ioctl(_VBUS_ARG DWORD dwIoControlCode,PVOID lpInBuffer,DWORD nInBufferSize,PVOID lpOutBuffer,DWORD nOutBufferSize,PDWORD lpBytesReturned)1123 int hpt_default_ioctl(_VBUS_ARG
1124 							DWORD dwIoControlCode,       	/* operation control code */
1125 							PVOID lpInBuffer,            	/* input data buffer */
1126 							DWORD nInBufferSize,         	/* size of input data buffer */
1127 							PVOID lpOutBuffer,           	/* output data buffer */
1128 							DWORD nOutBufferSize,        	/* size of output data buffer */
1129 							PDWORD lpBytesReturned      	/* byte count */
1130 					)
1131 {
1132 	switch(dwIoControlCode)	{
1133 
1134 	case HPT_IOCTL_GET_VERSION:
1135 
1136 		if (nInBufferSize != 0) return -1;
1137 		if (nOutBufferSize != sizeof(DWORD)) return -1;
1138 		*((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION;
1139 		break;
1140 
1141 	case HPT_IOCTL_GET_CONTROLLER_COUNT:
1142 
1143 		if (nOutBufferSize!=sizeof(DWORD)) return -1;
1144 		*(PDWORD)lpOutBuffer = hpt_get_controller_count();
1145 		break;
1146 
1147 	case HPT_IOCTL_GET_CONTROLLER_INFO:
1148 		{
1149 			int id;
1150 			PCONTROLLER_INFO pInfo;
1151 
1152 			if (nInBufferSize!=sizeof(DWORD)) return -1;
1153 			if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1;
1154 
1155 			id = *(DWORD *)lpInBuffer;
1156 			pInfo = (PCONTROLLER_INFO)lpOutBuffer;
1157 			if (hpt_get_controller_info(id, pInfo)!=0)
1158 				return -1;
1159 		}
1160 		break;
1161 
1162 	case HPT_IOCTL_GET_CHANNEL_INFO:
1163 		{
1164 			int id, bus;
1165 			PCHANNEL_INFO pInfo;
1166 
1167 			if (nInBufferSize!=8) return -1;
1168 			if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1;
1169 
1170 			id = *(DWORD *)lpInBuffer;
1171 			bus = ((DWORD *)lpInBuffer)[1];
1172 			pInfo = (PCHANNEL_INFO)lpOutBuffer;
1173 
1174 			if (hpt_get_channel_info(id, bus, pInfo)!=0)
1175 				return -1;
1176 		}
1177 		break;
1178 
1179 	case HPT_IOCTL_GET_LOGICAL_DEVICES:
1180 		{
1181 			DWORD nMax;
1182 			DEVICEID *pIds;
1183 
1184 			if (nInBufferSize!=sizeof(DWORD)) return -1;
1185 			nMax = *(DWORD *)lpInBuffer;
1186 			if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1;
1187 
1188 			pIds = ((DEVICEID *)lpOutBuffer)+1;
1189 			*(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax);
1190 		}
1191 		break;
1192 
1193 	case HPT_IOCTL_GET_DEVICE_INFO:
1194 		{
1195 			DEVICEID id;
1196 			PLOGICAL_DEVICE_INFO pInfo;
1197 
1198 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1199 			if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1;
1200 
1201 			id = *(DWORD *)lpInBuffer;
1202 			if (id == INVALID_DEVICEID)	return -1;
1203 
1204 			pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer;
1205 			memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO));
1206 
1207 			if (hpt_get_device_info(id, pInfo)!=0)
1208 				return -1;
1209 		}
1210 		break;
1211 
1212 	case HPT_IOCTL_GET_DEVICE_INFO_V2:
1213 		{
1214 			DEVICEID id;
1215 			PLOGICAL_DEVICE_INFO_V2 pInfo;
1216 
1217 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1218 			if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1;
1219 
1220 			id = *(DWORD *)lpInBuffer;
1221 			if (id == INVALID_DEVICEID)	return -1;
1222 
1223 			pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer;
1224 			memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2));
1225 
1226 			if (hpt_get_device_info_v2(id, pInfo)!=0)
1227 				return -1;
1228 		}
1229 		break;
1230 
1231 #ifdef SUPPORT_ARRAY
1232 	case HPT_IOCTL_CREATE_ARRAY:
1233 		{
1234 			if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
1235 			if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
1236 
1237 			*(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer);
1238 
1239 			if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
1240 				return -1;
1241 		}
1242 		break;
1243 
1244 	case HPT_IOCTL_CREATE_ARRAY_V2:
1245 		{
1246 			if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1;
1247 			if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
1248 
1249 			*(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer);
1250 
1251 			if (*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
1252 				return -1;
1253 		}
1254 		break;
1255 
1256 	case HPT_IOCTL_SET_ARRAY_INFO:
1257 		{
1258 			DEVICEID idArray;
1259 			PALTERABLE_ARRAY_INFO pInfo;
1260 
1261 			if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1;
1262 			if (nOutBufferSize!=0) return -1;
1263 
1264 			idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray;
1265 			pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info;
1266 
1267 			if(hpt_set_array_info(_VBUS_P idArray,  pInfo))
1268 				return -1;
1269 		}
1270 		break;
1271 
1272 	case HPT_IOCTL_SET_DEVICE_INFO:
1273 		{
1274 			DEVICEID idDisk;
1275 			PALTERABLE_DEVICE_INFO pInfo;
1276 
1277 			if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1;
1278 			if (nOutBufferSize!=0) return -1;
1279 
1280 			idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk;
1281 			pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info;
1282 			if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0)
1283 				return -1;
1284 		}
1285 		break;
1286 
1287 	case HPT_IOCTL_SET_DEVICE_INFO_V2:
1288 		{
1289 			DEVICEID idDisk;
1290 			PALTERABLE_DEVICE_INFO_V2 pInfo;
1291 
1292 			if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1;
1293 			if (nOutBufferSize!=0) return -1;
1294 
1295 			idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk;
1296 			pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info;
1297 			if(hpt_set_device_info_v2(_VBUS_P idDisk, pInfo) != 0)
1298 				return -1;
1299 		}
1300 		break;
1301 
1302 	case HPT_IOCTL_SET_BOOT_MARK:
1303 		{
1304 			DEVICEID id;
1305 			PVDevice pTop;
1306 			int i;
1307 			IAL_ADAPTER_T *pAdapter = gIal_Adapter;
1308 			PVBus pVBus;
1309 
1310 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1311 			id = *(DEVICEID *)lpInBuffer;
1312 			while(pAdapter != 0)
1313 			{
1314 				pVBus = &pAdapter->VBus;
1315 				for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
1316 				{
1317 					if(!(pTop = pVBus->pVDevice[i])) continue;
1318 					if (pTop->pVBus!=_vbus_p) return -1;
1319 					while (pTop->pParent) pTop = pTop->pParent;
1320 					if (id==0 && pTop->vf_bootmark)
1321 						pTop->vf_bootmark = 0;
1322 					else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark)
1323 						pTop->vf_bootmark = 1;
1324 					else
1325 						continue;
1326 					SyncArrayInfo(pTop);
1327 					break;
1328 				}
1329 				pAdapter = pAdapter->next;
1330 			}
1331 		}
1332 		break;
1333 
1334 	case HPT_IOCTL_ADD_SPARE_DISK:
1335 		{
1336 			DEVICEID id;
1337 
1338 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1339 			if (nOutBufferSize!=0) return -1;
1340 
1341 			id = *(DEVICEID *)lpInBuffer;
1342 
1343 			if(hpt_add_spare_disk(_VBUS_P id))
1344 				return -1;
1345 		}
1346 		break;
1347 
1348 	case HPT_IOCTL_REMOVE_SPARE_DISK:
1349 		{
1350 			DEVICEID id;
1351 
1352 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1353 			if (nOutBufferSize!=0) return -1;
1354 
1355 			id = *(DEVICEID *)lpInBuffer;
1356 
1357 			if(hpt_remove_spare_disk(_VBUS_P id))
1358 				return -1;
1359 		}
1360 		break;
1361 
1362 	case HPT_IOCTL_ADD_DISK_TO_ARRAY:
1363 		{
1364 			DEVICEID id1,id2;
1365 			id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray;
1366 			id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk;
1367 
1368 			if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1;
1369 			if (nOutBufferSize != 0) return -1;
1370 
1371 			if(hpt_add_disk_to_array(_VBUS_P id1, id2))
1372 				return -1;
1373 		}
1374 		break;
1375 #endif
1376 	case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
1377 		{
1378 			PDRIVER_CAPABILITIES cap;
1379 			if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
1380 			cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
1381 
1382 			if(hpt_get_driver_capabilities(cap))
1383 				return -1;
1384 		}
1385 		break;
1386 
1387 	case HPT_IOCTL_GET_CONTROLLER_VENID:
1388 		{
1389 			DWORD id = ((DWORD*)lpInBuffer)[0];
1390 			IAL_ADAPTER_T *pAdapTemp;
1391 			int iControllerCount = 0;
1392 
1393 			for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
1394 				if (iControllerCount++==id)
1395 					break;
1396 
1397 			if (!pAdapTemp)
1398 				return -1;
1399 
1400 			if (nOutBufferSize < 4)
1401 				return -1;
1402 
1403 			*(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB;
1404 			return 0;
1405 		}
1406 
1407 	case HPT_IOCTL_EPROM_IO:
1408 		{
1409 			DWORD id           = ((DWORD*)lpInBuffer)[0];
1410 			DWORD offset	   = ((DWORD*)lpInBuffer)[1];
1411 			DWORD direction    = ((DWORD*)lpInBuffer)[2];
1412 			DWORD length	   = ((DWORD*)lpInBuffer)[3];
1413 			IAL_ADAPTER_T *pAdapTemp;
1414 			int iControllerCount = 0;
1415 
1416 			for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
1417 				if (iControllerCount++==id)
1418 					break;
1419 
1420 			if (!pAdapTemp)
1421 				return -1;
1422 
1423 			if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) ||
1424 				nOutBufferSize < (direction? 0 : length))
1425 				return -1;
1426 
1427 			if (direction == 0) /* read */
1428 				sx508x_flash_access(&pAdapTemp->mvSataAdapter,
1429 					offset, lpOutBuffer, length, 1);
1430 			else
1431 				sx508x_flash_access(&pAdapTemp->mvSataAdapter,
1432 					offset, (char *)lpInBuffer + 16, length, 0);
1433 
1434 			return 0;
1435 		}
1436 		break;
1437 
1438 	default:
1439 		return -1;
1440 	}
1441 
1442 	if (lpBytesReturned)
1443 		*lpBytesReturned = nOutBufferSize;
1444 	return 0;
1445 }
1446