xref: /dflybsd-src/sys/dev/raid/hptmv/entry.c (revision ea778d16176a228522f06362e3aebac8f92f4b11)
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/entry.c,v 1.23 2010/06/19 13:42:14 mav Exp $
2735878b55SSascha Wildner  */
2835878b55SSascha Wildner 
2935878b55SSascha Wildner #include <sys/param.h>
3035878b55SSascha Wildner #include <sys/systm.h>
3135878b55SSascha Wildner #include <sys/kernel.h>
3235878b55SSascha Wildner #include <sys/bus.h>
3335878b55SSascha Wildner #include <sys/malloc.h>
3435878b55SSascha Wildner #include <sys/resource.h>
3535878b55SSascha Wildner #include <sys/time.h>
3635878b55SSascha Wildner #include <sys/callout.h>
3735878b55SSascha Wildner #include <sys/signalvar.h>
3835878b55SSascha Wildner #include <sys/eventhandler.h>
3935878b55SSascha Wildner #include <sys/proc.h>
4035878b55SSascha Wildner #include <sys/kthread.h>
4135878b55SSascha Wildner 
4235878b55SSascha Wildner #include <sys/lock.h>
4335878b55SSascha Wildner #include <sys/module.h>
4435878b55SSascha Wildner 
4535878b55SSascha Wildner #include <bus/pci/pcireg.h>
4635878b55SSascha Wildner #include <bus/pci/pcivar.h>
4735878b55SSascha Wildner 
4835878b55SSascha Wildner #ifndef __KERNEL__
4935878b55SSascha Wildner #define __KERNEL__
5035878b55SSascha Wildner #endif
5135878b55SSascha Wildner 
5235878b55SSascha Wildner #include <dev/raid/hptmv/global.h>
5335878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h>
5435878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h>
5535878b55SSascha Wildner #include <dev/raid/hptmv/access601.h>
5635878b55SSascha Wildner 
5735878b55SSascha Wildner 
5835878b55SSascha Wildner #ifdef DEBUG
5935878b55SSascha Wildner #ifdef DEBUG_LEVEL
6035878b55SSascha Wildner int hpt_dbg_level = DEBUG_LEVEL;
6135878b55SSascha Wildner #else
6235878b55SSascha Wildner int hpt_dbg_level = 0;
6335878b55SSascha Wildner #endif
6435878b55SSascha Wildner #endif
6535878b55SSascha Wildner 
6635878b55SSascha Wildner #define MV_ERROR kprintf
6735878b55SSascha Wildner 
6835878b55SSascha Wildner /*
6935878b55SSascha Wildner  * CAM SIM entry points
7035878b55SSascha Wildner  */
7135878b55SSascha Wildner static int 	hpt_probe (device_t dev);
7235878b55SSascha Wildner static void launch_worker_thread(void);
7335878b55SSascha Wildner static int 	hpt_attach(device_t dev);
7435878b55SSascha Wildner static int 	hpt_detach(device_t dev);
7535878b55SSascha Wildner static int 	hpt_shutdown(device_t dev);
7635878b55SSascha Wildner static void hpt_poll(struct cam_sim *sim);
7735878b55SSascha Wildner static void hpt_intr(void *arg);
7835878b55SSascha Wildner static void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
7935878b55SSascha Wildner static void hpt_action(struct cam_sim *sim, union ccb *ccb);
8035878b55SSascha Wildner 
812050a95dSSascha Wildner static struct thread *hptdaemonproc;
822050a95dSSascha Wildner 
8335878b55SSascha Wildner static device_method_t driver_methods[] = {
8435878b55SSascha Wildner 	/* Device interface */
8535878b55SSascha Wildner 	DEVMETHOD(device_probe,		hpt_probe),
8635878b55SSascha Wildner 	DEVMETHOD(device_attach,	hpt_attach),
8735878b55SSascha Wildner 	DEVMETHOD(device_detach,	hpt_detach),
8835878b55SSascha Wildner 
8935878b55SSascha Wildner 	DEVMETHOD(device_shutdown,	hpt_shutdown),
9035878b55SSascha Wildner 	{ 0, 0 }
9135878b55SSascha Wildner };
9235878b55SSascha Wildner 
9335878b55SSascha Wildner static driver_t hpt_pci_driver = {
9435878b55SSascha Wildner 	__str(PROC_DIR_NAME),
9535878b55SSascha Wildner 	driver_methods,
9635878b55SSascha Wildner 	sizeof(IAL_ADAPTER_T)
9735878b55SSascha Wildner };
9835878b55SSascha Wildner 
9935878b55SSascha Wildner static devclass_t	hpt_devclass;
10035878b55SSascha Wildner 
10135878b55SSascha Wildner #define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6)
10235878b55SSascha Wildner __DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0);
10335878b55SSascha Wildner 
10435878b55SSascha Wildner #define ccb_ccb_ptr spriv_ptr0
10535878b55SSascha Wildner #define ccb_adapter ccb_h.spriv_ptr1
10635878b55SSascha Wildner 
10735878b55SSascha Wildner static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev);
10835878b55SSascha Wildner static void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb);
10935878b55SSascha Wildner static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd);
11035878b55SSascha Wildner static void ccb_done(union ccb *ccb);
11135878b55SSascha Wildner static void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb);
11235878b55SSascha Wildner static void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb);
11335878b55SSascha Wildner static void	hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter);
11435878b55SSascha Wildner static void	hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
11535878b55SSascha Wildner static void	handleEdmaError(_VBUS_ARG PCommand pCmd);
11635878b55SSascha Wildner static int	hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
11735878b55SSascha Wildner static int	fResetActiveCommands(PVBus _vbus_p);
11835878b55SSascha Wildner static void	fRegisterVdevice(IAL_ADAPTER_T *pAdapter);
11935878b55SSascha Wildner static int	hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter);
12035878b55SSascha Wildner static void	hptmv_handle_event_disconnect(void *data);
12135878b55SSascha Wildner static void	hptmv_handle_event_connect(void *data);
12235878b55SSascha Wildner static int	start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
12335878b55SSascha Wildner static void	init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel);
12435878b55SSascha Wildner static int	hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel);
12535878b55SSascha Wildner static int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg,
12635878b55SSascha Wildner     int logical);
12735878b55SSascha Wildner static MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
12835878b55SSascha Wildner     MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId,
12935878b55SSascha Wildner     MV_U16 responseFlags, MV_U32 timeStamp,
13035878b55SSascha Wildner     MV_STORAGE_DEVICE_REGISTERS *registerStruct);
13135878b55SSascha Wildner static MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter,
13235878b55SSascha Wildner     MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2);
13335878b55SSascha Wildner 
13435878b55SSascha Wildner #define ccb_ccb_ptr spriv_ptr0
13535878b55SSascha Wildner #define ccb_adapter ccb_h.spriv_ptr1
13635878b55SSascha Wildner 
1374090d6ffSSascha Wildner IAL_ADAPTER_T *gIal_Adapter = NULL;
1384090d6ffSSascha Wildner IAL_ADAPTER_T *pCurAdapter = NULL;
13935878b55SSascha Wildner static MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM];
14035878b55SSascha Wildner 
14135878b55SSascha Wildner typedef struct st_HPT_DPC {
14235878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter;
14335878b55SSascha Wildner 	void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR);
14435878b55SSascha Wildner 	void *arg;
14535878b55SSascha Wildner 	UCHAR flags;
14635878b55SSascha Wildner } ST_HPT_DPC;
14735878b55SSascha Wildner 
14835878b55SSascha Wildner #define MAX_DPC 16
14935878b55SSascha Wildner UCHAR DPC_Request_Nums = 0;
15035878b55SSascha Wildner static ST_HPT_DPC DpcQueue[MAX_DPC];
15135878b55SSascha Wildner static int DpcQueue_First=0;
15235878b55SSascha Wildner static int DpcQueue_Last = 0;
15335878b55SSascha Wildner 
15435878b55SSascha Wildner char DRIVER_VERSION[] = "v1.16";
15535878b55SSascha Wildner 
15635878b55SSascha Wildner static struct lock driver_lock;
157c898d682SSascha Wildner void lock_driver(void)
15835878b55SSascha Wildner {
15935878b55SSascha Wildner 	lockmgr(&driver_lock, LK_EXCLUSIVE);
16035878b55SSascha Wildner }
161c898d682SSascha Wildner void unlock_driver(void)
16235878b55SSascha Wildner {
16335878b55SSascha Wildner 	lockmgr(&driver_lock, LK_RELEASE);
16435878b55SSascha Wildner }
16535878b55SSascha Wildner 
16635878b55SSascha Wildner /*******************************************************************************
16735878b55SSascha Wildner  *	Name:	hptmv_free_channel
16835878b55SSascha Wildner  *
16935878b55SSascha Wildner  *	Description:	free allocated queues for the given channel
17035878b55SSascha Wildner  *
17135878b55SSascha Wildner  *	Parameters:    	pMvSataAdapter - pointer to the RR18xx controler this
17235878b55SSascha Wildner  * 					channel connected to.
17335878b55SSascha Wildner  *			channelNum - channel number.
17435878b55SSascha Wildner  *
17535878b55SSascha Wildner  ******************************************************************************/
17635878b55SSascha Wildner static void
17735878b55SSascha Wildner hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
17835878b55SSascha Wildner {
17935878b55SSascha Wildner 	HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM);
18035878b55SSascha Wildner 	pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL;
18135878b55SSascha Wildner }
18235878b55SSascha Wildner 
18335878b55SSascha Wildner static void failDevice(PVDevice pVDev)
18435878b55SSascha Wildner {
18535878b55SSascha Wildner 	PVBus _vbus_p = pVDev->pVBus;
18635878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
18735878b55SSascha Wildner 
18835878b55SSascha Wildner 	pVDev->u.disk.df_on_line = 0;
18935878b55SSascha Wildner 	pVDev->vf_online = 0;
19035878b55SSascha Wildner 	if (pVDev->pfnDeviceFailed)
19135878b55SSascha Wildner 		CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev);
19235878b55SSascha Wildner 
19335878b55SSascha Wildner 	fNotifyGUI(ET_DEVICE_REMOVED, pVDev);
19435878b55SSascha Wildner 
19535878b55SSascha Wildner #ifndef FOR_DEMO
19635878b55SSascha Wildner 	if (pAdapter->ver_601==2 && !pAdapter->beeping) {
19735878b55SSascha Wildner 		pAdapter->beeping = 1;
19835878b55SSascha Wildner 		BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress);
19935878b55SSascha Wildner 		set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1);
20035878b55SSascha Wildner 	}
20135878b55SSascha Wildner #endif
20235878b55SSascha Wildner }
20335878b55SSascha Wildner 
20435878b55SSascha Wildner int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel);
20535878b55SSascha Wildner 
20635878b55SSascha Wildner static void
20735878b55SSascha Wildner handleEdmaError(_VBUS_ARG PCommand pCmd)
20835878b55SSascha Wildner {
20935878b55SSascha Wildner 	PDevice pDevice = &pCmd->pVDevice->u.disk;
21035878b55SSascha Wildner 	MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter;
21135878b55SSascha Wildner 
21235878b55SSascha Wildner 	if (!pDevice->df_on_line) {
21335878b55SSascha Wildner 		KdPrint(("Device is offline"));
21435878b55SSascha Wildner 		pCmd->Result = RETURN_BAD_DEVICE;
21535878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
21635878b55SSascha Wildner 		return;
21735878b55SSascha Wildner 	}
21835878b55SSascha Wildner 
21935878b55SSascha Wildner 	if (pCmd->RetryCount++>5) {
22035878b55SSascha Wildner 		hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber));
22135878b55SSascha Wildner failed:
22235878b55SSascha Wildner 		failDevice(pCmd->pVDevice);
22335878b55SSascha Wildner 		pCmd->Result = RETURN_IDE_ERROR;
22435878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
22535878b55SSascha Wildner 		return;
22635878b55SSascha Wildner 	}
22735878b55SSascha Wildner 
22835878b55SSascha Wildner 	/* reset the channel and retry the command */
22935878b55SSascha Wildner 	if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber))
23035878b55SSascha Wildner 		goto failed;
23135878b55SSascha Wildner 
23235878b55SSascha Wildner 	fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice));
23335878b55SSascha Wildner 
23435878b55SSascha Wildner 	hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber));
23535878b55SSascha Wildner 	fDeviceSendCommand(_VBUS_P pCmd);
23635878b55SSascha Wildner }
23735878b55SSascha Wildner 
23835878b55SSascha Wildner /****************************************************************
23935878b55SSascha Wildner  *	Name:	hptmv_init_channel
24035878b55SSascha Wildner  *
24135878b55SSascha Wildner  *	Description:	allocate request and response queues for the EDMA of the
24235878b55SSascha Wildner  *					given channel and sets other fields.
24335878b55SSascha Wildner  *
24435878b55SSascha Wildner  *	Parameters:
24535878b55SSascha Wildner  *		pAdapter - pointer to the emulated adapter data structure
24635878b55SSascha Wildner  *		channelNum - channel number.
24735878b55SSascha Wildner  *	Return:	0 on success, otherwise on failure
24835878b55SSascha Wildner  ****************************************************************/
24935878b55SSascha Wildner static int
25035878b55SSascha Wildner hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
25135878b55SSascha Wildner {
25235878b55SSascha Wildner 	MV_SATA_CHANNEL *pMvSataChannel;
25335878b55SSascha Wildner 	dma_addr_t    req_dma_addr;
25435878b55SSascha Wildner 	dma_addr_t    rsp_dma_addr;
25535878b55SSascha Wildner 
25635878b55SSascha Wildner 	if (channelNum >= MV_SATA_CHANNELS_NUM)
25735878b55SSascha Wildner 	{
25835878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: Bad channelNum=%d",
25935878b55SSascha Wildner 				 pAdapter->mvSataAdapter.adapterId, channelNum);
26035878b55SSascha Wildner 		return -1;
26135878b55SSascha Wildner 	}
26235878b55SSascha Wildner 
26335878b55SSascha Wildner 	pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum];
26435878b55SSascha Wildner 	pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel;
26535878b55SSascha Wildner 	pMvSataChannel->channelNumber = channelNum;
26635878b55SSascha Wildner 	pMvSataChannel->lba48Address = MV_FALSE;
26735878b55SSascha Wildner 	pMvSataChannel->maxReadTransfer = MV_FALSE;
26835878b55SSascha Wildner 
26935878b55SSascha Wildner 	pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *)
27035878b55SSascha Wildner 								   (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE));
27135878b55SSascha Wildner 	req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE);
27235878b55SSascha Wildner 
27335878b55SSascha Wildner 
27435878b55SSascha Wildner 	KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr));
27535878b55SSascha Wildner 
27635878b55SSascha Wildner 	/* check the 1K alignment of the request queue*/
27735878b55SSascha Wildner 	if (req_dma_addr & 0x3ff)
27835878b55SSascha Wildner 	{
27935878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned,"
28035878b55SSascha Wildner 				 " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId,
28135878b55SSascha Wildner 				 (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum);
28235878b55SSascha Wildner 		return -1;
28335878b55SSascha Wildner 	}
28435878b55SSascha Wildner 	pMvSataChannel->requestQueuePciLowAddress = req_dma_addr;
28535878b55SSascha Wildner 	pMvSataChannel->requestQueuePciHiAddress = 0;
28635878b55SSascha Wildner 	KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p",
28735878b55SSascha Wildner 			  pAdapter->mvSataAdapter.adapterId, channelNum,
28835878b55SSascha Wildner 			  pMvSataChannel->requestQueue));
28935878b55SSascha Wildner 	pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *)
29035878b55SSascha Wildner 									(pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE));
29135878b55SSascha Wildner 	rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE);
29235878b55SSascha Wildner 
29335878b55SSascha Wildner 	/* check the 256 alignment of the response queue*/
29435878b55SSascha Wildner 	if (rsp_dma_addr & 0xff)
29535878b55SSascha Wildner 	{
29635878b55SSascha Wildner 		MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte "
29735878b55SSascha Wildner 				 "aligned, dma_addr=%llx\n",
29835878b55SSascha Wildner 				 pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr);
29935878b55SSascha Wildner 		return -1;
30035878b55SSascha Wildner 	}
30135878b55SSascha Wildner 	pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr;
30235878b55SSascha Wildner 	pMvSataChannel->responseQueuePciHiAddress = 0;
30335878b55SSascha Wildner 	KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p",
30435878b55SSascha Wildner 			  pAdapter->mvSataAdapter.adapterId, channelNum,
30535878b55SSascha Wildner 			  pMvSataChannel->responseQueue));
30635878b55SSascha Wildner 
30735878b55SSascha Wildner 	pAdapter->mvChannel[channelNum].online = MV_TRUE;
30835878b55SSascha Wildner 	return 0;
30935878b55SSascha Wildner }
31035878b55SSascha Wildner 
31135878b55SSascha Wildner /******************************************************************************
31235878b55SSascha Wildner  *	Name: hptmv_parse_identify_results
31335878b55SSascha Wildner  *
31435878b55SSascha Wildner  *	Description:	this functions parses the identify command results, checks
31535878b55SSascha Wildner  *					that the connected deives can be accesed by RR18xx EDMA,
31635878b55SSascha Wildner  *					and updates the channel stucture accordingly.
31735878b55SSascha Wildner  *
31835878b55SSascha Wildner  *	Parameters:     pMvSataChannel, pointer to the channel data structure.
31935878b55SSascha Wildner  *
32035878b55SSascha Wildner  *	Returns:       	=0 ->success, < 0 ->failure.
32135878b55SSascha Wildner  *
32235878b55SSascha Wildner  ******************************************************************************/
32335878b55SSascha Wildner static int
32435878b55SSascha Wildner hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel)
32535878b55SSascha Wildner {
32635878b55SSascha Wildner 	MV_U16  *iden = pMvSataChannel->identifyDevice;
32735878b55SSascha Wildner 
32835878b55SSascha Wildner 	/*LBA addressing*/
32935878b55SSascha Wildner 	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200))
33035878b55SSascha Wildner 	{
33135878b55SSascha Wildner 		KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n"));
33235878b55SSascha Wildner 		return -1;
33335878b55SSascha Wildner 	}
33435878b55SSascha Wildner 	else
33535878b55SSascha Wildner 	{
33635878b55SSascha Wildner 		KdPrint(("%25s - %s\n", "Capabilities", "LBA supported"));
33735878b55SSascha Wildner 	}
33835878b55SSascha Wildner 	/*DMA support*/
33935878b55SSascha Wildner 	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100))
34035878b55SSascha Wildner 	{
34135878b55SSascha Wildner 		KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n"));
34235878b55SSascha Wildner 		return -1;
34335878b55SSascha Wildner 	}
34435878b55SSascha Wildner 	else
34535878b55SSascha Wildner 	{
34635878b55SSascha Wildner 		KdPrint(("%25s - %s\n", "Capabilities", "DMA supported"));
34735878b55SSascha Wildner 	}
34835878b55SSascha Wildner 	/* PIO */
34935878b55SSascha Wildner 	if ((iden[IDEN_VALID] & 2) == 0)
35035878b55SSascha Wildner 	{
35135878b55SSascha Wildner 		KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n"));
35235878b55SSascha Wildner 		return -1;
35335878b55SSascha Wildner 	}
35435878b55SSascha Wildner 	KdPrint(("%25s - 0x%02x\n", "PIO modes supported",
35535878b55SSascha Wildner 			  iden[IDEN_PIO_MODE_SPPORTED] & 0xff));
35635878b55SSascha Wildner 
35735878b55SSascha Wildner 	/*UDMA*/
35835878b55SSascha Wildner 	if ((iden[IDEN_VALID] & 4) == 0)
35935878b55SSascha Wildner 	{
36035878b55SSascha Wildner 		KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n"));
36135878b55SSascha Wildner 		return -1;
36235878b55SSascha Wildner 	}
36335878b55SSascha Wildner 
36435878b55SSascha Wildner 	/* 48 bit address */
36535878b55SSascha Wildner 	if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400))
36635878b55SSascha Wildner 	{
36735878b55SSascha Wildner 		KdPrint(("%25s - %s\n", "LBA48 addressing", "supported"));
36835878b55SSascha Wildner 		pMvSataChannel->lba48Address = MV_TRUE;
36935878b55SSascha Wildner 	}
37035878b55SSascha Wildner 	else
37135878b55SSascha Wildner 	{
37235878b55SSascha Wildner 		KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported"));
37335878b55SSascha Wildner 		pMvSataChannel->lba48Address = MV_FALSE;
37435878b55SSascha Wildner 	}
37535878b55SSascha Wildner 	return 0;
37635878b55SSascha Wildner }
37735878b55SSascha Wildner 
37835878b55SSascha Wildner static void
37935878b55SSascha Wildner init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel)
38035878b55SSascha Wildner {
38135878b55SSascha Wildner 	PVDevice pVDev = &pAdapter->VDevices[channel];
38235878b55SSascha Wildner 	MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel];
38335878b55SSascha Wildner 	MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice;
38435878b55SSascha Wildner 
38535878b55SSascha Wildner 	pMvSataChannel->outstandingCommands = 0;
38635878b55SSascha Wildner 
38735878b55SSascha Wildner 	pVDev->u.disk.mv         = pMvSataChannel;
38835878b55SSascha Wildner 	pVDev->u.disk.df_on_line = 1;
38935878b55SSascha Wildner 	pVDev->u.disk.pVBus      = &pAdapter->VBus;
39035878b55SSascha Wildner 	pVDev->pVBus             = &pAdapter->VBus;
39135878b55SSascha Wildner 
39235878b55SSascha Wildner #ifdef SUPPORT_48BIT_LBA
39335878b55SSascha Wildner 	if (pMvSataChannel->lba48Address == MV_TRUE)
39435878b55SSascha Wildner 		pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1;
39535878b55SSascha Wildner 	else
39635878b55SSascha Wildner #endif
39735878b55SSascha Wildner 	if(IdentifyData[53] & 1) {
39835878b55SSascha Wildner 	pVDev->u.disk.dDeRealCapacity =
39935878b55SSascha Wildner 	  (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ?
40035878b55SSascha Wildner 		  (IdentifyData[61]<<16 | IdentifyData[60]) :
40135878b55SSascha Wildner 				(IdentifyData[58]<<16 | IdentifyData[57])) - 1;
40235878b55SSascha Wildner 	} else
40335878b55SSascha Wildner 		pVDev->u.disk.dDeRealCapacity =
40435878b55SSascha Wildner 				 (IdentifyData[61]<<16 | IdentifyData[60]) - 1;
40535878b55SSascha Wildner 
40635878b55SSascha Wildner 	pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
40735878b55SSascha Wildner 		pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0;
40835878b55SSascha Wildner 
40935878b55SSascha Wildner 	if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) {
41035878b55SSascha Wildner 		pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
41135878b55SSascha Wildner 			pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8;
41235878b55SSascha Wildner 	}
41335878b55SSascha Wildner }
41435878b55SSascha Wildner 
41535878b55SSascha Wildner static void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged)
41635878b55SSascha Wildner {
41735878b55SSascha Wildner 	PVDevice pVDev;
41835878b55SSascha Wildner 	MV_SATA_ADAPTER  *pMvSataAdapter = &pAdapter->mvSataAdapter;
41935878b55SSascha Wildner 	MV_SATA_CHANNEL  *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex];
42035878b55SSascha Wildner 
42135878b55SSascha Wildner 	if (!pMvSataChannel) return;
42235878b55SSascha Wildner 
42335878b55SSascha Wildner 	if (plugged)
42435878b55SSascha Wildner 	{
42535878b55SSascha Wildner 		pVDev = &(pAdapter->VDevices[channelIndex]);
42635878b55SSascha Wildner 		init_vdev_params(pAdapter, channelIndex);
42735878b55SSascha Wildner 
42835878b55SSascha Wildner 		pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI :
42935878b55SSascha Wildner 			pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
43035878b55SSascha Wildner 
43135878b55SSascha Wildner 		pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO;
43235878b55SSascha Wildner 		pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
43335878b55SSascha Wildner 		pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
43435878b55SSascha Wildner 		pVDev->vf_online = 1;
43535878b55SSascha Wildner 
43635878b55SSascha Wildner #ifdef SUPPORT_ARRAY
43735878b55SSascha Wildner 		if(pVDev->pParent)
43835878b55SSascha Wildner 		{
43935878b55SSascha Wildner 			int iMember;
44035878b55SSascha Wildner 			for(iMember = 0; iMember < 	pVDev->pParent->u.array.bArnMember; iMember++)
44135878b55SSascha Wildner 				if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev)
44235878b55SSascha Wildner 					pVDev->pParent->u.array.pMember[iMember] = NULL;
44335878b55SSascha Wildner 			pVDev->pParent = NULL;
44435878b55SSascha Wildner 		}
44535878b55SSascha Wildner #endif
44635878b55SSascha Wildner 		fNotifyGUI(ET_DEVICE_PLUGGED,pVDev);
44735878b55SSascha Wildner 		fCheckBootable(pVDev);
44835878b55SSascha Wildner 		RegisterVDevice(pVDev);
44935878b55SSascha Wildner 
45035878b55SSascha Wildner #ifndef FOR_DEMO
45135878b55SSascha Wildner 		if (pAdapter->beeping) {
45235878b55SSascha Wildner 			pAdapter->beeping = 0;
45335878b55SSascha Wildner 			BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
45435878b55SSascha Wildner 		}
45535878b55SSascha Wildner #endif
45635878b55SSascha Wildner 
45735878b55SSascha Wildner 	}
45835878b55SSascha Wildner 	else
45935878b55SSascha Wildner 	{
46035878b55SSascha Wildner 		pVDev  = &(pAdapter->VDevices[channelIndex]);
46135878b55SSascha Wildner 		failDevice(pVDev);
46235878b55SSascha Wildner 	}
46335878b55SSascha Wildner }
46435878b55SSascha Wildner 
46535878b55SSascha Wildner static int
46635878b55SSascha Wildner start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
46735878b55SSascha Wildner {
46835878b55SSascha Wildner 	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
46935878b55SSascha Wildner 	MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum];
47035878b55SSascha Wildner 	MV_CHANNEL		*pChannelInfo = &(pAdapter->mvChannel[channelNum]);
47135878b55SSascha Wildner 	MV_U32          udmaMode,pioMode;
47235878b55SSascha Wildner 
47335878b55SSascha Wildner 	KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId,
47435878b55SSascha Wildner 			 channelNum));
47535878b55SSascha Wildner 
47635878b55SSascha Wildner 
47735878b55SSascha Wildner 	/* Software reset channel */
47835878b55SSascha Wildner 	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
47935878b55SSascha Wildner 	{
48035878b55SSascha Wildner 		MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n",
48135878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channelNum);
48235878b55SSascha Wildner 		return -1;
48335878b55SSascha Wildner 	}
48435878b55SSascha Wildner 
48535878b55SSascha Wildner 	/* Hardware reset channel */
48635878b55SSascha Wildner 	if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
48735878b55SSascha Wildner 	{
48835878b55SSascha Wildner 		/* If failed, try again - this is when trying to hardreset a channel */
48935878b55SSascha Wildner 		/* when drive is just spinning up */
49035878b55SSascha Wildner 		StallExec(5000000); /* wait 5 sec before trying again */
49135878b55SSascha Wildner 		if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
49235878b55SSascha Wildner 		{
49335878b55SSascha Wildner 			MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n",
49435878b55SSascha Wildner 					 pMvSataAdapter->adapterId, channelNum);
49535878b55SSascha Wildner 			return -1;
49635878b55SSascha Wildner 		}
49735878b55SSascha Wildner 	}
49835878b55SSascha Wildner 
49935878b55SSascha Wildner 	/* identify device*/
50035878b55SSascha Wildner 	if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE)
50135878b55SSascha Wildner 	{
50235878b55SSascha Wildner 		MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n"
50335878b55SSascha Wildner 				 , pMvSataAdapter->adapterId, channelNum);
50435878b55SSascha Wildner 		return -1;
50535878b55SSascha Wildner 	}
50635878b55SSascha Wildner 	if (hptmv_parse_identify_results(pMvSataChannel))
50735878b55SSascha Wildner 	{
50835878b55SSascha Wildner 		MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n"
50935878b55SSascha Wildner 				 , pMvSataAdapter->adapterId, channelNum);
51035878b55SSascha Wildner 		return -1;
51135878b55SSascha Wildner 	}
51235878b55SSascha Wildner 
51335878b55SSascha Wildner 	/* mvStorageDevATASetFeatures */
51435878b55SSascha Wildner 	/* Disable 8 bit PIO in case CFA enabled */
51535878b55SSascha Wildner 	if (pMvSataChannel->identifyDevice[86] & 4)
51635878b55SSascha Wildner 	{
51735878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n",
51835878b55SSascha Wildner 				  pMvSataAdapter->adapterId));
51935878b55SSascha Wildner 		if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
52035878b55SSascha Wildner 									   MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0,
52135878b55SSascha Wildner 									   0, 0, 0) == MV_FALSE)
52235878b55SSascha Wildner 		{
52335878b55SSascha Wildner 			MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures"
52435878b55SSascha Wildner 					 " failed\n", pMvSataAdapter->adapterId, channelNum);
52535878b55SSascha Wildner 			return -1;
52635878b55SSascha Wildner 		}
52735878b55SSascha Wildner 	}
52835878b55SSascha Wildner 	/* Write cache */
52935878b55SSascha Wildner #ifdef ENABLE_WRITE_CACHE
53035878b55SSascha Wildner 	if (pMvSataChannel->identifyDevice[82] & 0x20)
53135878b55SSascha Wildner 	{
53235878b55SSascha Wildner 		if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */
53335878b55SSascha Wildner 		{
53435878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
53535878b55SSascha Wildner 										   MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0,
53635878b55SSascha Wildner 										   0, 0, 0) == MV_FALSE)
53735878b55SSascha Wildner 			{
53835878b55SSascha Wildner 				MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
53935878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelNum);
54035878b55SSascha Wildner 				return -1;
54135878b55SSascha Wildner 			}
54235878b55SSascha Wildner 		}
54335878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n",
54435878b55SSascha Wildner 				  pMvSataAdapter->adapterId, channelNum));
54535878b55SSascha Wildner 	}
54635878b55SSascha Wildner 	else
54735878b55SSascha Wildner 	{
54835878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n",
54935878b55SSascha Wildner 				  pMvSataAdapter->adapterId, channelNum));
55035878b55SSascha Wildner 	}
55135878b55SSascha Wildner #else /* disable write cache */
55235878b55SSascha Wildner 	{
55335878b55SSascha Wildner 		if (pMvSataChannel->identifyDevice[85] & 0x20)
55435878b55SSascha Wildner 		{
55535878b55SSascha Wildner 			KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n",
55635878b55SSascha Wildner 					  pMvSataAdapter->adapterId, channelNum));
55735878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
55835878b55SSascha Wildner 										   MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0,
55935878b55SSascha Wildner 										   0, 0, 0) == MV_FALSE)
56035878b55SSascha Wildner 			{
56135878b55SSascha Wildner 				MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
56235878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelNum);
56335878b55SSascha Wildner 				return -1;
56435878b55SSascha Wildner 			}
56535878b55SSascha Wildner 		}
56635878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n",
56735878b55SSascha Wildner 				  pMvSataAdapter->adapterId, channelNum));
56835878b55SSascha Wildner 	}
56935878b55SSascha Wildner #endif
57035878b55SSascha Wildner 
57135878b55SSascha Wildner 	/* Set transfer mode */
57235878b55SSascha Wildner 	KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n",
57335878b55SSascha Wildner 			  pMvSataAdapter->adapterId));
57435878b55SSascha Wildner 	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
57535878b55SSascha Wildner 								   MV_ATA_SET_FEATURES_TRANSFER,
57635878b55SSascha Wildner 								   MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) ==
57735878b55SSascha Wildner 		MV_FALSE)
57835878b55SSascha Wildner 	{
57935878b55SSascha Wildner 		MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
58035878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channelNum);
58135878b55SSascha Wildner 		return -1;
58235878b55SSascha Wildner 	}
58335878b55SSascha Wildner 
58435878b55SSascha Wildner 	if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1)
58535878b55SSascha Wildner 	{
58635878b55SSascha Wildner 		pioMode = MV_ATA_TRANSFER_PIO_4;
58735878b55SSascha Wildner 	}
58835878b55SSascha Wildner 	else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2)
58935878b55SSascha Wildner 	{
59035878b55SSascha Wildner 		pioMode = MV_ATA_TRANSFER_PIO_3;
59135878b55SSascha Wildner 	}
59235878b55SSascha Wildner 	else
59335878b55SSascha Wildner 	{
59435878b55SSascha Wildner 		MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n");
59535878b55SSascha Wildner 		pioMode = MV_ATA_TRANSFER_PIO_SLOW;
59635878b55SSascha Wildner 	}
59735878b55SSascha Wildner 
59835878b55SSascha Wildner 	KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n",
59935878b55SSascha Wildner 			  pMvSataAdapter->adapterId));
60035878b55SSascha Wildner 	pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode;
60135878b55SSascha Wildner 	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
60235878b55SSascha Wildner 								   MV_ATA_SET_FEATURES_TRANSFER,
60335878b55SSascha Wildner 								   pioMode, 0, 0, 0) == MV_FALSE)
60435878b55SSascha Wildner 	{
60535878b55SSascha Wildner 		MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
60635878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channelNum);
60735878b55SSascha Wildner 		return -1;
60835878b55SSascha Wildner 	}
60935878b55SSascha Wildner 
61035878b55SSascha Wildner 	udmaMode = MV_ATA_TRANSFER_UDMA_0;
61135878b55SSascha Wildner 	if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40)
61235878b55SSascha Wildner 	{
61335878b55SSascha Wildner 		udmaMode =  MV_ATA_TRANSFER_UDMA_6;
61435878b55SSascha Wildner 	}
61535878b55SSascha Wildner 	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20)
61635878b55SSascha Wildner 	{
61735878b55SSascha Wildner 		udmaMode =  MV_ATA_TRANSFER_UDMA_5;
61835878b55SSascha Wildner 	}
61935878b55SSascha Wildner 	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10)
62035878b55SSascha Wildner 	{
62135878b55SSascha Wildner 		udmaMode =  MV_ATA_TRANSFER_UDMA_4;
62235878b55SSascha Wildner 	}
62335878b55SSascha Wildner 	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8)
62435878b55SSascha Wildner 	{
62535878b55SSascha Wildner 		udmaMode =  MV_ATA_TRANSFER_UDMA_3;
62635878b55SSascha Wildner 	}
62735878b55SSascha Wildner 	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4)
62835878b55SSascha Wildner 	{
62935878b55SSascha Wildner 		udmaMode =  MV_ATA_TRANSFER_UDMA_2;
63035878b55SSascha Wildner 	}
63135878b55SSascha Wildner 
63235878b55SSascha Wildner 	KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n",
63335878b55SSascha Wildner 			  pMvSataAdapter->adapterId, udmaMode & 0xf));
63435878b55SSascha Wildner 	pChannelInfo->maxUltraDmaModeSupported = udmaMode;
63535878b55SSascha Wildner 
63635878b55SSascha Wildner 	/*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
63735878b55SSascha Wildner 								   MV_ATA_SET_FEATURES_TRANSFER, udmaMode,
63835878b55SSascha Wildner 								   0, 0, 0) == MV_FALSE)
63935878b55SSascha Wildner 	{
64035878b55SSascha Wildner 		MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
64135878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channelNum);
64235878b55SSascha Wildner 		return -1;
64335878b55SSascha Wildner 	}*/
64435878b55SSascha Wildner 	if (pChannelInfo->maxUltraDmaModeSupported == 0xFF)
64535878b55SSascha Wildner 		return TRUE;
64635878b55SSascha Wildner 	else
64735878b55SSascha Wildner 		do
64835878b55SSascha Wildner 		{
64935878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
65035878b55SSascha Wildner 								   MV_ATA_SET_FEATURES_TRANSFER,
65135878b55SSascha Wildner 								   pChannelInfo->maxUltraDmaModeSupported,
65235878b55SSascha Wildner 								   0, 0, 0) == MV_FALSE)
65335878b55SSascha Wildner 			{
65435878b55SSascha Wildner 				if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0)
65535878b55SSascha Wildner 				{
65635878b55SSascha Wildner 					if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
65735878b55SSascha Wildner 					{
65835878b55SSascha Wildner 						MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress,
65935878b55SSascha Wildner 										  pMvSataChannel->eDmaRegsOffset +
66035878b55SSascha Wildner 										  0x11c, /* command reg */
66135878b55SSascha Wildner 										  MV_ATA_COMMAND_IDLE_IMMEDIATE);
66235878b55SSascha Wildner 						mvMicroSecondsDelay(10000);
66335878b55SSascha Wildner 						mvSataChannelHardReset(pMvSataAdapter, channelNum);
66435878b55SSascha Wildner 						if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
66535878b55SSascha Wildner 							return FALSE;
66635878b55SSascha Wildner 					}
66735878b55SSascha Wildner 					if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
66835878b55SSascha Wildner 						return FALSE;
66935878b55SSascha Wildner 					pChannelInfo->maxUltraDmaModeSupported--;
67035878b55SSascha Wildner 					continue;
67135878b55SSascha Wildner 				}
67235878b55SSascha Wildner 				else   return FALSE;
67335878b55SSascha Wildner 			}
67435878b55SSascha Wildner 			break;
67535878b55SSascha Wildner 		}while (1);
67635878b55SSascha Wildner 
67735878b55SSascha Wildner 	/* Read look ahead */
67835878b55SSascha Wildner #ifdef ENABLE_READ_AHEAD
67935878b55SSascha Wildner 	if (pMvSataChannel->identifyDevice[82] & 0x40)
68035878b55SSascha Wildner 	{
68135878b55SSascha Wildner 		if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */
68235878b55SSascha Wildner 		{
68335878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
68435878b55SSascha Wildner 										   MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0,
68535878b55SSascha Wildner 										   0, 0) == MV_FALSE)
68635878b55SSascha Wildner 			{
68735878b55SSascha Wildner 				MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
68835878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelNum);
68935878b55SSascha Wildner 				return -1;
69035878b55SSascha Wildner 			}
69135878b55SSascha Wildner 		}
69235878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n",
69335878b55SSascha Wildner 				  pMvSataAdapter->adapterId, channelNum));
69435878b55SSascha Wildner 	}
69535878b55SSascha Wildner 	else
69635878b55SSascha Wildner 	{
69735878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n",
69835878b55SSascha Wildner 				  pMvSataAdapter->adapterId, channelNum));
69935878b55SSascha Wildner 	}
70035878b55SSascha Wildner #else
70135878b55SSascha Wildner 	{
70235878b55SSascha Wildner 		if (pMvSataChannel->identifyDevice[86] & 0x20)
70335878b55SSascha Wildner 		{
70435878b55SSascha Wildner 			KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n",
70535878b55SSascha Wildner 					  pMvSataAdapter->adapterId, channelNum));
70635878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
70735878b55SSascha Wildner 										   MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0,
70835878b55SSascha Wildner 										   0, 0) == MV_FALSE)
70935878b55SSascha Wildner 			{
71035878b55SSascha Wildner 				MV_ERROR("RR18xx [%d]:channel %d:  ATA Set Features failed\n",
71135878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelNum);
71235878b55SSascha Wildner 				return -1;
71335878b55SSascha Wildner 			}
71435878b55SSascha Wildner 		}
71535878b55SSascha Wildner 		KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n",
71635878b55SSascha Wildner 				  pMvSataAdapter->adapterId, channelNum));
71735878b55SSascha Wildner 	}
71835878b55SSascha Wildner #endif
71935878b55SSascha Wildner 
72035878b55SSascha Wildner 
72135878b55SSascha Wildner 	{
72235878b55SSascha Wildner 		KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n",
72335878b55SSascha Wildner 				  pMvSataAdapter->adapterId,
72435878b55SSascha Wildner 				  channelNum));
72535878b55SSascha Wildner 		if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum,
72635878b55SSascha Wildner 								 MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE)
72735878b55SSascha Wildner 		{
72835878b55SSascha Wildner 			MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n",
72935878b55SSascha Wildner 					 pMvSataAdapter->adapterId, channelNum);
73035878b55SSascha Wildner 			return -1;
73135878b55SSascha Wildner 		}
73235878b55SSascha Wildner 	}
73335878b55SSascha Wildner 	/* Enable EDMA */
73435878b55SSascha Wildner 	if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE)
73535878b55SSascha Wildner 	{
73635878b55SSascha Wildner 		MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n",
73735878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channelNum);
73835878b55SSascha Wildner 		return -1;
73935878b55SSascha Wildner 	}
74035878b55SSascha Wildner 	MV_ERROR("RR18xx [%d,%d]: channel started successfully\n",
74135878b55SSascha Wildner 			 pMvSataAdapter->adapterId, channelNum);
74235878b55SSascha Wildner 
74335878b55SSascha Wildner #ifndef FOR_DEMO
74435878b55SSascha Wildner 	set_fail_led(pMvSataAdapter, channelNum, 0);
74535878b55SSascha Wildner #endif
74635878b55SSascha Wildner 	return 0;
74735878b55SSascha Wildner }
74835878b55SSascha Wildner 
74935878b55SSascha Wildner static void
75035878b55SSascha Wildner hptmv_handle_event(void * data, int flag)
75135878b55SSascha Wildner {
75235878b55SSascha Wildner 	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)data;
75335878b55SSascha Wildner 	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
75435878b55SSascha Wildner 	MV_U8           channelIndex;
75535878b55SSascha Wildner 
75635878b55SSascha Wildner /*	mvOsSemTake(&pMvSataAdapter->semaphore); */
75735878b55SSascha Wildner 	for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
75835878b55SSascha Wildner 	{
75935878b55SSascha Wildner 		switch(pAdapter->sataEvents[channelIndex])
76035878b55SSascha Wildner 		{
76135878b55SSascha Wildner 			case SATA_EVENT_CHANNEL_CONNECTED:
76235878b55SSascha Wildner 				/* Handle only connects */
76335878b55SSascha Wildner 				if (flag == 1)
76435878b55SSascha Wildner 					break;
76535878b55SSascha Wildner 				KdPrint(("RR18xx [%d,%d]: new device connected\n",
76635878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelIndex));
76735878b55SSascha Wildner 				hptmv_init_channel(pAdapter, channelIndex);
76835878b55SSascha Wildner 				if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE)
76935878b55SSascha Wildner 				{
77035878b55SSascha Wildner 					MV_ERROR("RR18xx [%d,%d] Failed to configure\n",
77135878b55SSascha Wildner 							 pMvSataAdapter->adapterId, channelIndex);
77235878b55SSascha Wildner 					hptmv_free_channel(pAdapter, channelIndex);
77335878b55SSascha Wildner 				}
77435878b55SSascha Wildner 				else
77535878b55SSascha Wildner 				{
77635878b55SSascha Wildner 					/*mvSataChannelHardReset(pMvSataAdapter, channel);*/
77735878b55SSascha Wildner 					if (start_channel( pAdapter, channelIndex))
77835878b55SSascha Wildner 					{
77935878b55SSascha Wildner 						MV_ERROR("RR18xx [%d,%d]Failed to start channel\n",
78035878b55SSascha Wildner 								 pMvSataAdapter->adapterId, channelIndex);
78135878b55SSascha Wildner 						hptmv_free_channel(pAdapter, channelIndex);
78235878b55SSascha Wildner 					}
78335878b55SSascha Wildner 					else
78435878b55SSascha Wildner 					{
78535878b55SSascha Wildner 						device_change(pAdapter, channelIndex, TRUE);
78635878b55SSascha Wildner 					}
78735878b55SSascha Wildner 				}
78835878b55SSascha Wildner 				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
78935878b55SSascha Wildner 			   break;
79035878b55SSascha Wildner 
79135878b55SSascha Wildner 			case SATA_EVENT_CHANNEL_DISCONNECTED:
79235878b55SSascha Wildner 				/* Handle only disconnects */
79335878b55SSascha Wildner 				if (flag == 0)
79435878b55SSascha Wildner 					break;
79535878b55SSascha Wildner 				KdPrint(("RR18xx [%d,%d]: device disconnected\n",
79635878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelIndex));
79735878b55SSascha Wildner 					/* Flush pending commands */
79835878b55SSascha Wildner 				if(pMvSataAdapter->sataChannel[channelIndex])
79935878b55SSascha Wildner 				{
80035878b55SSascha Wildner 					_VBUS_INST(&pAdapter->VBus)
80135878b55SSascha Wildner 					mvSataFlushDmaQueue (pMvSataAdapter, channelIndex,
80235878b55SSascha Wildner 										 MV_FLUSH_TYPE_CALLBACK);
80335878b55SSascha Wildner 					CheckPendingCall(_VBUS_P0);
80435878b55SSascha Wildner 					mvSataRemoveChannel(pMvSataAdapter,channelIndex);
80535878b55SSascha Wildner 					hptmv_free_channel(pAdapter, channelIndex);
80635878b55SSascha Wildner 					pMvSataAdapter->sataChannel[channelIndex] = NULL;
80735878b55SSascha Wildner 					KdPrint(("RR18xx [%d,%d]: channel removed\n",
80835878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channelIndex));
80935878b55SSascha Wildner 					if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
81035878b55SSascha Wildner 						Check_Idle_Call(pAdapter);
81135878b55SSascha Wildner 				}
81235878b55SSascha Wildner 				else
81335878b55SSascha Wildner 				{
81435878b55SSascha Wildner 					KdPrint(("RR18xx [%d,%d]: channel already removed!!\n",
81535878b55SSascha Wildner 							 pMvSataAdapter->adapterId, channelIndex));
81635878b55SSascha Wildner 				}
81735878b55SSascha Wildner 				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
81835878b55SSascha Wildner 				break;
81935878b55SSascha Wildner 
82035878b55SSascha Wildner 			case SATA_EVENT_NO_CHANGE:
82135878b55SSascha Wildner 				break;
82235878b55SSascha Wildner 
82335878b55SSascha Wildner 			default:
82435878b55SSascha Wildner 				break;
82535878b55SSascha Wildner 		}
82635878b55SSascha Wildner 	}
82735878b55SSascha Wildner /*	mvOsSemRelease(&pMvSataAdapter->semaphore); */
82835878b55SSascha Wildner }
82935878b55SSascha Wildner 
83035878b55SSascha Wildner #define EVENT_CONNECT					1
83135878b55SSascha Wildner #define EVENT_DISCONNECT				0
83235878b55SSascha Wildner 
83335878b55SSascha Wildner static void
83435878b55SSascha Wildner hptmv_handle_event_connect(void *data)
83535878b55SSascha Wildner {
83635878b55SSascha Wildner   hptmv_handle_event (data, 0);
83735878b55SSascha Wildner }
83835878b55SSascha Wildner 
83935878b55SSascha Wildner static void
84035878b55SSascha Wildner hptmv_handle_event_disconnect(void *data)
84135878b55SSascha Wildner {
84235878b55SSascha Wildner   hptmv_handle_event (data, 1);
84335878b55SSascha Wildner }
84435878b55SSascha Wildner 
84535878b55SSascha Wildner static MV_BOOLEAN
84635878b55SSascha Wildner hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
84735878b55SSascha Wildner 								   MV_U32 param1, MV_U32 param2)
84835878b55SSascha Wildner {
84935878b55SSascha Wildner 	IAL_ADAPTER_T   *pAdapter = pMvSataAdapter->IALData;
85035878b55SSascha Wildner 
85135878b55SSascha Wildner 	switch (eventType)
85235878b55SSascha Wildner 	{
85335878b55SSascha Wildner 		case MV_EVENT_TYPE_SATA_CABLE:
85435878b55SSascha Wildner 			{
85535878b55SSascha Wildner 				MV_U8   channel = param2;
85635878b55SSascha Wildner 
85735878b55SSascha Wildner 				if (param1 == EVENT_CONNECT)
85835878b55SSascha Wildner 				{
85935878b55SSascha Wildner 					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED;
86035878b55SSascha Wildner 					KdPrint(("RR18xx [%d,%d]: device connected event received\n",
86135878b55SSascha Wildner 							 pMvSataAdapter->adapterId, channel));
86235878b55SSascha Wildner 					/* Delete previous timers (if multiple drives connected in the same time */
86335878b55SSascha Wildner 					callout_reset(&pAdapter->event_timer_connect, 10*hz, hptmv_handle_event_connect, pAdapter);
86435878b55SSascha Wildner 				}
86535878b55SSascha Wildner 				else if (param1 == EVENT_DISCONNECT)
86635878b55SSascha Wildner 				{
86735878b55SSascha Wildner 					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED;
86835878b55SSascha Wildner 					KdPrint(("RR18xx [%d,%d]: device disconnected event received \n",
86935878b55SSascha Wildner 							 pMvSataAdapter->adapterId, channel));
87035878b55SSascha Wildner 					device_change(pAdapter, channel, FALSE);
87135878b55SSascha Wildner 					/* Delete previous timers (if multiple drives disconnected in the same time */
87235878b55SSascha Wildner 					/* callout_reset(&pAdapter->event_timer_disconnect, 10*hz, hptmv_handle_event_disconnect, pAdapter); */
87335878b55SSascha Wildner 					/*It is not necessary to wait, handle it directly*/
87435878b55SSascha Wildner 					hptmv_handle_event_disconnect(pAdapter);
87535878b55SSascha Wildner 				}
87635878b55SSascha Wildner 				else
87735878b55SSascha Wildner 				{
87835878b55SSascha Wildner 
87935878b55SSascha Wildner 					MV_ERROR("RR18xx: illigal value for param1(%d) at "
88035878b55SSascha Wildner 							 "connect/disconect event, host=%d\n", param1,
88135878b55SSascha Wildner 							 pMvSataAdapter->adapterId );
88235878b55SSascha Wildner 
88335878b55SSascha Wildner 				}
88435878b55SSascha Wildner 			}
88535878b55SSascha Wildner 			break;
88635878b55SSascha Wildner 		case MV_EVENT_TYPE_ADAPTER_ERROR:
88735878b55SSascha Wildner 			KdPrint(("RR18xx: DEVICE error event received, pci cause "
88835878b55SSascha Wildner 					  "reg=%x,  don't how to handle this\n", param1));
88935878b55SSascha Wildner 			return MV_TRUE;
89035878b55SSascha Wildner 		default:
89135878b55SSascha Wildner 			MV_ERROR("RR18xx[%d]: unknown event type (%d)\n",
89235878b55SSascha Wildner 					 pMvSataAdapter->adapterId, eventType);
89335878b55SSascha Wildner 			return MV_FALSE;
89435878b55SSascha Wildner 	}
89535878b55SSascha Wildner 	return MV_TRUE;
89635878b55SSascha Wildner }
89735878b55SSascha Wildner 
89835878b55SSascha Wildner static int
89935878b55SSascha Wildner hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
90035878b55SSascha Wildner {
90135878b55SSascha Wildner 	pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE,
90235878b55SSascha Wildner 			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
90335878b55SSascha Wildner 	if (pAdapter->requestsArrayBaseAddr == NULL)
90435878b55SSascha Wildner 	{
90535878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request"
90635878b55SSascha Wildner 				 " queues\n", pAdapter->mvSataAdapter.adapterId);
90735878b55SSascha Wildner 		return -1;
90835878b55SSascha Wildner 	}
90935878b55SSascha Wildner 	pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr);
91035878b55SSascha Wildner 	pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr;
91135878b55SSascha Wildner 	pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
91235878b55SSascha Wildner 	pAdapter->requestsArrayBaseAlignedAddr  = (MV_U8 *)
91335878b55SSascha Wildner 		(((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1));
91435878b55SSascha Wildner 	pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr;
91535878b55SSascha Wildner 	pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
91635878b55SSascha Wildner 	pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1);
91735878b55SSascha Wildner 
91835878b55SSascha Wildner 	if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) !=
91935878b55SSascha Wildner 		(pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr))
92035878b55SSascha Wildner 	{
92135878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n",
92235878b55SSascha Wildner 				 pAdapter->mvSataAdapter.adapterId);
92335878b55SSascha Wildner 		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
92435878b55SSascha Wildner 		return -1;
92535878b55SSascha Wildner 	}
92635878b55SSascha Wildner 	/* response queues */
92735878b55SSascha Wildner 	pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE,
92835878b55SSascha Wildner 			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
92935878b55SSascha Wildner 	if (pAdapter->responsesArrayBaseAddr == NULL)
93035878b55SSascha Wildner 	{
93135878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response"
93235878b55SSascha Wildner 				 " queues\n", pAdapter->mvSataAdapter.adapterId);
93335878b55SSascha Wildner 		contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
93435878b55SSascha Wildner 		return -1;
93535878b55SSascha Wildner 	}
93635878b55SSascha Wildner 	pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr);
93735878b55SSascha Wildner 	pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr;
93835878b55SSascha Wildner 	pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
93935878b55SSascha Wildner 	pAdapter->responsesArrayBaseAlignedAddr  = (MV_U8 *)
94035878b55SSascha Wildner 		(((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1));
94135878b55SSascha Wildner 	pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr;
94235878b55SSascha Wildner 	pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
94335878b55SSascha Wildner 	pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1);
94435878b55SSascha Wildner 
94535878b55SSascha Wildner 	if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) !=
94635878b55SSascha Wildner 		(pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr))
94735878b55SSascha Wildner 	{
94835878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: Error in Response Quueues Alignment\n",
94935878b55SSascha Wildner 				 pAdapter->mvSataAdapter.adapterId);
95035878b55SSascha Wildner 		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
95135878b55SSascha Wildner 		contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
95235878b55SSascha Wildner 		return -1;
95335878b55SSascha Wildner 	}
95435878b55SSascha Wildner 	return 0;
95535878b55SSascha Wildner }
95635878b55SSascha Wildner 
95735878b55SSascha Wildner static void
95835878b55SSascha Wildner hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter)
95935878b55SSascha Wildner {
96035878b55SSascha Wildner 	contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
96135878b55SSascha Wildner 	contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
96235878b55SSascha Wildner }
96335878b55SSascha Wildner 
96435878b55SSascha Wildner static PVOID
96535878b55SSascha Wildner AllocatePRDTable(IAL_ADAPTER_T *pAdapter)
96635878b55SSascha Wildner {
96735878b55SSascha Wildner 	PVOID ret;
96835878b55SSascha Wildner 	if (pAdapter->pFreePRDLink) {
96935878b55SSascha Wildner 		KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink));
97035878b55SSascha Wildner 		ret = pAdapter->pFreePRDLink;
97135878b55SSascha Wildner 		pAdapter->pFreePRDLink = *(void**)ret;
97235878b55SSascha Wildner 		return ret;
97335878b55SSascha Wildner 	}
97435878b55SSascha Wildner 	return NULL;
97535878b55SSascha Wildner }
97635878b55SSascha Wildner 
97735878b55SSascha Wildner static void
97835878b55SSascha Wildner FreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable)
97935878b55SSascha Wildner {
98035878b55SSascha Wildner 	*(void**)PRDTable = pAdapter->pFreePRDLink;
98135878b55SSascha Wildner 	pAdapter->pFreePRDLink = PRDTable;
98235878b55SSascha Wildner }
98335878b55SSascha Wildner 
98435878b55SSascha Wildner extern PVDevice fGetFirstChild(PVDevice pLogical);
98535878b55SSascha Wildner extern void fResetBootMark(PVDevice pLogical);
98635878b55SSascha Wildner static void
98735878b55SSascha Wildner fRegisterVdevice(IAL_ADAPTER_T *pAdapter)
98835878b55SSascha Wildner {
98935878b55SSascha Wildner 	PVDevice pPhysical, pLogical;
99035878b55SSascha Wildner 	PVBus  pVBus;
99135878b55SSascha Wildner 	int i,j;
99235878b55SSascha Wildner 
99335878b55SSascha Wildner 	for(i=0;i<MV_SATA_CHANNELS_NUM;i++) {
99435878b55SSascha Wildner 		pPhysical = &(pAdapter->VDevices[i]);
99535878b55SSascha Wildner 		pLogical = pPhysical;
99635878b55SSascha Wildner 		while (pLogical->pParent) pLogical = pLogical->pParent;
99735878b55SSascha Wildner 		if (pLogical->vf_online==0) {
99835878b55SSascha Wildner 			pPhysical->vf_bootmark = pLogical->vf_bootmark = 0;
99935878b55SSascha Wildner 			continue;
100035878b55SSascha Wildner 		}
100135878b55SSascha Wildner 		if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical))
100235878b55SSascha Wildner 			continue;
100335878b55SSascha Wildner 
100435878b55SSascha Wildner 		pVBus = &pAdapter->VBus;
100535878b55SSascha Wildner 		if(pVBus)
100635878b55SSascha Wildner 		{
100735878b55SSascha Wildner 			j=0;
100835878b55SSascha Wildner 			while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++;
100935878b55SSascha Wildner 			if(j<MAX_VDEVICE_PER_VBUS){
101035878b55SSascha Wildner 				pVBus->pVDevice[j] = pLogical;
101135878b55SSascha Wildner 				pLogical->pVBus = pVBus;
101235878b55SSascha Wildner 
101335878b55SSascha Wildner 				if (j>0 && pLogical->vf_bootmark) {
101435878b55SSascha Wildner 					if (pVBus->pVDevice[0]->vf_bootmark) {
101535878b55SSascha Wildner 						fResetBootMark(pLogical);
101635878b55SSascha Wildner 					}
101735878b55SSascha Wildner 					else {
101835878b55SSascha Wildner 						do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j);
101935878b55SSascha Wildner 						pVBus->pVDevice[0] = pLogical;
102035878b55SSascha Wildner 					}
102135878b55SSascha Wildner 				}
102235878b55SSascha Wildner 			}
102335878b55SSascha Wildner 		}
102435878b55SSascha Wildner 	}
102535878b55SSascha Wildner }
102635878b55SSascha Wildner 
102735878b55SSascha Wildner PVDevice
102835878b55SSascha Wildner GetSpareDisk(_VBUS_ARG PVDevice pArray)
102935878b55SSascha Wildner {
103035878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt;
103135878b55SSascha Wildner 	LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1);
103235878b55SSascha Wildner 	LBA_T thiscap, maxcap = MAX_LBA_T;
103335878b55SSascha Wildner 	PVDevice pVDevice, pFind = NULL;
103435878b55SSascha Wildner 	int i;
103535878b55SSascha Wildner 
103635878b55SSascha Wildner 	for(i=0;i<MV_SATA_CHANNELS_NUM;i++)
103735878b55SSascha Wildner 	{
103835878b55SSascha Wildner 		pVDevice = &pAdapter->VDevices[i];
103935878b55SSascha Wildner 		if(!pVDevice)
104035878b55SSascha Wildner 			continue;
104135878b55SSascha Wildner 		thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity;
104235878b55SSascha Wildner 		/* find the smallest usable spare disk */
104335878b55SSascha Wildner 		if (pVDevice->VDeviceType==VD_SPARE &&
104435878b55SSascha Wildner 			pVDevice->u.disk.df_on_line &&
104535878b55SSascha Wildner 			thiscap < maxcap &&
104635878b55SSascha Wildner 			thiscap >= capacity)
104735878b55SSascha Wildner 		{
104835878b55SSascha Wildner 				maxcap = pVDevice->VDeviceCapacity;
104935878b55SSascha Wildner 				pFind = pVDevice;
105035878b55SSascha Wildner 		}
105135878b55SSascha Wildner 	}
105235878b55SSascha Wildner 	return pFind;
105335878b55SSascha Wildner }
105435878b55SSascha Wildner 
105535878b55SSascha Wildner /******************************************************************
105635878b55SSascha Wildner  * IO ATA Command
105735878b55SSascha Wildner  *******************************************************************/
105835878b55SSascha Wildner int HPTLIBAPI
105935878b55SSascha Wildner fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer)
106035878b55SSascha Wildner {
106135878b55SSascha Wildner 	return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer);
106235878b55SSascha Wildner }
106335878b55SSascha Wildner 
106435878b55SSascha Wildner void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode)
106535878b55SSascha Wildner {
106635878b55SSascha Wildner 	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
106735878b55SSascha Wildner 	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
106835878b55SSascha Wildner 	MV_U8 channelIndex = pSataChannel->channelNumber;
106935878b55SSascha Wildner 	UCHAR mvMode;
107035878b55SSascha Wildner 	/* 508x don't use MW-DMA? */
107135878b55SSascha Wildner 	if (NewMode>4 && NewMode<8) NewMode = 4;
107235878b55SSascha Wildner 	pDev->bDeModeSetting = NewMode;
107335878b55SSascha Wildner 	if (NewMode<=4)
107435878b55SSascha Wildner 		mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode;
107535878b55SSascha Wildner 	else
107635878b55SSascha Wildner 		mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8);
107735878b55SSascha Wildner 
107835878b55SSascha Wildner 	/*To fix 88i8030 bug*/
107935878b55SSascha Wildner 	if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4)
108035878b55SSascha Wildner 		mvMode = MV_ATA_TRANSFER_UDMA_0;
108135878b55SSascha Wildner 
108235878b55SSascha Wildner 	mvSataDisableChannelDma(pSataAdapter, channelIndex);
108335878b55SSascha Wildner 	/* Flush pending commands */
108435878b55SSascha Wildner 	mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE);
108535878b55SSascha Wildner 
108635878b55SSascha Wildner 	if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
108735878b55SSascha Wildner 								   MV_ATA_SET_FEATURES_TRANSFER,
108835878b55SSascha Wildner 								   mvMode, 0, 0, 0) == MV_FALSE)
108935878b55SSascha Wildner 	{
109035878b55SSascha Wildner 		KdPrint(("channel %d: Set Features failed\n", channelIndex));
109135878b55SSascha Wildner 	}
109235878b55SSascha Wildner 	/* Enable EDMA */
109335878b55SSascha Wildner 	if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE)
109435878b55SSascha Wildner 		KdPrint(("Failed to enable DMA, channel=%d", channelIndex));
109535878b55SSascha Wildner }
109635878b55SSascha Wildner 
109735878b55SSascha Wildner int HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth)
109835878b55SSascha Wildner {
109935878b55SSascha Wildner 	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
110035878b55SSascha Wildner 	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
110135878b55SSascha Wildner 	MV_U8 channelIndex = pSataChannel->channelNumber;
110235878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
110335878b55SSascha Wildner 	MV_CHANNEL		*channelInfo = &(pAdapter->mvChannel[channelIndex]);
110435878b55SSascha Wildner 	int dmaActive = pSataChannel->queueCommandsEnabled;
110535878b55SSascha Wildner 	int ret = 0;
110635878b55SSascha Wildner 
110735878b55SSascha Wildner 	if (dmaActive) {
110835878b55SSascha Wildner 		mvSataDisableChannelDma(pSataAdapter, channelIndex);
110935878b55SSascha Wildner 		mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
111035878b55SSascha Wildner 	}
111135878b55SSascha Wildner 
111235878b55SSascha Wildner 	if (enable) {
111335878b55SSascha Wildner 		if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED &&
111435878b55SSascha Wildner 			(pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) {
111535878b55SSascha Wildner 			UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1;
111635878b55SSascha Wildner 			channelInfo->queueDepth = (depth==32)? 31 : depth;
111735878b55SSascha Wildner 			mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth);
111835878b55SSascha Wildner 			ret = 1;
111935878b55SSascha Wildner 		}
112035878b55SSascha Wildner 	}
112135878b55SSascha Wildner 	else
112235878b55SSascha Wildner 	{
112335878b55SSascha Wildner 		if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) {
112435878b55SSascha Wildner 			channelInfo->queueDepth = 2;
112535878b55SSascha Wildner 			mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0);
112635878b55SSascha Wildner 			ret = 1;
112735878b55SSascha Wildner 		}
112835878b55SSascha Wildner 	}
112935878b55SSascha Wildner 
113035878b55SSascha Wildner 	if (dmaActive)
113135878b55SSascha Wildner 		mvSataEnableChannelDma(pSataAdapter,channelIndex);
113235878b55SSascha Wildner 	return ret;
113335878b55SSascha Wildner }
113435878b55SSascha Wildner 
113535878b55SSascha Wildner int HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth)
113635878b55SSascha Wildner {
113735878b55SSascha Wildner 	return 0;
113835878b55SSascha Wildner }
113935878b55SSascha Wildner 
114035878b55SSascha Wildner int HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable)
114135878b55SSascha Wildner {
114235878b55SSascha Wildner 	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
114335878b55SSascha Wildner 	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
114435878b55SSascha Wildner 	MV_U8 channelIndex = pSataChannel->channelNumber;
114535878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
114635878b55SSascha Wildner 	MV_CHANNEL		*channelInfo = &(pAdapter->mvChannel[channelIndex]);
114735878b55SSascha Wildner 	int dmaActive = pSataChannel->queueCommandsEnabled;
114835878b55SSascha Wildner 	int ret = 0;
114935878b55SSascha Wildner 
115035878b55SSascha Wildner 	if (dmaActive) {
115135878b55SSascha Wildner 		mvSataDisableChannelDma(pSataAdapter, channelIndex);
115235878b55SSascha Wildner 		mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
115335878b55SSascha Wildner 	}
115435878b55SSascha Wildner 
115535878b55SSascha Wildner 	if ((pSataChannel->identifyDevice[82] & (0x20))) {
115635878b55SSascha Wildner 		if (enable) {
115735878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
115835878b55SSascha Wildner 				MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0))
115935878b55SSascha Wildner 			{
116035878b55SSascha Wildner 				channelInfo->writeCacheEnabled = MV_TRUE;
116135878b55SSascha Wildner 				ret = 1;
116235878b55SSascha Wildner 			}
116335878b55SSascha Wildner 		}
116435878b55SSascha Wildner 		else {
116535878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
116635878b55SSascha Wildner 				MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0))
116735878b55SSascha Wildner 			{
116835878b55SSascha Wildner 				channelInfo->writeCacheEnabled = MV_FALSE;
116935878b55SSascha Wildner 				ret = 1;
117035878b55SSascha Wildner 			}
117135878b55SSascha Wildner 		}
117235878b55SSascha Wildner 	}
117335878b55SSascha Wildner 
117435878b55SSascha Wildner 	if (dmaActive)
117535878b55SSascha Wildner 		mvSataEnableChannelDma(pSataAdapter,channelIndex);
117635878b55SSascha Wildner 	return ret;
117735878b55SSascha Wildner }
117835878b55SSascha Wildner 
117935878b55SSascha Wildner int HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable)
118035878b55SSascha Wildner {
118135878b55SSascha Wildner 	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
118235878b55SSascha Wildner 	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
118335878b55SSascha Wildner 	MV_U8 channelIndex = pSataChannel->channelNumber;
118435878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
118535878b55SSascha Wildner 	MV_CHANNEL		*channelInfo = &(pAdapter->mvChannel[channelIndex]);
118635878b55SSascha Wildner 	int dmaActive = pSataChannel->queueCommandsEnabled;
118735878b55SSascha Wildner 	int ret = 0;
118835878b55SSascha Wildner 
118935878b55SSascha Wildner 	if (dmaActive) {
119035878b55SSascha Wildner 		mvSataDisableChannelDma(pSataAdapter, channelIndex);
119135878b55SSascha Wildner 		mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
119235878b55SSascha Wildner 	}
119335878b55SSascha Wildner 
119435878b55SSascha Wildner 	if ((pSataChannel->identifyDevice[82] & (0x40))) {
119535878b55SSascha Wildner 		if (enable) {
119635878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
119735878b55SSascha Wildner 				MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0))
119835878b55SSascha Wildner 			{
119935878b55SSascha Wildner 				channelInfo->readAheadEnabled = MV_TRUE;
120035878b55SSascha Wildner 				ret = 1;
120135878b55SSascha Wildner 			}
120235878b55SSascha Wildner 		}
120335878b55SSascha Wildner 		else {
120435878b55SSascha Wildner 			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
120535878b55SSascha Wildner 				MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0))
120635878b55SSascha Wildner 			{
120735878b55SSascha Wildner 				channelInfo->readAheadEnabled = MV_FALSE;
120835878b55SSascha Wildner 				ret = 1;
120935878b55SSascha Wildner 			}
121035878b55SSascha Wildner 		}
121135878b55SSascha Wildner 	}
121235878b55SSascha Wildner 
121335878b55SSascha Wildner 	if (dmaActive)
121435878b55SSascha Wildner 		mvSataEnableChannelDma(pSataAdapter,channelIndex);
121535878b55SSascha Wildner 	return ret;
121635878b55SSascha Wildner }
121735878b55SSascha Wildner 
121835878b55SSascha Wildner #ifdef SUPPORT_ARRAY
121935878b55SSascha Wildner #define IdeRegisterVDevice  fCheckArray
122035878b55SSascha Wildner #else
122135878b55SSascha Wildner void
122235878b55SSascha Wildner IdeRegisterVDevice(PDevice pDev)
122335878b55SSascha Wildner {
122435878b55SSascha Wildner 	PVDevice pVDev = Map2pVDevice(pDev);
122535878b55SSascha Wildner 
122635878b55SSascha Wildner 	pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI :
122735878b55SSascha Wildner 						 pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
122835878b55SSascha Wildner 	pVDev->vf_online = 1;
122935878b55SSascha Wildner 	pVDev->VDeviceCapacity = pDev->dDeRealCapacity;
123035878b55SSascha Wildner 	pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
123135878b55SSascha Wildner 	pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
123235878b55SSascha Wildner }
123335878b55SSascha Wildner #endif
123435878b55SSascha Wildner 
123535878b55SSascha Wildner static __inline PBUS_DMAMAP
123635878b55SSascha Wildner dmamap_get(struct IALAdapter * pAdapter)
123735878b55SSascha Wildner {
123835878b55SSascha Wildner 	PBUS_DMAMAP	p = pAdapter->pbus_dmamap_list;
123935878b55SSascha Wildner 	if (p)
124035878b55SSascha Wildner 		pAdapter->pbus_dmamap_list = p-> next;
124135878b55SSascha Wildner 	return p;
124235878b55SSascha Wildner }
124335878b55SSascha Wildner 
124435878b55SSascha Wildner static __inline void
124535878b55SSascha Wildner dmamap_put(PBUS_DMAMAP p)
124635878b55SSascha Wildner {
124735878b55SSascha Wildner 	p->next = p->pAdapter->pbus_dmamap_list;
124835878b55SSascha Wildner 	p->pAdapter->pbus_dmamap_list = p;
124935878b55SSascha Wildner }
125035878b55SSascha Wildner 
125135878b55SSascha Wildner /*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/
125235878b55SSascha Wildner #define override_kernel_driver()
125335878b55SSascha Wildner 
125435878b55SSascha Wildner static void hpt_init(void *dummy)
125535878b55SSascha Wildner {
125635878b55SSascha Wildner 	override_kernel_driver();
125735878b55SSascha Wildner 	lockinit(&driver_lock, "hptsleeplock", 0, LK_CANRECURSE);
125835878b55SSascha Wildner }
125935878b55SSascha Wildner SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL);
126035878b55SSascha Wildner 
126135878b55SSascha Wildner static int num_adapters = 0;
126235878b55SSascha Wildner static int
126335878b55SSascha Wildner init_adapter(IAL_ADAPTER_T *pAdapter)
126435878b55SSascha Wildner {
126535878b55SSascha Wildner 	PVBus _vbus_p = &pAdapter->VBus;
126635878b55SSascha Wildner 	MV_SATA_ADAPTER *pMvSataAdapter;
126735878b55SSascha Wildner 	int i, channel, rid;
126835878b55SSascha Wildner 
126935878b55SSascha Wildner 	PVDevice pVDev;
127035878b55SSascha Wildner 
1271c898d682SSascha Wildner 	lock_driver();
127235878b55SSascha Wildner 
127335878b55SSascha Wildner 	pAdapter->next = 0;
127435878b55SSascha Wildner 
12754090d6ffSSascha Wildner 	if(gIal_Adapter == NULL){
127635878b55SSascha Wildner 		gIal_Adapter = pAdapter;
127735878b55SSascha Wildner 		pCurAdapter = gIal_Adapter;
127835878b55SSascha Wildner 	}
127935878b55SSascha Wildner 	else {
128035878b55SSascha Wildner 		pCurAdapter->next = pAdapter;
128135878b55SSascha Wildner 		pCurAdapter = pAdapter;
128235878b55SSascha Wildner 	}
128335878b55SSascha Wildner 
128435878b55SSascha Wildner 	pAdapter->outstandingCommands = 0;
128535878b55SSascha Wildner 
128635878b55SSascha Wildner 	pMvSataAdapter = &(pAdapter->mvSataAdapter);
128735878b55SSascha Wildner 	_vbus_p->OsExt = (void *)pAdapter;
128835878b55SSascha Wildner 	pMvSataAdapter->IALData = pAdapter;
128935878b55SSascha Wildner 
129035878b55SSascha Wildner 	if (bus_dma_tag_create(NULL,/* parent */
129135878b55SSascha Wildner 			4,	/* alignment */
129235878b55SSascha Wildner 			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
129335878b55SSascha Wildner 			BUS_SPACE_MAXADDR,	/* lowaddr */
129435878b55SSascha Wildner 			BUS_SPACE_MAXADDR,	/* highaddr */
129535878b55SSascha Wildner 			NULL, NULL, 		/* filter, filterarg */
129635878b55SSascha Wildner 			PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */
129735878b55SSascha Wildner 			MAX_SG_DESCRIPTORS, /* nsegments */
129835878b55SSascha Wildner 			0x10000,	/* maxsegsize */
129935878b55SSascha Wildner 			BUS_DMA_WAITOK, 	/* flags */
130035878b55SSascha Wildner 			&pAdapter->io_dma_parent /* tag */))
130135878b55SSascha Wildner 		{
130235878b55SSascha Wildner 			return ENXIO;
130335878b55SSascha Wildner 	}
130435878b55SSascha Wildner 
130535878b55SSascha Wildner 
130635878b55SSascha Wildner 	if (hptmv_allocate_edma_queues(pAdapter))
130735878b55SSascha Wildner 	{
130835878b55SSascha Wildner 		MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n");
1309c898d682SSascha Wildner 		unlock_driver();
131035878b55SSascha Wildner 		return ENOMEM;
131135878b55SSascha Wildner 	}
131235878b55SSascha Wildner 
131335878b55SSascha Wildner 	/* also map EPROM address */
131435878b55SSascha Wildner 	rid = 0x10;
131535878b55SSascha Wildner 	if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid,
131635878b55SSascha Wildner 			0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE))
131735878b55SSascha Wildner 		||
131835878b55SSascha Wildner 		!(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res)))
131935878b55SSascha Wildner 	{
132035878b55SSascha Wildner 		MV_ERROR("RR18xx: Failed to remap memory space\n");
132135878b55SSascha Wildner 		hptmv_free_edma_queues(pAdapter);
1322c898d682SSascha Wildner 		unlock_driver();
132335878b55SSascha Wildner 		return ENXIO;
132435878b55SSascha Wildner 	}
132535878b55SSascha Wildner 	else
132635878b55SSascha Wildner 	{
132735878b55SSascha Wildner 		KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress));
132835878b55SSascha Wildner 	}
132935878b55SSascha Wildner 
133035878b55SSascha Wildner 	pMvSataAdapter->adapterId = num_adapters++;
133135878b55SSascha Wildner 	/* get the revision ID */
133235878b55SSascha Wildner 	pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1);
133335878b55SSascha Wildner 	pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev);
133435878b55SSascha Wildner 
133535878b55SSascha Wildner 	/* init RR18xx */
133635878b55SSascha Wildner 	pMvSataAdapter->intCoalThre[0]= 1;
133735878b55SSascha Wildner 	pMvSataAdapter->intCoalThre[1]= 1;
133835878b55SSascha Wildner 	pMvSataAdapter->intTimeThre[0] = 1;
133935878b55SSascha Wildner 	pMvSataAdapter->intTimeThre[1] = 1;
134035878b55SSascha Wildner 	pMvSataAdapter->pciCommand = 0x0107E371;
134135878b55SSascha Wildner 	pMvSataAdapter->pciSerrMask = 0xd77fe6ul;
134235878b55SSascha Wildner 	pMvSataAdapter->pciInterruptMask = 0xd77fe6ul;
134335878b55SSascha Wildner 	pMvSataAdapter->mvSataEventNotify = hptmv_event_notify;
134435878b55SSascha Wildner 
134535878b55SSascha Wildner 	if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
134635878b55SSascha Wildner 	{
134735878b55SSascha Wildner 		MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n",
134835878b55SSascha Wildner 				 pMvSataAdapter->adapterId);
134935878b55SSascha Wildner unregister:
135035878b55SSascha Wildner 		bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res);
135135878b55SSascha Wildner 		hptmv_free_edma_queues(pAdapter);
1352c898d682SSascha Wildner 		unlock_driver();
135335878b55SSascha Wildner 		return ENXIO;
135435878b55SSascha Wildner 	}
135535878b55SSascha Wildner 	pAdapter->ver_601 = pMvSataAdapter->pcbVersion;
135635878b55SSascha Wildner 
135735878b55SSascha Wildner #ifndef FOR_DEMO
135835878b55SSascha Wildner 	set_fail_leds(pMvSataAdapter, 0);
135935878b55SSascha Wildner #endif
136035878b55SSascha Wildner 
136135878b55SSascha Wildner 	/* setup command blocks */
136235878b55SSascha Wildner 	KdPrint(("Allocate command blocks\n"));
136335878b55SSascha Wildner 	_vbus_(pFreeCommands) = 0;
136435878b55SSascha Wildner 	pAdapter->pCommandBlocks =
136535878b55SSascha Wildner 		kmalloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT);
136635878b55SSascha Wildner 	KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks));
136735878b55SSascha Wildner 	if (!pAdapter->pCommandBlocks) {
136835878b55SSascha Wildner 		MV_ERROR("insufficient memory\n");
136935878b55SSascha Wildner 		goto unregister;
137035878b55SSascha Wildner 	}
137135878b55SSascha Wildner 
137235878b55SSascha Wildner 	for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) {
137335878b55SSascha Wildner 		FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i]));
137435878b55SSascha Wildner 	}
137535878b55SSascha Wildner 
137635878b55SSascha Wildner 	/*Set up the bus_dmamap*/
137735878b55SSascha Wildner 	pAdapter->pbus_dmamap = (PBUS_DMAMAP)kmalloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT);
137835878b55SSascha Wildner 	if(!pAdapter->pbus_dmamap) {
137935878b55SSascha Wildner 		MV_ERROR("insufficient memory\n");
138035878b55SSascha Wildner 		kfree(pAdapter->pCommandBlocks, M_DEVBUF);
138135878b55SSascha Wildner 		goto unregister;
138235878b55SSascha Wildner 	}
138335878b55SSascha Wildner 
138435878b55SSascha Wildner 	memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM);
138535878b55SSascha Wildner 	pAdapter->pbus_dmamap_list = 0;
138635878b55SSascha Wildner 	for (i=0; i < MAX_QUEUE_COMM; i++) {
138735878b55SSascha Wildner 		PBUS_DMAMAP  pmap = &(pAdapter->pbus_dmamap[i]);
138835878b55SSascha Wildner 		pmap->pAdapter = pAdapter;
138935878b55SSascha Wildner 		dmamap_put(pmap);
139035878b55SSascha Wildner 
139135878b55SSascha Wildner 		if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) {
139235878b55SSascha Wildner 			MV_ERROR("Can not allocate dma map\n");
139335878b55SSascha Wildner 			kfree(pAdapter->pCommandBlocks, M_DEVBUF);
139435878b55SSascha Wildner 			kfree(pAdapter->pbus_dmamap, M_DEVBUF);
139535878b55SSascha Wildner 			goto unregister;
139635878b55SSascha Wildner 		}
139735878b55SSascha Wildner 	}
139835878b55SSascha Wildner 	/* setup PRD Tables */
139935878b55SSascha Wildner 	KdPrint(("Allocate PRD Tables\n"));
140035878b55SSascha Wildner 	pAdapter->pFreePRDLink = 0;
140135878b55SSascha Wildner 
140235878b55SSascha Wildner 	pAdapter->prdTableAddr = (PUCHAR)contigmalloc(
140335878b55SSascha Wildner 		(PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
140435878b55SSascha Wildner 
140535878b55SSascha Wildner 	KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr));
140635878b55SSascha Wildner 	if (!pAdapter->prdTableAddr) {
140735878b55SSascha Wildner 		MV_ERROR("insufficient PRD Tables\n");
140835878b55SSascha Wildner 		goto unregister;
140935878b55SSascha Wildner 	}
141035878b55SSascha Wildner 	pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL);
141135878b55SSascha Wildner 	{
141235878b55SSascha Wildner 		PUCHAR PRDTable = pAdapter->prdTableAlignedAddr;
141335878b55SSascha Wildner 		for (i=0; i<PRD_TABLES_FOR_VBUS; i++)
141435878b55SSascha Wildner 		{
141535878b55SSascha Wildner /*			KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */
141635878b55SSascha Wildner 			FreePRDTable(pAdapter, PRDTable);
141735878b55SSascha Wildner 			PRDTable += PRD_ENTRIES_SIZE;
141835878b55SSascha Wildner 		}
141935878b55SSascha Wildner 	}
142035878b55SSascha Wildner 
142135878b55SSascha Wildner 	/* enable the adapter interrupts */
142235878b55SSascha Wildner 
142335878b55SSascha Wildner 	/* configure and start the connected channels*/
142435878b55SSascha Wildner 	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
142535878b55SSascha Wildner 	{
142635878b55SSascha Wildner 		pAdapter->mvChannel[channel].online = MV_FALSE;
142735878b55SSascha Wildner 		if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel)
142835878b55SSascha Wildner 			== MV_TRUE)
142935878b55SSascha Wildner 		{
143035878b55SSascha Wildner 			KdPrint(("RR18xx[%d]: channel %d is connected\n",
143135878b55SSascha Wildner 					  pMvSataAdapter->adapterId, channel));
143235878b55SSascha Wildner 
143335878b55SSascha Wildner 			if (hptmv_init_channel(pAdapter, channel) == 0)
143435878b55SSascha Wildner 			{
143535878b55SSascha Wildner 				if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE)
143635878b55SSascha Wildner 				{
143735878b55SSascha Wildner 					MV_ERROR("RR18xx[%d]: Failed to configure channel"
143835878b55SSascha Wildner 							 " %d\n",pMvSataAdapter->adapterId, channel);
143935878b55SSascha Wildner 					hptmv_free_channel(pAdapter, channel);
144035878b55SSascha Wildner 				}
144135878b55SSascha Wildner 				else
144235878b55SSascha Wildner 				{
144335878b55SSascha Wildner 					if (start_channel(pAdapter, channel))
144435878b55SSascha Wildner 					{
144535878b55SSascha Wildner 						MV_ERROR("RR18xx[%d]: Failed to start channel,"
144635878b55SSascha Wildner 								 " channel=%d\n",pMvSataAdapter->adapterId,
144735878b55SSascha Wildner 								 channel);
144835878b55SSascha Wildner 						hptmv_free_channel(pAdapter, channel);
144935878b55SSascha Wildner 					}
145035878b55SSascha Wildner 					pAdapter->mvChannel[channel].online = MV_TRUE;
145135878b55SSascha Wildner 					/*  mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter,
145235878b55SSascha Wildner 													   channel,
145335878b55SSascha Wildner 													   MV_TRUE);*/
145435878b55SSascha Wildner 				}
145535878b55SSascha Wildner 			}
145635878b55SSascha Wildner 		}
145735878b55SSascha Wildner 		KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n",
145835878b55SSascha Wildner 			pAdapter->mvChannel[channel].online, channel));
145935878b55SSascha Wildner 	}
146035878b55SSascha Wildner 
146135878b55SSascha Wildner #ifdef SUPPORT_ARRAY
146235878b55SSascha Wildner 	for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) {
146335878b55SSascha Wildner 		pVDev = ArrayTables(i);
146435878b55SSascha Wildner 		mArFreeArrayTable(pVDev);
146535878b55SSascha Wildner 	}
146635878b55SSascha Wildner #endif
146735878b55SSascha Wildner 
146835878b55SSascha Wildner 	KdPrint(("Initialize Devices\n"));
146935878b55SSascha Wildner 	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
147035878b55SSascha Wildner 		MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel];
147135878b55SSascha Wildner 		if (pMvSataChannel) {
147235878b55SSascha Wildner 			init_vdev_params(pAdapter, channel);
147335878b55SSascha Wildner 			IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk);
147435878b55SSascha Wildner 		}
147535878b55SSascha Wildner 	}
147635878b55SSascha Wildner #ifdef SUPPORT_ARRAY
147735878b55SSascha Wildner 	CheckArrayCritical(_VBUS_P0);
147835878b55SSascha Wildner #endif
147935878b55SSascha Wildner 	_vbus_p->nInstances = 1;
148035878b55SSascha Wildner 	fRegisterVdevice(pAdapter);
148135878b55SSascha Wildner 
148235878b55SSascha Wildner 	for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) {
148335878b55SSascha Wildner 		pVDev = _vbus_p->pVDevice[channel];
148435878b55SSascha Wildner 		if (pVDev && pVDev->vf_online)
148535878b55SSascha Wildner 			fCheckBootable(pVDev);
148635878b55SSascha Wildner 	}
148735878b55SSascha Wildner 
148835878b55SSascha Wildner #if defined(SUPPORT_ARRAY) && defined(_RAID5N_)
148935878b55SSascha Wildner 	init_raid5_memory(_VBUS_P0);
149035878b55SSascha Wildner 	_vbus_(r5).enable_write_back = 1;
149135878b55SSascha Wildner 	kprintf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled");
149235878b55SSascha Wildner #endif
149335878b55SSascha Wildner 
149435878b55SSascha Wildner 	mvSataUnmaskAdapterInterrupt(pMvSataAdapter);
1495c898d682SSascha Wildner 	unlock_driver();
149635878b55SSascha Wildner 	return 0;
149735878b55SSascha Wildner }
149835878b55SSascha Wildner 
149935878b55SSascha Wildner int
150035878b55SSascha Wildner MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
150135878b55SSascha Wildner {
150235878b55SSascha Wildner 	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData;
150335878b55SSascha Wildner 
150435878b55SSascha Wildner 	mvSataDisableChannelDma(pMvSataAdapter, channel);
150535878b55SSascha Wildner 	/* Flush pending commands */
150635878b55SSascha Wildner 	mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
150735878b55SSascha Wildner 
150835878b55SSascha Wildner 	/* Software reset channel */
150935878b55SSascha Wildner 	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE)
151035878b55SSascha Wildner 	{
151135878b55SSascha Wildner 		MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n",
151235878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channel);
151335878b55SSascha Wildner 		hptmv_free_channel(pAdapter, channel);
151435878b55SSascha Wildner 		return -1;
151535878b55SSascha Wildner 	}
151635878b55SSascha Wildner 
151735878b55SSascha Wildner 	/* Hardware reset channel */
151835878b55SSascha Wildner 	if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE)
151935878b55SSascha Wildner 	{
152035878b55SSascha Wildner 		MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n",
152135878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channel);
152235878b55SSascha Wildner 		hptmv_free_channel(pAdapter, channel);
152335878b55SSascha Wildner 		return -1;
152435878b55SSascha Wildner 	}
152535878b55SSascha Wildner 
152635878b55SSascha Wildner 	if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE)
152735878b55SSascha Wildner 	{
152835878b55SSascha Wildner 		 MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n",
152935878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channel);
153035878b55SSascha Wildner 		hptmv_free_channel(pAdapter, channel);
153135878b55SSascha Wildner 		return -1;
153235878b55SSascha Wildner 	}else
153335878b55SSascha Wildner 	{
153435878b55SSascha Wildner 		MV_ERROR("channel %d: perform recalibrate command", channel);
153535878b55SSascha Wildner 		if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
153635878b55SSascha Wildner 								MV_NON_UDMA_PROTOCOL_NON_DATA,
153735878b55SSascha Wildner 								MV_FALSE,
153835878b55SSascha Wildner 								NULL,	 /* pBuffer*/
153935878b55SSascha Wildner 								0,		 /* count  */
154035878b55SSascha Wildner 								0,		/*features*/
154135878b55SSascha Wildner 										/* sectorCount */
154235878b55SSascha Wildner 								0,
154335878b55SSascha Wildner 								0,	/* lbaLow */
154435878b55SSascha Wildner 								0,	/* lbaMid */
154535878b55SSascha Wildner 									/* lbaHigh */
154635878b55SSascha Wildner 								0,
154735878b55SSascha Wildner 								0,		/* device */
154835878b55SSascha Wildner 										/* command */
154935878b55SSascha Wildner 								0x10))
155035878b55SSascha Wildner 			MV_ERROR("channel %d: recalibrate failed", channel);
155135878b55SSascha Wildner 
155235878b55SSascha Wildner 		/* Set transfer mode */
155335878b55SSascha Wildner 		if((mvStorageDevATASetFeatures(pMvSataAdapter, channel,
155435878b55SSascha Wildner 						MV_ATA_SET_FEATURES_TRANSFER,
155535878b55SSascha Wildner 						MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) ||
155635878b55SSascha Wildner 			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
155735878b55SSascha Wildner 						MV_ATA_SET_FEATURES_TRANSFER,
155835878b55SSascha Wildner 						pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) ||
155935878b55SSascha Wildner 			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
156035878b55SSascha Wildner 						MV_ATA_SET_FEATURES_TRANSFER,
156135878b55SSascha Wildner 						pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) )
156235878b55SSascha Wildner 		{
156335878b55SSascha Wildner 			MV_ERROR("channel %d: Set Features failed", channel);
156435878b55SSascha Wildner 			hptmv_free_channel(pAdapter, channel);
156535878b55SSascha Wildner 			return -1;
156635878b55SSascha Wildner 		}
156735878b55SSascha Wildner 		/* Enable EDMA */
156835878b55SSascha Wildner 		if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE)
156935878b55SSascha Wildner 		{
157035878b55SSascha Wildner 			MV_ERROR("Failed to enable DMA, channel=%d", channel);
157135878b55SSascha Wildner 			hptmv_free_channel(pAdapter, channel);
157235878b55SSascha Wildner 			return -1;
157335878b55SSascha Wildner 		}
157435878b55SSascha Wildner 	}
157535878b55SSascha Wildner 	return 0;
157635878b55SSascha Wildner }
157735878b55SSascha Wildner 
157835878b55SSascha Wildner static int
157935878b55SSascha Wildner fResetActiveCommands(PVBus _vbus_p)
158035878b55SSascha Wildner {
158135878b55SSascha Wildner 	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
158235878b55SSascha Wildner 	MV_U8 channel;
158335878b55SSascha Wildner 	for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
158435878b55SSascha Wildner 		if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands)
158535878b55SSascha Wildner 			MvSataResetChannel(pMvSataAdapter,channel);
158635878b55SSascha Wildner 	}
158735878b55SSascha Wildner 	return 0;
158835878b55SSascha Wildner }
158935878b55SSascha Wildner 
159035878b55SSascha Wildner void fCompleteAllCommandsSynchronously(PVBus _vbus_p)
159135878b55SSascha Wildner {
159235878b55SSascha Wildner 	UINT cont;
159335878b55SSascha Wildner 	ULONG ticks = 0;
159435878b55SSascha Wildner 	MV_U8 channel;
159535878b55SSascha Wildner 	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
159635878b55SSascha Wildner 	MV_SATA_CHANNEL *pMvSataChannel;
159735878b55SSascha Wildner 
159835878b55SSascha Wildner 	do {
159935878b55SSascha Wildner check_cmds:
160035878b55SSascha Wildner 		cont = 0;
160135878b55SSascha Wildner 		CheckPendingCall(_VBUS_P0);
160235878b55SSascha Wildner #ifdef _RAID5N_
160335878b55SSascha Wildner 		dataxfer_poll();
160435878b55SSascha Wildner 		xor_poll();
160535878b55SSascha Wildner #endif
160635878b55SSascha Wildner 		for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
160735878b55SSascha Wildner 			pMvSataChannel = pMvSataAdapter->sataChannel[channel];
160835878b55SSascha Wildner 			if (pMvSataChannel && pMvSataChannel->outstandingCommands)
160935878b55SSascha Wildner 			{
161035878b55SSascha Wildner 				while (pMvSataChannel->outstandingCommands) {
161135878b55SSascha Wildner 					if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) {
161235878b55SSascha Wildner 						StallExec(1000);
161335878b55SSascha Wildner 						if (ticks++ > 3000) {
161435878b55SSascha Wildner 							MvSataResetChannel(pMvSataAdapter,channel);
161535878b55SSascha Wildner 							goto check_cmds;
161635878b55SSascha Wildner 						}
161735878b55SSascha Wildner 					}
161835878b55SSascha Wildner 					else
161935878b55SSascha Wildner 						ticks = 0;
162035878b55SSascha Wildner 				}
162135878b55SSascha Wildner 				cont = 1;
162235878b55SSascha Wildner 			}
162335878b55SSascha Wildner 		}
162435878b55SSascha Wildner 	} while (cont);
162535878b55SSascha Wildner }
162635878b55SSascha Wildner 
162735878b55SSascha Wildner void
162835878b55SSascha Wildner fResetVBus(_VBUS_ARG0)
162935878b55SSascha Wildner {
163035878b55SSascha Wildner 	KdPrint(("fMvResetBus(%p)", _vbus_p));
163135878b55SSascha Wildner 
163235878b55SSascha Wildner 	/* some commands may already finished. */
163335878b55SSascha Wildner 	CheckPendingCall(_VBUS_P0);
163435878b55SSascha Wildner 
163535878b55SSascha Wildner 	fResetActiveCommands(_vbus_p);
163635878b55SSascha Wildner 	/*
163735878b55SSascha Wildner 	 * the other pending commands may still be finished successfully.
163835878b55SSascha Wildner 	 */
163935878b55SSascha Wildner 	fCompleteAllCommandsSynchronously(_vbus_p);
164035878b55SSascha Wildner 
164135878b55SSascha Wildner 	/* Now there should be no pending commands. No more action needed. */
164235878b55SSascha Wildner 	CheckIdleCall(_VBUS_P0);
164335878b55SSascha Wildner 
164435878b55SSascha Wildner 	KdPrint(("fMvResetBus() done"));
164535878b55SSascha Wildner }
164635878b55SSascha Wildner 
164735878b55SSascha Wildner /*No rescan function*/
164835878b55SSascha Wildner void
164935878b55SSascha Wildner fRescanAllDevice(_VBUS_ARG0)
165035878b55SSascha Wildner {
165135878b55SSascha Wildner }
165235878b55SSascha Wildner 
165335878b55SSascha Wildner static MV_BOOLEAN
165435878b55SSascha Wildner CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
165535878b55SSascha Wildner 					MV_U8 channelNum,
165635878b55SSascha Wildner 					MV_COMPLETION_TYPE comp_type,
165735878b55SSascha Wildner 					MV_VOID_PTR commandId,
165835878b55SSascha Wildner 					MV_U16 responseFlags,
165935878b55SSascha Wildner 					MV_U32 timeStamp,
166035878b55SSascha Wildner 					MV_STORAGE_DEVICE_REGISTERS *registerStruct)
166135878b55SSascha Wildner {
166235878b55SSascha Wildner 	PCommand pCmd = (PCommand) commandId;
166335878b55SSascha Wildner 	_VBUS_INST(pCmd->pVDevice->pVBus)
166435878b55SSascha Wildner 
166535878b55SSascha Wildner 	if (pCmd->uScratch.sata_param.prdAddr)
166635878b55SSascha Wildner 		FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr);
166735878b55SSascha Wildner 
166835878b55SSascha Wildner 	switch (comp_type)
166935878b55SSascha Wildner 	{
167035878b55SSascha Wildner 	case MV_COMPLETION_TYPE_NORMAL:
167135878b55SSascha Wildner 		pCmd->Result = RETURN_SUCCESS;
167235878b55SSascha Wildner 		break;
167335878b55SSascha Wildner 	case MV_COMPLETION_TYPE_ABORT:
167435878b55SSascha Wildner 		pCmd->Result = RETURN_BUS_RESET;
167535878b55SSascha Wildner 		break;
167635878b55SSascha Wildner 	case MV_COMPLETION_TYPE_ERROR:
167735878b55SSascha Wildner 		 MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n",
167835878b55SSascha Wildner 				 pMvSataAdapter->adapterId, channelNum, responseFlags);
167935878b55SSascha Wildner 
168035878b55SSascha Wildner 		if (responseFlags & 4) {
168135878b55SSascha Wildner 			MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x,"
168235878b55SSascha Wildner 				" LBA high %x, device %x, status %x\n",
168335878b55SSascha Wildner 				registerStruct->errorRegister,
168435878b55SSascha Wildner 				registerStruct->sectorCountRegister,
168535878b55SSascha Wildner 				registerStruct->lbaLowRegister,
168635878b55SSascha Wildner 				registerStruct->lbaMidRegister,
168735878b55SSascha Wildner 				registerStruct->lbaHighRegister,
168835878b55SSascha Wildner 				registerStruct->deviceRegister,
168935878b55SSascha Wildner 				registerStruct->statusRegister);
169035878b55SSascha Wildner 		}
169135878b55SSascha Wildner 		/*We can't do handleEdmaError directly here, because CommandCompletionCB is called by
169235878b55SSascha Wildner 		 * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/
169335878b55SSascha Wildner 		pCmd->uScratch.sata_param.responseFlags = responseFlags;
169435878b55SSascha Wildner 		pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister;
169535878b55SSascha Wildner 		pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister;
169635878b55SSascha Wildner 		pCmd->pVDevice->u.disk.QueueLength--;
169735878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd);
169835878b55SSascha Wildner 		return TRUE;
169935878b55SSascha Wildner 
170035878b55SSascha Wildner 	default:
170135878b55SSascha Wildner 		MV_ERROR(" Unknown completion type (%d)\n", comp_type);
170235878b55SSascha Wildner 		return MV_FALSE;
170335878b55SSascha Wildner 	}
170435878b55SSascha Wildner 
170535878b55SSascha Wildner 	if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) {
170635878b55SSascha Wildner 		pCmd->uScratch.sata_param.cmd_priv --;
170735878b55SSascha Wildner 		return TRUE;
170835878b55SSascha Wildner 	}
170935878b55SSascha Wildner 	pCmd->pVDevice->u.disk.QueueLength--;
171035878b55SSascha Wildner 	CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
171135878b55SSascha Wildner 	return TRUE;
171235878b55SSascha Wildner }
171335878b55SSascha Wildner 
171435878b55SSascha Wildner void
171535878b55SSascha Wildner fDeviceSendCommand(_VBUS_ARG PCommand pCmd)
171635878b55SSascha Wildner {
171735878b55SSascha Wildner 	MV_SATA_EDMA_PRD_ENTRY  *pPRDTable = 0;
171835878b55SSascha Wildner 	MV_SATA_ADAPTER *pMvSataAdapter;
171935878b55SSascha Wildner 	MV_SATA_CHANNEL *pMvSataChannel;
172035878b55SSascha Wildner 	PVDevice pVDevice = pCmd->pVDevice;
172135878b55SSascha Wildner 	PDevice  pDevice = &pVDevice->u.disk;
172235878b55SSascha Wildner 	LBA_T    Lba = pCmd->uCmd.Ide.Lba;
172335878b55SSascha Wildner 	USHORT   nSector = pCmd->uCmd.Ide.nSectors;
172435878b55SSascha Wildner 
172535878b55SSascha Wildner 	MV_QUEUE_COMMAND_RESULT result;
172635878b55SSascha Wildner 	MV_QUEUE_COMMAND_INFO commandInfo;
172735878b55SSascha Wildner 	MV_UDMA_COMMAND_PARAMS  *pUdmaParams = &commandInfo.commandParams.udmaCommand;
172835878b55SSascha Wildner 	MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand;
172935878b55SSascha Wildner 
173035878b55SSascha Wildner 	MV_BOOLEAN is48bit;
173135878b55SSascha Wildner 	MV_U8      channel;
173235878b55SSascha Wildner 	int        i=0;
173335878b55SSascha Wildner 
173435878b55SSascha Wildner 	DECLARE_BUFFER(FPSCAT_GATH, tmpSg);
173535878b55SSascha Wildner 
173635878b55SSascha Wildner 	if (!pDevice->df_on_line) {
173735878b55SSascha Wildner 		MV_ERROR("Device is offline");
173835878b55SSascha Wildner 		pCmd->Result = RETURN_BAD_DEVICE;
173935878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
174035878b55SSascha Wildner 		return;
174135878b55SSascha Wildner 	}
174235878b55SSascha Wildner 
174335878b55SSascha Wildner 	pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors;
174435878b55SSascha Wildner 	pMvSataChannel = pDevice->mv;
174535878b55SSascha Wildner 	pMvSataAdapter = pMvSataChannel->mvSataAdapter;
174635878b55SSascha Wildner 	channel = pMvSataChannel->channelNumber;
174735878b55SSascha Wildner 
174835878b55SSascha Wildner 	/* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */
174935878b55SSascha Wildner 	Lba += pDevice->dDeHiddenLba;
175035878b55SSascha Wildner 	/* check LBA */
175135878b55SSascha Wildner 	if (Lba+nSector-1 > pDevice->dDeRealCapacity) {
175235878b55SSascha Wildner 		pCmd->Result = RETURN_INVALID_REQUEST;
175335878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
175435878b55SSascha Wildner 		return;
175535878b55SSascha Wildner 	}
175635878b55SSascha Wildner 
175735878b55SSascha Wildner 	/*
175835878b55SSascha Wildner 	 * always use 48bit LBA if drive supports it.
175935878b55SSascha Wildner 	 * Some Seagate drives report error if you use a 28-bit command
176035878b55SSascha Wildner 	 * to access sector 0xfffffff.
176135878b55SSascha Wildner 	 */
176235878b55SSascha Wildner 	is48bit = pMvSataChannel->lba48Address;
176335878b55SSascha Wildner 
176435878b55SSascha Wildner 	switch (pCmd->uCmd.Ide.Command)
176535878b55SSascha Wildner 	{
176635878b55SSascha Wildner 	case IDE_COMMAND_READ:
176735878b55SSascha Wildner 	case IDE_COMMAND_WRITE:
176835878b55SSascha Wildner 		if (pDevice->bDeModeSetting<8) goto pio;
176935878b55SSascha Wildner 
177035878b55SSascha Wildner 		commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA;
177135878b55SSascha Wildner 		pUdmaParams->isEXT = is48bit;
177235878b55SSascha Wildner 		pUdmaParams->numOfSectors = nSector;
177335878b55SSascha Wildner 		pUdmaParams->lowLBAAddress = Lba;
177435878b55SSascha Wildner 		pUdmaParams->highLBAAddress = 0;
177535878b55SSascha Wildner 		pUdmaParams->prdHighAddr = 0;
177635878b55SSascha Wildner 		pUdmaParams->callBack = CommandCompletionCB;
177735878b55SSascha Wildner 		pUdmaParams->commandId = (MV_VOID_PTR )pCmd;
177835878b55SSascha Wildner 		if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ)
177935878b55SSascha Wildner 			pUdmaParams->readWrite = MV_UDMA_TYPE_READ;
178035878b55SSascha Wildner 		else
178135878b55SSascha Wildner 			pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE;
178235878b55SSascha Wildner 
178335878b55SSascha Wildner 		if (pCmd->pSgTable && pCmd->cf_physical_sg) {
178435878b55SSascha Wildner 			FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
178535878b55SSascha Wildner 			do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
178635878b55SSascha Wildner 		}
178735878b55SSascha Wildner 		else {
178835878b55SSascha Wildner 			if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) {
178935878b55SSascha Wildner pio:
179035878b55SSascha Wildner 				mvSataDisableChannelDma(pMvSataAdapter, channel);
179135878b55SSascha Wildner 				mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
179235878b55SSascha Wildner 
179335878b55SSascha Wildner 				if (pCmd->pSgTable && pCmd->cf_physical_sg==0) {
179435878b55SSascha Wildner 					FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
179535878b55SSascha Wildner 					do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
179635878b55SSascha Wildner 				}
179735878b55SSascha Wildner 				else {
179835878b55SSascha Wildner 					if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) {
179935878b55SSascha Wildner 						pCmd->Result = RETURN_NEED_LOGICAL_SG;
180035878b55SSascha Wildner 						goto finish_cmd;
180135878b55SSascha Wildner 					}
180235878b55SSascha Wildner 				}
180335878b55SSascha Wildner 
180435878b55SSascha Wildner 				do {
180535878b55SSascha Wildner 					ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000;
180635878b55SSascha Wildner 					ULONG_PTR addr = tmpSg->dSgAddress;
180735878b55SSascha Wildner 					if (size & 0x1ff) {
180835878b55SSascha Wildner 						pCmd->Result = RETURN_INVALID_REQUEST;
180935878b55SSascha Wildner 						goto finish_cmd;
181035878b55SSascha Wildner 					}
181135878b55SSascha Wildner 					if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
181235878b55SSascha Wildner 						(pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN,
181335878b55SSascha Wildner 						is48bit,
181435878b55SSascha Wildner 						(MV_U16_PTR)addr,
181535878b55SSascha Wildner 						size >> 1,	/* count       */
181635878b55SSascha Wildner 						0,		/* features  N/A  */
181735878b55SSascha Wildner 						(MV_U16)(size>>9),	/*sector count*/
181835878b55SSascha Wildner 						(MV_U16)(  (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 )  | (UCHAR)(Lba & 0xFF) ), /*lbalow*/
181935878b55SSascha Wildner 						(MV_U16)((Lba >> 8) & 0xFF), /* lbaMid      */
182035878b55SSascha Wildner 						(MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh     */
182135878b55SSascha Wildner 						(MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device      */
182235878b55SSascha Wildner 						(MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command)
182335878b55SSascha Wildner 					)==MV_FALSE)
182435878b55SSascha Wildner 					{
182535878b55SSascha Wildner 						pCmd->Result = RETURN_IDE_ERROR;
182635878b55SSascha Wildner 						goto finish_cmd;
182735878b55SSascha Wildner 					}
182835878b55SSascha Wildner 					Lba += size>>9;
182935878b55SSascha Wildner 					if(Lba & 0xF0000000) is48bit = MV_TRUE;
183035878b55SSascha Wildner 				}
183135878b55SSascha Wildner 				while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
183235878b55SSascha Wildner 				pCmd->Result = RETURN_SUCCESS;
183335878b55SSascha Wildner finish_cmd:
183435878b55SSascha Wildner 				mvSataEnableChannelDma(pMvSataAdapter,channel);
183535878b55SSascha Wildner 				CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
183635878b55SSascha Wildner 				return;
183735878b55SSascha Wildner 			}
183835878b55SSascha Wildner 		}
183935878b55SSascha Wildner 
184035878b55SSascha Wildner 		pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData);
184135878b55SSascha Wildner 		KdPrint(("pPRDTable:%p\n",pPRDTable));
184235878b55SSascha Wildner 		if (!pPRDTable) {
184335878b55SSascha Wildner 			pCmd->Result = RETURN_DEVICE_BUSY;
184435878b55SSascha Wildner 			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
184535878b55SSascha Wildner 			HPT_ASSERT(0);
184635878b55SSascha Wildner 			return;
184735878b55SSascha Wildner 		}
184835878b55SSascha Wildner 
184935878b55SSascha Wildner 		do{
185035878b55SSascha Wildner 			pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0);
185135878b55SSascha Wildner 			pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag;
185235878b55SSascha Wildner 			pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize;
185335878b55SSascha Wildner 			pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress;
185435878b55SSascha Wildner 			pPRDTable[i].reserved = 0;
185535878b55SSascha Wildner 			i++;
185635878b55SSascha Wildner 		}while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
185735878b55SSascha Wildner 
185835878b55SSascha Wildner 		pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable);
185935878b55SSascha Wildner 		if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) {
186035878b55SSascha Wildner 			pUdmaParams->numOfSectors = 0;
186135878b55SSascha Wildner 		}
186235878b55SSascha Wildner 
186335878b55SSascha Wildner 		pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable;
186435878b55SSascha Wildner 
186535878b55SSascha Wildner 		result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
186635878b55SSascha Wildner 
186735878b55SSascha Wildner 		if (result != MV_QUEUE_COMMAND_RESULT_OK)
186835878b55SSascha Wildner 		{
186935878b55SSascha Wildner queue_failed:
187035878b55SSascha Wildner 			switch (result)
187135878b55SSascha Wildner 			{
187235878b55SSascha Wildner 			case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
187335878b55SSascha Wildner 				MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA "
187435878b55SSascha Wildner 						 "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress);
187535878b55SSascha Wildner 				pCmd->Result = RETURN_IDE_ERROR;
187635878b55SSascha Wildner 				break;
187735878b55SSascha Wildner 			case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
187835878b55SSascha Wildner 				MV_ERROR("IAL Error: Edma Queue command failed. EDMA"
187935878b55SSascha Wildner 						 " disabled adapter %d channel %d\n",
188035878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channel);
188135878b55SSascha Wildner 				mvSataEnableChannelDma(pMvSataAdapter,channel);
188235878b55SSascha Wildner 				pCmd->Result = RETURN_IDE_ERROR;
188335878b55SSascha Wildner 				break;
188435878b55SSascha Wildner 			case MV_QUEUE_COMMAND_RESULT_FULL:
188535878b55SSascha Wildner 				MV_ERROR("IAL Error: Edma Queue command failed. Queue is"
188635878b55SSascha Wildner 						 " Full adapter %d channel %d\n",
188735878b55SSascha Wildner 						 pMvSataAdapter->adapterId, channel);
188835878b55SSascha Wildner 				pCmd->Result = RETURN_DEVICE_BUSY;
188935878b55SSascha Wildner 				break;
189035878b55SSascha Wildner 			case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
189135878b55SSascha Wildner 				MV_ERROR("IAL Error: Edma Queue command failed. (Bad "
189235878b55SSascha Wildner 						 "Params), pMvSataAdapter: %p,  pSataChannel: %p.\n",
189335878b55SSascha Wildner 						 pMvSataAdapter, pMvSataAdapter->sataChannel[channel]);
189435878b55SSascha Wildner 				pCmd->Result = RETURN_IDE_ERROR;
189535878b55SSascha Wildner 				break;
189635878b55SSascha Wildner 			default:
189735878b55SSascha Wildner 				MV_ERROR("IAL Error: Bad result value (%d) from queue"
189835878b55SSascha Wildner 						 " command\n", result);
189935878b55SSascha Wildner 				pCmd->Result = RETURN_IDE_ERROR;
190035878b55SSascha Wildner 			}
190135878b55SSascha Wildner 			if(pPRDTable)
190235878b55SSascha Wildner 				FreePRDTable(pMvSataAdapter->IALData,pPRDTable);
190335878b55SSascha Wildner 			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
190435878b55SSascha Wildner 		}
190535878b55SSascha Wildner 		pDevice->QueueLength++;
190635878b55SSascha Wildner 		return;
190735878b55SSascha Wildner 
190835878b55SSascha Wildner 	case IDE_COMMAND_VERIFY:
190935878b55SSascha Wildner 		commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
191035878b55SSascha Wildner 		pNoUdmaParams->bufPtr = NULL;
191135878b55SSascha Wildner 		pNoUdmaParams->callBack = CommandCompletionCB;
191235878b55SSascha Wildner 		pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd;
191335878b55SSascha Wildner 		pNoUdmaParams->count = 0;
191435878b55SSascha Wildner 		pNoUdmaParams->features = 0;
191535878b55SSascha Wildner 		pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
191635878b55SSascha Wildner 
191735878b55SSascha Wildner 		pCmd->uScratch.sata_param.cmd_priv = 1;
191835878b55SSascha Wildner 		if (pMvSataChannel->lba48Address == MV_TRUE){
191935878b55SSascha Wildner 			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT;
192035878b55SSascha Wildner 			pNoUdmaParams->isEXT = MV_TRUE;
192135878b55SSascha Wildner 			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
192235878b55SSascha Wildner 			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
192335878b55SSascha Wildner 			pNoUdmaParams->lbaLow =
192435878b55SSascha Wildner 				(MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff));
192535878b55SSascha Wildner 			pNoUdmaParams->sectorCount = nSector;
192635878b55SSascha Wildner 			pNoUdmaParams->device = 0x40;
192735878b55SSascha Wildner 			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
192835878b55SSascha Wildner 			if (result != MV_QUEUE_COMMAND_RESULT_OK){
192935878b55SSascha Wildner 				goto queue_failed;
193035878b55SSascha Wildner 			}
193135878b55SSascha Wildner 			return;
193235878b55SSascha Wildner 		}
193335878b55SSascha Wildner 		else{
193435878b55SSascha Wildner 			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS;
193535878b55SSascha Wildner 			pNoUdmaParams->isEXT = MV_FALSE;
193635878b55SSascha Wildner 			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
193735878b55SSascha Wildner 			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
193835878b55SSascha Wildner 			pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff);
193935878b55SSascha Wildner 			pNoUdmaParams->sectorCount = 0xff & nSector;
194035878b55SSascha Wildner 			pNoUdmaParams->device = (MV_U8)(0x40 |
194135878b55SSascha Wildner 				((Lba & 0xf000000) >> 24));
194235878b55SSascha Wildner 			pNoUdmaParams->callBack = CommandCompletionCB;
194335878b55SSascha Wildner 			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
194435878b55SSascha Wildner 			/*FIXME: how about the commands already queued? but marvel also forgets to consider this*/
194535878b55SSascha Wildner 			if (result != MV_QUEUE_COMMAND_RESULT_OK){
194635878b55SSascha Wildner 				goto queue_failed;
194735878b55SSascha Wildner 			}
194835878b55SSascha Wildner 		}
194935878b55SSascha Wildner 		break;
195035878b55SSascha Wildner 	default:
195135878b55SSascha Wildner 		pCmd->Result = RETURN_INVALID_REQUEST;
195235878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
195335878b55SSascha Wildner 		break;
195435878b55SSascha Wildner 	}
195535878b55SSascha Wildner }
195635878b55SSascha Wildner 
195735878b55SSascha Wildner /**********************************************************
195835878b55SSascha Wildner  *
195935878b55SSascha Wildner  *	Probe the hostadapter.
196035878b55SSascha Wildner  *
196135878b55SSascha Wildner  **********************************************************/
196235878b55SSascha Wildner static int
196335878b55SSascha Wildner hpt_probe(device_t dev)
196435878b55SSascha Wildner {
196535878b55SSascha Wildner 	if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) &&
196635878b55SSascha Wildner 		(pci_get_device(dev) == MV_SATA_DEVICE_ID_5081
196735878b55SSascha Wildner #ifdef FOR_DEMO
196835878b55SSascha Wildner 		|| pci_get_device(dev) == MV_SATA_DEVICE_ID_5080
196935878b55SSascha Wildner #endif
197035878b55SSascha Wildner 		))
197135878b55SSascha Wildner 	{
197235878b55SSascha Wildner 		KdPrintI((CONTROLLER_NAME " found\n"));
197335878b55SSascha Wildner 		device_set_desc(dev, CONTROLLER_NAME);
197435878b55SSascha Wildner 		return 0;
197535878b55SSascha Wildner 	}
197635878b55SSascha Wildner 	else
197735878b55SSascha Wildner 		return(ENXIO);
197835878b55SSascha Wildner }
197935878b55SSascha Wildner 
198035878b55SSascha Wildner /***********************************************************
198135878b55SSascha Wildner  *
198235878b55SSascha Wildner  *      Auto configuration:  attach and init a host adapter.
198335878b55SSascha Wildner  *
198435878b55SSascha Wildner  ***********************************************************/
198535878b55SSascha Wildner static int
198635878b55SSascha Wildner hpt_attach(device_t dev)
198735878b55SSascha Wildner {
198835878b55SSascha Wildner 	IAL_ADAPTER_T * pAdapter = device_get_softc(dev);
198935878b55SSascha Wildner 	int rid;
199035878b55SSascha Wildner 	union ccb *ccb;
199135878b55SSascha Wildner 	struct cam_devq *devq;
199235878b55SSascha Wildner 	struct cam_sim *hpt_vsim;
199335878b55SSascha Wildner 
199435878b55SSascha Wildner 	kprintf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION);
199535878b55SSascha Wildner 
199635878b55SSascha Wildner 	if (!pAdapter)
199735878b55SSascha Wildner 	{
199835878b55SSascha Wildner 		pAdapter = (IAL_ADAPTER_T *)kmalloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT);
199935878b55SSascha Wildner 		device_set_softc(dev, (void *)pAdapter);
200035878b55SSascha Wildner 	}
200135878b55SSascha Wildner 
200235878b55SSascha Wildner 	if (!pAdapter) return (ENOMEM);
200335878b55SSascha Wildner 	bzero(pAdapter, sizeof(IAL_ADAPTER_T));
200435878b55SSascha Wildner 
200535878b55SSascha Wildner 	pAdapter->hpt_dev = dev;
200635878b55SSascha Wildner 
200735878b55SSascha Wildner 	rid = init_adapter(pAdapter);
200835878b55SSascha Wildner 	if (rid)
200935878b55SSascha Wildner 		return rid;
201035878b55SSascha Wildner 
201135878b55SSascha Wildner 	rid = 0;
201235878b55SSascha Wildner 	if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL)
201335878b55SSascha Wildner 	{
201435878b55SSascha Wildner 		hpt_printk(("can't allocate interrupt\n"));
201535878b55SSascha Wildner 		return(ENXIO);
201635878b55SSascha Wildner 	}
201735878b55SSascha Wildner 
201835878b55SSascha Wildner 	if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, 0,
201935878b55SSascha Wildner 				hpt_intr, pAdapter, &pAdapter->hpt_intr, NULL))
202035878b55SSascha Wildner 	{
202135878b55SSascha Wildner 		hpt_printk(("can't set up interrupt\n"));
202235878b55SSascha Wildner 		kfree(pAdapter, M_DEVBUF);
202335878b55SSascha Wildner 		return(ENXIO);
202435878b55SSascha Wildner 	}
202535878b55SSascha Wildner 
202635878b55SSascha Wildner 
202799eeb924SSascha Wildner 	ccb = kmalloc(sizeof(*ccb), M_DEVBUF, M_WAITOK);
202835878b55SSascha Wildner 	bzero(ccb, sizeof(*ccb));
202935878b55SSascha Wildner 	ccb->ccb_h.pinfo.priority = 1;
203035878b55SSascha Wildner 	ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
203199eeb924SSascha Wildner 
203235878b55SSascha Wildner 	/*
203335878b55SSascha Wildner 	 * Create the device queue for our SIM(s).
203435878b55SSascha Wildner 	 */
203535878b55SSascha Wildner 	if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL)
203635878b55SSascha Wildner 	{
203735878b55SSascha Wildner 		KdPrint(("ENXIO\n"));
203835878b55SSascha Wildner 		return ENOMEM;
203935878b55SSascha Wildner 	}
204035878b55SSascha Wildner 
204135878b55SSascha Wildner 	/*
204235878b55SSascha Wildner 	 * Construct our SIM entry
204335878b55SSascha Wildner 	 */
204435878b55SSascha Wildner 	hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
204535878b55SSascha Wildner 			pAdapter, device_get_unit(pAdapter->hpt_dev), &sim_mplock, 1, 8, devq);
204635878b55SSascha Wildner 	cam_simq_release(devq);
204735878b55SSascha Wildner 	if (hpt_vsim == NULL) {
204835878b55SSascha Wildner 		return ENOMEM;
204935878b55SSascha Wildner 	}
205035878b55SSascha Wildner 
205135878b55SSascha Wildner 	if (xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS)
205235878b55SSascha Wildner 	{
205335878b55SSascha Wildner 		cam_sim_free(hpt_vsim);
205435878b55SSascha Wildner 		hpt_vsim = NULL;
205535878b55SSascha Wildner 		return ENXIO;
205635878b55SSascha Wildner 	}
205735878b55SSascha Wildner 
205835878b55SSascha Wildner 	if(xpt_create_path(&pAdapter->path, /*periph */ NULL,
205935878b55SSascha Wildner 			cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD,
206035878b55SSascha Wildner 			CAM_LUN_WILDCARD) != CAM_REQ_CMP)
206135878b55SSascha Wildner 	{
206235878b55SSascha Wildner 		xpt_bus_deregister(cam_sim_path(hpt_vsim));
206335878b55SSascha Wildner 		cam_sim_free(hpt_vsim);
206435878b55SSascha Wildner 		hpt_vsim = NULL;
206535878b55SSascha Wildner 		return ENXIO;
206635878b55SSascha Wildner 	}
206735878b55SSascha Wildner 
206835878b55SSascha Wildner 	xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5);
206935878b55SSascha Wildner 	ccb->ccb_h.func_code = XPT_SASYNC_CB;
207035878b55SSascha Wildner 	ccb->csa.event_enable = AC_LOST_DEVICE;
207135878b55SSascha Wildner 	ccb->csa.callback = hpt_async;
207235878b55SSascha Wildner 	ccb->csa.callback_arg = hpt_vsim;
2073362298e4SSascha Wildner 	xpt_action(ccb);
207435878b55SSascha Wildner 	kfree(ccb, M_DEVBUF);
207535878b55SSascha Wildner 
207635878b55SSascha Wildner 	callout_init(&pAdapter->event_timer_connect);
207735878b55SSascha Wildner 	callout_init(&pAdapter->event_timer_disconnect);
207835878b55SSascha Wildner 
207935878b55SSascha Wildner 	if (device_get_unit(dev) == 0) {
208035878b55SSascha Wildner 		/* Start the work thread.  XXX */
208135878b55SSascha Wildner 		launch_worker_thread();
20822050a95dSSascha Wildner 
20832050a95dSSascha Wildner 		/*
20842050a95dSSascha Wildner 		 * hpt_worker_thread needs to be suspended after shutdown
20852050a95dSSascha Wildner 		 * sync, when fs sync finished.
20862050a95dSSascha Wildner 		 */
20872050a95dSSascha Wildner 		pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
20882050a95dSSascha Wildner 		    shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST);
208935878b55SSascha Wildner 	}
209035878b55SSascha Wildner 
209135878b55SSascha Wildner 	return 0;
209235878b55SSascha Wildner }
209335878b55SSascha Wildner 
209435878b55SSascha Wildner static int
209535878b55SSascha Wildner hpt_detach(device_t dev)
209635878b55SSascha Wildner {
209735878b55SSascha Wildner 	return (EBUSY);
209835878b55SSascha Wildner }
209935878b55SSascha Wildner 
210035878b55SSascha Wildner 
210135878b55SSascha Wildner /***************************************************************
210235878b55SSascha Wildner  * The poll function is used to simulate the interrupt when
210335878b55SSascha Wildner  * the interrupt subsystem is not functioning.
210435878b55SSascha Wildner  *
210535878b55SSascha Wildner  ***************************************************************/
210635878b55SSascha Wildner static void
210735878b55SSascha Wildner hpt_poll(struct cam_sim *sim)
210835878b55SSascha Wildner {
210935878b55SSascha Wildner 	hpt_intr((void *)cam_sim_softc(sim));
211035878b55SSascha Wildner }
211135878b55SSascha Wildner 
211235878b55SSascha Wildner /****************************************************************
211335878b55SSascha Wildner  *	Name:	hpt_intr
211435878b55SSascha Wildner  *	Description:	Interrupt handler.
211535878b55SSascha Wildner  ****************************************************************/
211635878b55SSascha Wildner static void
211735878b55SSascha Wildner hpt_intr(void *arg)
211835878b55SSascha Wildner {
211935878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg;
212035878b55SSascha Wildner 
2121c898d682SSascha Wildner 	lock_driver();
212235878b55SSascha Wildner 	/* KdPrintI(("----- Entering Isr() -----\n")); */
212335878b55SSascha Wildner 	if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE)
212435878b55SSascha Wildner 	{
212535878b55SSascha Wildner 		_VBUS_INST(&pAdapter->VBus)
212635878b55SSascha Wildner 		CheckPendingCall(_VBUS_P0);
212735878b55SSascha Wildner 	}
212835878b55SSascha Wildner 
212935878b55SSascha Wildner 	/* KdPrintI(("----- Leaving Isr() -----\n")); */
2130c898d682SSascha Wildner 	unlock_driver();
213135878b55SSascha Wildner }
213235878b55SSascha Wildner 
213335878b55SSascha Wildner /**********************************************************
213435878b55SSascha Wildner  * 			Asynchronous Events
213535878b55SSascha Wildner  *********************************************************/
213635878b55SSascha Wildner #if (!defined(UNREFERENCED_PARAMETER))
213735878b55SSascha Wildner #define UNREFERENCED_PARAMETER(x) (void)(x)
213835878b55SSascha Wildner #endif
213935878b55SSascha Wildner 
214035878b55SSascha Wildner static void
214135878b55SSascha Wildner hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path,
214235878b55SSascha Wildner     void * arg)
214335878b55SSascha Wildner {
214435878b55SSascha Wildner 	/* debug XXXX */
214535878b55SSascha Wildner 	panic("Here");
214635878b55SSascha Wildner 	UNREFERENCED_PARAMETER(callback_arg);
214735878b55SSascha Wildner 	UNREFERENCED_PARAMETER(code);
214835878b55SSascha Wildner 	UNREFERENCED_PARAMETER(path);
214935878b55SSascha Wildner 	UNREFERENCED_PARAMETER(arg);
215035878b55SSascha Wildner 
215135878b55SSascha Wildner }
215235878b55SSascha Wildner 
215335878b55SSascha Wildner static void
215435878b55SSascha Wildner FlushAdapter(IAL_ADAPTER_T *pAdapter)
215535878b55SSascha Wildner {
215635878b55SSascha Wildner 	int i;
215735878b55SSascha Wildner 
215835878b55SSascha Wildner 	hpt_printk(("flush all devices\n"));
215935878b55SSascha Wildner 
216035878b55SSascha Wildner 	/* flush all devices */
216135878b55SSascha Wildner 	for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) {
216235878b55SSascha Wildner 		PVDevice pVDev = pAdapter->VBus.pVDevice[i];
216335878b55SSascha Wildner 		if(pVDev) fFlushVDev(pVDev);
216435878b55SSascha Wildner 	}
216535878b55SSascha Wildner }
216635878b55SSascha Wildner 
216735878b55SSascha Wildner static int
216835878b55SSascha Wildner hpt_shutdown(device_t dev)
216935878b55SSascha Wildner {
217035878b55SSascha Wildner 		IAL_ADAPTER_T *pAdapter;
217135878b55SSascha Wildner 
217235878b55SSascha Wildner 		pAdapter = device_get_softc(dev);
217335878b55SSascha Wildner 		if (pAdapter == NULL)
217435878b55SSascha Wildner 			return (EINVAL);
217535878b55SSascha Wildner 
21762050a95dSSascha Wildner 		EVENTHANDLER_DEREGISTER(shutdown_post_sync, pAdapter->eh);
217735878b55SSascha Wildner 		FlushAdapter(pAdapter);
217835878b55SSascha Wildner 		  /* give the flush some time to happen,
217935878b55SSascha Wildner 		    *otherwise "shutdown -p now" will make file system corrupted */
218035878b55SSascha Wildner 		DELAY(1000 * 1000 * 5);
218135878b55SSascha Wildner 		return 0;
218235878b55SSascha Wildner }
218335878b55SSascha Wildner 
218435878b55SSascha Wildner void
218535878b55SSascha Wildner Check_Idle_Call(IAL_ADAPTER_T *pAdapter)
218635878b55SSascha Wildner {
218735878b55SSascha Wildner 	_VBUS_INST(&pAdapter->VBus)
218835878b55SSascha Wildner 
218935878b55SSascha Wildner 	if (mWaitingForIdle(_VBUS_P0)) {
219035878b55SSascha Wildner 		CheckIdleCall(_VBUS_P0);
219135878b55SSascha Wildner #ifdef SUPPORT_ARRAY
219235878b55SSascha Wildner 		{
219335878b55SSascha Wildner 			int i;
219435878b55SSascha Wildner 			PVDevice pArray;
219535878b55SSascha Wildner 			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){
219635878b55SSascha Wildner 				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
219735878b55SSascha Wildner 					continue;
219835878b55SSascha Wildner 				else if (pArray->u.array.rf_auto_rebuild) {
219935878b55SSascha Wildner 						KdPrint(("auto rebuild.\n"));
220035878b55SSascha Wildner 						pArray->u.array.rf_auto_rebuild = 0;
220135878b55SSascha Wildner 						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
220235878b55SSascha Wildner 				}
220335878b55SSascha Wildner 			}
220435878b55SSascha Wildner 		}
220535878b55SSascha Wildner #endif
220635878b55SSascha Wildner 	}
220735878b55SSascha Wildner 	/* launch the awaiting commands blocked by mWaitingForIdle */
220835878b55SSascha Wildner 	while(pAdapter->pending_Q!= NULL)
220935878b55SSascha Wildner 	{
221035878b55SSascha Wildner 		_VBUS_INST(&pAdapter->VBus)
221135878b55SSascha Wildner 		union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr;
221235878b55SSascha Wildner 		hpt_free_ccb(&pAdapter->pending_Q, ccb);
221335878b55SSascha Wildner 		CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb);
221435878b55SSascha Wildner 	}
221535878b55SSascha Wildner }
221635878b55SSascha Wildner 
221735878b55SSascha Wildner static void
221835878b55SSascha Wildner ccb_done(union ccb *ccb)
221935878b55SSascha Wildner {
222035878b55SSascha Wildner 	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
222135878b55SSascha Wildner 	IAL_ADAPTER_T * pAdapter = pmap->pAdapter;
222235878b55SSascha Wildner 	KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status));
222335878b55SSascha Wildner 
222435878b55SSascha Wildner 	dmamap_put(pmap);
222535878b55SSascha Wildner 	xpt_done(ccb);
222635878b55SSascha Wildner 
222735878b55SSascha Wildner 	pAdapter->outstandingCommands--;
222835878b55SSascha Wildner 
222935878b55SSascha Wildner 	if (pAdapter->outstandingCommands == 0)
223035878b55SSascha Wildner 	{
223135878b55SSascha Wildner 		if(DPC_Request_Nums == 0)
223235878b55SSascha Wildner 			Check_Idle_Call(pAdapter);
223335878b55SSascha Wildner 	}
223435878b55SSascha Wildner }
223535878b55SSascha Wildner 
223635878b55SSascha Wildner /****************************************************************
223735878b55SSascha Wildner  *	Name:	hpt_action
223835878b55SSascha Wildner  *	Description:	Process a queued command from the CAM layer.
223935878b55SSascha Wildner  *	Parameters:		sim - Pointer to SIM object
224035878b55SSascha Wildner  *					ccb - Pointer to SCSI command structure.
224135878b55SSascha Wildner  ****************************************************************/
224235878b55SSascha Wildner 
224335878b55SSascha Wildner void
224435878b55SSascha Wildner hpt_action(struct cam_sim *sim, union ccb *ccb)
224535878b55SSascha Wildner {
224635878b55SSascha Wildner 	IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim);
224735878b55SSascha Wildner 	PBUS_DMAMAP  pmap;
224835878b55SSascha Wildner 	_VBUS_INST(&pAdapter->VBus)
224935878b55SSascha Wildner 
225035878b55SSascha Wildner 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n"));
225135878b55SSascha Wildner 	KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code));
225235878b55SSascha Wildner 
225335878b55SSascha Wildner 	switch (ccb->ccb_h.func_code)
225435878b55SSascha Wildner 	{
225535878b55SSascha Wildner 		case XPT_SCSI_IO:	/* Execute the requested I/O operation */
225635878b55SSascha Wildner 		{
225735878b55SSascha Wildner 			/* ccb->ccb_h.path_id is not our bus id - don't check it */
225835878b55SSascha Wildner 
225935878b55SSascha Wildner 			if (ccb->ccb_h.target_lun)	{
226035878b55SSascha Wildner 				ccb->ccb_h.status = CAM_LUN_INVALID;
226135878b55SSascha Wildner 				xpt_done(ccb);
226235878b55SSascha Wildner 				return;
226335878b55SSascha Wildner 			}
226435878b55SSascha Wildner 			if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS ||
226535878b55SSascha Wildner 				pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) {
226635878b55SSascha Wildner 				ccb->ccb_h.status = CAM_TID_INVALID;
226735878b55SSascha Wildner 				xpt_done(ccb);
226835878b55SSascha Wildner 				return;
226935878b55SSascha Wildner 			}
227035878b55SSascha Wildner 
2271c898d682SSascha Wildner 			lock_driver();
227235878b55SSascha Wildner 			if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
227335878b55SSascha Wildner 				Check_Idle_Call(pAdapter);
227435878b55SSascha Wildner 
227535878b55SSascha Wildner 			pmap = dmamap_get(pAdapter);
227635878b55SSascha Wildner 			HPT_ASSERT(pmap);
227735878b55SSascha Wildner 			ccb->ccb_adapter = pmap;
227835878b55SSascha Wildner 			memset((void *)pmap->psg, 0,  sizeof(pmap->psg));
227935878b55SSascha Wildner 
228035878b55SSascha Wildner 			if (mWaitingForIdle(_VBUS_P0))
228135878b55SSascha Wildner 				hpt_queue_ccb(&pAdapter->pending_Q, ccb);
228235878b55SSascha Wildner 			else
228335878b55SSascha Wildner 				OsSendCommand(_VBUS_P ccb);
2284c898d682SSascha Wildner 			unlock_driver();
228535878b55SSascha Wildner 
228635878b55SSascha Wildner 			/* KdPrint(("leave scsiio\n")); */
228735878b55SSascha Wildner 			break;
228835878b55SSascha Wildner 		}
228935878b55SSascha Wildner 
229035878b55SSascha Wildner 		case XPT_RESET_BUS:
229135878b55SSascha Wildner 			KdPrint(("reset bus\n"));
2292c898d682SSascha Wildner 			lock_driver();
229335878b55SSascha Wildner 			fResetVBus(_VBUS_P0);
2294c898d682SSascha Wildner 			unlock_driver();
229535878b55SSascha Wildner 			xpt_done(ccb);
229635878b55SSascha Wildner 			break;
229735878b55SSascha Wildner 
229835878b55SSascha Wildner 		case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
229935878b55SSascha Wildner 		case XPT_EN_LUN:		/* Enable LUN as a target */
230035878b55SSascha Wildner 		case XPT_TARGET_IO:		/* Execute target I/O request */
230135878b55SSascha Wildner 		case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
230235878b55SSascha Wildner 		case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
230335878b55SSascha Wildner 		case XPT_ABORT:			/* Abort the specified CCB */
230435878b55SSascha Wildner 		case XPT_TERM_IO:		/* Terminate the I/O process */
230535878b55SSascha Wildner 			/* XXX Implement */
230635878b55SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_INVALID;
230735878b55SSascha Wildner 			xpt_done(ccb);
230835878b55SSascha Wildner 			break;
230935878b55SSascha Wildner 
231035878b55SSascha Wildner 		case XPT_GET_TRAN_SETTINGS:
231135878b55SSascha Wildner 		case XPT_SET_TRAN_SETTINGS:
231235878b55SSascha Wildner 			/* XXX Implement */
231335878b55SSascha Wildner 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
231435878b55SSascha Wildner 			xpt_done(ccb);
231535878b55SSascha Wildner 			break;
231635878b55SSascha Wildner 
231735878b55SSascha Wildner 		case XPT_CALC_GEOMETRY:
231835878b55SSascha Wildner 		{
231935878b55SSascha Wildner 			struct	  ccb_calc_geometry *ccg;
232035878b55SSascha Wildner 			u_int32_t size_mb;
232135878b55SSascha Wildner 			u_int32_t secs_per_cylinder;
232235878b55SSascha Wildner 
232335878b55SSascha Wildner 			ccg = &ccb->ccg;
232435878b55SSascha Wildner 			size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);
232535878b55SSascha Wildner 
232635878b55SSascha Wildner 			if (size_mb > 1024 ) {
232735878b55SSascha Wildner 				ccg->heads = 255;
232835878b55SSascha Wildner 				ccg->secs_per_track = 63;
232935878b55SSascha Wildner 			} else {
233035878b55SSascha Wildner 				ccg->heads = 64;
233135878b55SSascha Wildner 				ccg->secs_per_track = 32;
233235878b55SSascha Wildner 			}
233335878b55SSascha Wildner 			secs_per_cylinder = ccg->heads * ccg->secs_per_track;
233435878b55SSascha Wildner 			ccg->cylinders = ccg->volume_size / secs_per_cylinder;
233535878b55SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_CMP;
233635878b55SSascha Wildner 			xpt_done(ccb);
233735878b55SSascha Wildner 			break;
233835878b55SSascha Wildner 		}
233935878b55SSascha Wildner 
234035878b55SSascha Wildner 		case XPT_PATH_INQ:		/* Path routing inquiry */
234135878b55SSascha Wildner 		{
234235878b55SSascha Wildner 			struct ccb_pathinq *cpi = &ccb->cpi;
234335878b55SSascha Wildner 
234435878b55SSascha Wildner 			cpi->version_num = 1; /* XXX??? */
234535878b55SSascha Wildner 			cpi->hba_inquiry = PI_SDTR_ABLE;
234635878b55SSascha Wildner 			cpi->target_sprt = 0;
234735878b55SSascha Wildner 			/* Not necessary to reset bus */
234835878b55SSascha Wildner 			cpi->hba_misc = PIM_NOBUSRESET;
234935878b55SSascha Wildner 			cpi->hba_eng_cnt = 0;
235035878b55SSascha Wildner 
235135878b55SSascha Wildner 			cpi->max_target = MAX_VDEVICE_PER_VBUS;
235235878b55SSascha Wildner 			cpi->max_lun = 0;
235335878b55SSascha Wildner 			cpi->initiator_id = MAX_VDEVICE_PER_VBUS;
235435878b55SSascha Wildner 
235535878b55SSascha Wildner 			cpi->bus_id = cam_sim_bus(sim);
235635878b55SSascha Wildner 			cpi->base_transfer_speed = 3300;
235735878b55SSascha Wildner 			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
235835878b55SSascha Wildner 			strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
235935878b55SSascha Wildner 			strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
236035878b55SSascha Wildner 			cpi->unit_number = cam_sim_unit(sim);
236135878b55SSascha Wildner 			cpi->transport = XPORT_SPI;
236235878b55SSascha Wildner 			cpi->transport_version = 2;
236335878b55SSascha Wildner 			cpi->protocol = PROTO_SCSI;
236435878b55SSascha Wildner 			cpi->protocol_version = SCSI_REV_2;
2365*ea778d16SSascha Wildner 			cpi->maxio = HPTMV_DFLTPHYS;
236635878b55SSascha Wildner 			cpi->ccb_h.status = CAM_REQ_CMP;
236735878b55SSascha Wildner 			xpt_done(ccb);
236835878b55SSascha Wildner 			break;
236935878b55SSascha Wildner 		}
237035878b55SSascha Wildner 
237135878b55SSascha Wildner 		default:
237235878b55SSascha Wildner 			KdPrint(("invalid cmd\n"));
237335878b55SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_INVALID;
237435878b55SSascha Wildner 			xpt_done(ccb);
237535878b55SSascha Wildner 			break;
237635878b55SSascha Wildner 	}
237735878b55SSascha Wildner 	/* KdPrint(("leave hpt_action..............\n")); */
237835878b55SSascha Wildner }
237935878b55SSascha Wildner 
238035878b55SSascha Wildner /* shall be called at lock_driver() */
238135878b55SSascha Wildner static void
238235878b55SSascha Wildner hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb)
238335878b55SSascha Wildner {
238435878b55SSascha Wildner 	if(*ccb_Q == NULL)
238535878b55SSascha Wildner 		ccb->ccb_h.ccb_ccb_ptr = ccb;
238635878b55SSascha Wildner 	else {
238735878b55SSascha Wildner 		ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr;
238835878b55SSascha Wildner 		(*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb;
238935878b55SSascha Wildner 	}
239035878b55SSascha Wildner 
239135878b55SSascha Wildner 	*ccb_Q = ccb;
239235878b55SSascha Wildner }
239335878b55SSascha Wildner 
239435878b55SSascha Wildner /* shall be called at lock_driver() */
239535878b55SSascha Wildner static void
239635878b55SSascha Wildner hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb)
239735878b55SSascha Wildner {
239835878b55SSascha Wildner 	union ccb *TempCCB;
239935878b55SSascha Wildner 
240035878b55SSascha Wildner 	TempCCB = *ccb_Q;
240135878b55SSascha Wildner 
240235878b55SSascha Wildner 	if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/
240335878b55SSascha Wildner 		*ccb_Q = NULL;
240435878b55SSascha Wildner 	else {
240535878b55SSascha Wildner 		while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb)
240635878b55SSascha Wildner 			TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr;
240735878b55SSascha Wildner 
240835878b55SSascha Wildner 		TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr;
240935878b55SSascha Wildner 
241035878b55SSascha Wildner 		if(*ccb_Q == ccb)
241135878b55SSascha Wildner 			*ccb_Q = TempCCB;
241235878b55SSascha Wildner 	}
241335878b55SSascha Wildner }
241435878b55SSascha Wildner 
241535878b55SSascha Wildner #ifdef SUPPORT_ARRAY
241635878b55SSascha Wildner /***************************************************************************
241735878b55SSascha Wildner  * Function:     hpt_worker_thread
241835878b55SSascha Wildner  * Description:  Do background rebuilding. Execute in kernel thread context.
241935878b55SSascha Wildner  * Returns:      None
242035878b55SSascha Wildner  ***************************************************************************/
242135878b55SSascha Wildner static void hpt_worker_thread(void)
242235878b55SSascha Wildner {
242335878b55SSascha Wildner 	for(;;)	{
242435878b55SSascha Wildner 		while (DpcQueue_First!=DpcQueue_Last) {
242535878b55SSascha Wildner 			ST_HPT_DPC p;
2426c898d682SSascha Wildner 			lock_driver();
242735878b55SSascha Wildner 			p = DpcQueue[DpcQueue_First];
242835878b55SSascha Wildner 			DpcQueue_First++;
242935878b55SSascha Wildner 			DpcQueue_First %= MAX_DPC;
243035878b55SSascha Wildner 			DPC_Request_Nums++;
2431c898d682SSascha Wildner 			unlock_driver();
243235878b55SSascha Wildner 			p.dpc(p.pAdapter, p.arg, p.flags);
243335878b55SSascha Wildner 
2434c898d682SSascha Wildner 			lock_driver();
243535878b55SSascha Wildner 			DPC_Request_Nums--;
243635878b55SSascha Wildner 			/* since we may have prevented Check_Idle_Call, do it here */
243735878b55SSascha Wildner 			if (DPC_Request_Nums==0) {
243835878b55SSascha Wildner 				if (p.pAdapter->outstandingCommands == 0) {
243935878b55SSascha Wildner 					_VBUS_INST(&p.pAdapter->VBus);
244035878b55SSascha Wildner 					Check_Idle_Call(p.pAdapter);
244135878b55SSascha Wildner 					CheckPendingCall(_VBUS_P0);
244235878b55SSascha Wildner 				}
244335878b55SSascha Wildner 			}
2444c898d682SSascha Wildner 			unlock_driver();
244535878b55SSascha Wildner 
244635878b55SSascha Wildner 			/*Schedule out*/
244735878b55SSascha Wildner 			tsleep((caddr_t)hpt_worker_thread, 0, "sched", 1);
244835878b55SSascha Wildner 			if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) {
244935878b55SSascha Wildner 				/* abort rebuilding process. */
245035878b55SSascha Wildner 				IAL_ADAPTER_T *pAdapter;
245135878b55SSascha Wildner 				PVDevice      pArray;
245235878b55SSascha Wildner 				PVBus         _vbus_p;
245335878b55SSascha Wildner 				int i;
245435878b55SSascha Wildner 				pAdapter = gIal_Adapter;
245535878b55SSascha Wildner 
24564090d6ffSSascha Wildner 				while(pAdapter != NULL){
245735878b55SSascha Wildner 
245835878b55SSascha Wildner 					_vbus_p = &pAdapter->VBus;
245935878b55SSascha Wildner 
246035878b55SSascha Wildner 					for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
246135878b55SSascha Wildner 					{
246235878b55SSascha Wildner 						if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
246335878b55SSascha Wildner 							continue;
246435878b55SSascha Wildner 						else if (pArray->u.array.rf_rebuilding ||
246535878b55SSascha Wildner 								pArray->u.array.rf_verifying ||
246635878b55SSascha Wildner 								pArray->u.array.rf_initializing)
246735878b55SSascha Wildner 							{
246835878b55SSascha Wildner 								pArray->u.array.rf_abort_rebuild = 1;
246935878b55SSascha Wildner 							}
247035878b55SSascha Wildner 					}
247135878b55SSascha Wildner 					pAdapter = pAdapter->next;
247235878b55SSascha Wildner 				}
247335878b55SSascha Wildner 			}
247435878b55SSascha Wildner 		}
247535878b55SSascha Wildner 
247635878b55SSascha Wildner /*Remove this debug option*/
247735878b55SSascha Wildner /*
247835878b55SSascha Wildner #ifdef DEBUG
247935878b55SSascha Wildner 		if (SIGISMEMBER(curproc->p_siglist, SIGSTOP))
248035878b55SSascha Wildner 			tsleep((caddr_t)hpt_worker_thread, 0, "hptrdy", 2*hz);
248135878b55SSascha Wildner #endif
248235878b55SSascha Wildner */
248335878b55SSascha Wildner 		kproc_suspend_loop();
248435878b55SSascha Wildner 		tsleep((caddr_t)hpt_worker_thread, 0, "hptrdy", 2*hz);  /* wait for something to do */
248535878b55SSascha Wildner 	}
248635878b55SSascha Wildner }
248735878b55SSascha Wildner 
248835878b55SSascha Wildner static struct kproc_desc hpt_kp = {
248935878b55SSascha Wildner 	"hpt_wt",
249035878b55SSascha Wildner 	hpt_worker_thread,
249135878b55SSascha Wildner 	&hptdaemonproc
249235878b55SSascha Wildner };
249335878b55SSascha Wildner 
249435878b55SSascha Wildner /*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/
249535878b55SSascha Wildner static void
249635878b55SSascha Wildner launch_worker_thread(void)
249735878b55SSascha Wildner {
249835878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapTemp;
249935878b55SSascha Wildner 
250035878b55SSascha Wildner 	kproc_start(&hpt_kp);
250135878b55SSascha Wildner 
250235878b55SSascha Wildner 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
250335878b55SSascha Wildner 
250435878b55SSascha Wildner 		_VBUS_INST(&pAdapTemp->VBus)
250535878b55SSascha Wildner 		int i;
250635878b55SSascha Wildner 		PVDevice pVDev;
250735878b55SSascha Wildner 
250835878b55SSascha Wildner 		for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
250935878b55SSascha Wildner 			if ((pVDev=ArrayTables(i))->u.array.dArStamp==0)
251035878b55SSascha Wildner 				continue;
251135878b55SSascha Wildner 			else{
251235878b55SSascha Wildner 				if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding)
251335878b55SSascha Wildner 					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev,
251435878b55SSascha Wildner 					(UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
251535878b55SSascha Wildner 			}
251635878b55SSascha Wildner 	}
251735878b55SSascha Wildner }
251835878b55SSascha Wildner /*
251935878b55SSascha Wildner  *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL);
252035878b55SSascha Wildner */
252135878b55SSascha Wildner 
252235878b55SSascha Wildner #endif
252335878b55SSascha Wildner 
252435878b55SSascha Wildner /********************************************************************************/
252535878b55SSascha Wildner 
252635878b55SSascha Wildner int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical)
252735878b55SSascha Wildner {
252835878b55SSascha Wildner 	union ccb *ccb = (union ccb *)pCmd->pOrgCommand;
252935878b55SSascha Wildner 	bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
253035878b55SSascha Wildner 	int idx;
253135878b55SSascha Wildner 
253235878b55SSascha Wildner 	if(logical) {
253335878b55SSascha Wildner 		if (ccb->ccb_h.flags & CAM_DATA_PHYS)
253435878b55SSascha Wildner 			panic("physical address unsupported");
253535878b55SSascha Wildner 
253635878b55SSascha Wildner 		if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
253735878b55SSascha Wildner 			if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
253835878b55SSascha Wildner 				panic("physical address unsupported");
253935878b55SSascha Wildner 
254035878b55SSascha Wildner 			for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
254135878b55SSascha Wildner 				pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr;
254235878b55SSascha Wildner 				pSg[idx].wSgSize = sgList[idx].ds_len;
254335878b55SSascha Wildner 				pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0;
254435878b55SSascha Wildner 			}
254535878b55SSascha Wildner 		}
254635878b55SSascha Wildner 		else {
254735878b55SSascha Wildner 			pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr;
254835878b55SSascha Wildner 			pSg->wSgSize = ccb->csio.dxfer_len;
254935878b55SSascha Wildner 			pSg->wSgFlag = SG_FLAG_EOT;
255035878b55SSascha Wildner 		}
255135878b55SSascha Wildner 		return TRUE;
255235878b55SSascha Wildner 	}
255335878b55SSascha Wildner 
255435878b55SSascha Wildner 	/* since we have provided physical sg, nobody will ask us to build physical sg */
255535878b55SSascha Wildner 	HPT_ASSERT(0);
255635878b55SSascha Wildner 	return FALSE;
255735878b55SSascha Wildner }
255835878b55SSascha Wildner 
255935878b55SSascha Wildner /*******************************************************************************/
256035878b55SSascha Wildner ULONG HPTLIBAPI
256135878b55SSascha Wildner GetStamp(void)
256235878b55SSascha Wildner {
256335878b55SSascha Wildner 	/*
256435878b55SSascha Wildner 	 * the system variable, ticks, can't be used since it hasn't yet been active
256535878b55SSascha Wildner 	 * when our driver starts (ticks==0, it's a invalid stamp value)
256635878b55SSascha Wildner 	 */
256735878b55SSascha Wildner 	ULONG stamp;
256835878b55SSascha Wildner 	do { stamp = krandom(); } while (stamp==0);
256935878b55SSascha Wildner 	return stamp;
257035878b55SSascha Wildner }
257135878b55SSascha Wildner 
257235878b55SSascha Wildner 
257335878b55SSascha Wildner static void
257435878b55SSascha Wildner SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev)
257535878b55SSascha Wildner {
257635878b55SSascha Wildner 	int i;
257735878b55SSascha Wildner 	IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice;
257835878b55SSascha Wildner 
257935878b55SSascha Wildner 	inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/
258035878b55SSascha Wildner 	inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5);
258135878b55SSascha Wildner #ifndef SERIAL_CMDS
258235878b55SSascha Wildner 	inquiryData->CommandQueue = 1;
258335878b55SSascha Wildner #endif
258435878b55SSascha Wildner 
258535878b55SSascha Wildner 	switch(pVDev->VDeviceType) {
258635878b55SSascha Wildner 	case VD_SINGLE_DISK:
258735878b55SSascha Wildner 	case VD_ATAPI:
258835878b55SSascha Wildner 	case VD_REMOVABLE:
258935878b55SSascha Wildner 		/* Set the removable bit, if applicable. */
259035878b55SSascha Wildner 		if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80))
259135878b55SSascha Wildner 			inquiryData->RemovableMedia = 1;
259235878b55SSascha Wildner 
259335878b55SSascha Wildner 		/* Fill in vendor identification fields. */
259435878b55SSascha Wildner 		for (i = 0; i < 20; i += 2) {
259535878b55SSascha Wildner 			inquiryData->VendorId[i] 	= ((PUCHAR)pIdentify->ModelNumber)[i + 1];
259635878b55SSascha Wildner 			inquiryData->VendorId[i+1] 	= ((PUCHAR)pIdentify->ModelNumber)[i];
259735878b55SSascha Wildner 
259835878b55SSascha Wildner 		}
259935878b55SSascha Wildner 
260035878b55SSascha Wildner 		/* Initialize unused portion of product id. */
260135878b55SSascha Wildner 		for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' ';
260235878b55SSascha Wildner 
260335878b55SSascha Wildner 		/* firmware revision */
260435878b55SSascha Wildner 		for (i = 0; i < 4; i += 2)
260535878b55SSascha Wildner 		{
260635878b55SSascha Wildner 			inquiryData->ProductRevisionLevel[i] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i+1];
260735878b55SSascha Wildner 			inquiryData->ProductRevisionLevel[i+1] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i];
260835878b55SSascha Wildner 		}
260935878b55SSascha Wildner 		break;
261035878b55SSascha Wildner 	default:
261135878b55SSascha Wildner 		memcpy(&inquiryData->VendorId, "RR18xx  ", 8);
261235878b55SSascha Wildner #ifdef SUPPORT_ARRAY
261335878b55SSascha Wildner 		switch(pVDev->VDeviceType){
261435878b55SSascha Wildner 		case VD_RAID_0:
261535878b55SSascha Wildner 			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
261635878b55SSascha Wildner 				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
261735878b55SSascha Wildner 				memcpy(&inquiryData->ProductId, "RAID 1/0 Array  ", 16);
261835878b55SSascha Wildner 			else
261935878b55SSascha Wildner 				memcpy(&inquiryData->ProductId, "RAID 0 Array    ", 16);
262035878b55SSascha Wildner 			break;
262135878b55SSascha Wildner 		case VD_RAID_1:
262235878b55SSascha Wildner 			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
262335878b55SSascha Wildner 				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
262435878b55SSascha Wildner 				memcpy(&inquiryData->ProductId, "RAID 0/1 Array  ", 16);
262535878b55SSascha Wildner 			else
262635878b55SSascha Wildner 				memcpy(&inquiryData->ProductId, "RAID 1 Array    ", 16);
262735878b55SSascha Wildner 			break;
262835878b55SSascha Wildner 		case VD_RAID_5:
262935878b55SSascha Wildner 			memcpy(&inquiryData->ProductId, "RAID 5 Array    ", 16);
263035878b55SSascha Wildner 			break;
263135878b55SSascha Wildner 		case VD_JBOD:
263235878b55SSascha Wildner 			memcpy(&inquiryData->ProductId, "JBOD Array      ", 16);
263335878b55SSascha Wildner 			break;
263435878b55SSascha Wildner 		}
263535878b55SSascha Wildner #endif
263635878b55SSascha Wildner 		memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4);
263735878b55SSascha Wildner 		break;
263835878b55SSascha Wildner 	}
263935878b55SSascha Wildner }
264035878b55SSascha Wildner 
264135878b55SSascha Wildner static void
264235878b55SSascha Wildner hpt_timeout(void *arg)
264335878b55SSascha Wildner {
264435878b55SSascha Wildner 	_VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus)
2645c898d682SSascha Wildner 	lock_driver();
264635878b55SSascha Wildner 	fResetVBus(_VBUS_P0);
2647c898d682SSascha Wildner 	unlock_driver();
264835878b55SSascha Wildner }
264935878b55SSascha Wildner 
265035878b55SSascha Wildner static void
265135878b55SSascha Wildner hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
265235878b55SSascha Wildner {
265335878b55SSascha Wildner 	PCommand pCmd = (PCommand)arg;
265435878b55SSascha Wildner 	union ccb *ccb = pCmd->pOrgCommand;
265535878b55SSascha Wildner 	struct ccb_hdr *ccb_h = &ccb->ccb_h;
265635878b55SSascha Wildner 	PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter;
265735878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
265835878b55SSascha Wildner 	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
265935878b55SSascha Wildner 	FPSCAT_GATH psg = pCmd->pSgTable;
266035878b55SSascha Wildner 	int idx;
266135878b55SSascha Wildner 	_VBUS_INST(pVDev->pVBus)
266235878b55SSascha Wildner 
266335878b55SSascha Wildner 	HPT_ASSERT(pCmd->cf_physical_sg);
266435878b55SSascha Wildner 
266535878b55SSascha Wildner 	if (error || nsegs == 0)
266635878b55SSascha Wildner 		panic("busdma error");
266735878b55SSascha Wildner 
266835878b55SSascha Wildner 	HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS);
266935878b55SSascha Wildner 
267035878b55SSascha Wildner 	for (idx = 0; idx < nsegs; idx++, psg++) {
267135878b55SSascha Wildner 		psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr;
267235878b55SSascha Wildner 		psg->wSgSize = segs[idx].ds_len;
267335878b55SSascha Wildner 		psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0;
267435878b55SSascha Wildner /*		KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */
267535878b55SSascha Wildner 	}
267635878b55SSascha Wildner /*	psg[-1].wSgFlag = SG_FLAG_EOT; */
267735878b55SSascha Wildner 
267835878b55SSascha Wildner 	if (pCmd->cf_data_in) {
267935878b55SSascha Wildner 		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD);
268035878b55SSascha Wildner 	}
268135878b55SSascha Wildner 	else if (pCmd->cf_data_out) {
268235878b55SSascha Wildner 		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE);
268335878b55SSascha Wildner 	}
268435878b55SSascha Wildner 
268535878b55SSascha Wildner 	callout_reset(&ccb->ccb_h.timeout_ch, 20*hz, hpt_timeout, ccb);
268635878b55SSascha Wildner 	pVDev->pfnSendCommand(_VBUS_P pCmd);
268735878b55SSascha Wildner 	CheckPendingCall(_VBUS_P0);
268835878b55SSascha Wildner }
268935878b55SSascha Wildner 
269035878b55SSascha Wildner 
269135878b55SSascha Wildner 
269235878b55SSascha Wildner static void HPTLIBAPI
269335878b55SSascha Wildner OsSendCommand(_VBUS_ARG union ccb *ccb)
269435878b55SSascha Wildner {
269535878b55SSascha Wildner 	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
269635878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
269735878b55SSascha Wildner 	struct ccb_hdr *ccb_h = &ccb->ccb_h;
269835878b55SSascha Wildner 	struct ccb_scsiio *csio = &ccb->csio;
269935878b55SSascha Wildner 	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
270035878b55SSascha Wildner 
270135878b55SSascha Wildner 	KdPrintI(("OsSendCommand: ccb %p  cdb %x-%x-%x\n",
270235878b55SSascha Wildner 		ccb,
270335878b55SSascha Wildner 		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0],
270435878b55SSascha Wildner 		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4],
270535878b55SSascha Wildner 		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8]
270635878b55SSascha Wildner 	));
270735878b55SSascha Wildner 
270835878b55SSascha Wildner 	pAdapter->outstandingCommands++;
270935878b55SSascha Wildner 
271035878b55SSascha Wildner 	if (pVDev == NULL || pVDev->vf_online == 0) {
271135878b55SSascha Wildner 		ccb->ccb_h.status = CAM_REQ_INVALID;
271235878b55SSascha Wildner 		ccb_done(ccb);
271335878b55SSascha Wildner 		goto Command_Complished;
271435878b55SSascha Wildner 	}
271535878b55SSascha Wildner 
271635878b55SSascha Wildner 	switch(ccb->csio.cdb_io.cdb_bytes[0])
271735878b55SSascha Wildner 	{
271835878b55SSascha Wildner 		case TEST_UNIT_READY:
271935878b55SSascha Wildner 		case START_STOP_UNIT:
272035878b55SSascha Wildner 		case SYNCHRONIZE_CACHE:
272135878b55SSascha Wildner 			/* FALLTHROUGH */
272235878b55SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_CMP;
272335878b55SSascha Wildner 			break;
272435878b55SSascha Wildner 
272535878b55SSascha Wildner 		case INQUIRY:
272635878b55SSascha Wildner 			ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len);
272735878b55SSascha Wildner 			SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev);
272835878b55SSascha Wildner 			ccb_h->status = CAM_REQ_CMP;
272935878b55SSascha Wildner 			break;
273035878b55SSascha Wildner 
273135878b55SSascha Wildner 		case READ_CAPACITY:
273235878b55SSascha Wildner 		{
273335878b55SSascha Wildner 			UCHAR *rbuf=csio->data_ptr;
273435878b55SSascha Wildner 			unsigned int cap;
273535878b55SSascha Wildner 
273635878b55SSascha Wildner 			if (pVDev->VDeviceCapacity > 0xfffffffful) {
273735878b55SSascha Wildner 				cap = 0xfffffffful;
273835878b55SSascha Wildner 			} else {
273935878b55SSascha Wildner 				cap = pVDev->VDeviceCapacity - 1;
274035878b55SSascha Wildner 			}
274135878b55SSascha Wildner 
274235878b55SSascha Wildner 			rbuf[0] = (UCHAR)(cap>>24);
274335878b55SSascha Wildner 			rbuf[1] = (UCHAR)(cap>>16);
274435878b55SSascha Wildner 			rbuf[2] = (UCHAR)(cap>>8);
274535878b55SSascha Wildner 			rbuf[3] = (UCHAR)cap;
274635878b55SSascha Wildner 			/* Claim 512 byte blocks (big-endian). */
274735878b55SSascha Wildner 			rbuf[4] = 0;
274835878b55SSascha Wildner 			rbuf[5] = 0;
274935878b55SSascha Wildner 			rbuf[6] = 2;
275035878b55SSascha Wildner 			rbuf[7] = 0;
275135878b55SSascha Wildner 
275235878b55SSascha Wildner 			ccb_h->status = CAM_REQ_CMP;
275335878b55SSascha Wildner 			break;
275435878b55SSascha Wildner 		}
275535878b55SSascha Wildner 
275635878b55SSascha Wildner 		case 0x9e: /*SERVICE_ACTION_IN*/
275735878b55SSascha Wildner 		{
275835878b55SSascha Wildner 			UCHAR *rbuf = csio->data_ptr;
275935878b55SSascha Wildner 			LBA_T cap = pVDev->VDeviceCapacity - 1;
276035878b55SSascha Wildner 
276135878b55SSascha Wildner 			rbuf[0] = (UCHAR)(cap>>56);
276235878b55SSascha Wildner 			rbuf[1] = (UCHAR)(cap>>48);
276335878b55SSascha Wildner 			rbuf[2] = (UCHAR)(cap>>40);
276435878b55SSascha Wildner 			rbuf[3] = (UCHAR)(cap>>32);
276535878b55SSascha Wildner 			rbuf[4] = (UCHAR)(cap>>24);
276635878b55SSascha Wildner 			rbuf[5] = (UCHAR)(cap>>16);
276735878b55SSascha Wildner 			rbuf[6] = (UCHAR)(cap>>8);
276835878b55SSascha Wildner 			rbuf[7] = (UCHAR)cap;
276935878b55SSascha Wildner 			rbuf[8] = 0;
277035878b55SSascha Wildner 			rbuf[9] = 0;
277135878b55SSascha Wildner 			rbuf[10] = 2;
277235878b55SSascha Wildner 			rbuf[11] = 0;
277335878b55SSascha Wildner 
277435878b55SSascha Wildner 			ccb_h->status = CAM_REQ_CMP;
277535878b55SSascha Wildner 			break;
277635878b55SSascha Wildner 		}
277735878b55SSascha Wildner 
277835878b55SSascha Wildner 		case READ_6:
277935878b55SSascha Wildner 		case WRITE_6:
278035878b55SSascha Wildner 		case READ_10:
278135878b55SSascha Wildner 		case WRITE_10:
278235878b55SSascha Wildner 		case 0x88: /* READ_16 */
278335878b55SSascha Wildner 		case 0x8a: /* WRITE_16 */
278435878b55SSascha Wildner 		case 0x13:
278535878b55SSascha Wildner 		case 0x2f:
278635878b55SSascha Wildner 		{
278735878b55SSascha Wildner 			UCHAR Cdb[16];
278835878b55SSascha Wildner 			UCHAR CdbLength;
278935878b55SSascha Wildner 			_VBUS_INST(pVDev->pVBus)
279035878b55SSascha Wildner 			PCommand pCmd = AllocateCommand(_VBUS_P0);
279135878b55SSascha Wildner 			HPT_ASSERT(pCmd);
279235878b55SSascha Wildner 
279335878b55SSascha Wildner 			CdbLength = csio->cdb_len;
279435878b55SSascha Wildner 			if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
279535878b55SSascha Wildner 			{
279635878b55SSascha Wildner 				if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0)
279735878b55SSascha Wildner 				{
279835878b55SSascha Wildner 					bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength);
279935878b55SSascha Wildner 				}
280035878b55SSascha Wildner 				else
280135878b55SSascha Wildner 				{
280235878b55SSascha Wildner 					KdPrintE(("ERROR!!!\n"));
280335878b55SSascha Wildner 					ccb->ccb_h.status = CAM_REQ_INVALID;
280435878b55SSascha Wildner 					break;
280535878b55SSascha Wildner 				}
280635878b55SSascha Wildner 			}
280735878b55SSascha Wildner 			else
280835878b55SSascha Wildner 			{
280935878b55SSascha Wildner 				bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength);
281035878b55SSascha Wildner 			}
281135878b55SSascha Wildner 
281235878b55SSascha Wildner 			pCmd->pOrgCommand = ccb;
281335878b55SSascha Wildner 			pCmd->pVDevice = pVDev;
281435878b55SSascha Wildner 			pCmd->pfnCompletion = fOsCommandDone;
281535878b55SSascha Wildner 			pCmd->pfnBuildSgl = fOsBuildSgl;
281635878b55SSascha Wildner 			pCmd->pSgTable = pmap->psg;
281735878b55SSascha Wildner 
281835878b55SSascha Wildner 			switch (Cdb[0])
281935878b55SSascha Wildner 			{
282035878b55SSascha Wildner 				case READ_6:
282135878b55SSascha Wildner 				case WRITE_6:
282235878b55SSascha Wildner 				case 0x13:
282335878b55SSascha Wildner 					pCmd->uCmd.Ide.Lba =  ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3];
282435878b55SSascha Wildner 					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4];
282535878b55SSascha Wildner 					break;
282635878b55SSascha Wildner 
282735878b55SSascha Wildner 				case 0x88: /* READ_16 */
282835878b55SSascha Wildner 				case 0x8a: /* WRITE_16 */
282935878b55SSascha Wildner 					pCmd->uCmd.Ide.Lba =
283035878b55SSascha Wildner 						(HPT_U64)Cdb[2] << 56 |
283135878b55SSascha Wildner 						(HPT_U64)Cdb[3] << 48 |
283235878b55SSascha Wildner 						(HPT_U64)Cdb[4] << 40 |
283335878b55SSascha Wildner 						(HPT_U64)Cdb[5] << 32 |
283435878b55SSascha Wildner 						(HPT_U64)Cdb[6] << 24 |
283535878b55SSascha Wildner 						(HPT_U64)Cdb[7] << 16 |
283635878b55SSascha Wildner 						(HPT_U64)Cdb[8] << 8 |
283735878b55SSascha Wildner 						(HPT_U64)Cdb[9];
283835878b55SSascha Wildner 					pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13];
283935878b55SSascha Wildner 					break;
284035878b55SSascha Wildner 
284135878b55SSascha Wildner 				default:
284235878b55SSascha Wildner 					pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24);
284335878b55SSascha Wildner 					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8);
284435878b55SSascha Wildner 					break;
284535878b55SSascha Wildner 			}
284635878b55SSascha Wildner 
284735878b55SSascha Wildner 			switch (Cdb[0])
284835878b55SSascha Wildner 			{
284935878b55SSascha Wildner 				case READ_6:
285035878b55SSascha Wildner 				case READ_10:
285135878b55SSascha Wildner 				case 0x88: /* READ_16 */
285235878b55SSascha Wildner 					pCmd->uCmd.Ide.Command = IDE_COMMAND_READ;
285335878b55SSascha Wildner 					pCmd->cf_data_in = 1;
285435878b55SSascha Wildner 					break;
285535878b55SSascha Wildner 
285635878b55SSascha Wildner 				case WRITE_6:
285735878b55SSascha Wildner 				case WRITE_10:
285835878b55SSascha Wildner 				case 0x8a: /* WRITE_16 */
285935878b55SSascha Wildner 					pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE;
286035878b55SSascha Wildner 					pCmd->cf_data_out = 1;
286135878b55SSascha Wildner 					break;
286235878b55SSascha Wildner 				case 0x13:
286335878b55SSascha Wildner 				case 0x2f:
286435878b55SSascha Wildner 					pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY;
286535878b55SSascha Wildner 					break;
286635878b55SSascha Wildner 			}
286735878b55SSascha Wildner /*///////////////////////// */
286835878b55SSascha Wildner 			if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
286935878b55SSascha Wildner 				int idx;
287035878b55SSascha Wildner 				bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
287135878b55SSascha Wildner 
287235878b55SSascha Wildner 				if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
287335878b55SSascha Wildner 					pCmd->cf_physical_sg = 1;
287435878b55SSascha Wildner 
287535878b55SSascha Wildner 				for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
287635878b55SSascha Wildner 					pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr;
287735878b55SSascha Wildner 					pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len;
287835878b55SSascha Wildner 					pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0;
287935878b55SSascha Wildner 				}
288035878b55SSascha Wildner 
288135878b55SSascha Wildner 				callout_reset(&ccb->ccb_h.timeout_ch, 20*hz, hpt_timeout, ccb);
288235878b55SSascha Wildner 				pVDev->pfnSendCommand(_VBUS_P pCmd);
288335878b55SSascha Wildner 			}
288435878b55SSascha Wildner 			else {
288535878b55SSascha Wildner 				int error;
288635878b55SSascha Wildner 				pCmd->cf_physical_sg = 1;
288735878b55SSascha Wildner 				error = bus_dmamap_load(pAdapter->io_dma_parent,
288835878b55SSascha Wildner 							pmap->dma_map,
288935878b55SSascha Wildner 							ccb->csio.data_ptr, ccb->csio.dxfer_len,
289035878b55SSascha Wildner 							hpt_io_dmamap_callback, pCmd,
289135878b55SSascha Wildner 							BUS_DMA_WAITOK
289235878b55SSascha Wildner 						);
289335878b55SSascha Wildner 				KdPrint(("bus_dmamap_load return %d\n", error));
289435878b55SSascha Wildner 				if (error && error!=EINPROGRESS) {
289535878b55SSascha Wildner 					hpt_printk(("bus_dmamap_load error %d\n", error));
289635878b55SSascha Wildner 					FreeCommand(_VBUS_P pCmd);
289735878b55SSascha Wildner 					ccb->ccb_h.status = CAM_REQ_CMP_ERR;
289835878b55SSascha Wildner 					dmamap_put(pmap);
289935878b55SSascha Wildner 					pAdapter->outstandingCommands--;
290035878b55SSascha Wildner 					xpt_done(ccb);
290135878b55SSascha Wildner 				}
290235878b55SSascha Wildner 			}
290335878b55SSascha Wildner 			goto Command_Complished;
290435878b55SSascha Wildner 		}
290535878b55SSascha Wildner 
290635878b55SSascha Wildner 		default:
290735878b55SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_INVALID;
290835878b55SSascha Wildner 			break;
290935878b55SSascha Wildner 	}
291035878b55SSascha Wildner 	ccb_done(ccb);
291135878b55SSascha Wildner Command_Complished:
291235878b55SSascha Wildner 	CheckPendingCall(_VBUS_P0);
291335878b55SSascha Wildner 	return;
291435878b55SSascha Wildner }
291535878b55SSascha Wildner 
291635878b55SSascha Wildner static void HPTLIBAPI
291735878b55SSascha Wildner fOsCommandDone(_VBUS_ARG PCommand pCmd)
291835878b55SSascha Wildner {
291935878b55SSascha Wildner 	union ccb *ccb = pCmd->pOrgCommand;
292035878b55SSascha Wildner 	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
292135878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
292235878b55SSascha Wildner 
292335878b55SSascha Wildner 	KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result));
292435878b55SSascha Wildner 
292535878b55SSascha Wildner 	callout_stop(&ccb->ccb_h.timeout_ch);
292635878b55SSascha Wildner 
292735878b55SSascha Wildner 	switch(pCmd->Result) {
292835878b55SSascha Wildner 	case RETURN_SUCCESS:
292935878b55SSascha Wildner 		ccb->ccb_h.status = CAM_REQ_CMP;
293035878b55SSascha Wildner 		break;
293135878b55SSascha Wildner 	case RETURN_BAD_DEVICE:
293235878b55SSascha Wildner 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
293335878b55SSascha Wildner 		break;
293435878b55SSascha Wildner 	case RETURN_DEVICE_BUSY:
293535878b55SSascha Wildner 		ccb->ccb_h.status = CAM_BUSY;
293635878b55SSascha Wildner 		break;
293735878b55SSascha Wildner 	case RETURN_INVALID_REQUEST:
293835878b55SSascha Wildner 		ccb->ccb_h.status = CAM_REQ_INVALID;
293935878b55SSascha Wildner 		break;
294035878b55SSascha Wildner 	case RETURN_SELECTION_TIMEOUT:
294135878b55SSascha Wildner 		ccb->ccb_h.status = CAM_SEL_TIMEOUT;
294235878b55SSascha Wildner 		break;
294335878b55SSascha Wildner 	case RETURN_RETRY:
294435878b55SSascha Wildner 		ccb->ccb_h.status = CAM_BUSY;
294535878b55SSascha Wildner 		break;
294635878b55SSascha Wildner 	default:
294735878b55SSascha Wildner 		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
294835878b55SSascha Wildner 		break;
294935878b55SSascha Wildner 	}
295035878b55SSascha Wildner 
295135878b55SSascha Wildner 	if (pCmd->cf_data_in) {
295235878b55SSascha Wildner 		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD);
295335878b55SSascha Wildner 	}
295435878b55SSascha Wildner 	else if (pCmd->cf_data_in) {
295535878b55SSascha Wildner 		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE);
295635878b55SSascha Wildner 	}
295735878b55SSascha Wildner 
295835878b55SSascha Wildner 	bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map);
295935878b55SSascha Wildner 
296035878b55SSascha Wildner 	FreeCommand(_VBUS_P pCmd);
296135878b55SSascha Wildner 	ccb_done(ccb);
296235878b55SSascha Wildner }
296335878b55SSascha Wildner 
296435878b55SSascha Wildner int
296535878b55SSascha Wildner hpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags)
296635878b55SSascha Wildner {
296735878b55SSascha Wildner 	int p;
296835878b55SSascha Wildner 
296935878b55SSascha Wildner 	p = (DpcQueue_Last + 1) % MAX_DPC;
297035878b55SSascha Wildner 	if (p==DpcQueue_First) {
297135878b55SSascha Wildner 		KdPrint(("DPC Queue full!\n"));
297235878b55SSascha Wildner 		return -1;
297335878b55SSascha Wildner 	}
297435878b55SSascha Wildner 
297535878b55SSascha Wildner 	DpcQueue[DpcQueue_Last].dpc = dpc;
297635878b55SSascha Wildner 	DpcQueue[DpcQueue_Last].pAdapter = pAdapter;
297735878b55SSascha Wildner 	DpcQueue[DpcQueue_Last].arg = arg;
297835878b55SSascha Wildner 	DpcQueue[DpcQueue_Last].flags = flags;
297935878b55SSascha Wildner 	DpcQueue_Last = p;
298035878b55SSascha Wildner 
298135878b55SSascha Wildner 	return 0;
298235878b55SSascha Wildner }
298335878b55SSascha Wildner 
298435878b55SSascha Wildner #ifdef _RAID5N_
298535878b55SSascha Wildner /*
298635878b55SSascha Wildner  * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices.
298735878b55SSascha Wildner  * How about the memory for 5081 request/response array and PRD table?
298835878b55SSascha Wildner  */
298935878b55SSascha Wildner void
299035878b55SSascha Wildner *os_alloc_page(_VBUS_ARG0)
299135878b55SSascha Wildner {
299235878b55SSascha Wildner 	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
299335878b55SSascha Wildner }
299435878b55SSascha Wildner 
299535878b55SSascha Wildner void
299635878b55SSascha Wildner *os_alloc_dma_page(_VBUS_ARG0)
299735878b55SSascha Wildner {
299835878b55SSascha Wildner 	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
299935878b55SSascha Wildner }
300035878b55SSascha Wildner 
300135878b55SSascha Wildner void
300235878b55SSascha Wildner os_free_page(_VBUS_ARG void *p)
300335878b55SSascha Wildner {
300435878b55SSascha Wildner 	contigfree(p, 0x1000, M_DEVBUF);
300535878b55SSascha Wildner }
300635878b55SSascha Wildner 
300735878b55SSascha Wildner void
300835878b55SSascha Wildner os_free_dma_page(_VBUS_ARG void *p)
300935878b55SSascha Wildner {
301035878b55SSascha Wildner 	contigfree(p, 0x1000, M_DEVBUF);
301135878b55SSascha Wildner }
301235878b55SSascha Wildner 
301335878b55SSascha Wildner void
301435878b55SSascha Wildner DoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes)
301535878b55SSascha Wildner {
301635878b55SSascha Wildner 	UINT i;
301735878b55SSascha Wildner 	for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++;
301835878b55SSascha Wildner }
301935878b55SSascha Wildner 
302035878b55SSascha Wildner void
302135878b55SSascha Wildner DoXor2(ULONG *p0, ULONG *p2, UINT nBytes)
302235878b55SSascha Wildner {
302335878b55SSascha Wildner 	UINT i;
302435878b55SSascha Wildner 	for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++;
302535878b55SSascha Wildner }
302635878b55SSascha Wildner #endif
3027