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