1*35878b55SSascha Wildner /* 2*35878b55SSascha Wildner * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 3*35878b55SSascha Wildner * All rights reserved. 4*35878b55SSascha Wildner * 5*35878b55SSascha Wildner * Redistribution and use in source and binary forms, with or without 6*35878b55SSascha Wildner * modification, are permitted provided that the following conditions 7*35878b55SSascha Wildner * are met: 8*35878b55SSascha Wildner * 1. Redistributions of source code must retain the above copyright 9*35878b55SSascha Wildner * notice, this list of conditions and the following disclaimer. 10*35878b55SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 11*35878b55SSascha Wildner * notice, this list of conditions and the following disclaimer in the 12*35878b55SSascha Wildner * documentation and/or other materials provided with the distribution. 13*35878b55SSascha Wildner * 14*35878b55SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*35878b55SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*35878b55SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*35878b55SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*35878b55SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*35878b55SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*35878b55SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*35878b55SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*35878b55SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*35878b55SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*35878b55SSascha Wildner * SUCH DAMAGE. 25*35878b55SSascha Wildner * 26*35878b55SSascha Wildner * $FreeBSD: src/sys/dev/hptmv/entry.c,v 1.23 2010/06/19 13:42:14 mav Exp $ 27*35878b55SSascha Wildner */ 28*35878b55SSascha Wildner 29*35878b55SSascha Wildner #include <sys/param.h> 30*35878b55SSascha Wildner #include <sys/systm.h> 31*35878b55SSascha Wildner #include <sys/kernel.h> 32*35878b55SSascha Wildner #include <sys/bus.h> 33*35878b55SSascha Wildner #include <sys/malloc.h> 34*35878b55SSascha Wildner #include <sys/resource.h> 35*35878b55SSascha Wildner #include <sys/time.h> 36*35878b55SSascha Wildner #include <sys/callout.h> 37*35878b55SSascha Wildner #include <sys/signalvar.h> 38*35878b55SSascha Wildner #include <sys/eventhandler.h> 39*35878b55SSascha Wildner #include <sys/proc.h> 40*35878b55SSascha Wildner #include <sys/kthread.h> 41*35878b55SSascha Wildner 42*35878b55SSascha Wildner #include <sys/lock.h> 43*35878b55SSascha Wildner #include <sys/module.h> 44*35878b55SSascha Wildner 45*35878b55SSascha Wildner #include <bus/pci/pcireg.h> 46*35878b55SSascha Wildner #include <bus/pci/pcivar.h> 47*35878b55SSascha Wildner 48*35878b55SSascha Wildner #ifndef __KERNEL__ 49*35878b55SSascha Wildner #define __KERNEL__ 50*35878b55SSascha Wildner #endif 51*35878b55SSascha Wildner 52*35878b55SSascha Wildner #include <dev/raid/hptmv/global.h> 53*35878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h> 54*35878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h> 55*35878b55SSascha Wildner #include <dev/raid/hptmv/access601.h> 56*35878b55SSascha Wildner 57*35878b55SSascha Wildner 58*35878b55SSascha Wildner #ifdef DEBUG 59*35878b55SSascha Wildner #ifdef DEBUG_LEVEL 60*35878b55SSascha Wildner int hpt_dbg_level = DEBUG_LEVEL; 61*35878b55SSascha Wildner #else 62*35878b55SSascha Wildner int hpt_dbg_level = 0; 63*35878b55SSascha Wildner #endif 64*35878b55SSascha Wildner #endif 65*35878b55SSascha Wildner 66*35878b55SSascha Wildner #define MV_ERROR kprintf 67*35878b55SSascha Wildner 68*35878b55SSascha Wildner /* 69*35878b55SSascha Wildner * CAM SIM entry points 70*35878b55SSascha Wildner */ 71*35878b55SSascha Wildner static int hpt_probe (device_t dev); 72*35878b55SSascha Wildner static void launch_worker_thread(void); 73*35878b55SSascha Wildner static int hpt_attach(device_t dev); 74*35878b55SSascha Wildner static int hpt_detach(device_t dev); 75*35878b55SSascha Wildner static int hpt_shutdown(device_t dev); 76*35878b55SSascha Wildner static void hpt_poll(struct cam_sim *sim); 77*35878b55SSascha Wildner static void hpt_intr(void *arg); 78*35878b55SSascha Wildner static void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); 79*35878b55SSascha Wildner static void hpt_action(struct cam_sim *sim, union ccb *ccb); 80*35878b55SSascha Wildner 81*35878b55SSascha Wildner static device_method_t driver_methods[] = { 82*35878b55SSascha Wildner /* Device interface */ 83*35878b55SSascha Wildner DEVMETHOD(device_probe, hpt_probe), 84*35878b55SSascha Wildner DEVMETHOD(device_attach, hpt_attach), 85*35878b55SSascha Wildner DEVMETHOD(device_detach, hpt_detach), 86*35878b55SSascha Wildner 87*35878b55SSascha Wildner DEVMETHOD(device_shutdown, hpt_shutdown), 88*35878b55SSascha Wildner { 0, 0 } 89*35878b55SSascha Wildner }; 90*35878b55SSascha Wildner 91*35878b55SSascha Wildner static driver_t hpt_pci_driver = { 92*35878b55SSascha Wildner __str(PROC_DIR_NAME), 93*35878b55SSascha Wildner driver_methods, 94*35878b55SSascha Wildner sizeof(IAL_ADAPTER_T) 95*35878b55SSascha Wildner }; 96*35878b55SSascha Wildner 97*35878b55SSascha Wildner static devclass_t hpt_devclass; 98*35878b55SSascha Wildner 99*35878b55SSascha Wildner #define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 100*35878b55SSascha Wildner __DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 101*35878b55SSascha Wildner 102*35878b55SSascha Wildner #define ccb_ccb_ptr spriv_ptr0 103*35878b55SSascha Wildner #define ccb_adapter ccb_h.spriv_ptr1 104*35878b55SSascha Wildner 105*35878b55SSascha Wildner static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); 106*35878b55SSascha Wildner static void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); 107*35878b55SSascha Wildner static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); 108*35878b55SSascha Wildner static void ccb_done(union ccb *ccb); 109*35878b55SSascha Wildner static void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); 110*35878b55SSascha Wildner static void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); 111*35878b55SSascha Wildner static void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter); 112*35878b55SSascha Wildner static void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 113*35878b55SSascha Wildner static void handleEdmaError(_VBUS_ARG PCommand pCmd); 114*35878b55SSascha Wildner static int hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 115*35878b55SSascha Wildner static int fResetActiveCommands(PVBus _vbus_p); 116*35878b55SSascha Wildner static void fRegisterVdevice(IAL_ADAPTER_T *pAdapter); 117*35878b55SSascha Wildner static int hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter); 118*35878b55SSascha Wildner static void hptmv_handle_event_disconnect(void *data); 119*35878b55SSascha Wildner static void hptmv_handle_event_connect(void *data); 120*35878b55SSascha Wildner static int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 121*35878b55SSascha Wildner static void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel); 122*35878b55SSascha Wildner static int hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel); 123*35878b55SSascha Wildner static int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, 124*35878b55SSascha Wildner int logical); 125*35878b55SSascha Wildner static MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 126*35878b55SSascha Wildner MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId, 127*35878b55SSascha Wildner MV_U16 responseFlags, MV_U32 timeStamp, 128*35878b55SSascha Wildner MV_STORAGE_DEVICE_REGISTERS *registerStruct); 129*35878b55SSascha Wildner static MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, 130*35878b55SSascha Wildner MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2); 131*35878b55SSascha Wildner 132*35878b55SSascha Wildner #define ccb_ccb_ptr spriv_ptr0 133*35878b55SSascha Wildner #define ccb_adapter ccb_h.spriv_ptr1 134*35878b55SSascha Wildner 135*35878b55SSascha Wildner IAL_ADAPTER_T *gIal_Adapter = 0; 136*35878b55SSascha Wildner IAL_ADAPTER_T *pCurAdapter = 0; 137*35878b55SSascha Wildner static MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; 138*35878b55SSascha Wildner 139*35878b55SSascha Wildner typedef struct st_HPT_DPC { 140*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 141*35878b55SSascha Wildner void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR); 142*35878b55SSascha Wildner void *arg; 143*35878b55SSascha Wildner UCHAR flags; 144*35878b55SSascha Wildner } ST_HPT_DPC; 145*35878b55SSascha Wildner 146*35878b55SSascha Wildner #define MAX_DPC 16 147*35878b55SSascha Wildner UCHAR DPC_Request_Nums = 0; 148*35878b55SSascha Wildner static ST_HPT_DPC DpcQueue[MAX_DPC]; 149*35878b55SSascha Wildner static int DpcQueue_First=0; 150*35878b55SSascha Wildner static int DpcQueue_Last = 0; 151*35878b55SSascha Wildner 152*35878b55SSascha Wildner char DRIVER_VERSION[] = "v1.16"; 153*35878b55SSascha Wildner 154*35878b55SSascha Wildner static struct lock driver_lock; 155*35878b55SSascha Wildner intrmask_t lock_driver() 156*35878b55SSascha Wildner { 157*35878b55SSascha Wildner 158*35878b55SSascha Wildner intrmask_t spl = 0; 159*35878b55SSascha Wildner lockmgr(&driver_lock, LK_EXCLUSIVE); 160*35878b55SSascha Wildner return spl; 161*35878b55SSascha Wildner } 162*35878b55SSascha Wildner void unlock_driver(intrmask_t spl) 163*35878b55SSascha Wildner { 164*35878b55SSascha Wildner lockmgr(&driver_lock, LK_RELEASE); 165*35878b55SSascha Wildner } 166*35878b55SSascha Wildner 167*35878b55SSascha Wildner /******************************************************************************* 168*35878b55SSascha Wildner * Name: hptmv_free_channel 169*35878b55SSascha Wildner * 170*35878b55SSascha Wildner * Description: free allocated queues for the given channel 171*35878b55SSascha Wildner * 172*35878b55SSascha Wildner * Parameters: pMvSataAdapter - pointer to the RR18xx controler this 173*35878b55SSascha Wildner * channel connected to. 174*35878b55SSascha Wildner * channelNum - channel number. 175*35878b55SSascha Wildner * 176*35878b55SSascha Wildner ******************************************************************************/ 177*35878b55SSascha Wildner static void 178*35878b55SSascha Wildner hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 179*35878b55SSascha Wildner { 180*35878b55SSascha Wildner HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM); 181*35878b55SSascha Wildner pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL; 182*35878b55SSascha Wildner } 183*35878b55SSascha Wildner 184*35878b55SSascha Wildner static void failDevice(PVDevice pVDev) 185*35878b55SSascha Wildner { 186*35878b55SSascha Wildner PVBus _vbus_p = pVDev->pVBus; 187*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 188*35878b55SSascha Wildner 189*35878b55SSascha Wildner pVDev->u.disk.df_on_line = 0; 190*35878b55SSascha Wildner pVDev->vf_online = 0; 191*35878b55SSascha Wildner if (pVDev->pfnDeviceFailed) 192*35878b55SSascha Wildner CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev); 193*35878b55SSascha Wildner 194*35878b55SSascha Wildner fNotifyGUI(ET_DEVICE_REMOVED, pVDev); 195*35878b55SSascha Wildner 196*35878b55SSascha Wildner #ifndef FOR_DEMO 197*35878b55SSascha Wildner if (pAdapter->ver_601==2 && !pAdapter->beeping) { 198*35878b55SSascha Wildner pAdapter->beeping = 1; 199*35878b55SSascha Wildner BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); 200*35878b55SSascha Wildner set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1); 201*35878b55SSascha Wildner } 202*35878b55SSascha Wildner #endif 203*35878b55SSascha Wildner } 204*35878b55SSascha Wildner 205*35878b55SSascha Wildner int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel); 206*35878b55SSascha Wildner 207*35878b55SSascha Wildner static void 208*35878b55SSascha Wildner handleEdmaError(_VBUS_ARG PCommand pCmd) 209*35878b55SSascha Wildner { 210*35878b55SSascha Wildner PDevice pDevice = &pCmd->pVDevice->u.disk; 211*35878b55SSascha Wildner MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter; 212*35878b55SSascha Wildner 213*35878b55SSascha Wildner if (!pDevice->df_on_line) { 214*35878b55SSascha Wildner KdPrint(("Device is offline")); 215*35878b55SSascha Wildner pCmd->Result = RETURN_BAD_DEVICE; 216*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 217*35878b55SSascha Wildner return; 218*35878b55SSascha Wildner } 219*35878b55SSascha Wildner 220*35878b55SSascha Wildner if (pCmd->RetryCount++>5) { 221*35878b55SSascha Wildner hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber)); 222*35878b55SSascha Wildner failed: 223*35878b55SSascha Wildner failDevice(pCmd->pVDevice); 224*35878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 225*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 226*35878b55SSascha Wildner return; 227*35878b55SSascha Wildner } 228*35878b55SSascha Wildner 229*35878b55SSascha Wildner /* reset the channel and retry the command */ 230*35878b55SSascha Wildner if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber)) 231*35878b55SSascha Wildner goto failed; 232*35878b55SSascha Wildner 233*35878b55SSascha Wildner fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice)); 234*35878b55SSascha Wildner 235*35878b55SSascha Wildner hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber)); 236*35878b55SSascha Wildner fDeviceSendCommand(_VBUS_P pCmd); 237*35878b55SSascha Wildner } 238*35878b55SSascha Wildner 239*35878b55SSascha Wildner /**************************************************************** 240*35878b55SSascha Wildner * Name: hptmv_init_channel 241*35878b55SSascha Wildner * 242*35878b55SSascha Wildner * Description: allocate request and response queues for the EDMA of the 243*35878b55SSascha Wildner * given channel and sets other fields. 244*35878b55SSascha Wildner * 245*35878b55SSascha Wildner * Parameters: 246*35878b55SSascha Wildner * pAdapter - pointer to the emulated adapter data structure 247*35878b55SSascha Wildner * channelNum - channel number. 248*35878b55SSascha Wildner * Return: 0 on success, otherwise on failure 249*35878b55SSascha Wildner ****************************************************************/ 250*35878b55SSascha Wildner static int 251*35878b55SSascha Wildner hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 252*35878b55SSascha Wildner { 253*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel; 254*35878b55SSascha Wildner dma_addr_t req_dma_addr; 255*35878b55SSascha Wildner dma_addr_t rsp_dma_addr; 256*35878b55SSascha Wildner 257*35878b55SSascha Wildner if (channelNum >= MV_SATA_CHANNELS_NUM) 258*35878b55SSascha Wildner { 259*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Bad channelNum=%d", 260*35878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum); 261*35878b55SSascha Wildner return -1; 262*35878b55SSascha Wildner } 263*35878b55SSascha Wildner 264*35878b55SSascha Wildner pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; 265*35878b55SSascha Wildner pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel; 266*35878b55SSascha Wildner pMvSataChannel->channelNumber = channelNum; 267*35878b55SSascha Wildner pMvSataChannel->lba48Address = MV_FALSE; 268*35878b55SSascha Wildner pMvSataChannel->maxReadTransfer = MV_FALSE; 269*35878b55SSascha Wildner 270*35878b55SSascha Wildner pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *) 271*35878b55SSascha Wildner (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); 272*35878b55SSascha Wildner req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); 273*35878b55SSascha Wildner 274*35878b55SSascha Wildner 275*35878b55SSascha Wildner KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr)); 276*35878b55SSascha Wildner 277*35878b55SSascha Wildner /* check the 1K alignment of the request queue*/ 278*35878b55SSascha Wildner if (req_dma_addr & 0x3ff) 279*35878b55SSascha Wildner { 280*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned," 281*35878b55SSascha Wildner " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId, 282*35878b55SSascha Wildner (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum); 283*35878b55SSascha Wildner return -1; 284*35878b55SSascha Wildner } 285*35878b55SSascha Wildner pMvSataChannel->requestQueuePciLowAddress = req_dma_addr; 286*35878b55SSascha Wildner pMvSataChannel->requestQueuePciHiAddress = 0; 287*35878b55SSascha Wildner KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p", 288*35878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum, 289*35878b55SSascha Wildner pMvSataChannel->requestQueue)); 290*35878b55SSascha Wildner pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) 291*35878b55SSascha Wildner (pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); 292*35878b55SSascha Wildner rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); 293*35878b55SSascha Wildner 294*35878b55SSascha Wildner /* check the 256 alignment of the response queue*/ 295*35878b55SSascha Wildner if (rsp_dma_addr & 0xff) 296*35878b55SSascha Wildner { 297*35878b55SSascha Wildner MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte " 298*35878b55SSascha Wildner "aligned, dma_addr=%llx\n", 299*35878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr); 300*35878b55SSascha Wildner return -1; 301*35878b55SSascha Wildner } 302*35878b55SSascha Wildner pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr; 303*35878b55SSascha Wildner pMvSataChannel->responseQueuePciHiAddress = 0; 304*35878b55SSascha Wildner KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p", 305*35878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum, 306*35878b55SSascha Wildner pMvSataChannel->responseQueue)); 307*35878b55SSascha Wildner 308*35878b55SSascha Wildner pAdapter->mvChannel[channelNum].online = MV_TRUE; 309*35878b55SSascha Wildner return 0; 310*35878b55SSascha Wildner } 311*35878b55SSascha Wildner 312*35878b55SSascha Wildner /****************************************************************************** 313*35878b55SSascha Wildner * Name: hptmv_parse_identify_results 314*35878b55SSascha Wildner * 315*35878b55SSascha Wildner * Description: this functions parses the identify command results, checks 316*35878b55SSascha Wildner * that the connected deives can be accesed by RR18xx EDMA, 317*35878b55SSascha Wildner * and updates the channel stucture accordingly. 318*35878b55SSascha Wildner * 319*35878b55SSascha Wildner * Parameters: pMvSataChannel, pointer to the channel data structure. 320*35878b55SSascha Wildner * 321*35878b55SSascha Wildner * Returns: =0 ->success, < 0 ->failure. 322*35878b55SSascha Wildner * 323*35878b55SSascha Wildner ******************************************************************************/ 324*35878b55SSascha Wildner static int 325*35878b55SSascha Wildner hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) 326*35878b55SSascha Wildner { 327*35878b55SSascha Wildner MV_U16 *iden = pMvSataChannel->identifyDevice; 328*35878b55SSascha Wildner 329*35878b55SSascha Wildner /*LBA addressing*/ 330*35878b55SSascha Wildner if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) 331*35878b55SSascha Wildner { 332*35878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n")); 333*35878b55SSascha Wildner return -1; 334*35878b55SSascha Wildner } 335*35878b55SSascha Wildner else 336*35878b55SSascha Wildner { 337*35878b55SSascha Wildner KdPrint(("%25s - %s\n", "Capabilities", "LBA supported")); 338*35878b55SSascha Wildner } 339*35878b55SSascha Wildner /*DMA support*/ 340*35878b55SSascha Wildner if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) 341*35878b55SSascha Wildner { 342*35878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n")); 343*35878b55SSascha Wildner return -1; 344*35878b55SSascha Wildner } 345*35878b55SSascha Wildner else 346*35878b55SSascha Wildner { 347*35878b55SSascha Wildner KdPrint(("%25s - %s\n", "Capabilities", "DMA supported")); 348*35878b55SSascha Wildner } 349*35878b55SSascha Wildner /* PIO */ 350*35878b55SSascha Wildner if ((iden[IDEN_VALID] & 2) == 0) 351*35878b55SSascha Wildner { 352*35878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n")); 353*35878b55SSascha Wildner return -1; 354*35878b55SSascha Wildner } 355*35878b55SSascha Wildner KdPrint(("%25s - 0x%02x\n", "PIO modes supported", 356*35878b55SSascha Wildner iden[IDEN_PIO_MODE_SPPORTED] & 0xff)); 357*35878b55SSascha Wildner 358*35878b55SSascha Wildner /*UDMA*/ 359*35878b55SSascha Wildner if ((iden[IDEN_VALID] & 4) == 0) 360*35878b55SSascha Wildner { 361*35878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n")); 362*35878b55SSascha Wildner return -1; 363*35878b55SSascha Wildner } 364*35878b55SSascha Wildner 365*35878b55SSascha Wildner /* 48 bit address */ 366*35878b55SSascha Wildner if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) 367*35878b55SSascha Wildner { 368*35878b55SSascha Wildner KdPrint(("%25s - %s\n", "LBA48 addressing", "supported")); 369*35878b55SSascha Wildner pMvSataChannel->lba48Address = MV_TRUE; 370*35878b55SSascha Wildner } 371*35878b55SSascha Wildner else 372*35878b55SSascha Wildner { 373*35878b55SSascha Wildner KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported")); 374*35878b55SSascha Wildner pMvSataChannel->lba48Address = MV_FALSE; 375*35878b55SSascha Wildner } 376*35878b55SSascha Wildner return 0; 377*35878b55SSascha Wildner } 378*35878b55SSascha Wildner 379*35878b55SSascha Wildner static void 380*35878b55SSascha Wildner init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) 381*35878b55SSascha Wildner { 382*35878b55SSascha Wildner PVDevice pVDev = &pAdapter->VDevices[channel]; 383*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; 384*35878b55SSascha Wildner MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice; 385*35878b55SSascha Wildner 386*35878b55SSascha Wildner pMvSataChannel->outstandingCommands = 0; 387*35878b55SSascha Wildner 388*35878b55SSascha Wildner pVDev->u.disk.mv = pMvSataChannel; 389*35878b55SSascha Wildner pVDev->u.disk.df_on_line = 1; 390*35878b55SSascha Wildner pVDev->u.disk.pVBus = &pAdapter->VBus; 391*35878b55SSascha Wildner pVDev->pVBus = &pAdapter->VBus; 392*35878b55SSascha Wildner 393*35878b55SSascha Wildner #ifdef SUPPORT_48BIT_LBA 394*35878b55SSascha Wildner if (pMvSataChannel->lba48Address == MV_TRUE) 395*35878b55SSascha Wildner pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; 396*35878b55SSascha Wildner else 397*35878b55SSascha Wildner #endif 398*35878b55SSascha Wildner if(IdentifyData[53] & 1) { 399*35878b55SSascha Wildner pVDev->u.disk.dDeRealCapacity = 400*35878b55SSascha Wildner (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ? 401*35878b55SSascha Wildner (IdentifyData[61]<<16 | IdentifyData[60]) : 402*35878b55SSascha Wildner (IdentifyData[58]<<16 | IdentifyData[57])) - 1; 403*35878b55SSascha Wildner } else 404*35878b55SSascha Wildner pVDev->u.disk.dDeRealCapacity = 405*35878b55SSascha Wildner (IdentifyData[61]<<16 | IdentifyData[60]) - 1; 406*35878b55SSascha Wildner 407*35878b55SSascha Wildner pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 408*35878b55SSascha Wildner pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0; 409*35878b55SSascha Wildner 410*35878b55SSascha Wildner if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) { 411*35878b55SSascha Wildner pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 412*35878b55SSascha Wildner pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8; 413*35878b55SSascha Wildner } 414*35878b55SSascha Wildner } 415*35878b55SSascha Wildner 416*35878b55SSascha Wildner static void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) 417*35878b55SSascha Wildner { 418*35878b55SSascha Wildner PVDevice pVDev; 419*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 420*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; 421*35878b55SSascha Wildner 422*35878b55SSascha Wildner if (!pMvSataChannel) return; 423*35878b55SSascha Wildner 424*35878b55SSascha Wildner if (plugged) 425*35878b55SSascha Wildner { 426*35878b55SSascha Wildner pVDev = &(pAdapter->VDevices[channelIndex]); 427*35878b55SSascha Wildner init_vdev_params(pAdapter, channelIndex); 428*35878b55SSascha Wildner 429*35878b55SSascha Wildner pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI : 430*35878b55SSascha Wildner pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 431*35878b55SSascha Wildner 432*35878b55SSascha Wildner pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO; 433*35878b55SSascha Wildner pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 434*35878b55SSascha Wildner pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 435*35878b55SSascha Wildner pVDev->vf_online = 1; 436*35878b55SSascha Wildner 437*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 438*35878b55SSascha Wildner if(pVDev->pParent) 439*35878b55SSascha Wildner { 440*35878b55SSascha Wildner int iMember; 441*35878b55SSascha Wildner for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++) 442*35878b55SSascha Wildner if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) 443*35878b55SSascha Wildner pVDev->pParent->u.array.pMember[iMember] = NULL; 444*35878b55SSascha Wildner pVDev->pParent = NULL; 445*35878b55SSascha Wildner } 446*35878b55SSascha Wildner #endif 447*35878b55SSascha Wildner fNotifyGUI(ET_DEVICE_PLUGGED,pVDev); 448*35878b55SSascha Wildner fCheckBootable(pVDev); 449*35878b55SSascha Wildner RegisterVDevice(pVDev); 450*35878b55SSascha Wildner 451*35878b55SSascha Wildner #ifndef FOR_DEMO 452*35878b55SSascha Wildner if (pAdapter->beeping) { 453*35878b55SSascha Wildner pAdapter->beeping = 0; 454*35878b55SSascha Wildner BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 455*35878b55SSascha Wildner } 456*35878b55SSascha Wildner #endif 457*35878b55SSascha Wildner 458*35878b55SSascha Wildner } 459*35878b55SSascha Wildner else 460*35878b55SSascha Wildner { 461*35878b55SSascha Wildner pVDev = &(pAdapter->VDevices[channelIndex]); 462*35878b55SSascha Wildner failDevice(pVDev); 463*35878b55SSascha Wildner } 464*35878b55SSascha Wildner } 465*35878b55SSascha Wildner 466*35878b55SSascha Wildner static int 467*35878b55SSascha Wildner start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 468*35878b55SSascha Wildner { 469*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 470*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; 471*35878b55SSascha Wildner MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]); 472*35878b55SSascha Wildner MV_U32 udmaMode,pioMode; 473*35878b55SSascha Wildner 474*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId, 475*35878b55SSascha Wildner channelNum)); 476*35878b55SSascha Wildner 477*35878b55SSascha Wildner 478*35878b55SSascha Wildner /* Software reset channel */ 479*35878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 480*35878b55SSascha Wildner { 481*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 482*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 483*35878b55SSascha Wildner return -1; 484*35878b55SSascha Wildner } 485*35878b55SSascha Wildner 486*35878b55SSascha Wildner /* Hardware reset channel */ 487*35878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 488*35878b55SSascha Wildner { 489*35878b55SSascha Wildner /* If failed, try again - this is when trying to hardreset a channel */ 490*35878b55SSascha Wildner /* when drive is just spinning up */ 491*35878b55SSascha Wildner StallExec(5000000); /* wait 5 sec before trying again */ 492*35878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 493*35878b55SSascha Wildner { 494*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n", 495*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 496*35878b55SSascha Wildner return -1; 497*35878b55SSascha Wildner } 498*35878b55SSascha Wildner } 499*35878b55SSascha Wildner 500*35878b55SSascha Wildner /* identify device*/ 501*35878b55SSascha Wildner if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE) 502*35878b55SSascha Wildner { 503*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n" 504*35878b55SSascha Wildner , pMvSataAdapter->adapterId, channelNum); 505*35878b55SSascha Wildner return -1; 506*35878b55SSascha Wildner } 507*35878b55SSascha Wildner if (hptmv_parse_identify_results(pMvSataChannel)) 508*35878b55SSascha Wildner { 509*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n" 510*35878b55SSascha Wildner , pMvSataAdapter->adapterId, channelNum); 511*35878b55SSascha Wildner return -1; 512*35878b55SSascha Wildner } 513*35878b55SSascha Wildner 514*35878b55SSascha Wildner /* mvStorageDevATASetFeatures */ 515*35878b55SSascha Wildner /* Disable 8 bit PIO in case CFA enabled */ 516*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[86] & 4) 517*35878b55SSascha Wildner { 518*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n", 519*35878b55SSascha Wildner pMvSataAdapter->adapterId)); 520*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 521*35878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, 522*35878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 523*35878b55SSascha Wildner { 524*35878b55SSascha Wildner MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures" 525*35878b55SSascha Wildner " failed\n", pMvSataAdapter->adapterId, channelNum); 526*35878b55SSascha Wildner return -1; 527*35878b55SSascha Wildner } 528*35878b55SSascha Wildner } 529*35878b55SSascha Wildner /* Write cache */ 530*35878b55SSascha Wildner #ifdef ENABLE_WRITE_CACHE 531*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[82] & 0x20) 532*35878b55SSascha Wildner { 533*35878b55SSascha Wildner if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */ 534*35878b55SSascha Wildner { 535*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 536*35878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 537*35878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 538*35878b55SSascha Wildner { 539*35878b55SSascha Wildner MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 540*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 541*35878b55SSascha Wildner return -1; 542*35878b55SSascha Wildner } 543*35878b55SSascha Wildner } 544*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n", 545*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 546*35878b55SSascha Wildner } 547*35878b55SSascha Wildner else 548*35878b55SSascha Wildner { 549*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n", 550*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 551*35878b55SSascha Wildner } 552*35878b55SSascha Wildner #else /* disable write cache */ 553*35878b55SSascha Wildner { 554*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[85] & 0x20) 555*35878b55SSascha Wildner { 556*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n", 557*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 558*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 559*35878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 560*35878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 561*35878b55SSascha Wildner { 562*35878b55SSascha Wildner MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 563*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 564*35878b55SSascha Wildner return -1; 565*35878b55SSascha Wildner } 566*35878b55SSascha Wildner } 567*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n", 568*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 569*35878b55SSascha Wildner } 570*35878b55SSascha Wildner #endif 571*35878b55SSascha Wildner 572*35878b55SSascha Wildner /* Set transfer mode */ 573*35878b55SSascha Wildner KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n", 574*35878b55SSascha Wildner pMvSataAdapter->adapterId)); 575*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 576*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 577*35878b55SSascha Wildner MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == 578*35878b55SSascha Wildner MV_FALSE) 579*35878b55SSascha Wildner { 580*35878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 581*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 582*35878b55SSascha Wildner return -1; 583*35878b55SSascha Wildner } 584*35878b55SSascha Wildner 585*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) 586*35878b55SSascha Wildner { 587*35878b55SSascha Wildner pioMode = MV_ATA_TRANSFER_PIO_4; 588*35878b55SSascha Wildner } 589*35878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) 590*35878b55SSascha Wildner { 591*35878b55SSascha Wildner pioMode = MV_ATA_TRANSFER_PIO_3; 592*35878b55SSascha Wildner } 593*35878b55SSascha Wildner else 594*35878b55SSascha Wildner { 595*35878b55SSascha Wildner MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n"); 596*35878b55SSascha Wildner pioMode = MV_ATA_TRANSFER_PIO_SLOW; 597*35878b55SSascha Wildner } 598*35878b55SSascha Wildner 599*35878b55SSascha Wildner KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n", 600*35878b55SSascha Wildner pMvSataAdapter->adapterId)); 601*35878b55SSascha Wildner pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode; 602*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 603*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 604*35878b55SSascha Wildner pioMode, 0, 0, 0) == MV_FALSE) 605*35878b55SSascha Wildner { 606*35878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 607*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 608*35878b55SSascha Wildner return -1; 609*35878b55SSascha Wildner } 610*35878b55SSascha Wildner 611*35878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_0; 612*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) 613*35878b55SSascha Wildner { 614*35878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_6; 615*35878b55SSascha Wildner } 616*35878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) 617*35878b55SSascha Wildner { 618*35878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_5; 619*35878b55SSascha Wildner } 620*35878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) 621*35878b55SSascha Wildner { 622*35878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_4; 623*35878b55SSascha Wildner } 624*35878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) 625*35878b55SSascha Wildner { 626*35878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_3; 627*35878b55SSascha Wildner } 628*35878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) 629*35878b55SSascha Wildner { 630*35878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_2; 631*35878b55SSascha Wildner } 632*35878b55SSascha Wildner 633*35878b55SSascha Wildner KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n", 634*35878b55SSascha Wildner pMvSataAdapter->adapterId, udmaMode & 0xf)); 635*35878b55SSascha Wildner pChannelInfo->maxUltraDmaModeSupported = udmaMode; 636*35878b55SSascha Wildner 637*35878b55SSascha Wildner /*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 638*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, udmaMode, 639*35878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 640*35878b55SSascha Wildner { 641*35878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 642*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 643*35878b55SSascha Wildner return -1; 644*35878b55SSascha Wildner }*/ 645*35878b55SSascha Wildner if (pChannelInfo->maxUltraDmaModeSupported == 0xFF) 646*35878b55SSascha Wildner return TRUE; 647*35878b55SSascha Wildner else 648*35878b55SSascha Wildner do 649*35878b55SSascha Wildner { 650*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 651*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 652*35878b55SSascha Wildner pChannelInfo->maxUltraDmaModeSupported, 653*35878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 654*35878b55SSascha Wildner { 655*35878b55SSascha Wildner if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0) 656*35878b55SSascha Wildner { 657*35878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 658*35878b55SSascha Wildner { 659*35878b55SSascha Wildner MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress, 660*35878b55SSascha Wildner pMvSataChannel->eDmaRegsOffset + 661*35878b55SSascha Wildner 0x11c, /* command reg */ 662*35878b55SSascha Wildner MV_ATA_COMMAND_IDLE_IMMEDIATE); 663*35878b55SSascha Wildner mvMicroSecondsDelay(10000); 664*35878b55SSascha Wildner mvSataChannelHardReset(pMvSataAdapter, channelNum); 665*35878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 666*35878b55SSascha Wildner return FALSE; 667*35878b55SSascha Wildner } 668*35878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 669*35878b55SSascha Wildner return FALSE; 670*35878b55SSascha Wildner pChannelInfo->maxUltraDmaModeSupported--; 671*35878b55SSascha Wildner continue; 672*35878b55SSascha Wildner } 673*35878b55SSascha Wildner else return FALSE; 674*35878b55SSascha Wildner } 675*35878b55SSascha Wildner break; 676*35878b55SSascha Wildner }while (1); 677*35878b55SSascha Wildner 678*35878b55SSascha Wildner /* Read look ahead */ 679*35878b55SSascha Wildner #ifdef ENABLE_READ_AHEAD 680*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[82] & 0x40) 681*35878b55SSascha Wildner { 682*35878b55SSascha Wildner if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */ 683*35878b55SSascha Wildner { 684*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 685*35878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 686*35878b55SSascha Wildner 0, 0) == MV_FALSE) 687*35878b55SSascha Wildner { 688*35878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 689*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 690*35878b55SSascha Wildner return -1; 691*35878b55SSascha Wildner } 692*35878b55SSascha Wildner } 693*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n", 694*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 695*35878b55SSascha Wildner } 696*35878b55SSascha Wildner else 697*35878b55SSascha Wildner { 698*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n", 699*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 700*35878b55SSascha Wildner } 701*35878b55SSascha Wildner #else 702*35878b55SSascha Wildner { 703*35878b55SSascha Wildner if (pMvSataChannel->identifyDevice[86] & 0x20) 704*35878b55SSascha Wildner { 705*35878b55SSascha Wildner KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n", 706*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 707*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 708*35878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 709*35878b55SSascha Wildner 0, 0) == MV_FALSE) 710*35878b55SSascha Wildner { 711*35878b55SSascha Wildner MV_ERROR("RR18xx [%d]:channel %d: ATA Set Features failed\n", 712*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 713*35878b55SSascha Wildner return -1; 714*35878b55SSascha Wildner } 715*35878b55SSascha Wildner } 716*35878b55SSascha Wildner KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n", 717*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 718*35878b55SSascha Wildner } 719*35878b55SSascha Wildner #endif 720*35878b55SSascha Wildner 721*35878b55SSascha Wildner 722*35878b55SSascha Wildner { 723*35878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n", 724*35878b55SSascha Wildner pMvSataAdapter->adapterId, 725*35878b55SSascha Wildner channelNum)); 726*35878b55SSascha Wildner if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, 727*35878b55SSascha Wildner MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) 728*35878b55SSascha Wildner { 729*35878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n", 730*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 731*35878b55SSascha Wildner return -1; 732*35878b55SSascha Wildner } 733*35878b55SSascha Wildner } 734*35878b55SSascha Wildner /* Enable EDMA */ 735*35878b55SSascha Wildner if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) 736*35878b55SSascha Wildner { 737*35878b55SSascha Wildner MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n", 738*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 739*35878b55SSascha Wildner return -1; 740*35878b55SSascha Wildner } 741*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: channel started successfully\n", 742*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 743*35878b55SSascha Wildner 744*35878b55SSascha Wildner #ifndef FOR_DEMO 745*35878b55SSascha Wildner set_fail_led(pMvSataAdapter, channelNum, 0); 746*35878b55SSascha Wildner #endif 747*35878b55SSascha Wildner return 0; 748*35878b55SSascha Wildner } 749*35878b55SSascha Wildner 750*35878b55SSascha Wildner static void 751*35878b55SSascha Wildner hptmv_handle_event(void * data, int flag) 752*35878b55SSascha Wildner { 753*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)data; 754*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 755*35878b55SSascha Wildner MV_U8 channelIndex; 756*35878b55SSascha Wildner 757*35878b55SSascha Wildner /* mvOsSemTake(&pMvSataAdapter->semaphore); */ 758*35878b55SSascha Wildner for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++) 759*35878b55SSascha Wildner { 760*35878b55SSascha Wildner switch(pAdapter->sataEvents[channelIndex]) 761*35878b55SSascha Wildner { 762*35878b55SSascha Wildner case SATA_EVENT_CHANNEL_CONNECTED: 763*35878b55SSascha Wildner /* Handle only connects */ 764*35878b55SSascha Wildner if (flag == 1) 765*35878b55SSascha Wildner break; 766*35878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: new device connected\n", 767*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 768*35878b55SSascha Wildner hptmv_init_channel(pAdapter, channelIndex); 769*35878b55SSascha Wildner if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE) 770*35878b55SSascha Wildner { 771*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d] Failed to configure\n", 772*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex); 773*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channelIndex); 774*35878b55SSascha Wildner } 775*35878b55SSascha Wildner else 776*35878b55SSascha Wildner { 777*35878b55SSascha Wildner /*mvSataChannelHardReset(pMvSataAdapter, channel);*/ 778*35878b55SSascha Wildner if (start_channel( pAdapter, channelIndex)) 779*35878b55SSascha Wildner { 780*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]Failed to start channel\n", 781*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex); 782*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channelIndex); 783*35878b55SSascha Wildner } 784*35878b55SSascha Wildner else 785*35878b55SSascha Wildner { 786*35878b55SSascha Wildner device_change(pAdapter, channelIndex, TRUE); 787*35878b55SSascha Wildner } 788*35878b55SSascha Wildner } 789*35878b55SSascha Wildner pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 790*35878b55SSascha Wildner break; 791*35878b55SSascha Wildner 792*35878b55SSascha Wildner case SATA_EVENT_CHANNEL_DISCONNECTED: 793*35878b55SSascha Wildner /* Handle only disconnects */ 794*35878b55SSascha Wildner if (flag == 0) 795*35878b55SSascha Wildner break; 796*35878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: device disconnected\n", 797*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 798*35878b55SSascha Wildner /* Flush pending commands */ 799*35878b55SSascha Wildner if(pMvSataAdapter->sataChannel[channelIndex]) 800*35878b55SSascha Wildner { 801*35878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 802*35878b55SSascha Wildner mvSataFlushDmaQueue (pMvSataAdapter, channelIndex, 803*35878b55SSascha Wildner MV_FLUSH_TYPE_CALLBACK); 804*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 805*35878b55SSascha Wildner mvSataRemoveChannel(pMvSataAdapter,channelIndex); 806*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channelIndex); 807*35878b55SSascha Wildner pMvSataAdapter->sataChannel[channelIndex] = NULL; 808*35878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: channel removed\n", 809*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 810*35878b55SSascha Wildner if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 811*35878b55SSascha Wildner Check_Idle_Call(pAdapter); 812*35878b55SSascha Wildner } 813*35878b55SSascha Wildner else 814*35878b55SSascha Wildner { 815*35878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: channel already removed!!\n", 816*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 817*35878b55SSascha Wildner } 818*35878b55SSascha Wildner pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 819*35878b55SSascha Wildner break; 820*35878b55SSascha Wildner 821*35878b55SSascha Wildner case SATA_EVENT_NO_CHANGE: 822*35878b55SSascha Wildner break; 823*35878b55SSascha Wildner 824*35878b55SSascha Wildner default: 825*35878b55SSascha Wildner break; 826*35878b55SSascha Wildner } 827*35878b55SSascha Wildner } 828*35878b55SSascha Wildner /* mvOsSemRelease(&pMvSataAdapter->semaphore); */ 829*35878b55SSascha Wildner } 830*35878b55SSascha Wildner 831*35878b55SSascha Wildner #define EVENT_CONNECT 1 832*35878b55SSascha Wildner #define EVENT_DISCONNECT 0 833*35878b55SSascha Wildner 834*35878b55SSascha Wildner static void 835*35878b55SSascha Wildner hptmv_handle_event_connect(void *data) 836*35878b55SSascha Wildner { 837*35878b55SSascha Wildner hptmv_handle_event (data, 0); 838*35878b55SSascha Wildner } 839*35878b55SSascha Wildner 840*35878b55SSascha Wildner static void 841*35878b55SSascha Wildner hptmv_handle_event_disconnect(void *data) 842*35878b55SSascha Wildner { 843*35878b55SSascha Wildner hptmv_handle_event (data, 1); 844*35878b55SSascha Wildner } 845*35878b55SSascha Wildner 846*35878b55SSascha Wildner static MV_BOOLEAN 847*35878b55SSascha Wildner hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType, 848*35878b55SSascha Wildner MV_U32 param1, MV_U32 param2) 849*35878b55SSascha Wildner { 850*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; 851*35878b55SSascha Wildner 852*35878b55SSascha Wildner switch (eventType) 853*35878b55SSascha Wildner { 854*35878b55SSascha Wildner case MV_EVENT_TYPE_SATA_CABLE: 855*35878b55SSascha Wildner { 856*35878b55SSascha Wildner MV_U8 channel = param2; 857*35878b55SSascha Wildner 858*35878b55SSascha Wildner if (param1 == EVENT_CONNECT) 859*35878b55SSascha Wildner { 860*35878b55SSascha Wildner pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED; 861*35878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: device connected event received\n", 862*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel)); 863*35878b55SSascha Wildner /* Delete previous timers (if multiple drives connected in the same time */ 864*35878b55SSascha Wildner callout_reset(&pAdapter->event_timer_connect, 10*hz, hptmv_handle_event_connect, pAdapter); 865*35878b55SSascha Wildner } 866*35878b55SSascha Wildner else if (param1 == EVENT_DISCONNECT) 867*35878b55SSascha Wildner { 868*35878b55SSascha Wildner pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED; 869*35878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: device disconnected event received \n", 870*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel)); 871*35878b55SSascha Wildner device_change(pAdapter, channel, FALSE); 872*35878b55SSascha Wildner /* Delete previous timers (if multiple drives disconnected in the same time */ 873*35878b55SSascha Wildner /* callout_reset(&pAdapter->event_timer_disconnect, 10*hz, hptmv_handle_event_disconnect, pAdapter); */ 874*35878b55SSascha Wildner /*It is not necessary to wait, handle it directly*/ 875*35878b55SSascha Wildner hptmv_handle_event_disconnect(pAdapter); 876*35878b55SSascha Wildner } 877*35878b55SSascha Wildner else 878*35878b55SSascha Wildner { 879*35878b55SSascha Wildner 880*35878b55SSascha Wildner MV_ERROR("RR18xx: illigal value for param1(%d) at " 881*35878b55SSascha Wildner "connect/disconect event, host=%d\n", param1, 882*35878b55SSascha Wildner pMvSataAdapter->adapterId ); 883*35878b55SSascha Wildner 884*35878b55SSascha Wildner } 885*35878b55SSascha Wildner } 886*35878b55SSascha Wildner break; 887*35878b55SSascha Wildner case MV_EVENT_TYPE_ADAPTER_ERROR: 888*35878b55SSascha Wildner KdPrint(("RR18xx: DEVICE error event received, pci cause " 889*35878b55SSascha Wildner "reg=%x, don't how to handle this\n", param1)); 890*35878b55SSascha Wildner return MV_TRUE; 891*35878b55SSascha Wildner default: 892*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: unknown event type (%d)\n", 893*35878b55SSascha Wildner pMvSataAdapter->adapterId, eventType); 894*35878b55SSascha Wildner return MV_FALSE; 895*35878b55SSascha Wildner } 896*35878b55SSascha Wildner return MV_TRUE; 897*35878b55SSascha Wildner } 898*35878b55SSascha Wildner 899*35878b55SSascha Wildner static int 900*35878b55SSascha Wildner hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) 901*35878b55SSascha Wildner { 902*35878b55SSascha Wildner pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE, 903*35878b55SSascha Wildner M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 904*35878b55SSascha Wildner if (pAdapter->requestsArrayBaseAddr == NULL) 905*35878b55SSascha Wildner { 906*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request" 907*35878b55SSascha Wildner " queues\n", pAdapter->mvSataAdapter.adapterId); 908*35878b55SSascha Wildner return -1; 909*35878b55SSascha Wildner } 910*35878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr); 911*35878b55SSascha Wildner pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr; 912*35878b55SSascha Wildner pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 913*35878b55SSascha Wildner pAdapter->requestsArrayBaseAlignedAddr = (MV_U8 *) 914*35878b55SSascha Wildner (((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); 915*35878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr; 916*35878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 917*35878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); 918*35878b55SSascha Wildner 919*35878b55SSascha Wildner if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) != 920*35878b55SSascha Wildner (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr)) 921*35878b55SSascha Wildner { 922*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n", 923*35878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId); 924*35878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 925*35878b55SSascha Wildner return -1; 926*35878b55SSascha Wildner } 927*35878b55SSascha Wildner /* response queues */ 928*35878b55SSascha Wildner pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE, 929*35878b55SSascha Wildner M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 930*35878b55SSascha Wildner if (pAdapter->responsesArrayBaseAddr == NULL) 931*35878b55SSascha Wildner { 932*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response" 933*35878b55SSascha Wildner " queues\n", pAdapter->mvSataAdapter.adapterId); 934*35878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 935*35878b55SSascha Wildner return -1; 936*35878b55SSascha Wildner } 937*35878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr); 938*35878b55SSascha Wildner pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr; 939*35878b55SSascha Wildner pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 940*35878b55SSascha Wildner pAdapter->responsesArrayBaseAlignedAddr = (MV_U8 *) 941*35878b55SSascha Wildner (((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); 942*35878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr; 943*35878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 944*35878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); 945*35878b55SSascha Wildner 946*35878b55SSascha Wildner if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) != 947*35878b55SSascha Wildner (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr)) 948*35878b55SSascha Wildner { 949*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Error in Response Quueues Alignment\n", 950*35878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId); 951*35878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 952*35878b55SSascha Wildner contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 953*35878b55SSascha Wildner return -1; 954*35878b55SSascha Wildner } 955*35878b55SSascha Wildner return 0; 956*35878b55SSascha Wildner } 957*35878b55SSascha Wildner 958*35878b55SSascha Wildner static void 959*35878b55SSascha Wildner hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter) 960*35878b55SSascha Wildner { 961*35878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 962*35878b55SSascha Wildner contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 963*35878b55SSascha Wildner } 964*35878b55SSascha Wildner 965*35878b55SSascha Wildner static PVOID 966*35878b55SSascha Wildner AllocatePRDTable(IAL_ADAPTER_T *pAdapter) 967*35878b55SSascha Wildner { 968*35878b55SSascha Wildner PVOID ret; 969*35878b55SSascha Wildner if (pAdapter->pFreePRDLink) { 970*35878b55SSascha Wildner KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink)); 971*35878b55SSascha Wildner ret = pAdapter->pFreePRDLink; 972*35878b55SSascha Wildner pAdapter->pFreePRDLink = *(void**)ret; 973*35878b55SSascha Wildner return ret; 974*35878b55SSascha Wildner } 975*35878b55SSascha Wildner return NULL; 976*35878b55SSascha Wildner } 977*35878b55SSascha Wildner 978*35878b55SSascha Wildner static void 979*35878b55SSascha Wildner FreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable) 980*35878b55SSascha Wildner { 981*35878b55SSascha Wildner *(void**)PRDTable = pAdapter->pFreePRDLink; 982*35878b55SSascha Wildner pAdapter->pFreePRDLink = PRDTable; 983*35878b55SSascha Wildner } 984*35878b55SSascha Wildner 985*35878b55SSascha Wildner extern PVDevice fGetFirstChild(PVDevice pLogical); 986*35878b55SSascha Wildner extern void fResetBootMark(PVDevice pLogical); 987*35878b55SSascha Wildner static void 988*35878b55SSascha Wildner fRegisterVdevice(IAL_ADAPTER_T *pAdapter) 989*35878b55SSascha Wildner { 990*35878b55SSascha Wildner PVDevice pPhysical, pLogical; 991*35878b55SSascha Wildner PVBus pVBus; 992*35878b55SSascha Wildner int i,j; 993*35878b55SSascha Wildner 994*35878b55SSascha Wildner for(i=0;i<MV_SATA_CHANNELS_NUM;i++) { 995*35878b55SSascha Wildner pPhysical = &(pAdapter->VDevices[i]); 996*35878b55SSascha Wildner pLogical = pPhysical; 997*35878b55SSascha Wildner while (pLogical->pParent) pLogical = pLogical->pParent; 998*35878b55SSascha Wildner if (pLogical->vf_online==0) { 999*35878b55SSascha Wildner pPhysical->vf_bootmark = pLogical->vf_bootmark = 0; 1000*35878b55SSascha Wildner continue; 1001*35878b55SSascha Wildner } 1002*35878b55SSascha Wildner if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical)) 1003*35878b55SSascha Wildner continue; 1004*35878b55SSascha Wildner 1005*35878b55SSascha Wildner pVBus = &pAdapter->VBus; 1006*35878b55SSascha Wildner if(pVBus) 1007*35878b55SSascha Wildner { 1008*35878b55SSascha Wildner j=0; 1009*35878b55SSascha Wildner while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++; 1010*35878b55SSascha Wildner if(j<MAX_VDEVICE_PER_VBUS){ 1011*35878b55SSascha Wildner pVBus->pVDevice[j] = pLogical; 1012*35878b55SSascha Wildner pLogical->pVBus = pVBus; 1013*35878b55SSascha Wildner 1014*35878b55SSascha Wildner if (j>0 && pLogical->vf_bootmark) { 1015*35878b55SSascha Wildner if (pVBus->pVDevice[0]->vf_bootmark) { 1016*35878b55SSascha Wildner fResetBootMark(pLogical); 1017*35878b55SSascha Wildner } 1018*35878b55SSascha Wildner else { 1019*35878b55SSascha Wildner do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j); 1020*35878b55SSascha Wildner pVBus->pVDevice[0] = pLogical; 1021*35878b55SSascha Wildner } 1022*35878b55SSascha Wildner } 1023*35878b55SSascha Wildner } 1024*35878b55SSascha Wildner } 1025*35878b55SSascha Wildner } 1026*35878b55SSascha Wildner } 1027*35878b55SSascha Wildner 1028*35878b55SSascha Wildner PVDevice 1029*35878b55SSascha Wildner GetSpareDisk(_VBUS_ARG PVDevice pArray) 1030*35878b55SSascha Wildner { 1031*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; 1032*35878b55SSascha Wildner LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); 1033*35878b55SSascha Wildner LBA_T thiscap, maxcap = MAX_LBA_T; 1034*35878b55SSascha Wildner PVDevice pVDevice, pFind = NULL; 1035*35878b55SSascha Wildner int i; 1036*35878b55SSascha Wildner 1037*35878b55SSascha Wildner for(i=0;i<MV_SATA_CHANNELS_NUM;i++) 1038*35878b55SSascha Wildner { 1039*35878b55SSascha Wildner pVDevice = &pAdapter->VDevices[i]; 1040*35878b55SSascha Wildner if(!pVDevice) 1041*35878b55SSascha Wildner continue; 1042*35878b55SSascha Wildner thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; 1043*35878b55SSascha Wildner /* find the smallest usable spare disk */ 1044*35878b55SSascha Wildner if (pVDevice->VDeviceType==VD_SPARE && 1045*35878b55SSascha Wildner pVDevice->u.disk.df_on_line && 1046*35878b55SSascha Wildner thiscap < maxcap && 1047*35878b55SSascha Wildner thiscap >= capacity) 1048*35878b55SSascha Wildner { 1049*35878b55SSascha Wildner maxcap = pVDevice->VDeviceCapacity; 1050*35878b55SSascha Wildner pFind = pVDevice; 1051*35878b55SSascha Wildner } 1052*35878b55SSascha Wildner } 1053*35878b55SSascha Wildner return pFind; 1054*35878b55SSascha Wildner } 1055*35878b55SSascha Wildner 1056*35878b55SSascha Wildner /****************************************************************** 1057*35878b55SSascha Wildner * IO ATA Command 1058*35878b55SSascha Wildner *******************************************************************/ 1059*35878b55SSascha Wildner int HPTLIBAPI 1060*35878b55SSascha Wildner fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer) 1061*35878b55SSascha Wildner { 1062*35878b55SSascha Wildner return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer); 1063*35878b55SSascha Wildner } 1064*35878b55SSascha Wildner 1065*35878b55SSascha Wildner void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) 1066*35878b55SSascha Wildner { 1067*35878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1068*35878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1069*35878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 1070*35878b55SSascha Wildner UCHAR mvMode; 1071*35878b55SSascha Wildner /* 508x don't use MW-DMA? */ 1072*35878b55SSascha Wildner if (NewMode>4 && NewMode<8) NewMode = 4; 1073*35878b55SSascha Wildner pDev->bDeModeSetting = NewMode; 1074*35878b55SSascha Wildner if (NewMode<=4) 1075*35878b55SSascha Wildner mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode; 1076*35878b55SSascha Wildner else 1077*35878b55SSascha Wildner mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8); 1078*35878b55SSascha Wildner 1079*35878b55SSascha Wildner /*To fix 88i8030 bug*/ 1080*35878b55SSascha Wildner if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4) 1081*35878b55SSascha Wildner mvMode = MV_ATA_TRANSFER_UDMA_0; 1082*35878b55SSascha Wildner 1083*35878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 1084*35878b55SSascha Wildner /* Flush pending commands */ 1085*35878b55SSascha Wildner mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE); 1086*35878b55SSascha Wildner 1087*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1088*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 1089*35878b55SSascha Wildner mvMode, 0, 0, 0) == MV_FALSE) 1090*35878b55SSascha Wildner { 1091*35878b55SSascha Wildner KdPrint(("channel %d: Set Features failed\n", channelIndex)); 1092*35878b55SSascha Wildner } 1093*35878b55SSascha Wildner /* Enable EDMA */ 1094*35878b55SSascha Wildner if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE) 1095*35878b55SSascha Wildner KdPrint(("Failed to enable DMA, channel=%d", channelIndex)); 1096*35878b55SSascha Wildner } 1097*35878b55SSascha Wildner 1098*35878b55SSascha Wildner int HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth) 1099*35878b55SSascha Wildner { 1100*35878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1101*35878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1102*35878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 1103*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1104*35878b55SSascha Wildner MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1105*35878b55SSascha Wildner int dmaActive = pSataChannel->queueCommandsEnabled; 1106*35878b55SSascha Wildner int ret = 0; 1107*35878b55SSascha Wildner 1108*35878b55SSascha Wildner if (dmaActive) { 1109*35878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 1110*35878b55SSascha Wildner mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1111*35878b55SSascha Wildner } 1112*35878b55SSascha Wildner 1113*35878b55SSascha Wildner if (enable) { 1114*35878b55SSascha Wildner if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED && 1115*35878b55SSascha Wildner (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) { 1116*35878b55SSascha Wildner UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1; 1117*35878b55SSascha Wildner channelInfo->queueDepth = (depth==32)? 31 : depth; 1118*35878b55SSascha Wildner mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth); 1119*35878b55SSascha Wildner ret = 1; 1120*35878b55SSascha Wildner } 1121*35878b55SSascha Wildner } 1122*35878b55SSascha Wildner else 1123*35878b55SSascha Wildner { 1124*35878b55SSascha Wildner if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) { 1125*35878b55SSascha Wildner channelInfo->queueDepth = 2; 1126*35878b55SSascha Wildner mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0); 1127*35878b55SSascha Wildner ret = 1; 1128*35878b55SSascha Wildner } 1129*35878b55SSascha Wildner } 1130*35878b55SSascha Wildner 1131*35878b55SSascha Wildner if (dmaActive) 1132*35878b55SSascha Wildner mvSataEnableChannelDma(pSataAdapter,channelIndex); 1133*35878b55SSascha Wildner return ret; 1134*35878b55SSascha Wildner } 1135*35878b55SSascha Wildner 1136*35878b55SSascha Wildner int HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth) 1137*35878b55SSascha Wildner { 1138*35878b55SSascha Wildner return 0; 1139*35878b55SSascha Wildner } 1140*35878b55SSascha Wildner 1141*35878b55SSascha Wildner int HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable) 1142*35878b55SSascha Wildner { 1143*35878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1144*35878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1145*35878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 1146*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1147*35878b55SSascha Wildner MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1148*35878b55SSascha Wildner int dmaActive = pSataChannel->queueCommandsEnabled; 1149*35878b55SSascha Wildner int ret = 0; 1150*35878b55SSascha Wildner 1151*35878b55SSascha Wildner if (dmaActive) { 1152*35878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 1153*35878b55SSascha Wildner mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1154*35878b55SSascha Wildner } 1155*35878b55SSascha Wildner 1156*35878b55SSascha Wildner if ((pSataChannel->identifyDevice[82] & (0x20))) { 1157*35878b55SSascha Wildner if (enable) { 1158*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1159*35878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0)) 1160*35878b55SSascha Wildner { 1161*35878b55SSascha Wildner channelInfo->writeCacheEnabled = MV_TRUE; 1162*35878b55SSascha Wildner ret = 1; 1163*35878b55SSascha Wildner } 1164*35878b55SSascha Wildner } 1165*35878b55SSascha Wildner else { 1166*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1167*35878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0)) 1168*35878b55SSascha Wildner { 1169*35878b55SSascha Wildner channelInfo->writeCacheEnabled = MV_FALSE; 1170*35878b55SSascha Wildner ret = 1; 1171*35878b55SSascha Wildner } 1172*35878b55SSascha Wildner } 1173*35878b55SSascha Wildner } 1174*35878b55SSascha Wildner 1175*35878b55SSascha Wildner if (dmaActive) 1176*35878b55SSascha Wildner mvSataEnableChannelDma(pSataAdapter,channelIndex); 1177*35878b55SSascha Wildner return ret; 1178*35878b55SSascha Wildner } 1179*35878b55SSascha Wildner 1180*35878b55SSascha Wildner int HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable) 1181*35878b55SSascha Wildner { 1182*35878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1183*35878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1184*35878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 1185*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1186*35878b55SSascha Wildner MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1187*35878b55SSascha Wildner int dmaActive = pSataChannel->queueCommandsEnabled; 1188*35878b55SSascha Wildner int ret = 0; 1189*35878b55SSascha Wildner 1190*35878b55SSascha Wildner if (dmaActive) { 1191*35878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 1192*35878b55SSascha Wildner mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1193*35878b55SSascha Wildner } 1194*35878b55SSascha Wildner 1195*35878b55SSascha Wildner if ((pSataChannel->identifyDevice[82] & (0x40))) { 1196*35878b55SSascha Wildner if (enable) { 1197*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1198*35878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0)) 1199*35878b55SSascha Wildner { 1200*35878b55SSascha Wildner channelInfo->readAheadEnabled = MV_TRUE; 1201*35878b55SSascha Wildner ret = 1; 1202*35878b55SSascha Wildner } 1203*35878b55SSascha Wildner } 1204*35878b55SSascha Wildner else { 1205*35878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1206*35878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0)) 1207*35878b55SSascha Wildner { 1208*35878b55SSascha Wildner channelInfo->readAheadEnabled = MV_FALSE; 1209*35878b55SSascha Wildner ret = 1; 1210*35878b55SSascha Wildner } 1211*35878b55SSascha Wildner } 1212*35878b55SSascha Wildner } 1213*35878b55SSascha Wildner 1214*35878b55SSascha Wildner if (dmaActive) 1215*35878b55SSascha Wildner mvSataEnableChannelDma(pSataAdapter,channelIndex); 1216*35878b55SSascha Wildner return ret; 1217*35878b55SSascha Wildner } 1218*35878b55SSascha Wildner 1219*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 1220*35878b55SSascha Wildner #define IdeRegisterVDevice fCheckArray 1221*35878b55SSascha Wildner #else 1222*35878b55SSascha Wildner void 1223*35878b55SSascha Wildner IdeRegisterVDevice(PDevice pDev) 1224*35878b55SSascha Wildner { 1225*35878b55SSascha Wildner PVDevice pVDev = Map2pVDevice(pDev); 1226*35878b55SSascha Wildner 1227*35878b55SSascha Wildner pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI : 1228*35878b55SSascha Wildner pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 1229*35878b55SSascha Wildner pVDev->vf_online = 1; 1230*35878b55SSascha Wildner pVDev->VDeviceCapacity = pDev->dDeRealCapacity; 1231*35878b55SSascha Wildner pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 1232*35878b55SSascha Wildner pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 1233*35878b55SSascha Wildner } 1234*35878b55SSascha Wildner #endif 1235*35878b55SSascha Wildner 1236*35878b55SSascha Wildner static __inline PBUS_DMAMAP 1237*35878b55SSascha Wildner dmamap_get(struct IALAdapter * pAdapter) 1238*35878b55SSascha Wildner { 1239*35878b55SSascha Wildner PBUS_DMAMAP p = pAdapter->pbus_dmamap_list; 1240*35878b55SSascha Wildner if (p) 1241*35878b55SSascha Wildner pAdapter->pbus_dmamap_list = p-> next; 1242*35878b55SSascha Wildner return p; 1243*35878b55SSascha Wildner } 1244*35878b55SSascha Wildner 1245*35878b55SSascha Wildner static __inline void 1246*35878b55SSascha Wildner dmamap_put(PBUS_DMAMAP p) 1247*35878b55SSascha Wildner { 1248*35878b55SSascha Wildner p->next = p->pAdapter->pbus_dmamap_list; 1249*35878b55SSascha Wildner p->pAdapter->pbus_dmamap_list = p; 1250*35878b55SSascha Wildner } 1251*35878b55SSascha Wildner 1252*35878b55SSascha Wildner /*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/ 1253*35878b55SSascha Wildner #define override_kernel_driver() 1254*35878b55SSascha Wildner 1255*35878b55SSascha Wildner static void hpt_init(void *dummy) 1256*35878b55SSascha Wildner { 1257*35878b55SSascha Wildner override_kernel_driver(); 1258*35878b55SSascha Wildner lockinit(&driver_lock, "hptsleeplock", 0, LK_CANRECURSE); 1259*35878b55SSascha Wildner } 1260*35878b55SSascha Wildner SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1261*35878b55SSascha Wildner 1262*35878b55SSascha Wildner static int num_adapters = 0; 1263*35878b55SSascha Wildner static int 1264*35878b55SSascha Wildner init_adapter(IAL_ADAPTER_T *pAdapter) 1265*35878b55SSascha Wildner { 1266*35878b55SSascha Wildner PVBus _vbus_p = &pAdapter->VBus; 1267*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter; 1268*35878b55SSascha Wildner int i, channel, rid; 1269*35878b55SSascha Wildner 1270*35878b55SSascha Wildner PVDevice pVDev; 1271*35878b55SSascha Wildner 1272*35878b55SSascha Wildner intrmask_t oldspl = lock_driver(); 1273*35878b55SSascha Wildner 1274*35878b55SSascha Wildner pAdapter->next = 0; 1275*35878b55SSascha Wildner 1276*35878b55SSascha Wildner if(gIal_Adapter == 0){ 1277*35878b55SSascha Wildner gIal_Adapter = pAdapter; 1278*35878b55SSascha Wildner pCurAdapter = gIal_Adapter; 1279*35878b55SSascha Wildner } 1280*35878b55SSascha Wildner else { 1281*35878b55SSascha Wildner pCurAdapter->next = pAdapter; 1282*35878b55SSascha Wildner pCurAdapter = pAdapter; 1283*35878b55SSascha Wildner } 1284*35878b55SSascha Wildner 1285*35878b55SSascha Wildner pAdapter->outstandingCommands = 0; 1286*35878b55SSascha Wildner 1287*35878b55SSascha Wildner pMvSataAdapter = &(pAdapter->mvSataAdapter); 1288*35878b55SSascha Wildner _vbus_p->OsExt = (void *)pAdapter; 1289*35878b55SSascha Wildner pMvSataAdapter->IALData = pAdapter; 1290*35878b55SSascha Wildner 1291*35878b55SSascha Wildner if (bus_dma_tag_create(NULL,/* parent */ 1292*35878b55SSascha Wildner 4, /* alignment */ 1293*35878b55SSascha Wildner BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1294*35878b55SSascha Wildner BUS_SPACE_MAXADDR, /* lowaddr */ 1295*35878b55SSascha Wildner BUS_SPACE_MAXADDR, /* highaddr */ 1296*35878b55SSascha Wildner NULL, NULL, /* filter, filterarg */ 1297*35878b55SSascha Wildner PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */ 1298*35878b55SSascha Wildner MAX_SG_DESCRIPTORS, /* nsegments */ 1299*35878b55SSascha Wildner 0x10000, /* maxsegsize */ 1300*35878b55SSascha Wildner BUS_DMA_WAITOK, /* flags */ 1301*35878b55SSascha Wildner &pAdapter->io_dma_parent /* tag */)) 1302*35878b55SSascha Wildner { 1303*35878b55SSascha Wildner return ENXIO; 1304*35878b55SSascha Wildner } 1305*35878b55SSascha Wildner 1306*35878b55SSascha Wildner 1307*35878b55SSascha Wildner if (hptmv_allocate_edma_queues(pAdapter)) 1308*35878b55SSascha Wildner { 1309*35878b55SSascha Wildner MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n"); 1310*35878b55SSascha Wildner unlock_driver(oldspl); 1311*35878b55SSascha Wildner return ENOMEM; 1312*35878b55SSascha Wildner } 1313*35878b55SSascha Wildner 1314*35878b55SSascha Wildner /* also map EPROM address */ 1315*35878b55SSascha Wildner rid = 0x10; 1316*35878b55SSascha Wildner if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid, 1317*35878b55SSascha Wildner 0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE)) 1318*35878b55SSascha Wildner || 1319*35878b55SSascha Wildner !(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res))) 1320*35878b55SSascha Wildner { 1321*35878b55SSascha Wildner MV_ERROR("RR18xx: Failed to remap memory space\n"); 1322*35878b55SSascha Wildner hptmv_free_edma_queues(pAdapter); 1323*35878b55SSascha Wildner unlock_driver(oldspl); 1324*35878b55SSascha Wildner return ENXIO; 1325*35878b55SSascha Wildner } 1326*35878b55SSascha Wildner else 1327*35878b55SSascha Wildner { 1328*35878b55SSascha Wildner KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress)); 1329*35878b55SSascha Wildner } 1330*35878b55SSascha Wildner 1331*35878b55SSascha Wildner pMvSataAdapter->adapterId = num_adapters++; 1332*35878b55SSascha Wildner /* get the revision ID */ 1333*35878b55SSascha Wildner pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); 1334*35878b55SSascha Wildner pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev); 1335*35878b55SSascha Wildner 1336*35878b55SSascha Wildner /* init RR18xx */ 1337*35878b55SSascha Wildner pMvSataAdapter->intCoalThre[0]= 1; 1338*35878b55SSascha Wildner pMvSataAdapter->intCoalThre[1]= 1; 1339*35878b55SSascha Wildner pMvSataAdapter->intTimeThre[0] = 1; 1340*35878b55SSascha Wildner pMvSataAdapter->intTimeThre[1] = 1; 1341*35878b55SSascha Wildner pMvSataAdapter->pciCommand = 0x0107E371; 1342*35878b55SSascha Wildner pMvSataAdapter->pciSerrMask = 0xd77fe6ul; 1343*35878b55SSascha Wildner pMvSataAdapter->pciInterruptMask = 0xd77fe6ul; 1344*35878b55SSascha Wildner pMvSataAdapter->mvSataEventNotify = hptmv_event_notify; 1345*35878b55SSascha Wildner 1346*35878b55SSascha Wildner if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) 1347*35878b55SSascha Wildner { 1348*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n", 1349*35878b55SSascha Wildner pMvSataAdapter->adapterId); 1350*35878b55SSascha Wildner unregister: 1351*35878b55SSascha Wildner bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res); 1352*35878b55SSascha Wildner hptmv_free_edma_queues(pAdapter); 1353*35878b55SSascha Wildner unlock_driver(oldspl); 1354*35878b55SSascha Wildner return ENXIO; 1355*35878b55SSascha Wildner } 1356*35878b55SSascha Wildner pAdapter->ver_601 = pMvSataAdapter->pcbVersion; 1357*35878b55SSascha Wildner 1358*35878b55SSascha Wildner #ifndef FOR_DEMO 1359*35878b55SSascha Wildner set_fail_leds(pMvSataAdapter, 0); 1360*35878b55SSascha Wildner #endif 1361*35878b55SSascha Wildner 1362*35878b55SSascha Wildner /* setup command blocks */ 1363*35878b55SSascha Wildner KdPrint(("Allocate command blocks\n")); 1364*35878b55SSascha Wildner _vbus_(pFreeCommands) = 0; 1365*35878b55SSascha Wildner pAdapter->pCommandBlocks = 1366*35878b55SSascha Wildner kmalloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT); 1367*35878b55SSascha Wildner KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks)); 1368*35878b55SSascha Wildner if (!pAdapter->pCommandBlocks) { 1369*35878b55SSascha Wildner MV_ERROR("insufficient memory\n"); 1370*35878b55SSascha Wildner goto unregister; 1371*35878b55SSascha Wildner } 1372*35878b55SSascha Wildner 1373*35878b55SSascha Wildner for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) { 1374*35878b55SSascha Wildner FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i])); 1375*35878b55SSascha Wildner } 1376*35878b55SSascha Wildner 1377*35878b55SSascha Wildner /*Set up the bus_dmamap*/ 1378*35878b55SSascha Wildner pAdapter->pbus_dmamap = (PBUS_DMAMAP)kmalloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT); 1379*35878b55SSascha Wildner if(!pAdapter->pbus_dmamap) { 1380*35878b55SSascha Wildner MV_ERROR("insufficient memory\n"); 1381*35878b55SSascha Wildner kfree(pAdapter->pCommandBlocks, M_DEVBUF); 1382*35878b55SSascha Wildner goto unregister; 1383*35878b55SSascha Wildner } 1384*35878b55SSascha Wildner 1385*35878b55SSascha Wildner memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM); 1386*35878b55SSascha Wildner pAdapter->pbus_dmamap_list = 0; 1387*35878b55SSascha Wildner for (i=0; i < MAX_QUEUE_COMM; i++) { 1388*35878b55SSascha Wildner PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]); 1389*35878b55SSascha Wildner pmap->pAdapter = pAdapter; 1390*35878b55SSascha Wildner dmamap_put(pmap); 1391*35878b55SSascha Wildner 1392*35878b55SSascha Wildner if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) { 1393*35878b55SSascha Wildner MV_ERROR("Can not allocate dma map\n"); 1394*35878b55SSascha Wildner kfree(pAdapter->pCommandBlocks, M_DEVBUF); 1395*35878b55SSascha Wildner kfree(pAdapter->pbus_dmamap, M_DEVBUF); 1396*35878b55SSascha Wildner goto unregister; 1397*35878b55SSascha Wildner } 1398*35878b55SSascha Wildner } 1399*35878b55SSascha Wildner /* setup PRD Tables */ 1400*35878b55SSascha Wildner KdPrint(("Allocate PRD Tables\n")); 1401*35878b55SSascha Wildner pAdapter->pFreePRDLink = 0; 1402*35878b55SSascha Wildner 1403*35878b55SSascha Wildner pAdapter->prdTableAddr = (PUCHAR)contigmalloc( 1404*35878b55SSascha Wildner (PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 1405*35878b55SSascha Wildner 1406*35878b55SSascha Wildner KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr)); 1407*35878b55SSascha Wildner if (!pAdapter->prdTableAddr) { 1408*35878b55SSascha Wildner MV_ERROR("insufficient PRD Tables\n"); 1409*35878b55SSascha Wildner goto unregister; 1410*35878b55SSascha Wildner } 1411*35878b55SSascha Wildner pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL); 1412*35878b55SSascha Wildner { 1413*35878b55SSascha Wildner PUCHAR PRDTable = pAdapter->prdTableAlignedAddr; 1414*35878b55SSascha Wildner for (i=0; i<PRD_TABLES_FOR_VBUS; i++) 1415*35878b55SSascha Wildner { 1416*35878b55SSascha Wildner /* KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */ 1417*35878b55SSascha Wildner FreePRDTable(pAdapter, PRDTable); 1418*35878b55SSascha Wildner PRDTable += PRD_ENTRIES_SIZE; 1419*35878b55SSascha Wildner } 1420*35878b55SSascha Wildner } 1421*35878b55SSascha Wildner 1422*35878b55SSascha Wildner /* enable the adapter interrupts */ 1423*35878b55SSascha Wildner 1424*35878b55SSascha Wildner /* configure and start the connected channels*/ 1425*35878b55SSascha Wildner for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 1426*35878b55SSascha Wildner { 1427*35878b55SSascha Wildner pAdapter->mvChannel[channel].online = MV_FALSE; 1428*35878b55SSascha Wildner if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) 1429*35878b55SSascha Wildner == MV_TRUE) 1430*35878b55SSascha Wildner { 1431*35878b55SSascha Wildner KdPrint(("RR18xx[%d]: channel %d is connected\n", 1432*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel)); 1433*35878b55SSascha Wildner 1434*35878b55SSascha Wildner if (hptmv_init_channel(pAdapter, channel) == 0) 1435*35878b55SSascha Wildner { 1436*35878b55SSascha Wildner if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE) 1437*35878b55SSascha Wildner { 1438*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to configure channel" 1439*35878b55SSascha Wildner " %d\n",pMvSataAdapter->adapterId, channel); 1440*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1441*35878b55SSascha Wildner } 1442*35878b55SSascha Wildner else 1443*35878b55SSascha Wildner { 1444*35878b55SSascha Wildner if (start_channel(pAdapter, channel)) 1445*35878b55SSascha Wildner { 1446*35878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to start channel," 1447*35878b55SSascha Wildner " channel=%d\n",pMvSataAdapter->adapterId, 1448*35878b55SSascha Wildner channel); 1449*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1450*35878b55SSascha Wildner } 1451*35878b55SSascha Wildner pAdapter->mvChannel[channel].online = MV_TRUE; 1452*35878b55SSascha Wildner /* mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter, 1453*35878b55SSascha Wildner channel, 1454*35878b55SSascha Wildner MV_TRUE);*/ 1455*35878b55SSascha Wildner } 1456*35878b55SSascha Wildner } 1457*35878b55SSascha Wildner } 1458*35878b55SSascha Wildner KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n", 1459*35878b55SSascha Wildner pAdapter->mvChannel[channel].online, channel)); 1460*35878b55SSascha Wildner } 1461*35878b55SSascha Wildner 1462*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 1463*35878b55SSascha Wildner for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) { 1464*35878b55SSascha Wildner pVDev = ArrayTables(i); 1465*35878b55SSascha Wildner mArFreeArrayTable(pVDev); 1466*35878b55SSascha Wildner } 1467*35878b55SSascha Wildner #endif 1468*35878b55SSascha Wildner 1469*35878b55SSascha Wildner KdPrint(("Initialize Devices\n")); 1470*35878b55SSascha Wildner for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { 1471*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1472*35878b55SSascha Wildner if (pMvSataChannel) { 1473*35878b55SSascha Wildner init_vdev_params(pAdapter, channel); 1474*35878b55SSascha Wildner IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk); 1475*35878b55SSascha Wildner } 1476*35878b55SSascha Wildner } 1477*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 1478*35878b55SSascha Wildner CheckArrayCritical(_VBUS_P0); 1479*35878b55SSascha Wildner #endif 1480*35878b55SSascha Wildner _vbus_p->nInstances = 1; 1481*35878b55SSascha Wildner fRegisterVdevice(pAdapter); 1482*35878b55SSascha Wildner 1483*35878b55SSascha Wildner for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) { 1484*35878b55SSascha Wildner pVDev = _vbus_p->pVDevice[channel]; 1485*35878b55SSascha Wildner if (pVDev && pVDev->vf_online) 1486*35878b55SSascha Wildner fCheckBootable(pVDev); 1487*35878b55SSascha Wildner } 1488*35878b55SSascha Wildner 1489*35878b55SSascha Wildner #if defined(SUPPORT_ARRAY) && defined(_RAID5N_) 1490*35878b55SSascha Wildner init_raid5_memory(_VBUS_P0); 1491*35878b55SSascha Wildner _vbus_(r5).enable_write_back = 1; 1492*35878b55SSascha Wildner kprintf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled"); 1493*35878b55SSascha Wildner #endif 1494*35878b55SSascha Wildner 1495*35878b55SSascha Wildner mvSataUnmaskAdapterInterrupt(pMvSataAdapter); 1496*35878b55SSascha Wildner unlock_driver(oldspl); 1497*35878b55SSascha Wildner return 0; 1498*35878b55SSascha Wildner } 1499*35878b55SSascha Wildner 1500*35878b55SSascha Wildner int 1501*35878b55SSascha Wildner MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) 1502*35878b55SSascha Wildner { 1503*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; 1504*35878b55SSascha Wildner 1505*35878b55SSascha Wildner mvSataDisableChannelDma(pMvSataAdapter, channel); 1506*35878b55SSascha Wildner /* Flush pending commands */ 1507*35878b55SSascha Wildner mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 1508*35878b55SSascha Wildner 1509*35878b55SSascha Wildner /* Software reset channel */ 1510*35878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE) 1511*35878b55SSascha Wildner { 1512*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 1513*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 1514*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1515*35878b55SSascha Wildner return -1; 1516*35878b55SSascha Wildner } 1517*35878b55SSascha Wildner 1518*35878b55SSascha Wildner /* Hardware reset channel */ 1519*35878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) 1520*35878b55SSascha Wildner { 1521*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n", 1522*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 1523*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1524*35878b55SSascha Wildner return -1; 1525*35878b55SSascha Wildner } 1526*35878b55SSascha Wildner 1527*35878b55SSascha Wildner if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE) 1528*35878b55SSascha Wildner { 1529*35878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n", 1530*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 1531*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1532*35878b55SSascha Wildner return -1; 1533*35878b55SSascha Wildner }else 1534*35878b55SSascha Wildner { 1535*35878b55SSascha Wildner MV_ERROR("channel %d: perform recalibrate command", channel); 1536*35878b55SSascha Wildner if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1537*35878b55SSascha Wildner MV_NON_UDMA_PROTOCOL_NON_DATA, 1538*35878b55SSascha Wildner MV_FALSE, 1539*35878b55SSascha Wildner NULL, /* pBuffer*/ 1540*35878b55SSascha Wildner 0, /* count */ 1541*35878b55SSascha Wildner 0, /*features*/ 1542*35878b55SSascha Wildner /* sectorCount */ 1543*35878b55SSascha Wildner 0, 1544*35878b55SSascha Wildner 0, /* lbaLow */ 1545*35878b55SSascha Wildner 0, /* lbaMid */ 1546*35878b55SSascha Wildner /* lbaHigh */ 1547*35878b55SSascha Wildner 0, 1548*35878b55SSascha Wildner 0, /* device */ 1549*35878b55SSascha Wildner /* command */ 1550*35878b55SSascha Wildner 0x10)) 1551*35878b55SSascha Wildner MV_ERROR("channel %d: recalibrate failed", channel); 1552*35878b55SSascha Wildner 1553*35878b55SSascha Wildner /* Set transfer mode */ 1554*35878b55SSascha Wildner if((mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1555*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 1556*35878b55SSascha Wildner MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) || 1557*35878b55SSascha Wildner (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1558*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 1559*35878b55SSascha Wildner pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) || 1560*35878b55SSascha Wildner (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1561*35878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 1562*35878b55SSascha Wildner pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) ) 1563*35878b55SSascha Wildner { 1564*35878b55SSascha Wildner MV_ERROR("channel %d: Set Features failed", channel); 1565*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1566*35878b55SSascha Wildner return -1; 1567*35878b55SSascha Wildner } 1568*35878b55SSascha Wildner /* Enable EDMA */ 1569*35878b55SSascha Wildner if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE) 1570*35878b55SSascha Wildner { 1571*35878b55SSascha Wildner MV_ERROR("Failed to enable DMA, channel=%d", channel); 1572*35878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 1573*35878b55SSascha Wildner return -1; 1574*35878b55SSascha Wildner } 1575*35878b55SSascha Wildner } 1576*35878b55SSascha Wildner return 0; 1577*35878b55SSascha Wildner } 1578*35878b55SSascha Wildner 1579*35878b55SSascha Wildner static int 1580*35878b55SSascha Wildner fResetActiveCommands(PVBus _vbus_p) 1581*35878b55SSascha Wildner { 1582*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 1583*35878b55SSascha Wildner MV_U8 channel; 1584*35878b55SSascha Wildner for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1585*35878b55SSascha Wildner if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands) 1586*35878b55SSascha Wildner MvSataResetChannel(pMvSataAdapter,channel); 1587*35878b55SSascha Wildner } 1588*35878b55SSascha Wildner return 0; 1589*35878b55SSascha Wildner } 1590*35878b55SSascha Wildner 1591*35878b55SSascha Wildner void fCompleteAllCommandsSynchronously(PVBus _vbus_p) 1592*35878b55SSascha Wildner { 1593*35878b55SSascha Wildner UINT cont; 1594*35878b55SSascha Wildner ULONG ticks = 0; 1595*35878b55SSascha Wildner MV_U8 channel; 1596*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 1597*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel; 1598*35878b55SSascha Wildner 1599*35878b55SSascha Wildner do { 1600*35878b55SSascha Wildner check_cmds: 1601*35878b55SSascha Wildner cont = 0; 1602*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 1603*35878b55SSascha Wildner #ifdef _RAID5N_ 1604*35878b55SSascha Wildner dataxfer_poll(); 1605*35878b55SSascha Wildner xor_poll(); 1606*35878b55SSascha Wildner #endif 1607*35878b55SSascha Wildner for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1608*35878b55SSascha Wildner pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1609*35878b55SSascha Wildner if (pMvSataChannel && pMvSataChannel->outstandingCommands) 1610*35878b55SSascha Wildner { 1611*35878b55SSascha Wildner while (pMvSataChannel->outstandingCommands) { 1612*35878b55SSascha Wildner if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) { 1613*35878b55SSascha Wildner StallExec(1000); 1614*35878b55SSascha Wildner if (ticks++ > 3000) { 1615*35878b55SSascha Wildner MvSataResetChannel(pMvSataAdapter,channel); 1616*35878b55SSascha Wildner goto check_cmds; 1617*35878b55SSascha Wildner } 1618*35878b55SSascha Wildner } 1619*35878b55SSascha Wildner else 1620*35878b55SSascha Wildner ticks = 0; 1621*35878b55SSascha Wildner } 1622*35878b55SSascha Wildner cont = 1; 1623*35878b55SSascha Wildner } 1624*35878b55SSascha Wildner } 1625*35878b55SSascha Wildner } while (cont); 1626*35878b55SSascha Wildner } 1627*35878b55SSascha Wildner 1628*35878b55SSascha Wildner void 1629*35878b55SSascha Wildner fResetVBus(_VBUS_ARG0) 1630*35878b55SSascha Wildner { 1631*35878b55SSascha Wildner KdPrint(("fMvResetBus(%p)", _vbus_p)); 1632*35878b55SSascha Wildner 1633*35878b55SSascha Wildner /* some commands may already finished. */ 1634*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 1635*35878b55SSascha Wildner 1636*35878b55SSascha Wildner fResetActiveCommands(_vbus_p); 1637*35878b55SSascha Wildner /* 1638*35878b55SSascha Wildner * the other pending commands may still be finished successfully. 1639*35878b55SSascha Wildner */ 1640*35878b55SSascha Wildner fCompleteAllCommandsSynchronously(_vbus_p); 1641*35878b55SSascha Wildner 1642*35878b55SSascha Wildner /* Now there should be no pending commands. No more action needed. */ 1643*35878b55SSascha Wildner CheckIdleCall(_VBUS_P0); 1644*35878b55SSascha Wildner 1645*35878b55SSascha Wildner KdPrint(("fMvResetBus() done")); 1646*35878b55SSascha Wildner } 1647*35878b55SSascha Wildner 1648*35878b55SSascha Wildner /*No rescan function*/ 1649*35878b55SSascha Wildner void 1650*35878b55SSascha Wildner fRescanAllDevice(_VBUS_ARG0) 1651*35878b55SSascha Wildner { 1652*35878b55SSascha Wildner } 1653*35878b55SSascha Wildner 1654*35878b55SSascha Wildner static MV_BOOLEAN 1655*35878b55SSascha Wildner CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 1656*35878b55SSascha Wildner MV_U8 channelNum, 1657*35878b55SSascha Wildner MV_COMPLETION_TYPE comp_type, 1658*35878b55SSascha Wildner MV_VOID_PTR commandId, 1659*35878b55SSascha Wildner MV_U16 responseFlags, 1660*35878b55SSascha Wildner MV_U32 timeStamp, 1661*35878b55SSascha Wildner MV_STORAGE_DEVICE_REGISTERS *registerStruct) 1662*35878b55SSascha Wildner { 1663*35878b55SSascha Wildner PCommand pCmd = (PCommand) commandId; 1664*35878b55SSascha Wildner _VBUS_INST(pCmd->pVDevice->pVBus) 1665*35878b55SSascha Wildner 1666*35878b55SSascha Wildner if (pCmd->uScratch.sata_param.prdAddr) 1667*35878b55SSascha Wildner FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr); 1668*35878b55SSascha Wildner 1669*35878b55SSascha Wildner switch (comp_type) 1670*35878b55SSascha Wildner { 1671*35878b55SSascha Wildner case MV_COMPLETION_TYPE_NORMAL: 1672*35878b55SSascha Wildner pCmd->Result = RETURN_SUCCESS; 1673*35878b55SSascha Wildner break; 1674*35878b55SSascha Wildner case MV_COMPLETION_TYPE_ABORT: 1675*35878b55SSascha Wildner pCmd->Result = RETURN_BUS_RESET; 1676*35878b55SSascha Wildner break; 1677*35878b55SSascha Wildner case MV_COMPLETION_TYPE_ERROR: 1678*35878b55SSascha Wildner MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n", 1679*35878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum, responseFlags); 1680*35878b55SSascha Wildner 1681*35878b55SSascha Wildner if (responseFlags & 4) { 1682*35878b55SSascha Wildner MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x," 1683*35878b55SSascha Wildner " LBA high %x, device %x, status %x\n", 1684*35878b55SSascha Wildner registerStruct->errorRegister, 1685*35878b55SSascha Wildner registerStruct->sectorCountRegister, 1686*35878b55SSascha Wildner registerStruct->lbaLowRegister, 1687*35878b55SSascha Wildner registerStruct->lbaMidRegister, 1688*35878b55SSascha Wildner registerStruct->lbaHighRegister, 1689*35878b55SSascha Wildner registerStruct->deviceRegister, 1690*35878b55SSascha Wildner registerStruct->statusRegister); 1691*35878b55SSascha Wildner } 1692*35878b55SSascha Wildner /*We can't do handleEdmaError directly here, because CommandCompletionCB is called by 1693*35878b55SSascha Wildner * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/ 1694*35878b55SSascha Wildner pCmd->uScratch.sata_param.responseFlags = responseFlags; 1695*35878b55SSascha Wildner pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister; 1696*35878b55SSascha Wildner pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister; 1697*35878b55SSascha Wildner pCmd->pVDevice->u.disk.QueueLength--; 1698*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd); 1699*35878b55SSascha Wildner return TRUE; 1700*35878b55SSascha Wildner 1701*35878b55SSascha Wildner default: 1702*35878b55SSascha Wildner MV_ERROR(" Unknown completion type (%d)\n", comp_type); 1703*35878b55SSascha Wildner return MV_FALSE; 1704*35878b55SSascha Wildner } 1705*35878b55SSascha Wildner 1706*35878b55SSascha Wildner if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) { 1707*35878b55SSascha Wildner pCmd->uScratch.sata_param.cmd_priv --; 1708*35878b55SSascha Wildner return TRUE; 1709*35878b55SSascha Wildner } 1710*35878b55SSascha Wildner pCmd->pVDevice->u.disk.QueueLength--; 1711*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1712*35878b55SSascha Wildner return TRUE; 1713*35878b55SSascha Wildner } 1714*35878b55SSascha Wildner 1715*35878b55SSascha Wildner void 1716*35878b55SSascha Wildner fDeviceSendCommand(_VBUS_ARG PCommand pCmd) 1717*35878b55SSascha Wildner { 1718*35878b55SSascha Wildner MV_SATA_EDMA_PRD_ENTRY *pPRDTable = 0; 1719*35878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter; 1720*35878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel; 1721*35878b55SSascha Wildner PVDevice pVDevice = pCmd->pVDevice; 1722*35878b55SSascha Wildner PDevice pDevice = &pVDevice->u.disk; 1723*35878b55SSascha Wildner LBA_T Lba = pCmd->uCmd.Ide.Lba; 1724*35878b55SSascha Wildner USHORT nSector = pCmd->uCmd.Ide.nSectors; 1725*35878b55SSascha Wildner 1726*35878b55SSascha Wildner MV_QUEUE_COMMAND_RESULT result; 1727*35878b55SSascha Wildner MV_QUEUE_COMMAND_INFO commandInfo; 1728*35878b55SSascha Wildner MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand; 1729*35878b55SSascha Wildner MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; 1730*35878b55SSascha Wildner 1731*35878b55SSascha Wildner MV_BOOLEAN is48bit; 1732*35878b55SSascha Wildner MV_U8 channel; 1733*35878b55SSascha Wildner int i=0; 1734*35878b55SSascha Wildner 1735*35878b55SSascha Wildner DECLARE_BUFFER(FPSCAT_GATH, tmpSg); 1736*35878b55SSascha Wildner 1737*35878b55SSascha Wildner if (!pDevice->df_on_line) { 1738*35878b55SSascha Wildner MV_ERROR("Device is offline"); 1739*35878b55SSascha Wildner pCmd->Result = RETURN_BAD_DEVICE; 1740*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1741*35878b55SSascha Wildner return; 1742*35878b55SSascha Wildner } 1743*35878b55SSascha Wildner 1744*35878b55SSascha Wildner pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors; 1745*35878b55SSascha Wildner pMvSataChannel = pDevice->mv; 1746*35878b55SSascha Wildner pMvSataAdapter = pMvSataChannel->mvSataAdapter; 1747*35878b55SSascha Wildner channel = pMvSataChannel->channelNumber; 1748*35878b55SSascha Wildner 1749*35878b55SSascha Wildner /* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */ 1750*35878b55SSascha Wildner Lba += pDevice->dDeHiddenLba; 1751*35878b55SSascha Wildner /* check LBA */ 1752*35878b55SSascha Wildner if (Lba+nSector-1 > pDevice->dDeRealCapacity) { 1753*35878b55SSascha Wildner pCmd->Result = RETURN_INVALID_REQUEST; 1754*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1755*35878b55SSascha Wildner return; 1756*35878b55SSascha Wildner } 1757*35878b55SSascha Wildner 1758*35878b55SSascha Wildner /* 1759*35878b55SSascha Wildner * always use 48bit LBA if drive supports it. 1760*35878b55SSascha Wildner * Some Seagate drives report error if you use a 28-bit command 1761*35878b55SSascha Wildner * to access sector 0xfffffff. 1762*35878b55SSascha Wildner */ 1763*35878b55SSascha Wildner is48bit = pMvSataChannel->lba48Address; 1764*35878b55SSascha Wildner 1765*35878b55SSascha Wildner switch (pCmd->uCmd.Ide.Command) 1766*35878b55SSascha Wildner { 1767*35878b55SSascha Wildner case IDE_COMMAND_READ: 1768*35878b55SSascha Wildner case IDE_COMMAND_WRITE: 1769*35878b55SSascha Wildner if (pDevice->bDeModeSetting<8) goto pio; 1770*35878b55SSascha Wildner 1771*35878b55SSascha Wildner commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA; 1772*35878b55SSascha Wildner pUdmaParams->isEXT = is48bit; 1773*35878b55SSascha Wildner pUdmaParams->numOfSectors = nSector; 1774*35878b55SSascha Wildner pUdmaParams->lowLBAAddress = Lba; 1775*35878b55SSascha Wildner pUdmaParams->highLBAAddress = 0; 1776*35878b55SSascha Wildner pUdmaParams->prdHighAddr = 0; 1777*35878b55SSascha Wildner pUdmaParams->callBack = CommandCompletionCB; 1778*35878b55SSascha Wildner pUdmaParams->commandId = (MV_VOID_PTR )pCmd; 1779*35878b55SSascha Wildner if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ) 1780*35878b55SSascha Wildner pUdmaParams->readWrite = MV_UDMA_TYPE_READ; 1781*35878b55SSascha Wildner else 1782*35878b55SSascha Wildner pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE; 1783*35878b55SSascha Wildner 1784*35878b55SSascha Wildner if (pCmd->pSgTable && pCmd->cf_physical_sg) { 1785*35878b55SSascha Wildner FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1786*35878b55SSascha Wildner do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1787*35878b55SSascha Wildner } 1788*35878b55SSascha Wildner else { 1789*35878b55SSascha Wildner if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { 1790*35878b55SSascha Wildner pio: 1791*35878b55SSascha Wildner mvSataDisableChannelDma(pMvSataAdapter, channel); 1792*35878b55SSascha Wildner mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 1793*35878b55SSascha Wildner 1794*35878b55SSascha Wildner if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { 1795*35878b55SSascha Wildner FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1796*35878b55SSascha Wildner do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1797*35878b55SSascha Wildner } 1798*35878b55SSascha Wildner else { 1799*35878b55SSascha Wildner if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) { 1800*35878b55SSascha Wildner pCmd->Result = RETURN_NEED_LOGICAL_SG; 1801*35878b55SSascha Wildner goto finish_cmd; 1802*35878b55SSascha Wildner } 1803*35878b55SSascha Wildner } 1804*35878b55SSascha Wildner 1805*35878b55SSascha Wildner do { 1806*35878b55SSascha Wildner ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; 1807*35878b55SSascha Wildner ULONG_PTR addr = tmpSg->dSgAddress; 1808*35878b55SSascha Wildner if (size & 0x1ff) { 1809*35878b55SSascha Wildner pCmd->Result = RETURN_INVALID_REQUEST; 1810*35878b55SSascha Wildner goto finish_cmd; 1811*35878b55SSascha Wildner } 1812*35878b55SSascha Wildner if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1813*35878b55SSascha Wildner (pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, 1814*35878b55SSascha Wildner is48bit, 1815*35878b55SSascha Wildner (MV_U16_PTR)addr, 1816*35878b55SSascha Wildner size >> 1, /* count */ 1817*35878b55SSascha Wildner 0, /* features N/A */ 1818*35878b55SSascha Wildner (MV_U16)(size>>9), /*sector count*/ 1819*35878b55SSascha Wildner (MV_U16)( (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | (UCHAR)(Lba & 0xFF) ), /*lbalow*/ 1820*35878b55SSascha Wildner (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ 1821*35878b55SSascha Wildner (MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh */ 1822*35878b55SSascha Wildner (MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device */ 1823*35878b55SSascha Wildner (MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command) 1824*35878b55SSascha Wildner )==MV_FALSE) 1825*35878b55SSascha Wildner { 1826*35878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 1827*35878b55SSascha Wildner goto finish_cmd; 1828*35878b55SSascha Wildner } 1829*35878b55SSascha Wildner Lba += size>>9; 1830*35878b55SSascha Wildner if(Lba & 0xF0000000) is48bit = MV_TRUE; 1831*35878b55SSascha Wildner } 1832*35878b55SSascha Wildner while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 1833*35878b55SSascha Wildner pCmd->Result = RETURN_SUCCESS; 1834*35878b55SSascha Wildner finish_cmd: 1835*35878b55SSascha Wildner mvSataEnableChannelDma(pMvSataAdapter,channel); 1836*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1837*35878b55SSascha Wildner return; 1838*35878b55SSascha Wildner } 1839*35878b55SSascha Wildner } 1840*35878b55SSascha Wildner 1841*35878b55SSascha Wildner pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData); 1842*35878b55SSascha Wildner KdPrint(("pPRDTable:%p\n",pPRDTable)); 1843*35878b55SSascha Wildner if (!pPRDTable) { 1844*35878b55SSascha Wildner pCmd->Result = RETURN_DEVICE_BUSY; 1845*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1846*35878b55SSascha Wildner HPT_ASSERT(0); 1847*35878b55SSascha Wildner return; 1848*35878b55SSascha Wildner } 1849*35878b55SSascha Wildner 1850*35878b55SSascha Wildner do{ 1851*35878b55SSascha Wildner pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0); 1852*35878b55SSascha Wildner pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag; 1853*35878b55SSascha Wildner pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize; 1854*35878b55SSascha Wildner pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress; 1855*35878b55SSascha Wildner pPRDTable[i].reserved = 0; 1856*35878b55SSascha Wildner i++; 1857*35878b55SSascha Wildner }while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 1858*35878b55SSascha Wildner 1859*35878b55SSascha Wildner pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable); 1860*35878b55SSascha Wildner if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) { 1861*35878b55SSascha Wildner pUdmaParams->numOfSectors = 0; 1862*35878b55SSascha Wildner } 1863*35878b55SSascha Wildner 1864*35878b55SSascha Wildner pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable; 1865*35878b55SSascha Wildner 1866*35878b55SSascha Wildner result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1867*35878b55SSascha Wildner 1868*35878b55SSascha Wildner if (result != MV_QUEUE_COMMAND_RESULT_OK) 1869*35878b55SSascha Wildner { 1870*35878b55SSascha Wildner queue_failed: 1871*35878b55SSascha Wildner switch (result) 1872*35878b55SSascha Wildner { 1873*35878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS: 1874*35878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA " 1875*35878b55SSascha Wildner "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress); 1876*35878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 1877*35878b55SSascha Wildner break; 1878*35878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED: 1879*35878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. EDMA" 1880*35878b55SSascha Wildner " disabled adapter %d channel %d\n", 1881*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 1882*35878b55SSascha Wildner mvSataEnableChannelDma(pMvSataAdapter,channel); 1883*35878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 1884*35878b55SSascha Wildner break; 1885*35878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_FULL: 1886*35878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. Queue is" 1887*35878b55SSascha Wildner " Full adapter %d channel %d\n", 1888*35878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 1889*35878b55SSascha Wildner pCmd->Result = RETURN_DEVICE_BUSY; 1890*35878b55SSascha Wildner break; 1891*35878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS: 1892*35878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. (Bad " 1893*35878b55SSascha Wildner "Params), pMvSataAdapter: %p, pSataChannel: %p.\n", 1894*35878b55SSascha Wildner pMvSataAdapter, pMvSataAdapter->sataChannel[channel]); 1895*35878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 1896*35878b55SSascha Wildner break; 1897*35878b55SSascha Wildner default: 1898*35878b55SSascha Wildner MV_ERROR("IAL Error: Bad result value (%d) from queue" 1899*35878b55SSascha Wildner " command\n", result); 1900*35878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 1901*35878b55SSascha Wildner } 1902*35878b55SSascha Wildner if(pPRDTable) 1903*35878b55SSascha Wildner FreePRDTable(pMvSataAdapter->IALData,pPRDTable); 1904*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1905*35878b55SSascha Wildner } 1906*35878b55SSascha Wildner pDevice->QueueLength++; 1907*35878b55SSascha Wildner return; 1908*35878b55SSascha Wildner 1909*35878b55SSascha Wildner case IDE_COMMAND_VERIFY: 1910*35878b55SSascha Wildner commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA; 1911*35878b55SSascha Wildner pNoUdmaParams->bufPtr = NULL; 1912*35878b55SSascha Wildner pNoUdmaParams->callBack = CommandCompletionCB; 1913*35878b55SSascha Wildner pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd; 1914*35878b55SSascha Wildner pNoUdmaParams->count = 0; 1915*35878b55SSascha Wildner pNoUdmaParams->features = 0; 1916*35878b55SSascha Wildner pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA; 1917*35878b55SSascha Wildner 1918*35878b55SSascha Wildner pCmd->uScratch.sata_param.cmd_priv = 1; 1919*35878b55SSascha Wildner if (pMvSataChannel->lba48Address == MV_TRUE){ 1920*35878b55SSascha Wildner pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; 1921*35878b55SSascha Wildner pNoUdmaParams->isEXT = MV_TRUE; 1922*35878b55SSascha Wildner pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 1923*35878b55SSascha Wildner pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 1924*35878b55SSascha Wildner pNoUdmaParams->lbaLow = 1925*35878b55SSascha Wildner (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); 1926*35878b55SSascha Wildner pNoUdmaParams->sectorCount = nSector; 1927*35878b55SSascha Wildner pNoUdmaParams->device = 0x40; 1928*35878b55SSascha Wildner result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1929*35878b55SSascha Wildner if (result != MV_QUEUE_COMMAND_RESULT_OK){ 1930*35878b55SSascha Wildner goto queue_failed; 1931*35878b55SSascha Wildner } 1932*35878b55SSascha Wildner return; 1933*35878b55SSascha Wildner } 1934*35878b55SSascha Wildner else{ 1935*35878b55SSascha Wildner pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; 1936*35878b55SSascha Wildner pNoUdmaParams->isEXT = MV_FALSE; 1937*35878b55SSascha Wildner pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 1938*35878b55SSascha Wildner pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 1939*35878b55SSascha Wildner pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); 1940*35878b55SSascha Wildner pNoUdmaParams->sectorCount = 0xff & nSector; 1941*35878b55SSascha Wildner pNoUdmaParams->device = (MV_U8)(0x40 | 1942*35878b55SSascha Wildner ((Lba & 0xf000000) >> 24)); 1943*35878b55SSascha Wildner pNoUdmaParams->callBack = CommandCompletionCB; 1944*35878b55SSascha Wildner result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1945*35878b55SSascha Wildner /*FIXME: how about the commands already queued? but marvel also forgets to consider this*/ 1946*35878b55SSascha Wildner if (result != MV_QUEUE_COMMAND_RESULT_OK){ 1947*35878b55SSascha Wildner goto queue_failed; 1948*35878b55SSascha Wildner } 1949*35878b55SSascha Wildner } 1950*35878b55SSascha Wildner break; 1951*35878b55SSascha Wildner default: 1952*35878b55SSascha Wildner pCmd->Result = RETURN_INVALID_REQUEST; 1953*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1954*35878b55SSascha Wildner break; 1955*35878b55SSascha Wildner } 1956*35878b55SSascha Wildner } 1957*35878b55SSascha Wildner 1958*35878b55SSascha Wildner /********************************************************** 1959*35878b55SSascha Wildner * 1960*35878b55SSascha Wildner * Probe the hostadapter. 1961*35878b55SSascha Wildner * 1962*35878b55SSascha Wildner **********************************************************/ 1963*35878b55SSascha Wildner static int 1964*35878b55SSascha Wildner hpt_probe(device_t dev) 1965*35878b55SSascha Wildner { 1966*35878b55SSascha Wildner if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) && 1967*35878b55SSascha Wildner (pci_get_device(dev) == MV_SATA_DEVICE_ID_5081 1968*35878b55SSascha Wildner #ifdef FOR_DEMO 1969*35878b55SSascha Wildner || pci_get_device(dev) == MV_SATA_DEVICE_ID_5080 1970*35878b55SSascha Wildner #endif 1971*35878b55SSascha Wildner )) 1972*35878b55SSascha Wildner { 1973*35878b55SSascha Wildner KdPrintI((CONTROLLER_NAME " found\n")); 1974*35878b55SSascha Wildner device_set_desc(dev, CONTROLLER_NAME); 1975*35878b55SSascha Wildner return 0; 1976*35878b55SSascha Wildner } 1977*35878b55SSascha Wildner else 1978*35878b55SSascha Wildner return(ENXIO); 1979*35878b55SSascha Wildner } 1980*35878b55SSascha Wildner 1981*35878b55SSascha Wildner /*********************************************************** 1982*35878b55SSascha Wildner * 1983*35878b55SSascha Wildner * Auto configuration: attach and init a host adapter. 1984*35878b55SSascha Wildner * 1985*35878b55SSascha Wildner ***********************************************************/ 1986*35878b55SSascha Wildner static int 1987*35878b55SSascha Wildner hpt_attach(device_t dev) 1988*35878b55SSascha Wildner { 1989*35878b55SSascha Wildner IAL_ADAPTER_T * pAdapter = device_get_softc(dev); 1990*35878b55SSascha Wildner int rid; 1991*35878b55SSascha Wildner union ccb *ccb; 1992*35878b55SSascha Wildner struct cam_devq *devq; 1993*35878b55SSascha Wildner struct cam_sim *hpt_vsim; 1994*35878b55SSascha Wildner 1995*35878b55SSascha Wildner kprintf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION); 1996*35878b55SSascha Wildner 1997*35878b55SSascha Wildner if (!pAdapter) 1998*35878b55SSascha Wildner { 1999*35878b55SSascha Wildner pAdapter = (IAL_ADAPTER_T *)kmalloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT); 2000*35878b55SSascha Wildner device_set_softc(dev, (void *)pAdapter); 2001*35878b55SSascha Wildner } 2002*35878b55SSascha Wildner 2003*35878b55SSascha Wildner if (!pAdapter) return (ENOMEM); 2004*35878b55SSascha Wildner bzero(pAdapter, sizeof(IAL_ADAPTER_T)); 2005*35878b55SSascha Wildner 2006*35878b55SSascha Wildner pAdapter->hpt_dev = dev; 2007*35878b55SSascha Wildner 2008*35878b55SSascha Wildner rid = init_adapter(pAdapter); 2009*35878b55SSascha Wildner if (rid) 2010*35878b55SSascha Wildner return rid; 2011*35878b55SSascha Wildner 2012*35878b55SSascha Wildner rid = 0; 2013*35878b55SSascha Wildner if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 2014*35878b55SSascha Wildner { 2015*35878b55SSascha Wildner hpt_printk(("can't allocate interrupt\n")); 2016*35878b55SSascha Wildner return(ENXIO); 2017*35878b55SSascha Wildner } 2018*35878b55SSascha Wildner 2019*35878b55SSascha Wildner if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, 0, 2020*35878b55SSascha Wildner hpt_intr, pAdapter, &pAdapter->hpt_intr, NULL)) 2021*35878b55SSascha Wildner { 2022*35878b55SSascha Wildner hpt_printk(("can't set up interrupt\n")); 2023*35878b55SSascha Wildner kfree(pAdapter, M_DEVBUF); 2024*35878b55SSascha Wildner return(ENXIO); 2025*35878b55SSascha Wildner } 2026*35878b55SSascha Wildner 2027*35878b55SSascha Wildner 2028*35878b55SSascha Wildner if((ccb = (union ccb *)kmalloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL) 2029*35878b55SSascha Wildner { 2030*35878b55SSascha Wildner bzero(ccb, sizeof(*ccb)); 2031*35878b55SSascha Wildner ccb->ccb_h.pinfo.priority = 1; 2032*35878b55SSascha Wildner ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; 2033*35878b55SSascha Wildner } 2034*35878b55SSascha Wildner else 2035*35878b55SSascha Wildner { 2036*35878b55SSascha Wildner return ENOMEM; 2037*35878b55SSascha Wildner } 2038*35878b55SSascha Wildner /* 2039*35878b55SSascha Wildner * Create the device queue for our SIM(s). 2040*35878b55SSascha Wildner */ 2041*35878b55SSascha Wildner if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) 2042*35878b55SSascha Wildner { 2043*35878b55SSascha Wildner KdPrint(("ENXIO\n")); 2044*35878b55SSascha Wildner return ENOMEM; 2045*35878b55SSascha Wildner } 2046*35878b55SSascha Wildner 2047*35878b55SSascha Wildner /* 2048*35878b55SSascha Wildner * Construct our SIM entry 2049*35878b55SSascha Wildner */ 2050*35878b55SSascha Wildner hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), 2051*35878b55SSascha Wildner pAdapter, device_get_unit(pAdapter->hpt_dev), &sim_mplock, 1, 8, devq); 2052*35878b55SSascha Wildner cam_simq_release(devq); 2053*35878b55SSascha Wildner if (hpt_vsim == NULL) { 2054*35878b55SSascha Wildner return ENOMEM; 2055*35878b55SSascha Wildner } 2056*35878b55SSascha Wildner 2057*35878b55SSascha Wildner if (xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS) 2058*35878b55SSascha Wildner { 2059*35878b55SSascha Wildner cam_sim_free(hpt_vsim); 2060*35878b55SSascha Wildner hpt_vsim = NULL; 2061*35878b55SSascha Wildner return ENXIO; 2062*35878b55SSascha Wildner } 2063*35878b55SSascha Wildner 2064*35878b55SSascha Wildner if(xpt_create_path(&pAdapter->path, /*periph */ NULL, 2065*35878b55SSascha Wildner cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, 2066*35878b55SSascha Wildner CAM_LUN_WILDCARD) != CAM_REQ_CMP) 2067*35878b55SSascha Wildner { 2068*35878b55SSascha Wildner xpt_bus_deregister(cam_sim_path(hpt_vsim)); 2069*35878b55SSascha Wildner cam_sim_free(hpt_vsim); 2070*35878b55SSascha Wildner hpt_vsim = NULL; 2071*35878b55SSascha Wildner return ENXIO; 2072*35878b55SSascha Wildner } 2073*35878b55SSascha Wildner 2074*35878b55SSascha Wildner xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5); 2075*35878b55SSascha Wildner ccb->ccb_h.func_code = XPT_SASYNC_CB; 2076*35878b55SSascha Wildner ccb->csa.event_enable = AC_LOST_DEVICE; 2077*35878b55SSascha Wildner ccb->csa.callback = hpt_async; 2078*35878b55SSascha Wildner ccb->csa.callback_arg = hpt_vsim; 2079*35878b55SSascha Wildner xpt_action((union ccb *)ccb); 2080*35878b55SSascha Wildner kfree(ccb, M_DEVBUF); 2081*35878b55SSascha Wildner 2082*35878b55SSascha Wildner callout_init(&pAdapter->event_timer_connect); 2083*35878b55SSascha Wildner callout_init(&pAdapter->event_timer_disconnect); 2084*35878b55SSascha Wildner 2085*35878b55SSascha Wildner if (device_get_unit(dev) == 0) { 2086*35878b55SSascha Wildner /* Start the work thread. XXX */ 2087*35878b55SSascha Wildner launch_worker_thread(); 2088*35878b55SSascha Wildner } 2089*35878b55SSascha Wildner 2090*35878b55SSascha Wildner return 0; 2091*35878b55SSascha Wildner } 2092*35878b55SSascha Wildner 2093*35878b55SSascha Wildner static int 2094*35878b55SSascha Wildner hpt_detach(device_t dev) 2095*35878b55SSascha Wildner { 2096*35878b55SSascha Wildner return (EBUSY); 2097*35878b55SSascha Wildner } 2098*35878b55SSascha Wildner 2099*35878b55SSascha Wildner 2100*35878b55SSascha Wildner /*************************************************************** 2101*35878b55SSascha Wildner * The poll function is used to simulate the interrupt when 2102*35878b55SSascha Wildner * the interrupt subsystem is not functioning. 2103*35878b55SSascha Wildner * 2104*35878b55SSascha Wildner ***************************************************************/ 2105*35878b55SSascha Wildner static void 2106*35878b55SSascha Wildner hpt_poll(struct cam_sim *sim) 2107*35878b55SSascha Wildner { 2108*35878b55SSascha Wildner hpt_intr((void *)cam_sim_softc(sim)); 2109*35878b55SSascha Wildner } 2110*35878b55SSascha Wildner 2111*35878b55SSascha Wildner /**************************************************************** 2112*35878b55SSascha Wildner * Name: hpt_intr 2113*35878b55SSascha Wildner * Description: Interrupt handler. 2114*35878b55SSascha Wildner ****************************************************************/ 2115*35878b55SSascha Wildner static void 2116*35878b55SSascha Wildner hpt_intr(void *arg) 2117*35878b55SSascha Wildner { 2118*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg; 2119*35878b55SSascha Wildner intrmask_t oldspl = lock_driver(); 2120*35878b55SSascha Wildner 2121*35878b55SSascha Wildner /* KdPrintI(("----- Entering Isr() -----\n")); */ 2122*35878b55SSascha Wildner if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE) 2123*35878b55SSascha Wildner { 2124*35878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 2125*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 2126*35878b55SSascha Wildner } 2127*35878b55SSascha Wildner 2128*35878b55SSascha Wildner /* KdPrintI(("----- Leaving Isr() -----\n")); */ 2129*35878b55SSascha Wildner unlock_driver(oldspl); 2130*35878b55SSascha Wildner } 2131*35878b55SSascha Wildner 2132*35878b55SSascha Wildner /********************************************************** 2133*35878b55SSascha Wildner * Asynchronous Events 2134*35878b55SSascha Wildner *********************************************************/ 2135*35878b55SSascha Wildner #if (!defined(UNREFERENCED_PARAMETER)) 2136*35878b55SSascha Wildner #define UNREFERENCED_PARAMETER(x) (void)(x) 2137*35878b55SSascha Wildner #endif 2138*35878b55SSascha Wildner 2139*35878b55SSascha Wildner static void 2140*35878b55SSascha Wildner hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, 2141*35878b55SSascha Wildner void * arg) 2142*35878b55SSascha Wildner { 2143*35878b55SSascha Wildner /* debug XXXX */ 2144*35878b55SSascha Wildner panic("Here"); 2145*35878b55SSascha Wildner UNREFERENCED_PARAMETER(callback_arg); 2146*35878b55SSascha Wildner UNREFERENCED_PARAMETER(code); 2147*35878b55SSascha Wildner UNREFERENCED_PARAMETER(path); 2148*35878b55SSascha Wildner UNREFERENCED_PARAMETER(arg); 2149*35878b55SSascha Wildner 2150*35878b55SSascha Wildner } 2151*35878b55SSascha Wildner 2152*35878b55SSascha Wildner static void 2153*35878b55SSascha Wildner FlushAdapter(IAL_ADAPTER_T *pAdapter) 2154*35878b55SSascha Wildner { 2155*35878b55SSascha Wildner int i; 2156*35878b55SSascha Wildner 2157*35878b55SSascha Wildner hpt_printk(("flush all devices\n")); 2158*35878b55SSascha Wildner 2159*35878b55SSascha Wildner /* flush all devices */ 2160*35878b55SSascha Wildner for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) { 2161*35878b55SSascha Wildner PVDevice pVDev = pAdapter->VBus.pVDevice[i]; 2162*35878b55SSascha Wildner if(pVDev) fFlushVDev(pVDev); 2163*35878b55SSascha Wildner } 2164*35878b55SSascha Wildner } 2165*35878b55SSascha Wildner 2166*35878b55SSascha Wildner static int 2167*35878b55SSascha Wildner hpt_shutdown(device_t dev) 2168*35878b55SSascha Wildner { 2169*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 2170*35878b55SSascha Wildner 2171*35878b55SSascha Wildner pAdapter = device_get_softc(dev); 2172*35878b55SSascha Wildner if (pAdapter == NULL) 2173*35878b55SSascha Wildner return (EINVAL); 2174*35878b55SSascha Wildner 2175*35878b55SSascha Wildner EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh); 2176*35878b55SSascha Wildner FlushAdapter(pAdapter); 2177*35878b55SSascha Wildner /* give the flush some time to happen, 2178*35878b55SSascha Wildner *otherwise "shutdown -p now" will make file system corrupted */ 2179*35878b55SSascha Wildner DELAY(1000 * 1000 * 5); 2180*35878b55SSascha Wildner return 0; 2181*35878b55SSascha Wildner } 2182*35878b55SSascha Wildner 2183*35878b55SSascha Wildner void 2184*35878b55SSascha Wildner Check_Idle_Call(IAL_ADAPTER_T *pAdapter) 2185*35878b55SSascha Wildner { 2186*35878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 2187*35878b55SSascha Wildner 2188*35878b55SSascha Wildner if (mWaitingForIdle(_VBUS_P0)) { 2189*35878b55SSascha Wildner CheckIdleCall(_VBUS_P0); 2190*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 2191*35878b55SSascha Wildner { 2192*35878b55SSascha Wildner int i; 2193*35878b55SSascha Wildner PVDevice pArray; 2194*35878b55SSascha Wildner for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ 2195*35878b55SSascha Wildner if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 2196*35878b55SSascha Wildner continue; 2197*35878b55SSascha Wildner else if (pArray->u.array.rf_auto_rebuild) { 2198*35878b55SSascha Wildner KdPrint(("auto rebuild.\n")); 2199*35878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 0; 2200*35878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 2201*35878b55SSascha Wildner } 2202*35878b55SSascha Wildner } 2203*35878b55SSascha Wildner } 2204*35878b55SSascha Wildner #endif 2205*35878b55SSascha Wildner } 2206*35878b55SSascha Wildner /* launch the awaiting commands blocked by mWaitingForIdle */ 2207*35878b55SSascha Wildner while(pAdapter->pending_Q!= NULL) 2208*35878b55SSascha Wildner { 2209*35878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 2210*35878b55SSascha Wildner union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; 2211*35878b55SSascha Wildner hpt_free_ccb(&pAdapter->pending_Q, ccb); 2212*35878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb); 2213*35878b55SSascha Wildner } 2214*35878b55SSascha Wildner } 2215*35878b55SSascha Wildner 2216*35878b55SSascha Wildner static void 2217*35878b55SSascha Wildner ccb_done(union ccb *ccb) 2218*35878b55SSascha Wildner { 2219*35878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2220*35878b55SSascha Wildner IAL_ADAPTER_T * pAdapter = pmap->pAdapter; 2221*35878b55SSascha Wildner KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status)); 2222*35878b55SSascha Wildner 2223*35878b55SSascha Wildner dmamap_put(pmap); 2224*35878b55SSascha Wildner xpt_done(ccb); 2225*35878b55SSascha Wildner 2226*35878b55SSascha Wildner pAdapter->outstandingCommands--; 2227*35878b55SSascha Wildner 2228*35878b55SSascha Wildner if (pAdapter->outstandingCommands == 0) 2229*35878b55SSascha Wildner { 2230*35878b55SSascha Wildner if(DPC_Request_Nums == 0) 2231*35878b55SSascha Wildner Check_Idle_Call(pAdapter); 2232*35878b55SSascha Wildner } 2233*35878b55SSascha Wildner } 2234*35878b55SSascha Wildner 2235*35878b55SSascha Wildner /**************************************************************** 2236*35878b55SSascha Wildner * Name: hpt_action 2237*35878b55SSascha Wildner * Description: Process a queued command from the CAM layer. 2238*35878b55SSascha Wildner * Parameters: sim - Pointer to SIM object 2239*35878b55SSascha Wildner * ccb - Pointer to SCSI command structure. 2240*35878b55SSascha Wildner ****************************************************************/ 2241*35878b55SSascha Wildner 2242*35878b55SSascha Wildner void 2243*35878b55SSascha Wildner hpt_action(struct cam_sim *sim, union ccb *ccb) 2244*35878b55SSascha Wildner { 2245*35878b55SSascha Wildner intrmask_t oldspl; 2246*35878b55SSascha Wildner IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim); 2247*35878b55SSascha Wildner PBUS_DMAMAP pmap; 2248*35878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 2249*35878b55SSascha Wildner 2250*35878b55SSascha Wildner CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n")); 2251*35878b55SSascha Wildner KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code)); 2252*35878b55SSascha Wildner 2253*35878b55SSascha Wildner switch (ccb->ccb_h.func_code) 2254*35878b55SSascha Wildner { 2255*35878b55SSascha Wildner case XPT_SCSI_IO: /* Execute the requested I/O operation */ 2256*35878b55SSascha Wildner { 2257*35878b55SSascha Wildner /* ccb->ccb_h.path_id is not our bus id - don't check it */ 2258*35878b55SSascha Wildner 2259*35878b55SSascha Wildner if (ccb->ccb_h.target_lun) { 2260*35878b55SSascha Wildner ccb->ccb_h.status = CAM_LUN_INVALID; 2261*35878b55SSascha Wildner xpt_done(ccb); 2262*35878b55SSascha Wildner return; 2263*35878b55SSascha Wildner } 2264*35878b55SSascha Wildner if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || 2265*35878b55SSascha Wildner pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { 2266*35878b55SSascha Wildner ccb->ccb_h.status = CAM_TID_INVALID; 2267*35878b55SSascha Wildner xpt_done(ccb); 2268*35878b55SSascha Wildner return; 2269*35878b55SSascha Wildner } 2270*35878b55SSascha Wildner 2271*35878b55SSascha Wildner oldspl = lock_driver(); 2272*35878b55SSascha Wildner if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 2273*35878b55SSascha Wildner Check_Idle_Call(pAdapter); 2274*35878b55SSascha Wildner 2275*35878b55SSascha Wildner pmap = dmamap_get(pAdapter); 2276*35878b55SSascha Wildner HPT_ASSERT(pmap); 2277*35878b55SSascha Wildner ccb->ccb_adapter = pmap; 2278*35878b55SSascha Wildner memset((void *)pmap->psg, 0, sizeof(pmap->psg)); 2279*35878b55SSascha Wildner 2280*35878b55SSascha Wildner if (mWaitingForIdle(_VBUS_P0)) 2281*35878b55SSascha Wildner hpt_queue_ccb(&pAdapter->pending_Q, ccb); 2282*35878b55SSascha Wildner else 2283*35878b55SSascha Wildner OsSendCommand(_VBUS_P ccb); 2284*35878b55SSascha Wildner unlock_driver(oldspl); 2285*35878b55SSascha Wildner 2286*35878b55SSascha Wildner /* KdPrint(("leave scsiio\n")); */ 2287*35878b55SSascha Wildner break; 2288*35878b55SSascha Wildner } 2289*35878b55SSascha Wildner 2290*35878b55SSascha Wildner case XPT_RESET_BUS: 2291*35878b55SSascha Wildner KdPrint(("reset bus\n")); 2292*35878b55SSascha Wildner oldspl = lock_driver(); 2293*35878b55SSascha Wildner fResetVBus(_VBUS_P0); 2294*35878b55SSascha Wildner unlock_driver(oldspl); 2295*35878b55SSascha Wildner xpt_done(ccb); 2296*35878b55SSascha Wildner break; 2297*35878b55SSascha Wildner 2298*35878b55SSascha Wildner case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 2299*35878b55SSascha Wildner case XPT_EN_LUN: /* Enable LUN as a target */ 2300*35878b55SSascha Wildner case XPT_TARGET_IO: /* Execute target I/O request */ 2301*35878b55SSascha Wildner case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 2302*35878b55SSascha Wildner case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 2303*35878b55SSascha Wildner case XPT_ABORT: /* Abort the specified CCB */ 2304*35878b55SSascha Wildner case XPT_TERM_IO: /* Terminate the I/O process */ 2305*35878b55SSascha Wildner /* XXX Implement */ 2306*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 2307*35878b55SSascha Wildner xpt_done(ccb); 2308*35878b55SSascha Wildner break; 2309*35878b55SSascha Wildner 2310*35878b55SSascha Wildner case XPT_GET_TRAN_SETTINGS: 2311*35878b55SSascha Wildner case XPT_SET_TRAN_SETTINGS: 2312*35878b55SSascha Wildner /* XXX Implement */ 2313*35878b55SSascha Wildner ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2314*35878b55SSascha Wildner xpt_done(ccb); 2315*35878b55SSascha Wildner break; 2316*35878b55SSascha Wildner 2317*35878b55SSascha Wildner case XPT_CALC_GEOMETRY: 2318*35878b55SSascha Wildner { 2319*35878b55SSascha Wildner struct ccb_calc_geometry *ccg; 2320*35878b55SSascha Wildner u_int32_t size_mb; 2321*35878b55SSascha Wildner u_int32_t secs_per_cylinder; 2322*35878b55SSascha Wildner 2323*35878b55SSascha Wildner ccg = &ccb->ccg; 2324*35878b55SSascha Wildner size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); 2325*35878b55SSascha Wildner 2326*35878b55SSascha Wildner if (size_mb > 1024 ) { 2327*35878b55SSascha Wildner ccg->heads = 255; 2328*35878b55SSascha Wildner ccg->secs_per_track = 63; 2329*35878b55SSascha Wildner } else { 2330*35878b55SSascha Wildner ccg->heads = 64; 2331*35878b55SSascha Wildner ccg->secs_per_track = 32; 2332*35878b55SSascha Wildner } 2333*35878b55SSascha Wildner secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2334*35878b55SSascha Wildner ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2335*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP; 2336*35878b55SSascha Wildner xpt_done(ccb); 2337*35878b55SSascha Wildner break; 2338*35878b55SSascha Wildner } 2339*35878b55SSascha Wildner 2340*35878b55SSascha Wildner case XPT_PATH_INQ: /* Path routing inquiry */ 2341*35878b55SSascha Wildner { 2342*35878b55SSascha Wildner struct ccb_pathinq *cpi = &ccb->cpi; 2343*35878b55SSascha Wildner 2344*35878b55SSascha Wildner cpi->version_num = 1; /* XXX??? */ 2345*35878b55SSascha Wildner cpi->hba_inquiry = PI_SDTR_ABLE; 2346*35878b55SSascha Wildner cpi->target_sprt = 0; 2347*35878b55SSascha Wildner /* Not necessary to reset bus */ 2348*35878b55SSascha Wildner cpi->hba_misc = PIM_NOBUSRESET; 2349*35878b55SSascha Wildner cpi->hba_eng_cnt = 0; 2350*35878b55SSascha Wildner 2351*35878b55SSascha Wildner cpi->max_target = MAX_VDEVICE_PER_VBUS; 2352*35878b55SSascha Wildner cpi->max_lun = 0; 2353*35878b55SSascha Wildner cpi->initiator_id = MAX_VDEVICE_PER_VBUS; 2354*35878b55SSascha Wildner 2355*35878b55SSascha Wildner cpi->bus_id = cam_sim_bus(sim); 2356*35878b55SSascha Wildner cpi->base_transfer_speed = 3300; 2357*35878b55SSascha Wildner strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2358*35878b55SSascha Wildner strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 2359*35878b55SSascha Wildner strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2360*35878b55SSascha Wildner cpi->unit_number = cam_sim_unit(sim); 2361*35878b55SSascha Wildner cpi->transport = XPORT_SPI; 2362*35878b55SSascha Wildner cpi->transport_version = 2; 2363*35878b55SSascha Wildner cpi->protocol = PROTO_SCSI; 2364*35878b55SSascha Wildner cpi->protocol_version = SCSI_REV_2; 2365*35878b55SSascha Wildner cpi->ccb_h.status = CAM_REQ_CMP; 2366*35878b55SSascha Wildner xpt_done(ccb); 2367*35878b55SSascha Wildner break; 2368*35878b55SSascha Wildner } 2369*35878b55SSascha Wildner 2370*35878b55SSascha Wildner default: 2371*35878b55SSascha Wildner KdPrint(("invalid cmd\n")); 2372*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 2373*35878b55SSascha Wildner xpt_done(ccb); 2374*35878b55SSascha Wildner break; 2375*35878b55SSascha Wildner } 2376*35878b55SSascha Wildner /* KdPrint(("leave hpt_action..............\n")); */ 2377*35878b55SSascha Wildner } 2378*35878b55SSascha Wildner 2379*35878b55SSascha Wildner /* shall be called at lock_driver() */ 2380*35878b55SSascha Wildner static void 2381*35878b55SSascha Wildner hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb) 2382*35878b55SSascha Wildner { 2383*35878b55SSascha Wildner if(*ccb_Q == NULL) 2384*35878b55SSascha Wildner ccb->ccb_h.ccb_ccb_ptr = ccb; 2385*35878b55SSascha Wildner else { 2386*35878b55SSascha Wildner ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr; 2387*35878b55SSascha Wildner (*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb; 2388*35878b55SSascha Wildner } 2389*35878b55SSascha Wildner 2390*35878b55SSascha Wildner *ccb_Q = ccb; 2391*35878b55SSascha Wildner } 2392*35878b55SSascha Wildner 2393*35878b55SSascha Wildner /* shall be called at lock_driver() */ 2394*35878b55SSascha Wildner static void 2395*35878b55SSascha Wildner hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb) 2396*35878b55SSascha Wildner { 2397*35878b55SSascha Wildner union ccb *TempCCB; 2398*35878b55SSascha Wildner 2399*35878b55SSascha Wildner TempCCB = *ccb_Q; 2400*35878b55SSascha Wildner 2401*35878b55SSascha Wildner if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/ 2402*35878b55SSascha Wildner *ccb_Q = NULL; 2403*35878b55SSascha Wildner else { 2404*35878b55SSascha Wildner while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb) 2405*35878b55SSascha Wildner TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr; 2406*35878b55SSascha Wildner 2407*35878b55SSascha Wildner TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr; 2408*35878b55SSascha Wildner 2409*35878b55SSascha Wildner if(*ccb_Q == ccb) 2410*35878b55SSascha Wildner *ccb_Q = TempCCB; 2411*35878b55SSascha Wildner } 2412*35878b55SSascha Wildner } 2413*35878b55SSascha Wildner 2414*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 2415*35878b55SSascha Wildner /*************************************************************************** 2416*35878b55SSascha Wildner * Function: hpt_worker_thread 2417*35878b55SSascha Wildner * Description: Do background rebuilding. Execute in kernel thread context. 2418*35878b55SSascha Wildner * Returns: None 2419*35878b55SSascha Wildner ***************************************************************************/ 2420*35878b55SSascha Wildner static void hpt_worker_thread(void) 2421*35878b55SSascha Wildner { 2422*35878b55SSascha Wildner intrmask_t oldspl; 2423*35878b55SSascha Wildner 2424*35878b55SSascha Wildner for(;;) { 2425*35878b55SSascha Wildner while (DpcQueue_First!=DpcQueue_Last) { 2426*35878b55SSascha Wildner ST_HPT_DPC p; 2427*35878b55SSascha Wildner oldspl = lock_driver(); 2428*35878b55SSascha Wildner p = DpcQueue[DpcQueue_First]; 2429*35878b55SSascha Wildner DpcQueue_First++; 2430*35878b55SSascha Wildner DpcQueue_First %= MAX_DPC; 2431*35878b55SSascha Wildner DPC_Request_Nums++; 2432*35878b55SSascha Wildner unlock_driver(oldspl); 2433*35878b55SSascha Wildner p.dpc(p.pAdapter, p.arg, p.flags); 2434*35878b55SSascha Wildner 2435*35878b55SSascha Wildner oldspl = lock_driver(); 2436*35878b55SSascha Wildner DPC_Request_Nums--; 2437*35878b55SSascha Wildner /* since we may have prevented Check_Idle_Call, do it here */ 2438*35878b55SSascha Wildner if (DPC_Request_Nums==0) { 2439*35878b55SSascha Wildner if (p.pAdapter->outstandingCommands == 0) { 2440*35878b55SSascha Wildner _VBUS_INST(&p.pAdapter->VBus); 2441*35878b55SSascha Wildner Check_Idle_Call(p.pAdapter); 2442*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 2443*35878b55SSascha Wildner } 2444*35878b55SSascha Wildner } 2445*35878b55SSascha Wildner unlock_driver(oldspl); 2446*35878b55SSascha Wildner 2447*35878b55SSascha Wildner /*Schedule out*/ 2448*35878b55SSascha Wildner tsleep((caddr_t)hpt_worker_thread, 0, "sched", 1); 2449*35878b55SSascha Wildner if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) { 2450*35878b55SSascha Wildner /* abort rebuilding process. */ 2451*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 2452*35878b55SSascha Wildner PVDevice pArray; 2453*35878b55SSascha Wildner PVBus _vbus_p; 2454*35878b55SSascha Wildner int i; 2455*35878b55SSascha Wildner pAdapter = gIal_Adapter; 2456*35878b55SSascha Wildner 2457*35878b55SSascha Wildner while(pAdapter != 0){ 2458*35878b55SSascha Wildner 2459*35878b55SSascha Wildner _vbus_p = &pAdapter->VBus; 2460*35878b55SSascha Wildner 2461*35878b55SSascha Wildner for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 2462*35878b55SSascha Wildner { 2463*35878b55SSascha Wildner if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 2464*35878b55SSascha Wildner continue; 2465*35878b55SSascha Wildner else if (pArray->u.array.rf_rebuilding || 2466*35878b55SSascha Wildner pArray->u.array.rf_verifying || 2467*35878b55SSascha Wildner pArray->u.array.rf_initializing) 2468*35878b55SSascha Wildner { 2469*35878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 1; 2470*35878b55SSascha Wildner } 2471*35878b55SSascha Wildner } 2472*35878b55SSascha Wildner pAdapter = pAdapter->next; 2473*35878b55SSascha Wildner } 2474*35878b55SSascha Wildner } 2475*35878b55SSascha Wildner } 2476*35878b55SSascha Wildner 2477*35878b55SSascha Wildner /*Remove this debug option*/ 2478*35878b55SSascha Wildner /* 2479*35878b55SSascha Wildner #ifdef DEBUG 2480*35878b55SSascha Wildner if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) 2481*35878b55SSascha Wildner tsleep((caddr_t)hpt_worker_thread, 0, "hptrdy", 2*hz); 2482*35878b55SSascha Wildner #endif 2483*35878b55SSascha Wildner */ 2484*35878b55SSascha Wildner kproc_suspend_loop(); 2485*35878b55SSascha Wildner tsleep((caddr_t)hpt_worker_thread, 0, "hptrdy", 2*hz); /* wait for something to do */ 2486*35878b55SSascha Wildner } 2487*35878b55SSascha Wildner } 2488*35878b55SSascha Wildner 2489*35878b55SSascha Wildner static struct thread *hptdaemonproc; 2490*35878b55SSascha Wildner static struct kproc_desc hpt_kp = { 2491*35878b55SSascha Wildner "hpt_wt", 2492*35878b55SSascha Wildner hpt_worker_thread, 2493*35878b55SSascha Wildner &hptdaemonproc 2494*35878b55SSascha Wildner }; 2495*35878b55SSascha Wildner 2496*35878b55SSascha Wildner /*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/ 2497*35878b55SSascha Wildner static void 2498*35878b55SSascha Wildner launch_worker_thread(void) 2499*35878b55SSascha Wildner { 2500*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 2501*35878b55SSascha Wildner 2502*35878b55SSascha Wildner kproc_start(&hpt_kp); 2503*35878b55SSascha Wildner 2504*35878b55SSascha Wildner for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 2505*35878b55SSascha Wildner 2506*35878b55SSascha Wildner _VBUS_INST(&pAdapTemp->VBus) 2507*35878b55SSascha Wildner int i; 2508*35878b55SSascha Wildner PVDevice pVDev; 2509*35878b55SSascha Wildner 2510*35878b55SSascha Wildner for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 2511*35878b55SSascha Wildner if ((pVDev=ArrayTables(i))->u.array.dArStamp==0) 2512*35878b55SSascha Wildner continue; 2513*35878b55SSascha Wildner else{ 2514*35878b55SSascha Wildner if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding) 2515*35878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev, 2516*35878b55SSascha Wildner (UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 2517*35878b55SSascha Wildner } 2518*35878b55SSascha Wildner } 2519*35878b55SSascha Wildner 2520*35878b55SSascha Wildner /* 2521*35878b55SSascha Wildner * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished. 2522*35878b55SSascha Wildner */ 2523*35878b55SSascha Wildner EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST); 2524*35878b55SSascha Wildner } 2525*35878b55SSascha Wildner /* 2526*35878b55SSascha Wildner *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL); 2527*35878b55SSascha Wildner */ 2528*35878b55SSascha Wildner 2529*35878b55SSascha Wildner #endif 2530*35878b55SSascha Wildner 2531*35878b55SSascha Wildner /********************************************************************************/ 2532*35878b55SSascha Wildner 2533*35878b55SSascha Wildner int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) 2534*35878b55SSascha Wildner { 2535*35878b55SSascha Wildner union ccb *ccb = (union ccb *)pCmd->pOrgCommand; 2536*35878b55SSascha Wildner bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 2537*35878b55SSascha Wildner int idx; 2538*35878b55SSascha Wildner 2539*35878b55SSascha Wildner if(logical) { 2540*35878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_DATA_PHYS) 2541*35878b55SSascha Wildner panic("physical address unsupported"); 2542*35878b55SSascha Wildner 2543*35878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2544*35878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 2545*35878b55SSascha Wildner panic("physical address unsupported"); 2546*35878b55SSascha Wildner 2547*35878b55SSascha Wildner for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 2548*35878b55SSascha Wildner pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 2549*35878b55SSascha Wildner pSg[idx].wSgSize = sgList[idx].ds_len; 2550*35878b55SSascha Wildner pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0; 2551*35878b55SSascha Wildner } 2552*35878b55SSascha Wildner } 2553*35878b55SSascha Wildner else { 2554*35878b55SSascha Wildner pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; 2555*35878b55SSascha Wildner pSg->wSgSize = ccb->csio.dxfer_len; 2556*35878b55SSascha Wildner pSg->wSgFlag = SG_FLAG_EOT; 2557*35878b55SSascha Wildner } 2558*35878b55SSascha Wildner return TRUE; 2559*35878b55SSascha Wildner } 2560*35878b55SSascha Wildner 2561*35878b55SSascha Wildner /* since we have provided physical sg, nobody will ask us to build physical sg */ 2562*35878b55SSascha Wildner HPT_ASSERT(0); 2563*35878b55SSascha Wildner return FALSE; 2564*35878b55SSascha Wildner } 2565*35878b55SSascha Wildner 2566*35878b55SSascha Wildner /*******************************************************************************/ 2567*35878b55SSascha Wildner ULONG HPTLIBAPI 2568*35878b55SSascha Wildner GetStamp(void) 2569*35878b55SSascha Wildner { 2570*35878b55SSascha Wildner /* 2571*35878b55SSascha Wildner * the system variable, ticks, can't be used since it hasn't yet been active 2572*35878b55SSascha Wildner * when our driver starts (ticks==0, it's a invalid stamp value) 2573*35878b55SSascha Wildner */ 2574*35878b55SSascha Wildner ULONG stamp; 2575*35878b55SSascha Wildner do { stamp = krandom(); } while (stamp==0); 2576*35878b55SSascha Wildner return stamp; 2577*35878b55SSascha Wildner } 2578*35878b55SSascha Wildner 2579*35878b55SSascha Wildner 2580*35878b55SSascha Wildner static void 2581*35878b55SSascha Wildner SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) 2582*35878b55SSascha Wildner { 2583*35878b55SSascha Wildner int i; 2584*35878b55SSascha Wildner IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; 2585*35878b55SSascha Wildner 2586*35878b55SSascha Wildner inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/ 2587*35878b55SSascha Wildner inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5); 2588*35878b55SSascha Wildner #ifndef SERIAL_CMDS 2589*35878b55SSascha Wildner inquiryData->CommandQueue = 1; 2590*35878b55SSascha Wildner #endif 2591*35878b55SSascha Wildner 2592*35878b55SSascha Wildner switch(pVDev->VDeviceType) { 2593*35878b55SSascha Wildner case VD_SINGLE_DISK: 2594*35878b55SSascha Wildner case VD_ATAPI: 2595*35878b55SSascha Wildner case VD_REMOVABLE: 2596*35878b55SSascha Wildner /* Set the removable bit, if applicable. */ 2597*35878b55SSascha Wildner if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80)) 2598*35878b55SSascha Wildner inquiryData->RemovableMedia = 1; 2599*35878b55SSascha Wildner 2600*35878b55SSascha Wildner /* Fill in vendor identification fields. */ 2601*35878b55SSascha Wildner for (i = 0; i < 20; i += 2) { 2602*35878b55SSascha Wildner inquiryData->VendorId[i] = ((PUCHAR)pIdentify->ModelNumber)[i + 1]; 2603*35878b55SSascha Wildner inquiryData->VendorId[i+1] = ((PUCHAR)pIdentify->ModelNumber)[i]; 2604*35878b55SSascha Wildner 2605*35878b55SSascha Wildner } 2606*35878b55SSascha Wildner 2607*35878b55SSascha Wildner /* Initialize unused portion of product id. */ 2608*35878b55SSascha Wildner for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' '; 2609*35878b55SSascha Wildner 2610*35878b55SSascha Wildner /* firmware revision */ 2611*35878b55SSascha Wildner for (i = 0; i < 4; i += 2) 2612*35878b55SSascha Wildner { 2613*35878b55SSascha Wildner inquiryData->ProductRevisionLevel[i] = ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; 2614*35878b55SSascha Wildner inquiryData->ProductRevisionLevel[i+1] = ((PUCHAR)pIdentify->FirmwareRevision)[i]; 2615*35878b55SSascha Wildner } 2616*35878b55SSascha Wildner break; 2617*35878b55SSascha Wildner default: 2618*35878b55SSascha Wildner memcpy(&inquiryData->VendorId, "RR18xx ", 8); 2619*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY 2620*35878b55SSascha Wildner switch(pVDev->VDeviceType){ 2621*35878b55SSascha Wildner case VD_RAID_0: 2622*35878b55SSascha Wildner if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2623*35878b55SSascha Wildner (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2624*35878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 1/0 Array ", 16); 2625*35878b55SSascha Wildner else 2626*35878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 0 Array ", 16); 2627*35878b55SSascha Wildner break; 2628*35878b55SSascha Wildner case VD_RAID_1: 2629*35878b55SSascha Wildner if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2630*35878b55SSascha Wildner (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2631*35878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 0/1 Array ", 16); 2632*35878b55SSascha Wildner else 2633*35878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 1 Array ", 16); 2634*35878b55SSascha Wildner break; 2635*35878b55SSascha Wildner case VD_RAID_5: 2636*35878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 5 Array ", 16); 2637*35878b55SSascha Wildner break; 2638*35878b55SSascha Wildner case VD_JBOD: 2639*35878b55SSascha Wildner memcpy(&inquiryData->ProductId, "JBOD Array ", 16); 2640*35878b55SSascha Wildner break; 2641*35878b55SSascha Wildner } 2642*35878b55SSascha Wildner #endif 2643*35878b55SSascha Wildner memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4); 2644*35878b55SSascha Wildner break; 2645*35878b55SSascha Wildner } 2646*35878b55SSascha Wildner } 2647*35878b55SSascha Wildner 2648*35878b55SSascha Wildner static void 2649*35878b55SSascha Wildner hpt_timeout(void *arg) 2650*35878b55SSascha Wildner { 2651*35878b55SSascha Wildner _VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus) 2652*35878b55SSascha Wildner intrmask_t oldspl = lock_driver(); 2653*35878b55SSascha Wildner fResetVBus(_VBUS_P0); 2654*35878b55SSascha Wildner unlock_driver(oldspl); 2655*35878b55SSascha Wildner } 2656*35878b55SSascha Wildner 2657*35878b55SSascha Wildner static void 2658*35878b55SSascha Wildner hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 2659*35878b55SSascha Wildner { 2660*35878b55SSascha Wildner PCommand pCmd = (PCommand)arg; 2661*35878b55SSascha Wildner union ccb *ccb = pCmd->pOrgCommand; 2662*35878b55SSascha Wildner struct ccb_hdr *ccb_h = &ccb->ccb_h; 2663*35878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter; 2664*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2665*35878b55SSascha Wildner PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2666*35878b55SSascha Wildner FPSCAT_GATH psg = pCmd->pSgTable; 2667*35878b55SSascha Wildner int idx; 2668*35878b55SSascha Wildner _VBUS_INST(pVDev->pVBus) 2669*35878b55SSascha Wildner 2670*35878b55SSascha Wildner HPT_ASSERT(pCmd->cf_physical_sg); 2671*35878b55SSascha Wildner 2672*35878b55SSascha Wildner if (error || nsegs == 0) 2673*35878b55SSascha Wildner panic("busdma error"); 2674*35878b55SSascha Wildner 2675*35878b55SSascha Wildner HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); 2676*35878b55SSascha Wildner 2677*35878b55SSascha Wildner for (idx = 0; idx < nsegs; idx++, psg++) { 2678*35878b55SSascha Wildner psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; 2679*35878b55SSascha Wildner psg->wSgSize = segs[idx].ds_len; 2680*35878b55SSascha Wildner psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; 2681*35878b55SSascha Wildner /* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ 2682*35878b55SSascha Wildner } 2683*35878b55SSascha Wildner /* psg[-1].wSgFlag = SG_FLAG_EOT; */ 2684*35878b55SSascha Wildner 2685*35878b55SSascha Wildner if (pCmd->cf_data_in) { 2686*35878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD); 2687*35878b55SSascha Wildner } 2688*35878b55SSascha Wildner else if (pCmd->cf_data_out) { 2689*35878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE); 2690*35878b55SSascha Wildner } 2691*35878b55SSascha Wildner 2692*35878b55SSascha Wildner callout_reset(&ccb->ccb_h.timeout_ch, 20*hz, hpt_timeout, ccb); 2693*35878b55SSascha Wildner pVDev->pfnSendCommand(_VBUS_P pCmd); 2694*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 2695*35878b55SSascha Wildner } 2696*35878b55SSascha Wildner 2697*35878b55SSascha Wildner 2698*35878b55SSascha Wildner 2699*35878b55SSascha Wildner static void HPTLIBAPI 2700*35878b55SSascha Wildner OsSendCommand(_VBUS_ARG union ccb *ccb) 2701*35878b55SSascha Wildner { 2702*35878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2703*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2704*35878b55SSascha Wildner struct ccb_hdr *ccb_h = &ccb->ccb_h; 2705*35878b55SSascha Wildner struct ccb_scsiio *csio = &ccb->csio; 2706*35878b55SSascha Wildner PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2707*35878b55SSascha Wildner 2708*35878b55SSascha Wildner KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", 2709*35878b55SSascha Wildner ccb, 2710*35878b55SSascha Wildner *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0], 2711*35878b55SSascha Wildner *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4], 2712*35878b55SSascha Wildner *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8] 2713*35878b55SSascha Wildner )); 2714*35878b55SSascha Wildner 2715*35878b55SSascha Wildner pAdapter->outstandingCommands++; 2716*35878b55SSascha Wildner 2717*35878b55SSascha Wildner if (pVDev == NULL || pVDev->vf_online == 0) { 2718*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 2719*35878b55SSascha Wildner ccb_done(ccb); 2720*35878b55SSascha Wildner goto Command_Complished; 2721*35878b55SSascha Wildner } 2722*35878b55SSascha Wildner 2723*35878b55SSascha Wildner switch(ccb->csio.cdb_io.cdb_bytes[0]) 2724*35878b55SSascha Wildner { 2725*35878b55SSascha Wildner case TEST_UNIT_READY: 2726*35878b55SSascha Wildner case START_STOP_UNIT: 2727*35878b55SSascha Wildner case SYNCHRONIZE_CACHE: 2728*35878b55SSascha Wildner /* FALLTHROUGH */ 2729*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP; 2730*35878b55SSascha Wildner break; 2731*35878b55SSascha Wildner 2732*35878b55SSascha Wildner case INQUIRY: 2733*35878b55SSascha Wildner ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); 2734*35878b55SSascha Wildner SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); 2735*35878b55SSascha Wildner ccb_h->status = CAM_REQ_CMP; 2736*35878b55SSascha Wildner break; 2737*35878b55SSascha Wildner 2738*35878b55SSascha Wildner case READ_CAPACITY: 2739*35878b55SSascha Wildner { 2740*35878b55SSascha Wildner UCHAR *rbuf=csio->data_ptr; 2741*35878b55SSascha Wildner unsigned int cap; 2742*35878b55SSascha Wildner 2743*35878b55SSascha Wildner if (pVDev->VDeviceCapacity > 0xfffffffful) { 2744*35878b55SSascha Wildner cap = 0xfffffffful; 2745*35878b55SSascha Wildner } else { 2746*35878b55SSascha Wildner cap = pVDev->VDeviceCapacity - 1; 2747*35878b55SSascha Wildner } 2748*35878b55SSascha Wildner 2749*35878b55SSascha Wildner rbuf[0] = (UCHAR)(cap>>24); 2750*35878b55SSascha Wildner rbuf[1] = (UCHAR)(cap>>16); 2751*35878b55SSascha Wildner rbuf[2] = (UCHAR)(cap>>8); 2752*35878b55SSascha Wildner rbuf[3] = (UCHAR)cap; 2753*35878b55SSascha Wildner /* Claim 512 byte blocks (big-endian). */ 2754*35878b55SSascha Wildner rbuf[4] = 0; 2755*35878b55SSascha Wildner rbuf[5] = 0; 2756*35878b55SSascha Wildner rbuf[6] = 2; 2757*35878b55SSascha Wildner rbuf[7] = 0; 2758*35878b55SSascha Wildner 2759*35878b55SSascha Wildner ccb_h->status = CAM_REQ_CMP; 2760*35878b55SSascha Wildner break; 2761*35878b55SSascha Wildner } 2762*35878b55SSascha Wildner 2763*35878b55SSascha Wildner case 0x9e: /*SERVICE_ACTION_IN*/ 2764*35878b55SSascha Wildner { 2765*35878b55SSascha Wildner UCHAR *rbuf = csio->data_ptr; 2766*35878b55SSascha Wildner LBA_T cap = pVDev->VDeviceCapacity - 1; 2767*35878b55SSascha Wildner 2768*35878b55SSascha Wildner rbuf[0] = (UCHAR)(cap>>56); 2769*35878b55SSascha Wildner rbuf[1] = (UCHAR)(cap>>48); 2770*35878b55SSascha Wildner rbuf[2] = (UCHAR)(cap>>40); 2771*35878b55SSascha Wildner rbuf[3] = (UCHAR)(cap>>32); 2772*35878b55SSascha Wildner rbuf[4] = (UCHAR)(cap>>24); 2773*35878b55SSascha Wildner rbuf[5] = (UCHAR)(cap>>16); 2774*35878b55SSascha Wildner rbuf[6] = (UCHAR)(cap>>8); 2775*35878b55SSascha Wildner rbuf[7] = (UCHAR)cap; 2776*35878b55SSascha Wildner rbuf[8] = 0; 2777*35878b55SSascha Wildner rbuf[9] = 0; 2778*35878b55SSascha Wildner rbuf[10] = 2; 2779*35878b55SSascha Wildner rbuf[11] = 0; 2780*35878b55SSascha Wildner 2781*35878b55SSascha Wildner ccb_h->status = CAM_REQ_CMP; 2782*35878b55SSascha Wildner break; 2783*35878b55SSascha Wildner } 2784*35878b55SSascha Wildner 2785*35878b55SSascha Wildner case READ_6: 2786*35878b55SSascha Wildner case WRITE_6: 2787*35878b55SSascha Wildner case READ_10: 2788*35878b55SSascha Wildner case WRITE_10: 2789*35878b55SSascha Wildner case 0x88: /* READ_16 */ 2790*35878b55SSascha Wildner case 0x8a: /* WRITE_16 */ 2791*35878b55SSascha Wildner case 0x13: 2792*35878b55SSascha Wildner case 0x2f: 2793*35878b55SSascha Wildner { 2794*35878b55SSascha Wildner UCHAR Cdb[16]; 2795*35878b55SSascha Wildner UCHAR CdbLength; 2796*35878b55SSascha Wildner _VBUS_INST(pVDev->pVBus) 2797*35878b55SSascha Wildner PCommand pCmd = AllocateCommand(_VBUS_P0); 2798*35878b55SSascha Wildner HPT_ASSERT(pCmd); 2799*35878b55SSascha Wildner 2800*35878b55SSascha Wildner CdbLength = csio->cdb_len; 2801*35878b55SSascha Wildner if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) 2802*35878b55SSascha Wildner { 2803*35878b55SSascha Wildner if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) 2804*35878b55SSascha Wildner { 2805*35878b55SSascha Wildner bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); 2806*35878b55SSascha Wildner } 2807*35878b55SSascha Wildner else 2808*35878b55SSascha Wildner { 2809*35878b55SSascha Wildner KdPrintE(("ERROR!!!\n")); 2810*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 2811*35878b55SSascha Wildner break; 2812*35878b55SSascha Wildner } 2813*35878b55SSascha Wildner } 2814*35878b55SSascha Wildner else 2815*35878b55SSascha Wildner { 2816*35878b55SSascha Wildner bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); 2817*35878b55SSascha Wildner } 2818*35878b55SSascha Wildner 2819*35878b55SSascha Wildner pCmd->pOrgCommand = ccb; 2820*35878b55SSascha Wildner pCmd->pVDevice = pVDev; 2821*35878b55SSascha Wildner pCmd->pfnCompletion = fOsCommandDone; 2822*35878b55SSascha Wildner pCmd->pfnBuildSgl = fOsBuildSgl; 2823*35878b55SSascha Wildner pCmd->pSgTable = pmap->psg; 2824*35878b55SSascha Wildner 2825*35878b55SSascha Wildner switch (Cdb[0]) 2826*35878b55SSascha Wildner { 2827*35878b55SSascha Wildner case READ_6: 2828*35878b55SSascha Wildner case WRITE_6: 2829*35878b55SSascha Wildner case 0x13: 2830*35878b55SSascha Wildner pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; 2831*35878b55SSascha Wildner pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; 2832*35878b55SSascha Wildner break; 2833*35878b55SSascha Wildner 2834*35878b55SSascha Wildner case 0x88: /* READ_16 */ 2835*35878b55SSascha Wildner case 0x8a: /* WRITE_16 */ 2836*35878b55SSascha Wildner pCmd->uCmd.Ide.Lba = 2837*35878b55SSascha Wildner (HPT_U64)Cdb[2] << 56 | 2838*35878b55SSascha Wildner (HPT_U64)Cdb[3] << 48 | 2839*35878b55SSascha Wildner (HPT_U64)Cdb[4] << 40 | 2840*35878b55SSascha Wildner (HPT_U64)Cdb[5] << 32 | 2841*35878b55SSascha Wildner (HPT_U64)Cdb[6] << 24 | 2842*35878b55SSascha Wildner (HPT_U64)Cdb[7] << 16 | 2843*35878b55SSascha Wildner (HPT_U64)Cdb[8] << 8 | 2844*35878b55SSascha Wildner (HPT_U64)Cdb[9]; 2845*35878b55SSascha Wildner pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13]; 2846*35878b55SSascha Wildner break; 2847*35878b55SSascha Wildner 2848*35878b55SSascha Wildner default: 2849*35878b55SSascha Wildner pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24); 2850*35878b55SSascha Wildner pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8); 2851*35878b55SSascha Wildner break; 2852*35878b55SSascha Wildner } 2853*35878b55SSascha Wildner 2854*35878b55SSascha Wildner switch (Cdb[0]) 2855*35878b55SSascha Wildner { 2856*35878b55SSascha Wildner case READ_6: 2857*35878b55SSascha Wildner case READ_10: 2858*35878b55SSascha Wildner case 0x88: /* READ_16 */ 2859*35878b55SSascha Wildner pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; 2860*35878b55SSascha Wildner pCmd->cf_data_in = 1; 2861*35878b55SSascha Wildner break; 2862*35878b55SSascha Wildner 2863*35878b55SSascha Wildner case WRITE_6: 2864*35878b55SSascha Wildner case WRITE_10: 2865*35878b55SSascha Wildner case 0x8a: /* WRITE_16 */ 2866*35878b55SSascha Wildner pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; 2867*35878b55SSascha Wildner pCmd->cf_data_out = 1; 2868*35878b55SSascha Wildner break; 2869*35878b55SSascha Wildner case 0x13: 2870*35878b55SSascha Wildner case 0x2f: 2871*35878b55SSascha Wildner pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; 2872*35878b55SSascha Wildner break; 2873*35878b55SSascha Wildner } 2874*35878b55SSascha Wildner /*///////////////////////// */ 2875*35878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2876*35878b55SSascha Wildner int idx; 2877*35878b55SSascha Wildner bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 2878*35878b55SSascha Wildner 2879*35878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 2880*35878b55SSascha Wildner pCmd->cf_physical_sg = 1; 2881*35878b55SSascha Wildner 2882*35878b55SSascha Wildner for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 2883*35878b55SSascha Wildner pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 2884*35878b55SSascha Wildner pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len; 2885*35878b55SSascha Wildner pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0; 2886*35878b55SSascha Wildner } 2887*35878b55SSascha Wildner 2888*35878b55SSascha Wildner callout_reset(&ccb->ccb_h.timeout_ch, 20*hz, hpt_timeout, ccb); 2889*35878b55SSascha Wildner pVDev->pfnSendCommand(_VBUS_P pCmd); 2890*35878b55SSascha Wildner } 2891*35878b55SSascha Wildner else { 2892*35878b55SSascha Wildner int error; 2893*35878b55SSascha Wildner pCmd->cf_physical_sg = 1; 2894*35878b55SSascha Wildner error = bus_dmamap_load(pAdapter->io_dma_parent, 2895*35878b55SSascha Wildner pmap->dma_map, 2896*35878b55SSascha Wildner ccb->csio.data_ptr, ccb->csio.dxfer_len, 2897*35878b55SSascha Wildner hpt_io_dmamap_callback, pCmd, 2898*35878b55SSascha Wildner BUS_DMA_WAITOK 2899*35878b55SSascha Wildner ); 2900*35878b55SSascha Wildner KdPrint(("bus_dmamap_load return %d\n", error)); 2901*35878b55SSascha Wildner if (error && error!=EINPROGRESS) { 2902*35878b55SSascha Wildner hpt_printk(("bus_dmamap_load error %d\n", error)); 2903*35878b55SSascha Wildner FreeCommand(_VBUS_P pCmd); 2904*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2905*35878b55SSascha Wildner dmamap_put(pmap); 2906*35878b55SSascha Wildner pAdapter->outstandingCommands--; 2907*35878b55SSascha Wildner xpt_done(ccb); 2908*35878b55SSascha Wildner } 2909*35878b55SSascha Wildner } 2910*35878b55SSascha Wildner goto Command_Complished; 2911*35878b55SSascha Wildner } 2912*35878b55SSascha Wildner 2913*35878b55SSascha Wildner default: 2914*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 2915*35878b55SSascha Wildner break; 2916*35878b55SSascha Wildner } 2917*35878b55SSascha Wildner ccb_done(ccb); 2918*35878b55SSascha Wildner Command_Complished: 2919*35878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 2920*35878b55SSascha Wildner return; 2921*35878b55SSascha Wildner } 2922*35878b55SSascha Wildner 2923*35878b55SSascha Wildner static void HPTLIBAPI 2924*35878b55SSascha Wildner fOsCommandDone(_VBUS_ARG PCommand pCmd) 2925*35878b55SSascha Wildner { 2926*35878b55SSascha Wildner union ccb *ccb = pCmd->pOrgCommand; 2927*35878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2928*35878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2929*35878b55SSascha Wildner 2930*35878b55SSascha Wildner KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result)); 2931*35878b55SSascha Wildner 2932*35878b55SSascha Wildner callout_stop(&ccb->ccb_h.timeout_ch); 2933*35878b55SSascha Wildner 2934*35878b55SSascha Wildner switch(pCmd->Result) { 2935*35878b55SSascha Wildner case RETURN_SUCCESS: 2936*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP; 2937*35878b55SSascha Wildner break; 2938*35878b55SSascha Wildner case RETURN_BAD_DEVICE: 2939*35878b55SSascha Wildner ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2940*35878b55SSascha Wildner break; 2941*35878b55SSascha Wildner case RETURN_DEVICE_BUSY: 2942*35878b55SSascha Wildner ccb->ccb_h.status = CAM_BUSY; 2943*35878b55SSascha Wildner break; 2944*35878b55SSascha Wildner case RETURN_INVALID_REQUEST: 2945*35878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 2946*35878b55SSascha Wildner break; 2947*35878b55SSascha Wildner case RETURN_SELECTION_TIMEOUT: 2948*35878b55SSascha Wildner ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2949*35878b55SSascha Wildner break; 2950*35878b55SSascha Wildner case RETURN_RETRY: 2951*35878b55SSascha Wildner ccb->ccb_h.status = CAM_BUSY; 2952*35878b55SSascha Wildner break; 2953*35878b55SSascha Wildner default: 2954*35878b55SSascha Wildner ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2955*35878b55SSascha Wildner break; 2956*35878b55SSascha Wildner } 2957*35878b55SSascha Wildner 2958*35878b55SSascha Wildner if (pCmd->cf_data_in) { 2959*35878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD); 2960*35878b55SSascha Wildner } 2961*35878b55SSascha Wildner else if (pCmd->cf_data_in) { 2962*35878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE); 2963*35878b55SSascha Wildner } 2964*35878b55SSascha Wildner 2965*35878b55SSascha Wildner bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map); 2966*35878b55SSascha Wildner 2967*35878b55SSascha Wildner FreeCommand(_VBUS_P pCmd); 2968*35878b55SSascha Wildner ccb_done(ccb); 2969*35878b55SSascha Wildner } 2970*35878b55SSascha Wildner 2971*35878b55SSascha Wildner int 2972*35878b55SSascha Wildner hpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags) 2973*35878b55SSascha Wildner { 2974*35878b55SSascha Wildner int p; 2975*35878b55SSascha Wildner 2976*35878b55SSascha Wildner p = (DpcQueue_Last + 1) % MAX_DPC; 2977*35878b55SSascha Wildner if (p==DpcQueue_First) { 2978*35878b55SSascha Wildner KdPrint(("DPC Queue full!\n")); 2979*35878b55SSascha Wildner return -1; 2980*35878b55SSascha Wildner } 2981*35878b55SSascha Wildner 2982*35878b55SSascha Wildner DpcQueue[DpcQueue_Last].dpc = dpc; 2983*35878b55SSascha Wildner DpcQueue[DpcQueue_Last].pAdapter = pAdapter; 2984*35878b55SSascha Wildner DpcQueue[DpcQueue_Last].arg = arg; 2985*35878b55SSascha Wildner DpcQueue[DpcQueue_Last].flags = flags; 2986*35878b55SSascha Wildner DpcQueue_Last = p; 2987*35878b55SSascha Wildner 2988*35878b55SSascha Wildner return 0; 2989*35878b55SSascha Wildner } 2990*35878b55SSascha Wildner 2991*35878b55SSascha Wildner #ifdef _RAID5N_ 2992*35878b55SSascha Wildner /* 2993*35878b55SSascha Wildner * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices. 2994*35878b55SSascha Wildner * How about the memory for 5081 request/response array and PRD table? 2995*35878b55SSascha Wildner */ 2996*35878b55SSascha Wildner void 2997*35878b55SSascha Wildner *os_alloc_page(_VBUS_ARG0) 2998*35878b55SSascha Wildner { 2999*35878b55SSascha Wildner return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 3000*35878b55SSascha Wildner } 3001*35878b55SSascha Wildner 3002*35878b55SSascha Wildner void 3003*35878b55SSascha Wildner *os_alloc_dma_page(_VBUS_ARG0) 3004*35878b55SSascha Wildner { 3005*35878b55SSascha Wildner return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 3006*35878b55SSascha Wildner } 3007*35878b55SSascha Wildner 3008*35878b55SSascha Wildner void 3009*35878b55SSascha Wildner os_free_page(_VBUS_ARG void *p) 3010*35878b55SSascha Wildner { 3011*35878b55SSascha Wildner contigfree(p, 0x1000, M_DEVBUF); 3012*35878b55SSascha Wildner } 3013*35878b55SSascha Wildner 3014*35878b55SSascha Wildner void 3015*35878b55SSascha Wildner os_free_dma_page(_VBUS_ARG void *p) 3016*35878b55SSascha Wildner { 3017*35878b55SSascha Wildner contigfree(p, 0x1000, M_DEVBUF); 3018*35878b55SSascha Wildner } 3019*35878b55SSascha Wildner 3020*35878b55SSascha Wildner void 3021*35878b55SSascha Wildner DoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes) 3022*35878b55SSascha Wildner { 3023*35878b55SSascha Wildner UINT i; 3024*35878b55SSascha Wildner for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++; 3025*35878b55SSascha Wildner } 3026*35878b55SSascha Wildner 3027*35878b55SSascha Wildner void 3028*35878b55SSascha Wildner DoXor2(ULONG *p0, ULONG *p2, UINT nBytes) 3029*35878b55SSascha Wildner { 3030*35878b55SSascha Wildner UINT i; 3031*35878b55SSascha Wildner for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++; 3032*35878b55SSascha Wildner } 3033*35878b55SSascha Wildner #endif 3034