entry.c revision 172836
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 *
26136849Sscottl * $FreeBSD: head/sys/dev/hptmv/entry.c 172836 2007-10-20 23:23:23Z julian $
27136849Sscottl */
28149871Sscottl
29136849Sscottl#include <sys/param.h>
30136849Sscottl#include <sys/systm.h>
31136849Sscottl#include <sys/kernel.h>
32136849Sscottl#include <sys/bus.h>
33136849Sscottl#include <sys/malloc.h>
34136849Sscottl#include <sys/resource.h>
35136849Sscottl#include <sys/time.h>
36136849Sscottl#include <sys/callout.h>
37136849Sscottl#include <sys/signalvar.h>
38136849Sscottl#include <sys/eventhandler.h>
39136849Sscottl#include <sys/proc.h>
40136849Sscottl#include <sys/kthread.h>
41136849Sscottl
42149871Sscottl#if (__FreeBSD_version >= 500000)
43149871Sscottl#include <sys/mutex.h>
44149871Sscottl#include <sys/module.h>
45149871Sscottl#endif
46149871Sscottl
47149871Sscottl#if (__FreeBSD_version >= 500000)
48136849Sscottl#include <dev/pci/pcireg.h>
49136849Sscottl#include <dev/pci/pcivar.h>
50149871Sscottl#else
51149871Sscottl#include <pci/pcireg.h>
52149871Sscottl#include <pci/pcivar.h>
53149871Sscottl#include <sys/wait.h>
54149871Sscottl#include <sys/sysproto.h>
55149871Sscottl#endif
56136849Sscottl
57149871Sscottl#ifndef __KERNEL__
58149871Sscottl#define __KERNEL__
59149871Sscottl#endif
60149871Sscottl
61136849Sscottl#include <dev/hptmv/global.h>
62136849Sscottl#include <dev/hptmv/hptintf.h>
63136849Sscottl#include <dev/hptmv/osbsd.h>
64143039Sscottl#include <dev/hptmv/access601.h>
65136849Sscottl
66149871Sscottl
67136849Sscottl#ifdef DEBUG
68136849Sscottl#ifdef DEBUG_LEVEL
69136849Sscottlint hpt_dbg_level = DEBUG_LEVEL;
70149871Sscottl#else
71136849Sscottlint hpt_dbg_level = 0;
72136849Sscottl#endif
73136849Sscottl#endif
74136849Sscottl
75136849Sscottl#define MV_ERROR printf
76149871Sscottl
77136849Sscottl/*
78136849Sscottl * CAM SIM entry points
79136849Sscottl */
80149871Sscottlstatic int 	hpt_probe (device_t dev);
81149871Sscottlstatic void launch_worker_thread(void);
82149871Sscottlstatic int 	hpt_attach(device_t dev);
83149871Sscottlstatic int 	hpt_detach(device_t dev);
84149871Sscottlstatic int 	hpt_shutdown(device_t dev);
85149871Sscottlstatic void hpt_poll(struct cam_sim *sim);
86149871Sscottlstatic void hpt_intr(void *arg);
87149871Sscottlstatic void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
88149871Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb);
89149871Sscottl
90149871Sscottlstatic device_method_t driver_methods[] = {
91149871Sscottl	/* Device interface */
92149871Sscottl	DEVMETHOD(device_probe,		hpt_probe),
93149871Sscottl	DEVMETHOD(device_attach,	hpt_attach),
94149871Sscottl	DEVMETHOD(device_detach,	hpt_detach),
95149871Sscottl
96149871Sscottl/*	DEVMETHOD(device_shutdown,	hpt_shutdown), */
97149871Sscottl	{ 0, 0 }
98149871Sscottl};
99149871Sscottl
100149871Sscottlstatic driver_t hpt_pci_driver = {
101149871Sscottl	__str(PROC_DIR_NAME),
102149871Sscottl	driver_methods,
103149871Sscottl	sizeof(IAL_ADAPTER_T)
104149871Sscottl};
105149871Sscottl
106149871Sscottlstatic devclass_t	hpt_devclass;
107149871Sscottl
108149871Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6)
109149871Sscottl__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0);
110149871Sscottl
111149871Sscottl#define ccb_ccb_ptr spriv_ptr0
112149871Sscottl#define ccb_adapter ccb_h.spriv_ptr1
113149871Sscottl
114149871Sscottlstatic void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev);
115149871Sscottlstatic void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb);
116149871Sscottlstatic void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd);
117149871Sscottlstatic void ccb_done(union ccb *ccb);
118149871Sscottlstatic void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb);
119149871Sscottlstatic void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb);
120136849Sscottlstatic void	hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter);
121136849Sscottlstatic void	hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
122136849Sscottlstatic void	handleEdmaError(_VBUS_ARG PCommand pCmd);
123136849Sscottlstatic int	hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
124136849Sscottlstatic int	fResetActiveCommands(PVBus _vbus_p);
125136849Sscottlstatic void	fRegisterVdevice(IAL_ADAPTER_T *pAdapter);
126136849Sscottlstatic int	hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter);
127136849Sscottlstatic void	hptmv_handle_event_disconnect(void *data);
128136849Sscottlstatic void	hptmv_handle_event_connect(void *data);
129136849Sscottlstatic int	start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
130136849Sscottlstatic void	init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel);
131136849Sscottlstatic int	hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel);
132136849Sscottlstatic int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg,
133136849Sscottl    int logical);
134136849Sscottlstatic MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
135136849Sscottl    MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId,
136136849Sscottl    MV_U16 responseFlags, MV_U32 timeStamp,
137136849Sscottl    MV_STORAGE_DEVICE_REGISTERS *registerStruct);
138136849Sscottlstatic MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter,
139136849Sscottl    MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2);
140136849Sscottl
141136849Sscottl#define ccb_ccb_ptr spriv_ptr0
142136849Sscottl#define ccb_adapter ccb_h.spriv_ptr1
143136849Sscottl
144136849SscottlIAL_ADAPTER_T *gIal_Adapter = 0;
145136849SscottlIAL_ADAPTER_T *pCurAdapter = 0;
146149871Sscottlstatic MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM];
147136849Sscottl
148136849Sscottltypedef struct st_HPT_DPC {
149136849Sscottl	IAL_ADAPTER_T *pAdapter;
150136849Sscottl	void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR);
151136849Sscottl	void *arg;
152136849Sscottl	UCHAR flags;
153136849Sscottl} ST_HPT_DPC;
154136849Sscottl
155136849Sscottl#define MAX_DPC 16
156136849SscottlUCHAR DPC_Request_Nums = 0;
157136849Sscottlstatic ST_HPT_DPC DpcQueue[MAX_DPC];
158136849Sscottlstatic int DpcQueue_First=0;
159136849Sscottlstatic int DpcQueue_Last = 0;
160136849Sscottl
161152374Sschweikhchar DRIVER_VERSION[] = "v1.12";
162136849Sscottl
163149871Sscottl#if (__FreeBSD_version >= 500000)
164149871Sscottlstatic struct mtx driver_lock;
165149871Sscottlintrmask_t lock_driver()
166149871Sscottl{
167136849Sscottl
168149871Sscottl	intrmask_t spl = 0;
169165774Sjhb	mtx_lock(&driver_lock);
170149871Sscottl	return spl;
171149871Sscottl}
172149871Sscottlvoid unlock_driver(intrmask_t spl)
173136849Sscottl{
174165774Sjhb	mtx_unlock(&driver_lock);
175149871Sscottl}
176149871Sscottl#else
177149871Sscottlstatic int driver_locked = 0;
178149871Sscottlintrmask_t lock_driver()
179149871Sscottl{
180136849Sscottl	intrmask_t spl = splcam();
181149871Sscottlloop:
182149871Sscottl	while (driver_locked)
183149871Sscottl		tsleep(&driver_locked, PRIBIO, "hptlck", hz);
184149871Sscottl	atomic_add_int(&driver_locked, 1);
185149871Sscottl	if (driver_locked>1) {
186149871Sscottl		atomic_subtract_int(&driver_locked, 1);
187149871Sscottl		goto loop;
188149871Sscottl	}
189136849Sscottl	return spl;
190136849Sscottl}
191136849Sscottl
192149871Sscottlvoid unlock_driver(intrmask_t spl)
193136849Sscottl{
194149871Sscottl	atomic_subtract_int(&driver_locked, 1);
195149871Sscottl	if (driver_locked==0) {
196149871Sscottl		wakeup(&driver_locked);
197149871Sscottl	}
198136849Sscottl	splx(spl);
199136849Sscottl}
200149871Sscottl#endif
201136849Sscottl
202136849Sscottl/*******************************************************************************
203136849Sscottl *	Name:	hptmv_free_channel
204136849Sscottl *
205136849Sscottl *	Description:	free allocated queues for the given channel
206136849Sscottl *
207136849Sscottl *	Parameters:    	pMvSataAdapter - pointer to the RR182x controler this
208136849Sscottl * 					channel connected to.
209136849Sscottl *			channelNum - channel number.
210136849Sscottl *
211136849Sscottl ******************************************************************************/
212136849Sscottlstatic void
213136849Sscottlhptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
214136849Sscottl{
215136849Sscottl	HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM);
216136849Sscottl	pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL;
217149871Sscottl}
218136849Sscottl
219149871Sscottlstatic void failDevice(PVDevice pVDev)
220149871Sscottl{
221149871Sscottl	PVBus _vbus_p = pVDev->pVBus;
222149871Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
223149871Sscottl
224149871Sscottl	pVDev->u.disk.df_on_line = 0;
225149871Sscottl	pVDev->vf_online = 0;
226149871Sscottl	if (pVDev->pfnDeviceFailed)
227149871Sscottl		CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev);
228149871Sscottl
229149871Sscottl	fNotifyGUI(ET_DEVICE_REMOVED, pVDev);
230149871Sscottl
231149871Sscottl#ifndef FOR_DEMO
232149871Sscottl	if (pAdapter->ver_601==2 && !pAdapter->beeping) {
233149871Sscottl		pAdapter->beeping = 1;
234149871Sscottl		BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress);
235149871Sscottl		set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1);
236136849Sscottl	}
237149871Sscottl#endif
238136849Sscottl}
239136849Sscottl
240136849Sscottlint MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel);
241149871Sscottl/*void fDeviceSendCommand(_VBUS_ARG PCommand pCmd); */
242136849Sscottl
243136849Sscottlstatic void
244136849SscottlhandleEdmaError(_VBUS_ARG PCommand pCmd)
245136849Sscottl{
246136849Sscottl	PDevice pDevice = &pCmd->pVDevice->u.disk;
247136849Sscottl	MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter;
248136849Sscottl
249136849Sscottl	if (!pDevice->df_on_line) {
250136849Sscottl		KdPrint(("Device is offline"));
251136849Sscottl		pCmd->Result = RETURN_BAD_DEVICE;
252136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
253136849Sscottl		return;
254136849Sscottl	}
255136849Sscottl
256136849Sscottl	if (pCmd->RetryCount++>5) {
257149871Sscottl		hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber));
258149871Sscottlfailed:
259149871Sscottl		failDevice(pCmd->pVDevice);
260136849Sscottl		pCmd->Result = RETURN_IDE_ERROR;
261136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
262136849Sscottl		return;
263136849Sscottl	}
264149871Sscottl
265149871Sscottl	/* reset the channel and retry the command */
266149871Sscottl	if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber))
267149871Sscottl		goto failed;
268149871Sscottl
269149871Sscottl	fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice));
270149871Sscottl
271149871Sscottl	hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber));
272136849Sscottl	fDeviceSendCommand(_VBUS_P pCmd);
273136849Sscottl}
274136849Sscottl
275136849Sscottl/****************************************************************
276136849Sscottl *	Name:	hptmv_init_channel
277136849Sscottl *
278149871Sscottl *	Description:	allocate request and response queues for the EDMA of the
279149871Sscottl *					given channel and sets other fields.
280149871Sscottl *
281136849Sscottl *	Parameters:
282136849Sscottl *		pAdapter - pointer to the emulated adapter data structure
283136849Sscottl *		channelNum - channel number.
284136849Sscottl *	Return:	0 on success, otherwise on failure
285136849Sscottl ****************************************************************/
286136849Sscottlstatic int
287136849Sscottlhptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
288136849Sscottl{
289136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
290136849Sscottl	dma_addr_t    req_dma_addr;
291136849Sscottl	dma_addr_t    rsp_dma_addr;
292136849Sscottl
293136849Sscottl	if (channelNum >= MV_SATA_CHANNELS_NUM)
294136849Sscottl	{
295136849Sscottl		MV_ERROR("RR182x[%d]: Bad channelNum=%d",
296136849Sscottl				 pAdapter->mvSataAdapter.adapterId, channelNum);
297136849Sscottl		return -1;
298136849Sscottl	}
299136849Sscottl
300149871Sscottl	pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum];
301136849Sscottl	pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel;
302136849Sscottl	pMvSataChannel->channelNumber = channelNum;
303136849Sscottl	pMvSataChannel->lba48Address = MV_FALSE;
304136849Sscottl	pMvSataChannel->maxReadTransfer = MV_FALSE;
305136849Sscottl
306149871Sscottl	pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *)
307149871Sscottl								   (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE));
308149871Sscottl	req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE);
309136849Sscottl
310136849Sscottl
311149871Sscottl	KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr));
312136849Sscottl
313136849Sscottl	/* check the 1K alignment of the request queue*/
314136849Sscottl	if (req_dma_addr & 0x3ff)
315136849Sscottl	{
316149871Sscottl		MV_ERROR("RR182x[%d]: request queue allocated isn't 1 K aligned,"
317149871Sscottl				 " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId,
318149871Sscottl				 (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum);
319136849Sscottl		return -1;
320136849Sscottl	}
321136849Sscottl	pMvSataChannel->requestQueuePciLowAddress = req_dma_addr;
322136849Sscottl	pMvSataChannel->requestQueuePciHiAddress = 0;
323136849Sscottl	KdPrint(("RR182x[%d,%d]: request queue allocated: 0x%p",
324149871Sscottl			  pAdapter->mvSataAdapter.adapterId, channelNum,
325149871Sscottl			  pMvSataChannel->requestQueue));
326149871Sscottl	pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *)
327149871Sscottl									(pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE));
328149871Sscottl	rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE);
329136849Sscottl
330136849Sscottl	/* check the 256 alignment of the response queue*/
331136849Sscottl	if (rsp_dma_addr & 0xff)
332136849Sscottl	{
333149871Sscottl		MV_ERROR("RR182x[%d,%d]: response queue allocated isn't 256 byte "
334149871Sscottl				 "aligned, dma_addr=%llx\n",
335149871Sscottl				 pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr);
336136849Sscottl		return -1;
337136849Sscottl	}
338136849Sscottl	pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr;
339136849Sscottl	pMvSataChannel->responseQueuePciHiAddress = 0;
340136849Sscottl	KdPrint(("RR182x[%d,%d]: response queue allocated: 0x%p",
341149871Sscottl			  pAdapter->mvSataAdapter.adapterId, channelNum,
342149871Sscottl			  pMvSataChannel->responseQueue));
343136849Sscottl
344136849Sscottl	pAdapter->mvChannel[channelNum].online = MV_TRUE;
345136849Sscottl	return 0;
346136849Sscottl}
347136849Sscottl
348136849Sscottl/******************************************************************************
349136849Sscottl *	Name: hptmv_parse_identify_results
350136849Sscottl *
351149871Sscottl *	Description:	this functions parses the identify command results, checks
352149871Sscottl *					that the connected deives can be accesed by RR182x EDMA,
353149871Sscottl *					and updates the channel stucture accordingly.
354149871Sscottl *
355136849Sscottl *	Parameters:     pMvSataChannel, pointer to the channel data structure.
356136849Sscottl *
357136849Sscottl *	Returns:       	=0 ->success, < 0 ->failure.
358136849Sscottl *
359136849Sscottl ******************************************************************************/
360136849Sscottlstatic int
361136849Sscottlhptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel)
362136849Sscottl{
363136849Sscottl	MV_U16  *iden = pMvSataChannel->identifyDevice;
364136849Sscottl
365136849Sscottl	/*LBA addressing*/
366149871Sscottl	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200))
367149871Sscottl	{
368136849Sscottl		KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n"));
369136849Sscottl		return -1;
370149871Sscottl	}
371149871Sscottl	else
372149871Sscottl	{
373136849Sscottl		KdPrint(("%25s - %s\n", "Capabilities", "LBA supported"));
374136849Sscottl	}
375136849Sscottl	/*DMA support*/
376149871Sscottl	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100))
377149871Sscottl	{
378136849Sscottl		KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n"));
379136849Sscottl		return -1;
380149871Sscottl	}
381149871Sscottl	else
382149871Sscottl	{
383136849Sscottl		KdPrint(("%25s - %s\n", "Capabilities", "DMA supported"));
384136849Sscottl	}
385136849Sscottl	/* PIO */
386149871Sscottl	if ((iden[IDEN_VALID] & 2) == 0)
387149871Sscottl	{
388149871Sscottl		KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n"));
389136849Sscottl		return -1;
390136849Sscottl	}
391136849Sscottl	KdPrint(("%25s - 0x%02x\n", "PIO modes supported",
392136849Sscottl			  iden[IDEN_PIO_MODE_SPPORTED] & 0xff));
393136849Sscottl
394136849Sscottl	/*UDMA*/
395149871Sscottl	if ((iden[IDEN_VALID] & 4) == 0)
396149871Sscottl	{
397149871Sscottl		KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n"));
398136849Sscottl		return -1;
399136849Sscottl	}
400136849Sscottl
401136849Sscottl	/* 48 bit address */
402149871Sscottl	if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400))
403149871Sscottl	{
404136849Sscottl		KdPrint(("%25s - %s\n", "LBA48 addressing", "supported"));
405136849Sscottl		pMvSataChannel->lba48Address = MV_TRUE;
406149871Sscottl	}
407149871Sscottl	else
408149871Sscottl	{
409136849Sscottl		KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported"));
410136849Sscottl		pMvSataChannel->lba48Address = MV_FALSE;
411136849Sscottl	}
412136849Sscottl	return 0;
413136849Sscottl}
414136849Sscottl
415136849Sscottlstatic void
416136849Sscottlinit_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel)
417136849Sscottl{
418149871Sscottl	PVDevice pVDev = &pAdapter->VDevices[channel];
419149871Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel];
420149871Sscottl	MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice;
421136849Sscottl
422136849Sscottl	pMvSataChannel->outstandingCommands = 0;
423136849Sscottl
424136849Sscottl	pVDev->u.disk.mv         = pMvSataChannel;
425136849Sscottl	pVDev->u.disk.df_on_line = 1;
426136849Sscottl	pVDev->u.disk.pVBus      = &pAdapter->VBus;
427136849Sscottl	pVDev->pVBus             = &pAdapter->VBus;
428136849Sscottl
429136849Sscottl#ifdef SUPPORT_48BIT_LBA
430136849Sscottl	if (pMvSataChannel->lba48Address == MV_TRUE)
431149871Sscottl		pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1;
432136849Sscottl	else
433136849Sscottl#endif
434136849Sscottl	if(IdentifyData[53] & 1) {
435149871Sscottl	pVDev->u.disk.dDeRealCapacity =
436149871Sscottl	  (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ?
437149871Sscottl		  (IdentifyData[61]<<16 | IdentifyData[60]) :
438149871Sscottl				(IdentifyData[58]<<16 | IdentifyData[57])) - 1;
439136849Sscottl	} else
440136849Sscottl		pVDev->u.disk.dDeRealCapacity =
441149871Sscottl				 (IdentifyData[61]<<16 | IdentifyData[60]) - 1;
442136849Sscottl
443136849Sscottl	pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
444149871Sscottl		pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0;
445136849Sscottl
446136849Sscottl	if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) {
447136849Sscottl		pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
448149871Sscottl			pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8;
449136849Sscottl	}
450136849Sscottl}
451136849Sscottl
452149871Sscottlstatic void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged)
453136849Sscottl{
454136849Sscottl	PVDevice pVDev;
455149871Sscottl	MV_SATA_ADAPTER  *pMvSataAdapter = &pAdapter->mvSataAdapter;
456149871Sscottl	MV_SATA_CHANNEL  *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex];
457149871Sscottl
458149871Sscottl	if (!pMvSataChannel) return;
459136849Sscottl
460149871Sscottl	if (plugged)
461149871Sscottl	{
462136849Sscottl		pVDev = &(pAdapter->VDevices[channelIndex]);
463136849Sscottl		init_vdev_params(pAdapter, channelIndex);
464136849Sscottl
465149871Sscottl		pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI :
466149871Sscottl			pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
467136849Sscottl
468149871Sscottl		pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO;
469136849Sscottl		pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
470136849Sscottl		pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
471136849Sscottl		pVDev->vf_online = 1;
472136849Sscottl
473136849Sscottl#ifdef SUPPORT_ARRAY
474149871Sscottl		if(pVDev->pParent)
475149871Sscottl		{
476136849Sscottl			int iMember;
477149871Sscottl			for(iMember = 0; iMember < 	pVDev->pParent->u.array.bArnMember; iMember++)
478149871Sscottl				if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev)
479136849Sscottl					pVDev->pParent->u.array.pMember[iMember] = NULL;
480136849Sscottl			pVDev->pParent = NULL;
481136849Sscottl		}
482136849Sscottl#endif
483136849Sscottl		fNotifyGUI(ET_DEVICE_PLUGGED,pVDev);
484136849Sscottl		fCheckBootable(pVDev);
485136849Sscottl		RegisterVDevice(pVDev);
486136849Sscottl
487136849Sscottl#ifndef FOR_DEMO
488136849Sscottl		if (pAdapter->beeping) {
489136849Sscottl			pAdapter->beeping = 0;
490136849Sscottl			BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
491136849Sscottl		}
492136849Sscottl#endif
493136849Sscottl
494149871Sscottl	}
495149871Sscottl	else
496149871Sscottl	{
497136849Sscottl		pVDev  = &(pAdapter->VDevices[channelIndex]);
498149871Sscottl		failDevice(pVDev);
499136849Sscottl	}
500136849Sscottl}
501136849Sscottl
502136849Sscottlstatic int
503136849Sscottlstart_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
504136849Sscottl{
505149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
506149871Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum];
507149871Sscottl	MV_CHANNEL		*pChannelInfo = &(pAdapter->mvChannel[channelNum]);
508149871Sscottl	MV_U32          udmaMode,pioMode;
509136849Sscottl
510136849Sscottl	KdPrint(("RR182x [%d]: start channel (%d)", pMvSataAdapter->adapterId,
511149871Sscottl			 channelNum));
512136849Sscottl
513136849Sscottl
514136849Sscottl	/* Software reset channel */
515149871Sscottl	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
516149871Sscottl	{
517136849Sscottl		MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n",
518149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
519136849Sscottl		return -1;
520136849Sscottl	}
521136849Sscottl
522136849Sscottl	/* Hardware reset channel */
523149871Sscottl	if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
524149871Sscottl	{
525149871Sscottl		/* If failed, try again - this is when trying to hardreset a channel */
526149871Sscottl		/* when drive is just spinning up */
527136849Sscottl		StallExec(5000000); /* wait 5 sec before trying again */
528149871Sscottl		if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
529149871Sscottl		{
530149871Sscottl			MV_ERROR("RR182x [%d,%d]: failed to perform Hard reset\n",
531149871Sscottl					 pMvSataAdapter->adapterId, channelNum);
532136849Sscottl			return -1;
533136849Sscottl		}
534136849Sscottl	}
535136849Sscottl
536136849Sscottl	/* identify device*/
537149871Sscottl	if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE)
538149871Sscottl	{
539149871Sscottl		MV_ERROR("RR182x [%d,%d]: failed to perform ATA Identify command\n"
540149871Sscottl				 , pMvSataAdapter->adapterId, channelNum);
541136849Sscottl		return -1;
542136849Sscottl	}
543149871Sscottl	if (hptmv_parse_identify_results(pMvSataChannel))
544149871Sscottl	{
545149871Sscottl		MV_ERROR("RR182x [%d,%d]: Error in parsing ATA Identify message\n"
546149871Sscottl				 , pMvSataAdapter->adapterId, channelNum);
547136849Sscottl		return -1;
548136849Sscottl	}
549136849Sscottl
550136849Sscottl	/* mvStorageDevATASetFeatures */
551136849Sscottl	/* Disable 8 bit PIO in case CFA enabled */
552149871Sscottl	if (pMvSataChannel->identifyDevice[86] & 4)
553149871Sscottl	{
554136849Sscottl		KdPrint(("RR182x [%d]: Disable 8 bit PIO (CFA enabled) \n",
555149871Sscottl				  pMvSataAdapter->adapterId));
556136849Sscottl		if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
557149871Sscottl									   MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0,
558149871Sscottl									   0, 0, 0) == MV_FALSE)
559149871Sscottl		{
560149871Sscottl			MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures"
561149871Sscottl					 " failed\n", pMvSataAdapter->adapterId, channelNum);
562136849Sscottl			return -1;
563136849Sscottl		}
564136849Sscottl	}
565149871Sscottl	/* Write cache */
566136849Sscottl#ifdef ENABLE_WRITE_CACHE
567149871Sscottl	if (pMvSataChannel->identifyDevice[82] & 0x20)
568149871Sscottl	{
569149871Sscottl		if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */
570149871Sscottl		{
571149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
572149871Sscottl										   MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0,
573149871Sscottl										   0, 0, 0) == MV_FALSE)
574149871Sscottl			{
575149871Sscottl				MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
576149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
577136849Sscottl				return -1;
578136849Sscottl			}
579136849Sscottl		}
580136849Sscottl		KdPrint(("RR182x [%d]: channel %d, write cache enabled\n",
581149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
582149871Sscottl	}
583149871Sscottl	else
584149871Sscottl	{
585136849Sscottl		KdPrint(("RR182x [%d]: channel %d, write cache not supported\n",
586149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
587136849Sscottl	}
588149871Sscottl#else /* disable write cache */
589149871Sscottl	{
590149871Sscottl		if (pMvSataChannel->identifyDevice[85] & 0x20)
591149871Sscottl		{
592149871Sscottl			KdPrint(("RR182x [%d]: channel =%d, disable write cache\n",
593149871Sscottl					  pMvSataAdapter->adapterId, channelNum));
594149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
595149871Sscottl										   MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0,
596149871Sscottl										   0, 0, 0) == MV_FALSE)
597149871Sscottl			{
598149871Sscottl				MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
599149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
600149871Sscottl				return -1;
601149871Sscottl			}
602136849Sscottl		}
603149871Sscottl		KdPrint(("RR182x [%d]: channel=%d, write cache disabled\n",
604149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
605136849Sscottl	}
606136849Sscottl#endif
607136849Sscottl
608136849Sscottl	/* Set transfer mode */
609136849Sscottl	KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_SLOW\n",
610149871Sscottl			  pMvSataAdapter->adapterId));
611136849Sscottl	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
612149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
613149871Sscottl								   MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) ==
614149871Sscottl		MV_FALSE)
615149871Sscottl	{
616136849Sscottl		MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
617149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
618136849Sscottl		return -1;
619136849Sscottl	}
620136849Sscottl
621149871Sscottl	if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1)
622149871Sscottl	{
623136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_4;
624149871Sscottl	}
625149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2)
626149871Sscottl	{
627136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_3;
628149871Sscottl	}
629149871Sscottl	else
630149871Sscottl	{
631149871Sscottl		MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n");
632136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_SLOW;
633136849Sscottl	}
634136849Sscottl
635136849Sscottl	KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_4\n",
636149871Sscottl			  pMvSataAdapter->adapterId));
637136849Sscottl	pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode;
638136849Sscottl	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
639149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
640149871Sscottl								   pioMode, 0, 0, 0) == MV_FALSE)
641149871Sscottl	{
642136849Sscottl		MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
643149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
644136849Sscottl		return -1;
645136849Sscottl	}
646136849Sscottl
647136849Sscottl	udmaMode = MV_ATA_TRANSFER_UDMA_0;
648149871Sscottl	if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40)
649149871Sscottl	{
650136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_6;
651149871Sscottl	}
652149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20)
653149871Sscottl	{
654136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_5;
655149871Sscottl	}
656149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10)
657149871Sscottl	{
658136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_4;
659149871Sscottl	}
660149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8)
661149871Sscottl	{
662136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_3;
663149871Sscottl	}
664149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4)
665149871Sscottl	{
666136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_2;
667136849Sscottl	}
668136849Sscottl
669136849Sscottl	KdPrint(("RR182x [%d] Set transfer mode XFER_UDMA_%d\n",
670149871Sscottl			  pMvSataAdapter->adapterId, udmaMode & 0xf));
671136849Sscottl	pChannelInfo->maxUltraDmaModeSupported = udmaMode;
672136849Sscottl
673149871Sscottl	/*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
674149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER, udmaMode,
675149871Sscottl								   0, 0, 0) == MV_FALSE)
676149871Sscottl	{
677136849Sscottl		MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
678149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
679136849Sscottl		return -1;
680149871Sscottl	}*/
681136849Sscottl	if (pChannelInfo->maxUltraDmaModeSupported == 0xFF)
682136849Sscottl		return TRUE;
683149871Sscottl	else
684149871Sscottl		do
685149871Sscottl		{
686149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
687149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
688149871Sscottl								   pChannelInfo->maxUltraDmaModeSupported,
689149871Sscottl								   0, 0, 0) == MV_FALSE)
690149871Sscottl			{
691149871Sscottl				if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0)
692149871Sscottl				{
693149871Sscottl					if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
694149871Sscottl					{
695149871Sscottl						MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress,
696149871Sscottl										  pMvSataChannel->eDmaRegsOffset +
697149871Sscottl										  0x11c, /* command reg */
698149871Sscottl										  MV_ATA_COMMAND_IDLE_IMMEDIATE);
699149871Sscottl						mvMicroSecondsDelay(10000);
700149871Sscottl						mvSataChannelHardReset(pMvSataAdapter, channelNum);
701149871Sscottl						if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
702149871Sscottl							return FALSE;
703149871Sscottl					}
704149871Sscottl					if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
705149871Sscottl						return FALSE;
706149871Sscottl					pChannelInfo->maxUltraDmaModeSupported--;
707149871Sscottl					continue;
708149871Sscottl				}
709149871Sscottl				else   return FALSE;
710149871Sscottl			}
711136849Sscottl			break;
712149871Sscottl		}while (1);
713136849Sscottl
714149871Sscottl	/* Read look ahead */
715136849Sscottl#ifdef ENABLE_READ_AHEAD
716149871Sscottl	if (pMvSataChannel->identifyDevice[82] & 0x40)
717149871Sscottl	{
718149871Sscottl		if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */
719149871Sscottl		{
720149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
721149871Sscottl										   MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0,
722149871Sscottl										   0, 0) == MV_FALSE)
723149871Sscottl			{
724149871Sscottl				MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
725149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
726136849Sscottl				return -1;
727136849Sscottl			}
728136849Sscottl		}
729136849Sscottl		KdPrint(("RR182x [%d]: channel=%d, read look ahead enabled\n",
730149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
731136849Sscottl	}
732149871Sscottl	else
733149871Sscottl	{
734149871Sscottl		KdPrint(("RR182x [%d]: channel %d, Read Look Ahead not supported\n",
735149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
736149871Sscottl	}
737149871Sscottl#else
738149871Sscottl	{
739149871Sscottl		if (pMvSataChannel->identifyDevice[86] & 0x20)
740149871Sscottl		{
741149871Sscottl			KdPrint(("RR182x [%d]:channel %d, disable read look ahead\n",
742149871Sscottl					  pMvSataAdapter->adapterId, channelNum));
743149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
744149871Sscottl										   MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0,
745149871Sscottl										   0, 0) == MV_FALSE)
746149871Sscottl			{
747149871Sscottl				MV_ERROR("RR182x [%d]:channel %d:  ATA Set Features failed\n",
748149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
749149871Sscottl				return -1;
750149871Sscottl			}
751136849Sscottl		}
752149871Sscottl		KdPrint(("RR182x [%d]:channel %d, read look ahead disabled\n",
753149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
754149871Sscottl	}
755136849Sscottl#endif
756136849Sscottl
757136849Sscottl
758149871Sscottl	{
759149871Sscottl		KdPrint(("RR182x [%d]: channel %d config EDMA, Non Queued Mode\n",
760149871Sscottl				  pMvSataAdapter->adapterId,
761149871Sscottl				  channelNum));
762149871Sscottl		if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum,
763149871Sscottl								 MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE)
764149871Sscottl		{
765149871Sscottl			MV_ERROR("RR182x [%d] channel %d Error: mvSataConfigEdmaMode failed\n",
766149871Sscottl					 pMvSataAdapter->adapterId, channelNum);
767136849Sscottl			return -1;
768136849Sscottl		}
769136849Sscottl	}
770136849Sscottl	/* Enable EDMA */
771149871Sscottl	if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE)
772149871Sscottl	{
773136849Sscottl		MV_ERROR("RR182x [%d] Failed to enable DMA, channel=%d\n",
774149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
775136849Sscottl		return -1;
776136849Sscottl	}
777136849Sscottl	MV_ERROR("RR182x [%d,%d]: channel started successfully\n",
778149871Sscottl			 pMvSataAdapter->adapterId, channelNum);
779136849Sscottl
780136849Sscottl#ifndef FOR_DEMO
781136849Sscottl	set_fail_led(pMvSataAdapter, channelNum, 0);
782136849Sscottl#endif
783136849Sscottl	return 0;
784136849Sscottl}
785136849Sscottl
786136849Sscottlstatic void
787136849Sscottlhptmv_handle_event(void * data, int flag)
788136849Sscottl{
789149871Sscottl	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)data;
790149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
791149871Sscottl	MV_U8           channelIndex;
792149871Sscottl
793149871Sscottl/*	mvOsSemTake(&pMvSataAdapter->semaphore); */
794149871Sscottl	for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
795149871Sscottl	{
796149871Sscottl		switch(pAdapter->sataEvents[channelIndex])
797149871Sscottl		{
798149871Sscottl			case SATA_EVENT_CHANNEL_CONNECTED:
799149871Sscottl				/* Handle only connects */
800149871Sscottl				if (flag == 1)
801149871Sscottl					break;
802149871Sscottl				KdPrint(("RR182x [%d,%d]: new device connected\n",
803149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
804149871Sscottl				hptmv_init_channel(pAdapter, channelIndex);
805149871Sscottl				if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE)
806149871Sscottl				{
807149871Sscottl					MV_ERROR("RR182x [%d,%d] Failed to configure\n",
808149871Sscottl							 pMvSataAdapter->adapterId, channelIndex);
809149871Sscottl					hptmv_free_channel(pAdapter, channelIndex);
810149871Sscottl				}
811149871Sscottl				else
812149871Sscottl				{
813149871Sscottl					/*mvSataChannelHardReset(pMvSataAdapter, channel);*/
814149871Sscottl					if (start_channel( pAdapter, channelIndex))
815149871Sscottl					{
816149871Sscottl						MV_ERROR("RR182x [%d,%d]Failed to start channel\n",
817149871Sscottl								 pMvSataAdapter->adapterId, channelIndex);
818149871Sscottl						hptmv_free_channel(pAdapter, channelIndex);
819149871Sscottl					}
820149871Sscottl					else
821149871Sscottl					{
822149871Sscottl						device_change(pAdapter, channelIndex, TRUE);
823149871Sscottl					}
824149871Sscottl				}
825149871Sscottl				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
826149871Sscottl			   break;
827136849Sscottl
828149871Sscottl			case SATA_EVENT_CHANNEL_DISCONNECTED:
829149871Sscottl				/* Handle only disconnects */
830149871Sscottl				if (flag == 0)
831149871Sscottl					break;
832149871Sscottl				KdPrint(("RR182x [%d,%d]: device disconnected\n",
833149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
834149871Sscottl					/* Flush pending commands */
835149871Sscottl				if(pMvSataAdapter->sataChannel[channelIndex])
836149871Sscottl				{
837149871Sscottl					_VBUS_INST(&pAdapter->VBus)
838149871Sscottl					mvSataFlushDmaQueue (pMvSataAdapter, channelIndex,
839149871Sscottl										 MV_FLUSH_TYPE_CALLBACK);
840149871Sscottl					CheckPendingCall(_VBUS_P0);
841149871Sscottl					mvSataRemoveChannel(pMvSataAdapter,channelIndex);
842149871Sscottl					hptmv_free_channel(pAdapter, channelIndex);
843149871Sscottl					pMvSataAdapter->sataChannel[channelIndex] = NULL;
844149871Sscottl					KdPrint(("RR182x [%d,%d]: channel removed\n",
845149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
846149871Sscottl					if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
847149871Sscottl						Check_Idle_Call(pAdapter);
848136849Sscottl				}
849149871Sscottl				else
850149871Sscottl				{
851149871Sscottl					KdPrint(("RR182x [%d,%d]: channel already removed!!\n",
852149871Sscottl							 pMvSataAdapter->adapterId, channelIndex));
853149871Sscottl				}
854149871Sscottl				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
855136849Sscottl				break;
856136849Sscottl
857149871Sscottl			case SATA_EVENT_NO_CHANGE:
858149871Sscottl				break;
859136849Sscottl
860149871Sscottl			default:
861149871Sscottl				break;
862136849Sscottl		}
863136849Sscottl	}
864149871Sscottl/*	mvOsSemRelease(&pMvSataAdapter->semaphore); */
865136849Sscottl}
866136849Sscottl
867136849Sscottl#define EVENT_CONNECT					1
868136849Sscottl#define EVENT_DISCONNECT				0
869136849Sscottl
870136849Sscottlstatic void
871136849Sscottlhptmv_handle_event_connect(void *data)
872136849Sscottl{
873149871Sscottl  hptmv_handle_event (data, 0);
874136849Sscottl}
875136849Sscottl
876136849Sscottlstatic void
877136849Sscottlhptmv_handle_event_disconnect(void *data)
878136849Sscottl{
879149871Sscottl  hptmv_handle_event (data, 1);
880136849Sscottl}
881136849Sscottl
882136849Sscottlstatic MV_BOOLEAN
883136849Sscottlhptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
884149871Sscottl								   MV_U32 param1, MV_U32 param2)
885136849Sscottl{
886149871Sscottl	IAL_ADAPTER_T   *pAdapter = pMvSataAdapter->IALData;
887136849Sscottl
888149871Sscottl	switch (eventType)
889136849Sscottl	{
890149871Sscottl		case MV_EVENT_TYPE_SATA_CABLE:
891149871Sscottl			{
892149871Sscottl				MV_U8   channel = param2;
893136849Sscottl
894149871Sscottl				if (param1 == EVENT_CONNECT)
895149871Sscottl				{
896149871Sscottl					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED;
897149871Sscottl					KdPrint(("RR182x [%d,%d]: device connected event received\n",
898149871Sscottl							 pMvSataAdapter->adapterId, channel));
899149871Sscottl					/* Delete previous timers (if multiple drives connected in the same time */
900149871Sscottl					pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz);
901149871Sscottl				}
902149871Sscottl				else if (param1 == EVENT_DISCONNECT)
903149871Sscottl				{
904149871Sscottl					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED;
905149871Sscottl					KdPrint(("RR182x [%d,%d]: device disconnected event received \n",
906149871Sscottl							 pMvSataAdapter->adapterId, channel));
907149871Sscottl					device_change(pAdapter, channel, FALSE);
908149871Sscottl					/* Delete previous timers (if multiple drives disconnected in the same time */
909149871Sscottl					/*pAdapter->event_timer_disconnect = timeout(hptmv_handle_event_disconnect, pAdapter, 10*hz); */
910149871Sscottl					/*It is not necessary to wait, handle it directly*/
911149871Sscottl					hptmv_handle_event_disconnect(pAdapter);
912149871Sscottl				}
913149871Sscottl				else
914149871Sscottl				{
915136849Sscottl
916149871Sscottl					MV_ERROR("RR182x: illigal value for param1(%d) at "
917149871Sscottl							 "connect/disconect event, host=%d\n", param1,
918149871Sscottl							 pMvSataAdapter->adapterId );
919149871Sscottl
920149871Sscottl				}
921149871Sscottl			}
922149871Sscottl			break;
923149871Sscottl		case MV_EVENT_TYPE_ADAPTER_ERROR:
924149871Sscottl			KdPrint(("RR182x: DEVICE error event received, pci cause "
925149871Sscottl					  "reg=%x,  don't how to handle this\n", param1));
926149871Sscottl			return MV_TRUE;
927149871Sscottl		default:
928149871Sscottl			MV_ERROR("RR182x[%d]: unknown event type (%d)\n",
929149871Sscottl					 pMvSataAdapter->adapterId, eventType);
930149871Sscottl			return MV_FALSE;
931136849Sscottl	}
932136849Sscottl	return MV_TRUE;
933136849Sscottl}
934136849Sscottl
935149871Sscottlstatic int
936136849Sscottlhptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
937136849Sscottl{
938149871Sscottl	pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE,
939149871Sscottl			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
940149871Sscottl	if (pAdapter->requestsArrayBaseAddr == NULL)
941149871Sscottl	{
942149871Sscottl		MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA request"
943149871Sscottl				 " queues\n", pAdapter->mvSataAdapter.adapterId);
944136849Sscottl		return -1;
945136849Sscottl	}
946149871Sscottl	pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr);
947149871Sscottl	pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr;
948136849Sscottl	pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
949149871Sscottl	pAdapter->requestsArrayBaseAlignedAddr  = (MV_U8 *)
950149871Sscottl		(((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1));
951149871Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr;
952136849Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
953149871Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1);
954136849Sscottl
955149871Sscottl	if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) !=
956149871Sscottl		(pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr))
957149871Sscottl	{
958136849Sscottl		MV_ERROR("RR182x[%d]: Error in Request Quueues Alignment\n",
959149871Sscottl				 pAdapter->mvSataAdapter.adapterId);
960149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
961136849Sscottl		return -1;
962136849Sscottl	}
963136849Sscottl	/* response queues */
964149871Sscottl	pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE,
965149871Sscottl			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
966149871Sscottl	if (pAdapter->responsesArrayBaseAddr == NULL)
967149871Sscottl	{
968149871Sscottl		MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA response"
969149871Sscottl				 " queues\n", pAdapter->mvSataAdapter.adapterId);
970149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
971136849Sscottl		return -1;
972136849Sscottl	}
973149871Sscottl	pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr);
974149871Sscottl	pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr;
975136849Sscottl	pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
976149871Sscottl	pAdapter->responsesArrayBaseAlignedAddr  = (MV_U8 *)
977149871Sscottl		(((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1));
978149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr;
979149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
980149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1);
981136849Sscottl
982149871Sscottl	if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) !=
983149871Sscottl		(pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr))
984149871Sscottl	{
985136849Sscottl		MV_ERROR("RR182x[%d]: Error in Response Quueues Alignment\n",
986149871Sscottl				 pAdapter->mvSataAdapter.adapterId);
987149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
988149871Sscottl		contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
989136849Sscottl		return -1;
990136849Sscottl	}
991136849Sscottl	return 0;
992136849Sscottl}
993136849Sscottl
994136849Sscottlstatic void
995136849Sscottlhptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter)
996136849Sscottl{
997149871Sscottl	contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
998149871Sscottl	contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
999136849Sscottl}
1000136849Sscottl
1001136849Sscottlstatic PVOID
1002136849SscottlAllocatePRDTable(IAL_ADAPTER_T *pAdapter)
1003136849Sscottl{
1004136849Sscottl	PVOID ret;
1005136849Sscottl	if (pAdapter->pFreePRDLink) {
1006149871Sscottl		KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink));
1007136849Sscottl		ret = pAdapter->pFreePRDLink;
1008136849Sscottl		pAdapter->pFreePRDLink = *(void**)ret;
1009136849Sscottl		return ret;
1010136849Sscottl	}
1011136849Sscottl	return NULL;
1012136849Sscottl}
1013136849Sscottl
1014136849Sscottlstatic void
1015136849SscottlFreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable)
1016136849Sscottl{
1017136849Sscottl	*(void**)PRDTable = pAdapter->pFreePRDLink;
1018136849Sscottl	pAdapter->pFreePRDLink = PRDTable;
1019136849Sscottl}
1020136849Sscottl
1021136849Sscottlextern PVDevice fGetFirstChild(PVDevice pLogical);
1022136849Sscottlextern void fResetBootMark(PVDevice pLogical);
1023136849Sscottlstatic void
1024136849SscottlfRegisterVdevice(IAL_ADAPTER_T *pAdapter)
1025136849Sscottl{
1026136849Sscottl	PVDevice pPhysical, pLogical;
1027136849Sscottl	PVBus  pVBus;
1028136849Sscottl	int i,j;
1029136849Sscottl
1030149871Sscottl	for(i=0;i<MV_SATA_CHANNELS_NUM;i++) {
1031136849Sscottl		pPhysical = &(pAdapter->VDevices[i]);
1032136849Sscottl		pLogical = pPhysical;
1033136849Sscottl		while (pLogical->pParent) pLogical = pLogical->pParent;
1034136849Sscottl		if (pLogical->vf_online==0) {
1035136849Sscottl			pPhysical->vf_bootmark = pLogical->vf_bootmark = 0;
1036136849Sscottl			continue;
1037136849Sscottl		}
1038149871Sscottl		if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical))
1039136849Sscottl			continue;
1040136849Sscottl
1041136849Sscottl		pVBus = &pAdapter->VBus;
1042149871Sscottl		if(pVBus)
1043149871Sscottl		{
1044136849Sscottl			j=0;
1045149871Sscottl			while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++;
1046149871Sscottl			if(j<MAX_VDEVICE_PER_VBUS){
1047136849Sscottl				pVBus->pVDevice[j] = pLogical;
1048136849Sscottl				pLogical->pVBus = pVBus;
1049136849Sscottl
1050136849Sscottl				if (j>0 && pLogical->vf_bootmark) {
1051136849Sscottl					if (pVBus->pVDevice[0]->vf_bootmark) {
1052136849Sscottl						fResetBootMark(pLogical);
1053149871Sscottl					}
1054149871Sscottl					else {
1055149871Sscottl						do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j);
1056136849Sscottl						pVBus->pVDevice[0] = pLogical;
1057136849Sscottl					}
1058136849Sscottl				}
1059136849Sscottl			}
1060136849Sscottl		}
1061136849Sscottl	}
1062136849Sscottl}
1063136849Sscottl
1064136849SscottlPVDevice
1065136849SscottlGetSpareDisk(_VBUS_ARG PVDevice pArray)
1066136849Sscottl{
1067149871Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt;
1068149871Sscottl	ULONG capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1);
1069136849Sscottl	ULONG thiscap, maxcap = MAX_LBA_T;
1070136849Sscottl	PVDevice pVDevice, pFind = NULL;
1071136849Sscottl	int i;
1072136849Sscottl
1073149871Sscottl	for(i=0;i<MV_SATA_CHANNELS_NUM;i++)
1074149871Sscottl	{
1075136849Sscottl		pVDevice = &pAdapter->VDevices[i];
1076136849Sscottl		if(!pVDevice)
1077136849Sscottl			continue;
1078149871Sscottl		thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity;
1079136849Sscottl		/* find the smallest usable spare disk */
1080136849Sscottl		if (pVDevice->VDeviceType==VD_SPARE &&
1081149871Sscottl			pVDevice->u.disk.df_on_line &&
1082149871Sscottl			thiscap < maxcap &&
1083149871Sscottl			thiscap >= capacity)
1084149871Sscottl		{
1085149871Sscottl				maxcap = pVDevice->VDeviceCapacity;
1086149871Sscottl				pFind = pVDevice;
1087136849Sscottl		}
1088136849Sscottl	}
1089136849Sscottl	return pFind;
1090136849Sscottl}
1091136849Sscottl
1092136849Sscottl/******************************************************************
1093136849Sscottl * IO ATA Command
1094136849Sscottl *******************************************************************/
1095136849Sscottlint HPTLIBAPI
1096136849SscottlfDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer)
1097136849Sscottl{
1098136849Sscottl	return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer);
1099136849Sscottl}
1100136849Sscottl
1101136849Sscottlvoid HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode)
1102136849Sscottl{
1103149871Sscottl	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
1104149871Sscottl	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
1105149871Sscottl	MV_U8 channelIndex = pSataChannel->channelNumber;
1106136849Sscottl	UCHAR mvMode;
1107136849Sscottl	/* 508x don't use MW-DMA? */
1108136849Sscottl	if (NewMode>4 && NewMode<8) NewMode = 4;
1109136849Sscottl	pDev->bDeModeSetting = NewMode;
1110136849Sscottl	if (NewMode<=4)
1111136849Sscottl		mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode;
1112136849Sscottl	else
1113136849Sscottl		mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8);
1114136849Sscottl
1115136849Sscottl	/*To fix 88i8030 bug*/
1116136849Sscottl	if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4)
1117136849Sscottl		mvMode = MV_ATA_TRANSFER_UDMA_0;
1118136849Sscottl
1119136849Sscottl	mvSataDisableChannelDma(pSataAdapter, channelIndex);
1120136849Sscottl	/* Flush pending commands */
1121136849Sscottl	mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE);
1122136849Sscottl
1123136849Sscottl	if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1124149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
1125149871Sscottl								   mvMode, 0, 0, 0) == MV_FALSE)
1126149871Sscottl	{
1127136849Sscottl		KdPrint(("channel %d: Set Features failed\n", channelIndex));
1128136849Sscottl	}
1129136849Sscottl	/* Enable EDMA */
1130136849Sscottl	if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE)
1131136849Sscottl		KdPrint(("Failed to enable DMA, channel=%d", channelIndex));
1132136849Sscottl}
1133136849Sscottl
1134136849Sscottl#ifdef SUPPORT_ARRAY
1135136849Sscottl#define IdeRegisterVDevice  fCheckArray
1136149871Sscottl#else
1137136849Sscottlvoid
1138136849SscottlIdeRegisterVDevice(PDevice pDev)
1139136849Sscottl{
1140136849Sscottl	PVDevice pVDev = Map2pVDevice(pDev);
1141136849Sscottl
1142136849Sscottl	pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI :
1143149871Sscottl						 pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
1144136849Sscottl	pVDev->vf_online = 1;
1145136849Sscottl	pVDev->VDeviceCapacity = pDev->dDeRealCapacity;
1146136849Sscottl	pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
1147136849Sscottl	pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
1148136849Sscottl}
1149136849Sscottl#endif
1150136849Sscottl
1151149871Sscottlstatic __inline PBUS_DMAMAP
1152149871Sscottldmamap_get(struct IALAdapter * pAdapter)
1153149871Sscottl{
1154149871Sscottl	PBUS_DMAMAP	p = pAdapter->pbus_dmamap_list;
1155149871Sscottl	if (p)
1156149871Sscottl		pAdapter->pbus_dmamap_list = p-> next;
1157149871Sscottl	return p;
1158149871Sscottl}
1159149871Sscottl
1160149871Sscottlstatic __inline void
1161149871Sscottldmamap_put(PBUS_DMAMAP p)
1162149871Sscottl{
1163149871Sscottl	p->next = p->pAdapter->pbus_dmamap_list;
1164149871Sscottl	p->pAdapter->pbus_dmamap_list = p;
1165149871Sscottl}
1166149871Sscottl
1167149871Sscottl/*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/
1168149871Sscottl#if __FreeBSD_version >= 500000
1169149871Sscottlstatic void hpt_init(void *dummy)
1170149871Sscottl{
1171165774Sjhb	mtx_init(&driver_lock, "hptlock", NULL, MTX_DEF);
1172149871Sscottl}
1173149871SscottlSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL);
1174149871Sscottl#endif
1175149871Sscottl
1176136849Sscottlstatic int num_adapters = 0;
1177136849Sscottlstatic int
1178136849Sscottlinit_adapter(IAL_ADAPTER_T *pAdapter)
1179136849Sscottl{
1180136849Sscottl	PVBus _vbus_p = &pAdapter->VBus;
1181136849Sscottl	MV_SATA_ADAPTER *pMvSataAdapter;
1182149871Sscottl	int i, channel, rid;
1183136849Sscottl
1184136849Sscottl	PVDevice pVDev;
1185136849Sscottl
1186136849Sscottl	pAdapter->next = 0;
1187136849Sscottl
1188149871Sscottl	if(gIal_Adapter == 0){
1189136849Sscottl		gIal_Adapter = pAdapter;
1190136849Sscottl		pCurAdapter = gIal_Adapter;
1191149871Sscottl	}
1192149871Sscottl	else {
1193136849Sscottl		pCurAdapter->next = pAdapter;
1194136849Sscottl		pCurAdapter = pAdapter;
1195136849Sscottl	}
1196136849Sscottl
1197136849Sscottl	pAdapter->outstandingCommands = 0;
1198136849Sscottl
1199136849Sscottl	pMvSataAdapter = &(pAdapter->mvSataAdapter);
1200136849Sscottl	_vbus_p->OsExt = (void *)pAdapter;
1201136849Sscottl	pMvSataAdapter->IALData = pAdapter;
1202136849Sscottl
1203149871Sscottl	if (bus_dma_tag_create(NULL,/* parent */
1204149871Sscottl			4,	/* alignment */
1205149871Sscottl			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1206149871Sscottl			BUS_SPACE_MAXADDR,	/* lowaddr */
1207149871Sscottl			BUS_SPACE_MAXADDR,	/* highaddr */
1208149871Sscottl			NULL, NULL, 		/* filter, filterarg */
1209149871Sscottl			PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */
1210149871Sscottl			MAX_SG_DESCRIPTORS, /* nsegments */
1211149871Sscottl			0x10000,	/* maxsegsize */
1212149871Sscottl			BUS_DMA_WAITOK, 	/* flags */
1213149871Sscottl#if __FreeBSD_version>502000
1214149871Sscottl			busdma_lock_mutex,	/* lockfunc */
1215149871Sscottl			&driver_lock,		/* lockfuncarg */
1216149871Sscottl#endif
1217149871Sscottl			&pAdapter->io_dma_parent /* tag */))
1218149871Sscottl		{
1219149871Sscottl			return ENXIO;;
1220136849Sscottl	}
1221136849Sscottl
1222136849Sscottl
1223149871Sscottl	if (hptmv_allocate_edma_queues(pAdapter))
1224149871Sscottl	{
1225136849Sscottl		MV_ERROR("RR182x: Failed to allocate memory for EDMA queues\n");
1226149871Sscottl		return ENOMEM;
1227136849Sscottl	}
1228136849Sscottl
1229136849Sscottl	/* also map EPROM address */
1230136849Sscottl	rid = 0x10;
1231149871Sscottl	if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid,
1232149871Sscottl			0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE))
1233149871Sscottl		||
1234149871Sscottl		!(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res)))
1235149871Sscottl	{
1236136849Sscottl		MV_ERROR("RR182x: Failed to remap memory space\n");
1237149871Sscottl		hptmv_free_edma_queues(pAdapter);
1238149871Sscottl		return ENXIO;
1239136849Sscottl	}
1240149871Sscottl	else
1241149871Sscottl	{
1242149871Sscottl		KdPrint(("RR182x: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress));
1243149871Sscottl	}
1244136849Sscottl
1245136849Sscottl	pMvSataAdapter->adapterId = num_adapters++;
1246136849Sscottl	/* get the revision ID */
1247149871Sscottl	pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1);
1248136849Sscottl	pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev);
1249149871Sscottl
1250136849Sscottl	/* init RR182x */
1251136849Sscottl	pMvSataAdapter->intCoalThre[0]= 1;
1252136849Sscottl	pMvSataAdapter->intCoalThre[1]= 1;
1253136849Sscottl	pMvSataAdapter->intTimeThre[0] = 1;
1254136849Sscottl	pMvSataAdapter->intTimeThre[1] = 1;
1255136849Sscottl	pMvSataAdapter->pciCommand = 0x0107E371;
1256136849Sscottl	pMvSataAdapter->pciSerrMask = 0xd77fe6ul;
1257136849Sscottl	pMvSataAdapter->pciInterruptMask = 0xd77fe6ul;
1258136849Sscottl	pMvSataAdapter->mvSataEventNotify = hptmv_event_notify;
1259136849Sscottl
1260149871Sscottl	if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
1261149871Sscottl	{
1262136849Sscottl		MV_ERROR("RR182x[%d]: core failed to initialize the adapter\n",
1263149871Sscottl				 pMvSataAdapter->adapterId);
1264149871Sscottlunregister:
1265149871Sscottl		bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res);
1266149871Sscottl		hptmv_free_edma_queues(pAdapter);
1267149871Sscottl		return ENXIO;
1268136849Sscottl	}
1269136849Sscottl	pAdapter->ver_601 = pMvSataAdapter->pcbVersion;
1270136849Sscottl
1271136849Sscottl#ifndef FOR_DEMO
1272136849Sscottl	set_fail_leds(pMvSataAdapter, 0);
1273136849Sscottl#endif
1274136849Sscottl
1275136849Sscottl	/* setup command blocks */
1276136849Sscottl	KdPrint(("Allocate command blocks\n"));
1277136849Sscottl	_vbus_(pFreeCommands) = 0;
1278149871Sscottl	pAdapter->pCommandBlocks =
1279149871Sscottl		malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT);
1280149871Sscottl	KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks));
1281149871Sscottl	if (!pAdapter->pCommandBlocks) {
1282149871Sscottl		MV_ERROR("insufficient memory\n");
1283149871Sscottl		goto unregister;
1284149871Sscottl	}
1285136849Sscottl
1286149871Sscottl	for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) {
1287149871Sscottl		FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i]));
1288149871Sscottl	}
1289136849Sscottl
1290149871Sscottl	/*Set up the bus_dmamap*/
1291149871Sscottl	pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT);
1292149871Sscottl	if(!pAdapter->pbus_dmamap) {
1293149871Sscottl		MV_ERROR("insufficient memory\n");
1294149871Sscottl		free(pAdapter->pCommandBlocks, M_DEVBUF);
1295149871Sscottl		goto unregister;
1296136849Sscottl	}
1297136849Sscottl
1298149871Sscottl	memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM);
1299149871Sscottl	pAdapter->pbus_dmamap_list = 0;
1300149871Sscottl	for (i=0; i < MAX_QUEUE_COMM; i++) {
1301149871Sscottl		PBUS_DMAMAP  pmap = &(pAdapter->pbus_dmamap[i]);
1302149871Sscottl		pmap->pAdapter = pAdapter;
1303149871Sscottl		dmamap_put(pmap);
1304149871Sscottl
1305149871Sscottl		if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) {
1306149871Sscottl			MV_ERROR("Can not allocate dma map\n");
1307149871Sscottl			free(pAdapter->pCommandBlocks, M_DEVBUF);
1308149871Sscottl			free(pAdapter->pbus_dmamap, M_DEVBUF);
1309149871Sscottl			goto unregister;
1310149871Sscottl		}
1311149871Sscottl	}
1312136849Sscottl	/* setup PRD Tables */
1313136849Sscottl	KdPrint(("Allocate PRD Tables\n"));
1314136849Sscottl	pAdapter->pFreePRDLink = 0;
1315149871Sscottl
1316149871Sscottl	pAdapter->prdTableAddr = (PUCHAR)contigmalloc(
1317149871Sscottl		(PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
1318149871Sscottl
1319136862Sscottl	KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr));
1320136849Sscottl	if (!pAdapter->prdTableAddr) {
1321136849Sscottl		MV_ERROR("insufficient PRD Tables\n");
1322136849Sscottl		goto unregister;
1323136849Sscottl	}
1324149871Sscottl	pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL);
1325149871Sscottl	{
1326149871Sscottl		PUCHAR PRDTable = pAdapter->prdTableAlignedAddr;
1327149871Sscottl		for (i=0; i<PRD_TABLES_FOR_VBUS; i++)
1328149871Sscottl		{
1329149871Sscottl/*			KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */
1330149871Sscottl			FreePRDTable(pAdapter, PRDTable);
1331149871Sscottl			PRDTable += PRD_ENTRIES_SIZE;
1332149871Sscottl		}
1333136849Sscottl	}
1334136849Sscottl
1335136849Sscottl	/* enable the adapter interrupts */
1336136849Sscottl
1337136849Sscottl	/* configure and start the connected channels*/
1338149871Sscottl	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
1339149871Sscottl	{
1340136849Sscottl		pAdapter->mvChannel[channel].online = MV_FALSE;
1341136849Sscottl		if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel)
1342149871Sscottl			== MV_TRUE)
1343149871Sscottl		{
1344149871Sscottl			KdPrint(("RR182x[%d]: channel %d is connected\n",
1345149871Sscottl					  pMvSataAdapter->adapterId, channel));
1346136849Sscottl
1347149871Sscottl			if (hptmv_init_channel(pAdapter, channel) == 0)
1348149871Sscottl			{
1349149871Sscottl				if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE)
1350149871Sscottl				{
1351149871Sscottl					MV_ERROR("RR182x[%d]: Failed to configure channel"
1352149871Sscottl							 " %d\n",pMvSataAdapter->adapterId, channel);
1353149871Sscottl					hptmv_free_channel(pAdapter, channel);
1354149871Sscottl				}
1355149871Sscottl				else
1356149871Sscottl				{
1357149871Sscottl					if (start_channel(pAdapter, channel))
1358149871Sscottl					{
1359149871Sscottl						MV_ERROR("RR182x[%d]: Failed to start channel,"
1360149871Sscottl								 " channel=%d\n",pMvSataAdapter->adapterId,
1361149871Sscottl								 channel);
1362149871Sscottl						hptmv_free_channel(pAdapter, channel);
1363149871Sscottl					}
1364149871Sscottl					pAdapter->mvChannel[channel].online = MV_TRUE;
1365149871Sscottl					/*  mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter,
1366149871Sscottl													   channel,
1367149871Sscottl													   MV_TRUE);*/
1368149871Sscottl				}
1369136849Sscottl			}
1370136849Sscottl		}
1371136849Sscottl		KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n",
1372136849Sscottl			pAdapter->mvChannel[channel].online, channel));
1373136849Sscottl	}
1374136849Sscottl
1375136849Sscottl#ifdef SUPPORT_ARRAY
1376136849Sscottl	for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) {
1377136849Sscottl		pVDev = ArrayTables(i);
1378136849Sscottl		mArFreeArrayTable(pVDev);
1379136849Sscottl	}
1380136849Sscottl#endif
1381136849Sscottl
1382136849Sscottl	KdPrint(("Initialize Devices\n"));
1383136849Sscottl	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
1384149871Sscottl		MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel];
1385136849Sscottl		if (pMvSataChannel) {
1386136849Sscottl			init_vdev_params(pAdapter, channel);
1387136849Sscottl			IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk);
1388136849Sscottl		}
1389136849Sscottl	}
1390136849Sscottl#ifdef SUPPORT_ARRAY
1391136849Sscottl	CheckArrayCritical(_VBUS_P0);
1392136849Sscottl#endif
1393136849Sscottl	_vbus_p->nInstances = 1;
1394136849Sscottl	fRegisterVdevice(pAdapter);
1395136849Sscottl
1396136849Sscottl	for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) {
1397136849Sscottl		pVDev = _vbus_p->pVDevice[channel];
1398136849Sscottl		if (pVDev && pVDev->vf_online)
1399136849Sscottl			fCheckBootable(pVDev);
1400136849Sscottl	}
1401136849Sscottl
1402136849Sscottl#if defined(SUPPORT_ARRAY) && defined(_RAID5N_)
1403136849Sscottl	init_raid5_memory(_VBUS_P0);
1404136849Sscottl	_vbus_(r5).enable_write_back = 1;
1405149871Sscottl	printf("RR182x: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled");
1406136849Sscottl#endif
1407136849Sscottl
1408136849Sscottl	mvSataUnmaskAdapterInterrupt(pMvSataAdapter);
1409136849Sscottl	return 0;
1410136849Sscottl}
1411136849Sscottl
1412136849Sscottlint
1413136849SscottlMvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
1414136849Sscottl{
1415149871Sscottl	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData;
1416136849Sscottl
1417136849Sscottl	mvSataDisableChannelDma(pMvSataAdapter, channel);
1418136849Sscottl	/* Flush pending commands */
1419136849Sscottl	mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
1420136849Sscottl
1421136849Sscottl	/* Software reset channel */
1422149871Sscottl	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE)
1423149871Sscottl	{
1424136849Sscottl		MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n",
1425149871Sscottl				 pMvSataAdapter->adapterId, channel);
1426149871Sscottl		hptmv_free_channel(pAdapter, channel);
1427136849Sscottl		return -1;
1428136849Sscottl	}
1429136849Sscottl
1430136849Sscottl	/* Hardware reset channel */
1431149871Sscottl	if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE)
1432149871Sscottl	{
1433149871Sscottl		MV_ERROR("RR182x [%d,%d] Failed to Hard reser the SATA channel\n",
1434149871Sscottl				 pMvSataAdapter->adapterId, channel);
1435136849Sscottl		hptmv_free_channel(pAdapter, channel);
1436136849Sscottl		return -1;
1437136849Sscottl	}
1438136849Sscottl
1439149871Sscottl	if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE)
1440149871Sscottl	{
1441149871Sscottl		 MV_ERROR("RR182x [%d,%d] Failed to Connect Device\n",
1442149871Sscottl				 pMvSataAdapter->adapterId, channel);
1443136849Sscottl		hptmv_free_channel(pAdapter, channel);
1444136849Sscottl		return -1;
1445149871Sscottl	}else
1446149871Sscottl	{
1447149871Sscottl		MV_ERROR("channel %d: perform recalibrate command", channel);
1448149871Sscottl		if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
1449149871Sscottl								MV_NON_UDMA_PROTOCOL_NON_DATA,
1450149871Sscottl								MV_FALSE,
1451149871Sscottl								NULL,	 /* pBuffer*/
1452149871Sscottl								0,		 /* count  */
1453149871Sscottl								0,		/*features*/
1454149871Sscottl										/* sectorCount */
1455149871Sscottl								0,
1456149871Sscottl								0,	/* lbaLow */
1457149871Sscottl								0,	/* lbaMid */
1458149871Sscottl									/* lbaHigh */
1459149871Sscottl								0,
1460149871Sscottl								0,		/* device */
1461149871Sscottl										/* command */
1462149871Sscottl								0x10))
1463149871Sscottl			MV_ERROR("channel %d: recalibrate failed", channel);
1464149871Sscottl
1465136849Sscottl		/* Set transfer mode */
1466136849Sscottl		if((mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1467149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1468149871Sscottl						MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) ||
1469149871Sscottl			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1470149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1471149871Sscottl						pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) ||
1472149871Sscottl			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1473149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1474149871Sscottl						pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) )
1475149871Sscottl		{
1476136849Sscottl			MV_ERROR("channel %d: Set Features failed", channel);
1477136849Sscottl			hptmv_free_channel(pAdapter, channel);
1478136849Sscottl			return -1;
1479136849Sscottl		}
1480136849Sscottl		/* Enable EDMA */
1481149871Sscottl		if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE)
1482149871Sscottl		{
1483136849Sscottl			MV_ERROR("Failed to enable DMA, channel=%d", channel);
1484136849Sscottl			hptmv_free_channel(pAdapter, channel);
1485136849Sscottl			return -1;
1486136849Sscottl		}
1487136849Sscottl	}
1488136849Sscottl	return 0;
1489136849Sscottl}
1490136849Sscottl
1491136849Sscottlstatic int
1492136849SscottlfResetActiveCommands(PVBus _vbus_p)
1493136849Sscottl{
1494149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
1495136849Sscottl	MV_U8 channel;
1496136849Sscottl	for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
1497149871Sscottl		if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands)
1498149871Sscottl			MvSataResetChannel(pMvSataAdapter,channel);
1499136849Sscottl	}
1500136849Sscottl	return 0;
1501136849Sscottl}
1502136849Sscottl
1503149871Sscottlvoid fCompleteAllCommandsSynchronously(PVBus _vbus_p)
1504136849Sscottl{
1505136849Sscottl	UINT cont;
1506136849Sscottl	ULONG ticks = 0;
1507136849Sscottl	MV_U8 channel;
1508149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
1509136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
1510136849Sscottl
1511136849Sscottl	do {
1512136849Sscottlcheck_cmds:
1513136849Sscottl		cont = 0;
1514136849Sscottl		CheckPendingCall(_VBUS_P0);
1515136849Sscottl#ifdef _RAID5N_
1516136849Sscottl		dataxfer_poll();
1517136849Sscottl		xor_poll();
1518136849Sscottl#endif
1519149871Sscottl		for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
1520136849Sscottl			pMvSataChannel = pMvSataAdapter->sataChannel[channel];
1521149871Sscottl			if (pMvSataChannel && pMvSataChannel->outstandingCommands)
1522149871Sscottl			{
1523136849Sscottl				while (pMvSataChannel->outstandingCommands) {
1524149871Sscottl					if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) {
1525136849Sscottl						StallExec(1000);
1526136849Sscottl						if (ticks++ > 3000) {
1527149871Sscottl							MvSataResetChannel(pMvSataAdapter,channel);
1528136849Sscottl							goto check_cmds;
1529136849Sscottl						}
1530149871Sscottl					}
1531149871Sscottl					else
1532136849Sscottl						ticks = 0;
1533136849Sscottl				}
1534136849Sscottl				cont = 1;
1535136849Sscottl			}
1536136849Sscottl		}
1537136849Sscottl	} while (cont);
1538136849Sscottl}
1539136849Sscottl
1540136849Sscottlvoid
1541136849SscottlfResetVBus(_VBUS_ARG0)
1542136849Sscottl{
1543136862Sscottl	KdPrint(("fMvResetBus(%p)", _vbus_p));
1544136849Sscottl
1545136849Sscottl	/* some commands may already finished. */
1546136849Sscottl	CheckPendingCall(_VBUS_P0);
1547136849Sscottl
1548136849Sscottl	fResetActiveCommands(_vbus_p);
1549136849Sscottl	/*
1550136849Sscottl	 * the other pending commands may still be finished successfully.
1551136849Sscottl	 */
1552136849Sscottl	fCompleteAllCommandsSynchronously(_vbus_p);
1553136849Sscottl
1554136849Sscottl	/* Now there should be no pending commands. No more action needed. */
1555136849Sscottl	CheckIdleCall(_VBUS_P0);
1556136849Sscottl
1557136849Sscottl	KdPrint(("fMvResetBus() done"));
1558136849Sscottl}
1559136849Sscottl
1560149871Sscottl/*No rescan function*/
1561136849Sscottlvoid
1562136849SscottlfRescanAllDevice(_VBUS_ARG0)
1563136849Sscottl{
1564136849Sscottl}
1565136849Sscottl
1566136849Sscottlstatic MV_BOOLEAN
1567149871SscottlCommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
1568149871Sscottl					MV_U8 channelNum,
1569149871Sscottl					MV_COMPLETION_TYPE comp_type,
1570149871Sscottl					MV_VOID_PTR commandId,
1571149871Sscottl					MV_U16 responseFlags,
1572149871Sscottl					MV_U32 timeStamp,
1573149871Sscottl					MV_STORAGE_DEVICE_REGISTERS *registerStruct)
1574136849Sscottl{
1575136849Sscottl	PCommand pCmd = (PCommand) commandId;
1576136849Sscottl	_VBUS_INST(pCmd->pVDevice->pVBus)
1577136849Sscottl
1578136849Sscottl	if (pCmd->uScratch.sata_param.prdAddr)
1579149871Sscottl		FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr);
1580136849Sscottl
1581149871Sscottl	switch (comp_type)
1582149871Sscottl	{
1583136849Sscottl	case MV_COMPLETION_TYPE_NORMAL:
1584136849Sscottl		pCmd->Result = RETURN_SUCCESS;
1585136849Sscottl		break;
1586136849Sscottl	case MV_COMPLETION_TYPE_ABORT:
1587136849Sscottl		pCmd->Result = RETURN_BUS_RESET;
1588136849Sscottl		break;
1589136849Sscottl	case MV_COMPLETION_TYPE_ERROR:
1590149871Sscottl		 MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n",
1591149871Sscottl				 pMvSataAdapter->adapterId, channelNum, responseFlags);
1592136849Sscottl
1593136849Sscottl		if (responseFlags & 4) {
1594149871Sscottl			MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x,"
1595149871Sscottl				" LBA high %x, device %x, status %x\n",
1596149871Sscottl				registerStruct->errorRegister,
1597149871Sscottl				registerStruct->sectorCountRegister,
1598149871Sscottl				registerStruct->lbaLowRegister,
1599149871Sscottl				registerStruct->lbaMidRegister,
1600149871Sscottl				registerStruct->lbaHighRegister,
1601149871Sscottl				registerStruct->deviceRegister,
1602149871Sscottl				registerStruct->statusRegister);
1603136849Sscottl		}
1604149871Sscottl		/*We can't do handleEdmaError directly here, because CommandCompletionCB is called by
1605149871Sscottl		 * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/
1606136849Sscottl		pCmd->uScratch.sata_param.responseFlags = responseFlags;
1607149871Sscottl		pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister;
1608149871Sscottl		pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister;
1609136849Sscottl		pCmd->pVDevice->u.disk.QueueLength--;
1610136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd);
1611136849Sscottl		return TRUE;
1612136849Sscottl
1613136849Sscottl	default:
1614136849Sscottl		MV_ERROR(" Unknown completion type (%d)\n", comp_type);
1615136849Sscottl		return MV_FALSE;
1616136849Sscottl	}
1617136849Sscottl
1618149871Sscottl	if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) {
1619136849Sscottl		pCmd->uScratch.sata_param.cmd_priv --;
1620136849Sscottl		return TRUE;
1621136849Sscottl	}
1622136849Sscottl	pCmd->pVDevice->u.disk.QueueLength--;
1623136849Sscottl	CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1624136849Sscottl	return TRUE;
1625136849Sscottl}
1626136849Sscottl
1627136849Sscottlvoid
1628136849SscottlfDeviceSendCommand(_VBUS_ARG PCommand pCmd)
1629136849Sscottl{
1630149871Sscottl	MV_SATA_EDMA_PRD_ENTRY  *pPRDTable = 0;
1631136849Sscottl	MV_SATA_ADAPTER *pMvSataAdapter;
1632136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
1633149871Sscottl	PVDevice pVDevice = pCmd->pVDevice;
1634149871Sscottl	PDevice  pDevice = &pVDevice->u.disk;
1635149871Sscottl	ULONG    Lba = pCmd->uCmd.Ide.Lba;
1636149871Sscottl	USHORT   nSector = pCmd->uCmd.Ide.nSectors;
1637149871Sscottl
1638136849Sscottl	MV_QUEUE_COMMAND_RESULT result;
1639136849Sscottl	MV_QUEUE_COMMAND_INFO commandInfo;
1640149871Sscottl	MV_UDMA_COMMAND_PARAMS  *pUdmaParams = &commandInfo.commandParams.udmaCommand;
1641149871Sscottl	MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand;
1642149871Sscottl
1643136849Sscottl	MV_BOOLEAN is48bit = MV_FALSE;
1644149871Sscottl	MV_U8      channel;
1645149871Sscottl	int        i=0;
1646149871Sscottl
1647136849Sscottl	DECLARE_BUFFER(FPSCAT_GATH, tmpSg);
1648136849Sscottl
1649136849Sscottl	if (!pDevice->df_on_line) {
1650136849Sscottl		MV_ERROR("Device is offline");
1651136849Sscottl		pCmd->Result = RETURN_BAD_DEVICE;
1652136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1653136849Sscottl		return;
1654136849Sscottl	}
1655136849Sscottl
1656136849Sscottl	pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors;
1657136849Sscottl	pMvSataChannel = pDevice->mv;
1658136849Sscottl	pMvSataAdapter = pMvSataChannel->mvSataAdapter;
1659136849Sscottl	channel = pMvSataChannel->channelNumber;
1660136849Sscottl
1661149871Sscottl	/* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */
1662136849Sscottl	Lba += pDevice->dDeHiddenLba;
1663136849Sscottl	/* check LBA */
1664136849Sscottl	if (Lba+nSector-1 > pDevice->dDeRealCapacity) {
1665136849Sscottl		pCmd->Result = RETURN_INVALID_REQUEST;
1666136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1667136849Sscottl		return;
1668136849Sscottl	}
1669136849Sscottl
1670136849Sscottl	if(Lba & 0xF0000000){
1671136849Sscottl		is48bit = MV_TRUE;
1672136849Sscottl	}
1673136849Sscottl
1674149871Sscottl	switch (pCmd->uCmd.Ide.Command)
1675149871Sscottl	{
1676136849Sscottl	case IDE_COMMAND_READ:
1677136849Sscottl	case IDE_COMMAND_WRITE:
1678136849Sscottl		if (pDevice->bDeModeSetting<8) goto pio;
1679136849Sscottl
1680136849Sscottl		commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA;
1681136849Sscottl		pUdmaParams->isEXT = is48bit;
1682136849Sscottl		pUdmaParams->numOfSectors = nSector;
1683136849Sscottl		pUdmaParams->lowLBAAddress = Lba;
1684136849Sscottl		pUdmaParams->highLBAAddress = 0;
1685136849Sscottl		pUdmaParams->prdHighAddr = 0;
1686136849Sscottl		pUdmaParams->callBack = CommandCompletionCB;
1687136849Sscottl		pUdmaParams->commandId = (MV_VOID_PTR )pCmd;
1688136849Sscottl		if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ)
1689136849Sscottl			pUdmaParams->readWrite = MV_UDMA_TYPE_READ;
1690136849Sscottl		else
1691136849Sscottl			pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE;
1692136849Sscottl
1693136849Sscottl		if (pCmd->pSgTable && pCmd->cf_physical_sg) {
1694136849Sscottl			FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
1695149871Sscottl			do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
1696149871Sscottl		}
1697149871Sscottl		else {
1698149871Sscottl			if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) {
1699136849Sscottlpio:
1700149871Sscottl				mvSataDisableChannelDma(pMvSataAdapter, channel);
1701149871Sscottl				mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
1702149871Sscottl
1703149871Sscottl				if (pCmd->pSgTable && pCmd->cf_physical_sg==0) {
1704149871Sscottl					FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
1705149871Sscottl					do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
1706149871Sscottl				}
1707149871Sscottl				else {
1708149871Sscottl					if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) {
1709149871Sscottl						pCmd->Result = RETURN_NEED_LOGICAL_SG;
1710149871Sscottl						goto finish_cmd;
1711149871Sscottl					}
1712149871Sscottl				}
1713149871Sscottl
1714136849Sscottl				do {
1715149871Sscottl					ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000;
1716149871Sscottl					ULONG_PTR addr = tmpSg->dSgAddress;
1717149871Sscottl					if (size & 0x1ff) {
1718149871Sscottl						pCmd->Result = RETURN_INVALID_REQUEST;
1719149871Sscottl						goto finish_cmd;
1720149871Sscottl					}
1721149871Sscottl					if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
1722149871Sscottl						(pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN,
1723149871Sscottl						is48bit,
1724149871Sscottl						(MV_U16_PTR)addr,
1725149871Sscottl						size >> 1,	/* count       */
1726149871Sscottl						0,		/* features  N/A  */
1727149871Sscottl						(MV_U16)(size>>9),	/*sector count*/
1728149871Sscottl						(MV_U16)(  (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 )  | (UCHAR)(Lba & 0xFF) ), /*lbalow*/
1729149871Sscottl						(MV_U16)((Lba >> 8) & 0xFF), /* lbaMid      */
1730149871Sscottl						(MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh     */
1731149871Sscottl						(MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device      */
1732149871Sscottl						(MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command)
1733149871Sscottl					)==MV_FALSE)
1734149871Sscottl					{
1735149871Sscottl						pCmd->Result = RETURN_IDE_ERROR;
1736149871Sscottl						goto finish_cmd;
1737149871Sscottl					}
1738149871Sscottl					Lba += size>>9;
1739149871Sscottl					if(Lba & 0xF0000000) is48bit = MV_TRUE;
1740136849Sscottl				}
1741149871Sscottl				while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
1742149871Sscottl				pCmd->Result = RETURN_SUCCESS;
1743149871Sscottlfinish_cmd:
1744149871Sscottl				mvSataEnableChannelDma(pMvSataAdapter,channel);
1745149871Sscottl				CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1746149871Sscottl				return;
1747136849Sscottl			}
1748136849Sscottl		}
1749136849Sscottl
1750149871Sscottl		pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData);
1751136862Sscottl		KdPrint(("pPRDTable:%p\n",pPRDTable));
1752136849Sscottl		if (!pPRDTable) {
1753136849Sscottl			pCmd->Result = RETURN_DEVICE_BUSY;
1754149871Sscottl			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1755136849Sscottl			HPT_ASSERT(0);
1756136849Sscottl			return;
1757136849Sscottl		}
1758136849Sscottl
1759149871Sscottl		do{
1760149871Sscottl			pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0);
1761136849Sscottl			pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag;
1762136849Sscottl			pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize;
1763136849Sscottl			pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress;
1764136849Sscottl			pPRDTable[i].reserved = 0;
1765136849Sscottl			i++;
1766149871Sscottl		}while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
1767136849Sscottl
1768149871Sscottl		pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable);
1769149871Sscottl		if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) {
1770136849Sscottl			pUdmaParams->numOfSectors = 0;
1771136849Sscottl		}
1772136849Sscottl
1773136849Sscottl		pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable;
1774136849Sscottl
1775149871Sscottl		result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1776136849Sscottl
1777149871Sscottl		if (result != MV_QUEUE_COMMAND_RESULT_OK)
1778149871Sscottl		{
1779136849Sscottlqueue_failed:
1780149871Sscottl			switch (result)
1781149871Sscottl			{
1782136849Sscottl			case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
1783149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA "
1784149871Sscottl						 "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress);
1785136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1786136849Sscottl				break;
1787136849Sscottl			case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
1788149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. EDMA"
1789149871Sscottl						 " disabled adapter %d channel %d\n",
1790149871Sscottl						 pMvSataAdapter->adapterId, channel);
1791136849Sscottl				mvSataEnableChannelDma(pMvSataAdapter,channel);
1792136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1793136849Sscottl				break;
1794136849Sscottl			case MV_QUEUE_COMMAND_RESULT_FULL:
1795149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. Queue is"
1796149871Sscottl						 " Full adapter %d channel %d\n",
1797149871Sscottl						 pMvSataAdapter->adapterId, channel);
1798136849Sscottl				pCmd->Result = RETURN_DEVICE_BUSY;
1799136849Sscottl				break;
1800136849Sscottl			case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
1801149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. (Bad "
1802149871Sscottl						 "Params), pMvSataAdapter: %p,  pSataChannel: %p.\n",
1803149871Sscottl						 pMvSataAdapter, pMvSataAdapter->sataChannel[channel]);
1804136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1805136849Sscottl				break;
1806136849Sscottl			default:
1807149871Sscottl				MV_ERROR("IAL Error: Bad result value (%d) from queue"
1808149871Sscottl						 " command\n", result);
1809136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1810136849Sscottl			}
1811136849Sscottl			if(pPRDTable)
1812149871Sscottl				FreePRDTable(pMvSataAdapter->IALData,pPRDTable);
1813149871Sscottl			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1814136849Sscottl		}
1815136849Sscottl		pDevice->QueueLength++;
1816136849Sscottl		return;
1817136849Sscottl
1818136849Sscottl	case IDE_COMMAND_VERIFY:
1819136849Sscottl		commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
1820136849Sscottl		pNoUdmaParams->bufPtr = NULL;
1821136849Sscottl		pNoUdmaParams->callBack = CommandCompletionCB;
1822136849Sscottl		pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd;
1823136849Sscottl		pNoUdmaParams->count = 0;
1824136849Sscottl		pNoUdmaParams->features = 0;
1825136849Sscottl		pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
1826136849Sscottl
1827136849Sscottl		pCmd->uScratch.sata_param.cmd_priv = 1;
1828136849Sscottl		if (pMvSataChannel->lba48Address == MV_TRUE){
1829149871Sscottl			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT;
1830136849Sscottl			pNoUdmaParams->isEXT = MV_TRUE;
1831149871Sscottl			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
1832136849Sscottl			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
1833136849Sscottl			pNoUdmaParams->lbaLow =
1834149871Sscottl				(MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff));
1835136849Sscottl			pNoUdmaParams->sectorCount = nSector;
1836136849Sscottl			pNoUdmaParams->device = 0x40;
1837149871Sscottl			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1838149871Sscottl			if (result != MV_QUEUE_COMMAND_RESULT_OK){
1839136849Sscottl				goto queue_failed;
1840136849Sscottl			}
1841136849Sscottl			return;
1842136849Sscottl		}
1843149871Sscottl		else{
1844149871Sscottl			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS;
1845149871Sscottl			pNoUdmaParams->isEXT = MV_FALSE;
1846149871Sscottl			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
1847149871Sscottl			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
1848149871Sscottl			pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff);
1849149871Sscottl			pNoUdmaParams->sectorCount = 0xff & nSector;
1850149871Sscottl			pNoUdmaParams->device = (MV_U8)(0x40 |
1851149871Sscottl				((Lba & 0xf000000) >> 24));
1852149871Sscottl			pNoUdmaParams->callBack = CommandCompletionCB;
1853149871Sscottl			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1854149871Sscottl			/*FIXME: how about the commands already queued? but marvel also forgets to consider this*/
1855149871Sscottl			if (result != MV_QUEUE_COMMAND_RESULT_OK){
1856149871Sscottl				goto queue_failed;
1857149871Sscottl			}
1858136849Sscottl		}
1859136849Sscottl		break;
1860136849Sscottl	default:
1861136849Sscottl		pCmd->Result = RETURN_INVALID_REQUEST;
1862136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1863136849Sscottl		break;
1864136849Sscottl	}
1865136849Sscottl}
1866136849Sscottl
1867136849Sscottl/**********************************************************
1868136849Sscottl *
1869136849Sscottl *	Probe the hostadapter.
1870136849Sscottl *
1871136849Sscottl **********************************************************/
1872136849Sscottlstatic int
1873136849Sscottlhpt_probe(device_t dev)
1874136849Sscottl{
1875136849Sscottl	if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) &&
1876136849Sscottl		(pci_get_device(dev) == MV_SATA_DEVICE_ID_5081
1877136849Sscottl#ifdef FOR_DEMO
1878136849Sscottl		|| pci_get_device(dev) == MV_SATA_DEVICE_ID_5080
1879136849Sscottl#endif
1880149871Sscottl		))
1881149871Sscottl	{
1882136849Sscottl		KdPrintI((CONTROLLER_NAME " found\n"));
1883136849Sscottl		device_set_desc(dev, CONTROLLER_NAME);
1884136849Sscottl		return 0;
1885136849Sscottl	}
1886136849Sscottl	else
1887136849Sscottl		return(ENXIO);
1888136849Sscottl}
1889136849Sscottl
1890136849Sscottl/***********************************************************
1891136849Sscottl *
1892136849Sscottl *      Auto configuration:  attach and init a host adapter.
1893136849Sscottl *
1894136849Sscottl ***********************************************************/
1895136849Sscottlstatic int
1896136849Sscottlhpt_attach(device_t dev)
1897136849Sscottl{
1898149871Sscottl	IAL_ADAPTER_T * pAdapter = device_get_softc(dev);
1899136849Sscottl	int rid;
1900136849Sscottl	union ccb *ccb;
1901136849Sscottl	struct cam_devq *devq;
1902136849Sscottl	struct cam_sim *hpt_vsim;
1903136849Sscottl
1904149871Sscottl	printf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION);
1905136849Sscottl
1906149871Sscottl	if (!pAdapter)
1907149871Sscottl	{
1908149871Sscottl		pAdapter = (IAL_ADAPTER_T *)malloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT);
1909149871Sscottl#if __FreeBSD_version > 410000
1910149871Sscottl		device_set_softc(dev, (void *)pAdapter);
1911149871Sscottl#else
1912149871Sscottl		device_set_driver(dev, (driver_t *)pAdapter);
1913149871Sscottl#endif
1914149871Sscottl	}
1915149871Sscottl
1916149871Sscottl	if (!pAdapter) return (ENOMEM);
1917149871Sscottl	bzero(pAdapter, sizeof(IAL_ADAPTER_T));
1918149871Sscottl
1919136849Sscottl	pAdapter->hpt_dev = dev;
1920136849Sscottl
1921136849Sscottl	rid = init_adapter(pAdapter);
1922136849Sscottl	if (rid)
1923136849Sscottl		return rid;
1924136849Sscottl
1925136849Sscottl	rid = 0;
1926149871Sscottl	if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL)
1927149871Sscottl	{
1928136849Sscottl		hpt_printk(("can't allocate interrupt\n"));
1929136849Sscottl		return(ENXIO);
1930136849Sscottl	}
1931136849Sscottl
1932166901Spiso	if(bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr))
1933149871Sscottl	{
1934136849Sscottl		hpt_printk(("can't set up interrupt\n"));
1935136849Sscottl		free(pAdapter, M_DEVBUF);
1936136849Sscottl		return(ENXIO);
1937136849Sscottl	}
1938136849Sscottl
1939149871Sscottl
1940149871Sscottl	if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL)
1941149871Sscottl	{
1942149871Sscottl		bzero(ccb, sizeof(*ccb));
1943136849Sscottl		ccb->ccb_h.pinfo.priority = 1;
1944136849Sscottl		ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
1945149871Sscottl	}
1946149871Sscottl	else
1947149871Sscottl	{
1948136849Sscottl		return ENOMEM;
1949136849Sscottl	}
1950136849Sscottl	/*
1951136849Sscottl	 * Create the device queue for our SIM(s).
1952136849Sscottl	 */
1953149871Sscottl	if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL)
1954149871Sscottl	{
1955136849Sscottl		KdPrint(("ENXIO\n"));
1956136849Sscottl		return ENOMEM;
1957136849Sscottl	}
1958136849Sscottl
1959136849Sscottl	/*
1960136849Sscottl	 * Construct our SIM entry
1961136849Sscottl	 */
1962149871Sscottl	if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
1963168752Sscottl			pAdapter, device_get_unit(pAdapter->hpt_dev),
1964168752Sscottl			&Giant, /*untagged*/1, /*tagged*/8,  devq)) == NULL)	{
1965136849Sscottl		cam_simq_free(devq);
1966136849Sscottl		return ENOMEM;
1967136849Sscottl	}
1968136849Sscottl
1969170872Sscottl	if(xpt_bus_register(hpt_vsim, dev, 0) != CAM_SUCCESS)
1970149871Sscottl	{
1971136849Sscottl		cam_sim_free(hpt_vsim, /*free devq*/ TRUE);
1972136849Sscottl		hpt_vsim = NULL;
1973136849Sscottl		return ENXIO;
1974136849Sscottl	}
1975136849Sscottl
1976136849Sscottl	if(xpt_create_path(&pAdapter->path, /*periph */ NULL,
1977149871Sscottl			cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD,
1978149871Sscottl			CAM_LUN_WILDCARD) != CAM_REQ_CMP)
1979149871Sscottl	{
1980136849Sscottl		xpt_bus_deregister(cam_sim_path(hpt_vsim));
1981136849Sscottl		cam_sim_free(hpt_vsim, /*free_devq*/TRUE);
1982136849Sscottl		hpt_vsim = NULL;
1983136849Sscottl		return ENXIO;
1984136849Sscottl	}
1985136849Sscottl
1986136849Sscottl	xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5);
1987136849Sscottl	ccb->ccb_h.func_code = XPT_SASYNC_CB;
1988136849Sscottl	ccb->csa.event_enable = AC_LOST_DEVICE;
1989136849Sscottl	ccb->csa.callback = hpt_async;
1990136849Sscottl	ccb->csa.callback_arg = hpt_vsim;
1991136849Sscottl	xpt_action((union ccb *)ccb);
1992136849Sscottl	free(ccb, M_DEVBUF);
1993136849Sscottl
1994149871Sscottl	/* Register shutdown handler, and start the work thread. */
1995139044Snjl	if (device_get_unit(dev) == 0) {
1996149871Sscottl		pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_final,
1997149871Sscottl			hpt_shutdown, dev, SHUTDOWN_PRI_DEFAULT);
1998149871Sscottl		if (pAdapter->eh)
1999139044Snjl			launch_worker_thread();
2000139044Snjl		else
2001149871Sscottl			hpt_printk(("shutdown event registration failed\n"));
2002139044Snjl	}
2003136849Sscottl
2004136849Sscottl	return 0;
2005136849Sscottl}
2006136849Sscottl
2007136849Sscottlstatic int
2008136849Sscottlhpt_detach(device_t dev)
2009149871Sscottl{
2010136849Sscottl	return (EBUSY);
2011136849Sscottl}
2012136849Sscottl
2013149871Sscottl
2014136849Sscottl/***************************************************************
2015136849Sscottl * The poll function is used to simulate the interrupt when
2016136849Sscottl * the interrupt subsystem is not functioning.
2017136849Sscottl *
2018136849Sscottl ***************************************************************/
2019136849Sscottlstatic void
2020136849Sscottlhpt_poll(struct cam_sim *sim)
2021136849Sscottl{
2022136849Sscottl	hpt_intr((void *)cam_sim_softc(sim));
2023136849Sscottl}
2024136849Sscottl
2025136849Sscottl/****************************************************************
2026136849Sscottl *	Name:	hpt_intr
2027136849Sscottl *	Description:	Interrupt handler.
2028136849Sscottl ****************************************************************/
2029136849Sscottlstatic void
2030136849Sscottlhpt_intr(void *arg)
2031136849Sscottl{
2032136849Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg;
2033149871Sscottl	intrmask_t oldspl = lock_driver();
2034136849Sscottl
2035136849Sscottl	/* KdPrintI(("----- Entering Isr() -----\n")); */
2036149871Sscottl	if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE)
2037149871Sscottl	{
2038136849Sscottl		_VBUS_INST(&pAdapter->VBus)
2039136849Sscottl		CheckPendingCall(_VBUS_P0);
2040136849Sscottl	}
2041136849Sscottl
2042136849Sscottl	/* KdPrintI(("----- Leaving Isr() -----\n")); */
2043136849Sscottl	unlock_driver(oldspl);
2044136849Sscottl}
2045136849Sscottl
2046136849Sscottl/**********************************************************
2047136849Sscottl * 			Asynchronous Events
2048136849Sscottl *********************************************************/
2049136849Sscottl#if (!defined(UNREFERENCED_PARAMETER))
2050136849Sscottl#define UNREFERENCED_PARAMETER(x) (void)(x)
2051136849Sscottl#endif
2052136849Sscottl
2053136849Sscottlstatic void
2054136849Sscottlhpt_async(void * callback_arg, u_int32_t code, struct cam_path * path,
2055136849Sscottl    void * arg)
2056136849Sscottl{
2057136849Sscottl	/* debug XXXX */
2058136849Sscottl	panic("Here");
2059136849Sscottl	UNREFERENCED_PARAMETER(callback_arg);
2060136849Sscottl	UNREFERENCED_PARAMETER(code);
2061136849Sscottl	UNREFERENCED_PARAMETER(path);
2062136849Sscottl	UNREFERENCED_PARAMETER(arg);
2063136849Sscottl
2064136849Sscottl}
2065136849Sscottl
2066136849Sscottlstatic void
2067136849SscottlFlushAdapter(IAL_ADAPTER_T *pAdapter)
2068136849Sscottl{
2069136849Sscottl	int i;
2070136849Sscottl
2071136849Sscottl	hpt_printk(("flush all devices\n"));
2072136849Sscottl
2073136849Sscottl	/* flush all devices */
2074136849Sscottl	for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) {
2075136849Sscottl		PVDevice pVDev = pAdapter->VBus.pVDevice[i];
2076149871Sscottl		if(pVDev) fFlushVDev(pVDev);
2077136849Sscottl	}
2078136849Sscottl}
2079136849Sscottl
2080136849Sscottlstatic int
2081136849Sscottlhpt_shutdown(device_t dev)
2082136849Sscottl{
2083149871Sscottl		IAL_ADAPTER_T *pAdapter;
2084149871Sscottl
2085149871Sscottl		pAdapter = device_get_softc(dev);
2086149871Sscottl		if (pAdapter == NULL)
2087149871Sscottl			return (EINVAL);
2088136849Sscottl
2089149871Sscottl		EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh);
2090149871Sscottl		FlushAdapter(pAdapter);
2091149871Sscottl		  /* give the flush some time to happen,
2092149871Sscottl		    *otherwise "shutdown -p now" will make file system corrupted */
2093149871Sscottl		DELAY(1000 * 1000 * 5);
2094149871Sscottl		return 0;
2095136849Sscottl}
2096136849Sscottl
2097136849Sscottlvoid
2098136849SscottlCheck_Idle_Call(IAL_ADAPTER_T *pAdapter)
2099136849Sscottl{
2100136849Sscottl	_VBUS_INST(&pAdapter->VBus)
2101136849Sscottl
2102136849Sscottl	if (mWaitingForIdle(_VBUS_P0)) {
2103136849Sscottl		CheckIdleCall(_VBUS_P0);
2104136849Sscottl#ifdef SUPPORT_ARRAY
2105149871Sscottl		{
2106149871Sscottl			int i;
2107136849Sscottl			PVDevice pArray;
2108149871Sscottl			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){
2109149871Sscottl				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
2110149871Sscottl					continue;
2111149871Sscottl				else if (pArray->u.array.rf_auto_rebuild) {
2112149871Sscottl						KdPrint(("auto rebuild.\n"));
2113149871Sscottl						pArray->u.array.rf_auto_rebuild = 0;
2114149871Sscottl						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
2115149871Sscottl				}
2116136849Sscottl			}
2117136849Sscottl		}
2118136849Sscottl#endif
2119136849Sscottl	}
2120136849Sscottl	/* launch the awaiting commands blocked by mWaitingForIdle */
2121149871Sscottl	while(pAdapter->pending_Q!= NULL)
2122149871Sscottl	{
2123136849Sscottl		_VBUS_INST(&pAdapter->VBus)
2124149871Sscottl		union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr;
2125136849Sscottl		hpt_free_ccb(&pAdapter->pending_Q, ccb);
2126136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb);
2127136849Sscottl	}
2128136849Sscottl}
2129136849Sscottl
2130136849Sscottlstatic void
2131136849Sscottlccb_done(union ccb *ccb)
2132136849Sscottl{
2133149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2134149871Sscottl	IAL_ADAPTER_T * pAdapter = pmap->pAdapter;
2135149871Sscottl	KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status));
2136136849Sscottl
2137149871Sscottl	dmamap_put(pmap);
2138136849Sscottl	xpt_done(ccb);
2139136849Sscottl
2140136849Sscottl	pAdapter->outstandingCommands--;
2141136849Sscottl
2142149871Sscottl	if (pAdapter->outstandingCommands == 0)
2143149871Sscottl	{
2144136849Sscottl		if(DPC_Request_Nums == 0)
2145136849Sscottl			Check_Idle_Call(pAdapter);
2146136849Sscottl	}
2147136849Sscottl}
2148136849Sscottl
2149136849Sscottl/****************************************************************
2150136849Sscottl *	Name:	hpt_action
2151136849Sscottl *	Description:	Process a queued command from the CAM layer.
2152136849Sscottl *	Parameters:		sim - Pointer to SIM object
2153136849Sscottl *					ccb - Pointer to SCSI command structure.
2154136849Sscottl ****************************************************************/
2155136849Sscottl
2156136849Sscottlvoid
2157136849Sscottlhpt_action(struct cam_sim *sim, union ccb *ccb)
2158136849Sscottl{
2159136849Sscottl	intrmask_t oldspl;
2160136849Sscottl	IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim);
2161149871Sscottl	PBUS_DMAMAP  pmap;
2162136849Sscottl	_VBUS_INST(&pAdapter->VBus)
2163136849Sscottl
2164149878Sscottl	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n"));
2165149871Sscottl	KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code));
2166136849Sscottl
2167149871Sscottl	switch (ccb->ccb_h.func_code)
2168149871Sscottl	{
2169149871Sscottl		case XPT_SCSI_IO:	/* Execute the requested I/O operation */
2170149871Sscottl		{
2171149871Sscottl			/* ccb->ccb_h.path_id is not our bus id - don't check it */
2172136849Sscottl
2173149871Sscottl			if (ccb->ccb_h.target_lun)	{
2174149871Sscottl				ccb->ccb_h.status = CAM_LUN_INVALID;
2175149871Sscottl				xpt_done(ccb);
2176149871Sscottl				return;
2177149871Sscottl			}
2178149871Sscottl			if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS ||
2179149871Sscottl				pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) {
2180149871Sscottl				ccb->ccb_h.status = CAM_TID_INVALID;
2181149871Sscottl				xpt_done(ccb);
2182149871Sscottl				return;
2183149871Sscottl			}
2184136849Sscottl
2185149871Sscottl			oldspl = lock_driver();
2186149871Sscottl			if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
2187149871Sscottl				Check_Idle_Call(pAdapter);
2188136849Sscottl
2189149871Sscottl			pmap = dmamap_get(pAdapter);
2190149871Sscottl			HPT_ASSERT(pmap);
2191149871Sscottl			ccb->ccb_adapter = pmap;
2192149871Sscottl			memset((void *)pmap->psg, 0,  sizeof(pmap->psg));
2193136849Sscottl
2194149871Sscottl			if (mWaitingForIdle(_VBUS_P0))
2195149871Sscottl				hpt_queue_ccb(&pAdapter->pending_Q, ccb);
2196149871Sscottl			else
2197149871Sscottl				OsSendCommand(_VBUS_P ccb);
2198149871Sscottl			unlock_driver(oldspl);
2199136849Sscottl
2200149871Sscottl			/* KdPrint(("leave scsiio\n")); */
2201149871Sscottl			break;
2202149871Sscottl		}
2203136849Sscottl
2204149871Sscottl		case XPT_RESET_BUS:
2205149871Sscottl			KdPrint(("reset bus\n"));
2206149871Sscottl			oldspl = lock_driver();
2207149871Sscottl			fResetVBus(_VBUS_P0);
2208149871Sscottl			unlock_driver(oldspl);
2209149871Sscottl			xpt_done(ccb);
2210149871Sscottl			break;
2211136849Sscottl
2212149871Sscottl		case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
2213149871Sscottl		case XPT_EN_LUN:		/* Enable LUN as a target */
2214149871Sscottl		case XPT_TARGET_IO:		/* Execute target I/O request */
2215149871Sscottl		case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
2216149871Sscottl		case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
2217149871Sscottl		case XPT_ABORT:			/* Abort the specified CCB */
2218149871Sscottl		case XPT_TERM_IO:		/* Terminate the I/O process */
2219149871Sscottl			/* XXX Implement */
2220149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2221149871Sscottl			xpt_done(ccb);
2222149871Sscottl			break;
2223136849Sscottl
2224149871Sscottl		case XPT_GET_TRAN_SETTINGS:
2225149871Sscottl		case XPT_SET_TRAN_SETTINGS:
2226149871Sscottl			/* XXX Implement */
2227149871Sscottl			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2228149871Sscottl			xpt_done(ccb);
2229149871Sscottl			break;
2230136849Sscottl
2231149871Sscottl		case XPT_CALC_GEOMETRY:
2232149871Sscottl		{
2233149871Sscottl			struct	  ccb_calc_geometry *ccg;
2234149871Sscottl			u_int32_t size_mb;
2235149871Sscottl			u_int32_t secs_per_cylinder;
2236136849Sscottl
2237149871Sscottl			ccg = &ccb->ccg;
2238149871Sscottl			size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);
2239149871Sscottl
2240149871Sscottl			if (size_mb > 1024 ) {
2241149871Sscottl				ccg->heads = 255;
2242149871Sscottl				ccg->secs_per_track = 63;
2243149871Sscottl			} else {
2244149871Sscottl				ccg->heads = 64;
2245149871Sscottl				ccg->secs_per_track = 32;
2246149871Sscottl			}
2247149871Sscottl			secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2248149871Sscottl			ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2249149871Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
2250149871Sscottl			xpt_done(ccb);
2251149871Sscottl			break;
2252136849Sscottl		}
2253136849Sscottl
2254149871Sscottl		case XPT_PATH_INQ:		/* Path routing inquiry */
2255149871Sscottl		{
2256149871Sscottl			struct ccb_pathinq *cpi = &ccb->cpi;
2257136849Sscottl
2258149871Sscottl			cpi->version_num = 1; /* XXX??? */
2259149871Sscottl			cpi->hba_inquiry = PI_SDTR_ABLE;
2260149871Sscottl			cpi->target_sprt = 0;
2261149871Sscottl			/* Not necessary to reset bus */
2262149871Sscottl			cpi->hba_misc = PIM_NOBUSRESET;
2263149871Sscottl			cpi->hba_eng_cnt = 0;
2264136849Sscottl
2265149871Sscottl			cpi->max_target = MAX_VDEVICE_PER_VBUS;
2266149871Sscottl			cpi->max_lun = 0;
2267149871Sscottl			cpi->initiator_id = MAX_VDEVICE_PER_VBUS;
2268136849Sscottl
2269149871Sscottl			cpi->bus_id = cam_sim_bus(sim);
2270149871Sscottl			cpi->base_transfer_speed = 3300;
2271149871Sscottl			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2272149871Sscottl			strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
2273149871Sscottl			strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2274149871Sscottl			cpi->unit_number = cam_sim_unit(sim);
2275149871Sscottl			cpi->ccb_h.status = CAM_REQ_CMP;
2276149871Sscottl			xpt_done(ccb);
2277149871Sscottl			break;
2278149871Sscottl		}
2279136849Sscottl
2280149871Sscottl		default:
2281149871Sscottl			KdPrint(("invalid cmd\n"));
2282149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2283149871Sscottl			xpt_done(ccb);
2284149871Sscottl			break;
2285136849Sscottl	}
2286136849Sscottl	/* KdPrint(("leave hpt_action..............\n")); */
2287136849Sscottl}
2288136849Sscottl
2289136849Sscottl/* shall be called at lock_driver() */
2290136849Sscottlstatic void
2291136849Sscottlhpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb)
2292136849Sscottl{
2293136849Sscottl	if(*ccb_Q == NULL)
2294136849Sscottl		ccb->ccb_h.ccb_ccb_ptr = ccb;
2295136849Sscottl	else {
2296136849Sscottl		ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr;
2297136849Sscottl		(*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb;
2298136849Sscottl	}
2299136849Sscottl
2300136849Sscottl	*ccb_Q = ccb;
2301136849Sscottl}
2302136849Sscottl
2303136849Sscottl/* shall be called at lock_driver() */
2304136849Sscottlstatic void
2305136849Sscottlhpt_free_ccb(union ccb **ccb_Q, union ccb *ccb)
2306136849Sscottl{
2307136849Sscottl	union ccb *TempCCB;
2308136849Sscottl
2309136849Sscottl	TempCCB = *ccb_Q;
2310136849Sscottl
2311149871Sscottl	if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/
2312136849Sscottl		*ccb_Q = NULL;
2313136849Sscottl	else {
2314136849Sscottl		while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb)
2315136849Sscottl			TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr;
2316136849Sscottl
2317136849Sscottl		TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr;
2318136849Sscottl
2319136849Sscottl		if(*ccb_Q == ccb)
2320136849Sscottl			*ccb_Q = TempCCB;
2321136849Sscottl	}
2322136849Sscottl}
2323136849Sscottl
2324136849Sscottl#ifdef SUPPORT_ARRAY
2325136849Sscottl/***************************************************************************
2326136849Sscottl * Function:     hpt_worker_thread
2327136849Sscottl * Description:  Do background rebuilding. Execute in kernel thread context.
2328136849Sscottl * Returns:      None
2329136849Sscottl ***************************************************************************/
2330136849Sscottlstatic void hpt_worker_thread(void)
2331136849Sscottl{
2332136849Sscottl	intrmask_t oldspl;
2333136849Sscottl
2334136849Sscottl	for(;;)	{
2335136849Sscottl		while (DpcQueue_First!=DpcQueue_Last) {
2336136849Sscottl			ST_HPT_DPC p;
2337136849Sscottl			oldspl = lock_driver();
2338136849Sscottl			p = DpcQueue[DpcQueue_First];
2339136849Sscottl			DpcQueue_First++;
2340136849Sscottl			DpcQueue_First %= MAX_DPC;
2341136849Sscottl			DPC_Request_Nums++;
2342136849Sscottl			unlock_driver(oldspl);
2343136849Sscottl			p.dpc(p.pAdapter, p.arg, p.flags);
2344136849Sscottl
2345136849Sscottl			oldspl = lock_driver();
2346136849Sscottl			DPC_Request_Nums--;
2347149871Sscottl			/* since we may have prevented Check_Idle_Call, do it here */
2348136849Sscottl			if (DPC_Request_Nums==0) {
2349136849Sscottl				if (p.pAdapter->outstandingCommands == 0) {
2350136849Sscottl					_VBUS_INST(&p.pAdapter->VBus);
2351136849Sscottl					Check_Idle_Call(p.pAdapter);
2352136849Sscottl					CheckPendingCall(_VBUS_P0);
2353136849Sscottl				}
2354136849Sscottl			}
2355136849Sscottl			unlock_driver(oldspl);
2356136849Sscottl
2357149871Sscottl			/*Schedule out*/
2358149871Sscottl#if (__FreeBSD_version < 500000)
2359149871Sscottl			YIELD_THREAD;
2360149871Sscottl#else
2361167086Sjhb			pause("sched", 1);
2362149871Sscottl#endif
2363149871Sscottl			if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) {
2364149871Sscottl				/* abort rebuilding process. */
2365149871Sscottl				IAL_ADAPTER_T *pAdapter;
2366149871Sscottl				PVDevice      pArray;
2367149871Sscottl				PVBus         _vbus_p;
2368149871Sscottl				int i;
2369149871Sscottl				pAdapter = gIal_Adapter;
2370149871Sscottl
2371149871Sscottl				while(pAdapter != 0){
2372149871Sscottl
2373149871Sscottl					_vbus_p = &pAdapter->VBus;
2374149871Sscottl
2375149871Sscottl					for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
2376149871Sscottl					{
2377149871Sscottl						if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
2378149871Sscottl							continue;
2379149871Sscottl						else if (pArray->u.array.rf_rebuilding ||
2380149871Sscottl								pArray->u.array.rf_verifying ||
2381149871Sscottl								pArray->u.array.rf_initializing)
2382149871Sscottl							{
2383149871Sscottl								pArray->u.array.rf_abort_rebuild = 1;
2384149871Sscottl							}
2385136849Sscottl					}
2386149871Sscottl					pAdapter = pAdapter->next;
2387136849Sscottl				}
2388136849Sscottl			}
2389136849Sscottl		}
2390136849Sscottl
2391149871Sscottl/*Remove this debug option*/
2392149871Sscottl/*
2393136849Sscottl#ifdef DEBUG
2394136849Sscottl		if (SIGISMEMBER(curproc->p_siglist, SIGSTOP))
2395167086Sjhb			pause("hptrdy", 2*hz);
2396136849Sscottl#endif
2397149871Sscottl*/
2398149871Sscottl	#if (__FreeBSD_version >= 500043)
2399172836Sjulian		kproc_suspend_check(curproc);
2400149871Sscottl	#else
2401136849Sscottl		kproc_suspend_loop(curproc);
2402149871Sscottl	#endif
2403167086Sjhb		pause("hptrdy", 2*hz);  /* wait for something to do */
2404136849Sscottl	}
2405136849Sscottl}
2406136849Sscottl
2407136849Sscottlstatic struct proc *hptdaemonproc;
2408136849Sscottlstatic struct kproc_desc hpt_kp = {
2409136849Sscottl	"hpt_wt",
2410136849Sscottl	hpt_worker_thread,
2411136849Sscottl	&hptdaemonproc
2412136849Sscottl};
2413136849Sscottl
2414149871Sscottl/*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/
2415136849Sscottlstatic void
2416136849Sscottllaunch_worker_thread(void)
2417136849Sscottl{
2418136849Sscottl	IAL_ADAPTER_T *pAdapTemp;
2419136849Sscottl
2420136849Sscottl	kproc_start(&hpt_kp);
2421136849Sscottl
2422136849Sscottl	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
2423136849Sscottl
2424136849Sscottl		_VBUS_INST(&pAdapTemp->VBus)
2425136849Sscottl		int i;
2426136849Sscottl		PVDevice pVDev;
2427136849Sscottl
2428136849Sscottl		for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
2429136849Sscottl			if ((pVDev=ArrayTables(i))->u.array.dArStamp==0)
2430136849Sscottl				continue;
2431149871Sscottl			else{
2432149871Sscottl				if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding)
2433149871Sscottl					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev,
2434149871Sscottl					(UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
2435149871Sscottl			}
2436136849Sscottl	}
2437136849Sscottl
2438136849Sscottl	/*
2439149871Sscottl	 * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished.
2440136849Sscottl	 */
2441136849Sscottl#if (__FreeBSD_version < 500043)
2442149871Sscottl	EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST);
2443149871Sscottl#else
2444149871Sscottl	EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, SHUTDOWN_PRI_FIRST);
2445136849Sscottl#endif
2446136849Sscottl}
2447149871Sscottl/*
2448149871Sscottl *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL);
2449149871Sscottl*/
2450136849Sscottl
2451149871Sscottl#endif
2452136849Sscottl
2453136849Sscottl/********************************************************************************/
2454136849Sscottl
2455149871Sscottlint HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical)
2456136849Sscottl{
2457149871Sscottl	union ccb *ccb = (union ccb *)pCmd->pOrgCommand;
2458149871Sscottl	bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
2459136849Sscottl	int idx;
2460136849Sscottl
2461149871Sscottl	if(logical) {
2462149871Sscottl		if (ccb->ccb_h.flags & CAM_DATA_PHYS)
2463149871Sscottl			panic("physical address unsupported");
2464136849Sscottl
2465149871Sscottl		if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
2466149871Sscottl			if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
2467149871Sscottl				panic("physical address unsupported");
2468149871Sscottl
2469149871Sscottl			for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
2470149871Sscottl				pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr;
2471149871Sscottl				pSg[idx].wSgSize = sgList[idx].ds_len;
2472149871Sscottl				pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0;
2473149871Sscottl			}
2474149871Sscottl		}
2475149871Sscottl		else {
2476149871Sscottl			pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr;
2477149871Sscottl			pSg->wSgSize = ccb->csio.dxfer_len;
2478149871Sscottl			pSg->wSgFlag = SG_FLAG_EOT;
2479149871Sscottl		}
2480136849Sscottl		return TRUE;
2481136849Sscottl	}
2482149871Sscottl
2483149871Sscottl	/* since we have provided physical sg, nobody will ask us to build physical sg */
2484149871Sscottl	HPT_ASSERT(0);
2485149871Sscottl	return FALSE;
2486136849Sscottl}
2487136849Sscottl
2488136849Sscottl/*******************************************************************************/
2489136849SscottlULONG HPTLIBAPI
2490136849SscottlGetStamp(void)
2491136849Sscottl{
2492136849Sscottl	/*
2493136849Sscottl	 * the system variable, ticks, can't be used since it hasn't yet been active
2494136849Sscottl	 * when our driver starts (ticks==0, it's a invalid stamp value)
2495136849Sscottl	 */
2496149871Sscottl	ULONG stamp;
2497149871Sscottl	do { stamp = random(); } while (stamp==0);
2498136849Sscottl	return stamp;
2499136849Sscottl}
2500136849Sscottl
2501136849Sscottl
2502136849Sscottlstatic void
2503136849SscottlSetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev)
2504136849Sscottl{
2505136849Sscottl	int i;
2506149871Sscottl	IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice;
2507149871Sscottl
2508136849Sscottl	inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/
2509136849Sscottl	inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5);
2510136849Sscottl#ifndef SERIAL_CMDS
2511136849Sscottl	inquiryData->CommandQueue = 1;
2512136849Sscottl#endif
2513136849Sscottl
2514136849Sscottl	switch(pVDev->VDeviceType) {
2515136849Sscottl	case VD_SINGLE_DISK:
2516136849Sscottl	case VD_ATAPI:
2517136849Sscottl	case VD_REMOVABLE:
2518136849Sscottl		/* Set the removable bit, if applicable. */
2519149871Sscottl		if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80))
2520136849Sscottl			inquiryData->RemovableMedia = 1;
2521136849Sscottl
2522136849Sscottl		/* Fill in vendor identification fields. */
2523149871Sscottl		for (i = 0; i < 20; i += 2) {
2524149871Sscottl			inquiryData->VendorId[i] 	= ((PUCHAR)pIdentify->ModelNumber)[i + 1];
2525149871Sscottl			inquiryData->VendorId[i+1] 	= ((PUCHAR)pIdentify->ModelNumber)[i];
2526136849Sscottl
2527136849Sscottl		}
2528136849Sscottl
2529136849Sscottl		/* Initialize unused portion of product id. */
2530136849Sscottl		for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' ';
2531136849Sscottl
2532136849Sscottl		/* firmware revision */
2533149871Sscottl		for (i = 0; i < 4; i += 2)
2534149871Sscottl		{
2535149871Sscottl			inquiryData->ProductRevisionLevel[i] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i+1];
2536149871Sscottl			inquiryData->ProductRevisionLevel[i+1] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i];
2537136849Sscottl		}
2538136849Sscottl		break;
2539136849Sscottl	default:
2540136849Sscottl		memcpy(&inquiryData->VendorId, "RR182x  ", 8);
2541136849Sscottl#ifdef SUPPORT_ARRAY
2542149871Sscottl		switch(pVDev->VDeviceType){
2543136849Sscottl		case VD_RAID_0:
2544149871Sscottl			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
2545149871Sscottl				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
2546149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 1/0 Array  ", 16);
2547136849Sscottl			else
2548149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 0 Array    ", 16);
2549136849Sscottl			break;
2550136849Sscottl		case VD_RAID_1:
2551149871Sscottl			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
2552149871Sscottl				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
2553149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 0/1 Array  ", 16);
2554136849Sscottl			else
2555149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 1 Array    ", 16);
2556136849Sscottl			break;
2557136849Sscottl		case VD_RAID_5:
2558136849Sscottl			memcpy(&inquiryData->ProductId, "RAID 5 Array    ", 16);
2559136849Sscottl			break;
2560136849Sscottl		case VD_JBOD:
2561136849Sscottl			memcpy(&inquiryData->ProductId, "JBOD Array      ", 16);
2562136849Sscottl			break;
2563136849Sscottl		}
2564136849Sscottl#endif
2565136849Sscottl		memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4);
2566136849Sscottl		break;
2567136849Sscottl	}
2568136849Sscottl}
2569136849Sscottl
2570136849Sscottlstatic void
2571136849Sscottlhpt_timeout(void *arg)
2572136849Sscottl{
2573149871Sscottl	_VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus)
2574149871Sscottl	intrmask_t oldspl = lock_driver();
2575136849Sscottl	fResetVBus(_VBUS_P0);
2576136849Sscottl	unlock_driver(oldspl);
2577136849Sscottl}
2578136849Sscottl
2579149871Sscottlstatic void
2580149871Sscottlhpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
2581149871Sscottl{
2582149871Sscottl	PCommand pCmd = (PCommand)arg;
2583149871Sscottl	union ccb *ccb = pCmd->pOrgCommand;
2584149871Sscottl	struct ccb_hdr *ccb_h = &ccb->ccb_h;
2585149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter;
2586149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2587149871Sscottl	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
2588149871Sscottl	FPSCAT_GATH psg = pCmd->pSgTable;
2589149871Sscottl	int idx;
2590149871Sscottl	_VBUS_INST(pVDev->pVBus)
2591149871Sscottl
2592149871Sscottl	HPT_ASSERT(pCmd->cf_physical_sg);
2593149871Sscottl
2594149871Sscottl	if (error || nsegs == 0)
2595149871Sscottl		panic("busdma error");
2596149871Sscottl
2597149871Sscottl	HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS);
2598149871Sscottl
2599149871Sscottl	for (idx = 0; idx < nsegs; idx++, psg++) {
2600149871Sscottl		psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr;
2601149871Sscottl		psg->wSgSize = segs[idx].ds_len;
2602149871Sscottl		psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0;
2603149871Sscottl/*		KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */
2604149871Sscottl	}
2605149871Sscottl/*	psg[-1].wSgFlag = SG_FLAG_EOT; */
2606149871Sscottl
2607149871Sscottl	if (pCmd->cf_data_in) {
2608149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD);
2609149871Sscottl	}
2610149871Sscottl	else if (pCmd->cf_data_out) {
2611149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE);
2612149871Sscottl	}
2613149871Sscottl
2614149871Sscottl	ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz);
2615149871Sscottl	pVDev->pfnSendCommand(_VBUS_P pCmd);
2616149871Sscottl	CheckPendingCall(_VBUS_P0);
2617149871Sscottl}
2618149871Sscottl
2619149871Sscottl
2620149871Sscottl
2621136849Sscottlstatic void HPTLIBAPI
2622136849SscottlOsSendCommand(_VBUS_ARG union ccb *ccb)
2623136849Sscottl{
2624149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2625149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2626149871Sscottl	struct ccb_hdr *ccb_h = &ccb->ccb_h;
2627149871Sscottl	struct ccb_scsiio *csio = &ccb->csio;
2628149871Sscottl	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
2629136849Sscottl
2630149871Sscottl	KdPrintI(("OsSendCommand: ccb %p  cdb %x-%x-%x\n",
2631136849Sscottl		ccb,
2632136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0],
2633136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4],
2634136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8]
2635136849Sscottl	));
2636136849Sscottl
2637136849Sscottl	pAdapter->outstandingCommands++;
2638136849Sscottl
2639136849Sscottl	if (pVDev == NULL || pVDev->vf_online == 0) {
2640136849Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2641136849Sscottl		ccb_done(ccb);
2642136849Sscottl		goto Command_Complished;
2643136849Sscottl	}
2644136849Sscottl
2645136849Sscottl	switch(ccb->csio.cdb_io.cdb_bytes[0])
2646136849Sscottl	{
2647149871Sscottl		case TEST_UNIT_READY:
2648149871Sscottl		case START_STOP_UNIT:
2649149871Sscottl		case SYNCHRONIZE_CACHE:
2650149871Sscottl			/* FALLTHROUGH */
2651149871Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
2652149871Sscottl			break;
2653136849Sscottl
2654149871Sscottl		case INQUIRY:
2655149871Sscottl			ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len);
2656149871Sscottl			SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev);
2657149871Sscottl			ccb_h->status = CAM_REQ_CMP;
2658149871Sscottl			break;
2659136849Sscottl
2660149871Sscottl		case READ_CAPACITY:
2661149871Sscottl		{
2662149871Sscottl			UCHAR swip[4];
2663149871Sscottl			/* Claim 512 byte blocks (big-endian). */
2664149871Sscottl			((PREAD_CAPACITY_DATA)csio->data_ptr)->BytesPerBlock = 0x20000;
2665149871Sscottl			*(ULONG*)swip = pVDev->VDeviceCapacity - 1;
2666149871Sscottl			((PREAD_CAPACITY_DATA)csio->data_ptr)->LogicalBlockAddress =
2667149871Sscottl				(swip[0] << 24) |  (swip[1] << 16) | (swip[2] << 8) | swip[3];
2668149871Sscottl			ccb_h->status = CAM_REQ_CMP;
2669149871Sscottl			break;
2670136849Sscottl		}
2671136849Sscottl
2672136849Sscottl		case READ_6:
2673136849Sscottl		case WRITE_6:
2674136849Sscottl		case READ_10:
2675136849Sscottl		case WRITE_10:
2676136849Sscottl		case 0x13:
2677136849Sscottl		case 0x2f:
2678149871Sscottl		{
2679149871Sscottl			UCHAR Cdb[16];
2680149871Sscottl			UCHAR CdbLength;
2681149871Sscottl			_VBUS_INST(pVDev->pVBus)
2682149871Sscottl			PCommand pCmd = AllocateCommand(_VBUS_P0);
2683149871Sscottl			HPT_ASSERT(pCmd);
2684136849Sscottl
2685149871Sscottl			CdbLength = csio->cdb_len;
2686149871Sscottl			if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
2687149871Sscottl			{
2688149871Sscottl				if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0)
2689149871Sscottl				{
2690149871Sscottl					bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength);
2691149871Sscottl				}
2692149871Sscottl				else
2693149871Sscottl				{
2694149871Sscottl					KdPrintE(("ERROR!!!\n"));
2695149871Sscottl					ccb->ccb_h.status = CAM_REQ_INVALID;
2696149871Sscottl					break;
2697149871Sscottl				}
2698149871Sscottl			}
2699149871Sscottl			else
2700149871Sscottl			{
2701149871Sscottl				bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength);
2702149871Sscottl			}
2703136849Sscottl
2704149871Sscottl			pCmd->pOrgCommand = ccb;
2705149871Sscottl			pCmd->pVDevice = pVDev;
2706149871Sscottl			pCmd->pfnCompletion = fOsCommandDone;
2707149871Sscottl			pCmd->pfnBuildSgl = fOsBuildSgl;
2708149871Sscottl			pCmd->pSgTable = pmap->psg;
2709136849Sscottl
2710149871Sscottl			switch (Cdb[0])
2711149871Sscottl			{
2712149871Sscottl				case READ_6:
2713149871Sscottl				case WRITE_6:
2714149871Sscottl				case 0x13:
2715149871Sscottl					pCmd->uCmd.Ide.Lba =  ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3];
2716149871Sscottl					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4];
2717149871Sscottl					break;
2718149871Sscottl
2719149871Sscottl				default:
2720149871Sscottl					pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24);
2721149871Sscottl					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8);
2722149871Sscottl					break;
2723149871Sscottl			}
2724149871Sscottl
2725149871Sscottl			switch (Cdb[0])
2726149871Sscottl			{
2727149871Sscottl				case READ_6:
2728149871Sscottl				case READ_10:
2729149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_READ;
2730149871Sscottl					pCmd->cf_data_in = 1;
2731149871Sscottl					break;
2732149871Sscottl
2733149871Sscottl				case WRITE_6:
2734149871Sscottl				case WRITE_10:
2735149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE;
2736149871Sscottl					pCmd->cf_data_out = 1;
2737149871Sscottl					break;
2738149871Sscottl				case 0x13:
2739149871Sscottl				case 0x2f:
2740149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY;
2741149871Sscottl					break;
2742149871Sscottl			}
2743149871Sscottl/*///////////////////////// */
2744149871Sscottl			if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
2745149871Sscottl				int idx;
2746149871Sscottl				bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
2747149871Sscottl
2748149871Sscottl				if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
2749149871Sscottl					pCmd->cf_physical_sg = 1;
2750149871Sscottl
2751149871Sscottl				for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
2752149871Sscottl					pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr;
2753149871Sscottl					pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len;
2754149871Sscottl					pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0;
2755149871Sscottl				}
2756149871Sscottl
2757149871Sscottl				ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz);
2758149871Sscottl				pVDev->pfnSendCommand(_VBUS_P pCmd);
2759149871Sscottl			}
2760149871Sscottl			else {
2761149871Sscottl				int error;
2762149871Sscottl				pCmd->cf_physical_sg = 1;
2763149871Sscottl				error = bus_dmamap_load(pAdapter->io_dma_parent,
2764149871Sscottl							pmap->dma_map,
2765149871Sscottl							ccb->csio.data_ptr, ccb->csio.dxfer_len,
2766149871Sscottl							hpt_io_dmamap_callback, pCmd,
2767149871Sscottl					    		BUS_DMA_WAITOK
2768149871Sscottl						);
2769149871Sscottl				KdPrint(("bus_dmamap_load return %d\n", error));
2770149871Sscottl				if (error && error!=EINPROGRESS) {
2771149871Sscottl					hpt_printk(("bus_dmamap_load error %d\n", error));
2772149871Sscottl					FreeCommand(_VBUS_P pCmd);
2773149871Sscottl					ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2774149871Sscottl					dmamap_put(pmap);
2775149871Sscottl					pAdapter->outstandingCommands--;
2776149871Sscottl					xpt_done(ccb);
2777149871Sscottl				}
2778149871Sscottl			}
2779149871Sscottl			goto Command_Complished;
2780149871Sscottl		}
2781149871Sscottl
2782149871Sscottl		default:
2783149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2784149871Sscottl			break;
2785136849Sscottl	}
2786136849Sscottl	ccb_done(ccb);
2787136849SscottlCommand_Complished:
2788136849Sscottl	CheckPendingCall(_VBUS_P0);
2789136849Sscottl	return;
2790136849Sscottl}
2791136849Sscottl
2792149871Sscottlstatic void HPTLIBAPI
2793136849SscottlfOsCommandDone(_VBUS_ARG PCommand pCmd)
2794136849Sscottl{
2795149871Sscottl	union ccb *ccb = pCmd->pOrgCommand;
2796149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2797149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2798136849Sscottl
2799149871Sscottl	KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result));
2800136849Sscottl
2801136849Sscottl	untimeout(hpt_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch);
2802136849Sscottl
2803136849Sscottl	switch(pCmd->Result) {
2804136849Sscottl	case RETURN_SUCCESS:
2805136849Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2806136849Sscottl		break;
2807136849Sscottl	case RETURN_BAD_DEVICE:
2808136849Sscottl		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2809136849Sscottl		break;
2810136849Sscottl	case RETURN_DEVICE_BUSY:
2811136849Sscottl		ccb->ccb_h.status = CAM_BUSY;
2812136849Sscottl		break;
2813136849Sscottl	case RETURN_INVALID_REQUEST:
2814136849Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2815136849Sscottl		break;
2816136849Sscottl	case RETURN_SELECTION_TIMEOUT:
2817136849Sscottl		ccb->ccb_h.status = CAM_SEL_TIMEOUT;
2818136849Sscottl		break;
2819136849Sscottl	case RETURN_RETRY:
2820136849Sscottl		ccb->ccb_h.status = CAM_BUSY;
2821136849Sscottl		break;
2822136849Sscottl	default:
2823136849Sscottl		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
2824136849Sscottl		break;
2825136849Sscottl	}
2826136849Sscottl
2827149871Sscottl	if (pCmd->cf_data_in) {
2828149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD);
2829136849Sscottl	}
2830149871Sscottl	else if (pCmd->cf_data_in) {
2831149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE);
2832149871Sscottl	}
2833149871Sscottl
2834149871Sscottl	bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map);
2835136849Sscottl
2836136849Sscottl	FreeCommand(_VBUS_P pCmd);
2837136849Sscottl	ccb_done(ccb);
2838136849Sscottl}
2839136849Sscottl
2840136849Sscottlint
2841136849Sscottlhpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags)
2842136849Sscottl{
2843136849Sscottl	int p;
2844136849Sscottl
2845136849Sscottl	p = (DpcQueue_Last + 1) % MAX_DPC;
2846136849Sscottl	if (p==DpcQueue_First) {
2847136849Sscottl		KdPrint(("DPC Queue full!\n"));
2848136849Sscottl		return -1;
2849136849Sscottl	}
2850136849Sscottl
2851136849Sscottl	DpcQueue[DpcQueue_Last].dpc = dpc;
2852136849Sscottl	DpcQueue[DpcQueue_Last].pAdapter = pAdapter;
2853136849Sscottl	DpcQueue[DpcQueue_Last].arg = arg;
2854136849Sscottl	DpcQueue[DpcQueue_Last].flags = flags;
2855136849Sscottl	DpcQueue_Last = p;
2856136849Sscottl
2857136849Sscottl	return 0;
2858136849Sscottl}
2859136849Sscottl
2860136849Sscottl#ifdef _RAID5N_
2861136849Sscottl/*
2862149871Sscottl * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices.
2863149871Sscottl * How about the memory for 5081 request/response array and PRD table?
2864136849Sscottl */
2865136849Sscottlvoid
2866136849Sscottl*os_alloc_page(_VBUS_ARG0)
2867136849Sscottl{
2868149871Sscottl	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
2869136849Sscottl}
2870149871Sscottl
2871136849Sscottlvoid
2872136849Sscottl*os_alloc_dma_page(_VBUS_ARG0)
2873136849Sscottl{
2874149871Sscottl	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
2875136849Sscottl}
2876136849Sscottl
2877136849Sscottlvoid
2878149871Sscottlos_free_page(_VBUS_ARG void *p)
2879149871Sscottl{
2880149871Sscottl	contigfree(p, 0x1000, M_DEVBUF);
2881136849Sscottl}
2882136849Sscottl
2883136849Sscottlvoid
2884149871Sscottlos_free_dma_page(_VBUS_ARG void *p)
2885149871Sscottl{
2886149871Sscottl	contigfree(p, 0x1000, M_DEVBUF);
2887136849Sscottl}
2888136849Sscottl
2889136849Sscottlvoid
2890136849SscottlDoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes)
2891136849Sscottl{
2892136849Sscottl	UINT i;
2893149871Sscottl	for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++;
2894136849Sscottl}
2895136849Sscottl
2896136849Sscottlvoid
2897136849SscottlDoXor2(ULONG *p0, ULONG *p2, UINT nBytes)
2898136849Sscottl{
2899136849Sscottl	UINT i;
2900149871Sscottl	for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++;
2901136849Sscottl}
2902136849Sscottl#endif
2903