entry.c revision 315221
1149871Sscottl/* 2149871Sscottl * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 3136849Sscottl * All rights reserved. 4136849Sscottl * 5136849Sscottl * Redistribution and use in source and binary forms, with or without 6136849Sscottl * modification, are permitted provided that the following conditions 7136849Sscottl * are met: 8136849Sscottl * 1. Redistributions of source code must retain the above copyright 9136849Sscottl * notice, this list of conditions and the following disclaimer. 10136849Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11136849Sscottl * notice, this list of conditions and the following disclaimer in the 12136849Sscottl * documentation and/or other materials provided with the distribution. 13136849Sscottl * 14136849Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15136849Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16136849Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17136849Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18136849Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19136849Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20136849Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21136849Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22136849Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23136849Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24136849Sscottl * SUCH DAMAGE. 25136849Sscottl */ 26227912Smarius 27227912Smarius#include <sys/cdefs.h> 28227912Smarius__FBSDID("$FreeBSD: stable/11/sys/dev/hptmv/entry.c 315221 2017-03-14 02:06:03Z pfg $"); 29149871Sscottl 30136849Sscottl#include <sys/param.h> 31136849Sscottl#include <sys/systm.h> 32136849Sscottl#include <sys/kernel.h> 33136849Sscottl#include <sys/bus.h> 34136849Sscottl#include <sys/malloc.h> 35136849Sscottl#include <sys/resource.h> 36136849Sscottl#include <sys/time.h> 37136849Sscottl#include <sys/callout.h> 38136849Sscottl#include <sys/signalvar.h> 39136849Sscottl#include <sys/eventhandler.h> 40136849Sscottl#include <sys/proc.h> 41136849Sscottl#include <sys/kthread.h> 42136849Sscottl 43149871Sscottl#include <sys/mutex.h> 44149871Sscottl#include <sys/module.h> 45269617Sjhb#include <sys/sx.h> 46149871Sscottl 47136849Sscottl#include <dev/pci/pcireg.h> 48136849Sscottl#include <dev/pci/pcivar.h> 49136849Sscottl 50149871Sscottl#ifndef __KERNEL__ 51149871Sscottl#define __KERNEL__ 52149871Sscottl#endif 53149871Sscottl 54136849Sscottl#include <dev/hptmv/global.h> 55136849Sscottl#include <dev/hptmv/hptintf.h> 56136849Sscottl#include <dev/hptmv/osbsd.h> 57143039Sscottl#include <dev/hptmv/access601.h> 58136849Sscottl 59149871Sscottl 60136849Sscottl#ifdef DEBUG 61136849Sscottl#ifdef DEBUG_LEVEL 62136849Sscottlint hpt_dbg_level = DEBUG_LEVEL; 63149871Sscottl#else 64136849Sscottlint hpt_dbg_level = 0; 65136849Sscottl#endif 66136849Sscottl#endif 67136849Sscottl 68136849Sscottl#define MV_ERROR printf 69149871Sscottl 70136849Sscottl/* 71136849Sscottl * CAM SIM entry points 72136849Sscottl */ 73149871Sscottlstatic int hpt_probe (device_t dev); 74149871Sscottlstatic void launch_worker_thread(void); 75149871Sscottlstatic int hpt_attach(device_t dev); 76149871Sscottlstatic int hpt_detach(device_t dev); 77149871Sscottlstatic int hpt_shutdown(device_t dev); 78149871Sscottlstatic void hpt_poll(struct cam_sim *sim); 79149871Sscottlstatic void hpt_intr(void *arg); 80149871Sscottlstatic void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); 81149871Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb); 82149871Sscottl 83149871Sscottlstatic device_method_t driver_methods[] = { 84149871Sscottl /* Device interface */ 85149871Sscottl DEVMETHOD(device_probe, hpt_probe), 86149871Sscottl DEVMETHOD(device_attach, hpt_attach), 87149871Sscottl DEVMETHOD(device_detach, hpt_detach), 88149871Sscottl 89190863Sdelphij DEVMETHOD(device_shutdown, hpt_shutdown), 90227912Smarius DEVMETHOD_END 91149871Sscottl}; 92149871Sscottl 93149871Sscottlstatic driver_t hpt_pci_driver = { 94149871Sscottl __str(PROC_DIR_NAME), 95149871Sscottl driver_methods, 96149871Sscottl sizeof(IAL_ADAPTER_T) 97149871Sscottl}; 98149871Sscottl 99149871Sscottlstatic devclass_t hpt_devclass; 100149871Sscottl 101149871Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 102149871Sscottl__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 103236379SeadlerMODULE_DEPEND(PROC_DIR_NAME, cam, 1, 1, 1); 104149871Sscottl 105149871Sscottl#define ccb_ccb_ptr spriv_ptr0 106149871Sscottl#define ccb_adapter ccb_h.spriv_ptr1 107149871Sscottl 108149871Sscottlstatic void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); 109149871Sscottlstatic void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); 110149871Sscottlstatic void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); 111149871Sscottlstatic void ccb_done(union ccb *ccb); 112149871Sscottlstatic void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); 113149871Sscottlstatic void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); 114269617Sjhbstatic void hpt_intr_locked(IAL_ADAPTER_T *pAdapter); 115136849Sscottlstatic void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter); 116136849Sscottlstatic void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 117136849Sscottlstatic void handleEdmaError(_VBUS_ARG PCommand pCmd); 118136849Sscottlstatic int hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 119136849Sscottlstatic int fResetActiveCommands(PVBus _vbus_p); 120136849Sscottlstatic void fRegisterVdevice(IAL_ADAPTER_T *pAdapter); 121136849Sscottlstatic int hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter); 122136849Sscottlstatic void hptmv_handle_event_disconnect(void *data); 123136849Sscottlstatic void hptmv_handle_event_connect(void *data); 124136849Sscottlstatic int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 125136849Sscottlstatic void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel); 126136849Sscottlstatic int hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel); 127136849Sscottlstatic int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, 128136849Sscottl int logical); 129136849Sscottlstatic MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 130136849Sscottl MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId, 131136849Sscottl MV_U16 responseFlags, MV_U32 timeStamp, 132136849Sscottl MV_STORAGE_DEVICE_REGISTERS *registerStruct); 133136849Sscottlstatic MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, 134136849Sscottl MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2); 135136849Sscottl 136136849Sscottl#define ccb_ccb_ptr spriv_ptr0 137136849Sscottl#define ccb_adapter ccb_h.spriv_ptr1 138136849Sscottl 139269617Sjhbstatic struct sx hptmv_list_lock; 140269617SjhbSX_SYSINIT(hptmv_list_lock, &hptmv_list_lock, "hptmv list"); 141315221SpfgIAL_ADAPTER_T *gIal_Adapter = NULL; 142315221SpfgIAL_ADAPTER_T *pCurAdapter = NULL; 143149871Sscottlstatic MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; 144136849Sscottl 145136849Sscottltypedef struct st_HPT_DPC { 146136849Sscottl IAL_ADAPTER_T *pAdapter; 147136849Sscottl void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR); 148136849Sscottl void *arg; 149136849Sscottl UCHAR flags; 150136849Sscottl} ST_HPT_DPC; 151136849Sscottl 152136849Sscottl#define MAX_DPC 16 153136849SscottlUCHAR DPC_Request_Nums = 0; 154136849Sscottlstatic ST_HPT_DPC DpcQueue[MAX_DPC]; 155136849Sscottlstatic int DpcQueue_First=0; 156136849Sscottlstatic int DpcQueue_Last = 0; 157269617Sjhbstatic struct mtx DpcQueue_Lock; 158269617SjhbMTX_SYSINIT(hpmtv_dpc_lock, &DpcQueue_Lock, "hptmv dpc", MTX_DEF); 159136849Sscottl 160190809Sdelphijchar DRIVER_VERSION[] = "v1.16"; 161136849Sscottl 162136849Sscottl/******************************************************************************* 163136849Sscottl * Name: hptmv_free_channel 164136849Sscottl * 165136849Sscottl * Description: free allocated queues for the given channel 166136849Sscottl * 167298955Spfg * Parameters: pMvSataAdapter - pointer to the RR18xx controller this 168136849Sscottl * channel connected to. 169136849Sscottl * channelNum - channel number. 170136849Sscottl * 171136849Sscottl ******************************************************************************/ 172136849Sscottlstatic void 173136849Sscottlhptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 174136849Sscottl{ 175136849Sscottl HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM); 176136849Sscottl pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL; 177149871Sscottl} 178136849Sscottl 179149871Sscottlstatic void failDevice(PVDevice pVDev) 180149871Sscottl{ 181149871Sscottl PVBus _vbus_p = pVDev->pVBus; 182149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 183149871Sscottl 184149871Sscottl pVDev->u.disk.df_on_line = 0; 185149871Sscottl pVDev->vf_online = 0; 186149871Sscottl if (pVDev->pfnDeviceFailed) 187149871Sscottl CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev); 188149871Sscottl 189149871Sscottl fNotifyGUI(ET_DEVICE_REMOVED, pVDev); 190149871Sscottl 191149871Sscottl#ifndef FOR_DEMO 192149871Sscottl if (pAdapter->ver_601==2 && !pAdapter->beeping) { 193149871Sscottl pAdapter->beeping = 1; 194149871Sscottl BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); 195149871Sscottl set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1); 196136849Sscottl } 197149871Sscottl#endif 198136849Sscottl} 199136849Sscottl 200136849Sscottlint MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel); 201136849Sscottl 202136849Sscottlstatic void 203136849SscottlhandleEdmaError(_VBUS_ARG PCommand pCmd) 204136849Sscottl{ 205136849Sscottl PDevice pDevice = &pCmd->pVDevice->u.disk; 206136849Sscottl MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter; 207136849Sscottl 208136849Sscottl if (!pDevice->df_on_line) { 209136849Sscottl KdPrint(("Device is offline")); 210136849Sscottl pCmd->Result = RETURN_BAD_DEVICE; 211136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 212136849Sscottl return; 213136849Sscottl } 214136849Sscottl 215136849Sscottl if (pCmd->RetryCount++>5) { 216149871Sscottl hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber)); 217149871Sscottlfailed: 218149871Sscottl failDevice(pCmd->pVDevice); 219136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 220136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 221136849Sscottl return; 222136849Sscottl } 223149871Sscottl 224149871Sscottl /* reset the channel and retry the command */ 225149871Sscottl if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber)) 226149871Sscottl goto failed; 227149871Sscottl 228149871Sscottl fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice)); 229149871Sscottl 230149871Sscottl hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber)); 231136849Sscottl fDeviceSendCommand(_VBUS_P pCmd); 232136849Sscottl} 233136849Sscottl 234136849Sscottl/**************************************************************** 235136849Sscottl * Name: hptmv_init_channel 236136849Sscottl * 237149871Sscottl * Description: allocate request and response queues for the EDMA of the 238149871Sscottl * given channel and sets other fields. 239149871Sscottl * 240136849Sscottl * Parameters: 241136849Sscottl * pAdapter - pointer to the emulated adapter data structure 242136849Sscottl * channelNum - channel number. 243136849Sscottl * Return: 0 on success, otherwise on failure 244136849Sscottl ****************************************************************/ 245136849Sscottlstatic int 246136849Sscottlhptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 247136849Sscottl{ 248136849Sscottl MV_SATA_CHANNEL *pMvSataChannel; 249136849Sscottl dma_addr_t req_dma_addr; 250136849Sscottl dma_addr_t rsp_dma_addr; 251136849Sscottl 252136849Sscottl if (channelNum >= MV_SATA_CHANNELS_NUM) 253136849Sscottl { 254190809Sdelphij MV_ERROR("RR18xx[%d]: Bad channelNum=%d", 255136849Sscottl pAdapter->mvSataAdapter.adapterId, channelNum); 256136849Sscottl return -1; 257136849Sscottl } 258136849Sscottl 259149871Sscottl pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; 260136849Sscottl pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel; 261136849Sscottl pMvSataChannel->channelNumber = channelNum; 262136849Sscottl pMvSataChannel->lba48Address = MV_FALSE; 263136849Sscottl pMvSataChannel->maxReadTransfer = MV_FALSE; 264136849Sscottl 265149871Sscottl pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *) 266149871Sscottl (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); 267149871Sscottl req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); 268136849Sscottl 269136849Sscottl 270149871Sscottl KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr)); 271136849Sscottl 272136849Sscottl /* check the 1K alignment of the request queue*/ 273136849Sscottl if (req_dma_addr & 0x3ff) 274136849Sscottl { 275190809Sdelphij MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned," 276149871Sscottl " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId, 277149871Sscottl (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum); 278136849Sscottl return -1; 279136849Sscottl } 280136849Sscottl pMvSataChannel->requestQueuePciLowAddress = req_dma_addr; 281136849Sscottl pMvSataChannel->requestQueuePciHiAddress = 0; 282190809Sdelphij KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p", 283149871Sscottl pAdapter->mvSataAdapter.adapterId, channelNum, 284149871Sscottl pMvSataChannel->requestQueue)); 285149871Sscottl pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) 286149871Sscottl (pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); 287149871Sscottl rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); 288136849Sscottl 289136849Sscottl /* check the 256 alignment of the response queue*/ 290136849Sscottl if (rsp_dma_addr & 0xff) 291136849Sscottl { 292190809Sdelphij MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte " 293149871Sscottl "aligned, dma_addr=%llx\n", 294149871Sscottl pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr); 295136849Sscottl return -1; 296136849Sscottl } 297136849Sscottl pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr; 298136849Sscottl pMvSataChannel->responseQueuePciHiAddress = 0; 299190809Sdelphij KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p", 300149871Sscottl pAdapter->mvSataAdapter.adapterId, channelNum, 301149871Sscottl pMvSataChannel->responseQueue)); 302136849Sscottl 303136849Sscottl pAdapter->mvChannel[channelNum].online = MV_TRUE; 304136849Sscottl return 0; 305136849Sscottl} 306136849Sscottl 307136849Sscottl/****************************************************************************** 308136849Sscottl * Name: hptmv_parse_identify_results 309136849Sscottl * 310149871Sscottl * Description: this functions parses the identify command results, checks 311190809Sdelphij * that the connected deives can be accesed by RR18xx EDMA, 312298955Spfg * and updates the channel structure accordingly. 313149871Sscottl * 314136849Sscottl * Parameters: pMvSataChannel, pointer to the channel data structure. 315136849Sscottl * 316136849Sscottl * Returns: =0 ->success, < 0 ->failure. 317136849Sscottl * 318136849Sscottl ******************************************************************************/ 319136849Sscottlstatic int 320136849Sscottlhptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) 321136849Sscottl{ 322136849Sscottl MV_U16 *iden = pMvSataChannel->identifyDevice; 323136849Sscottl 324136849Sscottl /*LBA addressing*/ 325149871Sscottl if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) 326149871Sscottl { 327136849Sscottl KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n")); 328136849Sscottl return -1; 329149871Sscottl } 330149871Sscottl else 331149871Sscottl { 332136849Sscottl KdPrint(("%25s - %s\n", "Capabilities", "LBA supported")); 333136849Sscottl } 334136849Sscottl /*DMA support*/ 335149871Sscottl if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) 336149871Sscottl { 337136849Sscottl KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n")); 338136849Sscottl return -1; 339149871Sscottl } 340149871Sscottl else 341149871Sscottl { 342136849Sscottl KdPrint(("%25s - %s\n", "Capabilities", "DMA supported")); 343136849Sscottl } 344136849Sscottl /* PIO */ 345149871Sscottl if ((iden[IDEN_VALID] & 2) == 0) 346149871Sscottl { 347149871Sscottl KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n")); 348136849Sscottl return -1; 349136849Sscottl } 350136849Sscottl KdPrint(("%25s - 0x%02x\n", "PIO modes supported", 351136849Sscottl iden[IDEN_PIO_MODE_SPPORTED] & 0xff)); 352136849Sscottl 353136849Sscottl /*UDMA*/ 354149871Sscottl if ((iden[IDEN_VALID] & 4) == 0) 355149871Sscottl { 356149871Sscottl KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n")); 357136849Sscottl return -1; 358136849Sscottl } 359136849Sscottl 360136849Sscottl /* 48 bit address */ 361149871Sscottl if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) 362149871Sscottl { 363136849Sscottl KdPrint(("%25s - %s\n", "LBA48 addressing", "supported")); 364136849Sscottl pMvSataChannel->lba48Address = MV_TRUE; 365149871Sscottl } 366149871Sscottl else 367149871Sscottl { 368136849Sscottl KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported")); 369136849Sscottl pMvSataChannel->lba48Address = MV_FALSE; 370136849Sscottl } 371136849Sscottl return 0; 372136849Sscottl} 373136849Sscottl 374136849Sscottlstatic void 375136849Sscottlinit_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) 376136849Sscottl{ 377149871Sscottl PVDevice pVDev = &pAdapter->VDevices[channel]; 378149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; 379149871Sscottl MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice; 380136849Sscottl 381136849Sscottl pMvSataChannel->outstandingCommands = 0; 382136849Sscottl 383136849Sscottl pVDev->u.disk.mv = pMvSataChannel; 384136849Sscottl pVDev->u.disk.df_on_line = 1; 385136849Sscottl pVDev->u.disk.pVBus = &pAdapter->VBus; 386136849Sscottl pVDev->pVBus = &pAdapter->VBus; 387136849Sscottl 388136849Sscottl#ifdef SUPPORT_48BIT_LBA 389136849Sscottl if (pMvSataChannel->lba48Address == MV_TRUE) 390149871Sscottl pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; 391136849Sscottl else 392136849Sscottl#endif 393136849Sscottl if(IdentifyData[53] & 1) { 394149871Sscottl pVDev->u.disk.dDeRealCapacity = 395149871Sscottl (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ? 396149871Sscottl (IdentifyData[61]<<16 | IdentifyData[60]) : 397149871Sscottl (IdentifyData[58]<<16 | IdentifyData[57])) - 1; 398136849Sscottl } else 399136849Sscottl pVDev->u.disk.dDeRealCapacity = 400149871Sscottl (IdentifyData[61]<<16 | IdentifyData[60]) - 1; 401136849Sscottl 402136849Sscottl pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 403149871Sscottl pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0; 404136849Sscottl 405136849Sscottl if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) { 406136849Sscottl pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 407149871Sscottl pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8; 408136849Sscottl } 409136849Sscottl} 410136849Sscottl 411149871Sscottlstatic void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) 412136849Sscottl{ 413136849Sscottl PVDevice pVDev; 414149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 415149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; 416149871Sscottl 417149871Sscottl if (!pMvSataChannel) return; 418136849Sscottl 419149871Sscottl if (plugged) 420149871Sscottl { 421136849Sscottl pVDev = &(pAdapter->VDevices[channelIndex]); 422136849Sscottl init_vdev_params(pAdapter, channelIndex); 423136849Sscottl 424149871Sscottl pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI : 425149871Sscottl pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 426136849Sscottl 427149871Sscottl pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO; 428136849Sscottl pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 429136849Sscottl pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 430136849Sscottl pVDev->vf_online = 1; 431136849Sscottl 432136849Sscottl#ifdef SUPPORT_ARRAY 433149871Sscottl if(pVDev->pParent) 434149871Sscottl { 435136849Sscottl int iMember; 436149871Sscottl for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++) 437149871Sscottl if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) 438136849Sscottl pVDev->pParent->u.array.pMember[iMember] = NULL; 439136849Sscottl pVDev->pParent = NULL; 440136849Sscottl } 441136849Sscottl#endif 442136849Sscottl fNotifyGUI(ET_DEVICE_PLUGGED,pVDev); 443136849Sscottl fCheckBootable(pVDev); 444136849Sscottl RegisterVDevice(pVDev); 445136849Sscottl 446136849Sscottl#ifndef FOR_DEMO 447136849Sscottl if (pAdapter->beeping) { 448136849Sscottl pAdapter->beeping = 0; 449136849Sscottl BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 450136849Sscottl } 451136849Sscottl#endif 452136849Sscottl 453149871Sscottl } 454149871Sscottl else 455149871Sscottl { 456136849Sscottl pVDev = &(pAdapter->VDevices[channelIndex]); 457149871Sscottl failDevice(pVDev); 458136849Sscottl } 459136849Sscottl} 460136849Sscottl 461136849Sscottlstatic int 462136849Sscottlstart_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 463136849Sscottl{ 464149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 465149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; 466149871Sscottl MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]); 467149871Sscottl MV_U32 udmaMode,pioMode; 468136849Sscottl 469190809Sdelphij KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId, 470149871Sscottl channelNum)); 471136849Sscottl 472136849Sscottl 473136849Sscottl /* Software reset channel */ 474149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 475149871Sscottl { 476190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 477149871Sscottl pMvSataAdapter->adapterId, channelNum); 478136849Sscottl return -1; 479136849Sscottl } 480136849Sscottl 481136849Sscottl /* Hardware reset channel */ 482149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 483149871Sscottl { 484149871Sscottl /* If failed, try again - this is when trying to hardreset a channel */ 485149871Sscottl /* when drive is just spinning up */ 486136849Sscottl StallExec(5000000); /* wait 5 sec before trying again */ 487149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 488149871Sscottl { 489190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n", 490149871Sscottl pMvSataAdapter->adapterId, channelNum); 491136849Sscottl return -1; 492136849Sscottl } 493136849Sscottl } 494136849Sscottl 495136849Sscottl /* identify device*/ 496149871Sscottl if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE) 497149871Sscottl { 498190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n" 499149871Sscottl , pMvSataAdapter->adapterId, channelNum); 500136849Sscottl return -1; 501136849Sscottl } 502149871Sscottl if (hptmv_parse_identify_results(pMvSataChannel)) 503149871Sscottl { 504190809Sdelphij MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n" 505149871Sscottl , pMvSataAdapter->adapterId, channelNum); 506136849Sscottl return -1; 507136849Sscottl } 508136849Sscottl 509136849Sscottl /* mvStorageDevATASetFeatures */ 510136849Sscottl /* Disable 8 bit PIO in case CFA enabled */ 511149871Sscottl if (pMvSataChannel->identifyDevice[86] & 4) 512149871Sscottl { 513190809Sdelphij KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n", 514149871Sscottl pMvSataAdapter->adapterId)); 515136849Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 516149871Sscottl MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, 517149871Sscottl 0, 0, 0) == MV_FALSE) 518149871Sscottl { 519190809Sdelphij MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures" 520149871Sscottl " failed\n", pMvSataAdapter->adapterId, channelNum); 521136849Sscottl return -1; 522136849Sscottl } 523136849Sscottl } 524149871Sscottl /* Write cache */ 525136849Sscottl#ifdef ENABLE_WRITE_CACHE 526149871Sscottl if (pMvSataChannel->identifyDevice[82] & 0x20) 527149871Sscottl { 528149871Sscottl if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */ 529149871Sscottl { 530149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 531149871Sscottl MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 532149871Sscottl 0, 0, 0) == MV_FALSE) 533149871Sscottl { 534190809Sdelphij MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 535149871Sscottl pMvSataAdapter->adapterId, channelNum); 536136849Sscottl return -1; 537136849Sscottl } 538136849Sscottl } 539190809Sdelphij KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n", 540149871Sscottl pMvSataAdapter->adapterId, channelNum)); 541149871Sscottl } 542149871Sscottl else 543149871Sscottl { 544190809Sdelphij KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n", 545149871Sscottl pMvSataAdapter->adapterId, channelNum)); 546136849Sscottl } 547149871Sscottl#else /* disable write cache */ 548149871Sscottl { 549149871Sscottl if (pMvSataChannel->identifyDevice[85] & 0x20) 550149871Sscottl { 551190809Sdelphij KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n", 552149871Sscottl pMvSataAdapter->adapterId, channelNum)); 553149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 554149871Sscottl MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 555149871Sscottl 0, 0, 0) == MV_FALSE) 556149871Sscottl { 557190809Sdelphij MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 558149871Sscottl pMvSataAdapter->adapterId, channelNum); 559149871Sscottl return -1; 560149871Sscottl } 561136849Sscottl } 562190809Sdelphij KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n", 563149871Sscottl pMvSataAdapter->adapterId, channelNum)); 564136849Sscottl } 565136849Sscottl#endif 566136849Sscottl 567136849Sscottl /* Set transfer mode */ 568190809Sdelphij KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n", 569149871Sscottl pMvSataAdapter->adapterId)); 570136849Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 571149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 572149871Sscottl MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == 573149871Sscottl MV_FALSE) 574149871Sscottl { 575190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 576149871Sscottl pMvSataAdapter->adapterId, channelNum); 577136849Sscottl return -1; 578136849Sscottl } 579136849Sscottl 580149871Sscottl if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) 581149871Sscottl { 582136849Sscottl pioMode = MV_ATA_TRANSFER_PIO_4; 583149871Sscottl } 584149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) 585149871Sscottl { 586136849Sscottl pioMode = MV_ATA_TRANSFER_PIO_3; 587149871Sscottl } 588149871Sscottl else 589149871Sscottl { 590149871Sscottl MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n"); 591136849Sscottl pioMode = MV_ATA_TRANSFER_PIO_SLOW; 592136849Sscottl } 593136849Sscottl 594190809Sdelphij KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n", 595149871Sscottl pMvSataAdapter->adapterId)); 596136849Sscottl pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode; 597136849Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 598149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 599149871Sscottl pioMode, 0, 0, 0) == MV_FALSE) 600149871Sscottl { 601190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 602149871Sscottl pMvSataAdapter->adapterId, channelNum); 603136849Sscottl return -1; 604136849Sscottl } 605136849Sscottl 606136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_0; 607149871Sscottl if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) 608149871Sscottl { 609136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_6; 610149871Sscottl } 611149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) 612149871Sscottl { 613136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_5; 614149871Sscottl } 615149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) 616149871Sscottl { 617136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_4; 618149871Sscottl } 619149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) 620149871Sscottl { 621136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_3; 622149871Sscottl } 623149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) 624149871Sscottl { 625136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_2; 626136849Sscottl } 627136849Sscottl 628190809Sdelphij KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n", 629149871Sscottl pMvSataAdapter->adapterId, udmaMode & 0xf)); 630136849Sscottl pChannelInfo->maxUltraDmaModeSupported = udmaMode; 631136849Sscottl 632149871Sscottl /*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 633149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, udmaMode, 634149871Sscottl 0, 0, 0) == MV_FALSE) 635149871Sscottl { 636190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 637149871Sscottl pMvSataAdapter->adapterId, channelNum); 638136849Sscottl return -1; 639149871Sscottl }*/ 640136849Sscottl if (pChannelInfo->maxUltraDmaModeSupported == 0xFF) 641136849Sscottl return TRUE; 642149871Sscottl else 643149871Sscottl do 644149871Sscottl { 645149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 646149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 647149871Sscottl pChannelInfo->maxUltraDmaModeSupported, 648149871Sscottl 0, 0, 0) == MV_FALSE) 649149871Sscottl { 650149871Sscottl if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0) 651149871Sscottl { 652149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 653149871Sscottl { 654149871Sscottl MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress, 655149871Sscottl pMvSataChannel->eDmaRegsOffset + 656149871Sscottl 0x11c, /* command reg */ 657149871Sscottl MV_ATA_COMMAND_IDLE_IMMEDIATE); 658149871Sscottl mvMicroSecondsDelay(10000); 659149871Sscottl mvSataChannelHardReset(pMvSataAdapter, channelNum); 660149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 661149871Sscottl return FALSE; 662149871Sscottl } 663149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 664149871Sscottl return FALSE; 665149871Sscottl pChannelInfo->maxUltraDmaModeSupported--; 666149871Sscottl continue; 667149871Sscottl } 668149871Sscottl else return FALSE; 669149871Sscottl } 670136849Sscottl break; 671149871Sscottl }while (1); 672136849Sscottl 673149871Sscottl /* Read look ahead */ 674136849Sscottl#ifdef ENABLE_READ_AHEAD 675149871Sscottl if (pMvSataChannel->identifyDevice[82] & 0x40) 676149871Sscottl { 677149871Sscottl if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */ 678149871Sscottl { 679149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 680149871Sscottl MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 681149871Sscottl 0, 0) == MV_FALSE) 682149871Sscottl { 683190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 684149871Sscottl pMvSataAdapter->adapterId, channelNum); 685136849Sscottl return -1; 686136849Sscottl } 687136849Sscottl } 688190809Sdelphij KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n", 689149871Sscottl pMvSataAdapter->adapterId, channelNum)); 690136849Sscottl } 691149871Sscottl else 692149871Sscottl { 693190809Sdelphij KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n", 694149871Sscottl pMvSataAdapter->adapterId, channelNum)); 695149871Sscottl } 696149871Sscottl#else 697149871Sscottl { 698149871Sscottl if (pMvSataChannel->identifyDevice[86] & 0x20) 699149871Sscottl { 700190809Sdelphij KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n", 701149871Sscottl pMvSataAdapter->adapterId, channelNum)); 702149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 703149871Sscottl MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 704149871Sscottl 0, 0) == MV_FALSE) 705149871Sscottl { 706190809Sdelphij MV_ERROR("RR18xx [%d]:channel %d: ATA Set Features failed\n", 707149871Sscottl pMvSataAdapter->adapterId, channelNum); 708149871Sscottl return -1; 709149871Sscottl } 710136849Sscottl } 711190809Sdelphij KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n", 712149871Sscottl pMvSataAdapter->adapterId, channelNum)); 713149871Sscottl } 714136849Sscottl#endif 715136849Sscottl 716136849Sscottl 717149871Sscottl { 718190809Sdelphij KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n", 719149871Sscottl pMvSataAdapter->adapterId, 720149871Sscottl channelNum)); 721149871Sscottl if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, 722149871Sscottl MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) 723149871Sscottl { 724190809Sdelphij MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n", 725149871Sscottl pMvSataAdapter->adapterId, channelNum); 726136849Sscottl return -1; 727136849Sscottl } 728136849Sscottl } 729136849Sscottl /* Enable EDMA */ 730149871Sscottl if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) 731149871Sscottl { 732190809Sdelphij MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n", 733149871Sscottl pMvSataAdapter->adapterId, channelNum); 734136849Sscottl return -1; 735136849Sscottl } 736190809Sdelphij MV_ERROR("RR18xx [%d,%d]: channel started successfully\n", 737149871Sscottl pMvSataAdapter->adapterId, channelNum); 738136849Sscottl 739136849Sscottl#ifndef FOR_DEMO 740136849Sscottl set_fail_led(pMvSataAdapter, channelNum, 0); 741136849Sscottl#endif 742136849Sscottl return 0; 743136849Sscottl} 744136849Sscottl 745136849Sscottlstatic void 746136849Sscottlhptmv_handle_event(void * data, int flag) 747136849Sscottl{ 748149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)data; 749149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 750149871Sscottl MV_U8 channelIndex; 751269617Sjhb 752269617Sjhb mtx_assert(&pAdapter->lock, MA_OWNED); 753149871Sscottl/* mvOsSemTake(&pMvSataAdapter->semaphore); */ 754149871Sscottl for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++) 755149871Sscottl { 756149871Sscottl switch(pAdapter->sataEvents[channelIndex]) 757149871Sscottl { 758149871Sscottl case SATA_EVENT_CHANNEL_CONNECTED: 759149871Sscottl /* Handle only connects */ 760149871Sscottl if (flag == 1) 761149871Sscottl break; 762190809Sdelphij KdPrint(("RR18xx [%d,%d]: new device connected\n", 763149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 764149871Sscottl hptmv_init_channel(pAdapter, channelIndex); 765149871Sscottl if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE) 766149871Sscottl { 767190809Sdelphij MV_ERROR("RR18xx [%d,%d] Failed to configure\n", 768149871Sscottl pMvSataAdapter->adapterId, channelIndex); 769149871Sscottl hptmv_free_channel(pAdapter, channelIndex); 770149871Sscottl } 771149871Sscottl else 772149871Sscottl { 773149871Sscottl /*mvSataChannelHardReset(pMvSataAdapter, channel);*/ 774149871Sscottl if (start_channel( pAdapter, channelIndex)) 775149871Sscottl { 776190809Sdelphij MV_ERROR("RR18xx [%d,%d]Failed to start channel\n", 777149871Sscottl pMvSataAdapter->adapterId, channelIndex); 778149871Sscottl hptmv_free_channel(pAdapter, channelIndex); 779149871Sscottl } 780149871Sscottl else 781149871Sscottl { 782149871Sscottl device_change(pAdapter, channelIndex, TRUE); 783149871Sscottl } 784149871Sscottl } 785149871Sscottl pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 786149871Sscottl break; 787136849Sscottl 788149871Sscottl case SATA_EVENT_CHANNEL_DISCONNECTED: 789149871Sscottl /* Handle only disconnects */ 790149871Sscottl if (flag == 0) 791149871Sscottl break; 792190809Sdelphij KdPrint(("RR18xx [%d,%d]: device disconnected\n", 793149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 794149871Sscottl /* Flush pending commands */ 795149871Sscottl if(pMvSataAdapter->sataChannel[channelIndex]) 796149871Sscottl { 797149871Sscottl _VBUS_INST(&pAdapter->VBus) 798149871Sscottl mvSataFlushDmaQueue (pMvSataAdapter, channelIndex, 799149871Sscottl MV_FLUSH_TYPE_CALLBACK); 800149871Sscottl CheckPendingCall(_VBUS_P0); 801149871Sscottl mvSataRemoveChannel(pMvSataAdapter,channelIndex); 802149871Sscottl hptmv_free_channel(pAdapter, channelIndex); 803149871Sscottl pMvSataAdapter->sataChannel[channelIndex] = NULL; 804190809Sdelphij KdPrint(("RR18xx [%d,%d]: channel removed\n", 805149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 806149871Sscottl if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 807149871Sscottl Check_Idle_Call(pAdapter); 808136849Sscottl } 809149871Sscottl else 810149871Sscottl { 811190809Sdelphij KdPrint(("RR18xx [%d,%d]: channel already removed!!\n", 812149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 813149871Sscottl } 814149871Sscottl pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 815136849Sscottl break; 816136849Sscottl 817149871Sscottl case SATA_EVENT_NO_CHANGE: 818149871Sscottl break; 819136849Sscottl 820149871Sscottl default: 821149871Sscottl break; 822136849Sscottl } 823136849Sscottl } 824149871Sscottl/* mvOsSemRelease(&pMvSataAdapter->semaphore); */ 825136849Sscottl} 826136849Sscottl 827136849Sscottl#define EVENT_CONNECT 1 828136849Sscottl#define EVENT_DISCONNECT 0 829136849Sscottl 830136849Sscottlstatic void 831136849Sscottlhptmv_handle_event_connect(void *data) 832136849Sscottl{ 833149871Sscottl hptmv_handle_event (data, 0); 834136849Sscottl} 835136849Sscottl 836136849Sscottlstatic void 837136849Sscottlhptmv_handle_event_disconnect(void *data) 838136849Sscottl{ 839149871Sscottl hptmv_handle_event (data, 1); 840136849Sscottl} 841136849Sscottl 842136849Sscottlstatic MV_BOOLEAN 843136849Sscottlhptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType, 844149871Sscottl MV_U32 param1, MV_U32 param2) 845136849Sscottl{ 846149871Sscottl IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; 847136849Sscottl 848149871Sscottl switch (eventType) 849136849Sscottl { 850149871Sscottl case MV_EVENT_TYPE_SATA_CABLE: 851149871Sscottl { 852149871Sscottl MV_U8 channel = param2; 853136849Sscottl 854149871Sscottl if (param1 == EVENT_CONNECT) 855149871Sscottl { 856149871Sscottl pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED; 857190809Sdelphij KdPrint(("RR18xx [%d,%d]: device connected event received\n", 858149871Sscottl pMvSataAdapter->adapterId, channel)); 859149871Sscottl /* Delete previous timers (if multiple drives connected in the same time */ 860269617Sjhb callout_reset(&pAdapter->event_timer_connect, 10 * hz, hptmv_handle_event_connect, pAdapter); 861149871Sscottl } 862149871Sscottl else if (param1 == EVENT_DISCONNECT) 863149871Sscottl { 864149871Sscottl pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED; 865190809Sdelphij KdPrint(("RR18xx [%d,%d]: device disconnected event received \n", 866149871Sscottl pMvSataAdapter->adapterId, channel)); 867149871Sscottl device_change(pAdapter, channel, FALSE); 868149871Sscottl /* Delete previous timers (if multiple drives disconnected in the same time */ 869269617Sjhb /*callout_reset(&pAdapter->event_timer_disconnect, 10 * hz, hptmv_handle_event_disconnect, pAdapter); */ 870149871Sscottl /*It is not necessary to wait, handle it directly*/ 871149871Sscottl hptmv_handle_event_disconnect(pAdapter); 872149871Sscottl } 873149871Sscottl else 874149871Sscottl { 875136849Sscottl 876250460Seadler MV_ERROR("RR18xx: illegal value for param1(%d) at " 877250460Seadler "connect/disconnect event, host=%d\n", param1, 878149871Sscottl pMvSataAdapter->adapterId ); 879149871Sscottl 880149871Sscottl } 881149871Sscottl } 882149871Sscottl break; 883149871Sscottl case MV_EVENT_TYPE_ADAPTER_ERROR: 884190809Sdelphij KdPrint(("RR18xx: DEVICE error event received, pci cause " 885149871Sscottl "reg=%x, don't how to handle this\n", param1)); 886149871Sscottl return MV_TRUE; 887149871Sscottl default: 888190809Sdelphij MV_ERROR("RR18xx[%d]: unknown event type (%d)\n", 889149871Sscottl pMvSataAdapter->adapterId, eventType); 890149871Sscottl return MV_FALSE; 891136849Sscottl } 892136849Sscottl return MV_TRUE; 893136849Sscottl} 894136849Sscottl 895149871Sscottlstatic int 896136849Sscottlhptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) 897136849Sscottl{ 898149871Sscottl pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE, 899149871Sscottl M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 900149871Sscottl if (pAdapter->requestsArrayBaseAddr == NULL) 901149871Sscottl { 902190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request" 903149871Sscottl " queues\n", pAdapter->mvSataAdapter.adapterId); 904136849Sscottl return -1; 905136849Sscottl } 906149871Sscottl pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr); 907149871Sscottl pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr; 908136849Sscottl pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 909149871Sscottl pAdapter->requestsArrayBaseAlignedAddr = (MV_U8 *) 910149871Sscottl (((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); 911149871Sscottl pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr; 912136849Sscottl pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 913149871Sscottl pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); 914136849Sscottl 915149871Sscottl if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) != 916149871Sscottl (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr)) 917149871Sscottl { 918190809Sdelphij MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n", 919149871Sscottl pAdapter->mvSataAdapter.adapterId); 920149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 921136849Sscottl return -1; 922136849Sscottl } 923136849Sscottl /* response queues */ 924149871Sscottl pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE, 925149871Sscottl M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 926149871Sscottl if (pAdapter->responsesArrayBaseAddr == NULL) 927149871Sscottl { 928190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response" 929149871Sscottl " queues\n", pAdapter->mvSataAdapter.adapterId); 930149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 931136849Sscottl return -1; 932136849Sscottl } 933149871Sscottl pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr); 934149871Sscottl pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr; 935136849Sscottl pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 936149871Sscottl pAdapter->responsesArrayBaseAlignedAddr = (MV_U8 *) 937149871Sscottl (((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); 938149871Sscottl pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr; 939149871Sscottl pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 940149871Sscottl pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); 941136849Sscottl 942149871Sscottl if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) != 943149871Sscottl (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr)) 944149871Sscottl { 945250460Seadler MV_ERROR("RR18xx[%d]: Error in Response Queues Alignment\n", 946149871Sscottl pAdapter->mvSataAdapter.adapterId); 947149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 948149871Sscottl contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 949136849Sscottl return -1; 950136849Sscottl } 951136849Sscottl return 0; 952136849Sscottl} 953136849Sscottl 954136849Sscottlstatic void 955136849Sscottlhptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter) 956136849Sscottl{ 957149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 958149871Sscottl contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 959136849Sscottl} 960136849Sscottl 961136849Sscottlstatic PVOID 962136849SscottlAllocatePRDTable(IAL_ADAPTER_T *pAdapter) 963136849Sscottl{ 964136849Sscottl PVOID ret; 965136849Sscottl if (pAdapter->pFreePRDLink) { 966149871Sscottl KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink)); 967136849Sscottl ret = pAdapter->pFreePRDLink; 968136849Sscottl pAdapter->pFreePRDLink = *(void**)ret; 969136849Sscottl return ret; 970136849Sscottl } 971136849Sscottl return NULL; 972136849Sscottl} 973136849Sscottl 974136849Sscottlstatic void 975136849SscottlFreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable) 976136849Sscottl{ 977136849Sscottl *(void**)PRDTable = pAdapter->pFreePRDLink; 978136849Sscottl pAdapter->pFreePRDLink = PRDTable; 979136849Sscottl} 980136849Sscottl 981136849Sscottlextern PVDevice fGetFirstChild(PVDevice pLogical); 982136849Sscottlextern void fResetBootMark(PVDevice pLogical); 983136849Sscottlstatic void 984136849SscottlfRegisterVdevice(IAL_ADAPTER_T *pAdapter) 985136849Sscottl{ 986136849Sscottl PVDevice pPhysical, pLogical; 987136849Sscottl PVBus pVBus; 988136849Sscottl int i,j; 989136849Sscottl 990149871Sscottl for(i=0;i<MV_SATA_CHANNELS_NUM;i++) { 991136849Sscottl pPhysical = &(pAdapter->VDevices[i]); 992136849Sscottl pLogical = pPhysical; 993136849Sscottl while (pLogical->pParent) pLogical = pLogical->pParent; 994136849Sscottl if (pLogical->vf_online==0) { 995136849Sscottl pPhysical->vf_bootmark = pLogical->vf_bootmark = 0; 996136849Sscottl continue; 997136849Sscottl } 998149871Sscottl if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical)) 999136849Sscottl continue; 1000136849Sscottl 1001136849Sscottl pVBus = &pAdapter->VBus; 1002149871Sscottl if(pVBus) 1003149871Sscottl { 1004136849Sscottl j=0; 1005149871Sscottl while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++; 1006149871Sscottl if(j<MAX_VDEVICE_PER_VBUS){ 1007136849Sscottl pVBus->pVDevice[j] = pLogical; 1008136849Sscottl pLogical->pVBus = pVBus; 1009136849Sscottl 1010136849Sscottl if (j>0 && pLogical->vf_bootmark) { 1011136849Sscottl if (pVBus->pVDevice[0]->vf_bootmark) { 1012136849Sscottl fResetBootMark(pLogical); 1013149871Sscottl } 1014149871Sscottl else { 1015149871Sscottl do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j); 1016136849Sscottl pVBus->pVDevice[0] = pLogical; 1017136849Sscottl } 1018136849Sscottl } 1019136849Sscottl } 1020136849Sscottl } 1021136849Sscottl } 1022136849Sscottl} 1023136849Sscottl 1024136849SscottlPVDevice 1025136849SscottlGetSpareDisk(_VBUS_ARG PVDevice pArray) 1026136849Sscottl{ 1027149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; 1028190809Sdelphij LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); 1029190809Sdelphij LBA_T thiscap, maxcap = MAX_LBA_T; 1030136849Sscottl PVDevice pVDevice, pFind = NULL; 1031136849Sscottl int i; 1032136849Sscottl 1033149871Sscottl for(i=0;i<MV_SATA_CHANNELS_NUM;i++) 1034149871Sscottl { 1035136849Sscottl pVDevice = &pAdapter->VDevices[i]; 1036136849Sscottl if(!pVDevice) 1037136849Sscottl continue; 1038149871Sscottl thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; 1039136849Sscottl /* find the smallest usable spare disk */ 1040136849Sscottl if (pVDevice->VDeviceType==VD_SPARE && 1041149871Sscottl pVDevice->u.disk.df_on_line && 1042149871Sscottl thiscap < maxcap && 1043149871Sscottl thiscap >= capacity) 1044149871Sscottl { 1045149871Sscottl maxcap = pVDevice->VDeviceCapacity; 1046149871Sscottl pFind = pVDevice; 1047136849Sscottl } 1048136849Sscottl } 1049136849Sscottl return pFind; 1050136849Sscottl} 1051136849Sscottl 1052136849Sscottl/****************************************************************** 1053136849Sscottl * IO ATA Command 1054136849Sscottl *******************************************************************/ 1055136849Sscottlint HPTLIBAPI 1056136849SscottlfDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer) 1057136849Sscottl{ 1058136849Sscottl return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer); 1059136849Sscottl} 1060136849Sscottl 1061136849Sscottlvoid HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) 1062136849Sscottl{ 1063149871Sscottl MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1064149871Sscottl MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1065149871Sscottl MV_U8 channelIndex = pSataChannel->channelNumber; 1066136849Sscottl UCHAR mvMode; 1067136849Sscottl /* 508x don't use MW-DMA? */ 1068136849Sscottl if (NewMode>4 && NewMode<8) NewMode = 4; 1069136849Sscottl pDev->bDeModeSetting = NewMode; 1070136849Sscottl if (NewMode<=4) 1071136849Sscottl mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode; 1072136849Sscottl else 1073136849Sscottl mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8); 1074136849Sscottl 1075136849Sscottl /*To fix 88i8030 bug*/ 1076136849Sscottl if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4) 1077136849Sscottl mvMode = MV_ATA_TRANSFER_UDMA_0; 1078136849Sscottl 1079136849Sscottl mvSataDisableChannelDma(pSataAdapter, channelIndex); 1080136849Sscottl /* Flush pending commands */ 1081136849Sscottl mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE); 1082136849Sscottl 1083136849Sscottl if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1084149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1085149871Sscottl mvMode, 0, 0, 0) == MV_FALSE) 1086149871Sscottl { 1087136849Sscottl KdPrint(("channel %d: Set Features failed\n", channelIndex)); 1088136849Sscottl } 1089136849Sscottl /* Enable EDMA */ 1090136849Sscottl if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE) 1091136849Sscottl KdPrint(("Failed to enable DMA, channel=%d", channelIndex)); 1092136849Sscottl} 1093136849Sscottl 1094190809Sdelphijint HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth) 1095190809Sdelphij{ 1096190809Sdelphij MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1097190809Sdelphij MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1098190809Sdelphij MV_U8 channelIndex = pSataChannel->channelNumber; 1099190809Sdelphij IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1100190809Sdelphij MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1101190809Sdelphij int dmaActive = pSataChannel->queueCommandsEnabled; 1102190809Sdelphij int ret = 0; 1103190809Sdelphij 1104190809Sdelphij if (dmaActive) { 1105190809Sdelphij mvSataDisableChannelDma(pSataAdapter, channelIndex); 1106190809Sdelphij mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1107190809Sdelphij } 1108190809Sdelphij 1109190809Sdelphij if (enable) { 1110190809Sdelphij if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED && 1111190809Sdelphij (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) { 1112190809Sdelphij UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1; 1113190809Sdelphij channelInfo->queueDepth = (depth==32)? 31 : depth; 1114190809Sdelphij mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth); 1115190809Sdelphij ret = 1; 1116190809Sdelphij } 1117190809Sdelphij } 1118190809Sdelphij else 1119190809Sdelphij { 1120190809Sdelphij if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) { 1121190809Sdelphij channelInfo->queueDepth = 2; 1122190809Sdelphij mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0); 1123190809Sdelphij ret = 1; 1124190809Sdelphij } 1125190809Sdelphij } 1126190809Sdelphij 1127190809Sdelphij if (dmaActive) 1128190809Sdelphij mvSataEnableChannelDma(pSataAdapter,channelIndex); 1129190809Sdelphij return ret; 1130190809Sdelphij} 1131190809Sdelphij 1132190809Sdelphijint HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth) 1133190809Sdelphij{ 1134190809Sdelphij return 0; 1135190809Sdelphij} 1136190809Sdelphij 1137190809Sdelphijint HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable) 1138190809Sdelphij{ 1139190809Sdelphij MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1140190809Sdelphij MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1141190809Sdelphij MV_U8 channelIndex = pSataChannel->channelNumber; 1142190809Sdelphij IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1143190809Sdelphij MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1144190809Sdelphij int dmaActive = pSataChannel->queueCommandsEnabled; 1145190809Sdelphij int ret = 0; 1146190809Sdelphij 1147190809Sdelphij if (dmaActive) { 1148190809Sdelphij mvSataDisableChannelDma(pSataAdapter, channelIndex); 1149190809Sdelphij mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1150190809Sdelphij } 1151190809Sdelphij 1152190809Sdelphij if ((pSataChannel->identifyDevice[82] & (0x20))) { 1153190809Sdelphij if (enable) { 1154190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1155190809Sdelphij MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0)) 1156190809Sdelphij { 1157190809Sdelphij channelInfo->writeCacheEnabled = MV_TRUE; 1158190809Sdelphij ret = 1; 1159190809Sdelphij } 1160190809Sdelphij } 1161190809Sdelphij else { 1162190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1163190809Sdelphij MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0)) 1164190809Sdelphij { 1165190809Sdelphij channelInfo->writeCacheEnabled = MV_FALSE; 1166190809Sdelphij ret = 1; 1167190809Sdelphij } 1168190809Sdelphij } 1169190809Sdelphij } 1170190809Sdelphij 1171190809Sdelphij if (dmaActive) 1172190809Sdelphij mvSataEnableChannelDma(pSataAdapter,channelIndex); 1173190809Sdelphij return ret; 1174190809Sdelphij} 1175190809Sdelphij 1176190809Sdelphijint HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable) 1177190809Sdelphij{ 1178190809Sdelphij MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1179190809Sdelphij MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1180190809Sdelphij MV_U8 channelIndex = pSataChannel->channelNumber; 1181190809Sdelphij IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1182190809Sdelphij MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1183190809Sdelphij int dmaActive = pSataChannel->queueCommandsEnabled; 1184190809Sdelphij int ret = 0; 1185190809Sdelphij 1186190809Sdelphij if (dmaActive) { 1187190809Sdelphij mvSataDisableChannelDma(pSataAdapter, channelIndex); 1188190809Sdelphij mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1189190809Sdelphij } 1190190809Sdelphij 1191190809Sdelphij if ((pSataChannel->identifyDevice[82] & (0x40))) { 1192190809Sdelphij if (enable) { 1193190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1194190809Sdelphij MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0)) 1195190809Sdelphij { 1196190809Sdelphij channelInfo->readAheadEnabled = MV_TRUE; 1197190809Sdelphij ret = 1; 1198190809Sdelphij } 1199190809Sdelphij } 1200190809Sdelphij else { 1201190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1202190809Sdelphij MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0)) 1203190809Sdelphij { 1204190809Sdelphij channelInfo->readAheadEnabled = MV_FALSE; 1205190809Sdelphij ret = 1; 1206190809Sdelphij } 1207190809Sdelphij } 1208190809Sdelphij } 1209190809Sdelphij 1210190809Sdelphij if (dmaActive) 1211190809Sdelphij mvSataEnableChannelDma(pSataAdapter,channelIndex); 1212190809Sdelphij return ret; 1213190809Sdelphij} 1214190809Sdelphij 1215136849Sscottl#ifdef SUPPORT_ARRAY 1216136849Sscottl#define IdeRegisterVDevice fCheckArray 1217149871Sscottl#else 1218136849Sscottlvoid 1219136849SscottlIdeRegisterVDevice(PDevice pDev) 1220136849Sscottl{ 1221136849Sscottl PVDevice pVDev = Map2pVDevice(pDev); 1222136849Sscottl 1223136849Sscottl pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI : 1224149871Sscottl pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 1225136849Sscottl pVDev->vf_online = 1; 1226136849Sscottl pVDev->VDeviceCapacity = pDev->dDeRealCapacity; 1227136849Sscottl pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 1228136849Sscottl pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 1229136849Sscottl} 1230136849Sscottl#endif 1231136849Sscottl 1232149871Sscottlstatic __inline PBUS_DMAMAP 1233149871Sscottldmamap_get(struct IALAdapter * pAdapter) 1234149871Sscottl{ 1235149871Sscottl PBUS_DMAMAP p = pAdapter->pbus_dmamap_list; 1236149871Sscottl if (p) 1237149871Sscottl pAdapter->pbus_dmamap_list = p-> next; 1238149871Sscottl return p; 1239149871Sscottl} 1240149871Sscottl 1241149871Sscottlstatic __inline void 1242149871Sscottldmamap_put(PBUS_DMAMAP p) 1243149871Sscottl{ 1244149871Sscottl p->next = p->pAdapter->pbus_dmamap_list; 1245149871Sscottl p->pAdapter->pbus_dmamap_list = p; 1246149871Sscottl} 1247149871Sscottl 1248136849Sscottlstatic int num_adapters = 0; 1249136849Sscottlstatic int 1250136849Sscottlinit_adapter(IAL_ADAPTER_T *pAdapter) 1251136849Sscottl{ 1252136849Sscottl PVBus _vbus_p = &pAdapter->VBus; 1253136849Sscottl MV_SATA_ADAPTER *pMvSataAdapter; 1254149871Sscottl int i, channel, rid; 1255136849Sscottl 1256136849Sscottl PVDevice pVDev; 1257136849Sscottl 1258269617Sjhb mtx_init(&pAdapter->lock, "hptsleeplock", NULL, MTX_DEF); 1259269617Sjhb callout_init_mtx(&pAdapter->event_timer_connect, &pAdapter->lock, 0); 1260269617Sjhb callout_init_mtx(&pAdapter->event_timer_disconnect, &pAdapter->lock, 0); 1261190809Sdelphij 1262269617Sjhb sx_xlock(&hptmv_list_lock); 1263136849Sscottl pAdapter->next = 0; 1264136849Sscottl 1265315221Spfg if(gIal_Adapter == NULL){ 1266136849Sscottl gIal_Adapter = pAdapter; 1267136849Sscottl pCurAdapter = gIal_Adapter; 1268149871Sscottl } 1269149871Sscottl else { 1270136849Sscottl pCurAdapter->next = pAdapter; 1271136849Sscottl pCurAdapter = pAdapter; 1272136849Sscottl } 1273269617Sjhb sx_xunlock(&hptmv_list_lock); 1274136849Sscottl 1275136849Sscottl pAdapter->outstandingCommands = 0; 1276136849Sscottl 1277136849Sscottl pMvSataAdapter = &(pAdapter->mvSataAdapter); 1278136849Sscottl _vbus_p->OsExt = (void *)pAdapter; 1279136849Sscottl pMvSataAdapter->IALData = pAdapter; 1280136849Sscottl 1281232854Sscottl if (bus_dma_tag_create(bus_get_dma_tag(pAdapter->hpt_dev),/* parent */ 1282149871Sscottl 4, /* alignment */ 1283149871Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1284149871Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1285149871Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1286149871Sscottl NULL, NULL, /* filter, filterarg */ 1287149871Sscottl PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */ 1288149871Sscottl MAX_SG_DESCRIPTORS, /* nsegments */ 1289149871Sscottl 0x10000, /* maxsegsize */ 1290149871Sscottl BUS_DMA_WAITOK, /* flags */ 1291149871Sscottl busdma_lock_mutex, /* lockfunc */ 1292269617Sjhb &pAdapter->lock, /* lockfuncarg */ 1293149871Sscottl &pAdapter->io_dma_parent /* tag */)) 1294149871Sscottl { 1295201758Smbr return ENXIO; 1296136849Sscottl } 1297136849Sscottl 1298136849Sscottl 1299149871Sscottl if (hptmv_allocate_edma_queues(pAdapter)) 1300149871Sscottl { 1301190809Sdelphij MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n"); 1302149871Sscottl return ENOMEM; 1303136849Sscottl } 1304136849Sscottl 1305136849Sscottl /* also map EPROM address */ 1306136849Sscottl rid = 0x10; 1307296135Sjhibbits if (!(pAdapter->mem_res = bus_alloc_resource_any(pAdapter->hpt_dev, 1308296135Sjhibbits SYS_RES_MEMORY, &rid, RF_ACTIVE)) 1309149871Sscottl || 1310149871Sscottl !(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res))) 1311149871Sscottl { 1312190809Sdelphij MV_ERROR("RR18xx: Failed to remap memory space\n"); 1313149871Sscottl hptmv_free_edma_queues(pAdapter); 1314149871Sscottl return ENXIO; 1315136849Sscottl } 1316149871Sscottl else 1317149871Sscottl { 1318190809Sdelphij KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress)); 1319149871Sscottl } 1320136849Sscottl 1321136849Sscottl pMvSataAdapter->adapterId = num_adapters++; 1322136849Sscottl /* get the revision ID */ 1323149871Sscottl pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); 1324136849Sscottl pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev); 1325149871Sscottl 1326190809Sdelphij /* init RR18xx */ 1327136849Sscottl pMvSataAdapter->intCoalThre[0]= 1; 1328136849Sscottl pMvSataAdapter->intCoalThre[1]= 1; 1329136849Sscottl pMvSataAdapter->intTimeThre[0] = 1; 1330136849Sscottl pMvSataAdapter->intTimeThre[1] = 1; 1331136849Sscottl pMvSataAdapter->pciCommand = 0x0107E371; 1332136849Sscottl pMvSataAdapter->pciSerrMask = 0xd77fe6ul; 1333136849Sscottl pMvSataAdapter->pciInterruptMask = 0xd77fe6ul; 1334136849Sscottl pMvSataAdapter->mvSataEventNotify = hptmv_event_notify; 1335136849Sscottl 1336149871Sscottl if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) 1337149871Sscottl { 1338190809Sdelphij MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n", 1339149871Sscottl pMvSataAdapter->adapterId); 1340149871Sscottlunregister: 1341149871Sscottl bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res); 1342149871Sscottl hptmv_free_edma_queues(pAdapter); 1343149871Sscottl return ENXIO; 1344136849Sscottl } 1345136849Sscottl pAdapter->ver_601 = pMvSataAdapter->pcbVersion; 1346136849Sscottl 1347136849Sscottl#ifndef FOR_DEMO 1348136849Sscottl set_fail_leds(pMvSataAdapter, 0); 1349136849Sscottl#endif 1350136849Sscottl 1351136849Sscottl /* setup command blocks */ 1352136849Sscottl KdPrint(("Allocate command blocks\n")); 1353136849Sscottl _vbus_(pFreeCommands) = 0; 1354149871Sscottl pAdapter->pCommandBlocks = 1355149871Sscottl malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT); 1356149871Sscottl KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks)); 1357149871Sscottl if (!pAdapter->pCommandBlocks) { 1358149871Sscottl MV_ERROR("insufficient memory\n"); 1359149871Sscottl goto unregister; 1360149871Sscottl } 1361136849Sscottl 1362149871Sscottl for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) { 1363149871Sscottl FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i])); 1364149871Sscottl } 1365136849Sscottl 1366149871Sscottl /*Set up the bus_dmamap*/ 1367149871Sscottl pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT); 1368149871Sscottl if(!pAdapter->pbus_dmamap) { 1369149871Sscottl MV_ERROR("insufficient memory\n"); 1370149871Sscottl free(pAdapter->pCommandBlocks, M_DEVBUF); 1371149871Sscottl goto unregister; 1372136849Sscottl } 1373136849Sscottl 1374149871Sscottl memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM); 1375149871Sscottl pAdapter->pbus_dmamap_list = 0; 1376149871Sscottl for (i=0; i < MAX_QUEUE_COMM; i++) { 1377149871Sscottl PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]); 1378149871Sscottl pmap->pAdapter = pAdapter; 1379149871Sscottl dmamap_put(pmap); 1380149871Sscottl 1381149871Sscottl if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) { 1382149871Sscottl MV_ERROR("Can not allocate dma map\n"); 1383149871Sscottl free(pAdapter->pCommandBlocks, M_DEVBUF); 1384149871Sscottl free(pAdapter->pbus_dmamap, M_DEVBUF); 1385149871Sscottl goto unregister; 1386149871Sscottl } 1387269617Sjhb callout_init_mtx(&pmap->timeout, &pAdapter->lock, 0); 1388149871Sscottl } 1389136849Sscottl /* setup PRD Tables */ 1390136849Sscottl KdPrint(("Allocate PRD Tables\n")); 1391136849Sscottl pAdapter->pFreePRDLink = 0; 1392149871Sscottl 1393149871Sscottl pAdapter->prdTableAddr = (PUCHAR)contigmalloc( 1394149871Sscottl (PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 1395149871Sscottl 1396136862Sscottl KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr)); 1397136849Sscottl if (!pAdapter->prdTableAddr) { 1398136849Sscottl MV_ERROR("insufficient PRD Tables\n"); 1399136849Sscottl goto unregister; 1400136849Sscottl } 1401149871Sscottl pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL); 1402149871Sscottl { 1403149871Sscottl PUCHAR PRDTable = pAdapter->prdTableAlignedAddr; 1404149871Sscottl for (i=0; i<PRD_TABLES_FOR_VBUS; i++) 1405149871Sscottl { 1406149871Sscottl/* KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */ 1407149871Sscottl FreePRDTable(pAdapter, PRDTable); 1408149871Sscottl PRDTable += PRD_ENTRIES_SIZE; 1409149871Sscottl } 1410136849Sscottl } 1411136849Sscottl 1412136849Sscottl /* enable the adapter interrupts */ 1413136849Sscottl 1414136849Sscottl /* configure and start the connected channels*/ 1415149871Sscottl for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 1416149871Sscottl { 1417136849Sscottl pAdapter->mvChannel[channel].online = MV_FALSE; 1418136849Sscottl if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) 1419149871Sscottl == MV_TRUE) 1420149871Sscottl { 1421190809Sdelphij KdPrint(("RR18xx[%d]: channel %d is connected\n", 1422149871Sscottl pMvSataAdapter->adapterId, channel)); 1423136849Sscottl 1424149871Sscottl if (hptmv_init_channel(pAdapter, channel) == 0) 1425149871Sscottl { 1426149871Sscottl if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE) 1427149871Sscottl { 1428190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to configure channel" 1429149871Sscottl " %d\n",pMvSataAdapter->adapterId, channel); 1430149871Sscottl hptmv_free_channel(pAdapter, channel); 1431149871Sscottl } 1432149871Sscottl else 1433149871Sscottl { 1434149871Sscottl if (start_channel(pAdapter, channel)) 1435149871Sscottl { 1436190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to start channel," 1437149871Sscottl " channel=%d\n",pMvSataAdapter->adapterId, 1438149871Sscottl channel); 1439149871Sscottl hptmv_free_channel(pAdapter, channel); 1440149871Sscottl } 1441149871Sscottl pAdapter->mvChannel[channel].online = MV_TRUE; 1442149871Sscottl /* mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter, 1443149871Sscottl channel, 1444149871Sscottl MV_TRUE);*/ 1445149871Sscottl } 1446136849Sscottl } 1447136849Sscottl } 1448136849Sscottl KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n", 1449136849Sscottl pAdapter->mvChannel[channel].online, channel)); 1450136849Sscottl } 1451136849Sscottl 1452136849Sscottl#ifdef SUPPORT_ARRAY 1453136849Sscottl for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) { 1454136849Sscottl pVDev = ArrayTables(i); 1455136849Sscottl mArFreeArrayTable(pVDev); 1456136849Sscottl } 1457136849Sscottl#endif 1458136849Sscottl 1459136849Sscottl KdPrint(("Initialize Devices\n")); 1460136849Sscottl for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { 1461149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1462136849Sscottl if (pMvSataChannel) { 1463136849Sscottl init_vdev_params(pAdapter, channel); 1464136849Sscottl IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk); 1465136849Sscottl } 1466136849Sscottl } 1467136849Sscottl#ifdef SUPPORT_ARRAY 1468136849Sscottl CheckArrayCritical(_VBUS_P0); 1469136849Sscottl#endif 1470136849Sscottl _vbus_p->nInstances = 1; 1471136849Sscottl fRegisterVdevice(pAdapter); 1472136849Sscottl 1473136849Sscottl for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) { 1474136849Sscottl pVDev = _vbus_p->pVDevice[channel]; 1475136849Sscottl if (pVDev && pVDev->vf_online) 1476136849Sscottl fCheckBootable(pVDev); 1477136849Sscottl } 1478136849Sscottl 1479136849Sscottl#if defined(SUPPORT_ARRAY) && defined(_RAID5N_) 1480136849Sscottl init_raid5_memory(_VBUS_P0); 1481136849Sscottl _vbus_(r5).enable_write_back = 1; 1482190809Sdelphij printf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled"); 1483136849Sscottl#endif 1484136849Sscottl 1485136849Sscottl mvSataUnmaskAdapterInterrupt(pMvSataAdapter); 1486136849Sscottl return 0; 1487136849Sscottl} 1488136849Sscottl 1489136849Sscottlint 1490136849SscottlMvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) 1491136849Sscottl{ 1492149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; 1493136849Sscottl 1494136849Sscottl mvSataDisableChannelDma(pMvSataAdapter, channel); 1495136849Sscottl /* Flush pending commands */ 1496136849Sscottl mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 1497136849Sscottl 1498136849Sscottl /* Software reset channel */ 1499149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE) 1500149871Sscottl { 1501190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 1502149871Sscottl pMvSataAdapter->adapterId, channel); 1503149871Sscottl hptmv_free_channel(pAdapter, channel); 1504136849Sscottl return -1; 1505136849Sscottl } 1506136849Sscottl 1507136849Sscottl /* Hardware reset channel */ 1508149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) 1509149871Sscottl { 1510190809Sdelphij MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n", 1511149871Sscottl pMvSataAdapter->adapterId, channel); 1512136849Sscottl hptmv_free_channel(pAdapter, channel); 1513136849Sscottl return -1; 1514136849Sscottl } 1515136849Sscottl 1516149871Sscottl if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE) 1517149871Sscottl { 1518190809Sdelphij MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n", 1519149871Sscottl pMvSataAdapter->adapterId, channel); 1520136849Sscottl hptmv_free_channel(pAdapter, channel); 1521136849Sscottl return -1; 1522149871Sscottl }else 1523149871Sscottl { 1524149871Sscottl MV_ERROR("channel %d: perform recalibrate command", channel); 1525149871Sscottl if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1526149871Sscottl MV_NON_UDMA_PROTOCOL_NON_DATA, 1527149871Sscottl MV_FALSE, 1528149871Sscottl NULL, /* pBuffer*/ 1529149871Sscottl 0, /* count */ 1530149871Sscottl 0, /*features*/ 1531149871Sscottl /* sectorCount */ 1532149871Sscottl 0, 1533149871Sscottl 0, /* lbaLow */ 1534149871Sscottl 0, /* lbaMid */ 1535149871Sscottl /* lbaHigh */ 1536149871Sscottl 0, 1537149871Sscottl 0, /* device */ 1538149871Sscottl /* command */ 1539149871Sscottl 0x10)) 1540149871Sscottl MV_ERROR("channel %d: recalibrate failed", channel); 1541149871Sscottl 1542136849Sscottl /* Set transfer mode */ 1543136849Sscottl if((mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1544149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1545149871Sscottl MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) || 1546149871Sscottl (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1547149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1548149871Sscottl pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) || 1549149871Sscottl (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1550149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1551149871Sscottl pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) ) 1552149871Sscottl { 1553136849Sscottl MV_ERROR("channel %d: Set Features failed", channel); 1554136849Sscottl hptmv_free_channel(pAdapter, channel); 1555136849Sscottl return -1; 1556136849Sscottl } 1557136849Sscottl /* Enable EDMA */ 1558149871Sscottl if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE) 1559149871Sscottl { 1560136849Sscottl MV_ERROR("Failed to enable DMA, channel=%d", channel); 1561136849Sscottl hptmv_free_channel(pAdapter, channel); 1562136849Sscottl return -1; 1563136849Sscottl } 1564136849Sscottl } 1565136849Sscottl return 0; 1566136849Sscottl} 1567136849Sscottl 1568136849Sscottlstatic int 1569136849SscottlfResetActiveCommands(PVBus _vbus_p) 1570136849Sscottl{ 1571149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 1572136849Sscottl MV_U8 channel; 1573136849Sscottl for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1574149871Sscottl if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands) 1575149871Sscottl MvSataResetChannel(pMvSataAdapter,channel); 1576136849Sscottl } 1577136849Sscottl return 0; 1578136849Sscottl} 1579136849Sscottl 1580149871Sscottlvoid fCompleteAllCommandsSynchronously(PVBus _vbus_p) 1581136849Sscottl{ 1582136849Sscottl UINT cont; 1583136849Sscottl ULONG ticks = 0; 1584136849Sscottl MV_U8 channel; 1585149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 1586136849Sscottl MV_SATA_CHANNEL *pMvSataChannel; 1587136849Sscottl 1588136849Sscottl do { 1589136849Sscottlcheck_cmds: 1590136849Sscottl cont = 0; 1591136849Sscottl CheckPendingCall(_VBUS_P0); 1592136849Sscottl#ifdef _RAID5N_ 1593136849Sscottl dataxfer_poll(); 1594136849Sscottl xor_poll(); 1595136849Sscottl#endif 1596149871Sscottl for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1597136849Sscottl pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1598149871Sscottl if (pMvSataChannel && pMvSataChannel->outstandingCommands) 1599149871Sscottl { 1600136849Sscottl while (pMvSataChannel->outstandingCommands) { 1601149871Sscottl if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) { 1602136849Sscottl StallExec(1000); 1603136849Sscottl if (ticks++ > 3000) { 1604149871Sscottl MvSataResetChannel(pMvSataAdapter,channel); 1605136849Sscottl goto check_cmds; 1606136849Sscottl } 1607149871Sscottl } 1608149871Sscottl else 1609136849Sscottl ticks = 0; 1610136849Sscottl } 1611136849Sscottl cont = 1; 1612136849Sscottl } 1613136849Sscottl } 1614136849Sscottl } while (cont); 1615136849Sscottl} 1616136849Sscottl 1617136849Sscottlvoid 1618136849SscottlfResetVBus(_VBUS_ARG0) 1619136849Sscottl{ 1620136862Sscottl KdPrint(("fMvResetBus(%p)", _vbus_p)); 1621136849Sscottl 1622136849Sscottl /* some commands may already finished. */ 1623136849Sscottl CheckPendingCall(_VBUS_P0); 1624136849Sscottl 1625136849Sscottl fResetActiveCommands(_vbus_p); 1626136849Sscottl /* 1627136849Sscottl * the other pending commands may still be finished successfully. 1628136849Sscottl */ 1629136849Sscottl fCompleteAllCommandsSynchronously(_vbus_p); 1630136849Sscottl 1631136849Sscottl /* Now there should be no pending commands. No more action needed. */ 1632136849Sscottl CheckIdleCall(_VBUS_P0); 1633136849Sscottl 1634136849Sscottl KdPrint(("fMvResetBus() done")); 1635136849Sscottl} 1636136849Sscottl 1637149871Sscottl/*No rescan function*/ 1638136849Sscottlvoid 1639136849SscottlfRescanAllDevice(_VBUS_ARG0) 1640136849Sscottl{ 1641136849Sscottl} 1642136849Sscottl 1643136849Sscottlstatic MV_BOOLEAN 1644149871SscottlCommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 1645149871Sscottl MV_U8 channelNum, 1646149871Sscottl MV_COMPLETION_TYPE comp_type, 1647149871Sscottl MV_VOID_PTR commandId, 1648149871Sscottl MV_U16 responseFlags, 1649149871Sscottl MV_U32 timeStamp, 1650149871Sscottl MV_STORAGE_DEVICE_REGISTERS *registerStruct) 1651136849Sscottl{ 1652136849Sscottl PCommand pCmd = (PCommand) commandId; 1653136849Sscottl _VBUS_INST(pCmd->pVDevice->pVBus) 1654136849Sscottl 1655136849Sscottl if (pCmd->uScratch.sata_param.prdAddr) 1656149871Sscottl FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr); 1657136849Sscottl 1658149871Sscottl switch (comp_type) 1659149871Sscottl { 1660136849Sscottl case MV_COMPLETION_TYPE_NORMAL: 1661136849Sscottl pCmd->Result = RETURN_SUCCESS; 1662136849Sscottl break; 1663136849Sscottl case MV_COMPLETION_TYPE_ABORT: 1664136849Sscottl pCmd->Result = RETURN_BUS_RESET; 1665136849Sscottl break; 1666136849Sscottl case MV_COMPLETION_TYPE_ERROR: 1667149871Sscottl MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n", 1668149871Sscottl pMvSataAdapter->adapterId, channelNum, responseFlags); 1669136849Sscottl 1670136849Sscottl if (responseFlags & 4) { 1671149871Sscottl MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x," 1672149871Sscottl " LBA high %x, device %x, status %x\n", 1673149871Sscottl registerStruct->errorRegister, 1674149871Sscottl registerStruct->sectorCountRegister, 1675149871Sscottl registerStruct->lbaLowRegister, 1676149871Sscottl registerStruct->lbaMidRegister, 1677149871Sscottl registerStruct->lbaHighRegister, 1678149871Sscottl registerStruct->deviceRegister, 1679149871Sscottl registerStruct->statusRegister); 1680136849Sscottl } 1681149871Sscottl /*We can't do handleEdmaError directly here, because CommandCompletionCB is called by 1682149871Sscottl * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/ 1683136849Sscottl pCmd->uScratch.sata_param.responseFlags = responseFlags; 1684149871Sscottl pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister; 1685149871Sscottl pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister; 1686136849Sscottl pCmd->pVDevice->u.disk.QueueLength--; 1687136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd); 1688136849Sscottl return TRUE; 1689136849Sscottl 1690136849Sscottl default: 1691136849Sscottl MV_ERROR(" Unknown completion type (%d)\n", comp_type); 1692136849Sscottl return MV_FALSE; 1693136849Sscottl } 1694136849Sscottl 1695149871Sscottl if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) { 1696136849Sscottl pCmd->uScratch.sata_param.cmd_priv --; 1697136849Sscottl return TRUE; 1698136849Sscottl } 1699136849Sscottl pCmd->pVDevice->u.disk.QueueLength--; 1700136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1701136849Sscottl return TRUE; 1702136849Sscottl} 1703136849Sscottl 1704136849Sscottlvoid 1705136849SscottlfDeviceSendCommand(_VBUS_ARG PCommand pCmd) 1706136849Sscottl{ 1707149871Sscottl MV_SATA_EDMA_PRD_ENTRY *pPRDTable = 0; 1708136849Sscottl MV_SATA_ADAPTER *pMvSataAdapter; 1709136849Sscottl MV_SATA_CHANNEL *pMvSataChannel; 1710149871Sscottl PVDevice pVDevice = pCmd->pVDevice; 1711149871Sscottl PDevice pDevice = &pVDevice->u.disk; 1712190809Sdelphij LBA_T Lba = pCmd->uCmd.Ide.Lba; 1713149871Sscottl USHORT nSector = pCmd->uCmd.Ide.nSectors; 1714149871Sscottl 1715136849Sscottl MV_QUEUE_COMMAND_RESULT result; 1716136849Sscottl MV_QUEUE_COMMAND_INFO commandInfo; 1717149871Sscottl MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand; 1718149871Sscottl MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; 1719149871Sscottl 1720190809Sdelphij MV_BOOLEAN is48bit; 1721149871Sscottl MV_U8 channel; 1722149871Sscottl int i=0; 1723149871Sscottl 1724136849Sscottl DECLARE_BUFFER(FPSCAT_GATH, tmpSg); 1725136849Sscottl 1726136849Sscottl if (!pDevice->df_on_line) { 1727136849Sscottl MV_ERROR("Device is offline"); 1728136849Sscottl pCmd->Result = RETURN_BAD_DEVICE; 1729136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1730136849Sscottl return; 1731136849Sscottl } 1732136849Sscottl 1733136849Sscottl pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors; 1734136849Sscottl pMvSataChannel = pDevice->mv; 1735136849Sscottl pMvSataAdapter = pMvSataChannel->mvSataAdapter; 1736136849Sscottl channel = pMvSataChannel->channelNumber; 1737136849Sscottl 1738149871Sscottl /* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */ 1739136849Sscottl Lba += pDevice->dDeHiddenLba; 1740136849Sscottl /* check LBA */ 1741136849Sscottl if (Lba+nSector-1 > pDevice->dDeRealCapacity) { 1742136849Sscottl pCmd->Result = RETURN_INVALID_REQUEST; 1743136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1744136849Sscottl return; 1745136849Sscottl } 1746136849Sscottl 1747190809Sdelphij /* 1748190809Sdelphij * always use 48bit LBA if drive supports it. 1749190809Sdelphij * Some Seagate drives report error if you use a 28-bit command 1750190809Sdelphij * to access sector 0xfffffff. 1751190809Sdelphij */ 1752190809Sdelphij is48bit = pMvSataChannel->lba48Address; 1753136849Sscottl 1754149871Sscottl switch (pCmd->uCmd.Ide.Command) 1755149871Sscottl { 1756136849Sscottl case IDE_COMMAND_READ: 1757136849Sscottl case IDE_COMMAND_WRITE: 1758136849Sscottl if (pDevice->bDeModeSetting<8) goto pio; 1759136849Sscottl 1760136849Sscottl commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA; 1761136849Sscottl pUdmaParams->isEXT = is48bit; 1762136849Sscottl pUdmaParams->numOfSectors = nSector; 1763136849Sscottl pUdmaParams->lowLBAAddress = Lba; 1764136849Sscottl pUdmaParams->highLBAAddress = 0; 1765136849Sscottl pUdmaParams->prdHighAddr = 0; 1766136849Sscottl pUdmaParams->callBack = CommandCompletionCB; 1767136849Sscottl pUdmaParams->commandId = (MV_VOID_PTR )pCmd; 1768136849Sscottl if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ) 1769136849Sscottl pUdmaParams->readWrite = MV_UDMA_TYPE_READ; 1770136849Sscottl else 1771136849Sscottl pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE; 1772136849Sscottl 1773136849Sscottl if (pCmd->pSgTable && pCmd->cf_physical_sg) { 1774136849Sscottl FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1775149871Sscottl do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1776149871Sscottl } 1777149871Sscottl else { 1778149871Sscottl if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { 1779136849Sscottlpio: 1780149871Sscottl mvSataDisableChannelDma(pMvSataAdapter, channel); 1781149871Sscottl mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 1782149871Sscottl 1783149871Sscottl if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { 1784149871Sscottl FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1785149871Sscottl do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1786149871Sscottl } 1787149871Sscottl else { 1788149871Sscottl if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) { 1789149871Sscottl pCmd->Result = RETURN_NEED_LOGICAL_SG; 1790149871Sscottl goto finish_cmd; 1791149871Sscottl } 1792149871Sscottl } 1793149871Sscottl 1794136849Sscottl do { 1795149871Sscottl ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; 1796149871Sscottl ULONG_PTR addr = tmpSg->dSgAddress; 1797149871Sscottl if (size & 0x1ff) { 1798149871Sscottl pCmd->Result = RETURN_INVALID_REQUEST; 1799149871Sscottl goto finish_cmd; 1800149871Sscottl } 1801149871Sscottl if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1802149871Sscottl (pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, 1803149871Sscottl is48bit, 1804149871Sscottl (MV_U16_PTR)addr, 1805149871Sscottl size >> 1, /* count */ 1806149871Sscottl 0, /* features N/A */ 1807149871Sscottl (MV_U16)(size>>9), /*sector count*/ 1808149871Sscottl (MV_U16)( (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | (UCHAR)(Lba & 0xFF) ), /*lbalow*/ 1809149871Sscottl (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ 1810149871Sscottl (MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh */ 1811149871Sscottl (MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device */ 1812149871Sscottl (MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command) 1813149871Sscottl )==MV_FALSE) 1814149871Sscottl { 1815149871Sscottl pCmd->Result = RETURN_IDE_ERROR; 1816149871Sscottl goto finish_cmd; 1817149871Sscottl } 1818149871Sscottl Lba += size>>9; 1819149871Sscottl if(Lba & 0xF0000000) is48bit = MV_TRUE; 1820136849Sscottl } 1821149871Sscottl while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 1822149871Sscottl pCmd->Result = RETURN_SUCCESS; 1823149871Sscottlfinish_cmd: 1824149871Sscottl mvSataEnableChannelDma(pMvSataAdapter,channel); 1825149871Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1826149871Sscottl return; 1827136849Sscottl } 1828136849Sscottl } 1829136849Sscottl 1830149871Sscottl pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData); 1831136862Sscottl KdPrint(("pPRDTable:%p\n",pPRDTable)); 1832136849Sscottl if (!pPRDTable) { 1833136849Sscottl pCmd->Result = RETURN_DEVICE_BUSY; 1834149871Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1835136849Sscottl HPT_ASSERT(0); 1836136849Sscottl return; 1837136849Sscottl } 1838136849Sscottl 1839149871Sscottl do{ 1840149871Sscottl pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0); 1841136849Sscottl pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag; 1842136849Sscottl pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize; 1843136849Sscottl pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress; 1844136849Sscottl pPRDTable[i].reserved = 0; 1845136849Sscottl i++; 1846149871Sscottl }while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 1847136849Sscottl 1848149871Sscottl pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable); 1849149871Sscottl if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) { 1850136849Sscottl pUdmaParams->numOfSectors = 0; 1851136849Sscottl } 1852136849Sscottl 1853136849Sscottl pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable; 1854136849Sscottl 1855149871Sscottl result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1856136849Sscottl 1857149871Sscottl if (result != MV_QUEUE_COMMAND_RESULT_OK) 1858149871Sscottl { 1859136849Sscottlqueue_failed: 1860149871Sscottl switch (result) 1861149871Sscottl { 1862136849Sscottl case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS: 1863149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA " 1864149871Sscottl "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress); 1865136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1866136849Sscottl break; 1867136849Sscottl case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED: 1868149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. EDMA" 1869149871Sscottl " disabled adapter %d channel %d\n", 1870149871Sscottl pMvSataAdapter->adapterId, channel); 1871136849Sscottl mvSataEnableChannelDma(pMvSataAdapter,channel); 1872136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1873136849Sscottl break; 1874136849Sscottl case MV_QUEUE_COMMAND_RESULT_FULL: 1875149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. Queue is" 1876149871Sscottl " Full adapter %d channel %d\n", 1877149871Sscottl pMvSataAdapter->adapterId, channel); 1878136849Sscottl pCmd->Result = RETURN_DEVICE_BUSY; 1879136849Sscottl break; 1880136849Sscottl case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS: 1881149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. (Bad " 1882149871Sscottl "Params), pMvSataAdapter: %p, pSataChannel: %p.\n", 1883149871Sscottl pMvSataAdapter, pMvSataAdapter->sataChannel[channel]); 1884136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1885136849Sscottl break; 1886136849Sscottl default: 1887149871Sscottl MV_ERROR("IAL Error: Bad result value (%d) from queue" 1888149871Sscottl " command\n", result); 1889136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1890136849Sscottl } 1891136849Sscottl if(pPRDTable) 1892149871Sscottl FreePRDTable(pMvSataAdapter->IALData,pPRDTable); 1893149871Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1894136849Sscottl } 1895136849Sscottl pDevice->QueueLength++; 1896136849Sscottl return; 1897136849Sscottl 1898136849Sscottl case IDE_COMMAND_VERIFY: 1899136849Sscottl commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA; 1900136849Sscottl pNoUdmaParams->bufPtr = NULL; 1901136849Sscottl pNoUdmaParams->callBack = CommandCompletionCB; 1902136849Sscottl pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd; 1903136849Sscottl pNoUdmaParams->count = 0; 1904136849Sscottl pNoUdmaParams->features = 0; 1905136849Sscottl pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA; 1906136849Sscottl 1907136849Sscottl pCmd->uScratch.sata_param.cmd_priv = 1; 1908136849Sscottl if (pMvSataChannel->lba48Address == MV_TRUE){ 1909149871Sscottl pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; 1910136849Sscottl pNoUdmaParams->isEXT = MV_TRUE; 1911149871Sscottl pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 1912136849Sscottl pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 1913136849Sscottl pNoUdmaParams->lbaLow = 1914149871Sscottl (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); 1915136849Sscottl pNoUdmaParams->sectorCount = nSector; 1916136849Sscottl pNoUdmaParams->device = 0x40; 1917149871Sscottl result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1918149871Sscottl if (result != MV_QUEUE_COMMAND_RESULT_OK){ 1919136849Sscottl goto queue_failed; 1920136849Sscottl } 1921136849Sscottl return; 1922136849Sscottl } 1923149871Sscottl else{ 1924149871Sscottl pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; 1925149871Sscottl pNoUdmaParams->isEXT = MV_FALSE; 1926149871Sscottl pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 1927149871Sscottl pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 1928149871Sscottl pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); 1929149871Sscottl pNoUdmaParams->sectorCount = 0xff & nSector; 1930149871Sscottl pNoUdmaParams->device = (MV_U8)(0x40 | 1931149871Sscottl ((Lba & 0xf000000) >> 24)); 1932149871Sscottl pNoUdmaParams->callBack = CommandCompletionCB; 1933149871Sscottl result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1934149871Sscottl /*FIXME: how about the commands already queued? but marvel also forgets to consider this*/ 1935149871Sscottl if (result != MV_QUEUE_COMMAND_RESULT_OK){ 1936149871Sscottl goto queue_failed; 1937149871Sscottl } 1938136849Sscottl } 1939136849Sscottl break; 1940136849Sscottl default: 1941136849Sscottl pCmd->Result = RETURN_INVALID_REQUEST; 1942136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1943136849Sscottl break; 1944136849Sscottl } 1945136849Sscottl} 1946136849Sscottl 1947136849Sscottl/********************************************************** 1948136849Sscottl * 1949136849Sscottl * Probe the hostadapter. 1950136849Sscottl * 1951136849Sscottl **********************************************************/ 1952136849Sscottlstatic int 1953136849Sscottlhpt_probe(device_t dev) 1954136849Sscottl{ 1955136849Sscottl if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) && 1956136849Sscottl (pci_get_device(dev) == MV_SATA_DEVICE_ID_5081 1957136849Sscottl#ifdef FOR_DEMO 1958136849Sscottl || pci_get_device(dev) == MV_SATA_DEVICE_ID_5080 1959136849Sscottl#endif 1960149871Sscottl )) 1961149871Sscottl { 1962136849Sscottl KdPrintI((CONTROLLER_NAME " found\n")); 1963136849Sscottl device_set_desc(dev, CONTROLLER_NAME); 1964267368Sdelphij return (BUS_PROBE_DEFAULT); 1965136849Sscottl } 1966136849Sscottl else 1967136849Sscottl return(ENXIO); 1968136849Sscottl} 1969136849Sscottl 1970136849Sscottl/*********************************************************** 1971136849Sscottl * 1972136849Sscottl * Auto configuration: attach and init a host adapter. 1973136849Sscottl * 1974136849Sscottl ***********************************************************/ 1975136849Sscottlstatic int 1976136849Sscottlhpt_attach(device_t dev) 1977136849Sscottl{ 1978149871Sscottl IAL_ADAPTER_T * pAdapter = device_get_softc(dev); 1979136849Sscottl int rid; 1980136849Sscottl union ccb *ccb; 1981136849Sscottl struct cam_devq *devq; 1982136849Sscottl struct cam_sim *hpt_vsim; 1983136849Sscottl 1984269617Sjhb device_printf(dev, "%s Version %s \n", DRIVER_NAME, DRIVER_VERSION); 1985136849Sscottl 1986136849Sscottl pAdapter->hpt_dev = dev; 1987136849Sscottl 1988136849Sscottl rid = init_adapter(pAdapter); 1989136849Sscottl if (rid) 1990136849Sscottl return rid; 1991136849Sscottl 1992136849Sscottl rid = 0; 1993295790Sjhibbits if ((pAdapter->hpt_irq = bus_alloc_resource_any(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1994149871Sscottl { 1995136849Sscottl hpt_printk(("can't allocate interrupt\n")); 1996136849Sscottl return(ENXIO); 1997136849Sscottl } 1998136849Sscottl 1999269617Sjhb if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, 2000269617Sjhb INTR_TYPE_CAM | INTR_MPSAFE, 2001190809Sdelphij NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr)) 2002149871Sscottl { 2003136849Sscottl hpt_printk(("can't set up interrupt\n")); 2004136849Sscottl free(pAdapter, M_DEVBUF); 2005136849Sscottl return(ENXIO); 2006136849Sscottl } 2007136849Sscottl 2008149871Sscottl 2009149871Sscottl if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL) 2010149871Sscottl { 2011149871Sscottl bzero(ccb, sizeof(*ccb)); 2012136849Sscottl ccb->ccb_h.pinfo.priority = 1; 2013136849Sscottl ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; 2014149871Sscottl } 2015149871Sscottl else 2016149871Sscottl { 2017136849Sscottl return ENOMEM; 2018136849Sscottl } 2019136849Sscottl /* 2020136849Sscottl * Create the device queue for our SIM(s). 2021136849Sscottl */ 2022149871Sscottl if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) 2023149871Sscottl { 2024136849Sscottl KdPrint(("ENXIO\n")); 2025136849Sscottl return ENOMEM; 2026136849Sscottl } 2027136849Sscottl 2028136849Sscottl /* 2029136849Sscottl * Construct our SIM entry 2030136849Sscottl */ 2031190809Sdelphij hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), 2032269617Sjhb pAdapter, device_get_unit(pAdapter->hpt_dev), 2033269617Sjhb &pAdapter->lock, 1, 8, devq); 2034190809Sdelphij if (hpt_vsim == NULL) { 2035136849Sscottl cam_simq_free(devq); 2036136849Sscottl return ENOMEM; 2037136849Sscottl } 2038136849Sscottl 2039269617Sjhb mtx_lock(&pAdapter->lock); 2040190809Sdelphij if (xpt_bus_register(hpt_vsim, dev, 0) != CAM_SUCCESS) 2041149871Sscottl { 2042136849Sscottl cam_sim_free(hpt_vsim, /*free devq*/ TRUE); 2043269617Sjhb mtx_unlock(&pAdapter->lock); 2044136849Sscottl hpt_vsim = NULL; 2045136849Sscottl return ENXIO; 2046136849Sscottl } 2047136849Sscottl 2048136849Sscottl if(xpt_create_path(&pAdapter->path, /*periph */ NULL, 2049149871Sscottl cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, 2050149871Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) 2051149871Sscottl { 2052136849Sscottl xpt_bus_deregister(cam_sim_path(hpt_vsim)); 2053136849Sscottl cam_sim_free(hpt_vsim, /*free_devq*/TRUE); 2054269617Sjhb mtx_unlock(&pAdapter->lock); 2055136849Sscottl hpt_vsim = NULL; 2056136849Sscottl return ENXIO; 2057136849Sscottl } 2058269617Sjhb mtx_unlock(&pAdapter->lock); 2059136849Sscottl 2060136849Sscottl xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5); 2061136849Sscottl ccb->ccb_h.func_code = XPT_SASYNC_CB; 2062136849Sscottl ccb->csa.event_enable = AC_LOST_DEVICE; 2063136849Sscottl ccb->csa.callback = hpt_async; 2064136849Sscottl ccb->csa.callback_arg = hpt_vsim; 2065136849Sscottl xpt_action((union ccb *)ccb); 2066136849Sscottl free(ccb, M_DEVBUF); 2067136849Sscottl 2068190863Sdelphij if (device_get_unit(dev) == 0) { 2069190810Sdelphij /* Start the work thread. XXX */ 2070190810Sdelphij launch_worker_thread(); 2071139044Snjl } 2072136849Sscottl 2073136849Sscottl return 0; 2074136849Sscottl} 2075136849Sscottl 2076136849Sscottlstatic int 2077136849Sscottlhpt_detach(device_t dev) 2078149871Sscottl{ 2079136849Sscottl return (EBUSY); 2080136849Sscottl} 2081136849Sscottl 2082149871Sscottl 2083136849Sscottl/*************************************************************** 2084136849Sscottl * The poll function is used to simulate the interrupt when 2085136849Sscottl * the interrupt subsystem is not functioning. 2086136849Sscottl * 2087136849Sscottl ***************************************************************/ 2088136849Sscottlstatic void 2089136849Sscottlhpt_poll(struct cam_sim *sim) 2090136849Sscottl{ 2091269617Sjhb IAL_ADAPTER_T *pAdapter; 2092269617Sjhb 2093269617Sjhb pAdapter = cam_sim_softc(sim); 2094269617Sjhb 2095269617Sjhb hpt_intr_locked((void *)cam_sim_softc(sim)); 2096136849Sscottl} 2097136849Sscottl 2098136849Sscottl/**************************************************************** 2099136849Sscottl * Name: hpt_intr 2100136849Sscottl * Description: Interrupt handler. 2101136849Sscottl ****************************************************************/ 2102136849Sscottlstatic void 2103136849Sscottlhpt_intr(void *arg) 2104136849Sscottl{ 2105269617Sjhb IAL_ADAPTER_T *pAdapter; 2106269617Sjhb 2107269617Sjhb pAdapter = arg; 2108269617Sjhb mtx_lock(&pAdapter->lock); 2109269617Sjhb hpt_intr_locked(pAdapter); 2110269617Sjhb mtx_unlock(&pAdapter->lock); 2111269617Sjhb} 2112269617Sjhb 2113269617Sjhbstatic void 2114269617Sjhbhpt_intr_locked(IAL_ADAPTER_T *pAdapter) 2115269617Sjhb{ 2116269617Sjhb 2117269617Sjhb mtx_assert(&pAdapter->lock, MA_OWNED); 2118136849Sscottl /* KdPrintI(("----- Entering Isr() -----\n")); */ 2119149871Sscottl if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE) 2120149871Sscottl { 2121136849Sscottl _VBUS_INST(&pAdapter->VBus) 2122136849Sscottl CheckPendingCall(_VBUS_P0); 2123136849Sscottl } 2124136849Sscottl 2125136849Sscottl /* KdPrintI(("----- Leaving Isr() -----\n")); */ 2126136849Sscottl} 2127136849Sscottl 2128136849Sscottl/********************************************************** 2129136849Sscottl * Asynchronous Events 2130136849Sscottl *********************************************************/ 2131136849Sscottl#if (!defined(UNREFERENCED_PARAMETER)) 2132136849Sscottl#define UNREFERENCED_PARAMETER(x) (void)(x) 2133136849Sscottl#endif 2134136849Sscottl 2135136849Sscottlstatic void 2136136849Sscottlhpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, 2137136849Sscottl void * arg) 2138136849Sscottl{ 2139136849Sscottl /* debug XXXX */ 2140136849Sscottl panic("Here"); 2141136849Sscottl UNREFERENCED_PARAMETER(callback_arg); 2142136849Sscottl UNREFERENCED_PARAMETER(code); 2143136849Sscottl UNREFERENCED_PARAMETER(path); 2144136849Sscottl UNREFERENCED_PARAMETER(arg); 2145136849Sscottl 2146136849Sscottl} 2147136849Sscottl 2148136849Sscottlstatic void 2149136849SscottlFlushAdapter(IAL_ADAPTER_T *pAdapter) 2150136849Sscottl{ 2151136849Sscottl int i; 2152136849Sscottl 2153136849Sscottl hpt_printk(("flush all devices\n")); 2154136849Sscottl 2155136849Sscottl /* flush all devices */ 2156136849Sscottl for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) { 2157136849Sscottl PVDevice pVDev = pAdapter->VBus.pVDevice[i]; 2158149871Sscottl if(pVDev) fFlushVDev(pVDev); 2159136849Sscottl } 2160136849Sscottl} 2161136849Sscottl 2162136849Sscottlstatic int 2163136849Sscottlhpt_shutdown(device_t dev) 2164136849Sscottl{ 2165149871Sscottl IAL_ADAPTER_T *pAdapter; 2166149871Sscottl 2167149871Sscottl pAdapter = device_get_softc(dev); 2168136849Sscottl 2169149871Sscottl EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh); 2170269617Sjhb mtx_lock(&pAdapter->lock); 2171149871Sscottl FlushAdapter(pAdapter); 2172269617Sjhb mtx_unlock(&pAdapter->lock); 2173149871Sscottl /* give the flush some time to happen, 2174149871Sscottl *otherwise "shutdown -p now" will make file system corrupted */ 2175149871Sscottl DELAY(1000 * 1000 * 5); 2176149871Sscottl return 0; 2177136849Sscottl} 2178136849Sscottl 2179136849Sscottlvoid 2180136849SscottlCheck_Idle_Call(IAL_ADAPTER_T *pAdapter) 2181136849Sscottl{ 2182136849Sscottl _VBUS_INST(&pAdapter->VBus) 2183136849Sscottl 2184136849Sscottl if (mWaitingForIdle(_VBUS_P0)) { 2185136849Sscottl CheckIdleCall(_VBUS_P0); 2186136849Sscottl#ifdef SUPPORT_ARRAY 2187149871Sscottl { 2188149871Sscottl int i; 2189136849Sscottl PVDevice pArray; 2190149871Sscottl for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ 2191149871Sscottl if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 2192149871Sscottl continue; 2193149871Sscottl else if (pArray->u.array.rf_auto_rebuild) { 2194149871Sscottl KdPrint(("auto rebuild.\n")); 2195149871Sscottl pArray->u.array.rf_auto_rebuild = 0; 2196149871Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 2197149871Sscottl } 2198136849Sscottl } 2199136849Sscottl } 2200136849Sscottl#endif 2201136849Sscottl } 2202136849Sscottl /* launch the awaiting commands blocked by mWaitingForIdle */ 2203149871Sscottl while(pAdapter->pending_Q!= NULL) 2204149871Sscottl { 2205136849Sscottl _VBUS_INST(&pAdapter->VBus) 2206149871Sscottl union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; 2207136849Sscottl hpt_free_ccb(&pAdapter->pending_Q, ccb); 2208136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb); 2209136849Sscottl } 2210136849Sscottl} 2211136849Sscottl 2212136849Sscottlstatic void 2213136849Sscottlccb_done(union ccb *ccb) 2214136849Sscottl{ 2215149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2216149871Sscottl IAL_ADAPTER_T * pAdapter = pmap->pAdapter; 2217149871Sscottl KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status)); 2218136849Sscottl 2219149871Sscottl dmamap_put(pmap); 2220136849Sscottl xpt_done(ccb); 2221136849Sscottl 2222136849Sscottl pAdapter->outstandingCommands--; 2223136849Sscottl 2224149871Sscottl if (pAdapter->outstandingCommands == 0) 2225149871Sscottl { 2226136849Sscottl if(DPC_Request_Nums == 0) 2227136849Sscottl Check_Idle_Call(pAdapter); 2228269617Sjhb wakeup(pAdapter); 2229136849Sscottl } 2230136849Sscottl} 2231136849Sscottl 2232136849Sscottl/**************************************************************** 2233136849Sscottl * Name: hpt_action 2234136849Sscottl * Description: Process a queued command from the CAM layer. 2235136849Sscottl * Parameters: sim - Pointer to SIM object 2236136849Sscottl * ccb - Pointer to SCSI command structure. 2237136849Sscottl ****************************************************************/ 2238136849Sscottl 2239136849Sscottlvoid 2240136849Sscottlhpt_action(struct cam_sim *sim, union ccb *ccb) 2241136849Sscottl{ 2242136849Sscottl IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim); 2243149871Sscottl PBUS_DMAMAP pmap; 2244136849Sscottl _VBUS_INST(&pAdapter->VBus) 2245136849Sscottl 2246269617Sjhb mtx_assert(&pAdapter->lock, MA_OWNED); 2247149878Sscottl CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n")); 2248149871Sscottl KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code)); 2249136849Sscottl 2250149871Sscottl switch (ccb->ccb_h.func_code) 2251149871Sscottl { 2252149871Sscottl case XPT_SCSI_IO: /* Execute the requested I/O operation */ 2253149871Sscottl { 2254149871Sscottl /* ccb->ccb_h.path_id is not our bus id - don't check it */ 2255136849Sscottl 2256149871Sscottl if (ccb->ccb_h.target_lun) { 2257149871Sscottl ccb->ccb_h.status = CAM_LUN_INVALID; 2258149871Sscottl xpt_done(ccb); 2259149871Sscottl return; 2260149871Sscottl } 2261149871Sscottl if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || 2262149871Sscottl pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { 2263149871Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 2264149871Sscottl xpt_done(ccb); 2265149871Sscottl return; 2266149871Sscottl } 2267136849Sscottl 2268149871Sscottl if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 2269149871Sscottl Check_Idle_Call(pAdapter); 2270136849Sscottl 2271149871Sscottl pmap = dmamap_get(pAdapter); 2272149871Sscottl HPT_ASSERT(pmap); 2273149871Sscottl ccb->ccb_adapter = pmap; 2274149871Sscottl memset((void *)pmap->psg, 0, sizeof(pmap->psg)); 2275136849Sscottl 2276149871Sscottl if (mWaitingForIdle(_VBUS_P0)) 2277149871Sscottl hpt_queue_ccb(&pAdapter->pending_Q, ccb); 2278149871Sscottl else 2279149871Sscottl OsSendCommand(_VBUS_P ccb); 2280136849Sscottl 2281149871Sscottl /* KdPrint(("leave scsiio\n")); */ 2282149871Sscottl break; 2283149871Sscottl } 2284136849Sscottl 2285149871Sscottl case XPT_RESET_BUS: 2286149871Sscottl KdPrint(("reset bus\n")); 2287149871Sscottl fResetVBus(_VBUS_P0); 2288149871Sscottl xpt_done(ccb); 2289149871Sscottl break; 2290136849Sscottl 2291149871Sscottl case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 2292149871Sscottl case XPT_ABORT: /* Abort the specified CCB */ 2293149871Sscottl case XPT_TERM_IO: /* Terminate the I/O process */ 2294149871Sscottl /* XXX Implement */ 2295149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2296149871Sscottl xpt_done(ccb); 2297149871Sscottl break; 2298136849Sscottl 2299149871Sscottl case XPT_GET_TRAN_SETTINGS: 2300149871Sscottl case XPT_SET_TRAN_SETTINGS: 2301149871Sscottl /* XXX Implement */ 2302149871Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2303149871Sscottl xpt_done(ccb); 2304149871Sscottl break; 2305136849Sscottl 2306149871Sscottl case XPT_CALC_GEOMETRY: 2307227912Smarius cam_calc_geometry(&ccb->ccg, 1); 2308149871Sscottl xpt_done(ccb); 2309149871Sscottl break; 2310136849Sscottl 2311149871Sscottl case XPT_PATH_INQ: /* Path routing inquiry */ 2312149871Sscottl { 2313149871Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 2314136849Sscottl 2315149871Sscottl cpi->version_num = 1; /* XXX??? */ 2316149871Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 2317149871Sscottl cpi->target_sprt = 0; 2318149871Sscottl /* Not necessary to reset bus */ 2319149871Sscottl cpi->hba_misc = PIM_NOBUSRESET; 2320149871Sscottl cpi->hba_eng_cnt = 0; 2321136849Sscottl 2322149871Sscottl cpi->max_target = MAX_VDEVICE_PER_VBUS; 2323149871Sscottl cpi->max_lun = 0; 2324149871Sscottl cpi->initiator_id = MAX_VDEVICE_PER_VBUS; 2325136849Sscottl 2326149871Sscottl cpi->bus_id = cam_sim_bus(sim); 2327149871Sscottl cpi->base_transfer_speed = 3300; 2328149871Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2329149871Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 2330149871Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2331149871Sscottl cpi->unit_number = cam_sim_unit(sim); 2332209341Smav cpi->transport = XPORT_SPI; 2333209341Smav cpi->transport_version = 2; 2334209341Smav cpi->protocol = PROTO_SCSI; 2335209341Smav cpi->protocol_version = SCSI_REV_2; 2336149871Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 2337149871Sscottl xpt_done(ccb); 2338149871Sscottl break; 2339149871Sscottl } 2340136849Sscottl 2341149871Sscottl default: 2342149871Sscottl KdPrint(("invalid cmd\n")); 2343149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2344149871Sscottl xpt_done(ccb); 2345149871Sscottl break; 2346136849Sscottl } 2347136849Sscottl /* KdPrint(("leave hpt_action..............\n")); */ 2348136849Sscottl} 2349136849Sscottl 2350136849Sscottl/* shall be called at lock_driver() */ 2351136849Sscottlstatic void 2352136849Sscottlhpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb) 2353136849Sscottl{ 2354136849Sscottl if(*ccb_Q == NULL) 2355136849Sscottl ccb->ccb_h.ccb_ccb_ptr = ccb; 2356136849Sscottl else { 2357136849Sscottl ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr; 2358136849Sscottl (*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb; 2359136849Sscottl } 2360136849Sscottl 2361136849Sscottl *ccb_Q = ccb; 2362136849Sscottl} 2363136849Sscottl 2364136849Sscottl/* shall be called at lock_driver() */ 2365136849Sscottlstatic void 2366136849Sscottlhpt_free_ccb(union ccb **ccb_Q, union ccb *ccb) 2367136849Sscottl{ 2368136849Sscottl union ccb *TempCCB; 2369136849Sscottl 2370136849Sscottl TempCCB = *ccb_Q; 2371136849Sscottl 2372149871Sscottl if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/ 2373136849Sscottl *ccb_Q = NULL; 2374136849Sscottl else { 2375136849Sscottl while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb) 2376136849Sscottl TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr; 2377136849Sscottl 2378136849Sscottl TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr; 2379136849Sscottl 2380136849Sscottl if(*ccb_Q == ccb) 2381136849Sscottl *ccb_Q = TempCCB; 2382136849Sscottl } 2383136849Sscottl} 2384136849Sscottl 2385136849Sscottl#ifdef SUPPORT_ARRAY 2386136849Sscottl/*************************************************************************** 2387136849Sscottl * Function: hpt_worker_thread 2388136849Sscottl * Description: Do background rebuilding. Execute in kernel thread context. 2389136849Sscottl * Returns: None 2390136849Sscottl ***************************************************************************/ 2391136849Sscottlstatic void hpt_worker_thread(void) 2392136849Sscottl{ 2393136849Sscottl 2394136849Sscottl for(;;) { 2395269617Sjhb mtx_lock(&DpcQueue_Lock); 2396136849Sscottl while (DpcQueue_First!=DpcQueue_Last) { 2397136849Sscottl ST_HPT_DPC p; 2398136849Sscottl p = DpcQueue[DpcQueue_First]; 2399136849Sscottl DpcQueue_First++; 2400136849Sscottl DpcQueue_First %= MAX_DPC; 2401136849Sscottl DPC_Request_Nums++; 2402269617Sjhb mtx_unlock(&DpcQueue_Lock); 2403136849Sscottl p.dpc(p.pAdapter, p.arg, p.flags); 2404136849Sscottl 2405269617Sjhb mtx_lock(&p.pAdapter->lock); 2406269617Sjhb mtx_lock(&DpcQueue_Lock); 2407136849Sscottl DPC_Request_Nums--; 2408149871Sscottl /* since we may have prevented Check_Idle_Call, do it here */ 2409136849Sscottl if (DPC_Request_Nums==0) { 2410136849Sscottl if (p.pAdapter->outstandingCommands == 0) { 2411136849Sscottl _VBUS_INST(&p.pAdapter->VBus); 2412136849Sscottl Check_Idle_Call(p.pAdapter); 2413136849Sscottl CheckPendingCall(_VBUS_P0); 2414136849Sscottl } 2415136849Sscottl } 2416269617Sjhb mtx_unlock(&p.pAdapter->lock); 2417269617Sjhb mtx_unlock(&DpcQueue_Lock); 2418136849Sscottl 2419149871Sscottl /*Schedule out*/ 2420149871Sscottl if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) { 2421149871Sscottl /* abort rebuilding process. */ 2422149871Sscottl IAL_ADAPTER_T *pAdapter; 2423149871Sscottl PVDevice pArray; 2424149871Sscottl PVBus _vbus_p; 2425149871Sscottl int i; 2426269617Sjhb 2427269617Sjhb sx_slock(&hptmv_list_lock); 2428149871Sscottl pAdapter = gIal_Adapter; 2429149871Sscottl 2430315221Spfg while(pAdapter != NULL){ 2431269617Sjhb mtx_lock(&pAdapter->lock); 2432149871Sscottl _vbus_p = &pAdapter->VBus; 2433149871Sscottl 2434149871Sscottl for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 2435149871Sscottl { 2436149871Sscottl if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 2437149871Sscottl continue; 2438149871Sscottl else if (pArray->u.array.rf_rebuilding || 2439149871Sscottl pArray->u.array.rf_verifying || 2440149871Sscottl pArray->u.array.rf_initializing) 2441149871Sscottl { 2442149871Sscottl pArray->u.array.rf_abort_rebuild = 1; 2443149871Sscottl } 2444136849Sscottl } 2445269617Sjhb mtx_unlock(&pAdapter->lock); 2446149871Sscottl pAdapter = pAdapter->next; 2447136849Sscottl } 2448269617Sjhb sx_sunlock(&hptmv_list_lock); 2449136849Sscottl } 2450269617Sjhb mtx_lock(&DpcQueue_Lock); 2451136849Sscottl } 2452269617Sjhb mtx_unlock(&DpcQueue_Lock); 2453136849Sscottl 2454149871Sscottl/*Remove this debug option*/ 2455149871Sscottl/* 2456136849Sscottl#ifdef DEBUG 2457136849Sscottl if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) 2458167086Sjhb pause("hptrdy", 2*hz); 2459136849Sscottl#endif 2460149871Sscottl*/ 2461172836Sjulian kproc_suspend_check(curproc); 2462269617Sjhb pause("-", 2*hz); /* wait for something to do */ 2463136849Sscottl } 2464136849Sscottl} 2465136849Sscottl 2466136849Sscottlstatic struct proc *hptdaemonproc; 2467136849Sscottlstatic struct kproc_desc hpt_kp = { 2468136849Sscottl "hpt_wt", 2469136849Sscottl hpt_worker_thread, 2470136849Sscottl &hptdaemonproc 2471136849Sscottl}; 2472136849Sscottl 2473149871Sscottl/*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/ 2474136849Sscottlstatic void 2475136849Sscottllaunch_worker_thread(void) 2476136849Sscottl{ 2477136849Sscottl IAL_ADAPTER_T *pAdapTemp; 2478136849Sscottl 2479136849Sscottl kproc_start(&hpt_kp); 2480136849Sscottl 2481269617Sjhb sx_slock(&hptmv_list_lock); 2482136849Sscottl for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 2483136849Sscottl 2484136849Sscottl _VBUS_INST(&pAdapTemp->VBus) 2485136849Sscottl int i; 2486136849Sscottl PVDevice pVDev; 2487136849Sscottl 2488136849Sscottl for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 2489136849Sscottl if ((pVDev=ArrayTables(i))->u.array.dArStamp==0) 2490136849Sscottl continue; 2491149871Sscottl else{ 2492149871Sscottl if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding) 2493149871Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev, 2494149871Sscottl (UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 2495149871Sscottl } 2496136849Sscottl } 2497269617Sjhb sx_sunlock(&hptmv_list_lock); 2498136849Sscottl 2499136849Sscottl /* 2500149871Sscottl * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished. 2501136849Sscottl */ 2502249849Smav EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, 2503249849Smav SHUTDOWN_PRI_LAST); 2504136849Sscottl} 2505149871Sscottl/* 2506149871Sscottl *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL); 2507149871Sscottl*/ 2508136849Sscottl 2509149871Sscottl#endif 2510136849Sscottl 2511136849Sscottl/********************************************************************************/ 2512136849Sscottl 2513149871Sscottlint HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) 2514136849Sscottl{ 2515267368Sdelphij union ccb *ccb = (union ccb *)pCmd->pOrgCommand; 2516267368Sdelphij 2517267368Sdelphij if (logical) { 2518267368Sdelphij pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; 2519267368Sdelphij pSg->wSgSize = ccb->csio.dxfer_len; 2520267368Sdelphij pSg->wSgFlag = SG_FLAG_EOT; 2521267368Sdelphij return TRUE; 2522267368Sdelphij } 2523149871Sscottl /* since we have provided physical sg, nobody will ask us to build physical sg */ 2524149871Sscottl HPT_ASSERT(0); 2525149871Sscottl return FALSE; 2526136849Sscottl} 2527136849Sscottl 2528136849Sscottl/*******************************************************************************/ 2529136849SscottlULONG HPTLIBAPI 2530136849SscottlGetStamp(void) 2531136849Sscottl{ 2532136849Sscottl /* 2533136849Sscottl * the system variable, ticks, can't be used since it hasn't yet been active 2534136849Sscottl * when our driver starts (ticks==0, it's a invalid stamp value) 2535136849Sscottl */ 2536149871Sscottl ULONG stamp; 2537149871Sscottl do { stamp = random(); } while (stamp==0); 2538136849Sscottl return stamp; 2539136849Sscottl} 2540136849Sscottl 2541136849Sscottl 2542136849Sscottlstatic void 2543136849SscottlSetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) 2544136849Sscottl{ 2545136849Sscottl int i; 2546149871Sscottl IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; 2547149871Sscottl 2548136849Sscottl inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/ 2549136849Sscottl inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5); 2550136849Sscottl#ifndef SERIAL_CMDS 2551136849Sscottl inquiryData->CommandQueue = 1; 2552136849Sscottl#endif 2553136849Sscottl 2554136849Sscottl switch(pVDev->VDeviceType) { 2555136849Sscottl case VD_SINGLE_DISK: 2556136849Sscottl case VD_ATAPI: 2557136849Sscottl case VD_REMOVABLE: 2558136849Sscottl /* Set the removable bit, if applicable. */ 2559149871Sscottl if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80)) 2560136849Sscottl inquiryData->RemovableMedia = 1; 2561136849Sscottl 2562136849Sscottl /* Fill in vendor identification fields. */ 2563149871Sscottl for (i = 0; i < 20; i += 2) { 2564149871Sscottl inquiryData->VendorId[i] = ((PUCHAR)pIdentify->ModelNumber)[i + 1]; 2565149871Sscottl inquiryData->VendorId[i+1] = ((PUCHAR)pIdentify->ModelNumber)[i]; 2566136849Sscottl 2567136849Sscottl } 2568136849Sscottl 2569136849Sscottl /* Initialize unused portion of product id. */ 2570136849Sscottl for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' '; 2571136849Sscottl 2572136849Sscottl /* firmware revision */ 2573149871Sscottl for (i = 0; i < 4; i += 2) 2574149871Sscottl { 2575149871Sscottl inquiryData->ProductRevisionLevel[i] = ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; 2576149871Sscottl inquiryData->ProductRevisionLevel[i+1] = ((PUCHAR)pIdentify->FirmwareRevision)[i]; 2577136849Sscottl } 2578136849Sscottl break; 2579136849Sscottl default: 2580190809Sdelphij memcpy(&inquiryData->VendorId, "RR18xx ", 8); 2581136849Sscottl#ifdef SUPPORT_ARRAY 2582149871Sscottl switch(pVDev->VDeviceType){ 2583136849Sscottl case VD_RAID_0: 2584149871Sscottl if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2585149871Sscottl (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2586149871Sscottl memcpy(&inquiryData->ProductId, "RAID 1/0 Array ", 16); 2587136849Sscottl else 2588149871Sscottl memcpy(&inquiryData->ProductId, "RAID 0 Array ", 16); 2589136849Sscottl break; 2590136849Sscottl case VD_RAID_1: 2591149871Sscottl if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2592149871Sscottl (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2593149871Sscottl memcpy(&inquiryData->ProductId, "RAID 0/1 Array ", 16); 2594136849Sscottl else 2595149871Sscottl memcpy(&inquiryData->ProductId, "RAID 1 Array ", 16); 2596136849Sscottl break; 2597136849Sscottl case VD_RAID_5: 2598136849Sscottl memcpy(&inquiryData->ProductId, "RAID 5 Array ", 16); 2599136849Sscottl break; 2600136849Sscottl case VD_JBOD: 2601136849Sscottl memcpy(&inquiryData->ProductId, "JBOD Array ", 16); 2602136849Sscottl break; 2603136849Sscottl } 2604136849Sscottl#endif 2605136849Sscottl memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4); 2606136849Sscottl break; 2607136849Sscottl } 2608136849Sscottl} 2609136849Sscottl 2610136849Sscottlstatic void 2611136849Sscottlhpt_timeout(void *arg) 2612136849Sscottl{ 2613269617Sjhb PBUS_DMAMAP pmap = (PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter; 2614269617Sjhb IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2615269617Sjhb _VBUS_INST(&pAdapter->VBus) 2616269617Sjhb 2617269617Sjhb mtx_assert(&pAdapter->lock, MA_OWNED); 2618136849Sscottl fResetVBus(_VBUS_P0); 2619136849Sscottl} 2620136849Sscottl 2621149871Sscottlstatic void 2622149871Sscottlhpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 2623149871Sscottl{ 2624149871Sscottl PCommand pCmd = (PCommand)arg; 2625149871Sscottl union ccb *ccb = pCmd->pOrgCommand; 2626149871Sscottl struct ccb_hdr *ccb_h = &ccb->ccb_h; 2627149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter; 2628149871Sscottl IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2629149871Sscottl PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2630149871Sscottl FPSCAT_GATH psg = pCmd->pSgTable; 2631149871Sscottl int idx; 2632149871Sscottl _VBUS_INST(pVDev->pVBus) 2633149871Sscottl 2634149871Sscottl HPT_ASSERT(pCmd->cf_physical_sg); 2635149871Sscottl 2636246713Skib if (error) 2637149871Sscottl panic("busdma error"); 2638149871Sscottl 2639149871Sscottl HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); 2640149871Sscottl 2641246713Skib if (nsegs != 0) { 2642246713Skib for (idx = 0; idx < nsegs; idx++, psg++) { 2643246713Skib psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; 2644246713Skib psg->wSgSize = segs[idx].ds_len; 2645246713Skib psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; 2646246713Skib /* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ 2647246713Skib } 2648246713Skib /* psg[-1].wSgFlag = SG_FLAG_EOT; */ 2649246713Skib 2650246713Skib if (pCmd->cf_data_in) { 2651246713Skib bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, 2652246713Skib BUS_DMASYNC_PREREAD); 2653246713Skib } 2654246713Skib else if (pCmd->cf_data_out) { 2655246713Skib bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, 2656246713Skib BUS_DMASYNC_PREWRITE); 2657246713Skib } 2658149871Sscottl } 2659149871Sscottl 2660269617Sjhb callout_reset(&pmap->timeout, 20 * hz, hpt_timeout, ccb); 2661149871Sscottl pVDev->pfnSendCommand(_VBUS_P pCmd); 2662149871Sscottl CheckPendingCall(_VBUS_P0); 2663149871Sscottl} 2664149871Sscottl 2665149871Sscottl 2666149871Sscottl 2667136849Sscottlstatic void HPTLIBAPI 2668136849SscottlOsSendCommand(_VBUS_ARG union ccb *ccb) 2669136849Sscottl{ 2670149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2671149871Sscottl IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2672149871Sscottl struct ccb_hdr *ccb_h = &ccb->ccb_h; 2673149871Sscottl struct ccb_scsiio *csio = &ccb->csio; 2674149871Sscottl PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2675136849Sscottl 2676149871Sscottl KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", 2677136849Sscottl ccb, 2678136849Sscottl *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0], 2679136849Sscottl *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4], 2680136849Sscottl *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8] 2681136849Sscottl )); 2682136849Sscottl 2683136849Sscottl pAdapter->outstandingCommands++; 2684136849Sscottl 2685136849Sscottl if (pVDev == NULL || pVDev->vf_online == 0) { 2686136849Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2687136849Sscottl ccb_done(ccb); 2688136849Sscottl goto Command_Complished; 2689136849Sscottl } 2690136849Sscottl 2691136849Sscottl switch(ccb->csio.cdb_io.cdb_bytes[0]) 2692136849Sscottl { 2693149871Sscottl case TEST_UNIT_READY: 2694149871Sscottl case START_STOP_UNIT: 2695149871Sscottl case SYNCHRONIZE_CACHE: 2696149871Sscottl /* FALLTHROUGH */ 2697149871Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 2698149871Sscottl break; 2699136849Sscottl 2700149871Sscottl case INQUIRY: 2701149871Sscottl ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); 2702149871Sscottl SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); 2703149871Sscottl ccb_h->status = CAM_REQ_CMP; 2704149871Sscottl break; 2705136849Sscottl 2706149871Sscottl case READ_CAPACITY: 2707149871Sscottl { 2708190809Sdelphij UCHAR *rbuf=csio->data_ptr; 2709190809Sdelphij unsigned int cap; 2710190809Sdelphij 2711190809Sdelphij if (pVDev->VDeviceCapacity > 0xfffffffful) { 2712190809Sdelphij cap = 0xfffffffful; 2713190809Sdelphij } else { 2714190809Sdelphij cap = pVDev->VDeviceCapacity - 1; 2715190809Sdelphij } 2716190809Sdelphij 2717190809Sdelphij rbuf[0] = (UCHAR)(cap>>24); 2718190809Sdelphij rbuf[1] = (UCHAR)(cap>>16); 2719190809Sdelphij rbuf[2] = (UCHAR)(cap>>8); 2720190809Sdelphij rbuf[3] = (UCHAR)cap; 2721149871Sscottl /* Claim 512 byte blocks (big-endian). */ 2722190809Sdelphij rbuf[4] = 0; 2723190809Sdelphij rbuf[5] = 0; 2724190809Sdelphij rbuf[6] = 2; 2725190809Sdelphij rbuf[7] = 0; 2726190809Sdelphij 2727149871Sscottl ccb_h->status = CAM_REQ_CMP; 2728149871Sscottl break; 2729136849Sscottl } 2730136849Sscottl 2731190809Sdelphij case 0x9e: /*SERVICE_ACTION_IN*/ 2732190809Sdelphij { 2733190809Sdelphij UCHAR *rbuf = csio->data_ptr; 2734190809Sdelphij LBA_T cap = pVDev->VDeviceCapacity - 1; 2735190809Sdelphij 2736190809Sdelphij rbuf[0] = (UCHAR)(cap>>56); 2737190809Sdelphij rbuf[1] = (UCHAR)(cap>>48); 2738190809Sdelphij rbuf[2] = (UCHAR)(cap>>40); 2739190809Sdelphij rbuf[3] = (UCHAR)(cap>>32); 2740190809Sdelphij rbuf[4] = (UCHAR)(cap>>24); 2741190809Sdelphij rbuf[5] = (UCHAR)(cap>>16); 2742190809Sdelphij rbuf[6] = (UCHAR)(cap>>8); 2743190809Sdelphij rbuf[7] = (UCHAR)cap; 2744190809Sdelphij rbuf[8] = 0; 2745190809Sdelphij rbuf[9] = 0; 2746190809Sdelphij rbuf[10] = 2; 2747190809Sdelphij rbuf[11] = 0; 2748190809Sdelphij 2749190809Sdelphij ccb_h->status = CAM_REQ_CMP; 2750190809Sdelphij break; 2751190809Sdelphij } 2752190809Sdelphij 2753136849Sscottl case READ_6: 2754136849Sscottl case WRITE_6: 2755136849Sscottl case READ_10: 2756136849Sscottl case WRITE_10: 2757190809Sdelphij case 0x88: /* READ_16 */ 2758190809Sdelphij case 0x8a: /* WRITE_16 */ 2759136849Sscottl case 0x13: 2760136849Sscottl case 0x2f: 2761149871Sscottl { 2762149871Sscottl UCHAR Cdb[16]; 2763149871Sscottl UCHAR CdbLength; 2764149871Sscottl _VBUS_INST(pVDev->pVBus) 2765149871Sscottl PCommand pCmd = AllocateCommand(_VBUS_P0); 2766246713Skib int error; 2767149871Sscottl HPT_ASSERT(pCmd); 2768136849Sscottl 2769149871Sscottl CdbLength = csio->cdb_len; 2770149871Sscottl if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) 2771149871Sscottl { 2772149871Sscottl if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) 2773149871Sscottl { 2774149871Sscottl bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); 2775149871Sscottl } 2776149871Sscottl else 2777149871Sscottl { 2778149871Sscottl KdPrintE(("ERROR!!!\n")); 2779149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2780149871Sscottl break; 2781149871Sscottl } 2782149871Sscottl } 2783149871Sscottl else 2784149871Sscottl { 2785149871Sscottl bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); 2786149871Sscottl } 2787136849Sscottl 2788149871Sscottl pCmd->pOrgCommand = ccb; 2789149871Sscottl pCmd->pVDevice = pVDev; 2790149871Sscottl pCmd->pfnCompletion = fOsCommandDone; 2791149871Sscottl pCmd->pfnBuildSgl = fOsBuildSgl; 2792149871Sscottl pCmd->pSgTable = pmap->psg; 2793136849Sscottl 2794149871Sscottl switch (Cdb[0]) 2795149871Sscottl { 2796149871Sscottl case READ_6: 2797149871Sscottl case WRITE_6: 2798149871Sscottl case 0x13: 2799149871Sscottl pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; 2800149871Sscottl pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; 2801149871Sscottl break; 2802149871Sscottl 2803190809Sdelphij case 0x88: /* READ_16 */ 2804190809Sdelphij case 0x8a: /* WRITE_16 */ 2805190809Sdelphij pCmd->uCmd.Ide.Lba = 2806190809Sdelphij (HPT_U64)Cdb[2] << 56 | 2807190809Sdelphij (HPT_U64)Cdb[3] << 48 | 2808190809Sdelphij (HPT_U64)Cdb[4] << 40 | 2809190809Sdelphij (HPT_U64)Cdb[5] << 32 | 2810190809Sdelphij (HPT_U64)Cdb[6] << 24 | 2811190809Sdelphij (HPT_U64)Cdb[7] << 16 | 2812190809Sdelphij (HPT_U64)Cdb[8] << 8 | 2813190809Sdelphij (HPT_U64)Cdb[9]; 2814190809Sdelphij pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13]; 2815190809Sdelphij break; 2816190809Sdelphij 2817149871Sscottl default: 2818149871Sscottl pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24); 2819149871Sscottl pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8); 2820149871Sscottl break; 2821149871Sscottl } 2822149871Sscottl 2823149871Sscottl switch (Cdb[0]) 2824149871Sscottl { 2825149871Sscottl case READ_6: 2826149871Sscottl case READ_10: 2827190809Sdelphij case 0x88: /* READ_16 */ 2828149871Sscottl pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; 2829149871Sscottl pCmd->cf_data_in = 1; 2830149871Sscottl break; 2831149871Sscottl 2832149871Sscottl case WRITE_6: 2833149871Sscottl case WRITE_10: 2834190809Sdelphij case 0x8a: /* WRITE_16 */ 2835149871Sscottl pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; 2836149871Sscottl pCmd->cf_data_out = 1; 2837149871Sscottl break; 2838149871Sscottl case 0x13: 2839149871Sscottl case 0x2f: 2840149871Sscottl pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; 2841149871Sscottl break; 2842149871Sscottl } 2843149871Sscottl/*///////////////////////// */ 2844246713Skib pCmd->cf_physical_sg = 1; 2845246713Skib error = bus_dmamap_load_ccb(pAdapter->io_dma_parent, 2846246713Skib pmap->dma_map, 2847246713Skib ccb, 2848246713Skib hpt_io_dmamap_callback, 2849246713Skib pCmd, BUS_DMA_WAITOK 2850246713Skib ); 2851246713Skib KdPrint(("bus_dmamap_load return %d\n", error)); 2852246713Skib if (error && error!=EINPROGRESS) { 2853246713Skib hpt_printk(("bus_dmamap_load error %d\n", error)); 2854246713Skib FreeCommand(_VBUS_P pCmd); 2855246713Skib ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2856246713Skib dmamap_put(pmap); 2857246713Skib pAdapter->outstandingCommands--; 2858269617Sjhb if (pAdapter->outstandingCommands == 0) 2859269617Sjhb wakeup(pAdapter); 2860246713Skib xpt_done(ccb); 2861149871Sscottl } 2862149871Sscottl goto Command_Complished; 2863149871Sscottl } 2864149871Sscottl 2865149871Sscottl default: 2866149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2867149871Sscottl break; 2868136849Sscottl } 2869136849Sscottl ccb_done(ccb); 2870136849SscottlCommand_Complished: 2871136849Sscottl CheckPendingCall(_VBUS_P0); 2872136849Sscottl return; 2873136849Sscottl} 2874136849Sscottl 2875149871Sscottlstatic void HPTLIBAPI 2876136849SscottlfOsCommandDone(_VBUS_ARG PCommand pCmd) 2877136849Sscottl{ 2878149871Sscottl union ccb *ccb = pCmd->pOrgCommand; 2879149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2880149871Sscottl IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2881136849Sscottl 2882149871Sscottl KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result)); 2883269617Sjhb 2884269617Sjhb callout_stop(&pmap->timeout); 2885136849Sscottl 2886136849Sscottl switch(pCmd->Result) { 2887136849Sscottl case RETURN_SUCCESS: 2888136849Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 2889136849Sscottl break; 2890136849Sscottl case RETURN_BAD_DEVICE: 2891136849Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2892136849Sscottl break; 2893136849Sscottl case RETURN_DEVICE_BUSY: 2894136849Sscottl ccb->ccb_h.status = CAM_BUSY; 2895136849Sscottl break; 2896136849Sscottl case RETURN_INVALID_REQUEST: 2897136849Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2898136849Sscottl break; 2899136849Sscottl case RETURN_SELECTION_TIMEOUT: 2900136849Sscottl ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2901136849Sscottl break; 2902136849Sscottl case RETURN_RETRY: 2903136849Sscottl ccb->ccb_h.status = CAM_BUSY; 2904136849Sscottl break; 2905136849Sscottl default: 2906136849Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2907136849Sscottl break; 2908136849Sscottl } 2909136849Sscottl 2910149871Sscottl if (pCmd->cf_data_in) { 2911149871Sscottl bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD); 2912136849Sscottl } 2913240210Sdelphij else if (pCmd->cf_data_out) { 2914149871Sscottl bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE); 2915149871Sscottl } 2916149871Sscottl 2917149871Sscottl bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map); 2918136849Sscottl 2919136849Sscottl FreeCommand(_VBUS_P pCmd); 2920136849Sscottl ccb_done(ccb); 2921136849Sscottl} 2922136849Sscottl 2923136849Sscottlint 2924136849Sscottlhpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags) 2925136849Sscottl{ 2926136849Sscottl int p; 2927136849Sscottl 2928269617Sjhb mtx_lock(&DpcQueue_Lock); 2929136849Sscottl p = (DpcQueue_Last + 1) % MAX_DPC; 2930136849Sscottl if (p==DpcQueue_First) { 2931136849Sscottl KdPrint(("DPC Queue full!\n")); 2932269617Sjhb mtx_unlock(&DpcQueue_Lock); 2933136849Sscottl return -1; 2934136849Sscottl } 2935136849Sscottl 2936136849Sscottl DpcQueue[DpcQueue_Last].dpc = dpc; 2937136849Sscottl DpcQueue[DpcQueue_Last].pAdapter = pAdapter; 2938136849Sscottl DpcQueue[DpcQueue_Last].arg = arg; 2939136849Sscottl DpcQueue[DpcQueue_Last].flags = flags; 2940136849Sscottl DpcQueue_Last = p; 2941269617Sjhb mtx_unlock(&DpcQueue_Lock); 2942136849Sscottl 2943136849Sscottl return 0; 2944136849Sscottl} 2945136849Sscottl 2946136849Sscottl#ifdef _RAID5N_ 2947136849Sscottl/* 2948149871Sscottl * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices. 2949149871Sscottl * How about the memory for 5081 request/response array and PRD table? 2950136849Sscottl */ 2951136849Sscottlvoid 2952136849Sscottl*os_alloc_page(_VBUS_ARG0) 2953136849Sscottl{ 2954149871Sscottl return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 2955136849Sscottl} 2956149871Sscottl 2957136849Sscottlvoid 2958136849Sscottl*os_alloc_dma_page(_VBUS_ARG0) 2959136849Sscottl{ 2960149871Sscottl return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 2961136849Sscottl} 2962136849Sscottl 2963136849Sscottlvoid 2964149871Sscottlos_free_page(_VBUS_ARG void *p) 2965149871Sscottl{ 2966149871Sscottl contigfree(p, 0x1000, M_DEVBUF); 2967136849Sscottl} 2968136849Sscottl 2969136849Sscottlvoid 2970149871Sscottlos_free_dma_page(_VBUS_ARG void *p) 2971149871Sscottl{ 2972149871Sscottl contigfree(p, 0x1000, M_DEVBUF); 2973136849Sscottl} 2974136849Sscottl 2975136849Sscottlvoid 2976136849SscottlDoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes) 2977136849Sscottl{ 2978136849Sscottl UINT i; 2979149871Sscottl for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++; 2980136849Sscottl} 2981136849Sscottl 2982136849Sscottlvoid 2983136849SscottlDoXor2(ULONG *p0, ULONG *p2, UINT nBytes) 2984136849Sscottl{ 2985136849Sscottl UINT i; 2986149871Sscottl for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++; 2987136849Sscottl} 2988136849Sscottl#endif 2989