entry.c revision 240210
1149871Sscottl/* 2149871Sscottl * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 3136849Sscottl * All rights reserved. 4136849Sscottl * 5136849Sscottl * Redistribution and use in source and binary forms, with or without 6136849Sscottl * modification, are permitted provided that the following conditions 7136849Sscottl * are met: 8136849Sscottl * 1. Redistributions of source code must retain the above copyright 9136849Sscottl * notice, this list of conditions and the following disclaimer. 10136849Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11136849Sscottl * notice, this list of conditions and the following disclaimer in the 12136849Sscottl * documentation and/or other materials provided with the distribution. 13136849Sscottl * 14136849Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15136849Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16136849Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17136849Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18136849Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19136849Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20136849Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21136849Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22136849Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23136849Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24136849Sscottl * SUCH DAMAGE. 25136849Sscottl */ 26227912Smarius 27227912Smarius#include <sys/cdefs.h> 28227912Smarius__FBSDID("$FreeBSD: head/sys/dev/hptmv/entry.c 240210 2012-09-07 19:00:27Z delphij $"); 29149871Sscottl 30136849Sscottl#include <sys/param.h> 31136849Sscottl#include <sys/systm.h> 32136849Sscottl#include <sys/kernel.h> 33136849Sscottl#include <sys/bus.h> 34136849Sscottl#include <sys/malloc.h> 35136849Sscottl#include <sys/resource.h> 36136849Sscottl#include <sys/time.h> 37136849Sscottl#include <sys/callout.h> 38136849Sscottl#include <sys/signalvar.h> 39136849Sscottl#include <sys/eventhandler.h> 40136849Sscottl#include <sys/proc.h> 41136849Sscottl#include <sys/kthread.h> 42136849Sscottl 43149871Sscottl#if (__FreeBSD_version >= 500000) 44149871Sscottl#include <sys/mutex.h> 45149871Sscottl#include <sys/module.h> 46149871Sscottl#endif 47149871Sscottl 48149871Sscottl#if (__FreeBSD_version >= 500000) 49136849Sscottl#include <dev/pci/pcireg.h> 50136849Sscottl#include <dev/pci/pcivar.h> 51149871Sscottl#else 52149871Sscottl#include <pci/pcireg.h> 53149871Sscottl#include <pci/pcivar.h> 54149871Sscottl#include <sys/wait.h> 55149871Sscottl#include <sys/sysproto.h> 56149871Sscottl#endif 57136849Sscottl 58149871Sscottl#ifndef __KERNEL__ 59149871Sscottl#define __KERNEL__ 60149871Sscottl#endif 61149871Sscottl 62136849Sscottl#include <dev/hptmv/global.h> 63136849Sscottl#include <dev/hptmv/hptintf.h> 64136849Sscottl#include <dev/hptmv/osbsd.h> 65143039Sscottl#include <dev/hptmv/access601.h> 66136849Sscottl 67149871Sscottl 68136849Sscottl#ifdef DEBUG 69136849Sscottl#ifdef DEBUG_LEVEL 70136849Sscottlint hpt_dbg_level = DEBUG_LEVEL; 71149871Sscottl#else 72136849Sscottlint hpt_dbg_level = 0; 73136849Sscottl#endif 74136849Sscottl#endif 75136849Sscottl 76136849Sscottl#define MV_ERROR printf 77149871Sscottl 78136849Sscottl/* 79136849Sscottl * CAM SIM entry points 80136849Sscottl */ 81149871Sscottlstatic int hpt_probe (device_t dev); 82149871Sscottlstatic void launch_worker_thread(void); 83149871Sscottlstatic int hpt_attach(device_t dev); 84149871Sscottlstatic int hpt_detach(device_t dev); 85149871Sscottlstatic int hpt_shutdown(device_t dev); 86149871Sscottlstatic void hpt_poll(struct cam_sim *sim); 87149871Sscottlstatic void hpt_intr(void *arg); 88149871Sscottlstatic void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); 89149871Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb); 90149871Sscottl 91149871Sscottlstatic device_method_t driver_methods[] = { 92149871Sscottl /* Device interface */ 93149871Sscottl DEVMETHOD(device_probe, hpt_probe), 94149871Sscottl DEVMETHOD(device_attach, hpt_attach), 95149871Sscottl DEVMETHOD(device_detach, hpt_detach), 96149871Sscottl 97190863Sdelphij DEVMETHOD(device_shutdown, hpt_shutdown), 98227912Smarius DEVMETHOD_END 99149871Sscottl}; 100149871Sscottl 101149871Sscottlstatic driver_t hpt_pci_driver = { 102149871Sscottl __str(PROC_DIR_NAME), 103149871Sscottl driver_methods, 104149871Sscottl sizeof(IAL_ADAPTER_T) 105149871Sscottl}; 106149871Sscottl 107149871Sscottlstatic devclass_t hpt_devclass; 108149871Sscottl 109149871Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 110149871Sscottl__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 111236379SeadlerMODULE_DEPEND(PROC_DIR_NAME, cam, 1, 1, 1); 112149871Sscottl 113149871Sscottl#define ccb_ccb_ptr spriv_ptr0 114149871Sscottl#define ccb_adapter ccb_h.spriv_ptr1 115149871Sscottl 116149871Sscottlstatic void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); 117149871Sscottlstatic void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); 118149871Sscottlstatic void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); 119149871Sscottlstatic void ccb_done(union ccb *ccb); 120149871Sscottlstatic void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); 121149871Sscottlstatic void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); 122136849Sscottlstatic void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter); 123136849Sscottlstatic void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 124136849Sscottlstatic void handleEdmaError(_VBUS_ARG PCommand pCmd); 125136849Sscottlstatic int hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 126136849Sscottlstatic int fResetActiveCommands(PVBus _vbus_p); 127136849Sscottlstatic void fRegisterVdevice(IAL_ADAPTER_T *pAdapter); 128136849Sscottlstatic int hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter); 129136849Sscottlstatic void hptmv_handle_event_disconnect(void *data); 130136849Sscottlstatic void hptmv_handle_event_connect(void *data); 131136849Sscottlstatic int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 132136849Sscottlstatic void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel); 133136849Sscottlstatic int hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel); 134136849Sscottlstatic int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, 135136849Sscottl int logical); 136136849Sscottlstatic MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 137136849Sscottl MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId, 138136849Sscottl MV_U16 responseFlags, MV_U32 timeStamp, 139136849Sscottl MV_STORAGE_DEVICE_REGISTERS *registerStruct); 140136849Sscottlstatic MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, 141136849Sscottl MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2); 142136849Sscottl 143136849Sscottl#define ccb_ccb_ptr spriv_ptr0 144136849Sscottl#define ccb_adapter ccb_h.spriv_ptr1 145136849Sscottl 146136849SscottlIAL_ADAPTER_T *gIal_Adapter = 0; 147136849SscottlIAL_ADAPTER_T *pCurAdapter = 0; 148149871Sscottlstatic MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; 149136849Sscottl 150136849Sscottltypedef struct st_HPT_DPC { 151136849Sscottl IAL_ADAPTER_T *pAdapter; 152136849Sscottl void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR); 153136849Sscottl void *arg; 154136849Sscottl UCHAR flags; 155136849Sscottl} ST_HPT_DPC; 156136849Sscottl 157136849Sscottl#define MAX_DPC 16 158136849SscottlUCHAR DPC_Request_Nums = 0; 159136849Sscottlstatic ST_HPT_DPC DpcQueue[MAX_DPC]; 160136849Sscottlstatic int DpcQueue_First=0; 161136849Sscottlstatic int DpcQueue_Last = 0; 162136849Sscottl 163190809Sdelphijchar DRIVER_VERSION[] = "v1.16"; 164136849Sscottl 165149871Sscottl#if (__FreeBSD_version >= 500000) 166149871Sscottlstatic struct mtx driver_lock; 167149871Sscottlintrmask_t lock_driver() 168149871Sscottl{ 169136849Sscottl 170149871Sscottl intrmask_t spl = 0; 171165774Sjhb mtx_lock(&driver_lock); 172149871Sscottl return spl; 173149871Sscottl} 174149871Sscottlvoid unlock_driver(intrmask_t spl) 175136849Sscottl{ 176165774Sjhb mtx_unlock(&driver_lock); 177149871Sscottl} 178149871Sscottl#else 179149871Sscottlstatic int driver_locked = 0; 180149871Sscottlintrmask_t lock_driver() 181149871Sscottl{ 182136849Sscottl intrmask_t spl = splcam(); 183149871Sscottlloop: 184149871Sscottl while (driver_locked) 185149871Sscottl tsleep(&driver_locked, PRIBIO, "hptlck", hz); 186149871Sscottl atomic_add_int(&driver_locked, 1); 187149871Sscottl if (driver_locked>1) { 188149871Sscottl atomic_subtract_int(&driver_locked, 1); 189149871Sscottl goto loop; 190149871Sscottl } 191136849Sscottl return spl; 192136849Sscottl} 193136849Sscottl 194149871Sscottlvoid unlock_driver(intrmask_t spl) 195136849Sscottl{ 196149871Sscottl atomic_subtract_int(&driver_locked, 1); 197149871Sscottl if (driver_locked==0) { 198149871Sscottl wakeup(&driver_locked); 199149871Sscottl } 200136849Sscottl splx(spl); 201136849Sscottl} 202149871Sscottl#endif 203136849Sscottl 204136849Sscottl/******************************************************************************* 205136849Sscottl * Name: hptmv_free_channel 206136849Sscottl * 207136849Sscottl * Description: free allocated queues for the given channel 208136849Sscottl * 209190809Sdelphij * Parameters: pMvSataAdapter - pointer to the RR18xx controler this 210136849Sscottl * channel connected to. 211136849Sscottl * channelNum - channel number. 212136849Sscottl * 213136849Sscottl ******************************************************************************/ 214136849Sscottlstatic void 215136849Sscottlhptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 216136849Sscottl{ 217136849Sscottl HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM); 218136849Sscottl pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL; 219149871Sscottl} 220136849Sscottl 221149871Sscottlstatic void failDevice(PVDevice pVDev) 222149871Sscottl{ 223149871Sscottl PVBus _vbus_p = pVDev->pVBus; 224149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 225149871Sscottl 226149871Sscottl pVDev->u.disk.df_on_line = 0; 227149871Sscottl pVDev->vf_online = 0; 228149871Sscottl if (pVDev->pfnDeviceFailed) 229149871Sscottl CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev); 230149871Sscottl 231149871Sscottl fNotifyGUI(ET_DEVICE_REMOVED, pVDev); 232149871Sscottl 233149871Sscottl#ifndef FOR_DEMO 234149871Sscottl if (pAdapter->ver_601==2 && !pAdapter->beeping) { 235149871Sscottl pAdapter->beeping = 1; 236149871Sscottl BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); 237149871Sscottl set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1); 238136849Sscottl } 239149871Sscottl#endif 240136849Sscottl} 241136849Sscottl 242136849Sscottlint MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel); 243136849Sscottl 244136849Sscottlstatic void 245136849SscottlhandleEdmaError(_VBUS_ARG PCommand pCmd) 246136849Sscottl{ 247136849Sscottl PDevice pDevice = &pCmd->pVDevice->u.disk; 248136849Sscottl MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter; 249136849Sscottl 250136849Sscottl if (!pDevice->df_on_line) { 251136849Sscottl KdPrint(("Device is offline")); 252136849Sscottl pCmd->Result = RETURN_BAD_DEVICE; 253136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 254136849Sscottl return; 255136849Sscottl } 256136849Sscottl 257136849Sscottl if (pCmd->RetryCount++>5) { 258149871Sscottl hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber)); 259149871Sscottlfailed: 260149871Sscottl failDevice(pCmd->pVDevice); 261136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 262136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 263136849Sscottl return; 264136849Sscottl } 265149871Sscottl 266149871Sscottl /* reset the channel and retry the command */ 267149871Sscottl if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber)) 268149871Sscottl goto failed; 269149871Sscottl 270149871Sscottl fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice)); 271149871Sscottl 272149871Sscottl hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber)); 273136849Sscottl fDeviceSendCommand(_VBUS_P pCmd); 274136849Sscottl} 275136849Sscottl 276136849Sscottl/**************************************************************** 277136849Sscottl * Name: hptmv_init_channel 278136849Sscottl * 279149871Sscottl * Description: allocate request and response queues for the EDMA of the 280149871Sscottl * given channel and sets other fields. 281149871Sscottl * 282136849Sscottl * Parameters: 283136849Sscottl * pAdapter - pointer to the emulated adapter data structure 284136849Sscottl * channelNum - channel number. 285136849Sscottl * Return: 0 on success, otherwise on failure 286136849Sscottl ****************************************************************/ 287136849Sscottlstatic int 288136849Sscottlhptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 289136849Sscottl{ 290136849Sscottl MV_SATA_CHANNEL *pMvSataChannel; 291136849Sscottl dma_addr_t req_dma_addr; 292136849Sscottl dma_addr_t rsp_dma_addr; 293136849Sscottl 294136849Sscottl if (channelNum >= MV_SATA_CHANNELS_NUM) 295136849Sscottl { 296190809Sdelphij MV_ERROR("RR18xx[%d]: Bad channelNum=%d", 297136849Sscottl pAdapter->mvSataAdapter.adapterId, channelNum); 298136849Sscottl return -1; 299136849Sscottl } 300136849Sscottl 301149871Sscottl pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; 302136849Sscottl pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel; 303136849Sscottl pMvSataChannel->channelNumber = channelNum; 304136849Sscottl pMvSataChannel->lba48Address = MV_FALSE; 305136849Sscottl pMvSataChannel->maxReadTransfer = MV_FALSE; 306136849Sscottl 307149871Sscottl pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *) 308149871Sscottl (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); 309149871Sscottl req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); 310136849Sscottl 311136849Sscottl 312149871Sscottl KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr)); 313136849Sscottl 314136849Sscottl /* check the 1K alignment of the request queue*/ 315136849Sscottl if (req_dma_addr & 0x3ff) 316136849Sscottl { 317190809Sdelphij MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned," 318149871Sscottl " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId, 319149871Sscottl (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum); 320136849Sscottl return -1; 321136849Sscottl } 322136849Sscottl pMvSataChannel->requestQueuePciLowAddress = req_dma_addr; 323136849Sscottl pMvSataChannel->requestQueuePciHiAddress = 0; 324190809Sdelphij KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p", 325149871Sscottl pAdapter->mvSataAdapter.adapterId, channelNum, 326149871Sscottl pMvSataChannel->requestQueue)); 327149871Sscottl pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) 328149871Sscottl (pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); 329149871Sscottl rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); 330136849Sscottl 331136849Sscottl /* check the 256 alignment of the response queue*/ 332136849Sscottl if (rsp_dma_addr & 0xff) 333136849Sscottl { 334190809Sdelphij MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte " 335149871Sscottl "aligned, dma_addr=%llx\n", 336149871Sscottl pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr); 337136849Sscottl return -1; 338136849Sscottl } 339136849Sscottl pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr; 340136849Sscottl pMvSataChannel->responseQueuePciHiAddress = 0; 341190809Sdelphij KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p", 342149871Sscottl pAdapter->mvSataAdapter.adapterId, channelNum, 343149871Sscottl pMvSataChannel->responseQueue)); 344136849Sscottl 345136849Sscottl pAdapter->mvChannel[channelNum].online = MV_TRUE; 346136849Sscottl return 0; 347136849Sscottl} 348136849Sscottl 349136849Sscottl/****************************************************************************** 350136849Sscottl * Name: hptmv_parse_identify_results 351136849Sscottl * 352149871Sscottl * Description: this functions parses the identify command results, checks 353190809Sdelphij * that the connected deives can be accesed by RR18xx EDMA, 354149871Sscottl * and updates the channel stucture accordingly. 355149871Sscottl * 356136849Sscottl * Parameters: pMvSataChannel, pointer to the channel data structure. 357136849Sscottl * 358136849Sscottl * Returns: =0 ->success, < 0 ->failure. 359136849Sscottl * 360136849Sscottl ******************************************************************************/ 361136849Sscottlstatic int 362136849Sscottlhptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) 363136849Sscottl{ 364136849Sscottl MV_U16 *iden = pMvSataChannel->identifyDevice; 365136849Sscottl 366136849Sscottl /*LBA addressing*/ 367149871Sscottl if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) 368149871Sscottl { 369136849Sscottl KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n")); 370136849Sscottl return -1; 371149871Sscottl } 372149871Sscottl else 373149871Sscottl { 374136849Sscottl KdPrint(("%25s - %s\n", "Capabilities", "LBA supported")); 375136849Sscottl } 376136849Sscottl /*DMA support*/ 377149871Sscottl if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) 378149871Sscottl { 379136849Sscottl KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n")); 380136849Sscottl return -1; 381149871Sscottl } 382149871Sscottl else 383149871Sscottl { 384136849Sscottl KdPrint(("%25s - %s\n", "Capabilities", "DMA supported")); 385136849Sscottl } 386136849Sscottl /* PIO */ 387149871Sscottl if ((iden[IDEN_VALID] & 2) == 0) 388149871Sscottl { 389149871Sscottl KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n")); 390136849Sscottl return -1; 391136849Sscottl } 392136849Sscottl KdPrint(("%25s - 0x%02x\n", "PIO modes supported", 393136849Sscottl iden[IDEN_PIO_MODE_SPPORTED] & 0xff)); 394136849Sscottl 395136849Sscottl /*UDMA*/ 396149871Sscottl if ((iden[IDEN_VALID] & 4) == 0) 397149871Sscottl { 398149871Sscottl KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n")); 399136849Sscottl return -1; 400136849Sscottl } 401136849Sscottl 402136849Sscottl /* 48 bit address */ 403149871Sscottl if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) 404149871Sscottl { 405136849Sscottl KdPrint(("%25s - %s\n", "LBA48 addressing", "supported")); 406136849Sscottl pMvSataChannel->lba48Address = MV_TRUE; 407149871Sscottl } 408149871Sscottl else 409149871Sscottl { 410136849Sscottl KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported")); 411136849Sscottl pMvSataChannel->lba48Address = MV_FALSE; 412136849Sscottl } 413136849Sscottl return 0; 414136849Sscottl} 415136849Sscottl 416136849Sscottlstatic void 417136849Sscottlinit_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) 418136849Sscottl{ 419149871Sscottl PVDevice pVDev = &pAdapter->VDevices[channel]; 420149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; 421149871Sscottl MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice; 422136849Sscottl 423136849Sscottl pMvSataChannel->outstandingCommands = 0; 424136849Sscottl 425136849Sscottl pVDev->u.disk.mv = pMvSataChannel; 426136849Sscottl pVDev->u.disk.df_on_line = 1; 427136849Sscottl pVDev->u.disk.pVBus = &pAdapter->VBus; 428136849Sscottl pVDev->pVBus = &pAdapter->VBus; 429136849Sscottl 430136849Sscottl#ifdef SUPPORT_48BIT_LBA 431136849Sscottl if (pMvSataChannel->lba48Address == MV_TRUE) 432149871Sscottl pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; 433136849Sscottl else 434136849Sscottl#endif 435136849Sscottl if(IdentifyData[53] & 1) { 436149871Sscottl pVDev->u.disk.dDeRealCapacity = 437149871Sscottl (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ? 438149871Sscottl (IdentifyData[61]<<16 | IdentifyData[60]) : 439149871Sscottl (IdentifyData[58]<<16 | IdentifyData[57])) - 1; 440136849Sscottl } else 441136849Sscottl pVDev->u.disk.dDeRealCapacity = 442149871Sscottl (IdentifyData[61]<<16 | IdentifyData[60]) - 1; 443136849Sscottl 444136849Sscottl pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 445149871Sscottl pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0; 446136849Sscottl 447136849Sscottl if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) { 448136849Sscottl pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 449149871Sscottl pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8; 450136849Sscottl } 451136849Sscottl} 452136849Sscottl 453149871Sscottlstatic void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) 454136849Sscottl{ 455136849Sscottl PVDevice pVDev; 456149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 457149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; 458149871Sscottl 459149871Sscottl if (!pMvSataChannel) return; 460136849Sscottl 461149871Sscottl if (plugged) 462149871Sscottl { 463136849Sscottl pVDev = &(pAdapter->VDevices[channelIndex]); 464136849Sscottl init_vdev_params(pAdapter, channelIndex); 465136849Sscottl 466149871Sscottl pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI : 467149871Sscottl pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 468136849Sscottl 469149871Sscottl pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO; 470136849Sscottl pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 471136849Sscottl pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 472136849Sscottl pVDev->vf_online = 1; 473136849Sscottl 474136849Sscottl#ifdef SUPPORT_ARRAY 475149871Sscottl if(pVDev->pParent) 476149871Sscottl { 477136849Sscottl int iMember; 478149871Sscottl for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++) 479149871Sscottl if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) 480136849Sscottl pVDev->pParent->u.array.pMember[iMember] = NULL; 481136849Sscottl pVDev->pParent = NULL; 482136849Sscottl } 483136849Sscottl#endif 484136849Sscottl fNotifyGUI(ET_DEVICE_PLUGGED,pVDev); 485136849Sscottl fCheckBootable(pVDev); 486136849Sscottl RegisterVDevice(pVDev); 487136849Sscottl 488136849Sscottl#ifndef FOR_DEMO 489136849Sscottl if (pAdapter->beeping) { 490136849Sscottl pAdapter->beeping = 0; 491136849Sscottl BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 492136849Sscottl } 493136849Sscottl#endif 494136849Sscottl 495149871Sscottl } 496149871Sscottl else 497149871Sscottl { 498136849Sscottl pVDev = &(pAdapter->VDevices[channelIndex]); 499149871Sscottl failDevice(pVDev); 500136849Sscottl } 501136849Sscottl} 502136849Sscottl 503136849Sscottlstatic int 504136849Sscottlstart_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 505136849Sscottl{ 506149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 507149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; 508149871Sscottl MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]); 509149871Sscottl MV_U32 udmaMode,pioMode; 510136849Sscottl 511190809Sdelphij KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId, 512149871Sscottl channelNum)); 513136849Sscottl 514136849Sscottl 515136849Sscottl /* Software reset channel */ 516149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 517149871Sscottl { 518190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 519149871Sscottl pMvSataAdapter->adapterId, channelNum); 520136849Sscottl return -1; 521136849Sscottl } 522136849Sscottl 523136849Sscottl /* Hardware reset channel */ 524149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 525149871Sscottl { 526149871Sscottl /* If failed, try again - this is when trying to hardreset a channel */ 527149871Sscottl /* when drive is just spinning up */ 528136849Sscottl StallExec(5000000); /* wait 5 sec before trying again */ 529149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 530149871Sscottl { 531190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n", 532149871Sscottl pMvSataAdapter->adapterId, channelNum); 533136849Sscottl return -1; 534136849Sscottl } 535136849Sscottl } 536136849Sscottl 537136849Sscottl /* identify device*/ 538149871Sscottl if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE) 539149871Sscottl { 540190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n" 541149871Sscottl , pMvSataAdapter->adapterId, channelNum); 542136849Sscottl return -1; 543136849Sscottl } 544149871Sscottl if (hptmv_parse_identify_results(pMvSataChannel)) 545149871Sscottl { 546190809Sdelphij MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n" 547149871Sscottl , pMvSataAdapter->adapterId, channelNum); 548136849Sscottl return -1; 549136849Sscottl } 550136849Sscottl 551136849Sscottl /* mvStorageDevATASetFeatures */ 552136849Sscottl /* Disable 8 bit PIO in case CFA enabled */ 553149871Sscottl if (pMvSataChannel->identifyDevice[86] & 4) 554149871Sscottl { 555190809Sdelphij KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n", 556149871Sscottl pMvSataAdapter->adapterId)); 557136849Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 558149871Sscottl MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, 559149871Sscottl 0, 0, 0) == MV_FALSE) 560149871Sscottl { 561190809Sdelphij MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures" 562149871Sscottl " failed\n", pMvSataAdapter->adapterId, channelNum); 563136849Sscottl return -1; 564136849Sscottl } 565136849Sscottl } 566149871Sscottl /* Write cache */ 567136849Sscottl#ifdef ENABLE_WRITE_CACHE 568149871Sscottl if (pMvSataChannel->identifyDevice[82] & 0x20) 569149871Sscottl { 570149871Sscottl if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */ 571149871Sscottl { 572149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 573149871Sscottl MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 574149871Sscottl 0, 0, 0) == MV_FALSE) 575149871Sscottl { 576190809Sdelphij MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 577149871Sscottl pMvSataAdapter->adapterId, channelNum); 578136849Sscottl return -1; 579136849Sscottl } 580136849Sscottl } 581190809Sdelphij KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n", 582149871Sscottl pMvSataAdapter->adapterId, channelNum)); 583149871Sscottl } 584149871Sscottl else 585149871Sscottl { 586190809Sdelphij KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n", 587149871Sscottl pMvSataAdapter->adapterId, channelNum)); 588136849Sscottl } 589149871Sscottl#else /* disable write cache */ 590149871Sscottl { 591149871Sscottl if (pMvSataChannel->identifyDevice[85] & 0x20) 592149871Sscottl { 593190809Sdelphij KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n", 594149871Sscottl pMvSataAdapter->adapterId, channelNum)); 595149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 596149871Sscottl MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 597149871Sscottl 0, 0, 0) == MV_FALSE) 598149871Sscottl { 599190809Sdelphij MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 600149871Sscottl pMvSataAdapter->adapterId, channelNum); 601149871Sscottl return -1; 602149871Sscottl } 603136849Sscottl } 604190809Sdelphij KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n", 605149871Sscottl pMvSataAdapter->adapterId, channelNum)); 606136849Sscottl } 607136849Sscottl#endif 608136849Sscottl 609136849Sscottl /* Set transfer mode */ 610190809Sdelphij KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n", 611149871Sscottl pMvSataAdapter->adapterId)); 612136849Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 613149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 614149871Sscottl MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == 615149871Sscottl MV_FALSE) 616149871Sscottl { 617190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 618149871Sscottl pMvSataAdapter->adapterId, channelNum); 619136849Sscottl return -1; 620136849Sscottl } 621136849Sscottl 622149871Sscottl if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) 623149871Sscottl { 624136849Sscottl pioMode = MV_ATA_TRANSFER_PIO_4; 625149871Sscottl } 626149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) 627149871Sscottl { 628136849Sscottl pioMode = MV_ATA_TRANSFER_PIO_3; 629149871Sscottl } 630149871Sscottl else 631149871Sscottl { 632149871Sscottl MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n"); 633136849Sscottl pioMode = MV_ATA_TRANSFER_PIO_SLOW; 634136849Sscottl } 635136849Sscottl 636190809Sdelphij KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n", 637149871Sscottl pMvSataAdapter->adapterId)); 638136849Sscottl pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode; 639136849Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 640149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 641149871Sscottl pioMode, 0, 0, 0) == MV_FALSE) 642149871Sscottl { 643190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 644149871Sscottl pMvSataAdapter->adapterId, channelNum); 645136849Sscottl return -1; 646136849Sscottl } 647136849Sscottl 648136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_0; 649149871Sscottl if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) 650149871Sscottl { 651136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_6; 652149871Sscottl } 653149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) 654149871Sscottl { 655136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_5; 656149871Sscottl } 657149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) 658149871Sscottl { 659136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_4; 660149871Sscottl } 661149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) 662149871Sscottl { 663136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_3; 664149871Sscottl } 665149871Sscottl else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) 666149871Sscottl { 667136849Sscottl udmaMode = MV_ATA_TRANSFER_UDMA_2; 668136849Sscottl } 669136849Sscottl 670190809Sdelphij KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n", 671149871Sscottl pMvSataAdapter->adapterId, udmaMode & 0xf)); 672136849Sscottl pChannelInfo->maxUltraDmaModeSupported = udmaMode; 673136849Sscottl 674149871Sscottl /*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 675149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, udmaMode, 676149871Sscottl 0, 0, 0) == MV_FALSE) 677149871Sscottl { 678190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 679149871Sscottl pMvSataAdapter->adapterId, channelNum); 680136849Sscottl return -1; 681149871Sscottl }*/ 682136849Sscottl if (pChannelInfo->maxUltraDmaModeSupported == 0xFF) 683136849Sscottl return TRUE; 684149871Sscottl else 685149871Sscottl do 686149871Sscottl { 687149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 688149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 689149871Sscottl pChannelInfo->maxUltraDmaModeSupported, 690149871Sscottl 0, 0, 0) == MV_FALSE) 691149871Sscottl { 692149871Sscottl if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0) 693149871Sscottl { 694149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 695149871Sscottl { 696149871Sscottl MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress, 697149871Sscottl pMvSataChannel->eDmaRegsOffset + 698149871Sscottl 0x11c, /* command reg */ 699149871Sscottl MV_ATA_COMMAND_IDLE_IMMEDIATE); 700149871Sscottl mvMicroSecondsDelay(10000); 701149871Sscottl mvSataChannelHardReset(pMvSataAdapter, channelNum); 702149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 703149871Sscottl return FALSE; 704149871Sscottl } 705149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 706149871Sscottl return FALSE; 707149871Sscottl pChannelInfo->maxUltraDmaModeSupported--; 708149871Sscottl continue; 709149871Sscottl } 710149871Sscottl else return FALSE; 711149871Sscottl } 712136849Sscottl break; 713149871Sscottl }while (1); 714136849Sscottl 715149871Sscottl /* Read look ahead */ 716136849Sscottl#ifdef ENABLE_READ_AHEAD 717149871Sscottl if (pMvSataChannel->identifyDevice[82] & 0x40) 718149871Sscottl { 719149871Sscottl if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */ 720149871Sscottl { 721149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 722149871Sscottl MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 723149871Sscottl 0, 0) == MV_FALSE) 724149871Sscottl { 725190809Sdelphij MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 726149871Sscottl pMvSataAdapter->adapterId, channelNum); 727136849Sscottl return -1; 728136849Sscottl } 729136849Sscottl } 730190809Sdelphij KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n", 731149871Sscottl pMvSataAdapter->adapterId, channelNum)); 732136849Sscottl } 733149871Sscottl else 734149871Sscottl { 735190809Sdelphij KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n", 736149871Sscottl pMvSataAdapter->adapterId, channelNum)); 737149871Sscottl } 738149871Sscottl#else 739149871Sscottl { 740149871Sscottl if (pMvSataChannel->identifyDevice[86] & 0x20) 741149871Sscottl { 742190809Sdelphij KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n", 743149871Sscottl pMvSataAdapter->adapterId, channelNum)); 744149871Sscottl if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 745149871Sscottl MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 746149871Sscottl 0, 0) == MV_FALSE) 747149871Sscottl { 748190809Sdelphij MV_ERROR("RR18xx [%d]:channel %d: ATA Set Features failed\n", 749149871Sscottl pMvSataAdapter->adapterId, channelNum); 750149871Sscottl return -1; 751149871Sscottl } 752136849Sscottl } 753190809Sdelphij KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n", 754149871Sscottl pMvSataAdapter->adapterId, channelNum)); 755149871Sscottl } 756136849Sscottl#endif 757136849Sscottl 758136849Sscottl 759149871Sscottl { 760190809Sdelphij KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n", 761149871Sscottl pMvSataAdapter->adapterId, 762149871Sscottl channelNum)); 763149871Sscottl if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, 764149871Sscottl MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) 765149871Sscottl { 766190809Sdelphij MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n", 767149871Sscottl pMvSataAdapter->adapterId, channelNum); 768136849Sscottl return -1; 769136849Sscottl } 770136849Sscottl } 771136849Sscottl /* Enable EDMA */ 772149871Sscottl if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) 773149871Sscottl { 774190809Sdelphij MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n", 775149871Sscottl pMvSataAdapter->adapterId, channelNum); 776136849Sscottl return -1; 777136849Sscottl } 778190809Sdelphij MV_ERROR("RR18xx [%d,%d]: channel started successfully\n", 779149871Sscottl pMvSataAdapter->adapterId, channelNum); 780136849Sscottl 781136849Sscottl#ifndef FOR_DEMO 782136849Sscottl set_fail_led(pMvSataAdapter, channelNum, 0); 783136849Sscottl#endif 784136849Sscottl return 0; 785136849Sscottl} 786136849Sscottl 787136849Sscottlstatic void 788136849Sscottlhptmv_handle_event(void * data, int flag) 789136849Sscottl{ 790149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)data; 791149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 792149871Sscottl MV_U8 channelIndex; 793149871Sscottl 794149871Sscottl/* mvOsSemTake(&pMvSataAdapter->semaphore); */ 795149871Sscottl for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++) 796149871Sscottl { 797149871Sscottl switch(pAdapter->sataEvents[channelIndex]) 798149871Sscottl { 799149871Sscottl case SATA_EVENT_CHANNEL_CONNECTED: 800149871Sscottl /* Handle only connects */ 801149871Sscottl if (flag == 1) 802149871Sscottl break; 803190809Sdelphij KdPrint(("RR18xx [%d,%d]: new device connected\n", 804149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 805149871Sscottl hptmv_init_channel(pAdapter, channelIndex); 806149871Sscottl if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE) 807149871Sscottl { 808190809Sdelphij MV_ERROR("RR18xx [%d,%d] Failed to configure\n", 809149871Sscottl pMvSataAdapter->adapterId, channelIndex); 810149871Sscottl hptmv_free_channel(pAdapter, channelIndex); 811149871Sscottl } 812149871Sscottl else 813149871Sscottl { 814149871Sscottl /*mvSataChannelHardReset(pMvSataAdapter, channel);*/ 815149871Sscottl if (start_channel( pAdapter, channelIndex)) 816149871Sscottl { 817190809Sdelphij MV_ERROR("RR18xx [%d,%d]Failed to start channel\n", 818149871Sscottl pMvSataAdapter->adapterId, channelIndex); 819149871Sscottl hptmv_free_channel(pAdapter, channelIndex); 820149871Sscottl } 821149871Sscottl else 822149871Sscottl { 823149871Sscottl device_change(pAdapter, channelIndex, TRUE); 824149871Sscottl } 825149871Sscottl } 826149871Sscottl pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 827149871Sscottl break; 828136849Sscottl 829149871Sscottl case SATA_EVENT_CHANNEL_DISCONNECTED: 830149871Sscottl /* Handle only disconnects */ 831149871Sscottl if (flag == 0) 832149871Sscottl break; 833190809Sdelphij KdPrint(("RR18xx [%d,%d]: device disconnected\n", 834149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 835149871Sscottl /* Flush pending commands */ 836149871Sscottl if(pMvSataAdapter->sataChannel[channelIndex]) 837149871Sscottl { 838149871Sscottl _VBUS_INST(&pAdapter->VBus) 839149871Sscottl mvSataFlushDmaQueue (pMvSataAdapter, channelIndex, 840149871Sscottl MV_FLUSH_TYPE_CALLBACK); 841149871Sscottl CheckPendingCall(_VBUS_P0); 842149871Sscottl mvSataRemoveChannel(pMvSataAdapter,channelIndex); 843149871Sscottl hptmv_free_channel(pAdapter, channelIndex); 844149871Sscottl pMvSataAdapter->sataChannel[channelIndex] = NULL; 845190809Sdelphij KdPrint(("RR18xx [%d,%d]: channel removed\n", 846149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 847149871Sscottl if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 848149871Sscottl Check_Idle_Call(pAdapter); 849136849Sscottl } 850149871Sscottl else 851149871Sscottl { 852190809Sdelphij KdPrint(("RR18xx [%d,%d]: channel already removed!!\n", 853149871Sscottl pMvSataAdapter->adapterId, channelIndex)); 854149871Sscottl } 855149871Sscottl pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 856136849Sscottl break; 857136849Sscottl 858149871Sscottl case SATA_EVENT_NO_CHANGE: 859149871Sscottl break; 860136849Sscottl 861149871Sscottl default: 862149871Sscottl break; 863136849Sscottl } 864136849Sscottl } 865149871Sscottl/* mvOsSemRelease(&pMvSataAdapter->semaphore); */ 866136849Sscottl} 867136849Sscottl 868136849Sscottl#define EVENT_CONNECT 1 869136849Sscottl#define EVENT_DISCONNECT 0 870136849Sscottl 871136849Sscottlstatic void 872136849Sscottlhptmv_handle_event_connect(void *data) 873136849Sscottl{ 874149871Sscottl hptmv_handle_event (data, 0); 875136849Sscottl} 876136849Sscottl 877136849Sscottlstatic void 878136849Sscottlhptmv_handle_event_disconnect(void *data) 879136849Sscottl{ 880149871Sscottl hptmv_handle_event (data, 1); 881136849Sscottl} 882136849Sscottl 883136849Sscottlstatic MV_BOOLEAN 884136849Sscottlhptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType, 885149871Sscottl MV_U32 param1, MV_U32 param2) 886136849Sscottl{ 887149871Sscottl IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; 888136849Sscottl 889149871Sscottl switch (eventType) 890136849Sscottl { 891149871Sscottl case MV_EVENT_TYPE_SATA_CABLE: 892149871Sscottl { 893149871Sscottl MV_U8 channel = param2; 894136849Sscottl 895149871Sscottl if (param1 == EVENT_CONNECT) 896149871Sscottl { 897149871Sscottl pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED; 898190809Sdelphij KdPrint(("RR18xx [%d,%d]: device connected event received\n", 899149871Sscottl pMvSataAdapter->adapterId, channel)); 900149871Sscottl /* Delete previous timers (if multiple drives connected in the same time */ 901149871Sscottl pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz); 902149871Sscottl } 903149871Sscottl else if (param1 == EVENT_DISCONNECT) 904149871Sscottl { 905149871Sscottl pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED; 906190809Sdelphij KdPrint(("RR18xx [%d,%d]: device disconnected event received \n", 907149871Sscottl pMvSataAdapter->adapterId, channel)); 908149871Sscottl device_change(pAdapter, channel, FALSE); 909149871Sscottl /* Delete previous timers (if multiple drives disconnected in the same time */ 910149871Sscottl /*pAdapter->event_timer_disconnect = timeout(hptmv_handle_event_disconnect, pAdapter, 10*hz); */ 911149871Sscottl /*It is not necessary to wait, handle it directly*/ 912149871Sscottl hptmv_handle_event_disconnect(pAdapter); 913149871Sscottl } 914149871Sscottl else 915149871Sscottl { 916136849Sscottl 917190809Sdelphij MV_ERROR("RR18xx: illigal value for param1(%d) at " 918149871Sscottl "connect/disconect event, host=%d\n", param1, 919149871Sscottl pMvSataAdapter->adapterId ); 920149871Sscottl 921149871Sscottl } 922149871Sscottl } 923149871Sscottl break; 924149871Sscottl case MV_EVENT_TYPE_ADAPTER_ERROR: 925190809Sdelphij KdPrint(("RR18xx: DEVICE error event received, pci cause " 926149871Sscottl "reg=%x, don't how to handle this\n", param1)); 927149871Sscottl return MV_TRUE; 928149871Sscottl default: 929190809Sdelphij MV_ERROR("RR18xx[%d]: unknown event type (%d)\n", 930149871Sscottl pMvSataAdapter->adapterId, eventType); 931149871Sscottl return MV_FALSE; 932136849Sscottl } 933136849Sscottl return MV_TRUE; 934136849Sscottl} 935136849Sscottl 936149871Sscottlstatic int 937136849Sscottlhptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) 938136849Sscottl{ 939149871Sscottl pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE, 940149871Sscottl M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 941149871Sscottl if (pAdapter->requestsArrayBaseAddr == NULL) 942149871Sscottl { 943190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request" 944149871Sscottl " queues\n", pAdapter->mvSataAdapter.adapterId); 945136849Sscottl return -1; 946136849Sscottl } 947149871Sscottl pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr); 948149871Sscottl pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr; 949136849Sscottl pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 950149871Sscottl pAdapter->requestsArrayBaseAlignedAddr = (MV_U8 *) 951149871Sscottl (((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); 952149871Sscottl pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr; 953136849Sscottl pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 954149871Sscottl pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); 955136849Sscottl 956149871Sscottl if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) != 957149871Sscottl (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr)) 958149871Sscottl { 959190809Sdelphij MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n", 960149871Sscottl pAdapter->mvSataAdapter.adapterId); 961149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 962136849Sscottl return -1; 963136849Sscottl } 964136849Sscottl /* response queues */ 965149871Sscottl pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE, 966149871Sscottl M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 967149871Sscottl if (pAdapter->responsesArrayBaseAddr == NULL) 968149871Sscottl { 969190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response" 970149871Sscottl " queues\n", pAdapter->mvSataAdapter.adapterId); 971149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 972136849Sscottl return -1; 973136849Sscottl } 974149871Sscottl pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr); 975149871Sscottl pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr; 976136849Sscottl pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 977149871Sscottl pAdapter->responsesArrayBaseAlignedAddr = (MV_U8 *) 978149871Sscottl (((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); 979149871Sscottl pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr; 980149871Sscottl pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 981149871Sscottl pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); 982136849Sscottl 983149871Sscottl if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) != 984149871Sscottl (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr)) 985149871Sscottl { 986190809Sdelphij MV_ERROR("RR18xx[%d]: Error in Response Quueues Alignment\n", 987149871Sscottl pAdapter->mvSataAdapter.adapterId); 988149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 989149871Sscottl contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 990136849Sscottl return -1; 991136849Sscottl } 992136849Sscottl return 0; 993136849Sscottl} 994136849Sscottl 995136849Sscottlstatic void 996136849Sscottlhptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter) 997136849Sscottl{ 998149871Sscottl contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 999149871Sscottl contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 1000136849Sscottl} 1001136849Sscottl 1002136849Sscottlstatic PVOID 1003136849SscottlAllocatePRDTable(IAL_ADAPTER_T *pAdapter) 1004136849Sscottl{ 1005136849Sscottl PVOID ret; 1006136849Sscottl if (pAdapter->pFreePRDLink) { 1007149871Sscottl KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink)); 1008136849Sscottl ret = pAdapter->pFreePRDLink; 1009136849Sscottl pAdapter->pFreePRDLink = *(void**)ret; 1010136849Sscottl return ret; 1011136849Sscottl } 1012136849Sscottl return NULL; 1013136849Sscottl} 1014136849Sscottl 1015136849Sscottlstatic void 1016136849SscottlFreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable) 1017136849Sscottl{ 1018136849Sscottl *(void**)PRDTable = pAdapter->pFreePRDLink; 1019136849Sscottl pAdapter->pFreePRDLink = PRDTable; 1020136849Sscottl} 1021136849Sscottl 1022136849Sscottlextern PVDevice fGetFirstChild(PVDevice pLogical); 1023136849Sscottlextern void fResetBootMark(PVDevice pLogical); 1024136849Sscottlstatic void 1025136849SscottlfRegisterVdevice(IAL_ADAPTER_T *pAdapter) 1026136849Sscottl{ 1027136849Sscottl PVDevice pPhysical, pLogical; 1028136849Sscottl PVBus pVBus; 1029136849Sscottl int i,j; 1030136849Sscottl 1031149871Sscottl for(i=0;i<MV_SATA_CHANNELS_NUM;i++) { 1032136849Sscottl pPhysical = &(pAdapter->VDevices[i]); 1033136849Sscottl pLogical = pPhysical; 1034136849Sscottl while (pLogical->pParent) pLogical = pLogical->pParent; 1035136849Sscottl if (pLogical->vf_online==0) { 1036136849Sscottl pPhysical->vf_bootmark = pLogical->vf_bootmark = 0; 1037136849Sscottl continue; 1038136849Sscottl } 1039149871Sscottl if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical)) 1040136849Sscottl continue; 1041136849Sscottl 1042136849Sscottl pVBus = &pAdapter->VBus; 1043149871Sscottl if(pVBus) 1044149871Sscottl { 1045136849Sscottl j=0; 1046149871Sscottl while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++; 1047149871Sscottl if(j<MAX_VDEVICE_PER_VBUS){ 1048136849Sscottl pVBus->pVDevice[j] = pLogical; 1049136849Sscottl pLogical->pVBus = pVBus; 1050136849Sscottl 1051136849Sscottl if (j>0 && pLogical->vf_bootmark) { 1052136849Sscottl if (pVBus->pVDevice[0]->vf_bootmark) { 1053136849Sscottl fResetBootMark(pLogical); 1054149871Sscottl } 1055149871Sscottl else { 1056149871Sscottl do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j); 1057136849Sscottl pVBus->pVDevice[0] = pLogical; 1058136849Sscottl } 1059136849Sscottl } 1060136849Sscottl } 1061136849Sscottl } 1062136849Sscottl } 1063136849Sscottl} 1064136849Sscottl 1065136849SscottlPVDevice 1066136849SscottlGetSpareDisk(_VBUS_ARG PVDevice pArray) 1067136849Sscottl{ 1068149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; 1069190809Sdelphij LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); 1070190809Sdelphij LBA_T thiscap, maxcap = MAX_LBA_T; 1071136849Sscottl PVDevice pVDevice, pFind = NULL; 1072136849Sscottl int i; 1073136849Sscottl 1074149871Sscottl for(i=0;i<MV_SATA_CHANNELS_NUM;i++) 1075149871Sscottl { 1076136849Sscottl pVDevice = &pAdapter->VDevices[i]; 1077136849Sscottl if(!pVDevice) 1078136849Sscottl continue; 1079149871Sscottl thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; 1080136849Sscottl /* find the smallest usable spare disk */ 1081136849Sscottl if (pVDevice->VDeviceType==VD_SPARE && 1082149871Sscottl pVDevice->u.disk.df_on_line && 1083149871Sscottl thiscap < maxcap && 1084149871Sscottl thiscap >= capacity) 1085149871Sscottl { 1086149871Sscottl maxcap = pVDevice->VDeviceCapacity; 1087149871Sscottl pFind = pVDevice; 1088136849Sscottl } 1089136849Sscottl } 1090136849Sscottl return pFind; 1091136849Sscottl} 1092136849Sscottl 1093136849Sscottl/****************************************************************** 1094136849Sscottl * IO ATA Command 1095136849Sscottl *******************************************************************/ 1096136849Sscottlint HPTLIBAPI 1097136849SscottlfDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer) 1098136849Sscottl{ 1099136849Sscottl return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer); 1100136849Sscottl} 1101136849Sscottl 1102136849Sscottlvoid HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) 1103136849Sscottl{ 1104149871Sscottl MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1105149871Sscottl MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1106149871Sscottl MV_U8 channelIndex = pSataChannel->channelNumber; 1107136849Sscottl UCHAR mvMode; 1108136849Sscottl /* 508x don't use MW-DMA? */ 1109136849Sscottl if (NewMode>4 && NewMode<8) NewMode = 4; 1110136849Sscottl pDev->bDeModeSetting = NewMode; 1111136849Sscottl if (NewMode<=4) 1112136849Sscottl mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode; 1113136849Sscottl else 1114136849Sscottl mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8); 1115136849Sscottl 1116136849Sscottl /*To fix 88i8030 bug*/ 1117136849Sscottl if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4) 1118136849Sscottl mvMode = MV_ATA_TRANSFER_UDMA_0; 1119136849Sscottl 1120136849Sscottl mvSataDisableChannelDma(pSataAdapter, channelIndex); 1121136849Sscottl /* Flush pending commands */ 1122136849Sscottl mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE); 1123136849Sscottl 1124136849Sscottl if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1125149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1126149871Sscottl mvMode, 0, 0, 0) == MV_FALSE) 1127149871Sscottl { 1128136849Sscottl KdPrint(("channel %d: Set Features failed\n", channelIndex)); 1129136849Sscottl } 1130136849Sscottl /* Enable EDMA */ 1131136849Sscottl if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE) 1132136849Sscottl KdPrint(("Failed to enable DMA, channel=%d", channelIndex)); 1133136849Sscottl} 1134136849Sscottl 1135190809Sdelphijint HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth) 1136190809Sdelphij{ 1137190809Sdelphij MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1138190809Sdelphij MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1139190809Sdelphij MV_U8 channelIndex = pSataChannel->channelNumber; 1140190809Sdelphij IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1141190809Sdelphij MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1142190809Sdelphij int dmaActive = pSataChannel->queueCommandsEnabled; 1143190809Sdelphij int ret = 0; 1144190809Sdelphij 1145190809Sdelphij if (dmaActive) { 1146190809Sdelphij mvSataDisableChannelDma(pSataAdapter, channelIndex); 1147190809Sdelphij mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1148190809Sdelphij } 1149190809Sdelphij 1150190809Sdelphij if (enable) { 1151190809Sdelphij if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED && 1152190809Sdelphij (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) { 1153190809Sdelphij UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1; 1154190809Sdelphij channelInfo->queueDepth = (depth==32)? 31 : depth; 1155190809Sdelphij mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth); 1156190809Sdelphij ret = 1; 1157190809Sdelphij } 1158190809Sdelphij } 1159190809Sdelphij else 1160190809Sdelphij { 1161190809Sdelphij if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) { 1162190809Sdelphij channelInfo->queueDepth = 2; 1163190809Sdelphij mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0); 1164190809Sdelphij ret = 1; 1165190809Sdelphij } 1166190809Sdelphij } 1167190809Sdelphij 1168190809Sdelphij if (dmaActive) 1169190809Sdelphij mvSataEnableChannelDma(pSataAdapter,channelIndex); 1170190809Sdelphij return ret; 1171190809Sdelphij} 1172190809Sdelphij 1173190809Sdelphijint HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth) 1174190809Sdelphij{ 1175190809Sdelphij return 0; 1176190809Sdelphij} 1177190809Sdelphij 1178190809Sdelphijint HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable) 1179190809Sdelphij{ 1180190809Sdelphij MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1181190809Sdelphij MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1182190809Sdelphij MV_U8 channelIndex = pSataChannel->channelNumber; 1183190809Sdelphij IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1184190809Sdelphij MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1185190809Sdelphij int dmaActive = pSataChannel->queueCommandsEnabled; 1186190809Sdelphij int ret = 0; 1187190809Sdelphij 1188190809Sdelphij if (dmaActive) { 1189190809Sdelphij mvSataDisableChannelDma(pSataAdapter, channelIndex); 1190190809Sdelphij mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1191190809Sdelphij } 1192190809Sdelphij 1193190809Sdelphij if ((pSataChannel->identifyDevice[82] & (0x20))) { 1194190809Sdelphij if (enable) { 1195190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1196190809Sdelphij MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0)) 1197190809Sdelphij { 1198190809Sdelphij channelInfo->writeCacheEnabled = MV_TRUE; 1199190809Sdelphij ret = 1; 1200190809Sdelphij } 1201190809Sdelphij } 1202190809Sdelphij else { 1203190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1204190809Sdelphij MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0)) 1205190809Sdelphij { 1206190809Sdelphij channelInfo->writeCacheEnabled = MV_FALSE; 1207190809Sdelphij ret = 1; 1208190809Sdelphij } 1209190809Sdelphij } 1210190809Sdelphij } 1211190809Sdelphij 1212190809Sdelphij if (dmaActive) 1213190809Sdelphij mvSataEnableChannelDma(pSataAdapter,channelIndex); 1214190809Sdelphij return ret; 1215190809Sdelphij} 1216190809Sdelphij 1217190809Sdelphijint HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable) 1218190809Sdelphij{ 1219190809Sdelphij MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1220190809Sdelphij MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1221190809Sdelphij MV_U8 channelIndex = pSataChannel->channelNumber; 1222190809Sdelphij IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 1223190809Sdelphij MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 1224190809Sdelphij int dmaActive = pSataChannel->queueCommandsEnabled; 1225190809Sdelphij int ret = 0; 1226190809Sdelphij 1227190809Sdelphij if (dmaActive) { 1228190809Sdelphij mvSataDisableChannelDma(pSataAdapter, channelIndex); 1229190809Sdelphij mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 1230190809Sdelphij } 1231190809Sdelphij 1232190809Sdelphij if ((pSataChannel->identifyDevice[82] & (0x40))) { 1233190809Sdelphij if (enable) { 1234190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1235190809Sdelphij MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0)) 1236190809Sdelphij { 1237190809Sdelphij channelInfo->readAheadEnabled = MV_TRUE; 1238190809Sdelphij ret = 1; 1239190809Sdelphij } 1240190809Sdelphij } 1241190809Sdelphij else { 1242190809Sdelphij if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1243190809Sdelphij MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0)) 1244190809Sdelphij { 1245190809Sdelphij channelInfo->readAheadEnabled = MV_FALSE; 1246190809Sdelphij ret = 1; 1247190809Sdelphij } 1248190809Sdelphij } 1249190809Sdelphij } 1250190809Sdelphij 1251190809Sdelphij if (dmaActive) 1252190809Sdelphij mvSataEnableChannelDma(pSataAdapter,channelIndex); 1253190809Sdelphij return ret; 1254190809Sdelphij} 1255190809Sdelphij 1256136849Sscottl#ifdef SUPPORT_ARRAY 1257136849Sscottl#define IdeRegisterVDevice fCheckArray 1258149871Sscottl#else 1259136849Sscottlvoid 1260136849SscottlIdeRegisterVDevice(PDevice pDev) 1261136849Sscottl{ 1262136849Sscottl PVDevice pVDev = Map2pVDevice(pDev); 1263136849Sscottl 1264136849Sscottl pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI : 1265149871Sscottl pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 1266136849Sscottl pVDev->vf_online = 1; 1267136849Sscottl pVDev->VDeviceCapacity = pDev->dDeRealCapacity; 1268136849Sscottl pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 1269136849Sscottl pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 1270136849Sscottl} 1271136849Sscottl#endif 1272136849Sscottl 1273149871Sscottlstatic __inline PBUS_DMAMAP 1274149871Sscottldmamap_get(struct IALAdapter * pAdapter) 1275149871Sscottl{ 1276149871Sscottl PBUS_DMAMAP p = pAdapter->pbus_dmamap_list; 1277149871Sscottl if (p) 1278149871Sscottl pAdapter->pbus_dmamap_list = p-> next; 1279149871Sscottl return p; 1280149871Sscottl} 1281149871Sscottl 1282149871Sscottlstatic __inline void 1283149871Sscottldmamap_put(PBUS_DMAMAP p) 1284149871Sscottl{ 1285149871Sscottl p->next = p->pAdapter->pbus_dmamap_list; 1286149871Sscottl p->pAdapter->pbus_dmamap_list = p; 1287149871Sscottl} 1288149871Sscottl 1289149871Sscottl/*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/ 1290149871Sscottl#if __FreeBSD_version >= 500000 1291190809Sdelphij#define override_kernel_driver() 1292190809Sdelphij 1293149871Sscottlstatic void hpt_init(void *dummy) 1294149871Sscottl{ 1295190809Sdelphij override_kernel_driver(); 1296190809Sdelphij mtx_init(&driver_lock, "hptsleeplock", NULL, MTX_DEF); 1297149871Sscottl} 1298149871SscottlSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1299149871Sscottl#endif 1300149871Sscottl 1301136849Sscottlstatic int num_adapters = 0; 1302136849Sscottlstatic int 1303136849Sscottlinit_adapter(IAL_ADAPTER_T *pAdapter) 1304136849Sscottl{ 1305136849Sscottl PVBus _vbus_p = &pAdapter->VBus; 1306136849Sscottl MV_SATA_ADAPTER *pMvSataAdapter; 1307149871Sscottl int i, channel, rid; 1308136849Sscottl 1309136849Sscottl PVDevice pVDev; 1310136849Sscottl 1311190809Sdelphij intrmask_t oldspl = lock_driver(); 1312190809Sdelphij 1313136849Sscottl pAdapter->next = 0; 1314136849Sscottl 1315149871Sscottl if(gIal_Adapter == 0){ 1316136849Sscottl gIal_Adapter = pAdapter; 1317136849Sscottl pCurAdapter = gIal_Adapter; 1318149871Sscottl } 1319149871Sscottl else { 1320136849Sscottl pCurAdapter->next = pAdapter; 1321136849Sscottl pCurAdapter = pAdapter; 1322136849Sscottl } 1323136849Sscottl 1324136849Sscottl pAdapter->outstandingCommands = 0; 1325136849Sscottl 1326136849Sscottl pMvSataAdapter = &(pAdapter->mvSataAdapter); 1327136849Sscottl _vbus_p->OsExt = (void *)pAdapter; 1328136849Sscottl pMvSataAdapter->IALData = pAdapter; 1329136849Sscottl 1330232854Sscottl if (bus_dma_tag_create(bus_get_dma_tag(pAdapter->hpt_dev),/* parent */ 1331149871Sscottl 4, /* alignment */ 1332149871Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1333149871Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1334149871Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1335149871Sscottl NULL, NULL, /* filter, filterarg */ 1336149871Sscottl PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */ 1337149871Sscottl MAX_SG_DESCRIPTORS, /* nsegments */ 1338149871Sscottl 0x10000, /* maxsegsize */ 1339149871Sscottl BUS_DMA_WAITOK, /* flags */ 1340149871Sscottl#if __FreeBSD_version>502000 1341149871Sscottl busdma_lock_mutex, /* lockfunc */ 1342149871Sscottl &driver_lock, /* lockfuncarg */ 1343149871Sscottl#endif 1344149871Sscottl &pAdapter->io_dma_parent /* tag */)) 1345149871Sscottl { 1346201758Smbr return ENXIO; 1347136849Sscottl } 1348136849Sscottl 1349136849Sscottl 1350149871Sscottl if (hptmv_allocate_edma_queues(pAdapter)) 1351149871Sscottl { 1352190809Sdelphij MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n"); 1353190809Sdelphij unlock_driver(oldspl); 1354149871Sscottl return ENOMEM; 1355136849Sscottl } 1356136849Sscottl 1357136849Sscottl /* also map EPROM address */ 1358136849Sscottl rid = 0x10; 1359149871Sscottl if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid, 1360149871Sscottl 0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE)) 1361149871Sscottl || 1362149871Sscottl !(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res))) 1363149871Sscottl { 1364190809Sdelphij MV_ERROR("RR18xx: Failed to remap memory space\n"); 1365149871Sscottl hptmv_free_edma_queues(pAdapter); 1366190809Sdelphij unlock_driver(oldspl); 1367149871Sscottl return ENXIO; 1368136849Sscottl } 1369149871Sscottl else 1370149871Sscottl { 1371190809Sdelphij KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress)); 1372149871Sscottl } 1373136849Sscottl 1374136849Sscottl pMvSataAdapter->adapterId = num_adapters++; 1375136849Sscottl /* get the revision ID */ 1376149871Sscottl pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); 1377136849Sscottl pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev); 1378149871Sscottl 1379190809Sdelphij /* init RR18xx */ 1380136849Sscottl pMvSataAdapter->intCoalThre[0]= 1; 1381136849Sscottl pMvSataAdapter->intCoalThre[1]= 1; 1382136849Sscottl pMvSataAdapter->intTimeThre[0] = 1; 1383136849Sscottl pMvSataAdapter->intTimeThre[1] = 1; 1384136849Sscottl pMvSataAdapter->pciCommand = 0x0107E371; 1385136849Sscottl pMvSataAdapter->pciSerrMask = 0xd77fe6ul; 1386136849Sscottl pMvSataAdapter->pciInterruptMask = 0xd77fe6ul; 1387136849Sscottl pMvSataAdapter->mvSataEventNotify = hptmv_event_notify; 1388136849Sscottl 1389149871Sscottl if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) 1390149871Sscottl { 1391190809Sdelphij MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n", 1392149871Sscottl pMvSataAdapter->adapterId); 1393149871Sscottlunregister: 1394149871Sscottl bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res); 1395149871Sscottl hptmv_free_edma_queues(pAdapter); 1396190809Sdelphij unlock_driver(oldspl); 1397149871Sscottl return ENXIO; 1398136849Sscottl } 1399136849Sscottl pAdapter->ver_601 = pMvSataAdapter->pcbVersion; 1400136849Sscottl 1401136849Sscottl#ifndef FOR_DEMO 1402136849Sscottl set_fail_leds(pMvSataAdapter, 0); 1403136849Sscottl#endif 1404136849Sscottl 1405136849Sscottl /* setup command blocks */ 1406136849Sscottl KdPrint(("Allocate command blocks\n")); 1407136849Sscottl _vbus_(pFreeCommands) = 0; 1408149871Sscottl pAdapter->pCommandBlocks = 1409149871Sscottl malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT); 1410149871Sscottl KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks)); 1411149871Sscottl if (!pAdapter->pCommandBlocks) { 1412149871Sscottl MV_ERROR("insufficient memory\n"); 1413149871Sscottl goto unregister; 1414149871Sscottl } 1415136849Sscottl 1416149871Sscottl for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) { 1417149871Sscottl FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i])); 1418149871Sscottl } 1419136849Sscottl 1420149871Sscottl /*Set up the bus_dmamap*/ 1421149871Sscottl pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT); 1422149871Sscottl if(!pAdapter->pbus_dmamap) { 1423149871Sscottl MV_ERROR("insufficient memory\n"); 1424149871Sscottl free(pAdapter->pCommandBlocks, M_DEVBUF); 1425149871Sscottl goto unregister; 1426136849Sscottl } 1427136849Sscottl 1428149871Sscottl memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM); 1429149871Sscottl pAdapter->pbus_dmamap_list = 0; 1430149871Sscottl for (i=0; i < MAX_QUEUE_COMM; i++) { 1431149871Sscottl PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]); 1432149871Sscottl pmap->pAdapter = pAdapter; 1433149871Sscottl dmamap_put(pmap); 1434149871Sscottl 1435149871Sscottl if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) { 1436149871Sscottl MV_ERROR("Can not allocate dma map\n"); 1437149871Sscottl free(pAdapter->pCommandBlocks, M_DEVBUF); 1438149871Sscottl free(pAdapter->pbus_dmamap, M_DEVBUF); 1439149871Sscottl goto unregister; 1440149871Sscottl } 1441149871Sscottl } 1442136849Sscottl /* setup PRD Tables */ 1443136849Sscottl KdPrint(("Allocate PRD Tables\n")); 1444136849Sscottl pAdapter->pFreePRDLink = 0; 1445149871Sscottl 1446149871Sscottl pAdapter->prdTableAddr = (PUCHAR)contigmalloc( 1447149871Sscottl (PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 1448149871Sscottl 1449136862Sscottl KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr)); 1450136849Sscottl if (!pAdapter->prdTableAddr) { 1451136849Sscottl MV_ERROR("insufficient PRD Tables\n"); 1452136849Sscottl goto unregister; 1453136849Sscottl } 1454149871Sscottl pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL); 1455149871Sscottl { 1456149871Sscottl PUCHAR PRDTable = pAdapter->prdTableAlignedAddr; 1457149871Sscottl for (i=0; i<PRD_TABLES_FOR_VBUS; i++) 1458149871Sscottl { 1459149871Sscottl/* KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */ 1460149871Sscottl FreePRDTable(pAdapter, PRDTable); 1461149871Sscottl PRDTable += PRD_ENTRIES_SIZE; 1462149871Sscottl } 1463136849Sscottl } 1464136849Sscottl 1465136849Sscottl /* enable the adapter interrupts */ 1466136849Sscottl 1467136849Sscottl /* configure and start the connected channels*/ 1468149871Sscottl for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 1469149871Sscottl { 1470136849Sscottl pAdapter->mvChannel[channel].online = MV_FALSE; 1471136849Sscottl if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) 1472149871Sscottl == MV_TRUE) 1473149871Sscottl { 1474190809Sdelphij KdPrint(("RR18xx[%d]: channel %d is connected\n", 1475149871Sscottl pMvSataAdapter->adapterId, channel)); 1476136849Sscottl 1477149871Sscottl if (hptmv_init_channel(pAdapter, channel) == 0) 1478149871Sscottl { 1479149871Sscottl if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE) 1480149871Sscottl { 1481190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to configure channel" 1482149871Sscottl " %d\n",pMvSataAdapter->adapterId, channel); 1483149871Sscottl hptmv_free_channel(pAdapter, channel); 1484149871Sscottl } 1485149871Sscottl else 1486149871Sscottl { 1487149871Sscottl if (start_channel(pAdapter, channel)) 1488149871Sscottl { 1489190809Sdelphij MV_ERROR("RR18xx[%d]: Failed to start channel," 1490149871Sscottl " channel=%d\n",pMvSataAdapter->adapterId, 1491149871Sscottl channel); 1492149871Sscottl hptmv_free_channel(pAdapter, channel); 1493149871Sscottl } 1494149871Sscottl pAdapter->mvChannel[channel].online = MV_TRUE; 1495149871Sscottl /* mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter, 1496149871Sscottl channel, 1497149871Sscottl MV_TRUE);*/ 1498149871Sscottl } 1499136849Sscottl } 1500136849Sscottl } 1501136849Sscottl KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n", 1502136849Sscottl pAdapter->mvChannel[channel].online, channel)); 1503136849Sscottl } 1504136849Sscottl 1505136849Sscottl#ifdef SUPPORT_ARRAY 1506136849Sscottl for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) { 1507136849Sscottl pVDev = ArrayTables(i); 1508136849Sscottl mArFreeArrayTable(pVDev); 1509136849Sscottl } 1510136849Sscottl#endif 1511136849Sscottl 1512136849Sscottl KdPrint(("Initialize Devices\n")); 1513136849Sscottl for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { 1514149871Sscottl MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1515136849Sscottl if (pMvSataChannel) { 1516136849Sscottl init_vdev_params(pAdapter, channel); 1517136849Sscottl IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk); 1518136849Sscottl } 1519136849Sscottl } 1520136849Sscottl#ifdef SUPPORT_ARRAY 1521136849Sscottl CheckArrayCritical(_VBUS_P0); 1522136849Sscottl#endif 1523136849Sscottl _vbus_p->nInstances = 1; 1524136849Sscottl fRegisterVdevice(pAdapter); 1525136849Sscottl 1526136849Sscottl for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) { 1527136849Sscottl pVDev = _vbus_p->pVDevice[channel]; 1528136849Sscottl if (pVDev && pVDev->vf_online) 1529136849Sscottl fCheckBootable(pVDev); 1530136849Sscottl } 1531136849Sscottl 1532136849Sscottl#if defined(SUPPORT_ARRAY) && defined(_RAID5N_) 1533136849Sscottl init_raid5_memory(_VBUS_P0); 1534136849Sscottl _vbus_(r5).enable_write_back = 1; 1535190809Sdelphij printf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled"); 1536136849Sscottl#endif 1537136849Sscottl 1538136849Sscottl mvSataUnmaskAdapterInterrupt(pMvSataAdapter); 1539190809Sdelphij unlock_driver(oldspl); 1540136849Sscottl return 0; 1541136849Sscottl} 1542136849Sscottl 1543136849Sscottlint 1544136849SscottlMvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) 1545136849Sscottl{ 1546149871Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; 1547136849Sscottl 1548136849Sscottl mvSataDisableChannelDma(pMvSataAdapter, channel); 1549136849Sscottl /* Flush pending commands */ 1550136849Sscottl mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 1551136849Sscottl 1552136849Sscottl /* Software reset channel */ 1553149871Sscottl if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE) 1554149871Sscottl { 1555190809Sdelphij MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 1556149871Sscottl pMvSataAdapter->adapterId, channel); 1557149871Sscottl hptmv_free_channel(pAdapter, channel); 1558136849Sscottl return -1; 1559136849Sscottl } 1560136849Sscottl 1561136849Sscottl /* Hardware reset channel */ 1562149871Sscottl if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) 1563149871Sscottl { 1564190809Sdelphij MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n", 1565149871Sscottl pMvSataAdapter->adapterId, channel); 1566136849Sscottl hptmv_free_channel(pAdapter, channel); 1567136849Sscottl return -1; 1568136849Sscottl } 1569136849Sscottl 1570149871Sscottl if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE) 1571149871Sscottl { 1572190809Sdelphij MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n", 1573149871Sscottl pMvSataAdapter->adapterId, channel); 1574136849Sscottl hptmv_free_channel(pAdapter, channel); 1575136849Sscottl return -1; 1576149871Sscottl }else 1577149871Sscottl { 1578149871Sscottl MV_ERROR("channel %d: perform recalibrate command", channel); 1579149871Sscottl if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1580149871Sscottl MV_NON_UDMA_PROTOCOL_NON_DATA, 1581149871Sscottl MV_FALSE, 1582149871Sscottl NULL, /* pBuffer*/ 1583149871Sscottl 0, /* count */ 1584149871Sscottl 0, /*features*/ 1585149871Sscottl /* sectorCount */ 1586149871Sscottl 0, 1587149871Sscottl 0, /* lbaLow */ 1588149871Sscottl 0, /* lbaMid */ 1589149871Sscottl /* lbaHigh */ 1590149871Sscottl 0, 1591149871Sscottl 0, /* device */ 1592149871Sscottl /* command */ 1593149871Sscottl 0x10)) 1594149871Sscottl MV_ERROR("channel %d: recalibrate failed", channel); 1595149871Sscottl 1596136849Sscottl /* Set transfer mode */ 1597136849Sscottl if((mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1598149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1599149871Sscottl MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) || 1600149871Sscottl (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1601149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1602149871Sscottl pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) || 1603149871Sscottl (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1604149871Sscottl MV_ATA_SET_FEATURES_TRANSFER, 1605149871Sscottl pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) ) 1606149871Sscottl { 1607136849Sscottl MV_ERROR("channel %d: Set Features failed", channel); 1608136849Sscottl hptmv_free_channel(pAdapter, channel); 1609136849Sscottl return -1; 1610136849Sscottl } 1611136849Sscottl /* Enable EDMA */ 1612149871Sscottl if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE) 1613149871Sscottl { 1614136849Sscottl MV_ERROR("Failed to enable DMA, channel=%d", channel); 1615136849Sscottl hptmv_free_channel(pAdapter, channel); 1616136849Sscottl return -1; 1617136849Sscottl } 1618136849Sscottl } 1619136849Sscottl return 0; 1620136849Sscottl} 1621136849Sscottl 1622136849Sscottlstatic int 1623136849SscottlfResetActiveCommands(PVBus _vbus_p) 1624136849Sscottl{ 1625149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 1626136849Sscottl MV_U8 channel; 1627136849Sscottl for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1628149871Sscottl if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands) 1629149871Sscottl MvSataResetChannel(pMvSataAdapter,channel); 1630136849Sscottl } 1631136849Sscottl return 0; 1632136849Sscottl} 1633136849Sscottl 1634149871Sscottlvoid fCompleteAllCommandsSynchronously(PVBus _vbus_p) 1635136849Sscottl{ 1636136849Sscottl UINT cont; 1637136849Sscottl ULONG ticks = 0; 1638136849Sscottl MV_U8 channel; 1639149871Sscottl MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 1640136849Sscottl MV_SATA_CHANNEL *pMvSataChannel; 1641136849Sscottl 1642136849Sscottl do { 1643136849Sscottlcheck_cmds: 1644136849Sscottl cont = 0; 1645136849Sscottl CheckPendingCall(_VBUS_P0); 1646136849Sscottl#ifdef _RAID5N_ 1647136849Sscottl dataxfer_poll(); 1648136849Sscottl xor_poll(); 1649136849Sscottl#endif 1650149871Sscottl for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1651136849Sscottl pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1652149871Sscottl if (pMvSataChannel && pMvSataChannel->outstandingCommands) 1653149871Sscottl { 1654136849Sscottl while (pMvSataChannel->outstandingCommands) { 1655149871Sscottl if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) { 1656136849Sscottl StallExec(1000); 1657136849Sscottl if (ticks++ > 3000) { 1658149871Sscottl MvSataResetChannel(pMvSataAdapter,channel); 1659136849Sscottl goto check_cmds; 1660136849Sscottl } 1661149871Sscottl } 1662149871Sscottl else 1663136849Sscottl ticks = 0; 1664136849Sscottl } 1665136849Sscottl cont = 1; 1666136849Sscottl } 1667136849Sscottl } 1668136849Sscottl } while (cont); 1669136849Sscottl} 1670136849Sscottl 1671136849Sscottlvoid 1672136849SscottlfResetVBus(_VBUS_ARG0) 1673136849Sscottl{ 1674136862Sscottl KdPrint(("fMvResetBus(%p)", _vbus_p)); 1675136849Sscottl 1676136849Sscottl /* some commands may already finished. */ 1677136849Sscottl CheckPendingCall(_VBUS_P0); 1678136849Sscottl 1679136849Sscottl fResetActiveCommands(_vbus_p); 1680136849Sscottl /* 1681136849Sscottl * the other pending commands may still be finished successfully. 1682136849Sscottl */ 1683136849Sscottl fCompleteAllCommandsSynchronously(_vbus_p); 1684136849Sscottl 1685136849Sscottl /* Now there should be no pending commands. No more action needed. */ 1686136849Sscottl CheckIdleCall(_VBUS_P0); 1687136849Sscottl 1688136849Sscottl KdPrint(("fMvResetBus() done")); 1689136849Sscottl} 1690136849Sscottl 1691149871Sscottl/*No rescan function*/ 1692136849Sscottlvoid 1693136849SscottlfRescanAllDevice(_VBUS_ARG0) 1694136849Sscottl{ 1695136849Sscottl} 1696136849Sscottl 1697136849Sscottlstatic MV_BOOLEAN 1698149871SscottlCommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 1699149871Sscottl MV_U8 channelNum, 1700149871Sscottl MV_COMPLETION_TYPE comp_type, 1701149871Sscottl MV_VOID_PTR commandId, 1702149871Sscottl MV_U16 responseFlags, 1703149871Sscottl MV_U32 timeStamp, 1704149871Sscottl MV_STORAGE_DEVICE_REGISTERS *registerStruct) 1705136849Sscottl{ 1706136849Sscottl PCommand pCmd = (PCommand) commandId; 1707136849Sscottl _VBUS_INST(pCmd->pVDevice->pVBus) 1708136849Sscottl 1709136849Sscottl if (pCmd->uScratch.sata_param.prdAddr) 1710149871Sscottl FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr); 1711136849Sscottl 1712149871Sscottl switch (comp_type) 1713149871Sscottl { 1714136849Sscottl case MV_COMPLETION_TYPE_NORMAL: 1715136849Sscottl pCmd->Result = RETURN_SUCCESS; 1716136849Sscottl break; 1717136849Sscottl case MV_COMPLETION_TYPE_ABORT: 1718136849Sscottl pCmd->Result = RETURN_BUS_RESET; 1719136849Sscottl break; 1720136849Sscottl case MV_COMPLETION_TYPE_ERROR: 1721149871Sscottl MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n", 1722149871Sscottl pMvSataAdapter->adapterId, channelNum, responseFlags); 1723136849Sscottl 1724136849Sscottl if (responseFlags & 4) { 1725149871Sscottl MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x," 1726149871Sscottl " LBA high %x, device %x, status %x\n", 1727149871Sscottl registerStruct->errorRegister, 1728149871Sscottl registerStruct->sectorCountRegister, 1729149871Sscottl registerStruct->lbaLowRegister, 1730149871Sscottl registerStruct->lbaMidRegister, 1731149871Sscottl registerStruct->lbaHighRegister, 1732149871Sscottl registerStruct->deviceRegister, 1733149871Sscottl registerStruct->statusRegister); 1734136849Sscottl } 1735149871Sscottl /*We can't do handleEdmaError directly here, because CommandCompletionCB is called by 1736149871Sscottl * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/ 1737136849Sscottl pCmd->uScratch.sata_param.responseFlags = responseFlags; 1738149871Sscottl pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister; 1739149871Sscottl pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister; 1740136849Sscottl pCmd->pVDevice->u.disk.QueueLength--; 1741136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd); 1742136849Sscottl return TRUE; 1743136849Sscottl 1744136849Sscottl default: 1745136849Sscottl MV_ERROR(" Unknown completion type (%d)\n", comp_type); 1746136849Sscottl return MV_FALSE; 1747136849Sscottl } 1748136849Sscottl 1749149871Sscottl if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) { 1750136849Sscottl pCmd->uScratch.sata_param.cmd_priv --; 1751136849Sscottl return TRUE; 1752136849Sscottl } 1753136849Sscottl pCmd->pVDevice->u.disk.QueueLength--; 1754136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1755136849Sscottl return TRUE; 1756136849Sscottl} 1757136849Sscottl 1758136849Sscottlvoid 1759136849SscottlfDeviceSendCommand(_VBUS_ARG PCommand pCmd) 1760136849Sscottl{ 1761149871Sscottl MV_SATA_EDMA_PRD_ENTRY *pPRDTable = 0; 1762136849Sscottl MV_SATA_ADAPTER *pMvSataAdapter; 1763136849Sscottl MV_SATA_CHANNEL *pMvSataChannel; 1764149871Sscottl PVDevice pVDevice = pCmd->pVDevice; 1765149871Sscottl PDevice pDevice = &pVDevice->u.disk; 1766190809Sdelphij LBA_T Lba = pCmd->uCmd.Ide.Lba; 1767149871Sscottl USHORT nSector = pCmd->uCmd.Ide.nSectors; 1768149871Sscottl 1769136849Sscottl MV_QUEUE_COMMAND_RESULT result; 1770136849Sscottl MV_QUEUE_COMMAND_INFO commandInfo; 1771149871Sscottl MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand; 1772149871Sscottl MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; 1773149871Sscottl 1774190809Sdelphij MV_BOOLEAN is48bit; 1775149871Sscottl MV_U8 channel; 1776149871Sscottl int i=0; 1777149871Sscottl 1778136849Sscottl DECLARE_BUFFER(FPSCAT_GATH, tmpSg); 1779136849Sscottl 1780136849Sscottl if (!pDevice->df_on_line) { 1781136849Sscottl MV_ERROR("Device is offline"); 1782136849Sscottl pCmd->Result = RETURN_BAD_DEVICE; 1783136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1784136849Sscottl return; 1785136849Sscottl } 1786136849Sscottl 1787136849Sscottl pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors; 1788136849Sscottl pMvSataChannel = pDevice->mv; 1789136849Sscottl pMvSataAdapter = pMvSataChannel->mvSataAdapter; 1790136849Sscottl channel = pMvSataChannel->channelNumber; 1791136849Sscottl 1792149871Sscottl /* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */ 1793136849Sscottl Lba += pDevice->dDeHiddenLba; 1794136849Sscottl /* check LBA */ 1795136849Sscottl if (Lba+nSector-1 > pDevice->dDeRealCapacity) { 1796136849Sscottl pCmd->Result = RETURN_INVALID_REQUEST; 1797136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1798136849Sscottl return; 1799136849Sscottl } 1800136849Sscottl 1801190809Sdelphij /* 1802190809Sdelphij * always use 48bit LBA if drive supports it. 1803190809Sdelphij * Some Seagate drives report error if you use a 28-bit command 1804190809Sdelphij * to access sector 0xfffffff. 1805190809Sdelphij */ 1806190809Sdelphij is48bit = pMvSataChannel->lba48Address; 1807136849Sscottl 1808149871Sscottl switch (pCmd->uCmd.Ide.Command) 1809149871Sscottl { 1810136849Sscottl case IDE_COMMAND_READ: 1811136849Sscottl case IDE_COMMAND_WRITE: 1812136849Sscottl if (pDevice->bDeModeSetting<8) goto pio; 1813136849Sscottl 1814136849Sscottl commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA; 1815136849Sscottl pUdmaParams->isEXT = is48bit; 1816136849Sscottl pUdmaParams->numOfSectors = nSector; 1817136849Sscottl pUdmaParams->lowLBAAddress = Lba; 1818136849Sscottl pUdmaParams->highLBAAddress = 0; 1819136849Sscottl pUdmaParams->prdHighAddr = 0; 1820136849Sscottl pUdmaParams->callBack = CommandCompletionCB; 1821136849Sscottl pUdmaParams->commandId = (MV_VOID_PTR )pCmd; 1822136849Sscottl if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ) 1823136849Sscottl pUdmaParams->readWrite = MV_UDMA_TYPE_READ; 1824136849Sscottl else 1825136849Sscottl pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE; 1826136849Sscottl 1827136849Sscottl if (pCmd->pSgTable && pCmd->cf_physical_sg) { 1828136849Sscottl FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1829149871Sscottl do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1830149871Sscottl } 1831149871Sscottl else { 1832149871Sscottl if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { 1833136849Sscottlpio: 1834149871Sscottl mvSataDisableChannelDma(pMvSataAdapter, channel); 1835149871Sscottl mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 1836149871Sscottl 1837149871Sscottl if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { 1838149871Sscottl FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1839149871Sscottl do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1840149871Sscottl } 1841149871Sscottl else { 1842149871Sscottl if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) { 1843149871Sscottl pCmd->Result = RETURN_NEED_LOGICAL_SG; 1844149871Sscottl goto finish_cmd; 1845149871Sscottl } 1846149871Sscottl } 1847149871Sscottl 1848136849Sscottl do { 1849149871Sscottl ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; 1850149871Sscottl ULONG_PTR addr = tmpSg->dSgAddress; 1851149871Sscottl if (size & 0x1ff) { 1852149871Sscottl pCmd->Result = RETURN_INVALID_REQUEST; 1853149871Sscottl goto finish_cmd; 1854149871Sscottl } 1855149871Sscottl if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1856149871Sscottl (pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, 1857149871Sscottl is48bit, 1858149871Sscottl (MV_U16_PTR)addr, 1859149871Sscottl size >> 1, /* count */ 1860149871Sscottl 0, /* features N/A */ 1861149871Sscottl (MV_U16)(size>>9), /*sector count*/ 1862149871Sscottl (MV_U16)( (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | (UCHAR)(Lba & 0xFF) ), /*lbalow*/ 1863149871Sscottl (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ 1864149871Sscottl (MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh */ 1865149871Sscottl (MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device */ 1866149871Sscottl (MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command) 1867149871Sscottl )==MV_FALSE) 1868149871Sscottl { 1869149871Sscottl pCmd->Result = RETURN_IDE_ERROR; 1870149871Sscottl goto finish_cmd; 1871149871Sscottl } 1872149871Sscottl Lba += size>>9; 1873149871Sscottl if(Lba & 0xF0000000) is48bit = MV_TRUE; 1874136849Sscottl } 1875149871Sscottl while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 1876149871Sscottl pCmd->Result = RETURN_SUCCESS; 1877149871Sscottlfinish_cmd: 1878149871Sscottl mvSataEnableChannelDma(pMvSataAdapter,channel); 1879149871Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1880149871Sscottl return; 1881136849Sscottl } 1882136849Sscottl } 1883136849Sscottl 1884149871Sscottl pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData); 1885136862Sscottl KdPrint(("pPRDTable:%p\n",pPRDTable)); 1886136849Sscottl if (!pPRDTable) { 1887136849Sscottl pCmd->Result = RETURN_DEVICE_BUSY; 1888149871Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1889136849Sscottl HPT_ASSERT(0); 1890136849Sscottl return; 1891136849Sscottl } 1892136849Sscottl 1893149871Sscottl do{ 1894149871Sscottl pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0); 1895136849Sscottl pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag; 1896136849Sscottl pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize; 1897136849Sscottl pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress; 1898136849Sscottl pPRDTable[i].reserved = 0; 1899136849Sscottl i++; 1900149871Sscottl }while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 1901136849Sscottl 1902149871Sscottl pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable); 1903149871Sscottl if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) { 1904136849Sscottl pUdmaParams->numOfSectors = 0; 1905136849Sscottl } 1906136849Sscottl 1907136849Sscottl pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable; 1908136849Sscottl 1909149871Sscottl result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1910136849Sscottl 1911149871Sscottl if (result != MV_QUEUE_COMMAND_RESULT_OK) 1912149871Sscottl { 1913136849Sscottlqueue_failed: 1914149871Sscottl switch (result) 1915149871Sscottl { 1916136849Sscottl case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS: 1917149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA " 1918149871Sscottl "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress); 1919136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1920136849Sscottl break; 1921136849Sscottl case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED: 1922149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. EDMA" 1923149871Sscottl " disabled adapter %d channel %d\n", 1924149871Sscottl pMvSataAdapter->adapterId, channel); 1925136849Sscottl mvSataEnableChannelDma(pMvSataAdapter,channel); 1926136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1927136849Sscottl break; 1928136849Sscottl case MV_QUEUE_COMMAND_RESULT_FULL: 1929149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. Queue is" 1930149871Sscottl " Full adapter %d channel %d\n", 1931149871Sscottl pMvSataAdapter->adapterId, channel); 1932136849Sscottl pCmd->Result = RETURN_DEVICE_BUSY; 1933136849Sscottl break; 1934136849Sscottl case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS: 1935149871Sscottl MV_ERROR("IAL Error: Edma Queue command failed. (Bad " 1936149871Sscottl "Params), pMvSataAdapter: %p, pSataChannel: %p.\n", 1937149871Sscottl pMvSataAdapter, pMvSataAdapter->sataChannel[channel]); 1938136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1939136849Sscottl break; 1940136849Sscottl default: 1941149871Sscottl MV_ERROR("IAL Error: Bad result value (%d) from queue" 1942149871Sscottl " command\n", result); 1943136849Sscottl pCmd->Result = RETURN_IDE_ERROR; 1944136849Sscottl } 1945136849Sscottl if(pPRDTable) 1946149871Sscottl FreePRDTable(pMvSataAdapter->IALData,pPRDTable); 1947149871Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1948136849Sscottl } 1949136849Sscottl pDevice->QueueLength++; 1950136849Sscottl return; 1951136849Sscottl 1952136849Sscottl case IDE_COMMAND_VERIFY: 1953136849Sscottl commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA; 1954136849Sscottl pNoUdmaParams->bufPtr = NULL; 1955136849Sscottl pNoUdmaParams->callBack = CommandCompletionCB; 1956136849Sscottl pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd; 1957136849Sscottl pNoUdmaParams->count = 0; 1958136849Sscottl pNoUdmaParams->features = 0; 1959136849Sscottl pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA; 1960136849Sscottl 1961136849Sscottl pCmd->uScratch.sata_param.cmd_priv = 1; 1962136849Sscottl if (pMvSataChannel->lba48Address == MV_TRUE){ 1963149871Sscottl pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; 1964136849Sscottl pNoUdmaParams->isEXT = MV_TRUE; 1965149871Sscottl pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 1966136849Sscottl pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 1967136849Sscottl pNoUdmaParams->lbaLow = 1968149871Sscottl (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); 1969136849Sscottl pNoUdmaParams->sectorCount = nSector; 1970136849Sscottl pNoUdmaParams->device = 0x40; 1971149871Sscottl result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1972149871Sscottl if (result != MV_QUEUE_COMMAND_RESULT_OK){ 1973136849Sscottl goto queue_failed; 1974136849Sscottl } 1975136849Sscottl return; 1976136849Sscottl } 1977149871Sscottl else{ 1978149871Sscottl pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; 1979149871Sscottl pNoUdmaParams->isEXT = MV_FALSE; 1980149871Sscottl pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 1981149871Sscottl pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 1982149871Sscottl pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); 1983149871Sscottl pNoUdmaParams->sectorCount = 0xff & nSector; 1984149871Sscottl pNoUdmaParams->device = (MV_U8)(0x40 | 1985149871Sscottl ((Lba & 0xf000000) >> 24)); 1986149871Sscottl pNoUdmaParams->callBack = CommandCompletionCB; 1987149871Sscottl result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1988149871Sscottl /*FIXME: how about the commands already queued? but marvel also forgets to consider this*/ 1989149871Sscottl if (result != MV_QUEUE_COMMAND_RESULT_OK){ 1990149871Sscottl goto queue_failed; 1991149871Sscottl } 1992136849Sscottl } 1993136849Sscottl break; 1994136849Sscottl default: 1995136849Sscottl pCmd->Result = RETURN_INVALID_REQUEST; 1996136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 1997136849Sscottl break; 1998136849Sscottl } 1999136849Sscottl} 2000136849Sscottl 2001136849Sscottl/********************************************************** 2002136849Sscottl * 2003136849Sscottl * Probe the hostadapter. 2004136849Sscottl * 2005136849Sscottl **********************************************************/ 2006136849Sscottlstatic int 2007136849Sscottlhpt_probe(device_t dev) 2008136849Sscottl{ 2009136849Sscottl if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) && 2010136849Sscottl (pci_get_device(dev) == MV_SATA_DEVICE_ID_5081 2011136849Sscottl#ifdef FOR_DEMO 2012136849Sscottl || pci_get_device(dev) == MV_SATA_DEVICE_ID_5080 2013136849Sscottl#endif 2014149871Sscottl )) 2015149871Sscottl { 2016136849Sscottl KdPrintI((CONTROLLER_NAME " found\n")); 2017136849Sscottl device_set_desc(dev, CONTROLLER_NAME); 2018136849Sscottl return 0; 2019136849Sscottl } 2020136849Sscottl else 2021136849Sscottl return(ENXIO); 2022136849Sscottl} 2023136849Sscottl 2024136849Sscottl/*********************************************************** 2025136849Sscottl * 2026136849Sscottl * Auto configuration: attach and init a host adapter. 2027136849Sscottl * 2028136849Sscottl ***********************************************************/ 2029136849Sscottlstatic int 2030136849Sscottlhpt_attach(device_t dev) 2031136849Sscottl{ 2032149871Sscottl IAL_ADAPTER_T * pAdapter = device_get_softc(dev); 2033136849Sscottl int rid; 2034136849Sscottl union ccb *ccb; 2035136849Sscottl struct cam_devq *devq; 2036136849Sscottl struct cam_sim *hpt_vsim; 2037136849Sscottl 2038149871Sscottl printf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION); 2039136849Sscottl 2040149871Sscottl if (!pAdapter) 2041149871Sscottl { 2042149871Sscottl pAdapter = (IAL_ADAPTER_T *)malloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT); 2043149871Sscottl#if __FreeBSD_version > 410000 2044149871Sscottl device_set_softc(dev, (void *)pAdapter); 2045149871Sscottl#else 2046149871Sscottl device_set_driver(dev, (driver_t *)pAdapter); 2047149871Sscottl#endif 2048149871Sscottl } 2049149871Sscottl 2050149871Sscottl if (!pAdapter) return (ENOMEM); 2051149871Sscottl bzero(pAdapter, sizeof(IAL_ADAPTER_T)); 2052149871Sscottl 2053136849Sscottl pAdapter->hpt_dev = dev; 2054136849Sscottl 2055136849Sscottl rid = init_adapter(pAdapter); 2056136849Sscottl if (rid) 2057136849Sscottl return rid; 2058136849Sscottl 2059136849Sscottl rid = 0; 2060149871Sscottl if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 2061149871Sscottl { 2062136849Sscottl hpt_printk(("can't allocate interrupt\n")); 2063136849Sscottl return(ENXIO); 2064136849Sscottl } 2065136849Sscottl 2066190809Sdelphij#if __FreeBSD_version <700000 2067190809Sdelphij if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, 2068190809Sdelphij hpt_intr, pAdapter, &pAdapter->hpt_intr)) 2069190809Sdelphij#else 2070190809Sdelphij if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, 2071190809Sdelphij NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr)) 2072190809Sdelphij#endif 2073149871Sscottl { 2074136849Sscottl hpt_printk(("can't set up interrupt\n")); 2075136849Sscottl free(pAdapter, M_DEVBUF); 2076136849Sscottl return(ENXIO); 2077136849Sscottl } 2078136849Sscottl 2079149871Sscottl 2080149871Sscottl if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL) 2081149871Sscottl { 2082149871Sscottl bzero(ccb, sizeof(*ccb)); 2083136849Sscottl ccb->ccb_h.pinfo.priority = 1; 2084136849Sscottl ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; 2085149871Sscottl } 2086149871Sscottl else 2087149871Sscottl { 2088136849Sscottl return ENOMEM; 2089136849Sscottl } 2090136849Sscottl /* 2091136849Sscottl * Create the device queue for our SIM(s). 2092136849Sscottl */ 2093149871Sscottl if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) 2094149871Sscottl { 2095136849Sscottl KdPrint(("ENXIO\n")); 2096136849Sscottl return ENOMEM; 2097136849Sscottl } 2098136849Sscottl 2099136849Sscottl /* 2100136849Sscottl * Construct our SIM entry 2101136849Sscottl */ 2102190809Sdelphij#if __FreeBSD_version <700000 2103190809Sdelphij hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), 2104190809Sdelphij pAdapter, device_get_unit(pAdapter->hpt_dev), 1, 8, devq); 2105190809Sdelphij#else 2106190809Sdelphij hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), 2107190809Sdelphij pAdapter, device_get_unit(pAdapter->hpt_dev), &Giant, 1, 8, devq); 2108190809Sdelphij#endif 2109190809Sdelphij if (hpt_vsim == NULL) { 2110136849Sscottl cam_simq_free(devq); 2111136849Sscottl return ENOMEM; 2112136849Sscottl } 2113136849Sscottl 2114190809Sdelphij#if __FreeBSD_version <700000 2115190809Sdelphij if (xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS) 2116190809Sdelphij#else 2117190809Sdelphij if (xpt_bus_register(hpt_vsim, dev, 0) != CAM_SUCCESS) 2118190809Sdelphij#endif 2119149871Sscottl { 2120136849Sscottl cam_sim_free(hpt_vsim, /*free devq*/ TRUE); 2121136849Sscottl hpt_vsim = NULL; 2122136849Sscottl return ENXIO; 2123136849Sscottl } 2124136849Sscottl 2125136849Sscottl if(xpt_create_path(&pAdapter->path, /*periph */ NULL, 2126149871Sscottl cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, 2127149871Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) 2128149871Sscottl { 2129136849Sscottl xpt_bus_deregister(cam_sim_path(hpt_vsim)); 2130136849Sscottl cam_sim_free(hpt_vsim, /*free_devq*/TRUE); 2131136849Sscottl hpt_vsim = NULL; 2132136849Sscottl return ENXIO; 2133136849Sscottl } 2134136849Sscottl 2135136849Sscottl xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5); 2136136849Sscottl ccb->ccb_h.func_code = XPT_SASYNC_CB; 2137136849Sscottl ccb->csa.event_enable = AC_LOST_DEVICE; 2138136849Sscottl ccb->csa.callback = hpt_async; 2139136849Sscottl ccb->csa.callback_arg = hpt_vsim; 2140136849Sscottl xpt_action((union ccb *)ccb); 2141136849Sscottl free(ccb, M_DEVBUF); 2142136849Sscottl 2143190863Sdelphij if (device_get_unit(dev) == 0) { 2144190810Sdelphij /* Start the work thread. XXX */ 2145190810Sdelphij launch_worker_thread(); 2146139044Snjl } 2147136849Sscottl 2148136849Sscottl return 0; 2149136849Sscottl} 2150136849Sscottl 2151136849Sscottlstatic int 2152136849Sscottlhpt_detach(device_t dev) 2153149871Sscottl{ 2154136849Sscottl return (EBUSY); 2155136849Sscottl} 2156136849Sscottl 2157149871Sscottl 2158136849Sscottl/*************************************************************** 2159136849Sscottl * The poll function is used to simulate the interrupt when 2160136849Sscottl * the interrupt subsystem is not functioning. 2161136849Sscottl * 2162136849Sscottl ***************************************************************/ 2163136849Sscottlstatic void 2164136849Sscottlhpt_poll(struct cam_sim *sim) 2165136849Sscottl{ 2166136849Sscottl hpt_intr((void *)cam_sim_softc(sim)); 2167136849Sscottl} 2168136849Sscottl 2169136849Sscottl/**************************************************************** 2170136849Sscottl * Name: hpt_intr 2171136849Sscottl * Description: Interrupt handler. 2172136849Sscottl ****************************************************************/ 2173136849Sscottlstatic void 2174136849Sscottlhpt_intr(void *arg) 2175136849Sscottl{ 2176136849Sscottl IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg; 2177149871Sscottl intrmask_t oldspl = lock_driver(); 2178136849Sscottl 2179136849Sscottl /* KdPrintI(("----- Entering Isr() -----\n")); */ 2180149871Sscottl if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE) 2181149871Sscottl { 2182136849Sscottl _VBUS_INST(&pAdapter->VBus) 2183136849Sscottl CheckPendingCall(_VBUS_P0); 2184136849Sscottl } 2185136849Sscottl 2186136849Sscottl /* KdPrintI(("----- Leaving Isr() -----\n")); */ 2187136849Sscottl unlock_driver(oldspl); 2188136849Sscottl} 2189136849Sscottl 2190136849Sscottl/********************************************************** 2191136849Sscottl * Asynchronous Events 2192136849Sscottl *********************************************************/ 2193136849Sscottl#if (!defined(UNREFERENCED_PARAMETER)) 2194136849Sscottl#define UNREFERENCED_PARAMETER(x) (void)(x) 2195136849Sscottl#endif 2196136849Sscottl 2197136849Sscottlstatic void 2198136849Sscottlhpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, 2199136849Sscottl void * arg) 2200136849Sscottl{ 2201136849Sscottl /* debug XXXX */ 2202136849Sscottl panic("Here"); 2203136849Sscottl UNREFERENCED_PARAMETER(callback_arg); 2204136849Sscottl UNREFERENCED_PARAMETER(code); 2205136849Sscottl UNREFERENCED_PARAMETER(path); 2206136849Sscottl UNREFERENCED_PARAMETER(arg); 2207136849Sscottl 2208136849Sscottl} 2209136849Sscottl 2210136849Sscottlstatic void 2211136849SscottlFlushAdapter(IAL_ADAPTER_T *pAdapter) 2212136849Sscottl{ 2213136849Sscottl int i; 2214136849Sscottl 2215136849Sscottl hpt_printk(("flush all devices\n")); 2216136849Sscottl 2217136849Sscottl /* flush all devices */ 2218136849Sscottl for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) { 2219136849Sscottl PVDevice pVDev = pAdapter->VBus.pVDevice[i]; 2220149871Sscottl if(pVDev) fFlushVDev(pVDev); 2221136849Sscottl } 2222136849Sscottl} 2223136849Sscottl 2224136849Sscottlstatic int 2225136849Sscottlhpt_shutdown(device_t dev) 2226136849Sscottl{ 2227149871Sscottl IAL_ADAPTER_T *pAdapter; 2228149871Sscottl 2229149871Sscottl pAdapter = device_get_softc(dev); 2230149871Sscottl if (pAdapter == NULL) 2231149871Sscottl return (EINVAL); 2232136849Sscottl 2233149871Sscottl EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh); 2234149871Sscottl FlushAdapter(pAdapter); 2235149871Sscottl /* give the flush some time to happen, 2236149871Sscottl *otherwise "shutdown -p now" will make file system corrupted */ 2237149871Sscottl DELAY(1000 * 1000 * 5); 2238149871Sscottl return 0; 2239136849Sscottl} 2240136849Sscottl 2241136849Sscottlvoid 2242136849SscottlCheck_Idle_Call(IAL_ADAPTER_T *pAdapter) 2243136849Sscottl{ 2244136849Sscottl _VBUS_INST(&pAdapter->VBus) 2245136849Sscottl 2246136849Sscottl if (mWaitingForIdle(_VBUS_P0)) { 2247136849Sscottl CheckIdleCall(_VBUS_P0); 2248136849Sscottl#ifdef SUPPORT_ARRAY 2249149871Sscottl { 2250149871Sscottl int i; 2251136849Sscottl PVDevice pArray; 2252149871Sscottl for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ 2253149871Sscottl if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 2254149871Sscottl continue; 2255149871Sscottl else if (pArray->u.array.rf_auto_rebuild) { 2256149871Sscottl KdPrint(("auto rebuild.\n")); 2257149871Sscottl pArray->u.array.rf_auto_rebuild = 0; 2258149871Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 2259149871Sscottl } 2260136849Sscottl } 2261136849Sscottl } 2262136849Sscottl#endif 2263136849Sscottl } 2264136849Sscottl /* launch the awaiting commands blocked by mWaitingForIdle */ 2265149871Sscottl while(pAdapter->pending_Q!= NULL) 2266149871Sscottl { 2267136849Sscottl _VBUS_INST(&pAdapter->VBus) 2268149871Sscottl union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; 2269136849Sscottl hpt_free_ccb(&pAdapter->pending_Q, ccb); 2270136849Sscottl CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb); 2271136849Sscottl } 2272136849Sscottl} 2273136849Sscottl 2274136849Sscottlstatic void 2275136849Sscottlccb_done(union ccb *ccb) 2276136849Sscottl{ 2277149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2278149871Sscottl IAL_ADAPTER_T * pAdapter = pmap->pAdapter; 2279149871Sscottl KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status)); 2280136849Sscottl 2281149871Sscottl dmamap_put(pmap); 2282136849Sscottl xpt_done(ccb); 2283136849Sscottl 2284136849Sscottl pAdapter->outstandingCommands--; 2285136849Sscottl 2286149871Sscottl if (pAdapter->outstandingCommands == 0) 2287149871Sscottl { 2288136849Sscottl if(DPC_Request_Nums == 0) 2289136849Sscottl Check_Idle_Call(pAdapter); 2290136849Sscottl } 2291136849Sscottl} 2292136849Sscottl 2293136849Sscottl/**************************************************************** 2294136849Sscottl * Name: hpt_action 2295136849Sscottl * Description: Process a queued command from the CAM layer. 2296136849Sscottl * Parameters: sim - Pointer to SIM object 2297136849Sscottl * ccb - Pointer to SCSI command structure. 2298136849Sscottl ****************************************************************/ 2299136849Sscottl 2300136849Sscottlvoid 2301136849Sscottlhpt_action(struct cam_sim *sim, union ccb *ccb) 2302136849Sscottl{ 2303136849Sscottl intrmask_t oldspl; 2304136849Sscottl IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim); 2305149871Sscottl PBUS_DMAMAP pmap; 2306136849Sscottl _VBUS_INST(&pAdapter->VBus) 2307136849Sscottl 2308149878Sscottl CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n")); 2309149871Sscottl KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code)); 2310136849Sscottl 2311149871Sscottl switch (ccb->ccb_h.func_code) 2312149871Sscottl { 2313149871Sscottl case XPT_SCSI_IO: /* Execute the requested I/O operation */ 2314149871Sscottl { 2315149871Sscottl /* ccb->ccb_h.path_id is not our bus id - don't check it */ 2316136849Sscottl 2317149871Sscottl if (ccb->ccb_h.target_lun) { 2318149871Sscottl ccb->ccb_h.status = CAM_LUN_INVALID; 2319149871Sscottl xpt_done(ccb); 2320149871Sscottl return; 2321149871Sscottl } 2322149871Sscottl if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || 2323149871Sscottl pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { 2324149871Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 2325149871Sscottl xpt_done(ccb); 2326149871Sscottl return; 2327149871Sscottl } 2328136849Sscottl 2329149871Sscottl oldspl = lock_driver(); 2330149871Sscottl if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 2331149871Sscottl Check_Idle_Call(pAdapter); 2332136849Sscottl 2333149871Sscottl pmap = dmamap_get(pAdapter); 2334149871Sscottl HPT_ASSERT(pmap); 2335149871Sscottl ccb->ccb_adapter = pmap; 2336149871Sscottl memset((void *)pmap->psg, 0, sizeof(pmap->psg)); 2337136849Sscottl 2338149871Sscottl if (mWaitingForIdle(_VBUS_P0)) 2339149871Sscottl hpt_queue_ccb(&pAdapter->pending_Q, ccb); 2340149871Sscottl else 2341149871Sscottl OsSendCommand(_VBUS_P ccb); 2342149871Sscottl unlock_driver(oldspl); 2343136849Sscottl 2344149871Sscottl /* KdPrint(("leave scsiio\n")); */ 2345149871Sscottl break; 2346149871Sscottl } 2347136849Sscottl 2348149871Sscottl case XPT_RESET_BUS: 2349149871Sscottl KdPrint(("reset bus\n")); 2350149871Sscottl oldspl = lock_driver(); 2351149871Sscottl fResetVBus(_VBUS_P0); 2352149871Sscottl unlock_driver(oldspl); 2353149871Sscottl xpt_done(ccb); 2354149871Sscottl break; 2355136849Sscottl 2356149871Sscottl case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 2357149871Sscottl case XPT_EN_LUN: /* Enable LUN as a target */ 2358149871Sscottl case XPT_TARGET_IO: /* Execute target I/O request */ 2359149871Sscottl case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 2360149871Sscottl case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 2361149871Sscottl case XPT_ABORT: /* Abort the specified CCB */ 2362149871Sscottl case XPT_TERM_IO: /* Terminate the I/O process */ 2363149871Sscottl /* XXX Implement */ 2364149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2365149871Sscottl xpt_done(ccb); 2366149871Sscottl break; 2367136849Sscottl 2368149871Sscottl case XPT_GET_TRAN_SETTINGS: 2369149871Sscottl case XPT_SET_TRAN_SETTINGS: 2370149871Sscottl /* XXX Implement */ 2371149871Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2372149871Sscottl xpt_done(ccb); 2373149871Sscottl break; 2374136849Sscottl 2375149871Sscottl case XPT_CALC_GEOMETRY: 2376227912Smarius#if __FreeBSD_version >= 500000 2377227912Smarius cam_calc_geometry(&ccb->ccg, 1); 2378227912Smarius#else 2379227912Smarius { 2380149871Sscottl struct ccb_calc_geometry *ccg; 2381149871Sscottl u_int32_t size_mb; 2382149871Sscottl u_int32_t secs_per_cylinder; 2383136849Sscottl 2384149871Sscottl ccg = &ccb->ccg; 2385149871Sscottl size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); 2386149871Sscottl 2387149871Sscottl if (size_mb > 1024 ) { 2388149871Sscottl ccg->heads = 255; 2389149871Sscottl ccg->secs_per_track = 63; 2390149871Sscottl } else { 2391149871Sscottl ccg->heads = 64; 2392149871Sscottl ccg->secs_per_track = 32; 2393149871Sscottl } 2394149871Sscottl secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2395149871Sscottl ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2396149871Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 2397227912Smarius } 2398227912Smarius#endif 2399149871Sscottl xpt_done(ccb); 2400149871Sscottl break; 2401136849Sscottl 2402149871Sscottl case XPT_PATH_INQ: /* Path routing inquiry */ 2403149871Sscottl { 2404149871Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 2405136849Sscottl 2406149871Sscottl cpi->version_num = 1; /* XXX??? */ 2407149871Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 2408149871Sscottl cpi->target_sprt = 0; 2409149871Sscottl /* Not necessary to reset bus */ 2410149871Sscottl cpi->hba_misc = PIM_NOBUSRESET; 2411149871Sscottl cpi->hba_eng_cnt = 0; 2412136849Sscottl 2413149871Sscottl cpi->max_target = MAX_VDEVICE_PER_VBUS; 2414149871Sscottl cpi->max_lun = 0; 2415149871Sscottl cpi->initiator_id = MAX_VDEVICE_PER_VBUS; 2416136849Sscottl 2417149871Sscottl cpi->bus_id = cam_sim_bus(sim); 2418149871Sscottl cpi->base_transfer_speed = 3300; 2419149871Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2420149871Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 2421149871Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2422149871Sscottl cpi->unit_number = cam_sim_unit(sim); 2423209341Smav cpi->transport = XPORT_SPI; 2424209341Smav cpi->transport_version = 2; 2425209341Smav cpi->protocol = PROTO_SCSI; 2426209341Smav cpi->protocol_version = SCSI_REV_2; 2427149871Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 2428149871Sscottl xpt_done(ccb); 2429149871Sscottl break; 2430149871Sscottl } 2431136849Sscottl 2432149871Sscottl default: 2433149871Sscottl KdPrint(("invalid cmd\n")); 2434149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2435149871Sscottl xpt_done(ccb); 2436149871Sscottl break; 2437136849Sscottl } 2438136849Sscottl /* KdPrint(("leave hpt_action..............\n")); */ 2439136849Sscottl} 2440136849Sscottl 2441136849Sscottl/* shall be called at lock_driver() */ 2442136849Sscottlstatic void 2443136849Sscottlhpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb) 2444136849Sscottl{ 2445136849Sscottl if(*ccb_Q == NULL) 2446136849Sscottl ccb->ccb_h.ccb_ccb_ptr = ccb; 2447136849Sscottl else { 2448136849Sscottl ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr; 2449136849Sscottl (*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb; 2450136849Sscottl } 2451136849Sscottl 2452136849Sscottl *ccb_Q = ccb; 2453136849Sscottl} 2454136849Sscottl 2455136849Sscottl/* shall be called at lock_driver() */ 2456136849Sscottlstatic void 2457136849Sscottlhpt_free_ccb(union ccb **ccb_Q, union ccb *ccb) 2458136849Sscottl{ 2459136849Sscottl union ccb *TempCCB; 2460136849Sscottl 2461136849Sscottl TempCCB = *ccb_Q; 2462136849Sscottl 2463149871Sscottl if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/ 2464136849Sscottl *ccb_Q = NULL; 2465136849Sscottl else { 2466136849Sscottl while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb) 2467136849Sscottl TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr; 2468136849Sscottl 2469136849Sscottl TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr; 2470136849Sscottl 2471136849Sscottl if(*ccb_Q == ccb) 2472136849Sscottl *ccb_Q = TempCCB; 2473136849Sscottl } 2474136849Sscottl} 2475136849Sscottl 2476136849Sscottl#ifdef SUPPORT_ARRAY 2477136849Sscottl/*************************************************************************** 2478136849Sscottl * Function: hpt_worker_thread 2479136849Sscottl * Description: Do background rebuilding. Execute in kernel thread context. 2480136849Sscottl * Returns: None 2481136849Sscottl ***************************************************************************/ 2482136849Sscottlstatic void hpt_worker_thread(void) 2483136849Sscottl{ 2484136849Sscottl intrmask_t oldspl; 2485136849Sscottl 2486136849Sscottl for(;;) { 2487136849Sscottl while (DpcQueue_First!=DpcQueue_Last) { 2488136849Sscottl ST_HPT_DPC p; 2489136849Sscottl oldspl = lock_driver(); 2490136849Sscottl p = DpcQueue[DpcQueue_First]; 2491136849Sscottl DpcQueue_First++; 2492136849Sscottl DpcQueue_First %= MAX_DPC; 2493136849Sscottl DPC_Request_Nums++; 2494136849Sscottl unlock_driver(oldspl); 2495136849Sscottl p.dpc(p.pAdapter, p.arg, p.flags); 2496136849Sscottl 2497136849Sscottl oldspl = lock_driver(); 2498136849Sscottl DPC_Request_Nums--; 2499149871Sscottl /* since we may have prevented Check_Idle_Call, do it here */ 2500136849Sscottl if (DPC_Request_Nums==0) { 2501136849Sscottl if (p.pAdapter->outstandingCommands == 0) { 2502136849Sscottl _VBUS_INST(&p.pAdapter->VBus); 2503136849Sscottl Check_Idle_Call(p.pAdapter); 2504136849Sscottl CheckPendingCall(_VBUS_P0); 2505136849Sscottl } 2506136849Sscottl } 2507136849Sscottl unlock_driver(oldspl); 2508136849Sscottl 2509149871Sscottl /*Schedule out*/ 2510149871Sscottl#if (__FreeBSD_version < 500000) 2511149871Sscottl YIELD_THREAD; 2512149871Sscottl#else 2513190809Sdelphij#if (__FreeBSD_version > 700033) 2514167086Sjhb pause("sched", 1); 2515190809Sdelphij#else 2516190809Sdelphij tsleep((caddr_t)hpt_worker_thread, PPAUSE, "sched", 1); 2517149871Sscottl#endif 2518190809Sdelphij#endif 2519149871Sscottl if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) { 2520149871Sscottl /* abort rebuilding process. */ 2521149871Sscottl IAL_ADAPTER_T *pAdapter; 2522149871Sscottl PVDevice pArray; 2523149871Sscottl PVBus _vbus_p; 2524149871Sscottl int i; 2525149871Sscottl pAdapter = gIal_Adapter; 2526149871Sscottl 2527149871Sscottl while(pAdapter != 0){ 2528149871Sscottl 2529149871Sscottl _vbus_p = &pAdapter->VBus; 2530149871Sscottl 2531149871Sscottl for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 2532149871Sscottl { 2533149871Sscottl if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 2534149871Sscottl continue; 2535149871Sscottl else if (pArray->u.array.rf_rebuilding || 2536149871Sscottl pArray->u.array.rf_verifying || 2537149871Sscottl pArray->u.array.rf_initializing) 2538149871Sscottl { 2539149871Sscottl pArray->u.array.rf_abort_rebuild = 1; 2540149871Sscottl } 2541136849Sscottl } 2542149871Sscottl pAdapter = pAdapter->next; 2543136849Sscottl } 2544136849Sscottl } 2545136849Sscottl } 2546136849Sscottl 2547149871Sscottl/*Remove this debug option*/ 2548149871Sscottl/* 2549136849Sscottl#ifdef DEBUG 2550136849Sscottl if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) 2551190809Sdelphij#if (__FreeBSD_version > 700033) 2552167086Sjhb pause("hptrdy", 2*hz); 2553190809Sdelphij#else 2554190809Sdelphij tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz); 2555136849Sscottl#endif 2556190809Sdelphij#endif 2557149871Sscottl*/ 2558190809Sdelphij #if (__FreeBSD_version >= 800002) 2559172836Sjulian kproc_suspend_check(curproc); 2560190809Sdelphij #elif (__FreeBSD_version >= 500043) 2561190809Sdelphij kthread_suspend_check(curproc); 2562149871Sscottl #else 2563136849Sscottl kproc_suspend_loop(curproc); 2564149871Sscottl #endif 2565190809Sdelphij#if (__FreeBSD_version > 700033) 2566167086Sjhb pause("hptrdy", 2*hz); /* wait for something to do */ 2567190809Sdelphij#else 2568190809Sdelphij tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz); /* wait for something to do */ 2569190809Sdelphij#endif 2570136849Sscottl } 2571136849Sscottl} 2572136849Sscottl 2573136849Sscottlstatic struct proc *hptdaemonproc; 2574136849Sscottlstatic struct kproc_desc hpt_kp = { 2575136849Sscottl "hpt_wt", 2576136849Sscottl hpt_worker_thread, 2577136849Sscottl &hptdaemonproc 2578136849Sscottl}; 2579136849Sscottl 2580149871Sscottl/*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/ 2581136849Sscottlstatic void 2582136849Sscottllaunch_worker_thread(void) 2583136849Sscottl{ 2584136849Sscottl IAL_ADAPTER_T *pAdapTemp; 2585136849Sscottl 2586136849Sscottl kproc_start(&hpt_kp); 2587136849Sscottl 2588136849Sscottl for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 2589136849Sscottl 2590136849Sscottl _VBUS_INST(&pAdapTemp->VBus) 2591136849Sscottl int i; 2592136849Sscottl PVDevice pVDev; 2593136849Sscottl 2594136849Sscottl for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 2595136849Sscottl if ((pVDev=ArrayTables(i))->u.array.dArStamp==0) 2596136849Sscottl continue; 2597149871Sscottl else{ 2598149871Sscottl if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding) 2599149871Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev, 2600149871Sscottl (UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 2601149871Sscottl } 2602136849Sscottl } 2603136849Sscottl 2604136849Sscottl /* 2605149871Sscottl * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished. 2606136849Sscottl */ 2607136849Sscottl#if (__FreeBSD_version < 500043) 2608149871Sscottl EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST); 2609149871Sscottl#else 2610149871Sscottl EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, SHUTDOWN_PRI_FIRST); 2611136849Sscottl#endif 2612136849Sscottl} 2613149871Sscottl/* 2614149871Sscottl *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL); 2615149871Sscottl*/ 2616136849Sscottl 2617149871Sscottl#endif 2618136849Sscottl 2619136849Sscottl/********************************************************************************/ 2620136849Sscottl 2621149871Sscottlint HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) 2622136849Sscottl{ 2623149871Sscottl union ccb *ccb = (union ccb *)pCmd->pOrgCommand; 2624149871Sscottl bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 2625136849Sscottl int idx; 2626136849Sscottl 2627149871Sscottl if(logical) { 2628149871Sscottl if (ccb->ccb_h.flags & CAM_DATA_PHYS) 2629149871Sscottl panic("physical address unsupported"); 2630136849Sscottl 2631149871Sscottl if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2632149871Sscottl if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 2633149871Sscottl panic("physical address unsupported"); 2634149871Sscottl 2635149871Sscottl for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 2636149871Sscottl pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 2637149871Sscottl pSg[idx].wSgSize = sgList[idx].ds_len; 2638149871Sscottl pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0; 2639149871Sscottl } 2640149871Sscottl } 2641149871Sscottl else { 2642149871Sscottl pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; 2643149871Sscottl pSg->wSgSize = ccb->csio.dxfer_len; 2644149871Sscottl pSg->wSgFlag = SG_FLAG_EOT; 2645149871Sscottl } 2646136849Sscottl return TRUE; 2647136849Sscottl } 2648149871Sscottl 2649149871Sscottl /* since we have provided physical sg, nobody will ask us to build physical sg */ 2650149871Sscottl HPT_ASSERT(0); 2651149871Sscottl return FALSE; 2652136849Sscottl} 2653136849Sscottl 2654136849Sscottl/*******************************************************************************/ 2655136849SscottlULONG HPTLIBAPI 2656136849SscottlGetStamp(void) 2657136849Sscottl{ 2658136849Sscottl /* 2659136849Sscottl * the system variable, ticks, can't be used since it hasn't yet been active 2660136849Sscottl * when our driver starts (ticks==0, it's a invalid stamp value) 2661136849Sscottl */ 2662149871Sscottl ULONG stamp; 2663149871Sscottl do { stamp = random(); } while (stamp==0); 2664136849Sscottl return stamp; 2665136849Sscottl} 2666136849Sscottl 2667136849Sscottl 2668136849Sscottlstatic void 2669136849SscottlSetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) 2670136849Sscottl{ 2671136849Sscottl int i; 2672149871Sscottl IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; 2673149871Sscottl 2674136849Sscottl inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/ 2675136849Sscottl inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5); 2676136849Sscottl#ifndef SERIAL_CMDS 2677136849Sscottl inquiryData->CommandQueue = 1; 2678136849Sscottl#endif 2679136849Sscottl 2680136849Sscottl switch(pVDev->VDeviceType) { 2681136849Sscottl case VD_SINGLE_DISK: 2682136849Sscottl case VD_ATAPI: 2683136849Sscottl case VD_REMOVABLE: 2684136849Sscottl /* Set the removable bit, if applicable. */ 2685149871Sscottl if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80)) 2686136849Sscottl inquiryData->RemovableMedia = 1; 2687136849Sscottl 2688136849Sscottl /* Fill in vendor identification fields. */ 2689149871Sscottl for (i = 0; i < 20; i += 2) { 2690149871Sscottl inquiryData->VendorId[i] = ((PUCHAR)pIdentify->ModelNumber)[i + 1]; 2691149871Sscottl inquiryData->VendorId[i+1] = ((PUCHAR)pIdentify->ModelNumber)[i]; 2692136849Sscottl 2693136849Sscottl } 2694136849Sscottl 2695136849Sscottl /* Initialize unused portion of product id. */ 2696136849Sscottl for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' '; 2697136849Sscottl 2698136849Sscottl /* firmware revision */ 2699149871Sscottl for (i = 0; i < 4; i += 2) 2700149871Sscottl { 2701149871Sscottl inquiryData->ProductRevisionLevel[i] = ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; 2702149871Sscottl inquiryData->ProductRevisionLevel[i+1] = ((PUCHAR)pIdentify->FirmwareRevision)[i]; 2703136849Sscottl } 2704136849Sscottl break; 2705136849Sscottl default: 2706190809Sdelphij memcpy(&inquiryData->VendorId, "RR18xx ", 8); 2707136849Sscottl#ifdef SUPPORT_ARRAY 2708149871Sscottl switch(pVDev->VDeviceType){ 2709136849Sscottl case VD_RAID_0: 2710149871Sscottl if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2711149871Sscottl (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2712149871Sscottl memcpy(&inquiryData->ProductId, "RAID 1/0 Array ", 16); 2713136849Sscottl else 2714149871Sscottl memcpy(&inquiryData->ProductId, "RAID 0 Array ", 16); 2715136849Sscottl break; 2716136849Sscottl case VD_RAID_1: 2717149871Sscottl if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2718149871Sscottl (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2719149871Sscottl memcpy(&inquiryData->ProductId, "RAID 0/1 Array ", 16); 2720136849Sscottl else 2721149871Sscottl memcpy(&inquiryData->ProductId, "RAID 1 Array ", 16); 2722136849Sscottl break; 2723136849Sscottl case VD_RAID_5: 2724136849Sscottl memcpy(&inquiryData->ProductId, "RAID 5 Array ", 16); 2725136849Sscottl break; 2726136849Sscottl case VD_JBOD: 2727136849Sscottl memcpy(&inquiryData->ProductId, "JBOD Array ", 16); 2728136849Sscottl break; 2729136849Sscottl } 2730136849Sscottl#endif 2731136849Sscottl memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4); 2732136849Sscottl break; 2733136849Sscottl } 2734136849Sscottl} 2735136849Sscottl 2736136849Sscottlstatic void 2737136849Sscottlhpt_timeout(void *arg) 2738136849Sscottl{ 2739149871Sscottl _VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus) 2740149871Sscottl intrmask_t oldspl = lock_driver(); 2741136849Sscottl fResetVBus(_VBUS_P0); 2742136849Sscottl unlock_driver(oldspl); 2743136849Sscottl} 2744136849Sscottl 2745149871Sscottlstatic void 2746149871Sscottlhpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 2747149871Sscottl{ 2748149871Sscottl PCommand pCmd = (PCommand)arg; 2749149871Sscottl union ccb *ccb = pCmd->pOrgCommand; 2750149871Sscottl struct ccb_hdr *ccb_h = &ccb->ccb_h; 2751149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter; 2752149871Sscottl IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2753149871Sscottl PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2754149871Sscottl FPSCAT_GATH psg = pCmd->pSgTable; 2755149871Sscottl int idx; 2756149871Sscottl _VBUS_INST(pVDev->pVBus) 2757149871Sscottl 2758149871Sscottl HPT_ASSERT(pCmd->cf_physical_sg); 2759149871Sscottl 2760149871Sscottl if (error || nsegs == 0) 2761149871Sscottl panic("busdma error"); 2762149871Sscottl 2763149871Sscottl HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); 2764149871Sscottl 2765149871Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2766149871Sscottl psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; 2767149871Sscottl psg->wSgSize = segs[idx].ds_len; 2768149871Sscottl psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; 2769149871Sscottl/* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ 2770149871Sscottl } 2771149871Sscottl/* psg[-1].wSgFlag = SG_FLAG_EOT; */ 2772149871Sscottl 2773149871Sscottl if (pCmd->cf_data_in) { 2774149871Sscottl bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD); 2775149871Sscottl } 2776149871Sscottl else if (pCmd->cf_data_out) { 2777149871Sscottl bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE); 2778149871Sscottl } 2779149871Sscottl 2780149871Sscottl ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); 2781149871Sscottl pVDev->pfnSendCommand(_VBUS_P pCmd); 2782149871Sscottl CheckPendingCall(_VBUS_P0); 2783149871Sscottl} 2784149871Sscottl 2785149871Sscottl 2786149871Sscottl 2787136849Sscottlstatic void HPTLIBAPI 2788136849SscottlOsSendCommand(_VBUS_ARG union ccb *ccb) 2789136849Sscottl{ 2790149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2791149871Sscottl IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2792149871Sscottl struct ccb_hdr *ccb_h = &ccb->ccb_h; 2793149871Sscottl struct ccb_scsiio *csio = &ccb->csio; 2794149871Sscottl PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2795136849Sscottl 2796149871Sscottl KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", 2797136849Sscottl ccb, 2798136849Sscottl *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0], 2799136849Sscottl *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4], 2800136849Sscottl *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8] 2801136849Sscottl )); 2802136849Sscottl 2803136849Sscottl pAdapter->outstandingCommands++; 2804136849Sscottl 2805136849Sscottl if (pVDev == NULL || pVDev->vf_online == 0) { 2806136849Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2807136849Sscottl ccb_done(ccb); 2808136849Sscottl goto Command_Complished; 2809136849Sscottl } 2810136849Sscottl 2811136849Sscottl switch(ccb->csio.cdb_io.cdb_bytes[0]) 2812136849Sscottl { 2813149871Sscottl case TEST_UNIT_READY: 2814149871Sscottl case START_STOP_UNIT: 2815149871Sscottl case SYNCHRONIZE_CACHE: 2816149871Sscottl /* FALLTHROUGH */ 2817149871Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 2818149871Sscottl break; 2819136849Sscottl 2820149871Sscottl case INQUIRY: 2821149871Sscottl ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); 2822149871Sscottl SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); 2823149871Sscottl ccb_h->status = CAM_REQ_CMP; 2824149871Sscottl break; 2825136849Sscottl 2826149871Sscottl case READ_CAPACITY: 2827149871Sscottl { 2828190809Sdelphij UCHAR *rbuf=csio->data_ptr; 2829190809Sdelphij unsigned int cap; 2830190809Sdelphij 2831190809Sdelphij if (pVDev->VDeviceCapacity > 0xfffffffful) { 2832190809Sdelphij cap = 0xfffffffful; 2833190809Sdelphij } else { 2834190809Sdelphij cap = pVDev->VDeviceCapacity - 1; 2835190809Sdelphij } 2836190809Sdelphij 2837190809Sdelphij rbuf[0] = (UCHAR)(cap>>24); 2838190809Sdelphij rbuf[1] = (UCHAR)(cap>>16); 2839190809Sdelphij rbuf[2] = (UCHAR)(cap>>8); 2840190809Sdelphij rbuf[3] = (UCHAR)cap; 2841149871Sscottl /* Claim 512 byte blocks (big-endian). */ 2842190809Sdelphij rbuf[4] = 0; 2843190809Sdelphij rbuf[5] = 0; 2844190809Sdelphij rbuf[6] = 2; 2845190809Sdelphij rbuf[7] = 0; 2846190809Sdelphij 2847149871Sscottl ccb_h->status = CAM_REQ_CMP; 2848149871Sscottl break; 2849136849Sscottl } 2850136849Sscottl 2851190809Sdelphij case 0x9e: /*SERVICE_ACTION_IN*/ 2852190809Sdelphij { 2853190809Sdelphij UCHAR *rbuf = csio->data_ptr; 2854190809Sdelphij LBA_T cap = pVDev->VDeviceCapacity - 1; 2855190809Sdelphij 2856190809Sdelphij rbuf[0] = (UCHAR)(cap>>56); 2857190809Sdelphij rbuf[1] = (UCHAR)(cap>>48); 2858190809Sdelphij rbuf[2] = (UCHAR)(cap>>40); 2859190809Sdelphij rbuf[3] = (UCHAR)(cap>>32); 2860190809Sdelphij rbuf[4] = (UCHAR)(cap>>24); 2861190809Sdelphij rbuf[5] = (UCHAR)(cap>>16); 2862190809Sdelphij rbuf[6] = (UCHAR)(cap>>8); 2863190809Sdelphij rbuf[7] = (UCHAR)cap; 2864190809Sdelphij rbuf[8] = 0; 2865190809Sdelphij rbuf[9] = 0; 2866190809Sdelphij rbuf[10] = 2; 2867190809Sdelphij rbuf[11] = 0; 2868190809Sdelphij 2869190809Sdelphij ccb_h->status = CAM_REQ_CMP; 2870190809Sdelphij break; 2871190809Sdelphij } 2872190809Sdelphij 2873136849Sscottl case READ_6: 2874136849Sscottl case WRITE_6: 2875136849Sscottl case READ_10: 2876136849Sscottl case WRITE_10: 2877190809Sdelphij case 0x88: /* READ_16 */ 2878190809Sdelphij case 0x8a: /* WRITE_16 */ 2879136849Sscottl case 0x13: 2880136849Sscottl case 0x2f: 2881149871Sscottl { 2882149871Sscottl UCHAR Cdb[16]; 2883149871Sscottl UCHAR CdbLength; 2884149871Sscottl _VBUS_INST(pVDev->pVBus) 2885149871Sscottl PCommand pCmd = AllocateCommand(_VBUS_P0); 2886149871Sscottl HPT_ASSERT(pCmd); 2887136849Sscottl 2888149871Sscottl CdbLength = csio->cdb_len; 2889149871Sscottl if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) 2890149871Sscottl { 2891149871Sscottl if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) 2892149871Sscottl { 2893149871Sscottl bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); 2894149871Sscottl } 2895149871Sscottl else 2896149871Sscottl { 2897149871Sscottl KdPrintE(("ERROR!!!\n")); 2898149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2899149871Sscottl break; 2900149871Sscottl } 2901149871Sscottl } 2902149871Sscottl else 2903149871Sscottl { 2904149871Sscottl bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); 2905149871Sscottl } 2906136849Sscottl 2907149871Sscottl pCmd->pOrgCommand = ccb; 2908149871Sscottl pCmd->pVDevice = pVDev; 2909149871Sscottl pCmd->pfnCompletion = fOsCommandDone; 2910149871Sscottl pCmd->pfnBuildSgl = fOsBuildSgl; 2911149871Sscottl pCmd->pSgTable = pmap->psg; 2912136849Sscottl 2913149871Sscottl switch (Cdb[0]) 2914149871Sscottl { 2915149871Sscottl case READ_6: 2916149871Sscottl case WRITE_6: 2917149871Sscottl case 0x13: 2918149871Sscottl pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; 2919149871Sscottl pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; 2920149871Sscottl break; 2921149871Sscottl 2922190809Sdelphij case 0x88: /* READ_16 */ 2923190809Sdelphij case 0x8a: /* WRITE_16 */ 2924190809Sdelphij pCmd->uCmd.Ide.Lba = 2925190809Sdelphij (HPT_U64)Cdb[2] << 56 | 2926190809Sdelphij (HPT_U64)Cdb[3] << 48 | 2927190809Sdelphij (HPT_U64)Cdb[4] << 40 | 2928190809Sdelphij (HPT_U64)Cdb[5] << 32 | 2929190809Sdelphij (HPT_U64)Cdb[6] << 24 | 2930190809Sdelphij (HPT_U64)Cdb[7] << 16 | 2931190809Sdelphij (HPT_U64)Cdb[8] << 8 | 2932190809Sdelphij (HPT_U64)Cdb[9]; 2933190809Sdelphij pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13]; 2934190809Sdelphij break; 2935190809Sdelphij 2936149871Sscottl default: 2937149871Sscottl pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24); 2938149871Sscottl pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8); 2939149871Sscottl break; 2940149871Sscottl } 2941149871Sscottl 2942149871Sscottl switch (Cdb[0]) 2943149871Sscottl { 2944149871Sscottl case READ_6: 2945149871Sscottl case READ_10: 2946190809Sdelphij case 0x88: /* READ_16 */ 2947149871Sscottl pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; 2948149871Sscottl pCmd->cf_data_in = 1; 2949149871Sscottl break; 2950149871Sscottl 2951149871Sscottl case WRITE_6: 2952149871Sscottl case WRITE_10: 2953190809Sdelphij case 0x8a: /* WRITE_16 */ 2954149871Sscottl pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; 2955149871Sscottl pCmd->cf_data_out = 1; 2956149871Sscottl break; 2957149871Sscottl case 0x13: 2958149871Sscottl case 0x2f: 2959149871Sscottl pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; 2960149871Sscottl break; 2961149871Sscottl } 2962149871Sscottl/*///////////////////////// */ 2963149871Sscottl if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2964149871Sscottl int idx; 2965149871Sscottl bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 2966149871Sscottl 2967149871Sscottl if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 2968149871Sscottl pCmd->cf_physical_sg = 1; 2969149871Sscottl 2970149871Sscottl for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 2971149871Sscottl pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 2972149871Sscottl pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len; 2973149871Sscottl pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0; 2974149871Sscottl } 2975149871Sscottl 2976149871Sscottl ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); 2977149871Sscottl pVDev->pfnSendCommand(_VBUS_P pCmd); 2978149871Sscottl } 2979149871Sscottl else { 2980149871Sscottl int error; 2981149871Sscottl pCmd->cf_physical_sg = 1; 2982149871Sscottl error = bus_dmamap_load(pAdapter->io_dma_parent, 2983149871Sscottl pmap->dma_map, 2984149871Sscottl ccb->csio.data_ptr, ccb->csio.dxfer_len, 2985149871Sscottl hpt_io_dmamap_callback, pCmd, 2986149871Sscottl BUS_DMA_WAITOK 2987149871Sscottl ); 2988149871Sscottl KdPrint(("bus_dmamap_load return %d\n", error)); 2989149871Sscottl if (error && error!=EINPROGRESS) { 2990149871Sscottl hpt_printk(("bus_dmamap_load error %d\n", error)); 2991149871Sscottl FreeCommand(_VBUS_P pCmd); 2992149871Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2993149871Sscottl dmamap_put(pmap); 2994149871Sscottl pAdapter->outstandingCommands--; 2995149871Sscottl xpt_done(ccb); 2996149871Sscottl } 2997149871Sscottl } 2998149871Sscottl goto Command_Complished; 2999149871Sscottl } 3000149871Sscottl 3001149871Sscottl default: 3002149871Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 3003149871Sscottl break; 3004136849Sscottl } 3005136849Sscottl ccb_done(ccb); 3006136849SscottlCommand_Complished: 3007136849Sscottl CheckPendingCall(_VBUS_P0); 3008136849Sscottl return; 3009136849Sscottl} 3010136849Sscottl 3011149871Sscottlstatic void HPTLIBAPI 3012136849SscottlfOsCommandDone(_VBUS_ARG PCommand pCmd) 3013136849Sscottl{ 3014149871Sscottl union ccb *ccb = pCmd->pOrgCommand; 3015149871Sscottl PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 3016149871Sscottl IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 3017136849Sscottl 3018149871Sscottl KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result)); 3019136849Sscottl 3020136849Sscottl untimeout(hpt_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch); 3021136849Sscottl 3022136849Sscottl switch(pCmd->Result) { 3023136849Sscottl case RETURN_SUCCESS: 3024136849Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 3025136849Sscottl break; 3026136849Sscottl case RETURN_BAD_DEVICE: 3027136849Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 3028136849Sscottl break; 3029136849Sscottl case RETURN_DEVICE_BUSY: 3030136849Sscottl ccb->ccb_h.status = CAM_BUSY; 3031136849Sscottl break; 3032136849Sscottl case RETURN_INVALID_REQUEST: 3033136849Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 3034136849Sscottl break; 3035136849Sscottl case RETURN_SELECTION_TIMEOUT: 3036136849Sscottl ccb->ccb_h.status = CAM_SEL_TIMEOUT; 3037136849Sscottl break; 3038136849Sscottl case RETURN_RETRY: 3039136849Sscottl ccb->ccb_h.status = CAM_BUSY; 3040136849Sscottl break; 3041136849Sscottl default: 3042136849Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 3043136849Sscottl break; 3044136849Sscottl } 3045136849Sscottl 3046149871Sscottl if (pCmd->cf_data_in) { 3047149871Sscottl bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD); 3048136849Sscottl } 3049240210Sdelphij else if (pCmd->cf_data_out) { 3050149871Sscottl bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE); 3051149871Sscottl } 3052149871Sscottl 3053149871Sscottl bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map); 3054136849Sscottl 3055136849Sscottl FreeCommand(_VBUS_P pCmd); 3056136849Sscottl ccb_done(ccb); 3057136849Sscottl} 3058136849Sscottl 3059136849Sscottlint 3060136849Sscottlhpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags) 3061136849Sscottl{ 3062136849Sscottl int p; 3063136849Sscottl 3064136849Sscottl p = (DpcQueue_Last + 1) % MAX_DPC; 3065136849Sscottl if (p==DpcQueue_First) { 3066136849Sscottl KdPrint(("DPC Queue full!\n")); 3067136849Sscottl return -1; 3068136849Sscottl } 3069136849Sscottl 3070136849Sscottl DpcQueue[DpcQueue_Last].dpc = dpc; 3071136849Sscottl DpcQueue[DpcQueue_Last].pAdapter = pAdapter; 3072136849Sscottl DpcQueue[DpcQueue_Last].arg = arg; 3073136849Sscottl DpcQueue[DpcQueue_Last].flags = flags; 3074136849Sscottl DpcQueue_Last = p; 3075136849Sscottl 3076136849Sscottl return 0; 3077136849Sscottl} 3078136849Sscottl 3079136849Sscottl#ifdef _RAID5N_ 3080136849Sscottl/* 3081149871Sscottl * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices. 3082149871Sscottl * How about the memory for 5081 request/response array and PRD table? 3083136849Sscottl */ 3084136849Sscottlvoid 3085136849Sscottl*os_alloc_page(_VBUS_ARG0) 3086136849Sscottl{ 3087149871Sscottl return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 3088136849Sscottl} 3089149871Sscottl 3090136849Sscottlvoid 3091136849Sscottl*os_alloc_dma_page(_VBUS_ARG0) 3092136849Sscottl{ 3093149871Sscottl return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 3094136849Sscottl} 3095136849Sscottl 3096136849Sscottlvoid 3097149871Sscottlos_free_page(_VBUS_ARG void *p) 3098149871Sscottl{ 3099149871Sscottl contigfree(p, 0x1000, M_DEVBUF); 3100136849Sscottl} 3101136849Sscottl 3102136849Sscottlvoid 3103149871Sscottlos_free_dma_page(_VBUS_ARG void *p) 3104149871Sscottl{ 3105149871Sscottl contigfree(p, 0x1000, M_DEVBUF); 3106136849Sscottl} 3107136849Sscottl 3108136849Sscottlvoid 3109136849SscottlDoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes) 3110136849Sscottl{ 3111136849Sscottl UINT i; 3112149871Sscottl for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++; 3113136849Sscottl} 3114136849Sscottl 3115136849Sscottlvoid 3116136849SscottlDoXor2(ULONG *p0, ULONG *p2, UINT nBytes) 3117136849Sscottl{ 3118136849Sscottl UINT i; 3119149871Sscottl for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++; 3120136849Sscottl} 3121136849Sscottl#endif 3122