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