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