entry.c revision 246713
1149871Sscottl/*
2149871Sscottl * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
3136849Sscottl * All rights reserved.
4136849Sscottl *
5136849Sscottl * Redistribution and use in source and binary forms, with or without
6136849Sscottl * modification, are permitted provided that the following conditions
7136849Sscottl * are met:
8136849Sscottl * 1. Redistributions of source code must retain the above copyright
9136849Sscottl *    notice, this list of conditions and the following disclaimer.
10136849Sscottl * 2. Redistributions in binary form must reproduce the above copyright
11136849Sscottl *    notice, this list of conditions and the following disclaimer in the
12136849Sscottl *    documentation and/or other materials provided with the distribution.
13136849Sscottl *
14136849Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15136849Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16136849Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17136849Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18136849Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19136849Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20136849Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21136849Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22136849Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23136849Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24136849Sscottl * SUCH DAMAGE.
25136849Sscottl */
26227912Smarius
27227912Smarius#include <sys/cdefs.h>
28227912Smarius__FBSDID("$FreeBSD: head/sys/dev/hptmv/entry.c 246713 2013-02-12 16:57:20Z kib $");
29149871Sscottl
30136849Sscottl#include <sys/param.h>
31136849Sscottl#include <sys/systm.h>
32136849Sscottl#include <sys/kernel.h>
33136849Sscottl#include <sys/bus.h>
34136849Sscottl#include <sys/malloc.h>
35136849Sscottl#include <sys/resource.h>
36136849Sscottl#include <sys/time.h>
37136849Sscottl#include <sys/callout.h>
38136849Sscottl#include <sys/signalvar.h>
39136849Sscottl#include <sys/eventhandler.h>
40136849Sscottl#include <sys/proc.h>
41136849Sscottl#include <sys/kthread.h>
42136849Sscottl
43149871Sscottl#if (__FreeBSD_version >= 500000)
44149871Sscottl#include <sys/mutex.h>
45149871Sscottl#include <sys/module.h>
46149871Sscottl#endif
47149871Sscottl
48149871Sscottl#if (__FreeBSD_version >= 500000)
49136849Sscottl#include <dev/pci/pcireg.h>
50136849Sscottl#include <dev/pci/pcivar.h>
51149871Sscottl#else
52149871Sscottl#include <pci/pcireg.h>
53149871Sscottl#include <pci/pcivar.h>
54149871Sscottl#include <sys/wait.h>
55149871Sscottl#include <sys/sysproto.h>
56149871Sscottl#endif
57136849Sscottl
58149871Sscottl#ifndef __KERNEL__
59149871Sscottl#define __KERNEL__
60149871Sscottl#endif
61149871Sscottl
62136849Sscottl#include <dev/hptmv/global.h>
63136849Sscottl#include <dev/hptmv/hptintf.h>
64136849Sscottl#include <dev/hptmv/osbsd.h>
65143039Sscottl#include <dev/hptmv/access601.h>
66136849Sscottl
67149871Sscottl
68136849Sscottl#ifdef DEBUG
69136849Sscottl#ifdef DEBUG_LEVEL
70136849Sscottlint hpt_dbg_level = DEBUG_LEVEL;
71149871Sscottl#else
72136849Sscottlint hpt_dbg_level = 0;
73136849Sscottl#endif
74136849Sscottl#endif
75136849Sscottl
76136849Sscottl#define MV_ERROR printf
77149871Sscottl
78136849Sscottl/*
79136849Sscottl * CAM SIM entry points
80136849Sscottl */
81149871Sscottlstatic int 	hpt_probe (device_t dev);
82149871Sscottlstatic void launch_worker_thread(void);
83149871Sscottlstatic int 	hpt_attach(device_t dev);
84149871Sscottlstatic int 	hpt_detach(device_t dev);
85149871Sscottlstatic int 	hpt_shutdown(device_t dev);
86149871Sscottlstatic void hpt_poll(struct cam_sim *sim);
87149871Sscottlstatic void hpt_intr(void *arg);
88149871Sscottlstatic void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
89149871Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb);
90149871Sscottl
91149871Sscottlstatic device_method_t driver_methods[] = {
92149871Sscottl	/* Device interface */
93149871Sscottl	DEVMETHOD(device_probe,		hpt_probe),
94149871Sscottl	DEVMETHOD(device_attach,	hpt_attach),
95149871Sscottl	DEVMETHOD(device_detach,	hpt_detach),
96149871Sscottl
97190863Sdelphij	DEVMETHOD(device_shutdown,	hpt_shutdown),
98227912Smarius	DEVMETHOD_END
99149871Sscottl};
100149871Sscottl
101149871Sscottlstatic driver_t hpt_pci_driver = {
102149871Sscottl	__str(PROC_DIR_NAME),
103149871Sscottl	driver_methods,
104149871Sscottl	sizeof(IAL_ADAPTER_T)
105149871Sscottl};
106149871Sscottl
107149871Sscottlstatic devclass_t	hpt_devclass;
108149871Sscottl
109149871Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6)
110149871Sscottl__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0);
111236379SeadlerMODULE_DEPEND(PROC_DIR_NAME, cam, 1, 1, 1);
112149871Sscottl
113149871Sscottl#define ccb_ccb_ptr spriv_ptr0
114149871Sscottl#define ccb_adapter ccb_h.spriv_ptr1
115149871Sscottl
116149871Sscottlstatic void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev);
117149871Sscottlstatic void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb);
118149871Sscottlstatic void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd);
119149871Sscottlstatic void ccb_done(union ccb *ccb);
120149871Sscottlstatic void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb);
121149871Sscottlstatic void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb);
122136849Sscottlstatic void	hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter);
123136849Sscottlstatic void	hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
124136849Sscottlstatic void	handleEdmaError(_VBUS_ARG PCommand pCmd);
125136849Sscottlstatic int	hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
126136849Sscottlstatic int	fResetActiveCommands(PVBus _vbus_p);
127136849Sscottlstatic void	fRegisterVdevice(IAL_ADAPTER_T *pAdapter);
128136849Sscottlstatic int	hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter);
129136849Sscottlstatic void	hptmv_handle_event_disconnect(void *data);
130136849Sscottlstatic void	hptmv_handle_event_connect(void *data);
131136849Sscottlstatic int	start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
132136849Sscottlstatic void	init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel);
133136849Sscottlstatic int	hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel);
134136849Sscottlstatic int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg,
135136849Sscottl    int logical);
136136849Sscottlstatic MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
137136849Sscottl    MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId,
138136849Sscottl    MV_U16 responseFlags, MV_U32 timeStamp,
139136849Sscottl    MV_STORAGE_DEVICE_REGISTERS *registerStruct);
140136849Sscottlstatic MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter,
141136849Sscottl    MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2);
142136849Sscottl
143136849Sscottl#define ccb_ccb_ptr spriv_ptr0
144136849Sscottl#define ccb_adapter ccb_h.spriv_ptr1
145136849Sscottl
146136849SscottlIAL_ADAPTER_T *gIal_Adapter = 0;
147136849SscottlIAL_ADAPTER_T *pCurAdapter = 0;
148149871Sscottlstatic MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM];
149136849Sscottl
150136849Sscottltypedef struct st_HPT_DPC {
151136849Sscottl	IAL_ADAPTER_T *pAdapter;
152136849Sscottl	void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR);
153136849Sscottl	void *arg;
154136849Sscottl	UCHAR flags;
155136849Sscottl} ST_HPT_DPC;
156136849Sscottl
157136849Sscottl#define MAX_DPC 16
158136849SscottlUCHAR DPC_Request_Nums = 0;
159136849Sscottlstatic ST_HPT_DPC DpcQueue[MAX_DPC];
160136849Sscottlstatic int DpcQueue_First=0;
161136849Sscottlstatic int DpcQueue_Last = 0;
162136849Sscottl
163190809Sdelphijchar DRIVER_VERSION[] = "v1.16";
164136849Sscottl
165149871Sscottl#if (__FreeBSD_version >= 500000)
166149871Sscottlstatic struct mtx driver_lock;
167149871Sscottlintrmask_t lock_driver()
168149871Sscottl{
169136849Sscottl
170149871Sscottl	intrmask_t spl = 0;
171165774Sjhb	mtx_lock(&driver_lock);
172149871Sscottl	return spl;
173149871Sscottl}
174149871Sscottlvoid unlock_driver(intrmask_t spl)
175136849Sscottl{
176165774Sjhb	mtx_unlock(&driver_lock);
177149871Sscottl}
178149871Sscottl#else
179149871Sscottlstatic int driver_locked = 0;
180149871Sscottlintrmask_t lock_driver()
181149871Sscottl{
182136849Sscottl	intrmask_t spl = splcam();
183149871Sscottlloop:
184149871Sscottl	while (driver_locked)
185149871Sscottl		tsleep(&driver_locked, PRIBIO, "hptlck", hz);
186149871Sscottl	atomic_add_int(&driver_locked, 1);
187149871Sscottl	if (driver_locked>1) {
188149871Sscottl		atomic_subtract_int(&driver_locked, 1);
189149871Sscottl		goto loop;
190149871Sscottl	}
191136849Sscottl	return spl;
192136849Sscottl}
193136849Sscottl
194149871Sscottlvoid unlock_driver(intrmask_t spl)
195136849Sscottl{
196149871Sscottl	atomic_subtract_int(&driver_locked, 1);
197149871Sscottl	if (driver_locked==0) {
198149871Sscottl		wakeup(&driver_locked);
199149871Sscottl	}
200136849Sscottl	splx(spl);
201136849Sscottl}
202149871Sscottl#endif
203136849Sscottl
204136849Sscottl/*******************************************************************************
205136849Sscottl *	Name:	hptmv_free_channel
206136849Sscottl *
207136849Sscottl *	Description:	free allocated queues for the given channel
208136849Sscottl *
209190809Sdelphij *	Parameters:    	pMvSataAdapter - pointer to the RR18xx controler this
210136849Sscottl * 					channel connected to.
211136849Sscottl *			channelNum - channel number.
212136849Sscottl *
213136849Sscottl ******************************************************************************/
214136849Sscottlstatic void
215136849Sscottlhptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
216136849Sscottl{
217136849Sscottl	HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM);
218136849Sscottl	pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL;
219149871Sscottl}
220136849Sscottl
221149871Sscottlstatic void failDevice(PVDevice pVDev)
222149871Sscottl{
223149871Sscottl	PVBus _vbus_p = pVDev->pVBus;
224149871Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
225149871Sscottl
226149871Sscottl	pVDev->u.disk.df_on_line = 0;
227149871Sscottl	pVDev->vf_online = 0;
228149871Sscottl	if (pVDev->pfnDeviceFailed)
229149871Sscottl		CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev);
230149871Sscottl
231149871Sscottl	fNotifyGUI(ET_DEVICE_REMOVED, pVDev);
232149871Sscottl
233149871Sscottl#ifndef FOR_DEMO
234149871Sscottl	if (pAdapter->ver_601==2 && !pAdapter->beeping) {
235149871Sscottl		pAdapter->beeping = 1;
236149871Sscottl		BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress);
237149871Sscottl		set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1);
238136849Sscottl	}
239149871Sscottl#endif
240136849Sscottl}
241136849Sscottl
242136849Sscottlint MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel);
243136849Sscottl
244136849Sscottlstatic void
245136849SscottlhandleEdmaError(_VBUS_ARG PCommand pCmd)
246136849Sscottl{
247136849Sscottl	PDevice pDevice = &pCmd->pVDevice->u.disk;
248136849Sscottl	MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter;
249136849Sscottl
250136849Sscottl	if (!pDevice->df_on_line) {
251136849Sscottl		KdPrint(("Device is offline"));
252136849Sscottl		pCmd->Result = RETURN_BAD_DEVICE;
253136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
254136849Sscottl		return;
255136849Sscottl	}
256136849Sscottl
257136849Sscottl	if (pCmd->RetryCount++>5) {
258149871Sscottl		hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber));
259149871Sscottlfailed:
260149871Sscottl		failDevice(pCmd->pVDevice);
261136849Sscottl		pCmd->Result = RETURN_IDE_ERROR;
262136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
263136849Sscottl		return;
264136849Sscottl	}
265149871Sscottl
266149871Sscottl	/* reset the channel and retry the command */
267149871Sscottl	if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber))
268149871Sscottl		goto failed;
269149871Sscottl
270149871Sscottl	fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice));
271149871Sscottl
272149871Sscottl	hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber));
273136849Sscottl	fDeviceSendCommand(_VBUS_P pCmd);
274136849Sscottl}
275136849Sscottl
276136849Sscottl/****************************************************************
277136849Sscottl *	Name:	hptmv_init_channel
278136849Sscottl *
279149871Sscottl *	Description:	allocate request and response queues for the EDMA of the
280149871Sscottl *					given channel and sets other fields.
281149871Sscottl *
282136849Sscottl *	Parameters:
283136849Sscottl *		pAdapter - pointer to the emulated adapter data structure
284136849Sscottl *		channelNum - channel number.
285136849Sscottl *	Return:	0 on success, otherwise on failure
286136849Sscottl ****************************************************************/
287136849Sscottlstatic int
288136849Sscottlhptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
289136849Sscottl{
290136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
291136849Sscottl	dma_addr_t    req_dma_addr;
292136849Sscottl	dma_addr_t    rsp_dma_addr;
293136849Sscottl
294136849Sscottl	if (channelNum >= MV_SATA_CHANNELS_NUM)
295136849Sscottl	{
296190809Sdelphij		MV_ERROR("RR18xx[%d]: Bad channelNum=%d",
297136849Sscottl				 pAdapter->mvSataAdapter.adapterId, channelNum);
298136849Sscottl		return -1;
299136849Sscottl	}
300136849Sscottl
301149871Sscottl	pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum];
302136849Sscottl	pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel;
303136849Sscottl	pMvSataChannel->channelNumber = channelNum;
304136849Sscottl	pMvSataChannel->lba48Address = MV_FALSE;
305136849Sscottl	pMvSataChannel->maxReadTransfer = MV_FALSE;
306136849Sscottl
307149871Sscottl	pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *)
308149871Sscottl								   (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE));
309149871Sscottl	req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE);
310136849Sscottl
311136849Sscottl
312149871Sscottl	KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr));
313136849Sscottl
314136849Sscottl	/* check the 1K alignment of the request queue*/
315136849Sscottl	if (req_dma_addr & 0x3ff)
316136849Sscottl	{
317190809Sdelphij		MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned,"
318149871Sscottl				 " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId,
319149871Sscottl				 (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum);
320136849Sscottl		return -1;
321136849Sscottl	}
322136849Sscottl	pMvSataChannel->requestQueuePciLowAddress = req_dma_addr;
323136849Sscottl	pMvSataChannel->requestQueuePciHiAddress = 0;
324190809Sdelphij	KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p",
325149871Sscottl			  pAdapter->mvSataAdapter.adapterId, channelNum,
326149871Sscottl			  pMvSataChannel->requestQueue));
327149871Sscottl	pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *)
328149871Sscottl									(pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE));
329149871Sscottl	rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE);
330136849Sscottl
331136849Sscottl	/* check the 256 alignment of the response queue*/
332136849Sscottl	if (rsp_dma_addr & 0xff)
333136849Sscottl	{
334190809Sdelphij		MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte "
335149871Sscottl				 "aligned, dma_addr=%llx\n",
336149871Sscottl				 pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr);
337136849Sscottl		return -1;
338136849Sscottl	}
339136849Sscottl	pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr;
340136849Sscottl	pMvSataChannel->responseQueuePciHiAddress = 0;
341190809Sdelphij	KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p",
342149871Sscottl			  pAdapter->mvSataAdapter.adapterId, channelNum,
343149871Sscottl			  pMvSataChannel->responseQueue));
344136849Sscottl
345136849Sscottl	pAdapter->mvChannel[channelNum].online = MV_TRUE;
346136849Sscottl	return 0;
347136849Sscottl}
348136849Sscottl
349136849Sscottl/******************************************************************************
350136849Sscottl *	Name: hptmv_parse_identify_results
351136849Sscottl *
352149871Sscottl *	Description:	this functions parses the identify command results, checks
353190809Sdelphij *					that the connected deives can be accesed by RR18xx EDMA,
354149871Sscottl *					and updates the channel stucture accordingly.
355149871Sscottl *
356136849Sscottl *	Parameters:     pMvSataChannel, pointer to the channel data structure.
357136849Sscottl *
358136849Sscottl *	Returns:       	=0 ->success, < 0 ->failure.
359136849Sscottl *
360136849Sscottl ******************************************************************************/
361136849Sscottlstatic int
362136849Sscottlhptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel)
363136849Sscottl{
364136849Sscottl	MV_U16  *iden = pMvSataChannel->identifyDevice;
365136849Sscottl
366136849Sscottl	/*LBA addressing*/
367149871Sscottl	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200))
368149871Sscottl	{
369136849Sscottl		KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n"));
370136849Sscottl		return -1;
371149871Sscottl	}
372149871Sscottl	else
373149871Sscottl	{
374136849Sscottl		KdPrint(("%25s - %s\n", "Capabilities", "LBA supported"));
375136849Sscottl	}
376136849Sscottl	/*DMA support*/
377149871Sscottl	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100))
378149871Sscottl	{
379136849Sscottl		KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n"));
380136849Sscottl		return -1;
381149871Sscottl	}
382149871Sscottl	else
383149871Sscottl	{
384136849Sscottl		KdPrint(("%25s - %s\n", "Capabilities", "DMA supported"));
385136849Sscottl	}
386136849Sscottl	/* PIO */
387149871Sscottl	if ((iden[IDEN_VALID] & 2) == 0)
388149871Sscottl	{
389149871Sscottl		KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n"));
390136849Sscottl		return -1;
391136849Sscottl	}
392136849Sscottl	KdPrint(("%25s - 0x%02x\n", "PIO modes supported",
393136849Sscottl			  iden[IDEN_PIO_MODE_SPPORTED] & 0xff));
394136849Sscottl
395136849Sscottl	/*UDMA*/
396149871Sscottl	if ((iden[IDEN_VALID] & 4) == 0)
397149871Sscottl	{
398149871Sscottl		KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n"));
399136849Sscottl		return -1;
400136849Sscottl	}
401136849Sscottl
402136849Sscottl	/* 48 bit address */
403149871Sscottl	if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400))
404149871Sscottl	{
405136849Sscottl		KdPrint(("%25s - %s\n", "LBA48 addressing", "supported"));
406136849Sscottl		pMvSataChannel->lba48Address = MV_TRUE;
407149871Sscottl	}
408149871Sscottl	else
409149871Sscottl	{
410136849Sscottl		KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported"));
411136849Sscottl		pMvSataChannel->lba48Address = MV_FALSE;
412136849Sscottl	}
413136849Sscottl	return 0;
414136849Sscottl}
415136849Sscottl
416136849Sscottlstatic void
417136849Sscottlinit_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel)
418136849Sscottl{
419149871Sscottl	PVDevice pVDev = &pAdapter->VDevices[channel];
420149871Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel];
421149871Sscottl	MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice;
422136849Sscottl
423136849Sscottl	pMvSataChannel->outstandingCommands = 0;
424136849Sscottl
425136849Sscottl	pVDev->u.disk.mv         = pMvSataChannel;
426136849Sscottl	pVDev->u.disk.df_on_line = 1;
427136849Sscottl	pVDev->u.disk.pVBus      = &pAdapter->VBus;
428136849Sscottl	pVDev->pVBus             = &pAdapter->VBus;
429136849Sscottl
430136849Sscottl#ifdef SUPPORT_48BIT_LBA
431136849Sscottl	if (pMvSataChannel->lba48Address == MV_TRUE)
432149871Sscottl		pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1;
433136849Sscottl	else
434136849Sscottl#endif
435136849Sscottl	if(IdentifyData[53] & 1) {
436149871Sscottl	pVDev->u.disk.dDeRealCapacity =
437149871Sscottl	  (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ?
438149871Sscottl		  (IdentifyData[61]<<16 | IdentifyData[60]) :
439149871Sscottl				(IdentifyData[58]<<16 | IdentifyData[57])) - 1;
440136849Sscottl	} else
441136849Sscottl		pVDev->u.disk.dDeRealCapacity =
442149871Sscottl				 (IdentifyData[61]<<16 | IdentifyData[60]) - 1;
443136849Sscottl
444136849Sscottl	pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
445149871Sscottl		pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0;
446136849Sscottl
447136849Sscottl	if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) {
448136849Sscottl		pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
449149871Sscottl			pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8;
450136849Sscottl	}
451136849Sscottl}
452136849Sscottl
453149871Sscottlstatic void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged)
454136849Sscottl{
455136849Sscottl	PVDevice pVDev;
456149871Sscottl	MV_SATA_ADAPTER  *pMvSataAdapter = &pAdapter->mvSataAdapter;
457149871Sscottl	MV_SATA_CHANNEL  *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex];
458149871Sscottl
459149871Sscottl	if (!pMvSataChannel) return;
460136849Sscottl
461149871Sscottl	if (plugged)
462149871Sscottl	{
463136849Sscottl		pVDev = &(pAdapter->VDevices[channelIndex]);
464136849Sscottl		init_vdev_params(pAdapter, channelIndex);
465136849Sscottl
466149871Sscottl		pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI :
467149871Sscottl			pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
468136849Sscottl
469149871Sscottl		pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO;
470136849Sscottl		pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
471136849Sscottl		pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
472136849Sscottl		pVDev->vf_online = 1;
473136849Sscottl
474136849Sscottl#ifdef SUPPORT_ARRAY
475149871Sscottl		if(pVDev->pParent)
476149871Sscottl		{
477136849Sscottl			int iMember;
478149871Sscottl			for(iMember = 0; iMember < 	pVDev->pParent->u.array.bArnMember; iMember++)
479149871Sscottl				if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev)
480136849Sscottl					pVDev->pParent->u.array.pMember[iMember] = NULL;
481136849Sscottl			pVDev->pParent = NULL;
482136849Sscottl		}
483136849Sscottl#endif
484136849Sscottl		fNotifyGUI(ET_DEVICE_PLUGGED,pVDev);
485136849Sscottl		fCheckBootable(pVDev);
486136849Sscottl		RegisterVDevice(pVDev);
487136849Sscottl
488136849Sscottl#ifndef FOR_DEMO
489136849Sscottl		if (pAdapter->beeping) {
490136849Sscottl			pAdapter->beeping = 0;
491136849Sscottl			BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
492136849Sscottl		}
493136849Sscottl#endif
494136849Sscottl
495149871Sscottl	}
496149871Sscottl	else
497149871Sscottl	{
498136849Sscottl		pVDev  = &(pAdapter->VDevices[channelIndex]);
499149871Sscottl		failDevice(pVDev);
500136849Sscottl	}
501136849Sscottl}
502136849Sscottl
503136849Sscottlstatic int
504136849Sscottlstart_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
505136849Sscottl{
506149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
507149871Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum];
508149871Sscottl	MV_CHANNEL		*pChannelInfo = &(pAdapter->mvChannel[channelNum]);
509149871Sscottl	MV_U32          udmaMode,pioMode;
510136849Sscottl
511190809Sdelphij	KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId,
512149871Sscottl			 channelNum));
513136849Sscottl
514136849Sscottl
515136849Sscottl	/* Software reset channel */
516149871Sscottl	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
517149871Sscottl	{
518190809Sdelphij		MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n",
519149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
520136849Sscottl		return -1;
521136849Sscottl	}
522136849Sscottl
523136849Sscottl	/* Hardware reset channel */
524149871Sscottl	if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
525149871Sscottl	{
526149871Sscottl		/* If failed, try again - this is when trying to hardreset a channel */
527149871Sscottl		/* when drive is just spinning up */
528136849Sscottl		StallExec(5000000); /* wait 5 sec before trying again */
529149871Sscottl		if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
530149871Sscottl		{
531190809Sdelphij			MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n",
532149871Sscottl					 pMvSataAdapter->adapterId, channelNum);
533136849Sscottl			return -1;
534136849Sscottl		}
535136849Sscottl	}
536136849Sscottl
537136849Sscottl	/* identify device*/
538149871Sscottl	if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE)
539149871Sscottl	{
540190809Sdelphij		MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n"
541149871Sscottl				 , pMvSataAdapter->adapterId, channelNum);
542136849Sscottl		return -1;
543136849Sscottl	}
544149871Sscottl	if (hptmv_parse_identify_results(pMvSataChannel))
545149871Sscottl	{
546190809Sdelphij		MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n"
547149871Sscottl				 , pMvSataAdapter->adapterId, channelNum);
548136849Sscottl		return -1;
549136849Sscottl	}
550136849Sscottl
551136849Sscottl	/* mvStorageDevATASetFeatures */
552136849Sscottl	/* Disable 8 bit PIO in case CFA enabled */
553149871Sscottl	if (pMvSataChannel->identifyDevice[86] & 4)
554149871Sscottl	{
555190809Sdelphij		KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n",
556149871Sscottl				  pMvSataAdapter->adapterId));
557136849Sscottl		if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
558149871Sscottl									   MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0,
559149871Sscottl									   0, 0, 0) == MV_FALSE)
560149871Sscottl		{
561190809Sdelphij			MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures"
562149871Sscottl					 " failed\n", pMvSataAdapter->adapterId, channelNum);
563136849Sscottl			return -1;
564136849Sscottl		}
565136849Sscottl	}
566149871Sscottl	/* Write cache */
567136849Sscottl#ifdef ENABLE_WRITE_CACHE
568149871Sscottl	if (pMvSataChannel->identifyDevice[82] & 0x20)
569149871Sscottl	{
570149871Sscottl		if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */
571149871Sscottl		{
572149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
573149871Sscottl										   MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0,
574149871Sscottl										   0, 0, 0) == MV_FALSE)
575149871Sscottl			{
576190809Sdelphij				MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
577149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
578136849Sscottl				return -1;
579136849Sscottl			}
580136849Sscottl		}
581190809Sdelphij		KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n",
582149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
583149871Sscottl	}
584149871Sscottl	else
585149871Sscottl	{
586190809Sdelphij		KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n",
587149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
588136849Sscottl	}
589149871Sscottl#else /* disable write cache */
590149871Sscottl	{
591149871Sscottl		if (pMvSataChannel->identifyDevice[85] & 0x20)
592149871Sscottl		{
593190809Sdelphij			KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n",
594149871Sscottl					  pMvSataAdapter->adapterId, channelNum));
595149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
596149871Sscottl										   MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0,
597149871Sscottl										   0, 0, 0) == MV_FALSE)
598149871Sscottl			{
599190809Sdelphij				MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
600149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
601149871Sscottl				return -1;
602149871Sscottl			}
603136849Sscottl		}
604190809Sdelphij		KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n",
605149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
606136849Sscottl	}
607136849Sscottl#endif
608136849Sscottl
609136849Sscottl	/* Set transfer mode */
610190809Sdelphij	KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n",
611149871Sscottl			  pMvSataAdapter->adapterId));
612136849Sscottl	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
613149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
614149871Sscottl								   MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) ==
615149871Sscottl		MV_FALSE)
616149871Sscottl	{
617190809Sdelphij		MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
618149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
619136849Sscottl		return -1;
620136849Sscottl	}
621136849Sscottl
622149871Sscottl	if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1)
623149871Sscottl	{
624136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_4;
625149871Sscottl	}
626149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2)
627149871Sscottl	{
628136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_3;
629149871Sscottl	}
630149871Sscottl	else
631149871Sscottl	{
632149871Sscottl		MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n");
633136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_SLOW;
634136849Sscottl	}
635136849Sscottl
636190809Sdelphij	KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n",
637149871Sscottl			  pMvSataAdapter->adapterId));
638136849Sscottl	pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode;
639136849Sscottl	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
640149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
641149871Sscottl								   pioMode, 0, 0, 0) == MV_FALSE)
642149871Sscottl	{
643190809Sdelphij		MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
644149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
645136849Sscottl		return -1;
646136849Sscottl	}
647136849Sscottl
648136849Sscottl	udmaMode = MV_ATA_TRANSFER_UDMA_0;
649149871Sscottl	if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40)
650149871Sscottl	{
651136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_6;
652149871Sscottl	}
653149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20)
654149871Sscottl	{
655136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_5;
656149871Sscottl	}
657149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10)
658149871Sscottl	{
659136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_4;
660149871Sscottl	}
661149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8)
662149871Sscottl	{
663136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_3;
664149871Sscottl	}
665149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4)
666149871Sscottl	{
667136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_2;
668136849Sscottl	}
669136849Sscottl
670190809Sdelphij	KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n",
671149871Sscottl			  pMvSataAdapter->adapterId, udmaMode & 0xf));
672136849Sscottl	pChannelInfo->maxUltraDmaModeSupported = udmaMode;
673136849Sscottl
674149871Sscottl	/*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
675149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER, udmaMode,
676149871Sscottl								   0, 0, 0) == MV_FALSE)
677149871Sscottl	{
678190809Sdelphij		MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
679149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
680136849Sscottl		return -1;
681149871Sscottl	}*/
682136849Sscottl	if (pChannelInfo->maxUltraDmaModeSupported == 0xFF)
683136849Sscottl		return TRUE;
684149871Sscottl	else
685149871Sscottl		do
686149871Sscottl		{
687149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
688149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
689149871Sscottl								   pChannelInfo->maxUltraDmaModeSupported,
690149871Sscottl								   0, 0, 0) == MV_FALSE)
691149871Sscottl			{
692149871Sscottl				if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0)
693149871Sscottl				{
694149871Sscottl					if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
695149871Sscottl					{
696149871Sscottl						MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress,
697149871Sscottl										  pMvSataChannel->eDmaRegsOffset +
698149871Sscottl										  0x11c, /* command reg */
699149871Sscottl										  MV_ATA_COMMAND_IDLE_IMMEDIATE);
700149871Sscottl						mvMicroSecondsDelay(10000);
701149871Sscottl						mvSataChannelHardReset(pMvSataAdapter, channelNum);
702149871Sscottl						if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
703149871Sscottl							return FALSE;
704149871Sscottl					}
705149871Sscottl					if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
706149871Sscottl						return FALSE;
707149871Sscottl					pChannelInfo->maxUltraDmaModeSupported--;
708149871Sscottl					continue;
709149871Sscottl				}
710149871Sscottl				else   return FALSE;
711149871Sscottl			}
712136849Sscottl			break;
713149871Sscottl		}while (1);
714136849Sscottl
715149871Sscottl	/* Read look ahead */
716136849Sscottl#ifdef ENABLE_READ_AHEAD
717149871Sscottl	if (pMvSataChannel->identifyDevice[82] & 0x40)
718149871Sscottl	{
719149871Sscottl		if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */
720149871Sscottl		{
721149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
722149871Sscottl										   MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0,
723149871Sscottl										   0, 0) == MV_FALSE)
724149871Sscottl			{
725190809Sdelphij				MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
726149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
727136849Sscottl				return -1;
728136849Sscottl			}
729136849Sscottl		}
730190809Sdelphij		KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n",
731149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
732136849Sscottl	}
733149871Sscottl	else
734149871Sscottl	{
735190809Sdelphij		KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n",
736149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
737149871Sscottl	}
738149871Sscottl#else
739149871Sscottl	{
740149871Sscottl		if (pMvSataChannel->identifyDevice[86] & 0x20)
741149871Sscottl		{
742190809Sdelphij			KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n",
743149871Sscottl					  pMvSataAdapter->adapterId, channelNum));
744149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
745149871Sscottl										   MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0,
746149871Sscottl										   0, 0) == MV_FALSE)
747149871Sscottl			{
748190809Sdelphij				MV_ERROR("RR18xx [%d]:channel %d:  ATA Set Features failed\n",
749149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
750149871Sscottl				return -1;
751149871Sscottl			}
752136849Sscottl		}
753190809Sdelphij		KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n",
754149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
755149871Sscottl	}
756136849Sscottl#endif
757136849Sscottl
758136849Sscottl
759149871Sscottl	{
760190809Sdelphij		KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n",
761149871Sscottl				  pMvSataAdapter->adapterId,
762149871Sscottl				  channelNum));
763149871Sscottl		if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum,
764149871Sscottl								 MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE)
765149871Sscottl		{
766190809Sdelphij			MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n",
767149871Sscottl					 pMvSataAdapter->adapterId, channelNum);
768136849Sscottl			return -1;
769136849Sscottl		}
770136849Sscottl	}
771136849Sscottl	/* Enable EDMA */
772149871Sscottl	if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE)
773149871Sscottl	{
774190809Sdelphij		MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n",
775149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
776136849Sscottl		return -1;
777136849Sscottl	}
778190809Sdelphij	MV_ERROR("RR18xx [%d,%d]: channel started successfully\n",
779149871Sscottl			 pMvSataAdapter->adapterId, channelNum);
780136849Sscottl
781136849Sscottl#ifndef FOR_DEMO
782136849Sscottl	set_fail_led(pMvSataAdapter, channelNum, 0);
783136849Sscottl#endif
784136849Sscottl	return 0;
785136849Sscottl}
786136849Sscottl
787136849Sscottlstatic void
788136849Sscottlhptmv_handle_event(void * data, int flag)
789136849Sscottl{
790149871Sscottl	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)data;
791149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
792149871Sscottl	MV_U8           channelIndex;
793149871Sscottl
794149871Sscottl/*	mvOsSemTake(&pMvSataAdapter->semaphore); */
795149871Sscottl	for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
796149871Sscottl	{
797149871Sscottl		switch(pAdapter->sataEvents[channelIndex])
798149871Sscottl		{
799149871Sscottl			case SATA_EVENT_CHANNEL_CONNECTED:
800149871Sscottl				/* Handle only connects */
801149871Sscottl				if (flag == 1)
802149871Sscottl					break;
803190809Sdelphij				KdPrint(("RR18xx [%d,%d]: new device connected\n",
804149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
805149871Sscottl				hptmv_init_channel(pAdapter, channelIndex);
806149871Sscottl				if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE)
807149871Sscottl				{
808190809Sdelphij					MV_ERROR("RR18xx [%d,%d] Failed to configure\n",
809149871Sscottl							 pMvSataAdapter->adapterId, channelIndex);
810149871Sscottl					hptmv_free_channel(pAdapter, channelIndex);
811149871Sscottl				}
812149871Sscottl				else
813149871Sscottl				{
814149871Sscottl					/*mvSataChannelHardReset(pMvSataAdapter, channel);*/
815149871Sscottl					if (start_channel( pAdapter, channelIndex))
816149871Sscottl					{
817190809Sdelphij						MV_ERROR("RR18xx [%d,%d]Failed to start channel\n",
818149871Sscottl								 pMvSataAdapter->adapterId, channelIndex);
819149871Sscottl						hptmv_free_channel(pAdapter, channelIndex);
820149871Sscottl					}
821149871Sscottl					else
822149871Sscottl					{
823149871Sscottl						device_change(pAdapter, channelIndex, TRUE);
824149871Sscottl					}
825149871Sscottl				}
826149871Sscottl				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
827149871Sscottl			   break;
828136849Sscottl
829149871Sscottl			case SATA_EVENT_CHANNEL_DISCONNECTED:
830149871Sscottl				/* Handle only disconnects */
831149871Sscottl				if (flag == 0)
832149871Sscottl					break;
833190809Sdelphij				KdPrint(("RR18xx [%d,%d]: device disconnected\n",
834149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
835149871Sscottl					/* Flush pending commands */
836149871Sscottl				if(pMvSataAdapter->sataChannel[channelIndex])
837149871Sscottl				{
838149871Sscottl					_VBUS_INST(&pAdapter->VBus)
839149871Sscottl					mvSataFlushDmaQueue (pMvSataAdapter, channelIndex,
840149871Sscottl										 MV_FLUSH_TYPE_CALLBACK);
841149871Sscottl					CheckPendingCall(_VBUS_P0);
842149871Sscottl					mvSataRemoveChannel(pMvSataAdapter,channelIndex);
843149871Sscottl					hptmv_free_channel(pAdapter, channelIndex);
844149871Sscottl					pMvSataAdapter->sataChannel[channelIndex] = NULL;
845190809Sdelphij					KdPrint(("RR18xx [%d,%d]: channel removed\n",
846149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
847149871Sscottl					if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
848149871Sscottl						Check_Idle_Call(pAdapter);
849136849Sscottl				}
850149871Sscottl				else
851149871Sscottl				{
852190809Sdelphij					KdPrint(("RR18xx [%d,%d]: channel already removed!!\n",
853149871Sscottl							 pMvSataAdapter->adapterId, channelIndex));
854149871Sscottl				}
855149871Sscottl				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
856136849Sscottl				break;
857136849Sscottl
858149871Sscottl			case SATA_EVENT_NO_CHANGE:
859149871Sscottl				break;
860136849Sscottl
861149871Sscottl			default:
862149871Sscottl				break;
863136849Sscottl		}
864136849Sscottl	}
865149871Sscottl/*	mvOsSemRelease(&pMvSataAdapter->semaphore); */
866136849Sscottl}
867136849Sscottl
868136849Sscottl#define EVENT_CONNECT					1
869136849Sscottl#define EVENT_DISCONNECT				0
870136849Sscottl
871136849Sscottlstatic void
872136849Sscottlhptmv_handle_event_connect(void *data)
873136849Sscottl{
874149871Sscottl  hptmv_handle_event (data, 0);
875136849Sscottl}
876136849Sscottl
877136849Sscottlstatic void
878136849Sscottlhptmv_handle_event_disconnect(void *data)
879136849Sscottl{
880149871Sscottl  hptmv_handle_event (data, 1);
881136849Sscottl}
882136849Sscottl
883136849Sscottlstatic MV_BOOLEAN
884136849Sscottlhptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
885149871Sscottl								   MV_U32 param1, MV_U32 param2)
886136849Sscottl{
887149871Sscottl	IAL_ADAPTER_T   *pAdapter = pMvSataAdapter->IALData;
888136849Sscottl
889149871Sscottl	switch (eventType)
890136849Sscottl	{
891149871Sscottl		case MV_EVENT_TYPE_SATA_CABLE:
892149871Sscottl			{
893149871Sscottl				MV_U8   channel = param2;
894136849Sscottl
895149871Sscottl				if (param1 == EVENT_CONNECT)
896149871Sscottl				{
897149871Sscottl					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED;
898190809Sdelphij					KdPrint(("RR18xx [%d,%d]: device connected event received\n",
899149871Sscottl							 pMvSataAdapter->adapterId, channel));
900149871Sscottl					/* Delete previous timers (if multiple drives connected in the same time */
901149871Sscottl					pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz);
902149871Sscottl				}
903149871Sscottl				else if (param1 == EVENT_DISCONNECT)
904149871Sscottl				{
905149871Sscottl					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED;
906190809Sdelphij					KdPrint(("RR18xx [%d,%d]: device disconnected event received \n",
907149871Sscottl							 pMvSataAdapter->adapterId, channel));
908149871Sscottl					device_change(pAdapter, channel, FALSE);
909149871Sscottl					/* Delete previous timers (if multiple drives disconnected in the same time */
910149871Sscottl					/*pAdapter->event_timer_disconnect = timeout(hptmv_handle_event_disconnect, pAdapter, 10*hz); */
911149871Sscottl					/*It is not necessary to wait, handle it directly*/
912149871Sscottl					hptmv_handle_event_disconnect(pAdapter);
913149871Sscottl				}
914149871Sscottl				else
915149871Sscottl				{
916136849Sscottl
917190809Sdelphij					MV_ERROR("RR18xx: illigal value for param1(%d) at "
918149871Sscottl							 "connect/disconect event, host=%d\n", param1,
919149871Sscottl							 pMvSataAdapter->adapterId );
920149871Sscottl
921149871Sscottl				}
922149871Sscottl			}
923149871Sscottl			break;
924149871Sscottl		case MV_EVENT_TYPE_ADAPTER_ERROR:
925190809Sdelphij			KdPrint(("RR18xx: DEVICE error event received, pci cause "
926149871Sscottl					  "reg=%x,  don't how to handle this\n", param1));
927149871Sscottl			return MV_TRUE;
928149871Sscottl		default:
929190809Sdelphij			MV_ERROR("RR18xx[%d]: unknown event type (%d)\n",
930149871Sscottl					 pMvSataAdapter->adapterId, eventType);
931149871Sscottl			return MV_FALSE;
932136849Sscottl	}
933136849Sscottl	return MV_TRUE;
934136849Sscottl}
935136849Sscottl
936149871Sscottlstatic int
937136849Sscottlhptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
938136849Sscottl{
939149871Sscottl	pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE,
940149871Sscottl			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
941149871Sscottl	if (pAdapter->requestsArrayBaseAddr == NULL)
942149871Sscottl	{
943190809Sdelphij		MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request"
944149871Sscottl				 " queues\n", pAdapter->mvSataAdapter.adapterId);
945136849Sscottl		return -1;
946136849Sscottl	}
947149871Sscottl	pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr);
948149871Sscottl	pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr;
949136849Sscottl	pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
950149871Sscottl	pAdapter->requestsArrayBaseAlignedAddr  = (MV_U8 *)
951149871Sscottl		(((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1));
952149871Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr;
953136849Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
954149871Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1);
955136849Sscottl
956149871Sscottl	if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) !=
957149871Sscottl		(pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr))
958149871Sscottl	{
959190809Sdelphij		MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n",
960149871Sscottl				 pAdapter->mvSataAdapter.adapterId);
961149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
962136849Sscottl		return -1;
963136849Sscottl	}
964136849Sscottl	/* response queues */
965149871Sscottl	pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE,
966149871Sscottl			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
967149871Sscottl	if (pAdapter->responsesArrayBaseAddr == NULL)
968149871Sscottl	{
969190809Sdelphij		MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response"
970149871Sscottl				 " queues\n", pAdapter->mvSataAdapter.adapterId);
971149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
972136849Sscottl		return -1;
973136849Sscottl	}
974149871Sscottl	pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr);
975149871Sscottl	pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr;
976136849Sscottl	pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
977149871Sscottl	pAdapter->responsesArrayBaseAlignedAddr  = (MV_U8 *)
978149871Sscottl		(((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1));
979149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr;
980149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
981149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1);
982136849Sscottl
983149871Sscottl	if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) !=
984149871Sscottl		(pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr))
985149871Sscottl	{
986190809Sdelphij		MV_ERROR("RR18xx[%d]: Error in Response Quueues Alignment\n",
987149871Sscottl				 pAdapter->mvSataAdapter.adapterId);
988149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
989149871Sscottl		contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
990136849Sscottl		return -1;
991136849Sscottl	}
992136849Sscottl	return 0;
993136849Sscottl}
994136849Sscottl
995136849Sscottlstatic void
996136849Sscottlhptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter)
997136849Sscottl{
998149871Sscottl	contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
999149871Sscottl	contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
1000136849Sscottl}
1001136849Sscottl
1002136849Sscottlstatic PVOID
1003136849SscottlAllocatePRDTable(IAL_ADAPTER_T *pAdapter)
1004136849Sscottl{
1005136849Sscottl	PVOID ret;
1006136849Sscottl	if (pAdapter->pFreePRDLink) {
1007149871Sscottl		KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink));
1008136849Sscottl		ret = pAdapter->pFreePRDLink;
1009136849Sscottl		pAdapter->pFreePRDLink = *(void**)ret;
1010136849Sscottl		return ret;
1011136849Sscottl	}
1012136849Sscottl	return NULL;
1013136849Sscottl}
1014136849Sscottl
1015136849Sscottlstatic void
1016136849SscottlFreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable)
1017136849Sscottl{
1018136849Sscottl	*(void**)PRDTable = pAdapter->pFreePRDLink;
1019136849Sscottl	pAdapter->pFreePRDLink = PRDTable;
1020136849Sscottl}
1021136849Sscottl
1022136849Sscottlextern PVDevice fGetFirstChild(PVDevice pLogical);
1023136849Sscottlextern void fResetBootMark(PVDevice pLogical);
1024136849Sscottlstatic void
1025136849SscottlfRegisterVdevice(IAL_ADAPTER_T *pAdapter)
1026136849Sscottl{
1027136849Sscottl	PVDevice pPhysical, pLogical;
1028136849Sscottl	PVBus  pVBus;
1029136849Sscottl	int i,j;
1030136849Sscottl
1031149871Sscottl	for(i=0;i<MV_SATA_CHANNELS_NUM;i++) {
1032136849Sscottl		pPhysical = &(pAdapter->VDevices[i]);
1033136849Sscottl		pLogical = pPhysical;
1034136849Sscottl		while (pLogical->pParent) pLogical = pLogical->pParent;
1035136849Sscottl		if (pLogical->vf_online==0) {
1036136849Sscottl			pPhysical->vf_bootmark = pLogical->vf_bootmark = 0;
1037136849Sscottl			continue;
1038136849Sscottl		}
1039149871Sscottl		if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical))
1040136849Sscottl			continue;
1041136849Sscottl
1042136849Sscottl		pVBus = &pAdapter->VBus;
1043149871Sscottl		if(pVBus)
1044149871Sscottl		{
1045136849Sscottl			j=0;
1046149871Sscottl			while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++;
1047149871Sscottl			if(j<MAX_VDEVICE_PER_VBUS){
1048136849Sscottl				pVBus->pVDevice[j] = pLogical;
1049136849Sscottl				pLogical->pVBus = pVBus;
1050136849Sscottl
1051136849Sscottl				if (j>0 && pLogical->vf_bootmark) {
1052136849Sscottl					if (pVBus->pVDevice[0]->vf_bootmark) {
1053136849Sscottl						fResetBootMark(pLogical);
1054149871Sscottl					}
1055149871Sscottl					else {
1056149871Sscottl						do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j);
1057136849Sscottl						pVBus->pVDevice[0] = pLogical;
1058136849Sscottl					}
1059136849Sscottl				}
1060136849Sscottl			}
1061136849Sscottl		}
1062136849Sscottl	}
1063136849Sscottl}
1064136849Sscottl
1065136849SscottlPVDevice
1066136849SscottlGetSpareDisk(_VBUS_ARG PVDevice pArray)
1067136849Sscottl{
1068149871Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt;
1069190809Sdelphij	LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1);
1070190809Sdelphij	LBA_T thiscap, maxcap = MAX_LBA_T;
1071136849Sscottl	PVDevice pVDevice, pFind = NULL;
1072136849Sscottl	int i;
1073136849Sscottl
1074149871Sscottl	for(i=0;i<MV_SATA_CHANNELS_NUM;i++)
1075149871Sscottl	{
1076136849Sscottl		pVDevice = &pAdapter->VDevices[i];
1077136849Sscottl		if(!pVDevice)
1078136849Sscottl			continue;
1079149871Sscottl		thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity;
1080136849Sscottl		/* find the smallest usable spare disk */
1081136849Sscottl		if (pVDevice->VDeviceType==VD_SPARE &&
1082149871Sscottl			pVDevice->u.disk.df_on_line &&
1083149871Sscottl			thiscap < maxcap &&
1084149871Sscottl			thiscap >= capacity)
1085149871Sscottl		{
1086149871Sscottl				maxcap = pVDevice->VDeviceCapacity;
1087149871Sscottl				pFind = pVDevice;
1088136849Sscottl		}
1089136849Sscottl	}
1090136849Sscottl	return pFind;
1091136849Sscottl}
1092136849Sscottl
1093136849Sscottl/******************************************************************
1094136849Sscottl * IO ATA Command
1095136849Sscottl *******************************************************************/
1096136849Sscottlint HPTLIBAPI
1097136849SscottlfDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer)
1098136849Sscottl{
1099136849Sscottl	return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer);
1100136849Sscottl}
1101136849Sscottl
1102136849Sscottlvoid HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode)
1103136849Sscottl{
1104149871Sscottl	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
1105149871Sscottl	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
1106149871Sscottl	MV_U8 channelIndex = pSataChannel->channelNumber;
1107136849Sscottl	UCHAR mvMode;
1108136849Sscottl	/* 508x don't use MW-DMA? */
1109136849Sscottl	if (NewMode>4 && NewMode<8) NewMode = 4;
1110136849Sscottl	pDev->bDeModeSetting = NewMode;
1111136849Sscottl	if (NewMode<=4)
1112136849Sscottl		mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode;
1113136849Sscottl	else
1114136849Sscottl		mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8);
1115136849Sscottl
1116136849Sscottl	/*To fix 88i8030 bug*/
1117136849Sscottl	if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4)
1118136849Sscottl		mvMode = MV_ATA_TRANSFER_UDMA_0;
1119136849Sscottl
1120136849Sscottl	mvSataDisableChannelDma(pSataAdapter, channelIndex);
1121136849Sscottl	/* Flush pending commands */
1122136849Sscottl	mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE);
1123136849Sscottl
1124136849Sscottl	if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1125149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
1126149871Sscottl								   mvMode, 0, 0, 0) == MV_FALSE)
1127149871Sscottl	{
1128136849Sscottl		KdPrint(("channel %d: Set Features failed\n", channelIndex));
1129136849Sscottl	}
1130136849Sscottl	/* Enable EDMA */
1131136849Sscottl	if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE)
1132136849Sscottl		KdPrint(("Failed to enable DMA, channel=%d", channelIndex));
1133136849Sscottl}
1134136849Sscottl
1135190809Sdelphijint HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth)
1136190809Sdelphij{
1137190809Sdelphij	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
1138190809Sdelphij	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
1139190809Sdelphij	MV_U8 channelIndex = pSataChannel->channelNumber;
1140190809Sdelphij	IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
1141190809Sdelphij	MV_CHANNEL		*channelInfo = &(pAdapter->mvChannel[channelIndex]);
1142190809Sdelphij	int dmaActive = pSataChannel->queueCommandsEnabled;
1143190809Sdelphij	int ret = 0;
1144190809Sdelphij
1145190809Sdelphij	if (dmaActive) {
1146190809Sdelphij		mvSataDisableChannelDma(pSataAdapter, channelIndex);
1147190809Sdelphij		mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
1148190809Sdelphij	}
1149190809Sdelphij
1150190809Sdelphij	if (enable) {
1151190809Sdelphij		if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED &&
1152190809Sdelphij			(pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) {
1153190809Sdelphij			UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1;
1154190809Sdelphij			channelInfo->queueDepth = (depth==32)? 31 : depth;
1155190809Sdelphij			mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth);
1156190809Sdelphij			ret = 1;
1157190809Sdelphij		}
1158190809Sdelphij	}
1159190809Sdelphij	else
1160190809Sdelphij	{
1161190809Sdelphij		if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) {
1162190809Sdelphij			channelInfo->queueDepth = 2;
1163190809Sdelphij			mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0);
1164190809Sdelphij			ret = 1;
1165190809Sdelphij		}
1166190809Sdelphij	}
1167190809Sdelphij
1168190809Sdelphij	if (dmaActive)
1169190809Sdelphij		mvSataEnableChannelDma(pSataAdapter,channelIndex);
1170190809Sdelphij	return ret;
1171190809Sdelphij}
1172190809Sdelphij
1173190809Sdelphijint HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth)
1174190809Sdelphij{
1175190809Sdelphij	return 0;
1176190809Sdelphij}
1177190809Sdelphij
1178190809Sdelphijint HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable)
1179190809Sdelphij{
1180190809Sdelphij	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
1181190809Sdelphij	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
1182190809Sdelphij	MV_U8 channelIndex = pSataChannel->channelNumber;
1183190809Sdelphij	IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
1184190809Sdelphij	MV_CHANNEL		*channelInfo = &(pAdapter->mvChannel[channelIndex]);
1185190809Sdelphij	int dmaActive = pSataChannel->queueCommandsEnabled;
1186190809Sdelphij	int ret = 0;
1187190809Sdelphij
1188190809Sdelphij	if (dmaActive) {
1189190809Sdelphij		mvSataDisableChannelDma(pSataAdapter, channelIndex);
1190190809Sdelphij		mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
1191190809Sdelphij	}
1192190809Sdelphij
1193190809Sdelphij	if ((pSataChannel->identifyDevice[82] & (0x20))) {
1194190809Sdelphij		if (enable) {
1195190809Sdelphij			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1196190809Sdelphij				MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0))
1197190809Sdelphij			{
1198190809Sdelphij				channelInfo->writeCacheEnabled = MV_TRUE;
1199190809Sdelphij				ret = 1;
1200190809Sdelphij			}
1201190809Sdelphij		}
1202190809Sdelphij		else {
1203190809Sdelphij			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1204190809Sdelphij				MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0))
1205190809Sdelphij			{
1206190809Sdelphij				channelInfo->writeCacheEnabled = MV_FALSE;
1207190809Sdelphij				ret = 1;
1208190809Sdelphij			}
1209190809Sdelphij		}
1210190809Sdelphij	}
1211190809Sdelphij
1212190809Sdelphij	if (dmaActive)
1213190809Sdelphij		mvSataEnableChannelDma(pSataAdapter,channelIndex);
1214190809Sdelphij	return ret;
1215190809Sdelphij}
1216190809Sdelphij
1217190809Sdelphijint HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable)
1218190809Sdelphij{
1219190809Sdelphij	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
1220190809Sdelphij	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
1221190809Sdelphij	MV_U8 channelIndex = pSataChannel->channelNumber;
1222190809Sdelphij	IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
1223190809Sdelphij	MV_CHANNEL		*channelInfo = &(pAdapter->mvChannel[channelIndex]);
1224190809Sdelphij	int dmaActive = pSataChannel->queueCommandsEnabled;
1225190809Sdelphij	int ret = 0;
1226190809Sdelphij
1227190809Sdelphij	if (dmaActive) {
1228190809Sdelphij		mvSataDisableChannelDma(pSataAdapter, channelIndex);
1229190809Sdelphij		mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
1230190809Sdelphij	}
1231190809Sdelphij
1232190809Sdelphij	if ((pSataChannel->identifyDevice[82] & (0x40))) {
1233190809Sdelphij		if (enable) {
1234190809Sdelphij			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1235190809Sdelphij				MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0))
1236190809Sdelphij			{
1237190809Sdelphij				channelInfo->readAheadEnabled = MV_TRUE;
1238190809Sdelphij				ret = 1;
1239190809Sdelphij			}
1240190809Sdelphij		}
1241190809Sdelphij		else {
1242190809Sdelphij			if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1243190809Sdelphij				MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0))
1244190809Sdelphij			{
1245190809Sdelphij				channelInfo->readAheadEnabled = MV_FALSE;
1246190809Sdelphij				ret = 1;
1247190809Sdelphij			}
1248190809Sdelphij		}
1249190809Sdelphij	}
1250190809Sdelphij
1251190809Sdelphij	if (dmaActive)
1252190809Sdelphij		mvSataEnableChannelDma(pSataAdapter,channelIndex);
1253190809Sdelphij	return ret;
1254190809Sdelphij}
1255190809Sdelphij
1256136849Sscottl#ifdef SUPPORT_ARRAY
1257136849Sscottl#define IdeRegisterVDevice  fCheckArray
1258149871Sscottl#else
1259136849Sscottlvoid
1260136849SscottlIdeRegisterVDevice(PDevice pDev)
1261136849Sscottl{
1262136849Sscottl	PVDevice pVDev = Map2pVDevice(pDev);
1263136849Sscottl
1264136849Sscottl	pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI :
1265149871Sscottl						 pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
1266136849Sscottl	pVDev->vf_online = 1;
1267136849Sscottl	pVDev->VDeviceCapacity = pDev->dDeRealCapacity;
1268136849Sscottl	pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
1269136849Sscottl	pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
1270136849Sscottl}
1271136849Sscottl#endif
1272136849Sscottl
1273149871Sscottlstatic __inline PBUS_DMAMAP
1274149871Sscottldmamap_get(struct IALAdapter * pAdapter)
1275149871Sscottl{
1276149871Sscottl	PBUS_DMAMAP	p = pAdapter->pbus_dmamap_list;
1277149871Sscottl	if (p)
1278149871Sscottl		pAdapter->pbus_dmamap_list = p-> next;
1279149871Sscottl	return p;
1280149871Sscottl}
1281149871Sscottl
1282149871Sscottlstatic __inline void
1283149871Sscottldmamap_put(PBUS_DMAMAP p)
1284149871Sscottl{
1285149871Sscottl	p->next = p->pAdapter->pbus_dmamap_list;
1286149871Sscottl	p->pAdapter->pbus_dmamap_list = p;
1287149871Sscottl}
1288149871Sscottl
1289149871Sscottl/*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/
1290149871Sscottl#if __FreeBSD_version >= 500000
1291190809Sdelphij#define override_kernel_driver()
1292190809Sdelphij
1293149871Sscottlstatic void hpt_init(void *dummy)
1294149871Sscottl{
1295190809Sdelphij	override_kernel_driver();
1296190809Sdelphij	mtx_init(&driver_lock, "hptsleeplock", NULL, MTX_DEF);
1297149871Sscottl}
1298149871SscottlSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL);
1299149871Sscottl#endif
1300149871Sscottl
1301136849Sscottlstatic int num_adapters = 0;
1302136849Sscottlstatic int
1303136849Sscottlinit_adapter(IAL_ADAPTER_T *pAdapter)
1304136849Sscottl{
1305136849Sscottl	PVBus _vbus_p = &pAdapter->VBus;
1306136849Sscottl	MV_SATA_ADAPTER *pMvSataAdapter;
1307149871Sscottl	int i, channel, rid;
1308136849Sscottl
1309136849Sscottl	PVDevice pVDev;
1310136849Sscottl
1311190809Sdelphij	intrmask_t oldspl = lock_driver();
1312190809Sdelphij
1313136849Sscottl	pAdapter->next = 0;
1314136849Sscottl
1315149871Sscottl	if(gIal_Adapter == 0){
1316136849Sscottl		gIal_Adapter = pAdapter;
1317136849Sscottl		pCurAdapter = gIal_Adapter;
1318149871Sscottl	}
1319149871Sscottl	else {
1320136849Sscottl		pCurAdapter->next = pAdapter;
1321136849Sscottl		pCurAdapter = pAdapter;
1322136849Sscottl	}
1323136849Sscottl
1324136849Sscottl	pAdapter->outstandingCommands = 0;
1325136849Sscottl
1326136849Sscottl	pMvSataAdapter = &(pAdapter->mvSataAdapter);
1327136849Sscottl	_vbus_p->OsExt = (void *)pAdapter;
1328136849Sscottl	pMvSataAdapter->IALData = pAdapter;
1329136849Sscottl
1330232854Sscottl	if (bus_dma_tag_create(bus_get_dma_tag(pAdapter->hpt_dev),/* parent */
1331149871Sscottl			4,	/* alignment */
1332149871Sscottl			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1333149871Sscottl			BUS_SPACE_MAXADDR,	/* lowaddr */
1334149871Sscottl			BUS_SPACE_MAXADDR,	/* highaddr */
1335149871Sscottl			NULL, NULL, 		/* filter, filterarg */
1336149871Sscottl			PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */
1337149871Sscottl			MAX_SG_DESCRIPTORS, /* nsegments */
1338149871Sscottl			0x10000,	/* maxsegsize */
1339149871Sscottl			BUS_DMA_WAITOK, 	/* flags */
1340149871Sscottl#if __FreeBSD_version>502000
1341149871Sscottl			busdma_lock_mutex,	/* lockfunc */
1342149871Sscottl			&driver_lock,		/* lockfuncarg */
1343149871Sscottl#endif
1344149871Sscottl			&pAdapter->io_dma_parent /* tag */))
1345149871Sscottl		{
1346201758Smbr			return ENXIO;
1347136849Sscottl	}
1348136849Sscottl
1349136849Sscottl
1350149871Sscottl	if (hptmv_allocate_edma_queues(pAdapter))
1351149871Sscottl	{
1352190809Sdelphij		MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n");
1353190809Sdelphij		unlock_driver(oldspl);
1354149871Sscottl		return ENOMEM;
1355136849Sscottl	}
1356136849Sscottl
1357136849Sscottl	/* also map EPROM address */
1358136849Sscottl	rid = 0x10;
1359149871Sscottl	if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid,
1360149871Sscottl			0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE))
1361149871Sscottl		||
1362149871Sscottl		!(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res)))
1363149871Sscottl	{
1364190809Sdelphij		MV_ERROR("RR18xx: Failed to remap memory space\n");
1365149871Sscottl		hptmv_free_edma_queues(pAdapter);
1366190809Sdelphij		unlock_driver(oldspl);
1367149871Sscottl		return ENXIO;
1368136849Sscottl	}
1369149871Sscottl	else
1370149871Sscottl	{
1371190809Sdelphij		KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress));
1372149871Sscottl	}
1373136849Sscottl
1374136849Sscottl	pMvSataAdapter->adapterId = num_adapters++;
1375136849Sscottl	/* get the revision ID */
1376149871Sscottl	pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1);
1377136849Sscottl	pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev);
1378149871Sscottl
1379190809Sdelphij	/* init RR18xx */
1380136849Sscottl	pMvSataAdapter->intCoalThre[0]= 1;
1381136849Sscottl	pMvSataAdapter->intCoalThre[1]= 1;
1382136849Sscottl	pMvSataAdapter->intTimeThre[0] = 1;
1383136849Sscottl	pMvSataAdapter->intTimeThre[1] = 1;
1384136849Sscottl	pMvSataAdapter->pciCommand = 0x0107E371;
1385136849Sscottl	pMvSataAdapter->pciSerrMask = 0xd77fe6ul;
1386136849Sscottl	pMvSataAdapter->pciInterruptMask = 0xd77fe6ul;
1387136849Sscottl	pMvSataAdapter->mvSataEventNotify = hptmv_event_notify;
1388136849Sscottl
1389149871Sscottl	if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
1390149871Sscottl	{
1391190809Sdelphij		MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n",
1392149871Sscottl				 pMvSataAdapter->adapterId);
1393149871Sscottlunregister:
1394149871Sscottl		bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res);
1395149871Sscottl		hptmv_free_edma_queues(pAdapter);
1396190809Sdelphij		unlock_driver(oldspl);
1397149871Sscottl		return ENXIO;
1398136849Sscottl	}
1399136849Sscottl	pAdapter->ver_601 = pMvSataAdapter->pcbVersion;
1400136849Sscottl
1401136849Sscottl#ifndef FOR_DEMO
1402136849Sscottl	set_fail_leds(pMvSataAdapter, 0);
1403136849Sscottl#endif
1404136849Sscottl
1405136849Sscottl	/* setup command blocks */
1406136849Sscottl	KdPrint(("Allocate command blocks\n"));
1407136849Sscottl	_vbus_(pFreeCommands) = 0;
1408149871Sscottl	pAdapter->pCommandBlocks =
1409149871Sscottl		malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT);
1410149871Sscottl	KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks));
1411149871Sscottl	if (!pAdapter->pCommandBlocks) {
1412149871Sscottl		MV_ERROR("insufficient memory\n");
1413149871Sscottl		goto unregister;
1414149871Sscottl	}
1415136849Sscottl
1416149871Sscottl	for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) {
1417149871Sscottl		FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i]));
1418149871Sscottl	}
1419136849Sscottl
1420149871Sscottl	/*Set up the bus_dmamap*/
1421149871Sscottl	pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT);
1422149871Sscottl	if(!pAdapter->pbus_dmamap) {
1423149871Sscottl		MV_ERROR("insufficient memory\n");
1424149871Sscottl		free(pAdapter->pCommandBlocks, M_DEVBUF);
1425149871Sscottl		goto unregister;
1426136849Sscottl	}
1427136849Sscottl
1428149871Sscottl	memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM);
1429149871Sscottl	pAdapter->pbus_dmamap_list = 0;
1430149871Sscottl	for (i=0; i < MAX_QUEUE_COMM; i++) {
1431149871Sscottl		PBUS_DMAMAP  pmap = &(pAdapter->pbus_dmamap[i]);
1432149871Sscottl		pmap->pAdapter = pAdapter;
1433149871Sscottl		dmamap_put(pmap);
1434149871Sscottl
1435149871Sscottl		if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) {
1436149871Sscottl			MV_ERROR("Can not allocate dma map\n");
1437149871Sscottl			free(pAdapter->pCommandBlocks, M_DEVBUF);
1438149871Sscottl			free(pAdapter->pbus_dmamap, M_DEVBUF);
1439149871Sscottl			goto unregister;
1440149871Sscottl		}
1441149871Sscottl	}
1442136849Sscottl	/* setup PRD Tables */
1443136849Sscottl	KdPrint(("Allocate PRD Tables\n"));
1444136849Sscottl	pAdapter->pFreePRDLink = 0;
1445149871Sscottl
1446149871Sscottl	pAdapter->prdTableAddr = (PUCHAR)contigmalloc(
1447149871Sscottl		(PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
1448149871Sscottl
1449136862Sscottl	KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr));
1450136849Sscottl	if (!pAdapter->prdTableAddr) {
1451136849Sscottl		MV_ERROR("insufficient PRD Tables\n");
1452136849Sscottl		goto unregister;
1453136849Sscottl	}
1454149871Sscottl	pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL);
1455149871Sscottl	{
1456149871Sscottl		PUCHAR PRDTable = pAdapter->prdTableAlignedAddr;
1457149871Sscottl		for (i=0; i<PRD_TABLES_FOR_VBUS; i++)
1458149871Sscottl		{
1459149871Sscottl/*			KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */
1460149871Sscottl			FreePRDTable(pAdapter, PRDTable);
1461149871Sscottl			PRDTable += PRD_ENTRIES_SIZE;
1462149871Sscottl		}
1463136849Sscottl	}
1464136849Sscottl
1465136849Sscottl	/* enable the adapter interrupts */
1466136849Sscottl
1467136849Sscottl	/* configure and start the connected channels*/
1468149871Sscottl	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
1469149871Sscottl	{
1470136849Sscottl		pAdapter->mvChannel[channel].online = MV_FALSE;
1471136849Sscottl		if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel)
1472149871Sscottl			== MV_TRUE)
1473149871Sscottl		{
1474190809Sdelphij			KdPrint(("RR18xx[%d]: channel %d is connected\n",
1475149871Sscottl					  pMvSataAdapter->adapterId, channel));
1476136849Sscottl
1477149871Sscottl			if (hptmv_init_channel(pAdapter, channel) == 0)
1478149871Sscottl			{
1479149871Sscottl				if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE)
1480149871Sscottl				{
1481190809Sdelphij					MV_ERROR("RR18xx[%d]: Failed to configure channel"
1482149871Sscottl							 " %d\n",pMvSataAdapter->adapterId, channel);
1483149871Sscottl					hptmv_free_channel(pAdapter, channel);
1484149871Sscottl				}
1485149871Sscottl				else
1486149871Sscottl				{
1487149871Sscottl					if (start_channel(pAdapter, channel))
1488149871Sscottl					{
1489190809Sdelphij						MV_ERROR("RR18xx[%d]: Failed to start channel,"
1490149871Sscottl								 " channel=%d\n",pMvSataAdapter->adapterId,
1491149871Sscottl								 channel);
1492149871Sscottl						hptmv_free_channel(pAdapter, channel);
1493149871Sscottl					}
1494149871Sscottl					pAdapter->mvChannel[channel].online = MV_TRUE;
1495149871Sscottl					/*  mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter,
1496149871Sscottl													   channel,
1497149871Sscottl													   MV_TRUE);*/
1498149871Sscottl				}
1499136849Sscottl			}
1500136849Sscottl		}
1501136849Sscottl		KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n",
1502136849Sscottl			pAdapter->mvChannel[channel].online, channel));
1503136849Sscottl	}
1504136849Sscottl
1505136849Sscottl#ifdef SUPPORT_ARRAY
1506136849Sscottl	for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) {
1507136849Sscottl		pVDev = ArrayTables(i);
1508136849Sscottl		mArFreeArrayTable(pVDev);
1509136849Sscottl	}
1510136849Sscottl#endif
1511136849Sscottl
1512136849Sscottl	KdPrint(("Initialize Devices\n"));
1513136849Sscottl	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
1514149871Sscottl		MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel];
1515136849Sscottl		if (pMvSataChannel) {
1516136849Sscottl			init_vdev_params(pAdapter, channel);
1517136849Sscottl			IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk);
1518136849Sscottl		}
1519136849Sscottl	}
1520136849Sscottl#ifdef SUPPORT_ARRAY
1521136849Sscottl	CheckArrayCritical(_VBUS_P0);
1522136849Sscottl#endif
1523136849Sscottl	_vbus_p->nInstances = 1;
1524136849Sscottl	fRegisterVdevice(pAdapter);
1525136849Sscottl
1526136849Sscottl	for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) {
1527136849Sscottl		pVDev = _vbus_p->pVDevice[channel];
1528136849Sscottl		if (pVDev && pVDev->vf_online)
1529136849Sscottl			fCheckBootable(pVDev);
1530136849Sscottl	}
1531136849Sscottl
1532136849Sscottl#if defined(SUPPORT_ARRAY) && defined(_RAID5N_)
1533136849Sscottl	init_raid5_memory(_VBUS_P0);
1534136849Sscottl	_vbus_(r5).enable_write_back = 1;
1535190809Sdelphij	printf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled");
1536136849Sscottl#endif
1537136849Sscottl
1538136849Sscottl	mvSataUnmaskAdapterInterrupt(pMvSataAdapter);
1539190809Sdelphij	unlock_driver(oldspl);
1540136849Sscottl	return 0;
1541136849Sscottl}
1542136849Sscottl
1543136849Sscottlint
1544136849SscottlMvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
1545136849Sscottl{
1546149871Sscottl	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData;
1547136849Sscottl
1548136849Sscottl	mvSataDisableChannelDma(pMvSataAdapter, channel);
1549136849Sscottl	/* Flush pending commands */
1550136849Sscottl	mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
1551136849Sscottl
1552136849Sscottl	/* Software reset channel */
1553149871Sscottl	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE)
1554149871Sscottl	{
1555190809Sdelphij		MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n",
1556149871Sscottl				 pMvSataAdapter->adapterId, channel);
1557149871Sscottl		hptmv_free_channel(pAdapter, channel);
1558136849Sscottl		return -1;
1559136849Sscottl	}
1560136849Sscottl
1561136849Sscottl	/* Hardware reset channel */
1562149871Sscottl	if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE)
1563149871Sscottl	{
1564190809Sdelphij		MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n",
1565149871Sscottl				 pMvSataAdapter->adapterId, channel);
1566136849Sscottl		hptmv_free_channel(pAdapter, channel);
1567136849Sscottl		return -1;
1568136849Sscottl	}
1569136849Sscottl
1570149871Sscottl	if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE)
1571149871Sscottl	{
1572190809Sdelphij		 MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n",
1573149871Sscottl				 pMvSataAdapter->adapterId, channel);
1574136849Sscottl		hptmv_free_channel(pAdapter, channel);
1575136849Sscottl		return -1;
1576149871Sscottl	}else
1577149871Sscottl	{
1578149871Sscottl		MV_ERROR("channel %d: perform recalibrate command", channel);
1579149871Sscottl		if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
1580149871Sscottl								MV_NON_UDMA_PROTOCOL_NON_DATA,
1581149871Sscottl								MV_FALSE,
1582149871Sscottl								NULL,	 /* pBuffer*/
1583149871Sscottl								0,		 /* count  */
1584149871Sscottl								0,		/*features*/
1585149871Sscottl										/* sectorCount */
1586149871Sscottl								0,
1587149871Sscottl								0,	/* lbaLow */
1588149871Sscottl								0,	/* lbaMid */
1589149871Sscottl									/* lbaHigh */
1590149871Sscottl								0,
1591149871Sscottl								0,		/* device */
1592149871Sscottl										/* command */
1593149871Sscottl								0x10))
1594149871Sscottl			MV_ERROR("channel %d: recalibrate failed", channel);
1595149871Sscottl
1596136849Sscottl		/* Set transfer mode */
1597136849Sscottl		if((mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1598149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1599149871Sscottl						MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) ||
1600149871Sscottl			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1601149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1602149871Sscottl						pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) ||
1603149871Sscottl			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1604149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1605149871Sscottl						pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) )
1606149871Sscottl		{
1607136849Sscottl			MV_ERROR("channel %d: Set Features failed", channel);
1608136849Sscottl			hptmv_free_channel(pAdapter, channel);
1609136849Sscottl			return -1;
1610136849Sscottl		}
1611136849Sscottl		/* Enable EDMA */
1612149871Sscottl		if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE)
1613149871Sscottl		{
1614136849Sscottl			MV_ERROR("Failed to enable DMA, channel=%d", channel);
1615136849Sscottl			hptmv_free_channel(pAdapter, channel);
1616136849Sscottl			return -1;
1617136849Sscottl		}
1618136849Sscottl	}
1619136849Sscottl	return 0;
1620136849Sscottl}
1621136849Sscottl
1622136849Sscottlstatic int
1623136849SscottlfResetActiveCommands(PVBus _vbus_p)
1624136849Sscottl{
1625149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
1626136849Sscottl	MV_U8 channel;
1627136849Sscottl	for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
1628149871Sscottl		if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands)
1629149871Sscottl			MvSataResetChannel(pMvSataAdapter,channel);
1630136849Sscottl	}
1631136849Sscottl	return 0;
1632136849Sscottl}
1633136849Sscottl
1634149871Sscottlvoid fCompleteAllCommandsSynchronously(PVBus _vbus_p)
1635136849Sscottl{
1636136849Sscottl	UINT cont;
1637136849Sscottl	ULONG ticks = 0;
1638136849Sscottl	MV_U8 channel;
1639149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
1640136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
1641136849Sscottl
1642136849Sscottl	do {
1643136849Sscottlcheck_cmds:
1644136849Sscottl		cont = 0;
1645136849Sscottl		CheckPendingCall(_VBUS_P0);
1646136849Sscottl#ifdef _RAID5N_
1647136849Sscottl		dataxfer_poll();
1648136849Sscottl		xor_poll();
1649136849Sscottl#endif
1650149871Sscottl		for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
1651136849Sscottl			pMvSataChannel = pMvSataAdapter->sataChannel[channel];
1652149871Sscottl			if (pMvSataChannel && pMvSataChannel->outstandingCommands)
1653149871Sscottl			{
1654136849Sscottl				while (pMvSataChannel->outstandingCommands) {
1655149871Sscottl					if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) {
1656136849Sscottl						StallExec(1000);
1657136849Sscottl						if (ticks++ > 3000) {
1658149871Sscottl							MvSataResetChannel(pMvSataAdapter,channel);
1659136849Sscottl							goto check_cmds;
1660136849Sscottl						}
1661149871Sscottl					}
1662149871Sscottl					else
1663136849Sscottl						ticks = 0;
1664136849Sscottl				}
1665136849Sscottl				cont = 1;
1666136849Sscottl			}
1667136849Sscottl		}
1668136849Sscottl	} while (cont);
1669136849Sscottl}
1670136849Sscottl
1671136849Sscottlvoid
1672136849SscottlfResetVBus(_VBUS_ARG0)
1673136849Sscottl{
1674136862Sscottl	KdPrint(("fMvResetBus(%p)", _vbus_p));
1675136849Sscottl
1676136849Sscottl	/* some commands may already finished. */
1677136849Sscottl	CheckPendingCall(_VBUS_P0);
1678136849Sscottl
1679136849Sscottl	fResetActiveCommands(_vbus_p);
1680136849Sscottl	/*
1681136849Sscottl	 * the other pending commands may still be finished successfully.
1682136849Sscottl	 */
1683136849Sscottl	fCompleteAllCommandsSynchronously(_vbus_p);
1684136849Sscottl
1685136849Sscottl	/* Now there should be no pending commands. No more action needed. */
1686136849Sscottl	CheckIdleCall(_VBUS_P0);
1687136849Sscottl
1688136849Sscottl	KdPrint(("fMvResetBus() done"));
1689136849Sscottl}
1690136849Sscottl
1691149871Sscottl/*No rescan function*/
1692136849Sscottlvoid
1693136849SscottlfRescanAllDevice(_VBUS_ARG0)
1694136849Sscottl{
1695136849Sscottl}
1696136849Sscottl
1697136849Sscottlstatic MV_BOOLEAN
1698149871SscottlCommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
1699149871Sscottl					MV_U8 channelNum,
1700149871Sscottl					MV_COMPLETION_TYPE comp_type,
1701149871Sscottl					MV_VOID_PTR commandId,
1702149871Sscottl					MV_U16 responseFlags,
1703149871Sscottl					MV_U32 timeStamp,
1704149871Sscottl					MV_STORAGE_DEVICE_REGISTERS *registerStruct)
1705136849Sscottl{
1706136849Sscottl	PCommand pCmd = (PCommand) commandId;
1707136849Sscottl	_VBUS_INST(pCmd->pVDevice->pVBus)
1708136849Sscottl
1709136849Sscottl	if (pCmd->uScratch.sata_param.prdAddr)
1710149871Sscottl		FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr);
1711136849Sscottl
1712149871Sscottl	switch (comp_type)
1713149871Sscottl	{
1714136849Sscottl	case MV_COMPLETION_TYPE_NORMAL:
1715136849Sscottl		pCmd->Result = RETURN_SUCCESS;
1716136849Sscottl		break;
1717136849Sscottl	case MV_COMPLETION_TYPE_ABORT:
1718136849Sscottl		pCmd->Result = RETURN_BUS_RESET;
1719136849Sscottl		break;
1720136849Sscottl	case MV_COMPLETION_TYPE_ERROR:
1721149871Sscottl		 MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n",
1722149871Sscottl				 pMvSataAdapter->adapterId, channelNum, responseFlags);
1723136849Sscottl
1724136849Sscottl		if (responseFlags & 4) {
1725149871Sscottl			MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x,"
1726149871Sscottl				" LBA high %x, device %x, status %x\n",
1727149871Sscottl				registerStruct->errorRegister,
1728149871Sscottl				registerStruct->sectorCountRegister,
1729149871Sscottl				registerStruct->lbaLowRegister,
1730149871Sscottl				registerStruct->lbaMidRegister,
1731149871Sscottl				registerStruct->lbaHighRegister,
1732149871Sscottl				registerStruct->deviceRegister,
1733149871Sscottl				registerStruct->statusRegister);
1734136849Sscottl		}
1735149871Sscottl		/*We can't do handleEdmaError directly here, because CommandCompletionCB is called by
1736149871Sscottl		 * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/
1737136849Sscottl		pCmd->uScratch.sata_param.responseFlags = responseFlags;
1738149871Sscottl		pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister;
1739149871Sscottl		pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister;
1740136849Sscottl		pCmd->pVDevice->u.disk.QueueLength--;
1741136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd);
1742136849Sscottl		return TRUE;
1743136849Sscottl
1744136849Sscottl	default:
1745136849Sscottl		MV_ERROR(" Unknown completion type (%d)\n", comp_type);
1746136849Sscottl		return MV_FALSE;
1747136849Sscottl	}
1748136849Sscottl
1749149871Sscottl	if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) {
1750136849Sscottl		pCmd->uScratch.sata_param.cmd_priv --;
1751136849Sscottl		return TRUE;
1752136849Sscottl	}
1753136849Sscottl	pCmd->pVDevice->u.disk.QueueLength--;
1754136849Sscottl	CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1755136849Sscottl	return TRUE;
1756136849Sscottl}
1757136849Sscottl
1758136849Sscottlvoid
1759136849SscottlfDeviceSendCommand(_VBUS_ARG PCommand pCmd)
1760136849Sscottl{
1761149871Sscottl	MV_SATA_EDMA_PRD_ENTRY  *pPRDTable = 0;
1762136849Sscottl	MV_SATA_ADAPTER *pMvSataAdapter;
1763136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
1764149871Sscottl	PVDevice pVDevice = pCmd->pVDevice;
1765149871Sscottl	PDevice  pDevice = &pVDevice->u.disk;
1766190809Sdelphij	LBA_T    Lba = pCmd->uCmd.Ide.Lba;
1767149871Sscottl	USHORT   nSector = pCmd->uCmd.Ide.nSectors;
1768149871Sscottl
1769136849Sscottl	MV_QUEUE_COMMAND_RESULT result;
1770136849Sscottl	MV_QUEUE_COMMAND_INFO commandInfo;
1771149871Sscottl	MV_UDMA_COMMAND_PARAMS  *pUdmaParams = &commandInfo.commandParams.udmaCommand;
1772149871Sscottl	MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand;
1773149871Sscottl
1774190809Sdelphij	MV_BOOLEAN is48bit;
1775149871Sscottl	MV_U8      channel;
1776149871Sscottl	int        i=0;
1777149871Sscottl
1778136849Sscottl	DECLARE_BUFFER(FPSCAT_GATH, tmpSg);
1779136849Sscottl
1780136849Sscottl	if (!pDevice->df_on_line) {
1781136849Sscottl		MV_ERROR("Device is offline");
1782136849Sscottl		pCmd->Result = RETURN_BAD_DEVICE;
1783136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1784136849Sscottl		return;
1785136849Sscottl	}
1786136849Sscottl
1787136849Sscottl	pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors;
1788136849Sscottl	pMvSataChannel = pDevice->mv;
1789136849Sscottl	pMvSataAdapter = pMvSataChannel->mvSataAdapter;
1790136849Sscottl	channel = pMvSataChannel->channelNumber;
1791136849Sscottl
1792149871Sscottl	/* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */
1793136849Sscottl	Lba += pDevice->dDeHiddenLba;
1794136849Sscottl	/* check LBA */
1795136849Sscottl	if (Lba+nSector-1 > pDevice->dDeRealCapacity) {
1796136849Sscottl		pCmd->Result = RETURN_INVALID_REQUEST;
1797136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1798136849Sscottl		return;
1799136849Sscottl	}
1800136849Sscottl
1801190809Sdelphij	/*
1802190809Sdelphij	 * always use 48bit LBA if drive supports it.
1803190809Sdelphij	 * Some Seagate drives report error if you use a 28-bit command
1804190809Sdelphij	 * to access sector 0xfffffff.
1805190809Sdelphij	 */
1806190809Sdelphij	is48bit = pMvSataChannel->lba48Address;
1807136849Sscottl
1808149871Sscottl	switch (pCmd->uCmd.Ide.Command)
1809149871Sscottl	{
1810136849Sscottl	case IDE_COMMAND_READ:
1811136849Sscottl	case IDE_COMMAND_WRITE:
1812136849Sscottl		if (pDevice->bDeModeSetting<8) goto pio;
1813136849Sscottl
1814136849Sscottl		commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA;
1815136849Sscottl		pUdmaParams->isEXT = is48bit;
1816136849Sscottl		pUdmaParams->numOfSectors = nSector;
1817136849Sscottl		pUdmaParams->lowLBAAddress = Lba;
1818136849Sscottl		pUdmaParams->highLBAAddress = 0;
1819136849Sscottl		pUdmaParams->prdHighAddr = 0;
1820136849Sscottl		pUdmaParams->callBack = CommandCompletionCB;
1821136849Sscottl		pUdmaParams->commandId = (MV_VOID_PTR )pCmd;
1822136849Sscottl		if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ)
1823136849Sscottl			pUdmaParams->readWrite = MV_UDMA_TYPE_READ;
1824136849Sscottl		else
1825136849Sscottl			pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE;
1826136849Sscottl
1827136849Sscottl		if (pCmd->pSgTable && pCmd->cf_physical_sg) {
1828136849Sscottl			FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
1829149871Sscottl			do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
1830149871Sscottl		}
1831149871Sscottl		else {
1832149871Sscottl			if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) {
1833136849Sscottlpio:
1834149871Sscottl				mvSataDisableChannelDma(pMvSataAdapter, channel);
1835149871Sscottl				mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
1836149871Sscottl
1837149871Sscottl				if (pCmd->pSgTable && pCmd->cf_physical_sg==0) {
1838149871Sscottl					FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
1839149871Sscottl					do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
1840149871Sscottl				}
1841149871Sscottl				else {
1842149871Sscottl					if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) {
1843149871Sscottl						pCmd->Result = RETURN_NEED_LOGICAL_SG;
1844149871Sscottl						goto finish_cmd;
1845149871Sscottl					}
1846149871Sscottl				}
1847149871Sscottl
1848136849Sscottl				do {
1849149871Sscottl					ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000;
1850149871Sscottl					ULONG_PTR addr = tmpSg->dSgAddress;
1851149871Sscottl					if (size & 0x1ff) {
1852149871Sscottl						pCmd->Result = RETURN_INVALID_REQUEST;
1853149871Sscottl						goto finish_cmd;
1854149871Sscottl					}
1855149871Sscottl					if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
1856149871Sscottl						(pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN,
1857149871Sscottl						is48bit,
1858149871Sscottl						(MV_U16_PTR)addr,
1859149871Sscottl						size >> 1,	/* count       */
1860149871Sscottl						0,		/* features  N/A  */
1861149871Sscottl						(MV_U16)(size>>9),	/*sector count*/
1862149871Sscottl						(MV_U16)(  (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 )  | (UCHAR)(Lba & 0xFF) ), /*lbalow*/
1863149871Sscottl						(MV_U16)((Lba >> 8) & 0xFF), /* lbaMid      */
1864149871Sscottl						(MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh     */
1865149871Sscottl						(MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device      */
1866149871Sscottl						(MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command)
1867149871Sscottl					)==MV_FALSE)
1868149871Sscottl					{
1869149871Sscottl						pCmd->Result = RETURN_IDE_ERROR;
1870149871Sscottl						goto finish_cmd;
1871149871Sscottl					}
1872149871Sscottl					Lba += size>>9;
1873149871Sscottl					if(Lba & 0xF0000000) is48bit = MV_TRUE;
1874136849Sscottl				}
1875149871Sscottl				while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
1876149871Sscottl				pCmd->Result = RETURN_SUCCESS;
1877149871Sscottlfinish_cmd:
1878149871Sscottl				mvSataEnableChannelDma(pMvSataAdapter,channel);
1879149871Sscottl				CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1880149871Sscottl				return;
1881136849Sscottl			}
1882136849Sscottl		}
1883136849Sscottl
1884149871Sscottl		pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData);
1885136862Sscottl		KdPrint(("pPRDTable:%p\n",pPRDTable));
1886136849Sscottl		if (!pPRDTable) {
1887136849Sscottl			pCmd->Result = RETURN_DEVICE_BUSY;
1888149871Sscottl			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1889136849Sscottl			HPT_ASSERT(0);
1890136849Sscottl			return;
1891136849Sscottl		}
1892136849Sscottl
1893149871Sscottl		do{
1894149871Sscottl			pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0);
1895136849Sscottl			pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag;
1896136849Sscottl			pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize;
1897136849Sscottl			pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress;
1898136849Sscottl			pPRDTable[i].reserved = 0;
1899136849Sscottl			i++;
1900149871Sscottl		}while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
1901136849Sscottl
1902149871Sscottl		pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable);
1903149871Sscottl		if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) {
1904136849Sscottl			pUdmaParams->numOfSectors = 0;
1905136849Sscottl		}
1906136849Sscottl
1907136849Sscottl		pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable;
1908136849Sscottl
1909149871Sscottl		result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1910136849Sscottl
1911149871Sscottl		if (result != MV_QUEUE_COMMAND_RESULT_OK)
1912149871Sscottl		{
1913136849Sscottlqueue_failed:
1914149871Sscottl			switch (result)
1915149871Sscottl			{
1916136849Sscottl			case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
1917149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA "
1918149871Sscottl						 "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress);
1919136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1920136849Sscottl				break;
1921136849Sscottl			case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
1922149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. EDMA"
1923149871Sscottl						 " disabled adapter %d channel %d\n",
1924149871Sscottl						 pMvSataAdapter->adapterId, channel);
1925136849Sscottl				mvSataEnableChannelDma(pMvSataAdapter,channel);
1926136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1927136849Sscottl				break;
1928136849Sscottl			case MV_QUEUE_COMMAND_RESULT_FULL:
1929149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. Queue is"
1930149871Sscottl						 " Full adapter %d channel %d\n",
1931149871Sscottl						 pMvSataAdapter->adapterId, channel);
1932136849Sscottl				pCmd->Result = RETURN_DEVICE_BUSY;
1933136849Sscottl				break;
1934136849Sscottl			case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
1935149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. (Bad "
1936149871Sscottl						 "Params), pMvSataAdapter: %p,  pSataChannel: %p.\n",
1937149871Sscottl						 pMvSataAdapter, pMvSataAdapter->sataChannel[channel]);
1938136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1939136849Sscottl				break;
1940136849Sscottl			default:
1941149871Sscottl				MV_ERROR("IAL Error: Bad result value (%d) from queue"
1942149871Sscottl						 " command\n", result);
1943136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1944136849Sscottl			}
1945136849Sscottl			if(pPRDTable)
1946149871Sscottl				FreePRDTable(pMvSataAdapter->IALData,pPRDTable);
1947149871Sscottl			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1948136849Sscottl		}
1949136849Sscottl		pDevice->QueueLength++;
1950136849Sscottl		return;
1951136849Sscottl
1952136849Sscottl	case IDE_COMMAND_VERIFY:
1953136849Sscottl		commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
1954136849Sscottl		pNoUdmaParams->bufPtr = NULL;
1955136849Sscottl		pNoUdmaParams->callBack = CommandCompletionCB;
1956136849Sscottl		pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd;
1957136849Sscottl		pNoUdmaParams->count = 0;
1958136849Sscottl		pNoUdmaParams->features = 0;
1959136849Sscottl		pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
1960136849Sscottl
1961136849Sscottl		pCmd->uScratch.sata_param.cmd_priv = 1;
1962136849Sscottl		if (pMvSataChannel->lba48Address == MV_TRUE){
1963149871Sscottl			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT;
1964136849Sscottl			pNoUdmaParams->isEXT = MV_TRUE;
1965149871Sscottl			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
1966136849Sscottl			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
1967136849Sscottl			pNoUdmaParams->lbaLow =
1968149871Sscottl				(MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff));
1969136849Sscottl			pNoUdmaParams->sectorCount = nSector;
1970136849Sscottl			pNoUdmaParams->device = 0x40;
1971149871Sscottl			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1972149871Sscottl			if (result != MV_QUEUE_COMMAND_RESULT_OK){
1973136849Sscottl				goto queue_failed;
1974136849Sscottl			}
1975136849Sscottl			return;
1976136849Sscottl		}
1977149871Sscottl		else{
1978149871Sscottl			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS;
1979149871Sscottl			pNoUdmaParams->isEXT = MV_FALSE;
1980149871Sscottl			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
1981149871Sscottl			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
1982149871Sscottl			pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff);
1983149871Sscottl			pNoUdmaParams->sectorCount = 0xff & nSector;
1984149871Sscottl			pNoUdmaParams->device = (MV_U8)(0x40 |
1985149871Sscottl				((Lba & 0xf000000) >> 24));
1986149871Sscottl			pNoUdmaParams->callBack = CommandCompletionCB;
1987149871Sscottl			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1988149871Sscottl			/*FIXME: how about the commands already queued? but marvel also forgets to consider this*/
1989149871Sscottl			if (result != MV_QUEUE_COMMAND_RESULT_OK){
1990149871Sscottl				goto queue_failed;
1991149871Sscottl			}
1992136849Sscottl		}
1993136849Sscottl		break;
1994136849Sscottl	default:
1995136849Sscottl		pCmd->Result = RETURN_INVALID_REQUEST;
1996136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1997136849Sscottl		break;
1998136849Sscottl	}
1999136849Sscottl}
2000136849Sscottl
2001136849Sscottl/**********************************************************
2002136849Sscottl *
2003136849Sscottl *	Probe the hostadapter.
2004136849Sscottl *
2005136849Sscottl **********************************************************/
2006136849Sscottlstatic int
2007136849Sscottlhpt_probe(device_t dev)
2008136849Sscottl{
2009136849Sscottl	if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) &&
2010136849Sscottl		(pci_get_device(dev) == MV_SATA_DEVICE_ID_5081
2011136849Sscottl#ifdef FOR_DEMO
2012136849Sscottl		|| pci_get_device(dev) == MV_SATA_DEVICE_ID_5080
2013136849Sscottl#endif
2014149871Sscottl		))
2015149871Sscottl	{
2016136849Sscottl		KdPrintI((CONTROLLER_NAME " found\n"));
2017136849Sscottl		device_set_desc(dev, CONTROLLER_NAME);
2018136849Sscottl		return 0;
2019136849Sscottl	}
2020136849Sscottl	else
2021136849Sscottl		return(ENXIO);
2022136849Sscottl}
2023136849Sscottl
2024136849Sscottl/***********************************************************
2025136849Sscottl *
2026136849Sscottl *      Auto configuration:  attach and init a host adapter.
2027136849Sscottl *
2028136849Sscottl ***********************************************************/
2029136849Sscottlstatic int
2030136849Sscottlhpt_attach(device_t dev)
2031136849Sscottl{
2032149871Sscottl	IAL_ADAPTER_T * pAdapter = device_get_softc(dev);
2033136849Sscottl	int rid;
2034136849Sscottl	union ccb *ccb;
2035136849Sscottl	struct cam_devq *devq;
2036136849Sscottl	struct cam_sim *hpt_vsim;
2037136849Sscottl
2038149871Sscottl	printf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION);
2039136849Sscottl
2040149871Sscottl	if (!pAdapter)
2041149871Sscottl	{
2042149871Sscottl		pAdapter = (IAL_ADAPTER_T *)malloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT);
2043149871Sscottl#if __FreeBSD_version > 410000
2044149871Sscottl		device_set_softc(dev, (void *)pAdapter);
2045149871Sscottl#else
2046149871Sscottl		device_set_driver(dev, (driver_t *)pAdapter);
2047149871Sscottl#endif
2048149871Sscottl	}
2049149871Sscottl
2050149871Sscottl	if (!pAdapter) return (ENOMEM);
2051149871Sscottl	bzero(pAdapter, sizeof(IAL_ADAPTER_T));
2052149871Sscottl
2053136849Sscottl	pAdapter->hpt_dev = dev;
2054136849Sscottl
2055136849Sscottl	rid = init_adapter(pAdapter);
2056136849Sscottl	if (rid)
2057136849Sscottl		return rid;
2058136849Sscottl
2059136849Sscottl	rid = 0;
2060149871Sscottl	if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL)
2061149871Sscottl	{
2062136849Sscottl		hpt_printk(("can't allocate interrupt\n"));
2063136849Sscottl		return(ENXIO);
2064136849Sscottl	}
2065136849Sscottl
2066190809Sdelphij#if __FreeBSD_version <700000
2067190809Sdelphij	if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM,
2068190809Sdelphij				hpt_intr, pAdapter, &pAdapter->hpt_intr))
2069190809Sdelphij#else
2070190809Sdelphij	if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM,
2071190809Sdelphij				NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr))
2072190809Sdelphij#endif
2073149871Sscottl	{
2074136849Sscottl		hpt_printk(("can't set up interrupt\n"));
2075136849Sscottl		free(pAdapter, M_DEVBUF);
2076136849Sscottl		return(ENXIO);
2077136849Sscottl	}
2078136849Sscottl
2079149871Sscottl
2080149871Sscottl	if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL)
2081149871Sscottl	{
2082149871Sscottl		bzero(ccb, sizeof(*ccb));
2083136849Sscottl		ccb->ccb_h.pinfo.priority = 1;
2084136849Sscottl		ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
2085149871Sscottl	}
2086149871Sscottl	else
2087149871Sscottl	{
2088136849Sscottl		return ENOMEM;
2089136849Sscottl	}
2090136849Sscottl	/*
2091136849Sscottl	 * Create the device queue for our SIM(s).
2092136849Sscottl	 */
2093149871Sscottl	if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL)
2094149871Sscottl	{
2095136849Sscottl		KdPrint(("ENXIO\n"));
2096136849Sscottl		return ENOMEM;
2097136849Sscottl	}
2098136849Sscottl
2099136849Sscottl	/*
2100136849Sscottl	 * Construct our SIM entry
2101136849Sscottl	 */
2102190809Sdelphij#if __FreeBSD_version <700000
2103190809Sdelphij	hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
2104190809Sdelphij			pAdapter, device_get_unit(pAdapter->hpt_dev), 1, 8, devq);
2105190809Sdelphij#else
2106190809Sdelphij	hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
2107190809Sdelphij			pAdapter, device_get_unit(pAdapter->hpt_dev), &Giant, 1, 8, devq);
2108190809Sdelphij#endif
2109190809Sdelphij	if (hpt_vsim == NULL) {
2110136849Sscottl		cam_simq_free(devq);
2111136849Sscottl		return ENOMEM;
2112136849Sscottl	}
2113136849Sscottl
2114190809Sdelphij#if __FreeBSD_version <700000
2115190809Sdelphij	if (xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS)
2116190809Sdelphij#else
2117190809Sdelphij	if (xpt_bus_register(hpt_vsim, dev, 0) != CAM_SUCCESS)
2118190809Sdelphij#endif
2119149871Sscottl	{
2120136849Sscottl		cam_sim_free(hpt_vsim, /*free devq*/ TRUE);
2121136849Sscottl		hpt_vsim = NULL;
2122136849Sscottl		return ENXIO;
2123136849Sscottl	}
2124136849Sscottl
2125136849Sscottl	if(xpt_create_path(&pAdapter->path, /*periph */ NULL,
2126149871Sscottl			cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD,
2127149871Sscottl			CAM_LUN_WILDCARD) != CAM_REQ_CMP)
2128149871Sscottl	{
2129136849Sscottl		xpt_bus_deregister(cam_sim_path(hpt_vsim));
2130136849Sscottl		cam_sim_free(hpt_vsim, /*free_devq*/TRUE);
2131136849Sscottl		hpt_vsim = NULL;
2132136849Sscottl		return ENXIO;
2133136849Sscottl	}
2134136849Sscottl
2135136849Sscottl	xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5);
2136136849Sscottl	ccb->ccb_h.func_code = XPT_SASYNC_CB;
2137136849Sscottl	ccb->csa.event_enable = AC_LOST_DEVICE;
2138136849Sscottl	ccb->csa.callback = hpt_async;
2139136849Sscottl	ccb->csa.callback_arg = hpt_vsim;
2140136849Sscottl	xpt_action((union ccb *)ccb);
2141136849Sscottl	free(ccb, M_DEVBUF);
2142136849Sscottl
2143190863Sdelphij	if (device_get_unit(dev) == 0) {
2144190810Sdelphij		/* Start the work thread.  XXX */
2145190810Sdelphij		launch_worker_thread();
2146139044Snjl	}
2147136849Sscottl
2148136849Sscottl	return 0;
2149136849Sscottl}
2150136849Sscottl
2151136849Sscottlstatic int
2152136849Sscottlhpt_detach(device_t dev)
2153149871Sscottl{
2154136849Sscottl	return (EBUSY);
2155136849Sscottl}
2156136849Sscottl
2157149871Sscottl
2158136849Sscottl/***************************************************************
2159136849Sscottl * The poll function is used to simulate the interrupt when
2160136849Sscottl * the interrupt subsystem is not functioning.
2161136849Sscottl *
2162136849Sscottl ***************************************************************/
2163136849Sscottlstatic void
2164136849Sscottlhpt_poll(struct cam_sim *sim)
2165136849Sscottl{
2166136849Sscottl	hpt_intr((void *)cam_sim_softc(sim));
2167136849Sscottl}
2168136849Sscottl
2169136849Sscottl/****************************************************************
2170136849Sscottl *	Name:	hpt_intr
2171136849Sscottl *	Description:	Interrupt handler.
2172136849Sscottl ****************************************************************/
2173136849Sscottlstatic void
2174136849Sscottlhpt_intr(void *arg)
2175136849Sscottl{
2176136849Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg;
2177149871Sscottl	intrmask_t oldspl = lock_driver();
2178136849Sscottl
2179136849Sscottl	/* KdPrintI(("----- Entering Isr() -----\n")); */
2180149871Sscottl	if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE)
2181149871Sscottl	{
2182136849Sscottl		_VBUS_INST(&pAdapter->VBus)
2183136849Sscottl		CheckPendingCall(_VBUS_P0);
2184136849Sscottl	}
2185136849Sscottl
2186136849Sscottl	/* KdPrintI(("----- Leaving Isr() -----\n")); */
2187136849Sscottl	unlock_driver(oldspl);
2188136849Sscottl}
2189136849Sscottl
2190136849Sscottl/**********************************************************
2191136849Sscottl * 			Asynchronous Events
2192136849Sscottl *********************************************************/
2193136849Sscottl#if (!defined(UNREFERENCED_PARAMETER))
2194136849Sscottl#define UNREFERENCED_PARAMETER(x) (void)(x)
2195136849Sscottl#endif
2196136849Sscottl
2197136849Sscottlstatic void
2198136849Sscottlhpt_async(void * callback_arg, u_int32_t code, struct cam_path * path,
2199136849Sscottl    void * arg)
2200136849Sscottl{
2201136849Sscottl	/* debug XXXX */
2202136849Sscottl	panic("Here");
2203136849Sscottl	UNREFERENCED_PARAMETER(callback_arg);
2204136849Sscottl	UNREFERENCED_PARAMETER(code);
2205136849Sscottl	UNREFERENCED_PARAMETER(path);
2206136849Sscottl	UNREFERENCED_PARAMETER(arg);
2207136849Sscottl
2208136849Sscottl}
2209136849Sscottl
2210136849Sscottlstatic void
2211136849SscottlFlushAdapter(IAL_ADAPTER_T *pAdapter)
2212136849Sscottl{
2213136849Sscottl	int i;
2214136849Sscottl
2215136849Sscottl	hpt_printk(("flush all devices\n"));
2216136849Sscottl
2217136849Sscottl	/* flush all devices */
2218136849Sscottl	for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) {
2219136849Sscottl		PVDevice pVDev = pAdapter->VBus.pVDevice[i];
2220149871Sscottl		if(pVDev) fFlushVDev(pVDev);
2221136849Sscottl	}
2222136849Sscottl}
2223136849Sscottl
2224136849Sscottlstatic int
2225136849Sscottlhpt_shutdown(device_t dev)
2226136849Sscottl{
2227149871Sscottl		IAL_ADAPTER_T *pAdapter;
2228149871Sscottl
2229149871Sscottl		pAdapter = device_get_softc(dev);
2230149871Sscottl		if (pAdapter == NULL)
2231149871Sscottl			return (EINVAL);
2232136849Sscottl
2233149871Sscottl		EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh);
2234149871Sscottl		FlushAdapter(pAdapter);
2235149871Sscottl		  /* give the flush some time to happen,
2236149871Sscottl		    *otherwise "shutdown -p now" will make file system corrupted */
2237149871Sscottl		DELAY(1000 * 1000 * 5);
2238149871Sscottl		return 0;
2239136849Sscottl}
2240136849Sscottl
2241136849Sscottlvoid
2242136849SscottlCheck_Idle_Call(IAL_ADAPTER_T *pAdapter)
2243136849Sscottl{
2244136849Sscottl	_VBUS_INST(&pAdapter->VBus)
2245136849Sscottl
2246136849Sscottl	if (mWaitingForIdle(_VBUS_P0)) {
2247136849Sscottl		CheckIdleCall(_VBUS_P0);
2248136849Sscottl#ifdef SUPPORT_ARRAY
2249149871Sscottl		{
2250149871Sscottl			int i;
2251136849Sscottl			PVDevice pArray;
2252149871Sscottl			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){
2253149871Sscottl				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
2254149871Sscottl					continue;
2255149871Sscottl				else if (pArray->u.array.rf_auto_rebuild) {
2256149871Sscottl						KdPrint(("auto rebuild.\n"));
2257149871Sscottl						pArray->u.array.rf_auto_rebuild = 0;
2258149871Sscottl						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
2259149871Sscottl				}
2260136849Sscottl			}
2261136849Sscottl		}
2262136849Sscottl#endif
2263136849Sscottl	}
2264136849Sscottl	/* launch the awaiting commands blocked by mWaitingForIdle */
2265149871Sscottl	while(pAdapter->pending_Q!= NULL)
2266149871Sscottl	{
2267136849Sscottl		_VBUS_INST(&pAdapter->VBus)
2268149871Sscottl		union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr;
2269136849Sscottl		hpt_free_ccb(&pAdapter->pending_Q, ccb);
2270136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb);
2271136849Sscottl	}
2272136849Sscottl}
2273136849Sscottl
2274136849Sscottlstatic void
2275136849Sscottlccb_done(union ccb *ccb)
2276136849Sscottl{
2277149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2278149871Sscottl	IAL_ADAPTER_T * pAdapter = pmap->pAdapter;
2279149871Sscottl	KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status));
2280136849Sscottl
2281149871Sscottl	dmamap_put(pmap);
2282136849Sscottl	xpt_done(ccb);
2283136849Sscottl
2284136849Sscottl	pAdapter->outstandingCommands--;
2285136849Sscottl
2286149871Sscottl	if (pAdapter->outstandingCommands == 0)
2287149871Sscottl	{
2288136849Sscottl		if(DPC_Request_Nums == 0)
2289136849Sscottl			Check_Idle_Call(pAdapter);
2290136849Sscottl	}
2291136849Sscottl}
2292136849Sscottl
2293136849Sscottl/****************************************************************
2294136849Sscottl *	Name:	hpt_action
2295136849Sscottl *	Description:	Process a queued command from the CAM layer.
2296136849Sscottl *	Parameters:		sim - Pointer to SIM object
2297136849Sscottl *					ccb - Pointer to SCSI command structure.
2298136849Sscottl ****************************************************************/
2299136849Sscottl
2300136849Sscottlvoid
2301136849Sscottlhpt_action(struct cam_sim *sim, union ccb *ccb)
2302136849Sscottl{
2303136849Sscottl	intrmask_t oldspl;
2304136849Sscottl	IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim);
2305149871Sscottl	PBUS_DMAMAP  pmap;
2306136849Sscottl	_VBUS_INST(&pAdapter->VBus)
2307136849Sscottl
2308149878Sscottl	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n"));
2309149871Sscottl	KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code));
2310136849Sscottl
2311149871Sscottl	switch (ccb->ccb_h.func_code)
2312149871Sscottl	{
2313149871Sscottl		case XPT_SCSI_IO:	/* Execute the requested I/O operation */
2314149871Sscottl		{
2315149871Sscottl			/* ccb->ccb_h.path_id is not our bus id - don't check it */
2316136849Sscottl
2317149871Sscottl			if (ccb->ccb_h.target_lun)	{
2318149871Sscottl				ccb->ccb_h.status = CAM_LUN_INVALID;
2319149871Sscottl				xpt_done(ccb);
2320149871Sscottl				return;
2321149871Sscottl			}
2322149871Sscottl			if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS ||
2323149871Sscottl				pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) {
2324149871Sscottl				ccb->ccb_h.status = CAM_TID_INVALID;
2325149871Sscottl				xpt_done(ccb);
2326149871Sscottl				return;
2327149871Sscottl			}
2328136849Sscottl
2329149871Sscottl			oldspl = lock_driver();
2330149871Sscottl			if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
2331149871Sscottl				Check_Idle_Call(pAdapter);
2332136849Sscottl
2333149871Sscottl			pmap = dmamap_get(pAdapter);
2334149871Sscottl			HPT_ASSERT(pmap);
2335149871Sscottl			ccb->ccb_adapter = pmap;
2336149871Sscottl			memset((void *)pmap->psg, 0,  sizeof(pmap->psg));
2337136849Sscottl
2338149871Sscottl			if (mWaitingForIdle(_VBUS_P0))
2339149871Sscottl				hpt_queue_ccb(&pAdapter->pending_Q, ccb);
2340149871Sscottl			else
2341149871Sscottl				OsSendCommand(_VBUS_P ccb);
2342149871Sscottl			unlock_driver(oldspl);
2343136849Sscottl
2344149871Sscottl			/* KdPrint(("leave scsiio\n")); */
2345149871Sscottl			break;
2346149871Sscottl		}
2347136849Sscottl
2348149871Sscottl		case XPT_RESET_BUS:
2349149871Sscottl			KdPrint(("reset bus\n"));
2350149871Sscottl			oldspl = lock_driver();
2351149871Sscottl			fResetVBus(_VBUS_P0);
2352149871Sscottl			unlock_driver(oldspl);
2353149871Sscottl			xpt_done(ccb);
2354149871Sscottl			break;
2355136849Sscottl
2356149871Sscottl		case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
2357149871Sscottl		case XPT_EN_LUN:		/* Enable LUN as a target */
2358149871Sscottl		case XPT_TARGET_IO:		/* Execute target I/O request */
2359149871Sscottl		case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
2360149871Sscottl		case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
2361149871Sscottl		case XPT_ABORT:			/* Abort the specified CCB */
2362149871Sscottl		case XPT_TERM_IO:		/* Terminate the I/O process */
2363149871Sscottl			/* XXX Implement */
2364149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2365149871Sscottl			xpt_done(ccb);
2366149871Sscottl			break;
2367136849Sscottl
2368149871Sscottl		case XPT_GET_TRAN_SETTINGS:
2369149871Sscottl		case XPT_SET_TRAN_SETTINGS:
2370149871Sscottl			/* XXX Implement */
2371149871Sscottl			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2372149871Sscottl			xpt_done(ccb);
2373149871Sscottl			break;
2374136849Sscottl
2375149871Sscottl		case XPT_CALC_GEOMETRY:
2376227912Smarius#if __FreeBSD_version >= 500000
2377227912Smarius			cam_calc_geometry(&ccb->ccg, 1);
2378227912Smarius#else
2379227912Smarius			{
2380149871Sscottl			struct	  ccb_calc_geometry *ccg;
2381149871Sscottl			u_int32_t size_mb;
2382149871Sscottl			u_int32_t secs_per_cylinder;
2383136849Sscottl
2384149871Sscottl			ccg = &ccb->ccg;
2385149871Sscottl			size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);
2386149871Sscottl
2387149871Sscottl			if (size_mb > 1024 ) {
2388149871Sscottl				ccg->heads = 255;
2389149871Sscottl				ccg->secs_per_track = 63;
2390149871Sscottl			} else {
2391149871Sscottl				ccg->heads = 64;
2392149871Sscottl				ccg->secs_per_track = 32;
2393149871Sscottl			}
2394149871Sscottl			secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2395149871Sscottl			ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2396149871Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
2397227912Smarius			}
2398227912Smarius#endif
2399149871Sscottl			xpt_done(ccb);
2400149871Sscottl			break;
2401136849Sscottl
2402149871Sscottl		case XPT_PATH_INQ:		/* Path routing inquiry */
2403149871Sscottl		{
2404149871Sscottl			struct ccb_pathinq *cpi = &ccb->cpi;
2405136849Sscottl
2406149871Sscottl			cpi->version_num = 1; /* XXX??? */
2407149871Sscottl			cpi->hba_inquiry = PI_SDTR_ABLE;
2408149871Sscottl			cpi->target_sprt = 0;
2409149871Sscottl			/* Not necessary to reset bus */
2410149871Sscottl			cpi->hba_misc = PIM_NOBUSRESET;
2411149871Sscottl			cpi->hba_eng_cnt = 0;
2412136849Sscottl
2413149871Sscottl			cpi->max_target = MAX_VDEVICE_PER_VBUS;
2414149871Sscottl			cpi->max_lun = 0;
2415149871Sscottl			cpi->initiator_id = MAX_VDEVICE_PER_VBUS;
2416136849Sscottl
2417149871Sscottl			cpi->bus_id = cam_sim_bus(sim);
2418149871Sscottl			cpi->base_transfer_speed = 3300;
2419149871Sscottl			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2420149871Sscottl			strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
2421149871Sscottl			strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2422149871Sscottl			cpi->unit_number = cam_sim_unit(sim);
2423209341Smav			cpi->transport = XPORT_SPI;
2424209341Smav			cpi->transport_version = 2;
2425209341Smav			cpi->protocol = PROTO_SCSI;
2426209341Smav			cpi->protocol_version = SCSI_REV_2;
2427149871Sscottl			cpi->ccb_h.status = CAM_REQ_CMP;
2428149871Sscottl			xpt_done(ccb);
2429149871Sscottl			break;
2430149871Sscottl		}
2431136849Sscottl
2432149871Sscottl		default:
2433149871Sscottl			KdPrint(("invalid cmd\n"));
2434149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2435149871Sscottl			xpt_done(ccb);
2436149871Sscottl			break;
2437136849Sscottl	}
2438136849Sscottl	/* KdPrint(("leave hpt_action..............\n")); */
2439136849Sscottl}
2440136849Sscottl
2441136849Sscottl/* shall be called at lock_driver() */
2442136849Sscottlstatic void
2443136849Sscottlhpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb)
2444136849Sscottl{
2445136849Sscottl	if(*ccb_Q == NULL)
2446136849Sscottl		ccb->ccb_h.ccb_ccb_ptr = ccb;
2447136849Sscottl	else {
2448136849Sscottl		ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr;
2449136849Sscottl		(*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb;
2450136849Sscottl	}
2451136849Sscottl
2452136849Sscottl	*ccb_Q = ccb;
2453136849Sscottl}
2454136849Sscottl
2455136849Sscottl/* shall be called at lock_driver() */
2456136849Sscottlstatic void
2457136849Sscottlhpt_free_ccb(union ccb **ccb_Q, union ccb *ccb)
2458136849Sscottl{
2459136849Sscottl	union ccb *TempCCB;
2460136849Sscottl
2461136849Sscottl	TempCCB = *ccb_Q;
2462136849Sscottl
2463149871Sscottl	if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/
2464136849Sscottl		*ccb_Q = NULL;
2465136849Sscottl	else {
2466136849Sscottl		while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb)
2467136849Sscottl			TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr;
2468136849Sscottl
2469136849Sscottl		TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr;
2470136849Sscottl
2471136849Sscottl		if(*ccb_Q == ccb)
2472136849Sscottl			*ccb_Q = TempCCB;
2473136849Sscottl	}
2474136849Sscottl}
2475136849Sscottl
2476136849Sscottl#ifdef SUPPORT_ARRAY
2477136849Sscottl/***************************************************************************
2478136849Sscottl * Function:     hpt_worker_thread
2479136849Sscottl * Description:  Do background rebuilding. Execute in kernel thread context.
2480136849Sscottl * Returns:      None
2481136849Sscottl ***************************************************************************/
2482136849Sscottlstatic void hpt_worker_thread(void)
2483136849Sscottl{
2484136849Sscottl	intrmask_t oldspl;
2485136849Sscottl
2486136849Sscottl	for(;;)	{
2487136849Sscottl		while (DpcQueue_First!=DpcQueue_Last) {
2488136849Sscottl			ST_HPT_DPC p;
2489136849Sscottl			oldspl = lock_driver();
2490136849Sscottl			p = DpcQueue[DpcQueue_First];
2491136849Sscottl			DpcQueue_First++;
2492136849Sscottl			DpcQueue_First %= MAX_DPC;
2493136849Sscottl			DPC_Request_Nums++;
2494136849Sscottl			unlock_driver(oldspl);
2495136849Sscottl			p.dpc(p.pAdapter, p.arg, p.flags);
2496136849Sscottl
2497136849Sscottl			oldspl = lock_driver();
2498136849Sscottl			DPC_Request_Nums--;
2499149871Sscottl			/* since we may have prevented Check_Idle_Call, do it here */
2500136849Sscottl			if (DPC_Request_Nums==0) {
2501136849Sscottl				if (p.pAdapter->outstandingCommands == 0) {
2502136849Sscottl					_VBUS_INST(&p.pAdapter->VBus);
2503136849Sscottl					Check_Idle_Call(p.pAdapter);
2504136849Sscottl					CheckPendingCall(_VBUS_P0);
2505136849Sscottl				}
2506136849Sscottl			}
2507136849Sscottl			unlock_driver(oldspl);
2508136849Sscottl
2509149871Sscottl			/*Schedule out*/
2510149871Sscottl#if (__FreeBSD_version < 500000)
2511149871Sscottl			YIELD_THREAD;
2512149871Sscottl#else
2513190809Sdelphij#if (__FreeBSD_version > 700033)
2514167086Sjhb			pause("sched", 1);
2515190809Sdelphij#else
2516190809Sdelphij			tsleep((caddr_t)hpt_worker_thread, PPAUSE, "sched", 1);
2517149871Sscottl#endif
2518190809Sdelphij#endif
2519149871Sscottl			if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) {
2520149871Sscottl				/* abort rebuilding process. */
2521149871Sscottl				IAL_ADAPTER_T *pAdapter;
2522149871Sscottl				PVDevice      pArray;
2523149871Sscottl				PVBus         _vbus_p;
2524149871Sscottl				int i;
2525149871Sscottl				pAdapter = gIal_Adapter;
2526149871Sscottl
2527149871Sscottl				while(pAdapter != 0){
2528149871Sscottl
2529149871Sscottl					_vbus_p = &pAdapter->VBus;
2530149871Sscottl
2531149871Sscottl					for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
2532149871Sscottl					{
2533149871Sscottl						if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
2534149871Sscottl							continue;
2535149871Sscottl						else if (pArray->u.array.rf_rebuilding ||
2536149871Sscottl								pArray->u.array.rf_verifying ||
2537149871Sscottl								pArray->u.array.rf_initializing)
2538149871Sscottl							{
2539149871Sscottl								pArray->u.array.rf_abort_rebuild = 1;
2540149871Sscottl							}
2541136849Sscottl					}
2542149871Sscottl					pAdapter = pAdapter->next;
2543136849Sscottl				}
2544136849Sscottl			}
2545136849Sscottl		}
2546136849Sscottl
2547149871Sscottl/*Remove this debug option*/
2548149871Sscottl/*
2549136849Sscottl#ifdef DEBUG
2550136849Sscottl		if (SIGISMEMBER(curproc->p_siglist, SIGSTOP))
2551190809Sdelphij#if (__FreeBSD_version > 700033)
2552167086Sjhb			pause("hptrdy", 2*hz);
2553190809Sdelphij#else
2554190809Sdelphij			tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz);
2555136849Sscottl#endif
2556190809Sdelphij#endif
2557149871Sscottl*/
2558190809Sdelphij	#if (__FreeBSD_version >= 800002)
2559172836Sjulian		kproc_suspend_check(curproc);
2560190809Sdelphij	#elif (__FreeBSD_version >= 500043)
2561190809Sdelphij		kthread_suspend_check(curproc);
2562149871Sscottl	#else
2563136849Sscottl		kproc_suspend_loop(curproc);
2564149871Sscottl	#endif
2565190809Sdelphij#if (__FreeBSD_version > 700033)
2566167086Sjhb		pause("hptrdy", 2*hz);  /* wait for something to do */
2567190809Sdelphij#else
2568190809Sdelphij		tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz);  /* wait for something to do */
2569190809Sdelphij#endif
2570136849Sscottl	}
2571136849Sscottl}
2572136849Sscottl
2573136849Sscottlstatic struct proc *hptdaemonproc;
2574136849Sscottlstatic struct kproc_desc hpt_kp = {
2575136849Sscottl	"hpt_wt",
2576136849Sscottl	hpt_worker_thread,
2577136849Sscottl	&hptdaemonproc
2578136849Sscottl};
2579136849Sscottl
2580149871Sscottl/*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/
2581136849Sscottlstatic void
2582136849Sscottllaunch_worker_thread(void)
2583136849Sscottl{
2584136849Sscottl	IAL_ADAPTER_T *pAdapTemp;
2585136849Sscottl
2586136849Sscottl	kproc_start(&hpt_kp);
2587136849Sscottl
2588136849Sscottl	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
2589136849Sscottl
2590136849Sscottl		_VBUS_INST(&pAdapTemp->VBus)
2591136849Sscottl		int i;
2592136849Sscottl		PVDevice pVDev;
2593136849Sscottl
2594136849Sscottl		for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
2595136849Sscottl			if ((pVDev=ArrayTables(i))->u.array.dArStamp==0)
2596136849Sscottl				continue;
2597149871Sscottl			else{
2598149871Sscottl				if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding)
2599149871Sscottl					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev,
2600149871Sscottl					(UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
2601149871Sscottl			}
2602136849Sscottl	}
2603136849Sscottl
2604136849Sscottl	/*
2605149871Sscottl	 * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished.
2606136849Sscottl	 */
2607136849Sscottl#if (__FreeBSD_version < 500043)
2608149871Sscottl	EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST);
2609149871Sscottl#else
2610149871Sscottl	EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, SHUTDOWN_PRI_FIRST);
2611136849Sscottl#endif
2612136849Sscottl}
2613149871Sscottl/*
2614149871Sscottl *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL);
2615149871Sscottl*/
2616136849Sscottl
2617149871Sscottl#endif
2618136849Sscottl
2619136849Sscottl/********************************************************************************/
2620136849Sscottl
2621149871Sscottlint HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical)
2622136849Sscottl{
2623136849Sscottl
2624149871Sscottl	/* since we have provided physical sg, nobody will ask us to build physical sg */
2625149871Sscottl	HPT_ASSERT(0);
2626149871Sscottl	return FALSE;
2627136849Sscottl}
2628136849Sscottl
2629136849Sscottl/*******************************************************************************/
2630136849SscottlULONG HPTLIBAPI
2631136849SscottlGetStamp(void)
2632136849Sscottl{
2633136849Sscottl	/*
2634136849Sscottl	 * the system variable, ticks, can't be used since it hasn't yet been active
2635136849Sscottl	 * when our driver starts (ticks==0, it's a invalid stamp value)
2636136849Sscottl	 */
2637149871Sscottl	ULONG stamp;
2638149871Sscottl	do { stamp = random(); } while (stamp==0);
2639136849Sscottl	return stamp;
2640136849Sscottl}
2641136849Sscottl
2642136849Sscottl
2643136849Sscottlstatic void
2644136849SscottlSetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev)
2645136849Sscottl{
2646136849Sscottl	int i;
2647149871Sscottl	IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice;
2648149871Sscottl
2649136849Sscottl	inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/
2650136849Sscottl	inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5);
2651136849Sscottl#ifndef SERIAL_CMDS
2652136849Sscottl	inquiryData->CommandQueue = 1;
2653136849Sscottl#endif
2654136849Sscottl
2655136849Sscottl	switch(pVDev->VDeviceType) {
2656136849Sscottl	case VD_SINGLE_DISK:
2657136849Sscottl	case VD_ATAPI:
2658136849Sscottl	case VD_REMOVABLE:
2659136849Sscottl		/* Set the removable bit, if applicable. */
2660149871Sscottl		if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80))
2661136849Sscottl			inquiryData->RemovableMedia = 1;
2662136849Sscottl
2663136849Sscottl		/* Fill in vendor identification fields. */
2664149871Sscottl		for (i = 0; i < 20; i += 2) {
2665149871Sscottl			inquiryData->VendorId[i] 	= ((PUCHAR)pIdentify->ModelNumber)[i + 1];
2666149871Sscottl			inquiryData->VendorId[i+1] 	= ((PUCHAR)pIdentify->ModelNumber)[i];
2667136849Sscottl
2668136849Sscottl		}
2669136849Sscottl
2670136849Sscottl		/* Initialize unused portion of product id. */
2671136849Sscottl		for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' ';
2672136849Sscottl
2673136849Sscottl		/* firmware revision */
2674149871Sscottl		for (i = 0; i < 4; i += 2)
2675149871Sscottl		{
2676149871Sscottl			inquiryData->ProductRevisionLevel[i] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i+1];
2677149871Sscottl			inquiryData->ProductRevisionLevel[i+1] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i];
2678136849Sscottl		}
2679136849Sscottl		break;
2680136849Sscottl	default:
2681190809Sdelphij		memcpy(&inquiryData->VendorId, "RR18xx  ", 8);
2682136849Sscottl#ifdef SUPPORT_ARRAY
2683149871Sscottl		switch(pVDev->VDeviceType){
2684136849Sscottl		case VD_RAID_0:
2685149871Sscottl			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
2686149871Sscottl				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
2687149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 1/0 Array  ", 16);
2688136849Sscottl			else
2689149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 0 Array    ", 16);
2690136849Sscottl			break;
2691136849Sscottl		case VD_RAID_1:
2692149871Sscottl			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
2693149871Sscottl				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
2694149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 0/1 Array  ", 16);
2695136849Sscottl			else
2696149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 1 Array    ", 16);
2697136849Sscottl			break;
2698136849Sscottl		case VD_RAID_5:
2699136849Sscottl			memcpy(&inquiryData->ProductId, "RAID 5 Array    ", 16);
2700136849Sscottl			break;
2701136849Sscottl		case VD_JBOD:
2702136849Sscottl			memcpy(&inquiryData->ProductId, "JBOD Array      ", 16);
2703136849Sscottl			break;
2704136849Sscottl		}
2705136849Sscottl#endif
2706136849Sscottl		memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4);
2707136849Sscottl		break;
2708136849Sscottl	}
2709136849Sscottl}
2710136849Sscottl
2711136849Sscottlstatic void
2712136849Sscottlhpt_timeout(void *arg)
2713136849Sscottl{
2714149871Sscottl	_VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus)
2715149871Sscottl	intrmask_t oldspl = lock_driver();
2716136849Sscottl	fResetVBus(_VBUS_P0);
2717136849Sscottl	unlock_driver(oldspl);
2718136849Sscottl}
2719136849Sscottl
2720149871Sscottlstatic void
2721149871Sscottlhpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
2722149871Sscottl{
2723149871Sscottl	PCommand pCmd = (PCommand)arg;
2724149871Sscottl	union ccb *ccb = pCmd->pOrgCommand;
2725149871Sscottl	struct ccb_hdr *ccb_h = &ccb->ccb_h;
2726149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter;
2727149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2728149871Sscottl	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
2729149871Sscottl	FPSCAT_GATH psg = pCmd->pSgTable;
2730149871Sscottl	int idx;
2731149871Sscottl	_VBUS_INST(pVDev->pVBus)
2732149871Sscottl
2733149871Sscottl	HPT_ASSERT(pCmd->cf_physical_sg);
2734149871Sscottl
2735246713Skib	if (error)
2736149871Sscottl		panic("busdma error");
2737149871Sscottl
2738149871Sscottl	HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS);
2739149871Sscottl
2740246713Skib	if (nsegs != 0) {
2741246713Skib		for (idx = 0; idx < nsegs; idx++, psg++) {
2742246713Skib			psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr;
2743246713Skib			psg->wSgSize = segs[idx].ds_len;
2744246713Skib			psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0;
2745246713Skib	/*		KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */
2746246713Skib		}
2747246713Skib		/*	psg[-1].wSgFlag = SG_FLAG_EOT; */
2748246713Skib
2749246713Skib		if (pCmd->cf_data_in) {
2750246713Skib			bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map,
2751246713Skib			    BUS_DMASYNC_PREREAD);
2752246713Skib		}
2753246713Skib		else if (pCmd->cf_data_out) {
2754246713Skib			bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map,
2755246713Skib			    BUS_DMASYNC_PREWRITE);
2756246713Skib		}
2757149871Sscottl	}
2758149871Sscottl
2759149871Sscottl	ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz);
2760149871Sscottl	pVDev->pfnSendCommand(_VBUS_P pCmd);
2761149871Sscottl	CheckPendingCall(_VBUS_P0);
2762149871Sscottl}
2763149871Sscottl
2764149871Sscottl
2765149871Sscottl
2766136849Sscottlstatic void HPTLIBAPI
2767136849SscottlOsSendCommand(_VBUS_ARG union ccb *ccb)
2768136849Sscottl{
2769149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2770149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2771149871Sscottl	struct ccb_hdr *ccb_h = &ccb->ccb_h;
2772149871Sscottl	struct ccb_scsiio *csio = &ccb->csio;
2773149871Sscottl	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
2774136849Sscottl
2775149871Sscottl	KdPrintI(("OsSendCommand: ccb %p  cdb %x-%x-%x\n",
2776136849Sscottl		ccb,
2777136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0],
2778136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4],
2779136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8]
2780136849Sscottl	));
2781136849Sscottl
2782136849Sscottl	pAdapter->outstandingCommands++;
2783136849Sscottl
2784136849Sscottl	if (pVDev == NULL || pVDev->vf_online == 0) {
2785136849Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2786136849Sscottl		ccb_done(ccb);
2787136849Sscottl		goto Command_Complished;
2788136849Sscottl	}
2789136849Sscottl
2790136849Sscottl	switch(ccb->csio.cdb_io.cdb_bytes[0])
2791136849Sscottl	{
2792149871Sscottl		case TEST_UNIT_READY:
2793149871Sscottl		case START_STOP_UNIT:
2794149871Sscottl		case SYNCHRONIZE_CACHE:
2795149871Sscottl			/* FALLTHROUGH */
2796149871Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
2797149871Sscottl			break;
2798136849Sscottl
2799149871Sscottl		case INQUIRY:
2800149871Sscottl			ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len);
2801149871Sscottl			SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev);
2802149871Sscottl			ccb_h->status = CAM_REQ_CMP;
2803149871Sscottl			break;
2804136849Sscottl
2805149871Sscottl		case READ_CAPACITY:
2806149871Sscottl		{
2807190809Sdelphij			UCHAR *rbuf=csio->data_ptr;
2808190809Sdelphij			unsigned int cap;
2809190809Sdelphij
2810190809Sdelphij			if (pVDev->VDeviceCapacity > 0xfffffffful) {
2811190809Sdelphij				cap = 0xfffffffful;
2812190809Sdelphij			} else {
2813190809Sdelphij				cap = pVDev->VDeviceCapacity - 1;
2814190809Sdelphij			}
2815190809Sdelphij
2816190809Sdelphij			rbuf[0] = (UCHAR)(cap>>24);
2817190809Sdelphij			rbuf[1] = (UCHAR)(cap>>16);
2818190809Sdelphij			rbuf[2] = (UCHAR)(cap>>8);
2819190809Sdelphij			rbuf[3] = (UCHAR)cap;
2820149871Sscottl			/* Claim 512 byte blocks (big-endian). */
2821190809Sdelphij			rbuf[4] = 0;
2822190809Sdelphij			rbuf[5] = 0;
2823190809Sdelphij			rbuf[6] = 2;
2824190809Sdelphij			rbuf[7] = 0;
2825190809Sdelphij
2826149871Sscottl			ccb_h->status = CAM_REQ_CMP;
2827149871Sscottl			break;
2828136849Sscottl		}
2829136849Sscottl
2830190809Sdelphij		case 0x9e: /*SERVICE_ACTION_IN*/
2831190809Sdelphij		{
2832190809Sdelphij			UCHAR *rbuf = csio->data_ptr;
2833190809Sdelphij			LBA_T cap = pVDev->VDeviceCapacity - 1;
2834190809Sdelphij
2835190809Sdelphij			rbuf[0] = (UCHAR)(cap>>56);
2836190809Sdelphij			rbuf[1] = (UCHAR)(cap>>48);
2837190809Sdelphij			rbuf[2] = (UCHAR)(cap>>40);
2838190809Sdelphij			rbuf[3] = (UCHAR)(cap>>32);
2839190809Sdelphij			rbuf[4] = (UCHAR)(cap>>24);
2840190809Sdelphij			rbuf[5] = (UCHAR)(cap>>16);
2841190809Sdelphij			rbuf[6] = (UCHAR)(cap>>8);
2842190809Sdelphij			rbuf[7] = (UCHAR)cap;
2843190809Sdelphij			rbuf[8] = 0;
2844190809Sdelphij			rbuf[9] = 0;
2845190809Sdelphij			rbuf[10] = 2;
2846190809Sdelphij			rbuf[11] = 0;
2847190809Sdelphij
2848190809Sdelphij			ccb_h->status = CAM_REQ_CMP;
2849190809Sdelphij			break;
2850190809Sdelphij		}
2851190809Sdelphij
2852136849Sscottl		case READ_6:
2853136849Sscottl		case WRITE_6:
2854136849Sscottl		case READ_10:
2855136849Sscottl		case WRITE_10:
2856190809Sdelphij		case 0x88: /* READ_16 */
2857190809Sdelphij		case 0x8a: /* WRITE_16 */
2858136849Sscottl		case 0x13:
2859136849Sscottl		case 0x2f:
2860149871Sscottl		{
2861149871Sscottl			UCHAR Cdb[16];
2862149871Sscottl			UCHAR CdbLength;
2863149871Sscottl			_VBUS_INST(pVDev->pVBus)
2864149871Sscottl			PCommand pCmd = AllocateCommand(_VBUS_P0);
2865246713Skib			int error;
2866149871Sscottl			HPT_ASSERT(pCmd);
2867136849Sscottl
2868149871Sscottl			CdbLength = csio->cdb_len;
2869149871Sscottl			if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
2870149871Sscottl			{
2871149871Sscottl				if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0)
2872149871Sscottl				{
2873149871Sscottl					bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength);
2874149871Sscottl				}
2875149871Sscottl				else
2876149871Sscottl				{
2877149871Sscottl					KdPrintE(("ERROR!!!\n"));
2878149871Sscottl					ccb->ccb_h.status = CAM_REQ_INVALID;
2879149871Sscottl					break;
2880149871Sscottl				}
2881149871Sscottl			}
2882149871Sscottl			else
2883149871Sscottl			{
2884149871Sscottl				bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength);
2885149871Sscottl			}
2886136849Sscottl
2887149871Sscottl			pCmd->pOrgCommand = ccb;
2888149871Sscottl			pCmd->pVDevice = pVDev;
2889149871Sscottl			pCmd->pfnCompletion = fOsCommandDone;
2890149871Sscottl			pCmd->pfnBuildSgl = fOsBuildSgl;
2891149871Sscottl			pCmd->pSgTable = pmap->psg;
2892136849Sscottl
2893149871Sscottl			switch (Cdb[0])
2894149871Sscottl			{
2895149871Sscottl				case READ_6:
2896149871Sscottl				case WRITE_6:
2897149871Sscottl				case 0x13:
2898149871Sscottl					pCmd->uCmd.Ide.Lba =  ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3];
2899149871Sscottl					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4];
2900149871Sscottl					break;
2901149871Sscottl
2902190809Sdelphij				case 0x88: /* READ_16 */
2903190809Sdelphij				case 0x8a: /* WRITE_16 */
2904190809Sdelphij					pCmd->uCmd.Ide.Lba =
2905190809Sdelphij						(HPT_U64)Cdb[2] << 56 |
2906190809Sdelphij						(HPT_U64)Cdb[3] << 48 |
2907190809Sdelphij						(HPT_U64)Cdb[4] << 40 |
2908190809Sdelphij						(HPT_U64)Cdb[5] << 32 |
2909190809Sdelphij						(HPT_U64)Cdb[6] << 24 |
2910190809Sdelphij						(HPT_U64)Cdb[7] << 16 |
2911190809Sdelphij						(HPT_U64)Cdb[8] << 8 |
2912190809Sdelphij						(HPT_U64)Cdb[9];
2913190809Sdelphij					pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13];
2914190809Sdelphij					break;
2915190809Sdelphij
2916149871Sscottl				default:
2917149871Sscottl					pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24);
2918149871Sscottl					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8);
2919149871Sscottl					break;
2920149871Sscottl			}
2921149871Sscottl
2922149871Sscottl			switch (Cdb[0])
2923149871Sscottl			{
2924149871Sscottl				case READ_6:
2925149871Sscottl				case READ_10:
2926190809Sdelphij				case 0x88: /* READ_16 */
2927149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_READ;
2928149871Sscottl					pCmd->cf_data_in = 1;
2929149871Sscottl					break;
2930149871Sscottl
2931149871Sscottl				case WRITE_6:
2932149871Sscottl				case WRITE_10:
2933190809Sdelphij				case 0x8a: /* WRITE_16 */
2934149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE;
2935149871Sscottl					pCmd->cf_data_out = 1;
2936149871Sscottl					break;
2937149871Sscottl				case 0x13:
2938149871Sscottl				case 0x2f:
2939149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY;
2940149871Sscottl					break;
2941149871Sscottl			}
2942149871Sscottl/*///////////////////////// */
2943246713Skib			pCmd->cf_physical_sg = 1;
2944246713Skib			error = bus_dmamap_load_ccb(pAdapter->io_dma_parent,
2945246713Skib						    pmap->dma_map,
2946246713Skib						    ccb,
2947246713Skib						    hpt_io_dmamap_callback,
2948246713Skib						    pCmd, BUS_DMA_WAITOK
2949246713Skib						    );
2950246713Skib			KdPrint(("bus_dmamap_load return %d\n", error));
2951246713Skib			if (error && error!=EINPROGRESS) {
2952246713Skib				hpt_printk(("bus_dmamap_load error %d\n", error));
2953246713Skib				FreeCommand(_VBUS_P pCmd);
2954246713Skib				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2955246713Skib				dmamap_put(pmap);
2956246713Skib				pAdapter->outstandingCommands--;
2957246713Skib				xpt_done(ccb);
2958149871Sscottl			}
2959149871Sscottl			goto Command_Complished;
2960149871Sscottl		}
2961149871Sscottl
2962149871Sscottl		default:
2963149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2964149871Sscottl			break;
2965136849Sscottl	}
2966136849Sscottl	ccb_done(ccb);
2967136849SscottlCommand_Complished:
2968136849Sscottl	CheckPendingCall(_VBUS_P0);
2969136849Sscottl	return;
2970136849Sscottl}
2971136849Sscottl
2972149871Sscottlstatic void HPTLIBAPI
2973136849SscottlfOsCommandDone(_VBUS_ARG PCommand pCmd)
2974136849Sscottl{
2975149871Sscottl	union ccb *ccb = pCmd->pOrgCommand;
2976149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2977149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2978136849Sscottl
2979149871Sscottl	KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result));
2980136849Sscottl
2981136849Sscottl	untimeout(hpt_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch);
2982136849Sscottl
2983136849Sscottl	switch(pCmd->Result) {
2984136849Sscottl	case RETURN_SUCCESS:
2985136849Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2986136849Sscottl		break;
2987136849Sscottl	case RETURN_BAD_DEVICE:
2988136849Sscottl		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2989136849Sscottl		break;
2990136849Sscottl	case RETURN_DEVICE_BUSY:
2991136849Sscottl		ccb->ccb_h.status = CAM_BUSY;
2992136849Sscottl		break;
2993136849Sscottl	case RETURN_INVALID_REQUEST:
2994136849Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2995136849Sscottl		break;
2996136849Sscottl	case RETURN_SELECTION_TIMEOUT:
2997136849Sscottl		ccb->ccb_h.status = CAM_SEL_TIMEOUT;
2998136849Sscottl		break;
2999136849Sscottl	case RETURN_RETRY:
3000136849Sscottl		ccb->ccb_h.status = CAM_BUSY;
3001136849Sscottl		break;
3002136849Sscottl	default:
3003136849Sscottl		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
3004136849Sscottl		break;
3005136849Sscottl	}
3006136849Sscottl
3007149871Sscottl	if (pCmd->cf_data_in) {
3008149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD);
3009136849Sscottl	}
3010240210Sdelphij	else if (pCmd->cf_data_out) {
3011149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE);
3012149871Sscottl	}
3013149871Sscottl
3014149871Sscottl	bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map);
3015136849Sscottl
3016136849Sscottl	FreeCommand(_VBUS_P pCmd);
3017136849Sscottl	ccb_done(ccb);
3018136849Sscottl}
3019136849Sscottl
3020136849Sscottlint
3021136849Sscottlhpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags)
3022136849Sscottl{
3023136849Sscottl	int p;
3024136849Sscottl
3025136849Sscottl	p = (DpcQueue_Last + 1) % MAX_DPC;
3026136849Sscottl	if (p==DpcQueue_First) {
3027136849Sscottl		KdPrint(("DPC Queue full!\n"));
3028136849Sscottl		return -1;
3029136849Sscottl	}
3030136849Sscottl
3031136849Sscottl	DpcQueue[DpcQueue_Last].dpc = dpc;
3032136849Sscottl	DpcQueue[DpcQueue_Last].pAdapter = pAdapter;
3033136849Sscottl	DpcQueue[DpcQueue_Last].arg = arg;
3034136849Sscottl	DpcQueue[DpcQueue_Last].flags = flags;
3035136849Sscottl	DpcQueue_Last = p;
3036136849Sscottl
3037136849Sscottl	return 0;
3038136849Sscottl}
3039136849Sscottl
3040136849Sscottl#ifdef _RAID5N_
3041136849Sscottl/*
3042149871Sscottl * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices.
3043149871Sscottl * How about the memory for 5081 request/response array and PRD table?
3044136849Sscottl */
3045136849Sscottlvoid
3046136849Sscottl*os_alloc_page(_VBUS_ARG0)
3047136849Sscottl{
3048149871Sscottl	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
3049136849Sscottl}
3050149871Sscottl
3051136849Sscottlvoid
3052136849Sscottl*os_alloc_dma_page(_VBUS_ARG0)
3053136849Sscottl{
3054149871Sscottl	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
3055136849Sscottl}
3056136849Sscottl
3057136849Sscottlvoid
3058149871Sscottlos_free_page(_VBUS_ARG void *p)
3059149871Sscottl{
3060149871Sscottl	contigfree(p, 0x1000, M_DEVBUF);
3061136849Sscottl}
3062136849Sscottl
3063136849Sscottlvoid
3064149871Sscottlos_free_dma_page(_VBUS_ARG void *p)
3065149871Sscottl{
3066149871Sscottl	contigfree(p, 0x1000, M_DEVBUF);
3067136849Sscottl}
3068136849Sscottl
3069136849Sscottlvoid
3070136849SscottlDoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes)
3071136849Sscottl{
3072136849Sscottl	UINT i;
3073149871Sscottl	for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++;
3074136849Sscottl}
3075136849Sscottl
3076136849Sscottlvoid
3077136849SscottlDoXor2(ULONG *p0, ULONG *p2, UINT nBytes)
3078136849Sscottl{
3079136849Sscottl	UINT i;
3080149871Sscottl	for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++;
3081136849Sscottl}
3082136849Sscottl#endif
3083