entry.c revision 149871
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 149871 2005-09-07 23:33:26Z scottl $
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 <machine/clock.h>
54149871Sscottl#include <sys/wait.h>
55149871Sscottl#include <sys/sysproto.h>
56149871Sscottl#endif
57136849Sscottl
58149871Sscottl#ifndef __KERNEL__
59149871Sscottl#define __KERNEL__
60149871Sscottl#endif
61149871Sscottl
62136849Sscottl#include <dev/hptmv/global.h>
63136849Sscottl#include <dev/hptmv/hptintf.h>
64136849Sscottl#include <dev/hptmv/osbsd.h>
65143039Sscottl#include <dev/hptmv/access601.h>
66136849Sscottl
67149871Sscottl
68136849Sscottl#ifdef DEBUG
69136849Sscottl#ifdef DEBUG_LEVEL
70136849Sscottlint hpt_dbg_level = DEBUG_LEVEL;
71149871Sscottl#else
72136849Sscottlint hpt_dbg_level = 0;
73136849Sscottl#endif
74136849Sscottl#endif
75136849Sscottl
76136849Sscottl#define MV_ERROR printf
77149871Sscottl
78136849Sscottl/*
79136849Sscottl * CAM SIM entry points
80136849Sscottl */
81149871Sscottlstatic int 	hpt_probe (device_t dev);
82149871Sscottlstatic void launch_worker_thread(void);
83149871Sscottlstatic int 	hpt_attach(device_t dev);
84149871Sscottlstatic int 	hpt_detach(device_t dev);
85149871Sscottlstatic int 	hpt_shutdown(device_t dev);
86149871Sscottlstatic void hpt_poll(struct cam_sim *sim);
87149871Sscottlstatic void hpt_intr(void *arg);
88149871Sscottlstatic void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
89149871Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb);
90149871Sscottl
91149871Sscottlstatic device_method_t driver_methods[] = {
92149871Sscottl	/* Device interface */
93149871Sscottl	DEVMETHOD(device_probe,		hpt_probe),
94149871Sscottl	DEVMETHOD(device_attach,	hpt_attach),
95149871Sscottl	DEVMETHOD(device_detach,	hpt_detach),
96149871Sscottl
97149871Sscottl/*	DEVMETHOD(device_shutdown,	hpt_shutdown), */
98149871Sscottl	{ 0, 0 }
99149871Sscottl};
100149871Sscottl
101149871Sscottlstatic driver_t hpt_pci_driver = {
102149871Sscottl	__str(PROC_DIR_NAME),
103149871Sscottl	driver_methods,
104149871Sscottl	sizeof(IAL_ADAPTER_T)
105149871Sscottl};
106149871Sscottl
107149871Sscottlstatic devclass_t	hpt_devclass;
108149871Sscottl
109149871Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6)
110149871Sscottl__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0);
111149871Sscottl
112149871Sscottl#define ccb_ccb_ptr spriv_ptr0
113149871Sscottl#define ccb_adapter ccb_h.spriv_ptr1
114149871Sscottl
115149871Sscottlstatic void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev);
116149871Sscottlstatic void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb);
117149871Sscottlstatic void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd);
118149871Sscottlstatic void ccb_done(union ccb *ccb);
119149871Sscottlstatic void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb);
120149871Sscottlstatic void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb);
121136849Sscottlstatic void	hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter);
122136849Sscottlstatic void	hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
123136849Sscottlstatic void	handleEdmaError(_VBUS_ARG PCommand pCmd);
124136849Sscottlstatic int	hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
125136849Sscottlstatic int	fResetActiveCommands(PVBus _vbus_p);
126136849Sscottlstatic void	fRegisterVdevice(IAL_ADAPTER_T *pAdapter);
127136849Sscottlstatic int	hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter);
128136849Sscottlstatic void	hptmv_handle_event_disconnect(void *data);
129136849Sscottlstatic void	hptmv_handle_event_connect(void *data);
130136849Sscottlstatic int	start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum);
131136849Sscottlstatic void	init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel);
132136849Sscottlstatic int	hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel);
133136849Sscottlstatic int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg,
134136849Sscottl    int logical);
135136849Sscottlstatic MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
136136849Sscottl    MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId,
137136849Sscottl    MV_U16 responseFlags, MV_U32 timeStamp,
138136849Sscottl    MV_STORAGE_DEVICE_REGISTERS *registerStruct);
139136849Sscottlstatic MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter,
140136849Sscottl    MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2);
141136849Sscottl
142136849Sscottl#define ccb_ccb_ptr spriv_ptr0
143136849Sscottl#define ccb_adapter ccb_h.spriv_ptr1
144136849Sscottl
145136849SscottlIAL_ADAPTER_T *gIal_Adapter = 0;
146136849SscottlIAL_ADAPTER_T *pCurAdapter = 0;
147149871Sscottlstatic MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM];
148136849Sscottl
149136849Sscottltypedef struct st_HPT_DPC {
150136849Sscottl	IAL_ADAPTER_T *pAdapter;
151136849Sscottl	void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR);
152136849Sscottl	void *arg;
153136849Sscottl	UCHAR flags;
154136849Sscottl} ST_HPT_DPC;
155136849Sscottl
156136849Sscottl#define MAX_DPC 16
157136849SscottlUCHAR DPC_Request_Nums = 0;
158136849Sscottlstatic ST_HPT_DPC DpcQueue[MAX_DPC];
159136849Sscottlstatic int DpcQueue_First=0;
160136849Sscottlstatic int DpcQueue_Last = 0;
161136849Sscottl
162149871Sscottlchar DRIVER_VERSION[] = "v1.12 (" __DATE__ " " __TIME__ ")";
163136849Sscottl
164149871Sscottl#if (__FreeBSD_version >= 500000)
165149871Sscottlstatic struct mtx driver_lock;
166149871Sscottlintrmask_t lock_driver()
167149871Sscottl{
168136849Sscottl
169149871Sscottl	intrmask_t spl = 0;
170149871Sscottl	mtx_lock_spin(&driver_lock);
171149871Sscottl	return spl;
172149871Sscottl}
173149871Sscottlvoid unlock_driver(intrmask_t spl)
174136849Sscottl{
175149871Sscottl	mtx_unlock_spin(&driver_lock);
176149871Sscottl}
177149871Sscottl#else
178149871Sscottlstatic int driver_locked = 0;
179149871Sscottlintrmask_t lock_driver()
180149871Sscottl{
181136849Sscottl	intrmask_t spl = splcam();
182149871Sscottlloop:
183149871Sscottl	while (driver_locked)
184149871Sscottl		tsleep(&driver_locked, PRIBIO, "hptlck", hz);
185149871Sscottl	atomic_add_int(&driver_locked, 1);
186149871Sscottl	if (driver_locked>1) {
187149871Sscottl		atomic_subtract_int(&driver_locked, 1);
188149871Sscottl		goto loop;
189149871Sscottl	}
190136849Sscottl	return spl;
191136849Sscottl}
192136849Sscottl
193149871Sscottlvoid unlock_driver(intrmask_t spl)
194136849Sscottl{
195149871Sscottl	atomic_subtract_int(&driver_locked, 1);
196149871Sscottl	if (driver_locked==0) {
197149871Sscottl		wakeup(&driver_locked);
198149871Sscottl	}
199136849Sscottl	splx(spl);
200136849Sscottl}
201149871Sscottl#endif
202136849Sscottl
203136849Sscottl/*******************************************************************************
204136849Sscottl *	Name:	hptmv_free_channel
205136849Sscottl *
206136849Sscottl *	Description:	free allocated queues for the given channel
207136849Sscottl *
208136849Sscottl *	Parameters:    	pMvSataAdapter - pointer to the RR182x controler this
209136849Sscottl * 					channel connected to.
210136849Sscottl *			channelNum - channel number.
211136849Sscottl *
212136849Sscottl ******************************************************************************/
213136849Sscottlstatic void
214136849Sscottlhptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
215136849Sscottl{
216136849Sscottl	HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM);
217136849Sscottl	pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL;
218149871Sscottl}
219136849Sscottl
220149871Sscottlstatic void failDevice(PVDevice pVDev)
221149871Sscottl{
222149871Sscottl	PVBus _vbus_p = pVDev->pVBus;
223149871Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
224149871Sscottl
225149871Sscottl	pVDev->u.disk.df_on_line = 0;
226149871Sscottl	pVDev->vf_online = 0;
227149871Sscottl	if (pVDev->pfnDeviceFailed)
228149871Sscottl		CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev);
229149871Sscottl
230149871Sscottl	fNotifyGUI(ET_DEVICE_REMOVED, pVDev);
231149871Sscottl
232149871Sscottl#ifndef FOR_DEMO
233149871Sscottl	if (pAdapter->ver_601==2 && !pAdapter->beeping) {
234149871Sscottl		pAdapter->beeping = 1;
235149871Sscottl		BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress);
236149871Sscottl		set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1);
237136849Sscottl	}
238149871Sscottl#endif
239136849Sscottl}
240136849Sscottl
241136849Sscottlint MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel);
242149871Sscottl/*void fDeviceSendCommand(_VBUS_ARG PCommand pCmd); */
243136849Sscottl
244136849Sscottlstatic void
245136849SscottlhandleEdmaError(_VBUS_ARG PCommand pCmd)
246136849Sscottl{
247136849Sscottl	PDevice pDevice = &pCmd->pVDevice->u.disk;
248136849Sscottl	MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter;
249136849Sscottl
250136849Sscottl	if (!pDevice->df_on_line) {
251136849Sscottl		KdPrint(("Device is offline"));
252136849Sscottl		pCmd->Result = RETURN_BAD_DEVICE;
253136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
254136849Sscottl		return;
255136849Sscottl	}
256136849Sscottl
257136849Sscottl	if (pCmd->RetryCount++>5) {
258149871Sscottl		hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber));
259149871Sscottlfailed:
260149871Sscottl		failDevice(pCmd->pVDevice);
261136849Sscottl		pCmd->Result = RETURN_IDE_ERROR;
262136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
263136849Sscottl		return;
264136849Sscottl	}
265149871Sscottl
266149871Sscottl	/* reset the channel and retry the command */
267149871Sscottl	if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber))
268149871Sscottl		goto failed;
269149871Sscottl
270149871Sscottl	fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice));
271149871Sscottl
272149871Sscottl	hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber));
273136849Sscottl	fDeviceSendCommand(_VBUS_P pCmd);
274136849Sscottl}
275136849Sscottl
276136849Sscottl/****************************************************************
277136849Sscottl *	Name:	hptmv_init_channel
278136849Sscottl *
279149871Sscottl *	Description:	allocate request and response queues for the EDMA of the
280149871Sscottl *					given channel and sets other fields.
281149871Sscottl *
282136849Sscottl *	Parameters:
283136849Sscottl *		pAdapter - pointer to the emulated adapter data structure
284136849Sscottl *		channelNum - channel number.
285136849Sscottl *	Return:	0 on success, otherwise on failure
286136849Sscottl ****************************************************************/
287136849Sscottlstatic int
288136849Sscottlhptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
289136849Sscottl{
290136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
291136849Sscottl	dma_addr_t    req_dma_addr;
292136849Sscottl	dma_addr_t    rsp_dma_addr;
293136849Sscottl
294136849Sscottl	if (channelNum >= MV_SATA_CHANNELS_NUM)
295136849Sscottl	{
296136849Sscottl		MV_ERROR("RR182x[%d]: Bad channelNum=%d",
297136849Sscottl				 pAdapter->mvSataAdapter.adapterId, channelNum);
298136849Sscottl		return -1;
299136849Sscottl	}
300136849Sscottl
301149871Sscottl	pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum];
302136849Sscottl	pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel;
303136849Sscottl	pMvSataChannel->channelNumber = channelNum;
304136849Sscottl	pMvSataChannel->lba48Address = MV_FALSE;
305136849Sscottl	pMvSataChannel->maxReadTransfer = MV_FALSE;
306136849Sscottl
307149871Sscottl	pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *)
308149871Sscottl								   (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE));
309149871Sscottl	req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE);
310136849Sscottl
311136849Sscottl
312149871Sscottl	KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr));
313136849Sscottl
314136849Sscottl	/* check the 1K alignment of the request queue*/
315136849Sscottl	if (req_dma_addr & 0x3ff)
316136849Sscottl	{
317149871Sscottl		MV_ERROR("RR182x[%d]: request queue allocated isn't 1 K aligned,"
318149871Sscottl				 " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId,
319149871Sscottl				 (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum);
320136849Sscottl		return -1;
321136849Sscottl	}
322136849Sscottl	pMvSataChannel->requestQueuePciLowAddress = req_dma_addr;
323136849Sscottl	pMvSataChannel->requestQueuePciHiAddress = 0;
324136849Sscottl	KdPrint(("RR182x[%d,%d]: request queue allocated: 0x%p",
325149871Sscottl			  pAdapter->mvSataAdapter.adapterId, channelNum,
326149871Sscottl			  pMvSataChannel->requestQueue));
327149871Sscottl	pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *)
328149871Sscottl									(pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE));
329149871Sscottl	rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE);
330136849Sscottl
331136849Sscottl	/* check the 256 alignment of the response queue*/
332136849Sscottl	if (rsp_dma_addr & 0xff)
333136849Sscottl	{
334149871Sscottl		MV_ERROR("RR182x[%d,%d]: response queue allocated isn't 256 byte "
335149871Sscottl				 "aligned, dma_addr=%llx\n",
336149871Sscottl				 pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr);
337136849Sscottl		return -1;
338136849Sscottl	}
339136849Sscottl	pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr;
340136849Sscottl	pMvSataChannel->responseQueuePciHiAddress = 0;
341136849Sscottl	KdPrint(("RR182x[%d,%d]: response queue allocated: 0x%p",
342149871Sscottl			  pAdapter->mvSataAdapter.adapterId, channelNum,
343149871Sscottl			  pMvSataChannel->responseQueue));
344136849Sscottl
345136849Sscottl	pAdapter->mvChannel[channelNum].online = MV_TRUE;
346136849Sscottl	return 0;
347136849Sscottl}
348136849Sscottl
349136849Sscottl/******************************************************************************
350136849Sscottl *	Name: hptmv_parse_identify_results
351136849Sscottl *
352149871Sscottl *	Description:	this functions parses the identify command results, checks
353149871Sscottl *					that the connected deives can be accesed by RR182x EDMA,
354149871Sscottl *					and updates the channel stucture accordingly.
355149871Sscottl *
356136849Sscottl *	Parameters:     pMvSataChannel, pointer to the channel data structure.
357136849Sscottl *
358136849Sscottl *	Returns:       	=0 ->success, < 0 ->failure.
359136849Sscottl *
360136849Sscottl ******************************************************************************/
361136849Sscottlstatic int
362136849Sscottlhptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel)
363136849Sscottl{
364136849Sscottl	MV_U16  *iden = pMvSataChannel->identifyDevice;
365136849Sscottl
366136849Sscottl	/*LBA addressing*/
367149871Sscottl	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200))
368149871Sscottl	{
369136849Sscottl		KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n"));
370136849Sscottl		return -1;
371149871Sscottl	}
372149871Sscottl	else
373149871Sscottl	{
374136849Sscottl		KdPrint(("%25s - %s\n", "Capabilities", "LBA supported"));
375136849Sscottl	}
376136849Sscottl	/*DMA support*/
377149871Sscottl	if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100))
378149871Sscottl	{
379136849Sscottl		KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n"));
380136849Sscottl		return -1;
381149871Sscottl	}
382149871Sscottl	else
383149871Sscottl	{
384136849Sscottl		KdPrint(("%25s - %s\n", "Capabilities", "DMA supported"));
385136849Sscottl	}
386136849Sscottl	/* PIO */
387149871Sscottl	if ((iden[IDEN_VALID] & 2) == 0)
388149871Sscottl	{
389149871Sscottl		KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n"));
390136849Sscottl		return -1;
391136849Sscottl	}
392136849Sscottl	KdPrint(("%25s - 0x%02x\n", "PIO modes supported",
393136849Sscottl			  iden[IDEN_PIO_MODE_SPPORTED] & 0xff));
394136849Sscottl
395136849Sscottl	/*UDMA*/
396149871Sscottl	if ((iden[IDEN_VALID] & 4) == 0)
397149871Sscottl	{
398149871Sscottl		KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n"));
399136849Sscottl		return -1;
400136849Sscottl	}
401136849Sscottl
402136849Sscottl	/* 48 bit address */
403149871Sscottl	if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400))
404149871Sscottl	{
405136849Sscottl		KdPrint(("%25s - %s\n", "LBA48 addressing", "supported"));
406136849Sscottl		pMvSataChannel->lba48Address = MV_TRUE;
407149871Sscottl	}
408149871Sscottl	else
409149871Sscottl	{
410136849Sscottl		KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported"));
411136849Sscottl		pMvSataChannel->lba48Address = MV_FALSE;
412136849Sscottl	}
413136849Sscottl	return 0;
414136849Sscottl}
415136849Sscottl
416136849Sscottlstatic void
417136849Sscottlinit_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel)
418136849Sscottl{
419149871Sscottl	PVDevice pVDev = &pAdapter->VDevices[channel];
420149871Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel];
421149871Sscottl	MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice;
422136849Sscottl
423136849Sscottl	pMvSataChannel->outstandingCommands = 0;
424136849Sscottl
425136849Sscottl	pVDev->u.disk.mv         = pMvSataChannel;
426136849Sscottl	pVDev->u.disk.df_on_line = 1;
427136849Sscottl	pVDev->u.disk.pVBus      = &pAdapter->VBus;
428136849Sscottl	pVDev->pVBus             = &pAdapter->VBus;
429136849Sscottl
430136849Sscottl#ifdef SUPPORT_48BIT_LBA
431136849Sscottl	if (pMvSataChannel->lba48Address == MV_TRUE)
432149871Sscottl		pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1;
433136849Sscottl	else
434136849Sscottl#endif
435136849Sscottl	if(IdentifyData[53] & 1) {
436149871Sscottl	pVDev->u.disk.dDeRealCapacity =
437149871Sscottl	  (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ?
438149871Sscottl		  (IdentifyData[61]<<16 | IdentifyData[60]) :
439149871Sscottl				(IdentifyData[58]<<16 | IdentifyData[57])) - 1;
440136849Sscottl	} else
441136849Sscottl		pVDev->u.disk.dDeRealCapacity =
442149871Sscottl				 (IdentifyData[61]<<16 | IdentifyData[60]) - 1;
443136849Sscottl
444136849Sscottl	pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
445149871Sscottl		pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0;
446136849Sscottl
447136849Sscottl	if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) {
448136849Sscottl		pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting =
449149871Sscottl			pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8;
450136849Sscottl	}
451136849Sscottl}
452136849Sscottl
453149871Sscottlstatic void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged)
454136849Sscottl{
455136849Sscottl	PVDevice pVDev;
456149871Sscottl	MV_SATA_ADAPTER  *pMvSataAdapter = &pAdapter->mvSataAdapter;
457149871Sscottl	MV_SATA_CHANNEL  *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex];
458149871Sscottl
459149871Sscottl	if (!pMvSataChannel) return;
460136849Sscottl
461149871Sscottl	if (plugged)
462149871Sscottl	{
463136849Sscottl		pVDev = &(pAdapter->VDevices[channelIndex]);
464136849Sscottl		init_vdev_params(pAdapter, channelIndex);
465136849Sscottl
466149871Sscottl		pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI :
467149871Sscottl			pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
468136849Sscottl
469149871Sscottl		pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO;
470136849Sscottl		pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
471136849Sscottl		pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
472136849Sscottl		pVDev->vf_online = 1;
473136849Sscottl
474136849Sscottl#ifdef SUPPORT_ARRAY
475149871Sscottl		if(pVDev->pParent)
476149871Sscottl		{
477136849Sscottl			int iMember;
478149871Sscottl			for(iMember = 0; iMember < 	pVDev->pParent->u.array.bArnMember; iMember++)
479149871Sscottl				if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev)
480136849Sscottl					pVDev->pParent->u.array.pMember[iMember] = NULL;
481136849Sscottl			pVDev->pParent = NULL;
482136849Sscottl		}
483136849Sscottl#endif
484136849Sscottl		fNotifyGUI(ET_DEVICE_PLUGGED,pVDev);
485136849Sscottl		fCheckBootable(pVDev);
486136849Sscottl		RegisterVDevice(pVDev);
487136849Sscottl
488136849Sscottl#ifndef FOR_DEMO
489136849Sscottl		if (pAdapter->beeping) {
490136849Sscottl			pAdapter->beeping = 0;
491136849Sscottl			BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
492136849Sscottl		}
493136849Sscottl#endif
494136849Sscottl
495149871Sscottl	}
496149871Sscottl	else
497149871Sscottl	{
498136849Sscottl		pVDev  = &(pAdapter->VDevices[channelIndex]);
499149871Sscottl		failDevice(pVDev);
500136849Sscottl	}
501136849Sscottl}
502136849Sscottl
503136849Sscottlstatic int
504136849Sscottlstart_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
505136849Sscottl{
506149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
507149871Sscottl	MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum];
508149871Sscottl	MV_CHANNEL		*pChannelInfo = &(pAdapter->mvChannel[channelNum]);
509149871Sscottl	MV_U32          udmaMode,pioMode;
510136849Sscottl
511136849Sscottl	KdPrint(("RR182x [%d]: start channel (%d)", pMvSataAdapter->adapterId,
512149871Sscottl			 channelNum));
513136849Sscottl
514136849Sscottl
515136849Sscottl	/* Software reset channel */
516149871Sscottl	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
517149871Sscottl	{
518136849Sscottl		MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n",
519149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
520136849Sscottl		return -1;
521136849Sscottl	}
522136849Sscottl
523136849Sscottl	/* Hardware reset channel */
524149871Sscottl	if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
525149871Sscottl	{
526149871Sscottl		/* If failed, try again - this is when trying to hardreset a channel */
527149871Sscottl		/* when drive is just spinning up */
528136849Sscottl		StallExec(5000000); /* wait 5 sec before trying again */
529149871Sscottl		if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
530149871Sscottl		{
531149871Sscottl			MV_ERROR("RR182x [%d,%d]: failed to perform Hard reset\n",
532149871Sscottl					 pMvSataAdapter->adapterId, channelNum);
533136849Sscottl			return -1;
534136849Sscottl		}
535136849Sscottl	}
536136849Sscottl
537136849Sscottl	/* identify device*/
538149871Sscottl	if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE)
539149871Sscottl	{
540149871Sscottl		MV_ERROR("RR182x [%d,%d]: failed to perform ATA Identify command\n"
541149871Sscottl				 , pMvSataAdapter->adapterId, channelNum);
542136849Sscottl		return -1;
543136849Sscottl	}
544149871Sscottl	if (hptmv_parse_identify_results(pMvSataChannel))
545149871Sscottl	{
546149871Sscottl		MV_ERROR("RR182x [%d,%d]: Error in parsing ATA Identify message\n"
547149871Sscottl				 , pMvSataAdapter->adapterId, channelNum);
548136849Sscottl		return -1;
549136849Sscottl	}
550136849Sscottl
551136849Sscottl	/* mvStorageDevATASetFeatures */
552136849Sscottl	/* Disable 8 bit PIO in case CFA enabled */
553149871Sscottl	if (pMvSataChannel->identifyDevice[86] & 4)
554149871Sscottl	{
555136849Sscottl		KdPrint(("RR182x [%d]: Disable 8 bit PIO (CFA enabled) \n",
556149871Sscottl				  pMvSataAdapter->adapterId));
557136849Sscottl		if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
558149871Sscottl									   MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0,
559149871Sscottl									   0, 0, 0) == MV_FALSE)
560149871Sscottl		{
561149871Sscottl			MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures"
562149871Sscottl					 " failed\n", pMvSataAdapter->adapterId, channelNum);
563136849Sscottl			return -1;
564136849Sscottl		}
565136849Sscottl	}
566149871Sscottl	/* Write cache */
567136849Sscottl#ifdef ENABLE_WRITE_CACHE
568149871Sscottl	if (pMvSataChannel->identifyDevice[82] & 0x20)
569149871Sscottl	{
570149871Sscottl		if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */
571149871Sscottl		{
572149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
573149871Sscottl										   MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0,
574149871Sscottl										   0, 0, 0) == MV_FALSE)
575149871Sscottl			{
576149871Sscottl				MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
577149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
578136849Sscottl				return -1;
579136849Sscottl			}
580136849Sscottl		}
581136849Sscottl		KdPrint(("RR182x [%d]: channel %d, write cache enabled\n",
582149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
583149871Sscottl	}
584149871Sscottl	else
585149871Sscottl	{
586136849Sscottl		KdPrint(("RR182x [%d]: channel %d, write cache not supported\n",
587149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
588136849Sscottl	}
589149871Sscottl#else /* disable write cache */
590149871Sscottl	{
591149871Sscottl		if (pMvSataChannel->identifyDevice[85] & 0x20)
592149871Sscottl		{
593149871Sscottl			KdPrint(("RR182x [%d]: channel =%d, disable write cache\n",
594149871Sscottl					  pMvSataAdapter->adapterId, channelNum));
595149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
596149871Sscottl										   MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0,
597149871Sscottl										   0, 0, 0) == MV_FALSE)
598149871Sscottl			{
599149871Sscottl				MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
600149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
601149871Sscottl				return -1;
602149871Sscottl			}
603136849Sscottl		}
604149871Sscottl		KdPrint(("RR182x [%d]: channel=%d, write cache disabled\n",
605149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
606136849Sscottl	}
607136849Sscottl#endif
608136849Sscottl
609136849Sscottl	/* Set transfer mode */
610136849Sscottl	KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_SLOW\n",
611149871Sscottl			  pMvSataAdapter->adapterId));
612136849Sscottl	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
613149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
614149871Sscottl								   MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) ==
615149871Sscottl		MV_FALSE)
616149871Sscottl	{
617136849Sscottl		MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
618149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
619136849Sscottl		return -1;
620136849Sscottl	}
621136849Sscottl
622149871Sscottl	if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1)
623149871Sscottl	{
624136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_4;
625149871Sscottl	}
626149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2)
627149871Sscottl	{
628136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_3;
629149871Sscottl	}
630149871Sscottl	else
631149871Sscottl	{
632149871Sscottl		MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n");
633136849Sscottl		pioMode = MV_ATA_TRANSFER_PIO_SLOW;
634136849Sscottl	}
635136849Sscottl
636136849Sscottl	KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_4\n",
637149871Sscottl			  pMvSataAdapter->adapterId));
638136849Sscottl	pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode;
639136849Sscottl	if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
640149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
641149871Sscottl								   pioMode, 0, 0, 0) == MV_FALSE)
642149871Sscottl	{
643136849Sscottl		MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
644149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
645136849Sscottl		return -1;
646136849Sscottl	}
647136849Sscottl
648136849Sscottl	udmaMode = MV_ATA_TRANSFER_UDMA_0;
649149871Sscottl	if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40)
650149871Sscottl	{
651136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_6;
652149871Sscottl	}
653149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20)
654149871Sscottl	{
655136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_5;
656149871Sscottl	}
657149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10)
658149871Sscottl	{
659136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_4;
660149871Sscottl	}
661149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8)
662149871Sscottl	{
663136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_3;
664149871Sscottl	}
665149871Sscottl	else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4)
666149871Sscottl	{
667136849Sscottl		udmaMode =  MV_ATA_TRANSFER_UDMA_2;
668136849Sscottl	}
669136849Sscottl
670136849Sscottl	KdPrint(("RR182x [%d] Set transfer mode XFER_UDMA_%d\n",
671149871Sscottl			  pMvSataAdapter->adapterId, udmaMode & 0xf));
672136849Sscottl	pChannelInfo->maxUltraDmaModeSupported = udmaMode;
673136849Sscottl
674149871Sscottl	/*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
675149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER, udmaMode,
676149871Sscottl								   0, 0, 0) == MV_FALSE)
677149871Sscottl	{
678136849Sscottl		MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
679149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
680136849Sscottl		return -1;
681149871Sscottl	}*/
682136849Sscottl	if (pChannelInfo->maxUltraDmaModeSupported == 0xFF)
683136849Sscottl		return TRUE;
684149871Sscottl	else
685149871Sscottl		do
686149871Sscottl		{
687149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
688149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
689149871Sscottl								   pChannelInfo->maxUltraDmaModeSupported,
690149871Sscottl								   0, 0, 0) == MV_FALSE)
691149871Sscottl			{
692149871Sscottl				if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0)
693149871Sscottl				{
694149871Sscottl					if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
695149871Sscottl					{
696149871Sscottl						MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress,
697149871Sscottl										  pMvSataChannel->eDmaRegsOffset +
698149871Sscottl										  0x11c, /* command reg */
699149871Sscottl										  MV_ATA_COMMAND_IDLE_IMMEDIATE);
700149871Sscottl						mvMicroSecondsDelay(10000);
701149871Sscottl						mvSataChannelHardReset(pMvSataAdapter, channelNum);
702149871Sscottl						if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
703149871Sscottl							return FALSE;
704149871Sscottl					}
705149871Sscottl					if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
706149871Sscottl						return FALSE;
707149871Sscottl					pChannelInfo->maxUltraDmaModeSupported--;
708149871Sscottl					continue;
709149871Sscottl				}
710149871Sscottl				else   return FALSE;
711149871Sscottl			}
712136849Sscottl			break;
713149871Sscottl		}while (1);
714136849Sscottl
715149871Sscottl	/* Read look ahead */
716136849Sscottl#ifdef ENABLE_READ_AHEAD
717149871Sscottl	if (pMvSataChannel->identifyDevice[82] & 0x40)
718149871Sscottl	{
719149871Sscottl		if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */
720149871Sscottl		{
721149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
722149871Sscottl										   MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0,
723149871Sscottl										   0, 0) == MV_FALSE)
724149871Sscottl			{
725149871Sscottl				MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
726149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
727136849Sscottl				return -1;
728136849Sscottl			}
729136849Sscottl		}
730136849Sscottl		KdPrint(("RR182x [%d]: channel=%d, read look ahead enabled\n",
731149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
732136849Sscottl	}
733149871Sscottl	else
734149871Sscottl	{
735149871Sscottl		KdPrint(("RR182x [%d]: channel %d, Read Look Ahead not supported\n",
736149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
737149871Sscottl	}
738149871Sscottl#else
739149871Sscottl	{
740149871Sscottl		if (pMvSataChannel->identifyDevice[86] & 0x20)
741149871Sscottl		{
742149871Sscottl			KdPrint(("RR182x [%d]:channel %d, disable read look ahead\n",
743149871Sscottl					  pMvSataAdapter->adapterId, channelNum));
744149871Sscottl			if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
745149871Sscottl										   MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0,
746149871Sscottl										   0, 0) == MV_FALSE)
747149871Sscottl			{
748149871Sscottl				MV_ERROR("RR182x [%d]:channel %d:  ATA Set Features failed\n",
749149871Sscottl						 pMvSataAdapter->adapterId, channelNum);
750149871Sscottl				return -1;
751149871Sscottl			}
752136849Sscottl		}
753149871Sscottl		KdPrint(("RR182x [%d]:channel %d, read look ahead disabled\n",
754149871Sscottl				  pMvSataAdapter->adapterId, channelNum));
755149871Sscottl	}
756136849Sscottl#endif
757136849Sscottl
758136849Sscottl
759149871Sscottl	{
760149871Sscottl		KdPrint(("RR182x [%d]: channel %d config EDMA, Non Queued Mode\n",
761149871Sscottl				  pMvSataAdapter->adapterId,
762149871Sscottl				  channelNum));
763149871Sscottl		if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum,
764149871Sscottl								 MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE)
765149871Sscottl		{
766149871Sscottl			MV_ERROR("RR182x [%d] channel %d Error: mvSataConfigEdmaMode failed\n",
767149871Sscottl					 pMvSataAdapter->adapterId, channelNum);
768136849Sscottl			return -1;
769136849Sscottl		}
770136849Sscottl	}
771136849Sscottl	/* Enable EDMA */
772149871Sscottl	if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE)
773149871Sscottl	{
774136849Sscottl		MV_ERROR("RR182x [%d] Failed to enable DMA, channel=%d\n",
775149871Sscottl				 pMvSataAdapter->adapterId, channelNum);
776136849Sscottl		return -1;
777136849Sscottl	}
778136849Sscottl	MV_ERROR("RR182x [%d,%d]: channel started successfully\n",
779149871Sscottl			 pMvSataAdapter->adapterId, channelNum);
780136849Sscottl
781136849Sscottl#ifndef FOR_DEMO
782136849Sscottl	set_fail_led(pMvSataAdapter, channelNum, 0);
783136849Sscottl#endif
784136849Sscottl	return 0;
785136849Sscottl}
786136849Sscottl
787136849Sscottlstatic void
788136849Sscottlhptmv_handle_event(void * data, int flag)
789136849Sscottl{
790149871Sscottl	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)data;
791149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter;
792149871Sscottl	MV_U8           channelIndex;
793149871Sscottl
794149871Sscottl/*	mvOsSemTake(&pMvSataAdapter->semaphore); */
795149871Sscottl	for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
796149871Sscottl	{
797149871Sscottl		switch(pAdapter->sataEvents[channelIndex])
798149871Sscottl		{
799149871Sscottl			case SATA_EVENT_CHANNEL_CONNECTED:
800149871Sscottl				/* Handle only connects */
801149871Sscottl				if (flag == 1)
802149871Sscottl					break;
803149871Sscottl				KdPrint(("RR182x [%d,%d]: new device connected\n",
804149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
805149871Sscottl				hptmv_init_channel(pAdapter, channelIndex);
806149871Sscottl				if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE)
807149871Sscottl				{
808149871Sscottl					MV_ERROR("RR182x [%d,%d] Failed to configure\n",
809149871Sscottl							 pMvSataAdapter->adapterId, channelIndex);
810149871Sscottl					hptmv_free_channel(pAdapter, channelIndex);
811149871Sscottl				}
812149871Sscottl				else
813149871Sscottl				{
814149871Sscottl					/*mvSataChannelHardReset(pMvSataAdapter, channel);*/
815149871Sscottl					if (start_channel( pAdapter, channelIndex))
816149871Sscottl					{
817149871Sscottl						MV_ERROR("RR182x [%d,%d]Failed to start channel\n",
818149871Sscottl								 pMvSataAdapter->adapterId, channelIndex);
819149871Sscottl						hptmv_free_channel(pAdapter, channelIndex);
820149871Sscottl					}
821149871Sscottl					else
822149871Sscottl					{
823149871Sscottl						device_change(pAdapter, channelIndex, TRUE);
824149871Sscottl					}
825149871Sscottl				}
826149871Sscottl				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
827149871Sscottl			   break;
828136849Sscottl
829149871Sscottl			case SATA_EVENT_CHANNEL_DISCONNECTED:
830149871Sscottl				/* Handle only disconnects */
831149871Sscottl				if (flag == 0)
832149871Sscottl					break;
833149871Sscottl				KdPrint(("RR182x [%d,%d]: device disconnected\n",
834149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
835149871Sscottl					/* Flush pending commands */
836149871Sscottl				if(pMvSataAdapter->sataChannel[channelIndex])
837149871Sscottl				{
838149871Sscottl					_VBUS_INST(&pAdapter->VBus)
839149871Sscottl					mvSataFlushDmaQueue (pMvSataAdapter, channelIndex,
840149871Sscottl										 MV_FLUSH_TYPE_CALLBACK);
841149871Sscottl					CheckPendingCall(_VBUS_P0);
842149871Sscottl					mvSataRemoveChannel(pMvSataAdapter,channelIndex);
843149871Sscottl					hptmv_free_channel(pAdapter, channelIndex);
844149871Sscottl					pMvSataAdapter->sataChannel[channelIndex] = NULL;
845149871Sscottl					KdPrint(("RR182x [%d,%d]: channel removed\n",
846149871Sscottl						 pMvSataAdapter->adapterId, channelIndex));
847149871Sscottl					if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
848149871Sscottl						Check_Idle_Call(pAdapter);
849136849Sscottl				}
850149871Sscottl				else
851149871Sscottl				{
852149871Sscottl					KdPrint(("RR182x [%d,%d]: channel already removed!!\n",
853149871Sscottl							 pMvSataAdapter->adapterId, channelIndex));
854149871Sscottl				}
855149871Sscottl				pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
856136849Sscottl				break;
857136849Sscottl
858149871Sscottl			case SATA_EVENT_NO_CHANGE:
859149871Sscottl				break;
860136849Sscottl
861149871Sscottl			default:
862149871Sscottl				break;
863136849Sscottl		}
864136849Sscottl	}
865149871Sscottl/*	mvOsSemRelease(&pMvSataAdapter->semaphore); */
866136849Sscottl}
867136849Sscottl
868136849Sscottl#define EVENT_CONNECT					1
869136849Sscottl#define EVENT_DISCONNECT				0
870136849Sscottl
871136849Sscottlstatic void
872136849Sscottlhptmv_handle_event_connect(void *data)
873136849Sscottl{
874149871Sscottl  hptmv_handle_event (data, 0);
875136849Sscottl}
876136849Sscottl
877136849Sscottlstatic void
878136849Sscottlhptmv_handle_event_disconnect(void *data)
879136849Sscottl{
880149871Sscottl  hptmv_handle_event (data, 1);
881136849Sscottl}
882136849Sscottl
883136849Sscottlstatic MV_BOOLEAN
884136849Sscottlhptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
885149871Sscottl								   MV_U32 param1, MV_U32 param2)
886136849Sscottl{
887149871Sscottl	IAL_ADAPTER_T   *pAdapter = pMvSataAdapter->IALData;
888136849Sscottl
889149871Sscottl	switch (eventType)
890136849Sscottl	{
891149871Sscottl		case MV_EVENT_TYPE_SATA_CABLE:
892149871Sscottl			{
893149871Sscottl				MV_U8   channel = param2;
894136849Sscottl
895149871Sscottl				if (param1 == EVENT_CONNECT)
896149871Sscottl				{
897149871Sscottl					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED;
898149871Sscottl					KdPrint(("RR182x [%d,%d]: device connected event received\n",
899149871Sscottl							 pMvSataAdapter->adapterId, channel));
900149871Sscottl					/* Delete previous timers (if multiple drives connected in the same time */
901149871Sscottl					pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz);
902149871Sscottl				}
903149871Sscottl				else if (param1 == EVENT_DISCONNECT)
904149871Sscottl				{
905149871Sscottl					pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED;
906149871Sscottl					KdPrint(("RR182x [%d,%d]: device disconnected event received \n",
907149871Sscottl							 pMvSataAdapter->adapterId, channel));
908149871Sscottl					device_change(pAdapter, channel, FALSE);
909149871Sscottl					/* Delete previous timers (if multiple drives disconnected in the same time */
910149871Sscottl					/*pAdapter->event_timer_disconnect = timeout(hptmv_handle_event_disconnect, pAdapter, 10*hz); */
911149871Sscottl					/*It is not necessary to wait, handle it directly*/
912149871Sscottl					hptmv_handle_event_disconnect(pAdapter);
913149871Sscottl				}
914149871Sscottl				else
915149871Sscottl				{
916136849Sscottl
917149871Sscottl					MV_ERROR("RR182x: illigal value for param1(%d) at "
918149871Sscottl							 "connect/disconect event, host=%d\n", param1,
919149871Sscottl							 pMvSataAdapter->adapterId );
920149871Sscottl
921149871Sscottl				}
922149871Sscottl			}
923149871Sscottl			break;
924149871Sscottl		case MV_EVENT_TYPE_ADAPTER_ERROR:
925149871Sscottl			KdPrint(("RR182x: DEVICE error event received, pci cause "
926149871Sscottl					  "reg=%x,  don't how to handle this\n", param1));
927149871Sscottl			return MV_TRUE;
928149871Sscottl		default:
929149871Sscottl			MV_ERROR("RR182x[%d]: unknown event type (%d)\n",
930149871Sscottl					 pMvSataAdapter->adapterId, eventType);
931149871Sscottl			return MV_FALSE;
932136849Sscottl	}
933136849Sscottl	return MV_TRUE;
934136849Sscottl}
935136849Sscottl
936149871Sscottlstatic int
937136849Sscottlhptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
938136849Sscottl{
939149871Sscottl	pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE,
940149871Sscottl			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
941149871Sscottl	if (pAdapter->requestsArrayBaseAddr == NULL)
942149871Sscottl	{
943149871Sscottl		MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA request"
944149871Sscottl				 " queues\n", pAdapter->mvSataAdapter.adapterId);
945136849Sscottl		return -1;
946136849Sscottl	}
947149871Sscottl	pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr);
948149871Sscottl	pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr;
949136849Sscottl	pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
950149871Sscottl	pAdapter->requestsArrayBaseAlignedAddr  = (MV_U8 *)
951149871Sscottl		(((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1));
952149871Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr;
953136849Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE;
954149871Sscottl	pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1);
955136849Sscottl
956149871Sscottl	if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) !=
957149871Sscottl		(pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr))
958149871Sscottl	{
959136849Sscottl		MV_ERROR("RR182x[%d]: Error in Request Quueues Alignment\n",
960149871Sscottl				 pAdapter->mvSataAdapter.adapterId);
961149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
962136849Sscottl		return -1;
963136849Sscottl	}
964136849Sscottl	/* response queues */
965149871Sscottl	pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE,
966149871Sscottl			M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
967149871Sscottl	if (pAdapter->responsesArrayBaseAddr == NULL)
968149871Sscottl	{
969149871Sscottl		MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA response"
970149871Sscottl				 " queues\n", pAdapter->mvSataAdapter.adapterId);
971149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
972136849Sscottl		return -1;
973136849Sscottl	}
974149871Sscottl	pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr);
975149871Sscottl	pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr;
976136849Sscottl	pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
977149871Sscottl	pAdapter->responsesArrayBaseAlignedAddr  = (MV_U8 *)
978149871Sscottl		(((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1));
979149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr;
980149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE;
981149871Sscottl	pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1);
982136849Sscottl
983149871Sscottl	if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) !=
984149871Sscottl		(pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr))
985149871Sscottl	{
986136849Sscottl		MV_ERROR("RR182x[%d]: Error in Response Quueues Alignment\n",
987149871Sscottl				 pAdapter->mvSataAdapter.adapterId);
988149871Sscottl		contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
989149871Sscottl		contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
990136849Sscottl		return -1;
991136849Sscottl	}
992136849Sscottl	return 0;
993136849Sscottl}
994136849Sscottl
995136849Sscottlstatic void
996136849Sscottlhptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter)
997136849Sscottl{
998149871Sscottl	contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
999149871Sscottl	contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
1000136849Sscottl}
1001136849Sscottl
1002136849Sscottlstatic PVOID
1003136849SscottlAllocatePRDTable(IAL_ADAPTER_T *pAdapter)
1004136849Sscottl{
1005136849Sscottl	PVOID ret;
1006136849Sscottl	if (pAdapter->pFreePRDLink) {
1007149871Sscottl		KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink));
1008136849Sscottl		ret = pAdapter->pFreePRDLink;
1009136849Sscottl		pAdapter->pFreePRDLink = *(void**)ret;
1010136849Sscottl		return ret;
1011136849Sscottl	}
1012136849Sscottl	return NULL;
1013136849Sscottl}
1014136849Sscottl
1015136849Sscottlstatic void
1016136849SscottlFreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable)
1017136849Sscottl{
1018136849Sscottl	*(void**)PRDTable = pAdapter->pFreePRDLink;
1019136849Sscottl	pAdapter->pFreePRDLink = PRDTable;
1020136849Sscottl}
1021136849Sscottl
1022136849Sscottlextern PVDevice fGetFirstChild(PVDevice pLogical);
1023136849Sscottlextern void fResetBootMark(PVDevice pLogical);
1024136849Sscottlstatic void
1025136849SscottlfRegisterVdevice(IAL_ADAPTER_T *pAdapter)
1026136849Sscottl{
1027136849Sscottl	PVDevice pPhysical, pLogical;
1028136849Sscottl	PVBus  pVBus;
1029136849Sscottl	int i,j;
1030136849Sscottl
1031149871Sscottl	for(i=0;i<MV_SATA_CHANNELS_NUM;i++) {
1032136849Sscottl		pPhysical = &(pAdapter->VDevices[i]);
1033136849Sscottl		pLogical = pPhysical;
1034136849Sscottl		while (pLogical->pParent) pLogical = pLogical->pParent;
1035136849Sscottl		if (pLogical->vf_online==0) {
1036136849Sscottl			pPhysical->vf_bootmark = pLogical->vf_bootmark = 0;
1037136849Sscottl			continue;
1038136849Sscottl		}
1039149871Sscottl		if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical))
1040136849Sscottl			continue;
1041136849Sscottl
1042136849Sscottl		pVBus = &pAdapter->VBus;
1043149871Sscottl		if(pVBus)
1044149871Sscottl		{
1045136849Sscottl			j=0;
1046149871Sscottl			while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++;
1047149871Sscottl			if(j<MAX_VDEVICE_PER_VBUS){
1048136849Sscottl				pVBus->pVDevice[j] = pLogical;
1049136849Sscottl				pLogical->pVBus = pVBus;
1050136849Sscottl
1051136849Sscottl				if (j>0 && pLogical->vf_bootmark) {
1052136849Sscottl					if (pVBus->pVDevice[0]->vf_bootmark) {
1053136849Sscottl						fResetBootMark(pLogical);
1054149871Sscottl					}
1055149871Sscottl					else {
1056149871Sscottl						do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j);
1057136849Sscottl						pVBus->pVDevice[0] = pLogical;
1058136849Sscottl					}
1059136849Sscottl				}
1060136849Sscottl			}
1061136849Sscottl		}
1062136849Sscottl	}
1063136849Sscottl}
1064136849Sscottl
1065136849SscottlPVDevice
1066136849SscottlGetSpareDisk(_VBUS_ARG PVDevice pArray)
1067136849Sscottl{
1068149871Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt;
1069149871Sscottl	ULONG capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1);
1070136849Sscottl	ULONG thiscap, maxcap = MAX_LBA_T;
1071136849Sscottl	PVDevice pVDevice, pFind = NULL;
1072136849Sscottl	int i;
1073136849Sscottl
1074149871Sscottl	for(i=0;i<MV_SATA_CHANNELS_NUM;i++)
1075149871Sscottl	{
1076136849Sscottl		pVDevice = &pAdapter->VDevices[i];
1077136849Sscottl		if(!pVDevice)
1078136849Sscottl			continue;
1079149871Sscottl		thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity;
1080136849Sscottl		/* find the smallest usable spare disk */
1081136849Sscottl		if (pVDevice->VDeviceType==VD_SPARE &&
1082149871Sscottl			pVDevice->u.disk.df_on_line &&
1083149871Sscottl			thiscap < maxcap &&
1084149871Sscottl			thiscap >= capacity)
1085149871Sscottl		{
1086149871Sscottl				maxcap = pVDevice->VDeviceCapacity;
1087149871Sscottl				pFind = pVDevice;
1088136849Sscottl		}
1089136849Sscottl	}
1090136849Sscottl	return pFind;
1091136849Sscottl}
1092136849Sscottl
1093136849Sscottl/******************************************************************
1094136849Sscottl * IO ATA Command
1095136849Sscottl *******************************************************************/
1096136849Sscottlint HPTLIBAPI
1097136849SscottlfDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer)
1098136849Sscottl{
1099136849Sscottl	return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer);
1100136849Sscottl}
1101136849Sscottl
1102136849Sscottlvoid HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode)
1103136849Sscottl{
1104149871Sscottl	MV_SATA_CHANNEL *pSataChannel = pDev->mv;
1105149871Sscottl	MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
1106149871Sscottl	MV_U8 channelIndex = pSataChannel->channelNumber;
1107136849Sscottl	UCHAR mvMode;
1108136849Sscottl	/* 508x don't use MW-DMA? */
1109136849Sscottl	if (NewMode>4 && NewMode<8) NewMode = 4;
1110136849Sscottl	pDev->bDeModeSetting = NewMode;
1111136849Sscottl	if (NewMode<=4)
1112136849Sscottl		mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode;
1113136849Sscottl	else
1114136849Sscottl		mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8);
1115136849Sscottl
1116136849Sscottl	/*To fix 88i8030 bug*/
1117136849Sscottl	if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4)
1118136849Sscottl		mvMode = MV_ATA_TRANSFER_UDMA_0;
1119136849Sscottl
1120136849Sscottl	mvSataDisableChannelDma(pSataAdapter, channelIndex);
1121136849Sscottl	/* Flush pending commands */
1122136849Sscottl	mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE);
1123136849Sscottl
1124136849Sscottl	if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
1125149871Sscottl								   MV_ATA_SET_FEATURES_TRANSFER,
1126149871Sscottl								   mvMode, 0, 0, 0) == MV_FALSE)
1127149871Sscottl	{
1128136849Sscottl		KdPrint(("channel %d: Set Features failed\n", channelIndex));
1129136849Sscottl	}
1130136849Sscottl	/* Enable EDMA */
1131136849Sscottl	if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE)
1132136849Sscottl		KdPrint(("Failed to enable DMA, channel=%d", channelIndex));
1133136849Sscottl}
1134136849Sscottl
1135136849Sscottl#ifdef SUPPORT_ARRAY
1136136849Sscottl#define IdeRegisterVDevice  fCheckArray
1137149871Sscottl#else
1138136849Sscottlvoid
1139136849SscottlIdeRegisterVDevice(PDevice pDev)
1140136849Sscottl{
1141136849Sscottl	PVDevice pVDev = Map2pVDevice(pDev);
1142136849Sscottl
1143136849Sscottl	pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI :
1144149871Sscottl						 pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK;
1145136849Sscottl	pVDev->vf_online = 1;
1146136849Sscottl	pVDev->VDeviceCapacity = pDev->dDeRealCapacity;
1147136849Sscottl	pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType];
1148136849Sscottl	pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType];
1149136849Sscottl}
1150136849Sscottl#endif
1151136849Sscottl
1152149871Sscottlstatic __inline PBUS_DMAMAP
1153149871Sscottldmamap_get(struct IALAdapter * pAdapter)
1154149871Sscottl{
1155149871Sscottl	PBUS_DMAMAP	p = pAdapter->pbus_dmamap_list;
1156149871Sscottl	if (p)
1157149871Sscottl		pAdapter->pbus_dmamap_list = p-> next;
1158149871Sscottl	return p;
1159149871Sscottl}
1160149871Sscottl
1161149871Sscottlstatic __inline void
1162149871Sscottldmamap_put(PBUS_DMAMAP p)
1163149871Sscottl{
1164149871Sscottl	p->next = p->pAdapter->pbus_dmamap_list;
1165149871Sscottl	p->pAdapter->pbus_dmamap_list = p;
1166149871Sscottl}
1167149871Sscottl
1168149871Sscottl/*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/
1169149871Sscottl#if __FreeBSD_version >= 500000
1170149871Sscottlstatic void hpt_init(void *dummy)
1171149871Sscottl{
1172149871Sscottl	mtx_init(&driver_lock, "hptlock", NULL, MTX_SPIN);
1173149871Sscottl}
1174149871SscottlSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL);
1175149871Sscottl#endif
1176149871Sscottl
1177136849Sscottlstatic int num_adapters = 0;
1178136849Sscottlstatic int
1179136849Sscottlinit_adapter(IAL_ADAPTER_T *pAdapter)
1180136849Sscottl{
1181136849Sscottl	PVBus _vbus_p = &pAdapter->VBus;
1182136849Sscottl	MV_SATA_ADAPTER *pMvSataAdapter;
1183149871Sscottl	int i, channel, rid;
1184136849Sscottl
1185136849Sscottl	PVDevice pVDev;
1186136849Sscottl
1187136849Sscottl	intrmask_t oldspl = lock_driver();
1188136849Sscottl
1189136849Sscottl	pAdapter->next = 0;
1190136849Sscottl
1191149871Sscottl	if(gIal_Adapter == 0){
1192136849Sscottl		gIal_Adapter = pAdapter;
1193136849Sscottl		pCurAdapter = gIal_Adapter;
1194149871Sscottl	}
1195149871Sscottl	else {
1196136849Sscottl		pCurAdapter->next = pAdapter;
1197136849Sscottl		pCurAdapter = pAdapter;
1198136849Sscottl	}
1199136849Sscottl
1200136849Sscottl	pAdapter->outstandingCommands = 0;
1201136849Sscottl
1202136849Sscottl	pMvSataAdapter = &(pAdapter->mvSataAdapter);
1203136849Sscottl	_vbus_p->OsExt = (void *)pAdapter;
1204136849Sscottl	pMvSataAdapter->IALData = pAdapter;
1205136849Sscottl
1206149871Sscottl	if (bus_dma_tag_create(NULL,/* parent */
1207149871Sscottl			4,	/* alignment */
1208149871Sscottl			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1209149871Sscottl			BUS_SPACE_MAXADDR,	/* lowaddr */
1210149871Sscottl			BUS_SPACE_MAXADDR,	/* highaddr */
1211149871Sscottl			NULL, NULL, 		/* filter, filterarg */
1212149871Sscottl			PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */
1213149871Sscottl			MAX_SG_DESCRIPTORS, /* nsegments */
1214149871Sscottl			0x10000,	/* maxsegsize */
1215149871Sscottl			BUS_DMA_WAITOK, 	/* flags */
1216149871Sscottl#if __FreeBSD_version>502000
1217149871Sscottl			busdma_lock_mutex,	/* lockfunc */
1218149871Sscottl			&driver_lock,		/* lockfuncarg */
1219149871Sscottl#endif
1220149871Sscottl			&pAdapter->io_dma_parent /* tag */))
1221149871Sscottl		{
1222149871Sscottl			return ENXIO;;
1223136849Sscottl	}
1224136849Sscottl
1225136849Sscottl
1226149871Sscottl	if (hptmv_allocate_edma_queues(pAdapter))
1227149871Sscottl	{
1228136849Sscottl		MV_ERROR("RR182x: Failed to allocate memory for EDMA queues\n");
1229149871Sscottl		unlock_driver(oldspl);
1230149871Sscottl		return ENOMEM;
1231136849Sscottl	}
1232136849Sscottl
1233136849Sscottl	/* also map EPROM address */
1234136849Sscottl	rid = 0x10;
1235149871Sscottl	if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid,
1236149871Sscottl			0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE))
1237149871Sscottl		||
1238149871Sscottl		!(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res)))
1239149871Sscottl	{
1240136849Sscottl		MV_ERROR("RR182x: Failed to remap memory space\n");
1241149871Sscottl		hptmv_free_edma_queues(pAdapter);
1242149871Sscottl		unlock_driver(oldspl);
1243149871Sscottl		return ENXIO;
1244136849Sscottl	}
1245149871Sscottl	else
1246149871Sscottl	{
1247149871Sscottl		KdPrint(("RR182x: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress));
1248149871Sscottl	}
1249136849Sscottl
1250136849Sscottl	pMvSataAdapter->adapterId = num_adapters++;
1251136849Sscottl	/* get the revision ID */
1252149871Sscottl	pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1);
1253136849Sscottl	pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev);
1254149871Sscottl
1255136849Sscottl	/* init RR182x */
1256136849Sscottl	pMvSataAdapter->intCoalThre[0]= 1;
1257136849Sscottl	pMvSataAdapter->intCoalThre[1]= 1;
1258136849Sscottl	pMvSataAdapter->intTimeThre[0] = 1;
1259136849Sscottl	pMvSataAdapter->intTimeThre[1] = 1;
1260136849Sscottl	pMvSataAdapter->pciCommand = 0x0107E371;
1261136849Sscottl	pMvSataAdapter->pciSerrMask = 0xd77fe6ul;
1262136849Sscottl	pMvSataAdapter->pciInterruptMask = 0xd77fe6ul;
1263136849Sscottl	pMvSataAdapter->mvSataEventNotify = hptmv_event_notify;
1264136849Sscottl
1265149871Sscottl	if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
1266149871Sscottl	{
1267136849Sscottl		MV_ERROR("RR182x[%d]: core failed to initialize the adapter\n",
1268149871Sscottl				 pMvSataAdapter->adapterId);
1269149871Sscottlunregister:
1270149871Sscottl		bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res);
1271149871Sscottl		hptmv_free_edma_queues(pAdapter);
1272149871Sscottl		unlock_driver(oldspl);
1273149871Sscottl		return ENXIO;
1274136849Sscottl	}
1275136849Sscottl	pAdapter->ver_601 = pMvSataAdapter->pcbVersion;
1276136849Sscottl
1277136849Sscottl#ifndef FOR_DEMO
1278136849Sscottl	set_fail_leds(pMvSataAdapter, 0);
1279136849Sscottl#endif
1280136849Sscottl
1281136849Sscottl	/* setup command blocks */
1282136849Sscottl	KdPrint(("Allocate command blocks\n"));
1283136849Sscottl	_vbus_(pFreeCommands) = 0;
1284149871Sscottl	pAdapter->pCommandBlocks =
1285149871Sscottl		malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT);
1286149871Sscottl	KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks));
1287149871Sscottl	if (!pAdapter->pCommandBlocks) {
1288149871Sscottl		MV_ERROR("insufficient memory\n");
1289149871Sscottl		goto unregister;
1290149871Sscottl	}
1291136849Sscottl
1292149871Sscottl	for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) {
1293149871Sscottl		FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i]));
1294149871Sscottl	}
1295136849Sscottl
1296149871Sscottl	/*Set up the bus_dmamap*/
1297149871Sscottl	pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT);
1298149871Sscottl	if(!pAdapter->pbus_dmamap) {
1299149871Sscottl		MV_ERROR("insufficient memory\n");
1300149871Sscottl		free(pAdapter->pCommandBlocks, M_DEVBUF);
1301149871Sscottl		goto unregister;
1302136849Sscottl	}
1303136849Sscottl
1304149871Sscottl	memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM);
1305149871Sscottl	pAdapter->pbus_dmamap_list = 0;
1306149871Sscottl	for (i=0; i < MAX_QUEUE_COMM; i++) {
1307149871Sscottl		PBUS_DMAMAP  pmap = &(pAdapter->pbus_dmamap[i]);
1308149871Sscottl		pmap->pAdapter = pAdapter;
1309149871Sscottl		dmamap_put(pmap);
1310149871Sscottl
1311149871Sscottl		if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) {
1312149871Sscottl			MV_ERROR("Can not allocate dma map\n");
1313149871Sscottl			free(pAdapter->pCommandBlocks, M_DEVBUF);
1314149871Sscottl			free(pAdapter->pbus_dmamap, M_DEVBUF);
1315149871Sscottl			goto unregister;
1316149871Sscottl		}
1317149871Sscottl	}
1318136849Sscottl	/* setup PRD Tables */
1319136849Sscottl	KdPrint(("Allocate PRD Tables\n"));
1320136849Sscottl	pAdapter->pFreePRDLink = 0;
1321149871Sscottl
1322149871Sscottl	pAdapter->prdTableAddr = (PUCHAR)contigmalloc(
1323149871Sscottl		(PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
1324149871Sscottl
1325136862Sscottl	KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr));
1326136849Sscottl	if (!pAdapter->prdTableAddr) {
1327136849Sscottl		MV_ERROR("insufficient PRD Tables\n");
1328136849Sscottl		goto unregister;
1329136849Sscottl	}
1330149871Sscottl	pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL);
1331149871Sscottl	{
1332149871Sscottl		PUCHAR PRDTable = pAdapter->prdTableAlignedAddr;
1333149871Sscottl		for (i=0; i<PRD_TABLES_FOR_VBUS; i++)
1334149871Sscottl		{
1335149871Sscottl/*			KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */
1336149871Sscottl			FreePRDTable(pAdapter, PRDTable);
1337149871Sscottl			PRDTable += PRD_ENTRIES_SIZE;
1338149871Sscottl		}
1339136849Sscottl	}
1340136849Sscottl
1341136849Sscottl	/* enable the adapter interrupts */
1342136849Sscottl
1343136849Sscottl	/* configure and start the connected channels*/
1344149871Sscottl	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++)
1345149871Sscottl	{
1346136849Sscottl		pAdapter->mvChannel[channel].online = MV_FALSE;
1347136849Sscottl		if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel)
1348149871Sscottl			== MV_TRUE)
1349149871Sscottl		{
1350149871Sscottl			KdPrint(("RR182x[%d]: channel %d is connected\n",
1351149871Sscottl					  pMvSataAdapter->adapterId, channel));
1352136849Sscottl
1353149871Sscottl			if (hptmv_init_channel(pAdapter, channel) == 0)
1354149871Sscottl			{
1355149871Sscottl				if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE)
1356149871Sscottl				{
1357149871Sscottl					MV_ERROR("RR182x[%d]: Failed to configure channel"
1358149871Sscottl							 " %d\n",pMvSataAdapter->adapterId, channel);
1359149871Sscottl					hptmv_free_channel(pAdapter, channel);
1360149871Sscottl				}
1361149871Sscottl				else
1362149871Sscottl				{
1363149871Sscottl					if (start_channel(pAdapter, channel))
1364149871Sscottl					{
1365149871Sscottl						MV_ERROR("RR182x[%d]: Failed to start channel,"
1366149871Sscottl								 " channel=%d\n",pMvSataAdapter->adapterId,
1367149871Sscottl								 channel);
1368149871Sscottl						hptmv_free_channel(pAdapter, channel);
1369149871Sscottl					}
1370149871Sscottl					pAdapter->mvChannel[channel].online = MV_TRUE;
1371149871Sscottl					/*  mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter,
1372149871Sscottl													   channel,
1373149871Sscottl													   MV_TRUE);*/
1374149871Sscottl				}
1375136849Sscottl			}
1376136849Sscottl		}
1377136849Sscottl		KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n",
1378136849Sscottl			pAdapter->mvChannel[channel].online, channel));
1379136849Sscottl	}
1380136849Sscottl
1381136849Sscottl#ifdef SUPPORT_ARRAY
1382136849Sscottl	for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) {
1383136849Sscottl		pVDev = ArrayTables(i);
1384136849Sscottl		mArFreeArrayTable(pVDev);
1385136849Sscottl	}
1386136849Sscottl#endif
1387136849Sscottl
1388136849Sscottl	KdPrint(("Initialize Devices\n"));
1389136849Sscottl	for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) {
1390149871Sscottl		MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel];
1391136849Sscottl		if (pMvSataChannel) {
1392136849Sscottl			init_vdev_params(pAdapter, channel);
1393136849Sscottl			IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk);
1394136849Sscottl		}
1395136849Sscottl	}
1396136849Sscottl#ifdef SUPPORT_ARRAY
1397136849Sscottl	CheckArrayCritical(_VBUS_P0);
1398136849Sscottl#endif
1399136849Sscottl	_vbus_p->nInstances = 1;
1400136849Sscottl	fRegisterVdevice(pAdapter);
1401136849Sscottl
1402136849Sscottl	for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) {
1403136849Sscottl		pVDev = _vbus_p->pVDevice[channel];
1404136849Sscottl		if (pVDev && pVDev->vf_online)
1405136849Sscottl			fCheckBootable(pVDev);
1406136849Sscottl	}
1407136849Sscottl
1408136849Sscottl#if defined(SUPPORT_ARRAY) && defined(_RAID5N_)
1409136849Sscottl	init_raid5_memory(_VBUS_P0);
1410136849Sscottl	_vbus_(r5).enable_write_back = 1;
1411149871Sscottl	printf("RR182x: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled");
1412136849Sscottl#endif
1413136849Sscottl
1414136849Sscottl	mvSataUnmaskAdapterInterrupt(pMvSataAdapter);
1415136849Sscottl	unlock_driver(oldspl);
1416136849Sscottl	return 0;
1417136849Sscottl}
1418136849Sscottl
1419136849Sscottlint
1420136849SscottlMvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
1421136849Sscottl{
1422149871Sscottl	IAL_ADAPTER_T   *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData;
1423136849Sscottl
1424136849Sscottl	mvSataDisableChannelDma(pMvSataAdapter, channel);
1425136849Sscottl	/* Flush pending commands */
1426136849Sscottl	mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
1427136849Sscottl
1428136849Sscottl	/* Software reset channel */
1429149871Sscottl	if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE)
1430149871Sscottl	{
1431136849Sscottl		MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n",
1432149871Sscottl				 pMvSataAdapter->adapterId, channel);
1433149871Sscottl		hptmv_free_channel(pAdapter, channel);
1434136849Sscottl		return -1;
1435136849Sscottl	}
1436136849Sscottl
1437136849Sscottl	/* Hardware reset channel */
1438149871Sscottl	if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE)
1439149871Sscottl	{
1440149871Sscottl		MV_ERROR("RR182x [%d,%d] Failed to Hard reser the SATA channel\n",
1441149871Sscottl				 pMvSataAdapter->adapterId, channel);
1442136849Sscottl		hptmv_free_channel(pAdapter, channel);
1443136849Sscottl		return -1;
1444136849Sscottl	}
1445136849Sscottl
1446149871Sscottl	if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE)
1447149871Sscottl	{
1448149871Sscottl		 MV_ERROR("RR182x [%d,%d] Failed to Connect Device\n",
1449149871Sscottl				 pMvSataAdapter->adapterId, channel);
1450136849Sscottl		hptmv_free_channel(pAdapter, channel);
1451136849Sscottl		return -1;
1452149871Sscottl	}else
1453149871Sscottl	{
1454149871Sscottl		MV_ERROR("channel %d: perform recalibrate command", channel);
1455149871Sscottl		if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
1456149871Sscottl								MV_NON_UDMA_PROTOCOL_NON_DATA,
1457149871Sscottl								MV_FALSE,
1458149871Sscottl								NULL,	 /* pBuffer*/
1459149871Sscottl								0,		 /* count  */
1460149871Sscottl								0,		/*features*/
1461149871Sscottl										/* sectorCount */
1462149871Sscottl								0,
1463149871Sscottl								0,	/* lbaLow */
1464149871Sscottl								0,	/* lbaMid */
1465149871Sscottl									/* lbaHigh */
1466149871Sscottl								0,
1467149871Sscottl								0,		/* device */
1468149871Sscottl										/* command */
1469149871Sscottl								0x10))
1470149871Sscottl			MV_ERROR("channel %d: recalibrate failed", channel);
1471149871Sscottl
1472136849Sscottl		/* Set transfer mode */
1473136849Sscottl		if((mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1474149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1475149871Sscottl						MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) ||
1476149871Sscottl			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1477149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1478149871Sscottl						pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) ||
1479149871Sscottl			(mvStorageDevATASetFeatures(pMvSataAdapter, channel,
1480149871Sscottl						MV_ATA_SET_FEATURES_TRANSFER,
1481149871Sscottl						pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) )
1482149871Sscottl		{
1483136849Sscottl			MV_ERROR("channel %d: Set Features failed", channel);
1484136849Sscottl			hptmv_free_channel(pAdapter, channel);
1485136849Sscottl			return -1;
1486136849Sscottl		}
1487136849Sscottl		/* Enable EDMA */
1488149871Sscottl		if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE)
1489149871Sscottl		{
1490136849Sscottl			MV_ERROR("Failed to enable DMA, channel=%d", channel);
1491136849Sscottl			hptmv_free_channel(pAdapter, channel);
1492136849Sscottl			return -1;
1493136849Sscottl		}
1494136849Sscottl	}
1495136849Sscottl	return 0;
1496136849Sscottl}
1497136849Sscottl
1498136849Sscottlstatic int
1499136849SscottlfResetActiveCommands(PVBus _vbus_p)
1500136849Sscottl{
1501149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
1502136849Sscottl	MV_U8 channel;
1503136849Sscottl	for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
1504149871Sscottl		if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands)
1505149871Sscottl			MvSataResetChannel(pMvSataAdapter,channel);
1506136849Sscottl	}
1507136849Sscottl	return 0;
1508136849Sscottl}
1509136849Sscottl
1510149871Sscottlvoid fCompleteAllCommandsSynchronously(PVBus _vbus_p)
1511136849Sscottl{
1512136849Sscottl	UINT cont;
1513136849Sscottl	ULONG ticks = 0;
1514136849Sscottl	MV_U8 channel;
1515149871Sscottl	MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter;
1516136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
1517136849Sscottl
1518136849Sscottl	do {
1519136849Sscottlcheck_cmds:
1520136849Sscottl		cont = 0;
1521136849Sscottl		CheckPendingCall(_VBUS_P0);
1522136849Sscottl#ifdef _RAID5N_
1523136849Sscottl		dataxfer_poll();
1524136849Sscottl		xor_poll();
1525136849Sscottl#endif
1526149871Sscottl		for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) {
1527136849Sscottl			pMvSataChannel = pMvSataAdapter->sataChannel[channel];
1528149871Sscottl			if (pMvSataChannel && pMvSataChannel->outstandingCommands)
1529149871Sscottl			{
1530136849Sscottl				while (pMvSataChannel->outstandingCommands) {
1531149871Sscottl					if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) {
1532136849Sscottl						StallExec(1000);
1533136849Sscottl						if (ticks++ > 3000) {
1534149871Sscottl							MvSataResetChannel(pMvSataAdapter,channel);
1535136849Sscottl							goto check_cmds;
1536136849Sscottl						}
1537149871Sscottl					}
1538149871Sscottl					else
1539136849Sscottl						ticks = 0;
1540136849Sscottl				}
1541136849Sscottl				cont = 1;
1542136849Sscottl			}
1543136849Sscottl		}
1544136849Sscottl	} while (cont);
1545136849Sscottl}
1546136849Sscottl
1547136849Sscottlvoid
1548136849SscottlfResetVBus(_VBUS_ARG0)
1549136849Sscottl{
1550136862Sscottl	KdPrint(("fMvResetBus(%p)", _vbus_p));
1551136849Sscottl
1552136849Sscottl	/* some commands may already finished. */
1553136849Sscottl	CheckPendingCall(_VBUS_P0);
1554136849Sscottl
1555136849Sscottl	fResetActiveCommands(_vbus_p);
1556136849Sscottl	/*
1557136849Sscottl	 * the other pending commands may still be finished successfully.
1558136849Sscottl	 */
1559136849Sscottl	fCompleteAllCommandsSynchronously(_vbus_p);
1560136849Sscottl
1561136849Sscottl	/* Now there should be no pending commands. No more action needed. */
1562136849Sscottl	CheckIdleCall(_VBUS_P0);
1563136849Sscottl
1564136849Sscottl	KdPrint(("fMvResetBus() done"));
1565136849Sscottl}
1566136849Sscottl
1567149871Sscottl/*No rescan function*/
1568136849Sscottlvoid
1569136849SscottlfRescanAllDevice(_VBUS_ARG0)
1570136849Sscottl{
1571136849Sscottl}
1572136849Sscottl
1573136849Sscottlstatic MV_BOOLEAN
1574149871SscottlCommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter,
1575149871Sscottl					MV_U8 channelNum,
1576149871Sscottl					MV_COMPLETION_TYPE comp_type,
1577149871Sscottl					MV_VOID_PTR commandId,
1578149871Sscottl					MV_U16 responseFlags,
1579149871Sscottl					MV_U32 timeStamp,
1580149871Sscottl					MV_STORAGE_DEVICE_REGISTERS *registerStruct)
1581136849Sscottl{
1582136849Sscottl	PCommand pCmd = (PCommand) commandId;
1583136849Sscottl	_VBUS_INST(pCmd->pVDevice->pVBus)
1584136849Sscottl
1585136849Sscottl	if (pCmd->uScratch.sata_param.prdAddr)
1586149871Sscottl		FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr);
1587136849Sscottl
1588149871Sscottl	switch (comp_type)
1589149871Sscottl	{
1590136849Sscottl	case MV_COMPLETION_TYPE_NORMAL:
1591136849Sscottl		pCmd->Result = RETURN_SUCCESS;
1592136849Sscottl		break;
1593136849Sscottl	case MV_COMPLETION_TYPE_ABORT:
1594136849Sscottl		pCmd->Result = RETURN_BUS_RESET;
1595136849Sscottl		break;
1596136849Sscottl	case MV_COMPLETION_TYPE_ERROR:
1597149871Sscottl		 MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n",
1598149871Sscottl				 pMvSataAdapter->adapterId, channelNum, responseFlags);
1599136849Sscottl
1600136849Sscottl		if (responseFlags & 4) {
1601149871Sscottl			MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x,"
1602149871Sscottl				" LBA high %x, device %x, status %x\n",
1603149871Sscottl				registerStruct->errorRegister,
1604149871Sscottl				registerStruct->sectorCountRegister,
1605149871Sscottl				registerStruct->lbaLowRegister,
1606149871Sscottl				registerStruct->lbaMidRegister,
1607149871Sscottl				registerStruct->lbaHighRegister,
1608149871Sscottl				registerStruct->deviceRegister,
1609149871Sscottl				registerStruct->statusRegister);
1610136849Sscottl		}
1611149871Sscottl		/*We can't do handleEdmaError directly here, because CommandCompletionCB is called by
1612149871Sscottl		 * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/
1613136849Sscottl		pCmd->uScratch.sata_param.responseFlags = responseFlags;
1614149871Sscottl		pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister;
1615149871Sscottl		pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister;
1616136849Sscottl		pCmd->pVDevice->u.disk.QueueLength--;
1617136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd);
1618136849Sscottl		return TRUE;
1619136849Sscottl
1620136849Sscottl	default:
1621136849Sscottl		MV_ERROR(" Unknown completion type (%d)\n", comp_type);
1622136849Sscottl		return MV_FALSE;
1623136849Sscottl	}
1624136849Sscottl
1625149871Sscottl	if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) {
1626136849Sscottl		pCmd->uScratch.sata_param.cmd_priv --;
1627136849Sscottl		return TRUE;
1628136849Sscottl	}
1629136849Sscottl	pCmd->pVDevice->u.disk.QueueLength--;
1630136849Sscottl	CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1631136849Sscottl	return TRUE;
1632136849Sscottl}
1633136849Sscottl
1634136849Sscottlvoid
1635136849SscottlfDeviceSendCommand(_VBUS_ARG PCommand pCmd)
1636136849Sscottl{
1637149871Sscottl	MV_SATA_EDMA_PRD_ENTRY  *pPRDTable = 0;
1638136849Sscottl	MV_SATA_ADAPTER *pMvSataAdapter;
1639136849Sscottl	MV_SATA_CHANNEL *pMvSataChannel;
1640149871Sscottl	PVDevice pVDevice = pCmd->pVDevice;
1641149871Sscottl	PDevice  pDevice = &pVDevice->u.disk;
1642149871Sscottl	ULONG    Lba = pCmd->uCmd.Ide.Lba;
1643149871Sscottl	USHORT   nSector = pCmd->uCmd.Ide.nSectors;
1644149871Sscottl
1645136849Sscottl	MV_QUEUE_COMMAND_RESULT result;
1646136849Sscottl	MV_QUEUE_COMMAND_INFO commandInfo;
1647149871Sscottl	MV_UDMA_COMMAND_PARAMS  *pUdmaParams = &commandInfo.commandParams.udmaCommand;
1648149871Sscottl	MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand;
1649149871Sscottl
1650136849Sscottl	MV_BOOLEAN is48bit = MV_FALSE;
1651149871Sscottl	MV_U8      channel;
1652149871Sscottl	int        i=0;
1653149871Sscottl
1654136849Sscottl	DECLARE_BUFFER(FPSCAT_GATH, tmpSg);
1655136849Sscottl
1656136849Sscottl	if (!pDevice->df_on_line) {
1657136849Sscottl		MV_ERROR("Device is offline");
1658136849Sscottl		pCmd->Result = RETURN_BAD_DEVICE;
1659136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1660136849Sscottl		return;
1661136849Sscottl	}
1662136849Sscottl
1663136849Sscottl	pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors;
1664136849Sscottl	pMvSataChannel = pDevice->mv;
1665136849Sscottl	pMvSataAdapter = pMvSataChannel->mvSataAdapter;
1666136849Sscottl	channel = pMvSataChannel->channelNumber;
1667136849Sscottl
1668149871Sscottl	/* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */
1669136849Sscottl	Lba += pDevice->dDeHiddenLba;
1670136849Sscottl	/* check LBA */
1671136849Sscottl	if (Lba+nSector-1 > pDevice->dDeRealCapacity) {
1672136849Sscottl		pCmd->Result = RETURN_INVALID_REQUEST;
1673136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1674136849Sscottl		return;
1675136849Sscottl	}
1676136849Sscottl
1677136849Sscottl	if(Lba & 0xF0000000){
1678136849Sscottl		is48bit = MV_TRUE;
1679136849Sscottl	}
1680136849Sscottl
1681149871Sscottl	switch (pCmd->uCmd.Ide.Command)
1682149871Sscottl	{
1683136849Sscottl	case IDE_COMMAND_READ:
1684136849Sscottl	case IDE_COMMAND_WRITE:
1685136849Sscottl		if (pDevice->bDeModeSetting<8) goto pio;
1686136849Sscottl
1687136849Sscottl		commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA;
1688136849Sscottl		pUdmaParams->isEXT = is48bit;
1689136849Sscottl		pUdmaParams->numOfSectors = nSector;
1690136849Sscottl		pUdmaParams->lowLBAAddress = Lba;
1691136849Sscottl		pUdmaParams->highLBAAddress = 0;
1692136849Sscottl		pUdmaParams->prdHighAddr = 0;
1693136849Sscottl		pUdmaParams->callBack = CommandCompletionCB;
1694136849Sscottl		pUdmaParams->commandId = (MV_VOID_PTR )pCmd;
1695136849Sscottl		if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ)
1696136849Sscottl			pUdmaParams->readWrite = MV_UDMA_TYPE_READ;
1697136849Sscottl		else
1698136849Sscottl			pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE;
1699136849Sscottl
1700136849Sscottl		if (pCmd->pSgTable && pCmd->cf_physical_sg) {
1701136849Sscottl			FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
1702149871Sscottl			do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
1703149871Sscottl		}
1704149871Sscottl		else {
1705149871Sscottl			if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) {
1706136849Sscottlpio:
1707149871Sscottl				mvSataDisableChannelDma(pMvSataAdapter, channel);
1708149871Sscottl				mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK);
1709149871Sscottl
1710149871Sscottl				if (pCmd->pSgTable && pCmd->cf_physical_sg==0) {
1711149871Sscottl					FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable;
1712149871Sscottl					do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0);
1713149871Sscottl				}
1714149871Sscottl				else {
1715149871Sscottl					if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) {
1716149871Sscottl						pCmd->Result = RETURN_NEED_LOGICAL_SG;
1717149871Sscottl						goto finish_cmd;
1718149871Sscottl					}
1719149871Sscottl				}
1720149871Sscottl
1721136849Sscottl				do {
1722149871Sscottl					ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000;
1723149871Sscottl					ULONG_PTR addr = tmpSg->dSgAddress;
1724149871Sscottl					if (size & 0x1ff) {
1725149871Sscottl						pCmd->Result = RETURN_INVALID_REQUEST;
1726149871Sscottl						goto finish_cmd;
1727149871Sscottl					}
1728149871Sscottl					if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel,
1729149871Sscottl						(pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN,
1730149871Sscottl						is48bit,
1731149871Sscottl						(MV_U16_PTR)addr,
1732149871Sscottl						size >> 1,	/* count       */
1733149871Sscottl						0,		/* features  N/A  */
1734149871Sscottl						(MV_U16)(size>>9),	/*sector count*/
1735149871Sscottl						(MV_U16)(  (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 )  | (UCHAR)(Lba & 0xFF) ), /*lbalow*/
1736149871Sscottl						(MV_U16)((Lba >> 8) & 0xFF), /* lbaMid      */
1737149871Sscottl						(MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh     */
1738149871Sscottl						(MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device      */
1739149871Sscottl						(MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command)
1740149871Sscottl					)==MV_FALSE)
1741149871Sscottl					{
1742149871Sscottl						pCmd->Result = RETURN_IDE_ERROR;
1743149871Sscottl						goto finish_cmd;
1744149871Sscottl					}
1745149871Sscottl					Lba += size>>9;
1746149871Sscottl					if(Lba & 0xF0000000) is48bit = MV_TRUE;
1747136849Sscottl				}
1748149871Sscottl				while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
1749149871Sscottl				pCmd->Result = RETURN_SUCCESS;
1750149871Sscottlfinish_cmd:
1751149871Sscottl				mvSataEnableChannelDma(pMvSataAdapter,channel);
1752149871Sscottl				CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1753149871Sscottl				return;
1754136849Sscottl			}
1755136849Sscottl		}
1756136849Sscottl
1757149871Sscottl		pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData);
1758136862Sscottl		KdPrint(("pPRDTable:%p\n",pPRDTable));
1759136849Sscottl		if (!pPRDTable) {
1760136849Sscottl			pCmd->Result = RETURN_DEVICE_BUSY;
1761149871Sscottl			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1762136849Sscottl			HPT_ASSERT(0);
1763136849Sscottl			return;
1764136849Sscottl		}
1765136849Sscottl
1766149871Sscottl		do{
1767149871Sscottl			pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0);
1768136849Sscottl			pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag;
1769136849Sscottl			pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize;
1770136849Sscottl			pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress;
1771136849Sscottl			pPRDTable[i].reserved = 0;
1772136849Sscottl			i++;
1773149871Sscottl		}while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0);
1774136849Sscottl
1775149871Sscottl		pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable);
1776149871Sscottl		if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) {
1777136849Sscottl			pUdmaParams->numOfSectors = 0;
1778136849Sscottl		}
1779136849Sscottl
1780136849Sscottl		pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable;
1781136849Sscottl
1782149871Sscottl		result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1783136849Sscottl
1784149871Sscottl		if (result != MV_QUEUE_COMMAND_RESULT_OK)
1785149871Sscottl		{
1786136849Sscottlqueue_failed:
1787149871Sscottl			switch (result)
1788149871Sscottl			{
1789136849Sscottl			case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
1790149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA "
1791149871Sscottl						 "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress);
1792136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1793136849Sscottl				break;
1794136849Sscottl			case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
1795149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. EDMA"
1796149871Sscottl						 " disabled adapter %d channel %d\n",
1797149871Sscottl						 pMvSataAdapter->adapterId, channel);
1798136849Sscottl				mvSataEnableChannelDma(pMvSataAdapter,channel);
1799136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1800136849Sscottl				break;
1801136849Sscottl			case MV_QUEUE_COMMAND_RESULT_FULL:
1802149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. Queue is"
1803149871Sscottl						 " Full adapter %d channel %d\n",
1804149871Sscottl						 pMvSataAdapter->adapterId, channel);
1805136849Sscottl				pCmd->Result = RETURN_DEVICE_BUSY;
1806136849Sscottl				break;
1807136849Sscottl			case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
1808149871Sscottl				MV_ERROR("IAL Error: Edma Queue command failed. (Bad "
1809149871Sscottl						 "Params), pMvSataAdapter: %p,  pSataChannel: %p.\n",
1810149871Sscottl						 pMvSataAdapter, pMvSataAdapter->sataChannel[channel]);
1811136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1812136849Sscottl				break;
1813136849Sscottl			default:
1814149871Sscottl				MV_ERROR("IAL Error: Bad result value (%d) from queue"
1815149871Sscottl						 " command\n", result);
1816136849Sscottl				pCmd->Result = RETURN_IDE_ERROR;
1817136849Sscottl			}
1818136849Sscottl			if(pPRDTable)
1819149871Sscottl				FreePRDTable(pMvSataAdapter->IALData,pPRDTable);
1820149871Sscottl			CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1821136849Sscottl		}
1822136849Sscottl		pDevice->QueueLength++;
1823136849Sscottl		return;
1824136849Sscottl
1825136849Sscottl	case IDE_COMMAND_VERIFY:
1826136849Sscottl		commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
1827136849Sscottl		pNoUdmaParams->bufPtr = NULL;
1828136849Sscottl		pNoUdmaParams->callBack = CommandCompletionCB;
1829136849Sscottl		pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd;
1830136849Sscottl		pNoUdmaParams->count = 0;
1831136849Sscottl		pNoUdmaParams->features = 0;
1832136849Sscottl		pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA;
1833136849Sscottl
1834136849Sscottl		pCmd->uScratch.sata_param.cmd_priv = 1;
1835136849Sscottl		if (pMvSataChannel->lba48Address == MV_TRUE){
1836149871Sscottl			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT;
1837136849Sscottl			pNoUdmaParams->isEXT = MV_TRUE;
1838149871Sscottl			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
1839136849Sscottl			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
1840136849Sscottl			pNoUdmaParams->lbaLow =
1841149871Sscottl				(MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff));
1842136849Sscottl			pNoUdmaParams->sectorCount = nSector;
1843136849Sscottl			pNoUdmaParams->device = 0x40;
1844149871Sscottl			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1845149871Sscottl			if (result != MV_QUEUE_COMMAND_RESULT_OK){
1846136849Sscottl				goto queue_failed;
1847136849Sscottl			}
1848136849Sscottl			return;
1849136849Sscottl		}
1850149871Sscottl		else{
1851149871Sscottl			pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS;
1852149871Sscottl			pNoUdmaParams->isEXT = MV_FALSE;
1853149871Sscottl			pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16);
1854149871Sscottl			pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8);
1855149871Sscottl			pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff);
1856149871Sscottl			pNoUdmaParams->sectorCount = 0xff & nSector;
1857149871Sscottl			pNoUdmaParams->device = (MV_U8)(0x40 |
1858149871Sscottl				((Lba & 0xf000000) >> 24));
1859149871Sscottl			pNoUdmaParams->callBack = CommandCompletionCB;
1860149871Sscottl			result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo);
1861149871Sscottl			/*FIXME: how about the commands already queued? but marvel also forgets to consider this*/
1862149871Sscottl			if (result != MV_QUEUE_COMMAND_RESULT_OK){
1863149871Sscottl				goto queue_failed;
1864149871Sscottl			}
1865136849Sscottl		}
1866136849Sscottl		break;
1867136849Sscottl	default:
1868136849Sscottl		pCmd->Result = RETURN_INVALID_REQUEST;
1869136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd);
1870136849Sscottl		break;
1871136849Sscottl	}
1872136849Sscottl}
1873136849Sscottl
1874136849Sscottl/**********************************************************
1875136849Sscottl *
1876136849Sscottl *	Probe the hostadapter.
1877136849Sscottl *
1878136849Sscottl **********************************************************/
1879136849Sscottlstatic int
1880136849Sscottlhpt_probe(device_t dev)
1881136849Sscottl{
1882136849Sscottl	if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) &&
1883136849Sscottl		(pci_get_device(dev) == MV_SATA_DEVICE_ID_5081
1884136849Sscottl#ifdef FOR_DEMO
1885136849Sscottl		|| pci_get_device(dev) == MV_SATA_DEVICE_ID_5080
1886136849Sscottl#endif
1887149871Sscottl		))
1888149871Sscottl	{
1889136849Sscottl		KdPrintI((CONTROLLER_NAME " found\n"));
1890136849Sscottl		device_set_desc(dev, CONTROLLER_NAME);
1891136849Sscottl		return 0;
1892136849Sscottl	}
1893136849Sscottl	else
1894136849Sscottl		return(ENXIO);
1895136849Sscottl}
1896136849Sscottl
1897136849Sscottl/***********************************************************
1898136849Sscottl *
1899136849Sscottl *      Auto configuration:  attach and init a host adapter.
1900136849Sscottl *
1901136849Sscottl ***********************************************************/
1902136849Sscottlstatic int
1903136849Sscottlhpt_attach(device_t dev)
1904136849Sscottl{
1905149871Sscottl	IAL_ADAPTER_T * pAdapter = device_get_softc(dev);
1906136849Sscottl	int rid;
1907136849Sscottl	union ccb *ccb;
1908136849Sscottl	struct cam_devq *devq;
1909136849Sscottl	struct cam_sim *hpt_vsim;
1910136849Sscottl
1911149871Sscottl	printf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION);
1912136849Sscottl
1913149871Sscottl	if (!pAdapter)
1914149871Sscottl	{
1915149871Sscottl		pAdapter = (IAL_ADAPTER_T *)malloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT);
1916149871Sscottl#if __FreeBSD_version > 410000
1917149871Sscottl		device_set_softc(dev, (void *)pAdapter);
1918149871Sscottl#else
1919149871Sscottl		device_set_driver(dev, (driver_t *)pAdapter);
1920149871Sscottl#endif
1921149871Sscottl	}
1922149871Sscottl
1923149871Sscottl	if (!pAdapter) return (ENOMEM);
1924149871Sscottl	bzero(pAdapter, sizeof(IAL_ADAPTER_T));
1925149871Sscottl
1926136849Sscottl	pAdapter->hpt_dev = dev;
1927136849Sscottl
1928136849Sscottl	rid = init_adapter(pAdapter);
1929136849Sscottl	if (rid)
1930136849Sscottl		return rid;
1931136849Sscottl
1932136849Sscottl	rid = 0;
1933149871Sscottl	if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL)
1934149871Sscottl	{
1935136849Sscottl		hpt_printk(("can't allocate interrupt\n"));
1936136849Sscottl		return(ENXIO);
1937136849Sscottl	}
1938136849Sscottl
1939149871Sscottl	if(bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, hpt_intr, pAdapter, &pAdapter->hpt_intr))
1940149871Sscottl	{
1941136849Sscottl		hpt_printk(("can't set up interrupt\n"));
1942136849Sscottl		free(pAdapter, M_DEVBUF);
1943136849Sscottl		return(ENXIO);
1944136849Sscottl	}
1945136849Sscottl
1946149871Sscottl
1947149871Sscottl	if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL)
1948149871Sscottl	{
1949149871Sscottl		bzero(ccb, sizeof(*ccb));
1950136849Sscottl		ccb->ccb_h.pinfo.priority = 1;
1951136849Sscottl		ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
1952149871Sscottl	}
1953149871Sscottl	else
1954149871Sscottl	{
1955136849Sscottl		return ENOMEM;
1956136849Sscottl	}
1957136849Sscottl	/*
1958136849Sscottl	 * Create the device queue for our SIM(s).
1959136849Sscottl	 */
1960149871Sscottl	if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL)
1961149871Sscottl	{
1962136849Sscottl		KdPrint(("ENXIO\n"));
1963136849Sscottl		return ENOMEM;
1964136849Sscottl	}
1965136849Sscottl
1966136849Sscottl	/*
1967136849Sscottl	 * Construct our SIM entry
1968136849Sscottl	 */
1969149871Sscottl	if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
1970149871Sscottl			pAdapter, device_get_unit(pAdapter->hpt_dev), /*untagged*/1, /*tagged*/8,  devq)) == NULL)	{
1971136849Sscottl		cam_simq_free(devq);
1972136849Sscottl		return ENOMEM;
1973136849Sscottl	}
1974136849Sscottl
1975149871Sscottl	if(xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS)
1976149871Sscottl	{
1977136849Sscottl		cam_sim_free(hpt_vsim, /*free devq*/ TRUE);
1978136849Sscottl		hpt_vsim = NULL;
1979136849Sscottl		return ENXIO;
1980136849Sscottl	}
1981136849Sscottl
1982136849Sscottl	if(xpt_create_path(&pAdapter->path, /*periph */ NULL,
1983149871Sscottl			cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD,
1984149871Sscottl			CAM_LUN_WILDCARD) != CAM_REQ_CMP)
1985149871Sscottl	{
1986136849Sscottl		xpt_bus_deregister(cam_sim_path(hpt_vsim));
1987136849Sscottl		cam_sim_free(hpt_vsim, /*free_devq*/TRUE);
1988136849Sscottl		hpt_vsim = NULL;
1989136849Sscottl		return ENXIO;
1990136849Sscottl	}
1991136849Sscottl
1992136849Sscottl	xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5);
1993136849Sscottl	ccb->ccb_h.func_code = XPT_SASYNC_CB;
1994136849Sscottl	ccb->csa.event_enable = AC_LOST_DEVICE;
1995136849Sscottl	ccb->csa.callback = hpt_async;
1996136849Sscottl	ccb->csa.callback_arg = hpt_vsim;
1997136849Sscottl	xpt_action((union ccb *)ccb);
1998136849Sscottl	free(ccb, M_DEVBUF);
1999136849Sscottl
2000149871Sscottl	/* Register shutdown handler, and start the work thread. */
2001139044Snjl	if (device_get_unit(dev) == 0) {
2002149871Sscottl		pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_final,
2003149871Sscottl			hpt_shutdown, dev, SHUTDOWN_PRI_DEFAULT);
2004149871Sscottl		if (pAdapter->eh)
2005139044Snjl			launch_worker_thread();
2006139044Snjl		else
2007149871Sscottl			hpt_printk(("shutdown event registration failed\n"));
2008139044Snjl	}
2009136849Sscottl
2010136849Sscottl	return 0;
2011136849Sscottl}
2012136849Sscottl
2013136849Sscottlstatic int
2014136849Sscottlhpt_detach(device_t dev)
2015149871Sscottl{
2016136849Sscottl	return (EBUSY);
2017136849Sscottl}
2018136849Sscottl
2019149871Sscottl
2020136849Sscottl/***************************************************************
2021136849Sscottl * The poll function is used to simulate the interrupt when
2022136849Sscottl * the interrupt subsystem is not functioning.
2023136849Sscottl *
2024136849Sscottl ***************************************************************/
2025136849Sscottlstatic void
2026136849Sscottlhpt_poll(struct cam_sim *sim)
2027136849Sscottl{
2028136849Sscottl	hpt_intr((void *)cam_sim_softc(sim));
2029136849Sscottl}
2030136849Sscottl
2031136849Sscottl/****************************************************************
2032136849Sscottl *	Name:	hpt_intr
2033136849Sscottl *	Description:	Interrupt handler.
2034136849Sscottl ****************************************************************/
2035136849Sscottlstatic void
2036136849Sscottlhpt_intr(void *arg)
2037136849Sscottl{
2038136849Sscottl	IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg;
2039149871Sscottl	intrmask_t oldspl = lock_driver();
2040136849Sscottl
2041136849Sscottl	/* KdPrintI(("----- Entering Isr() -----\n")); */
2042149871Sscottl	if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE)
2043149871Sscottl	{
2044136849Sscottl		_VBUS_INST(&pAdapter->VBus)
2045136849Sscottl		CheckPendingCall(_VBUS_P0);
2046136849Sscottl	}
2047136849Sscottl
2048136849Sscottl	/* KdPrintI(("----- Leaving Isr() -----\n")); */
2049136849Sscottl	unlock_driver(oldspl);
2050136849Sscottl}
2051136849Sscottl
2052136849Sscottl/**********************************************************
2053136849Sscottl * 			Asynchronous Events
2054136849Sscottl *********************************************************/
2055136849Sscottl#if (!defined(UNREFERENCED_PARAMETER))
2056136849Sscottl#define UNREFERENCED_PARAMETER(x) (void)(x)
2057136849Sscottl#endif
2058136849Sscottl
2059136849Sscottlstatic void
2060136849Sscottlhpt_async(void * callback_arg, u_int32_t code, struct cam_path * path,
2061136849Sscottl    void * arg)
2062136849Sscottl{
2063136849Sscottl	/* debug XXXX */
2064136849Sscottl	panic("Here");
2065136849Sscottl	UNREFERENCED_PARAMETER(callback_arg);
2066136849Sscottl	UNREFERENCED_PARAMETER(code);
2067136849Sscottl	UNREFERENCED_PARAMETER(path);
2068136849Sscottl	UNREFERENCED_PARAMETER(arg);
2069136849Sscottl
2070136849Sscottl}
2071136849Sscottl
2072136849Sscottlstatic void
2073136849SscottlFlushAdapter(IAL_ADAPTER_T *pAdapter)
2074136849Sscottl{
2075136849Sscottl	int i;
2076136849Sscottl
2077136849Sscottl	hpt_printk(("flush all devices\n"));
2078136849Sscottl
2079136849Sscottl	/* flush all devices */
2080136849Sscottl	for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) {
2081136849Sscottl		PVDevice pVDev = pAdapter->VBus.pVDevice[i];
2082149871Sscottl		if(pVDev) fFlushVDev(pVDev);
2083136849Sscottl	}
2084136849Sscottl}
2085136849Sscottl
2086136849Sscottlstatic int
2087136849Sscottlhpt_shutdown(device_t dev)
2088136849Sscottl{
2089149871Sscottl		IAL_ADAPTER_T *pAdapter;
2090149871Sscottl
2091149871Sscottl		pAdapter = device_get_softc(dev);
2092149871Sscottl		if (pAdapter == NULL)
2093149871Sscottl			return (EINVAL);
2094136849Sscottl
2095149871Sscottl		EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh);
2096149871Sscottl		FlushAdapter(pAdapter);
2097149871Sscottl		  /* give the flush some time to happen,
2098149871Sscottl		    *otherwise "shutdown -p now" will make file system corrupted */
2099149871Sscottl		DELAY(1000 * 1000 * 5);
2100149871Sscottl		return 0;
2101136849Sscottl}
2102136849Sscottl
2103136849Sscottlvoid
2104136849SscottlCheck_Idle_Call(IAL_ADAPTER_T *pAdapter)
2105136849Sscottl{
2106136849Sscottl	_VBUS_INST(&pAdapter->VBus)
2107136849Sscottl
2108136849Sscottl	if (mWaitingForIdle(_VBUS_P0)) {
2109136849Sscottl		CheckIdleCall(_VBUS_P0);
2110136849Sscottl#ifdef SUPPORT_ARRAY
2111149871Sscottl		{
2112149871Sscottl			int i;
2113136849Sscottl			PVDevice pArray;
2114149871Sscottl			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){
2115149871Sscottl				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
2116149871Sscottl					continue;
2117149871Sscottl				else if (pArray->u.array.rf_auto_rebuild) {
2118149871Sscottl						KdPrint(("auto rebuild.\n"));
2119149871Sscottl						pArray->u.array.rf_auto_rebuild = 0;
2120149871Sscottl						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
2121149871Sscottl				}
2122136849Sscottl			}
2123136849Sscottl		}
2124136849Sscottl#endif
2125136849Sscottl	}
2126136849Sscottl	/* launch the awaiting commands blocked by mWaitingForIdle */
2127149871Sscottl	while(pAdapter->pending_Q!= NULL)
2128149871Sscottl	{
2129136849Sscottl		_VBUS_INST(&pAdapter->VBus)
2130149871Sscottl		union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr;
2131136849Sscottl		hpt_free_ccb(&pAdapter->pending_Q, ccb);
2132136849Sscottl		CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb);
2133136849Sscottl	}
2134136849Sscottl}
2135136849Sscottl
2136136849Sscottlstatic void
2137136849Sscottlccb_done(union ccb *ccb)
2138136849Sscottl{
2139149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2140149871Sscottl	IAL_ADAPTER_T * pAdapter = pmap->pAdapter;
2141149871Sscottl	KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status));
2142136849Sscottl
2143149871Sscottl	dmamap_put(pmap);
2144136849Sscottl	xpt_done(ccb);
2145136849Sscottl
2146136849Sscottl	pAdapter->outstandingCommands--;
2147136849Sscottl
2148149871Sscottl	if (pAdapter->outstandingCommands == 0)
2149149871Sscottl	{
2150136849Sscottl		if(DPC_Request_Nums == 0)
2151136849Sscottl			Check_Idle_Call(pAdapter);
2152136849Sscottl	}
2153136849Sscottl}
2154136849Sscottl
2155136849Sscottl/****************************************************************
2156136849Sscottl *	Name:	hpt_action
2157136849Sscottl *	Description:	Process a queued command from the CAM layer.
2158136849Sscottl *	Parameters:		sim - Pointer to SIM object
2159136849Sscottl *					ccb - Pointer to SCSI command structure.
2160136849Sscottl ****************************************************************/
2161136849Sscottl
2162136849Sscottlvoid
2163136849Sscottlhpt_action(struct cam_sim *sim, union ccb *ccb)
2164136849Sscottl{
2165136849Sscottl	intrmask_t oldspl;
2166136849Sscottl	IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim);
2167149871Sscottl	PBUS_DMAMAP  pmap;
2168136849Sscottl	_VBUS_INST(&pAdapter->VBus)
2169136849Sscottl
2170149871Sscottl	CAM_DEBUG(ccb->ccb_h->path, CAM_DEBUG_TRACE, ("hpt_action\n"));
2171149871Sscottl	KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code));
2172136849Sscottl
2173149871Sscottl	switch (ccb->ccb_h.func_code)
2174149871Sscottl	{
2175149871Sscottl		case XPT_SCSI_IO:	/* Execute the requested I/O operation */
2176149871Sscottl		{
2177149871Sscottl			/* ccb->ccb_h.path_id is not our bus id - don't check it */
2178136849Sscottl
2179149871Sscottl			if (ccb->ccb_h.target_lun)	{
2180149871Sscottl				ccb->ccb_h.status = CAM_LUN_INVALID;
2181149871Sscottl				xpt_done(ccb);
2182149871Sscottl				return;
2183149871Sscottl			}
2184149871Sscottl			if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS ||
2185149871Sscottl				pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) {
2186149871Sscottl				ccb->ccb_h.status = CAM_TID_INVALID;
2187149871Sscottl				xpt_done(ccb);
2188149871Sscottl				return;
2189149871Sscottl			}
2190136849Sscottl
2191149871Sscottl			oldspl = lock_driver();
2192149871Sscottl			if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
2193149871Sscottl				Check_Idle_Call(pAdapter);
2194136849Sscottl
2195149871Sscottl			pmap = dmamap_get(pAdapter);
2196149871Sscottl			HPT_ASSERT(pmap);
2197149871Sscottl			ccb->ccb_adapter = pmap;
2198149871Sscottl			memset((void *)pmap->psg, 0,  sizeof(pmap->psg));
2199136849Sscottl
2200149871Sscottl			if (mWaitingForIdle(_VBUS_P0))
2201149871Sscottl				hpt_queue_ccb(&pAdapter->pending_Q, ccb);
2202149871Sscottl			else
2203149871Sscottl				OsSendCommand(_VBUS_P ccb);
2204149871Sscottl			unlock_driver(oldspl);
2205136849Sscottl
2206149871Sscottl			/* KdPrint(("leave scsiio\n")); */
2207149871Sscottl			break;
2208149871Sscottl		}
2209136849Sscottl
2210149871Sscottl		case XPT_RESET_BUS:
2211149871Sscottl			KdPrint(("reset bus\n"));
2212149871Sscottl			oldspl = lock_driver();
2213149871Sscottl			fResetVBus(_VBUS_P0);
2214149871Sscottl			unlock_driver(oldspl);
2215149871Sscottl			xpt_done(ccb);
2216149871Sscottl			break;
2217136849Sscottl
2218149871Sscottl		case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
2219149871Sscottl		case XPT_EN_LUN:		/* Enable LUN as a target */
2220149871Sscottl		case XPT_TARGET_IO:		/* Execute target I/O request */
2221149871Sscottl		case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
2222149871Sscottl		case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
2223149871Sscottl		case XPT_ABORT:			/* Abort the specified CCB */
2224149871Sscottl		case XPT_TERM_IO:		/* Terminate the I/O process */
2225149871Sscottl			/* XXX Implement */
2226149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2227149871Sscottl			xpt_done(ccb);
2228149871Sscottl			break;
2229136849Sscottl
2230149871Sscottl		case XPT_GET_TRAN_SETTINGS:
2231149871Sscottl		case XPT_SET_TRAN_SETTINGS:
2232149871Sscottl			/* XXX Implement */
2233149871Sscottl			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2234149871Sscottl			xpt_done(ccb);
2235149871Sscottl			break;
2236136849Sscottl
2237149871Sscottl		case XPT_CALC_GEOMETRY:
2238149871Sscottl		{
2239149871Sscottl			struct	  ccb_calc_geometry *ccg;
2240149871Sscottl			u_int32_t size_mb;
2241149871Sscottl			u_int32_t secs_per_cylinder;
2242136849Sscottl
2243149871Sscottl			ccg = &ccb->ccg;
2244149871Sscottl			size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);
2245149871Sscottl
2246149871Sscottl			if (size_mb > 1024 ) {
2247149871Sscottl				ccg->heads = 255;
2248149871Sscottl				ccg->secs_per_track = 63;
2249149871Sscottl			} else {
2250149871Sscottl				ccg->heads = 64;
2251149871Sscottl				ccg->secs_per_track = 32;
2252149871Sscottl			}
2253149871Sscottl			secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2254149871Sscottl			ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2255149871Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
2256149871Sscottl			xpt_done(ccb);
2257149871Sscottl			break;
2258136849Sscottl		}
2259136849Sscottl
2260149871Sscottl		case XPT_PATH_INQ:		/* Path routing inquiry */
2261149871Sscottl		{
2262149871Sscottl			struct ccb_pathinq *cpi = &ccb->cpi;
2263136849Sscottl
2264149871Sscottl			cpi->version_num = 1; /* XXX??? */
2265149871Sscottl			cpi->hba_inquiry = PI_SDTR_ABLE;
2266149871Sscottl			cpi->target_sprt = 0;
2267149871Sscottl			/* Not necessary to reset bus */
2268149871Sscottl			cpi->hba_misc = PIM_NOBUSRESET;
2269149871Sscottl			cpi->hba_eng_cnt = 0;
2270136849Sscottl
2271149871Sscottl			cpi->max_target = MAX_VDEVICE_PER_VBUS;
2272149871Sscottl			cpi->max_lun = 0;
2273149871Sscottl			cpi->initiator_id = MAX_VDEVICE_PER_VBUS;
2274136849Sscottl
2275149871Sscottl			cpi->bus_id = cam_sim_bus(sim);
2276149871Sscottl			cpi->base_transfer_speed = 3300;
2277149871Sscottl			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2278149871Sscottl			strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
2279149871Sscottl			strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2280149871Sscottl			cpi->unit_number = cam_sim_unit(sim);
2281149871Sscottl			cpi->ccb_h.status = CAM_REQ_CMP;
2282149871Sscottl			xpt_done(ccb);
2283149871Sscottl			break;
2284149871Sscottl		}
2285136849Sscottl
2286149871Sscottl		default:
2287149871Sscottl			KdPrint(("invalid cmd\n"));
2288149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2289149871Sscottl			xpt_done(ccb);
2290149871Sscottl			break;
2291136849Sscottl	}
2292136849Sscottl	/* KdPrint(("leave hpt_action..............\n")); */
2293136849Sscottl}
2294136849Sscottl
2295136849Sscottl/* shall be called at lock_driver() */
2296136849Sscottlstatic void
2297136849Sscottlhpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb)
2298136849Sscottl{
2299136849Sscottl	if(*ccb_Q == NULL)
2300136849Sscottl		ccb->ccb_h.ccb_ccb_ptr = ccb;
2301136849Sscottl	else {
2302136849Sscottl		ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr;
2303136849Sscottl		(*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb;
2304136849Sscottl	}
2305136849Sscottl
2306136849Sscottl	*ccb_Q = ccb;
2307136849Sscottl}
2308136849Sscottl
2309136849Sscottl/* shall be called at lock_driver() */
2310136849Sscottlstatic void
2311136849Sscottlhpt_free_ccb(union ccb **ccb_Q, union ccb *ccb)
2312136849Sscottl{
2313136849Sscottl	union ccb *TempCCB;
2314136849Sscottl
2315136849Sscottl	TempCCB = *ccb_Q;
2316136849Sscottl
2317149871Sscottl	if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/
2318136849Sscottl		*ccb_Q = NULL;
2319136849Sscottl	else {
2320136849Sscottl		while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb)
2321136849Sscottl			TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr;
2322136849Sscottl
2323136849Sscottl		TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr;
2324136849Sscottl
2325136849Sscottl		if(*ccb_Q == ccb)
2326136849Sscottl			*ccb_Q = TempCCB;
2327136849Sscottl	}
2328136849Sscottl}
2329136849Sscottl
2330136849Sscottl#ifdef SUPPORT_ARRAY
2331136849Sscottl/***************************************************************************
2332136849Sscottl * Function:     hpt_worker_thread
2333136849Sscottl * Description:  Do background rebuilding. Execute in kernel thread context.
2334136849Sscottl * Returns:      None
2335136849Sscottl ***************************************************************************/
2336136849Sscottlstatic void hpt_worker_thread(void)
2337136849Sscottl{
2338136849Sscottl	intrmask_t oldspl;
2339136849Sscottl
2340136849Sscottl	for(;;)	{
2341136849Sscottl		while (DpcQueue_First!=DpcQueue_Last) {
2342136849Sscottl			ST_HPT_DPC p;
2343136849Sscottl			oldspl = lock_driver();
2344136849Sscottl			p = DpcQueue[DpcQueue_First];
2345136849Sscottl			DpcQueue_First++;
2346136849Sscottl			DpcQueue_First %= MAX_DPC;
2347136849Sscottl			DPC_Request_Nums++;
2348136849Sscottl			unlock_driver(oldspl);
2349136849Sscottl			p.dpc(p.pAdapter, p.arg, p.flags);
2350136849Sscottl
2351136849Sscottl			oldspl = lock_driver();
2352136849Sscottl			DPC_Request_Nums--;
2353149871Sscottl			/* since we may have prevented Check_Idle_Call, do it here */
2354136849Sscottl			if (DPC_Request_Nums==0) {
2355136849Sscottl				if (p.pAdapter->outstandingCommands == 0) {
2356136849Sscottl					_VBUS_INST(&p.pAdapter->VBus);
2357136849Sscottl					Check_Idle_Call(p.pAdapter);
2358136849Sscottl					CheckPendingCall(_VBUS_P0);
2359136849Sscottl				}
2360136849Sscottl			}
2361136849Sscottl			unlock_driver(oldspl);
2362136849Sscottl
2363149871Sscottl			/*Schedule out*/
2364149871Sscottl#if (__FreeBSD_version < 500000)
2365149871Sscottl			YIELD_THREAD;
2366149871Sscottl#else
2367149871Sscottl			tsleep((caddr_t)hpt_worker_thread, PPAUSE, "sched", 1);
2368149871Sscottl#endif
2369149871Sscottl			if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) {
2370149871Sscottl				/* abort rebuilding process. */
2371149871Sscottl				IAL_ADAPTER_T *pAdapter;
2372149871Sscottl				PVDevice      pArray;
2373149871Sscottl				PVBus         _vbus_p;
2374149871Sscottl				int i;
2375149871Sscottl				pAdapter = gIal_Adapter;
2376149871Sscottl
2377149871Sscottl				while(pAdapter != 0){
2378149871Sscottl
2379149871Sscottl					_vbus_p = &pAdapter->VBus;
2380149871Sscottl
2381149871Sscottl					for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
2382149871Sscottl					{
2383149871Sscottl						if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
2384149871Sscottl							continue;
2385149871Sscottl						else if (pArray->u.array.rf_rebuilding ||
2386149871Sscottl								pArray->u.array.rf_verifying ||
2387149871Sscottl								pArray->u.array.rf_initializing)
2388149871Sscottl							{
2389149871Sscottl								pArray->u.array.rf_abort_rebuild = 1;
2390149871Sscottl							}
2391136849Sscottl					}
2392149871Sscottl					pAdapter = pAdapter->next;
2393136849Sscottl				}
2394136849Sscottl			}
2395136849Sscottl		}
2396136849Sscottl
2397149871Sscottl/*Remove this debug option*/
2398149871Sscottl/*
2399136849Sscottl#ifdef DEBUG
2400136849Sscottl		if (SIGISMEMBER(curproc->p_siglist, SIGSTOP))
2401149871Sscottl			tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz);
2402136849Sscottl#endif
2403149871Sscottl*/
2404149871Sscottl	#if (__FreeBSD_version >= 500043)
2405136849Sscottl		kthread_suspend_check(curproc);
2406149871Sscottl	#else
2407136849Sscottl		kproc_suspend_loop(curproc);
2408149871Sscottl	#endif
2409149871Sscottl		tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz);  /* wait for something to do */
2410136849Sscottl	}
2411136849Sscottl}
2412136849Sscottl
2413136849Sscottlstatic struct proc *hptdaemonproc;
2414136849Sscottlstatic struct kproc_desc hpt_kp = {
2415136849Sscottl	"hpt_wt",
2416136849Sscottl	hpt_worker_thread,
2417136849Sscottl	&hptdaemonproc
2418136849Sscottl};
2419136849Sscottl
2420149871Sscottl/*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/
2421136849Sscottlstatic void
2422136849Sscottllaunch_worker_thread(void)
2423136849Sscottl{
2424136849Sscottl	IAL_ADAPTER_T *pAdapTemp;
2425136849Sscottl
2426136849Sscottl	kproc_start(&hpt_kp);
2427136849Sscottl
2428136849Sscottl	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
2429136849Sscottl
2430136849Sscottl		_VBUS_INST(&pAdapTemp->VBus)
2431136849Sscottl		int i;
2432136849Sscottl		PVDevice pVDev;
2433136849Sscottl
2434136849Sscottl		for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
2435136849Sscottl			if ((pVDev=ArrayTables(i))->u.array.dArStamp==0)
2436136849Sscottl				continue;
2437149871Sscottl			else{
2438149871Sscottl				if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding)
2439149871Sscottl					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev,
2440149871Sscottl					(UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
2441149871Sscottl			}
2442136849Sscottl	}
2443136849Sscottl
2444136849Sscottl	/*
2445149871Sscottl	 * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished.
2446136849Sscottl	 */
2447136849Sscottl#if (__FreeBSD_version < 500043)
2448149871Sscottl	EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST);
2449149871Sscottl#else
2450149871Sscottl	EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, SHUTDOWN_PRI_FIRST);
2451136849Sscottl#endif
2452136849Sscottl}
2453149871Sscottl/*
2454149871Sscottl *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL);
2455149871Sscottl*/
2456136849Sscottl
2457149871Sscottl#endif
2458136849Sscottl
2459136849Sscottl/********************************************************************************/
2460136849Sscottl
2461149871Sscottlint HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical)
2462136849Sscottl{
2463149871Sscottl	union ccb *ccb = (union ccb *)pCmd->pOrgCommand;
2464149871Sscottl	bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
2465136849Sscottl	int idx;
2466136849Sscottl
2467149871Sscottl	if(logical) {
2468149871Sscottl		if (ccb->ccb_h.flags & CAM_DATA_PHYS)
2469149871Sscottl			panic("physical address unsupported");
2470136849Sscottl
2471149871Sscottl		if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
2472149871Sscottl			if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
2473149871Sscottl				panic("physical address unsupported");
2474149871Sscottl
2475149871Sscottl			for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
2476149871Sscottl				pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr;
2477149871Sscottl				pSg[idx].wSgSize = sgList[idx].ds_len;
2478149871Sscottl				pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0;
2479149871Sscottl			}
2480149871Sscottl		}
2481149871Sscottl		else {
2482149871Sscottl			pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr;
2483149871Sscottl			pSg->wSgSize = ccb->csio.dxfer_len;
2484149871Sscottl			pSg->wSgFlag = SG_FLAG_EOT;
2485149871Sscottl		}
2486136849Sscottl		return TRUE;
2487136849Sscottl	}
2488149871Sscottl
2489149871Sscottl	/* since we have provided physical sg, nobody will ask us to build physical sg */
2490149871Sscottl	HPT_ASSERT(0);
2491149871Sscottl	return FALSE;
2492136849Sscottl}
2493136849Sscottl
2494136849Sscottl/*******************************************************************************/
2495136849SscottlULONG HPTLIBAPI
2496136849SscottlGetStamp(void)
2497136849Sscottl{
2498136849Sscottl	/*
2499136849Sscottl	 * the system variable, ticks, can't be used since it hasn't yet been active
2500136849Sscottl	 * when our driver starts (ticks==0, it's a invalid stamp value)
2501136849Sscottl	 */
2502149871Sscottl	ULONG stamp;
2503149871Sscottl	do { stamp = random(); } while (stamp==0);
2504136849Sscottl	return stamp;
2505136849Sscottl}
2506136849Sscottl
2507136849Sscottl
2508136849Sscottlstatic void
2509136849SscottlSetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev)
2510136849Sscottl{
2511136849Sscottl	int i;
2512149871Sscottl	IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice;
2513149871Sscottl
2514136849Sscottl	inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/
2515136849Sscottl	inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5);
2516136849Sscottl#ifndef SERIAL_CMDS
2517136849Sscottl	inquiryData->CommandQueue = 1;
2518136849Sscottl#endif
2519136849Sscottl
2520136849Sscottl	switch(pVDev->VDeviceType) {
2521136849Sscottl	case VD_SINGLE_DISK:
2522136849Sscottl	case VD_ATAPI:
2523136849Sscottl	case VD_REMOVABLE:
2524136849Sscottl		/* Set the removable bit, if applicable. */
2525149871Sscottl		if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80))
2526136849Sscottl			inquiryData->RemovableMedia = 1;
2527136849Sscottl
2528136849Sscottl		/* Fill in vendor identification fields. */
2529149871Sscottl		for (i = 0; i < 20; i += 2) {
2530149871Sscottl			inquiryData->VendorId[i] 	= ((PUCHAR)pIdentify->ModelNumber)[i + 1];
2531149871Sscottl			inquiryData->VendorId[i+1] 	= ((PUCHAR)pIdentify->ModelNumber)[i];
2532136849Sscottl
2533136849Sscottl		}
2534136849Sscottl
2535136849Sscottl		/* Initialize unused portion of product id. */
2536136849Sscottl		for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' ';
2537136849Sscottl
2538136849Sscottl		/* firmware revision */
2539149871Sscottl		for (i = 0; i < 4; i += 2)
2540149871Sscottl		{
2541149871Sscottl			inquiryData->ProductRevisionLevel[i] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i+1];
2542149871Sscottl			inquiryData->ProductRevisionLevel[i+1] 	= ((PUCHAR)pIdentify->FirmwareRevision)[i];
2543136849Sscottl		}
2544136849Sscottl		break;
2545136849Sscottl	default:
2546136849Sscottl		memcpy(&inquiryData->VendorId, "RR182x  ", 8);
2547136849Sscottl#ifdef SUPPORT_ARRAY
2548149871Sscottl		switch(pVDev->VDeviceType){
2549136849Sscottl		case VD_RAID_0:
2550149871Sscottl			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
2551149871Sscottl				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
2552149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 1/0 Array  ", 16);
2553136849Sscottl			else
2554149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 0 Array    ", 16);
2555136849Sscottl			break;
2556136849Sscottl		case VD_RAID_1:
2557149871Sscottl			if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) ||
2558149871Sscottl				(pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1])))
2559149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 0/1 Array  ", 16);
2560136849Sscottl			else
2561149871Sscottl				memcpy(&inquiryData->ProductId, "RAID 1 Array    ", 16);
2562136849Sscottl			break;
2563136849Sscottl		case VD_RAID_5:
2564136849Sscottl			memcpy(&inquiryData->ProductId, "RAID 5 Array    ", 16);
2565136849Sscottl			break;
2566136849Sscottl		case VD_JBOD:
2567136849Sscottl			memcpy(&inquiryData->ProductId, "JBOD Array      ", 16);
2568136849Sscottl			break;
2569136849Sscottl		}
2570136849Sscottl#endif
2571136849Sscottl		memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4);
2572136849Sscottl		break;
2573136849Sscottl	}
2574136849Sscottl}
2575136849Sscottl
2576136849Sscottlstatic void
2577136849Sscottlhpt_timeout(void *arg)
2578136849Sscottl{
2579149871Sscottl	_VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus)
2580149871Sscottl	intrmask_t oldspl = lock_driver();
2581136849Sscottl	fResetVBus(_VBUS_P0);
2582136849Sscottl	unlock_driver(oldspl);
2583136849Sscottl}
2584136849Sscottl
2585149871Sscottlstatic void
2586149871Sscottlhpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
2587149871Sscottl{
2588149871Sscottl	PCommand pCmd = (PCommand)arg;
2589149871Sscottl	union ccb *ccb = pCmd->pOrgCommand;
2590149871Sscottl	struct ccb_hdr *ccb_h = &ccb->ccb_h;
2591149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter;
2592149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2593149871Sscottl	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
2594149871Sscottl	FPSCAT_GATH psg = pCmd->pSgTable;
2595149871Sscottl	int idx;
2596149871Sscottl	_VBUS_INST(pVDev->pVBus)
2597149871Sscottl
2598149871Sscottl	HPT_ASSERT(pCmd->cf_physical_sg);
2599149871Sscottl
2600149871Sscottl	if (error || nsegs == 0)
2601149871Sscottl		panic("busdma error");
2602149871Sscottl
2603149871Sscottl	HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS);
2604149871Sscottl
2605149871Sscottl	for (idx = 0; idx < nsegs; idx++, psg++) {
2606149871Sscottl		psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr;
2607149871Sscottl		psg->wSgSize = segs[idx].ds_len;
2608149871Sscottl		psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0;
2609149871Sscottl/*		KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */
2610149871Sscottl	}
2611149871Sscottl/*	psg[-1].wSgFlag = SG_FLAG_EOT; */
2612149871Sscottl
2613149871Sscottl	if (pCmd->cf_data_in) {
2614149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD);
2615149871Sscottl	}
2616149871Sscottl	else if (pCmd->cf_data_out) {
2617149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE);
2618149871Sscottl	}
2619149871Sscottl
2620149871Sscottl	ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz);
2621149871Sscottl	pVDev->pfnSendCommand(_VBUS_P pCmd);
2622149871Sscottl	CheckPendingCall(_VBUS_P0);
2623149871Sscottl}
2624149871Sscottl
2625149871Sscottl
2626149871Sscottl
2627136849Sscottlstatic void HPTLIBAPI
2628136849SscottlOsSendCommand(_VBUS_ARG union ccb *ccb)
2629136849Sscottl{
2630149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2631149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2632149871Sscottl	struct ccb_hdr *ccb_h = &ccb->ccb_h;
2633149871Sscottl	struct ccb_scsiio *csio = &ccb->csio;
2634149871Sscottl	PVDevice	pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id];
2635136849Sscottl
2636149871Sscottl	KdPrintI(("OsSendCommand: ccb %p  cdb %x-%x-%x\n",
2637136849Sscottl		ccb,
2638136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0],
2639136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4],
2640136849Sscottl		*(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8]
2641136849Sscottl	));
2642136849Sscottl
2643136849Sscottl	pAdapter->outstandingCommands++;
2644136849Sscottl
2645136849Sscottl	if (pVDev == NULL || pVDev->vf_online == 0) {
2646136849Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2647136849Sscottl		ccb_done(ccb);
2648136849Sscottl		goto Command_Complished;
2649136849Sscottl	}
2650136849Sscottl
2651136849Sscottl	switch(ccb->csio.cdb_io.cdb_bytes[0])
2652136849Sscottl	{
2653149871Sscottl		case TEST_UNIT_READY:
2654149871Sscottl		case START_STOP_UNIT:
2655149871Sscottl		case SYNCHRONIZE_CACHE:
2656149871Sscottl			/* FALLTHROUGH */
2657149871Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
2658149871Sscottl			break;
2659136849Sscottl
2660149871Sscottl		case INQUIRY:
2661149871Sscottl			ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len);
2662149871Sscottl			SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev);
2663149871Sscottl			ccb_h->status = CAM_REQ_CMP;
2664149871Sscottl			break;
2665136849Sscottl
2666149871Sscottl		case READ_CAPACITY:
2667149871Sscottl		{
2668149871Sscottl			UCHAR swip[4];
2669149871Sscottl			/* Claim 512 byte blocks (big-endian). */
2670149871Sscottl			((PREAD_CAPACITY_DATA)csio->data_ptr)->BytesPerBlock = 0x20000;
2671149871Sscottl			*(ULONG*)swip = pVDev->VDeviceCapacity - 1;
2672149871Sscottl			((PREAD_CAPACITY_DATA)csio->data_ptr)->LogicalBlockAddress =
2673149871Sscottl				(swip[0] << 24) |  (swip[1] << 16) | (swip[2] << 8) | swip[3];
2674149871Sscottl			ccb_h->status = CAM_REQ_CMP;
2675149871Sscottl			break;
2676136849Sscottl		}
2677136849Sscottl
2678136849Sscottl		case READ_6:
2679136849Sscottl		case WRITE_6:
2680136849Sscottl		case READ_10:
2681136849Sscottl		case WRITE_10:
2682136849Sscottl		case 0x13:
2683136849Sscottl		case 0x2f:
2684149871Sscottl		{
2685149871Sscottl			UCHAR Cdb[16];
2686149871Sscottl			UCHAR CdbLength;
2687149871Sscottl			_VBUS_INST(pVDev->pVBus)
2688149871Sscottl			PCommand pCmd = AllocateCommand(_VBUS_P0);
2689149871Sscottl			HPT_ASSERT(pCmd);
2690136849Sscottl
2691149871Sscottl			CdbLength = csio->cdb_len;
2692149871Sscottl			if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
2693149871Sscottl			{
2694149871Sscottl				if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0)
2695149871Sscottl				{
2696149871Sscottl					bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength);
2697149871Sscottl				}
2698149871Sscottl				else
2699149871Sscottl				{
2700149871Sscottl					KdPrintE(("ERROR!!!\n"));
2701149871Sscottl					ccb->ccb_h.status = CAM_REQ_INVALID;
2702149871Sscottl					break;
2703149871Sscottl				}
2704149871Sscottl			}
2705149871Sscottl			else
2706149871Sscottl			{
2707149871Sscottl				bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength);
2708149871Sscottl			}
2709136849Sscottl
2710149871Sscottl			pCmd->pOrgCommand = ccb;
2711149871Sscottl			pCmd->pVDevice = pVDev;
2712149871Sscottl			pCmd->pfnCompletion = fOsCommandDone;
2713149871Sscottl			pCmd->pfnBuildSgl = fOsBuildSgl;
2714149871Sscottl			pCmd->pSgTable = pmap->psg;
2715136849Sscottl
2716149871Sscottl			switch (Cdb[0])
2717149871Sscottl			{
2718149871Sscottl				case READ_6:
2719149871Sscottl				case WRITE_6:
2720149871Sscottl				case 0x13:
2721149871Sscottl					pCmd->uCmd.Ide.Lba =  ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3];
2722149871Sscottl					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4];
2723149871Sscottl					break;
2724149871Sscottl
2725149871Sscottl				default:
2726149871Sscottl					pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24);
2727149871Sscottl					pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8);
2728149871Sscottl					break;
2729149871Sscottl			}
2730149871Sscottl
2731149871Sscottl			switch (Cdb[0])
2732149871Sscottl			{
2733149871Sscottl				case READ_6:
2734149871Sscottl				case READ_10:
2735149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_READ;
2736149871Sscottl					pCmd->cf_data_in = 1;
2737149871Sscottl					break;
2738149871Sscottl
2739149871Sscottl				case WRITE_6:
2740149871Sscottl				case WRITE_10:
2741149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE;
2742149871Sscottl					pCmd->cf_data_out = 1;
2743149871Sscottl					break;
2744149871Sscottl				case 0x13:
2745149871Sscottl				case 0x2f:
2746149871Sscottl					pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY;
2747149871Sscottl					break;
2748149871Sscottl			}
2749149871Sscottl/*///////////////////////// */
2750149871Sscottl			if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
2751149871Sscottl				int idx;
2752149871Sscottl				bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
2753149871Sscottl
2754149871Sscottl				if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
2755149871Sscottl					pCmd->cf_physical_sg = 1;
2756149871Sscottl
2757149871Sscottl				for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
2758149871Sscottl					pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr;
2759149871Sscottl					pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len;
2760149871Sscottl					pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0;
2761149871Sscottl				}
2762149871Sscottl
2763149871Sscottl				ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz);
2764149871Sscottl				pVDev->pfnSendCommand(_VBUS_P pCmd);
2765149871Sscottl			}
2766149871Sscottl			else {
2767149871Sscottl				int error;
2768149871Sscottl				pCmd->cf_physical_sg = 1;
2769149871Sscottl				error = bus_dmamap_load(pAdapter->io_dma_parent,
2770149871Sscottl							pmap->dma_map,
2771149871Sscottl							ccb->csio.data_ptr, ccb->csio.dxfer_len,
2772149871Sscottl							hpt_io_dmamap_callback, pCmd,
2773149871Sscottl					    		BUS_DMA_WAITOK
2774149871Sscottl						);
2775149871Sscottl				KdPrint(("bus_dmamap_load return %d\n", error));
2776149871Sscottl				if (error && error!=EINPROGRESS) {
2777149871Sscottl					hpt_printk(("bus_dmamap_load error %d\n", error));
2778149871Sscottl					FreeCommand(_VBUS_P pCmd);
2779149871Sscottl					ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2780149871Sscottl					dmamap_put(pmap);
2781149871Sscottl					pAdapter->outstandingCommands--;
2782149871Sscottl					xpt_done(ccb);
2783149871Sscottl				}
2784149871Sscottl			}
2785149871Sscottl			goto Command_Complished;
2786149871Sscottl		}
2787149871Sscottl
2788149871Sscottl		default:
2789149871Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
2790149871Sscottl			break;
2791136849Sscottl	}
2792136849Sscottl	ccb_done(ccb);
2793136849SscottlCommand_Complished:
2794136849Sscottl	CheckPendingCall(_VBUS_P0);
2795136849Sscottl	return;
2796136849Sscottl}
2797136849Sscottl
2798149871Sscottlstatic void HPTLIBAPI
2799136849SscottlfOsCommandDone(_VBUS_ARG PCommand pCmd)
2800136849Sscottl{
2801149871Sscottl	union ccb *ccb = pCmd->pOrgCommand;
2802149871Sscottl	PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter;
2803149871Sscottl	IAL_ADAPTER_T *pAdapter = pmap->pAdapter;
2804136849Sscottl
2805149871Sscottl	KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result));
2806136849Sscottl
2807136849Sscottl	untimeout(hpt_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch);
2808136849Sscottl
2809136849Sscottl	switch(pCmd->Result) {
2810136849Sscottl	case RETURN_SUCCESS:
2811136849Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2812136849Sscottl		break;
2813136849Sscottl	case RETURN_BAD_DEVICE:
2814136849Sscottl		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2815136849Sscottl		break;
2816136849Sscottl	case RETURN_DEVICE_BUSY:
2817136849Sscottl		ccb->ccb_h.status = CAM_BUSY;
2818136849Sscottl		break;
2819136849Sscottl	case RETURN_INVALID_REQUEST:
2820136849Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2821136849Sscottl		break;
2822136849Sscottl	case RETURN_SELECTION_TIMEOUT:
2823136849Sscottl		ccb->ccb_h.status = CAM_SEL_TIMEOUT;
2824136849Sscottl		break;
2825136849Sscottl	case RETURN_RETRY:
2826136849Sscottl		ccb->ccb_h.status = CAM_BUSY;
2827136849Sscottl		break;
2828136849Sscottl	default:
2829136849Sscottl		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
2830136849Sscottl		break;
2831136849Sscottl	}
2832136849Sscottl
2833149871Sscottl	if (pCmd->cf_data_in) {
2834149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD);
2835136849Sscottl	}
2836149871Sscottl	else if (pCmd->cf_data_in) {
2837149871Sscottl		bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE);
2838149871Sscottl	}
2839149871Sscottl
2840149871Sscottl	bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map);
2841136849Sscottl
2842136849Sscottl	FreeCommand(_VBUS_P pCmd);
2843136849Sscottl	ccb_done(ccb);
2844136849Sscottl}
2845136849Sscottl
2846136849Sscottlint
2847136849Sscottlhpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags)
2848136849Sscottl{
2849136849Sscottl	int p;
2850136849Sscottl
2851136849Sscottl	p = (DpcQueue_Last + 1) % MAX_DPC;
2852136849Sscottl	if (p==DpcQueue_First) {
2853136849Sscottl		KdPrint(("DPC Queue full!\n"));
2854136849Sscottl		return -1;
2855136849Sscottl	}
2856136849Sscottl
2857136849Sscottl	DpcQueue[DpcQueue_Last].dpc = dpc;
2858136849Sscottl	DpcQueue[DpcQueue_Last].pAdapter = pAdapter;
2859136849Sscottl	DpcQueue[DpcQueue_Last].arg = arg;
2860136849Sscottl	DpcQueue[DpcQueue_Last].flags = flags;
2861136849Sscottl	DpcQueue_Last = p;
2862136849Sscottl
2863136849Sscottl	return 0;
2864136849Sscottl}
2865136849Sscottl
2866136849Sscottl#ifdef _RAID5N_
2867136849Sscottl/*
2868149871Sscottl * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices.
2869149871Sscottl * How about the memory for 5081 request/response array and PRD table?
2870136849Sscottl */
2871136849Sscottlvoid
2872136849Sscottl*os_alloc_page(_VBUS_ARG0)
2873136849Sscottl{
2874149871Sscottl	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
2875136849Sscottl}
2876149871Sscottl
2877136849Sscottlvoid
2878136849Sscottl*os_alloc_dma_page(_VBUS_ARG0)
2879136849Sscottl{
2880149871Sscottl	return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul);
2881136849Sscottl}
2882136849Sscottl
2883136849Sscottlvoid
2884149871Sscottlos_free_page(_VBUS_ARG void *p)
2885149871Sscottl{
2886149871Sscottl	contigfree(p, 0x1000, M_DEVBUF);
2887136849Sscottl}
2888136849Sscottl
2889136849Sscottlvoid
2890149871Sscottlos_free_dma_page(_VBUS_ARG void *p)
2891149871Sscottl{
2892149871Sscottl	contigfree(p, 0x1000, M_DEVBUF);
2893136849Sscottl}
2894136849Sscottl
2895136849Sscottlvoid
2896136849SscottlDoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes)
2897136849Sscottl{
2898136849Sscottl	UINT i;
2899149871Sscottl	for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++;
2900136849Sscottl}
2901136849Sscottl
2902136849Sscottlvoid
2903136849SscottlDoXor2(ULONG *p0, ULONG *p2, UINT nBytes)
2904136849Sscottl{
2905136849Sscottl	UINT i;
2906149871Sscottl	for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++;
2907136849Sscottl}
2908136849Sscottl#endif
2909