135878b55SSascha Wildner /* 235878b55SSascha Wildner * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 335878b55SSascha Wildner * All rights reserved. 435878b55SSascha Wildner * 535878b55SSascha Wildner * Redistribution and use in source and binary forms, with or without 635878b55SSascha Wildner * modification, are permitted provided that the following conditions 735878b55SSascha Wildner * are met: 835878b55SSascha Wildner * 1. Redistributions of source code must retain the above copyright 935878b55SSascha Wildner * notice, this list of conditions and the following disclaimer. 1035878b55SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 1135878b55SSascha Wildner * notice, this list of conditions and the following disclaimer in the 1235878b55SSascha Wildner * documentation and/or other materials provided with the distribution. 1335878b55SSascha Wildner * 1435878b55SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1535878b55SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1635878b55SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1735878b55SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1835878b55SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1935878b55SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2035878b55SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2135878b55SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2235878b55SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2335878b55SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2435878b55SSascha Wildner * SUCH DAMAGE. 2535878b55SSascha Wildner * 26c7e78657SSascha Wildner * $FreeBSD: src/sys/dev/hptmv/entry.c,v 1.26 2012/06/01 04:34:49 eadler Exp $ 2735878b55SSascha Wildner */ 2835878b55SSascha Wildner 2935878b55SSascha Wildner #include <sys/param.h> 3035878b55SSascha Wildner #include <sys/systm.h> 3135878b55SSascha Wildner #include <sys/kernel.h> 3235878b55SSascha Wildner #include <sys/bus.h> 3335878b55SSascha Wildner #include <sys/malloc.h> 3435878b55SSascha Wildner #include <sys/resource.h> 3535878b55SSascha Wildner #include <sys/time.h> 3635878b55SSascha Wildner #include <sys/callout.h> 3735878b55SSascha Wildner #include <sys/signalvar.h> 3835878b55SSascha Wildner #include <sys/eventhandler.h> 3935878b55SSascha Wildner #include <sys/proc.h> 4035878b55SSascha Wildner #include <sys/kthread.h> 4135878b55SSascha Wildner 4235878b55SSascha Wildner #include <sys/lock.h> 4335878b55SSascha Wildner #include <sys/module.h> 4435878b55SSascha Wildner 4535878b55SSascha Wildner #include <bus/pci/pcireg.h> 4635878b55SSascha Wildner #include <bus/pci/pcivar.h> 4735878b55SSascha Wildner 4835878b55SSascha Wildner #ifndef __KERNEL__ 4935878b55SSascha Wildner #define __KERNEL__ 5035878b55SSascha Wildner #endif 5135878b55SSascha Wildner 5235878b55SSascha Wildner #include <dev/raid/hptmv/global.h> 5335878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h> 5435878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h> 5535878b55SSascha Wildner #include <dev/raid/hptmv/access601.h> 5635878b55SSascha Wildner 5735878b55SSascha Wildner 5835878b55SSascha Wildner #ifdef DEBUG 5935878b55SSascha Wildner #ifdef DEBUG_LEVEL 6035878b55SSascha Wildner int hpt_dbg_level = DEBUG_LEVEL; 6135878b55SSascha Wildner #else 6235878b55SSascha Wildner int hpt_dbg_level = 0; 6335878b55SSascha Wildner #endif 6435878b55SSascha Wildner #endif 6535878b55SSascha Wildner 6635878b55SSascha Wildner #define MV_ERROR kprintf 6735878b55SSascha Wildner 6835878b55SSascha Wildner /* 6935878b55SSascha Wildner * CAM SIM entry points 7035878b55SSascha Wildner */ 7135878b55SSascha Wildner static int hpt_probe (device_t dev); 7235878b55SSascha Wildner static void launch_worker_thread(void); 7335878b55SSascha Wildner static int hpt_attach(device_t dev); 7435878b55SSascha Wildner static int hpt_detach(device_t dev); 7535878b55SSascha Wildner static int hpt_shutdown(device_t dev); 7635878b55SSascha Wildner static void hpt_poll(struct cam_sim *sim); 7735878b55SSascha Wildner static void hpt_intr(void *arg); 7835878b55SSascha Wildner static void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); 7935878b55SSascha Wildner static void hpt_action(struct cam_sim *sim, union ccb *ccb); 8035878b55SSascha Wildner 812050a95dSSascha Wildner static struct thread *hptdaemonproc; 822050a95dSSascha Wildner 8335878b55SSascha Wildner static device_method_t driver_methods[] = { 8435878b55SSascha Wildner /* Device interface */ 8535878b55SSascha Wildner DEVMETHOD(device_probe, hpt_probe), 8635878b55SSascha Wildner DEVMETHOD(device_attach, hpt_attach), 8735878b55SSascha Wildner DEVMETHOD(device_detach, hpt_detach), 8835878b55SSascha Wildner 8935878b55SSascha Wildner DEVMETHOD(device_shutdown, hpt_shutdown), 90d3c9c58eSSascha Wildner DEVMETHOD_END 9135878b55SSascha Wildner }; 9235878b55SSascha Wildner 9335878b55SSascha Wildner static driver_t hpt_pci_driver = { 9435878b55SSascha Wildner __str(PROC_DIR_NAME), 9535878b55SSascha Wildner driver_methods, 9635878b55SSascha Wildner sizeof(IAL_ADAPTER_T) 9735878b55SSascha Wildner }; 9835878b55SSascha Wildner 9935878b55SSascha Wildner static devclass_t hpt_devclass; 10035878b55SSascha Wildner 10135878b55SSascha Wildner #define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 10235878b55SSascha Wildner __DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 103c7e78657SSascha Wildner MODULE_DEPEND(PROC_DIR_NAME, cam, 1, 1, 1); 10435878b55SSascha Wildner 10535878b55SSascha Wildner #define ccb_ccb_ptr spriv_ptr0 10635878b55SSascha Wildner #define ccb_adapter ccb_h.spriv_ptr1 10735878b55SSascha Wildner 10835878b55SSascha Wildner static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); 10935878b55SSascha Wildner static void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); 11035878b55SSascha Wildner static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); 11135878b55SSascha Wildner static void ccb_done(union ccb *ccb); 11235878b55SSascha Wildner static void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); 11335878b55SSascha Wildner static void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); 11435878b55SSascha Wildner static void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter); 11535878b55SSascha Wildner static void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 11635878b55SSascha Wildner static void handleEdmaError(_VBUS_ARG PCommand pCmd); 11735878b55SSascha Wildner static int hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 11835878b55SSascha Wildner static int fResetActiveCommands(PVBus _vbus_p); 11935878b55SSascha Wildner static void fRegisterVdevice(IAL_ADAPTER_T *pAdapter); 12035878b55SSascha Wildner static int hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter); 12135878b55SSascha Wildner static void hptmv_handle_event_disconnect(void *data); 12235878b55SSascha Wildner static void hptmv_handle_event_connect(void *data); 12335878b55SSascha Wildner static int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 12435878b55SSascha Wildner static void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel); 12535878b55SSascha Wildner static int hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel); 12635878b55SSascha Wildner static int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, 12735878b55SSascha Wildner int logical); 12835878b55SSascha Wildner static MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 12935878b55SSascha Wildner MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId, 13035878b55SSascha Wildner MV_U16 responseFlags, MV_U32 timeStamp, 13135878b55SSascha Wildner MV_STORAGE_DEVICE_REGISTERS *registerStruct); 13235878b55SSascha Wildner static MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, 13335878b55SSascha Wildner MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2); 13435878b55SSascha Wildner 13535878b55SSascha Wildner #define ccb_ccb_ptr spriv_ptr0 13635878b55SSascha Wildner #define ccb_adapter ccb_h.spriv_ptr1 13735878b55SSascha Wildner 1384090d6ffSSascha Wildner IAL_ADAPTER_T *gIal_Adapter = NULL; 1394090d6ffSSascha Wildner IAL_ADAPTER_T *pCurAdapter = NULL; 14035878b55SSascha Wildner static MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; 14135878b55SSascha Wildner 14235878b55SSascha Wildner typedef struct st_HPT_DPC { 14335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 14435878b55SSascha Wildner void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR); 14535878b55SSascha Wildner void *arg; 14635878b55SSascha Wildner UCHAR flags; 14735878b55SSascha Wildner } ST_HPT_DPC; 14835878b55SSascha Wildner 14935878b55SSascha Wildner #define MAX_DPC 16 15035878b55SSascha Wildner UCHAR DPC_Request_Nums = 0; 15135878b55SSascha Wildner static ST_HPT_DPC DpcQueue[MAX_DPC]; 15235878b55SSascha Wildner static int DpcQueue_First=0; 15335878b55SSascha Wildner static int DpcQueue_Last = 0; 15435878b55SSascha Wildner 15535878b55SSascha Wildner char DRIVER_VERSION[] = "v1.16"; 15635878b55SSascha Wildner 15735878b55SSascha Wildner static struct lock driver_lock; 158c898d682SSascha Wildner void lock_driver(void) 15935878b55SSascha Wildner { 16035878b55SSascha Wildner lockmgr(&driver_lock, LK_EXCLUSIVE); 16135878b55SSascha Wildner } 162c898d682SSascha Wildner void unlock_driver(void) 16335878b55SSascha Wildner { 16435878b55SSascha Wildner lockmgr(&driver_lock, LK_RELEASE); 16535878b55SSascha Wildner } 16635878b55SSascha Wildner 16735878b55SSascha Wildner /******************************************************************************* 16835878b55SSascha Wildner * Name: hptmv_free_channel 16935878b55SSascha Wildner * 17035878b55SSascha Wildner * Description: free allocated queues for the given channel 17135878b55SSascha Wildner * 17235878b55SSascha Wildner * Parameters: pMvSataAdapter - pointer to the RR18xx controler this 17335878b55SSascha Wildner * channel connected to. 17435878b55SSascha Wildner * channelNum - channel number. 17535878b55SSascha Wildner * 17635878b55SSascha Wildner ******************************************************************************/ 17735878b55SSascha Wildner static void 17835878b55SSascha Wildner hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 17935878b55SSascha Wildner { 18035878b55SSascha Wildner HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM); 18135878b55SSascha Wildner pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL; 18235878b55SSascha Wildner } 18335878b55SSascha Wildner 18435878b55SSascha Wildner static void failDevice(PVDevice pVDev) 18535878b55SSascha Wildner { 18635878b55SSascha Wildner PVBus _vbus_p = pVDev->pVBus; 18735878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 18835878b55SSascha Wildner 18935878b55SSascha Wildner pVDev->u.disk.df_on_line = 0; 19035878b55SSascha Wildner pVDev->vf_online = 0; 19135878b55SSascha Wildner if (pVDev->pfnDeviceFailed) 19235878b55SSascha Wildner CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev); 19335878b55SSascha Wildner 19435878b55SSascha Wildner fNotifyGUI(ET_DEVICE_REMOVED, pVDev); 19535878b55SSascha Wildner 19635878b55SSascha Wildner #ifndef FOR_DEMO 19735878b55SSascha Wildner if (pAdapter->ver_601==2 && !pAdapter->beeping) { 19835878b55SSascha Wildner pAdapter->beeping = 1; 19935878b55SSascha Wildner BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); 20035878b55SSascha Wildner set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1); 20135878b55SSascha Wildner } 20235878b55SSascha Wildner #endif 20335878b55SSascha Wildner } 20435878b55SSascha Wildner 20535878b55SSascha Wildner int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel); 20635878b55SSascha Wildner 20735878b55SSascha Wildner static void 20835878b55SSascha Wildner handleEdmaError(_VBUS_ARG PCommand pCmd) 20935878b55SSascha Wildner { 21035878b55SSascha Wildner PDevice pDevice = &pCmd->pVDevice->u.disk; 21135878b55SSascha Wildner MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter; 21235878b55SSascha Wildner 21335878b55SSascha Wildner if (!pDevice->df_on_line) { 21435878b55SSascha Wildner KdPrint(("Device is offline")); 21535878b55SSascha Wildner pCmd->Result = RETURN_BAD_DEVICE; 21635878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 21735878b55SSascha Wildner return; 21835878b55SSascha Wildner } 21935878b55SSascha Wildner 22035878b55SSascha Wildner if (pCmd->RetryCount++>5) { 22135878b55SSascha Wildner hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber)); 22235878b55SSascha Wildner failed: 22335878b55SSascha Wildner failDevice(pCmd->pVDevice); 22435878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 22535878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 22635878b55SSascha Wildner return; 22735878b55SSascha Wildner } 22835878b55SSascha Wildner 22935878b55SSascha Wildner /* reset the channel and retry the command */ 23035878b55SSascha Wildner if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber)) 23135878b55SSascha Wildner goto failed; 23235878b55SSascha Wildner 23335878b55SSascha Wildner fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice)); 23435878b55SSascha Wildner 23535878b55SSascha Wildner hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber)); 23635878b55SSascha Wildner fDeviceSendCommand(_VBUS_P pCmd); 23735878b55SSascha Wildner } 23835878b55SSascha Wildner 23935878b55SSascha Wildner /**************************************************************** 24035878b55SSascha Wildner * Name: hptmv_init_channel 24135878b55SSascha Wildner * 24235878b55SSascha Wildner * Description: allocate request and response queues for the EDMA of the 24335878b55SSascha Wildner * given channel and sets other fields. 24435878b55SSascha Wildner * 24535878b55SSascha Wildner * Parameters: 24635878b55SSascha Wildner * pAdapter - pointer to the emulated adapter data structure 24735878b55SSascha Wildner * channelNum - channel number. 24835878b55SSascha Wildner * Return: 0 on success, otherwise on failure 24935878b55SSascha Wildner ****************************************************************/ 25035878b55SSascha Wildner static int 25135878b55SSascha Wildner hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 25235878b55SSascha Wildner { 25335878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel; 25435878b55SSascha Wildner dma_addr_t req_dma_addr; 25535878b55SSascha Wildner dma_addr_t rsp_dma_addr; 25635878b55SSascha Wildner 25735878b55SSascha Wildner if (channelNum >= MV_SATA_CHANNELS_NUM) 25835878b55SSascha Wildner { 25935878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Bad channelNum=%d", 26035878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum); 26135878b55SSascha Wildner return -1; 26235878b55SSascha Wildner } 26335878b55SSascha Wildner 26435878b55SSascha Wildner pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; 26535878b55SSascha Wildner pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel; 26635878b55SSascha Wildner pMvSataChannel->channelNumber = channelNum; 26735878b55SSascha Wildner pMvSataChannel->lba48Address = MV_FALSE; 26835878b55SSascha Wildner pMvSataChannel->maxReadTransfer = MV_FALSE; 26935878b55SSascha Wildner 27035878b55SSascha Wildner pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *) 27135878b55SSascha Wildner (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); 27235878b55SSascha Wildner req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); 27335878b55SSascha Wildner 27435878b55SSascha Wildner 27535878b55SSascha Wildner KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr)); 27635878b55SSascha Wildner 27735878b55SSascha Wildner /* check the 1K alignment of the request queue*/ 27835878b55SSascha Wildner if (req_dma_addr & 0x3ff) 27935878b55SSascha Wildner { 28035878b55SSascha Wildner MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned," 28135878b55SSascha Wildner " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId, 28235878b55SSascha Wildner (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum); 28335878b55SSascha Wildner return -1; 28435878b55SSascha Wildner } 28535878b55SSascha Wildner pMvSataChannel->requestQueuePciLowAddress = req_dma_addr; 28635878b55SSascha Wildner pMvSataChannel->requestQueuePciHiAddress = 0; 28735878b55SSascha Wildner KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p", 28835878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum, 28935878b55SSascha Wildner pMvSataChannel->requestQueue)); 29035878b55SSascha Wildner pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) 29135878b55SSascha Wildner (pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); 29235878b55SSascha Wildner rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); 29335878b55SSascha Wildner 29435878b55SSascha Wildner /* check the 256 alignment of the response queue*/ 29535878b55SSascha Wildner if (rsp_dma_addr & 0xff) 29635878b55SSascha Wildner { 29735878b55SSascha Wildner MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte " 29835878b55SSascha Wildner "aligned, dma_addr=%llx\n", 29935878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr); 30035878b55SSascha Wildner return -1; 30135878b55SSascha Wildner } 30235878b55SSascha Wildner pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr; 30335878b55SSascha Wildner pMvSataChannel->responseQueuePciHiAddress = 0; 30435878b55SSascha Wildner KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p", 30535878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId, channelNum, 30635878b55SSascha Wildner pMvSataChannel->responseQueue)); 30735878b55SSascha Wildner 30835878b55SSascha Wildner pAdapter->mvChannel[channelNum].online = MV_TRUE; 30935878b55SSascha Wildner return 0; 31035878b55SSascha Wildner } 31135878b55SSascha Wildner 31235878b55SSascha Wildner /****************************************************************************** 31335878b55SSascha Wildner * Name: hptmv_parse_identify_results 31435878b55SSascha Wildner * 31535878b55SSascha Wildner * Description: this functions parses the identify command results, checks 31635878b55SSascha Wildner * that the connected deives can be accesed by RR18xx EDMA, 31735878b55SSascha Wildner * and updates the channel stucture accordingly. 31835878b55SSascha Wildner * 31935878b55SSascha Wildner * Parameters: pMvSataChannel, pointer to the channel data structure. 32035878b55SSascha Wildner * 32135878b55SSascha Wildner * Returns: =0 ->success, < 0 ->failure. 32235878b55SSascha Wildner * 32335878b55SSascha Wildner ******************************************************************************/ 32435878b55SSascha Wildner static int 32535878b55SSascha Wildner hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) 32635878b55SSascha Wildner { 32735878b55SSascha Wildner MV_U16 *iden = pMvSataChannel->identifyDevice; 32835878b55SSascha Wildner 32935878b55SSascha Wildner /*LBA addressing*/ 33035878b55SSascha Wildner if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) 33135878b55SSascha Wildner { 33235878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n")); 33335878b55SSascha Wildner return -1; 33435878b55SSascha Wildner } 33535878b55SSascha Wildner else 33635878b55SSascha Wildner { 33735878b55SSascha Wildner KdPrint(("%25s - %s\n", "Capabilities", "LBA supported")); 33835878b55SSascha Wildner } 33935878b55SSascha Wildner /*DMA support*/ 34035878b55SSascha Wildner if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) 34135878b55SSascha Wildner { 34235878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n")); 34335878b55SSascha Wildner return -1; 34435878b55SSascha Wildner } 34535878b55SSascha Wildner else 34635878b55SSascha Wildner { 34735878b55SSascha Wildner KdPrint(("%25s - %s\n", "Capabilities", "DMA supported")); 34835878b55SSascha Wildner } 34935878b55SSascha Wildner /* PIO */ 35035878b55SSascha Wildner if ((iden[IDEN_VALID] & 2) == 0) 35135878b55SSascha Wildner { 35235878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n")); 35335878b55SSascha Wildner return -1; 35435878b55SSascha Wildner } 35535878b55SSascha Wildner KdPrint(("%25s - 0x%02x\n", "PIO modes supported", 35635878b55SSascha Wildner iden[IDEN_PIO_MODE_SPPORTED] & 0xff)); 35735878b55SSascha Wildner 35835878b55SSascha Wildner /*UDMA*/ 35935878b55SSascha Wildner if ((iden[IDEN_VALID] & 4) == 0) 36035878b55SSascha Wildner { 36135878b55SSascha Wildner KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n")); 36235878b55SSascha Wildner return -1; 36335878b55SSascha Wildner } 36435878b55SSascha Wildner 36535878b55SSascha Wildner /* 48 bit address */ 36635878b55SSascha Wildner if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) 36735878b55SSascha Wildner { 36835878b55SSascha Wildner KdPrint(("%25s - %s\n", "LBA48 addressing", "supported")); 36935878b55SSascha Wildner pMvSataChannel->lba48Address = MV_TRUE; 37035878b55SSascha Wildner } 37135878b55SSascha Wildner else 37235878b55SSascha Wildner { 37335878b55SSascha Wildner KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported")); 37435878b55SSascha Wildner pMvSataChannel->lba48Address = MV_FALSE; 37535878b55SSascha Wildner } 37635878b55SSascha Wildner return 0; 37735878b55SSascha Wildner } 37835878b55SSascha Wildner 37935878b55SSascha Wildner static void 38035878b55SSascha Wildner init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) 38135878b55SSascha Wildner { 38235878b55SSascha Wildner PVDevice pVDev = &pAdapter->VDevices[channel]; 38335878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; 38435878b55SSascha Wildner MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice; 38535878b55SSascha Wildner 38635878b55SSascha Wildner pMvSataChannel->outstandingCommands = 0; 38735878b55SSascha Wildner 38835878b55SSascha Wildner pVDev->u.disk.mv = pMvSataChannel; 38935878b55SSascha Wildner pVDev->u.disk.df_on_line = 1; 39035878b55SSascha Wildner pVDev->u.disk.pVBus = &pAdapter->VBus; 39135878b55SSascha Wildner pVDev->pVBus = &pAdapter->VBus; 39235878b55SSascha Wildner 39335878b55SSascha Wildner #ifdef SUPPORT_48BIT_LBA 39435878b55SSascha Wildner if (pMvSataChannel->lba48Address == MV_TRUE) 39535878b55SSascha Wildner pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; 39635878b55SSascha Wildner else 39735878b55SSascha Wildner #endif 39835878b55SSascha Wildner if(IdentifyData[53] & 1) { 39935878b55SSascha Wildner pVDev->u.disk.dDeRealCapacity = 40035878b55SSascha Wildner (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ? 40135878b55SSascha Wildner (IdentifyData[61]<<16 | IdentifyData[60]) : 40235878b55SSascha Wildner (IdentifyData[58]<<16 | IdentifyData[57])) - 1; 40335878b55SSascha Wildner } else 40435878b55SSascha Wildner pVDev->u.disk.dDeRealCapacity = 40535878b55SSascha Wildner (IdentifyData[61]<<16 | IdentifyData[60]) - 1; 40635878b55SSascha Wildner 40735878b55SSascha Wildner pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 40835878b55SSascha Wildner pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0; 40935878b55SSascha Wildner 41035878b55SSascha Wildner if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) { 41135878b55SSascha Wildner pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 41235878b55SSascha Wildner pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8; 41335878b55SSascha Wildner } 41435878b55SSascha Wildner } 41535878b55SSascha Wildner 41635878b55SSascha Wildner static void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) 41735878b55SSascha Wildner { 41835878b55SSascha Wildner PVDevice pVDev; 41935878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 42035878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; 42135878b55SSascha Wildner 42235878b55SSascha Wildner if (!pMvSataChannel) return; 42335878b55SSascha Wildner 42435878b55SSascha Wildner if (plugged) 42535878b55SSascha Wildner { 42635878b55SSascha Wildner pVDev = &(pAdapter->VDevices[channelIndex]); 42735878b55SSascha Wildner init_vdev_params(pAdapter, channelIndex); 42835878b55SSascha Wildner 42935878b55SSascha Wildner pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI : 43035878b55SSascha Wildner pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 43135878b55SSascha Wildner 43235878b55SSascha Wildner pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO; 43335878b55SSascha Wildner pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 43435878b55SSascha Wildner pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 43535878b55SSascha Wildner pVDev->vf_online = 1; 43635878b55SSascha Wildner 43735878b55SSascha Wildner #ifdef SUPPORT_ARRAY 43835878b55SSascha Wildner if(pVDev->pParent) 43935878b55SSascha Wildner { 44035878b55SSascha Wildner int iMember; 44135878b55SSascha Wildner for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++) 44235878b55SSascha Wildner if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) 44335878b55SSascha Wildner pVDev->pParent->u.array.pMember[iMember] = NULL; 44435878b55SSascha Wildner pVDev->pParent = NULL; 44535878b55SSascha Wildner } 44635878b55SSascha Wildner #endif 44735878b55SSascha Wildner fNotifyGUI(ET_DEVICE_PLUGGED,pVDev); 44835878b55SSascha Wildner fCheckBootable(pVDev); 44935878b55SSascha Wildner RegisterVDevice(pVDev); 45035878b55SSascha Wildner 45135878b55SSascha Wildner #ifndef FOR_DEMO 45235878b55SSascha Wildner if (pAdapter->beeping) { 45335878b55SSascha Wildner pAdapter->beeping = 0; 45435878b55SSascha Wildner BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 45535878b55SSascha Wildner } 45635878b55SSascha Wildner #endif 45735878b55SSascha Wildner 45835878b55SSascha Wildner } 45935878b55SSascha Wildner else 46035878b55SSascha Wildner { 46135878b55SSascha Wildner pVDev = &(pAdapter->VDevices[channelIndex]); 46235878b55SSascha Wildner failDevice(pVDev); 46335878b55SSascha Wildner } 46435878b55SSascha Wildner } 46535878b55SSascha Wildner 46635878b55SSascha Wildner static int 46735878b55SSascha Wildner start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 46835878b55SSascha Wildner { 46935878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 47035878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; 47135878b55SSascha Wildner MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]); 47235878b55SSascha Wildner MV_U32 udmaMode,pioMode; 47335878b55SSascha Wildner 47435878b55SSascha Wildner KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId, 47535878b55SSascha Wildner channelNum)); 47635878b55SSascha Wildner 47735878b55SSascha Wildner 47835878b55SSascha Wildner /* Software reset channel */ 47935878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 48035878b55SSascha Wildner { 48135878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 48235878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 48335878b55SSascha Wildner return -1; 48435878b55SSascha Wildner } 48535878b55SSascha Wildner 48635878b55SSascha Wildner /* Hardware reset channel */ 48735878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 48835878b55SSascha Wildner { 48935878b55SSascha Wildner /* If failed, try again - this is when trying to hardreset a channel */ 49035878b55SSascha Wildner /* when drive is just spinning up */ 49135878b55SSascha Wildner StallExec(5000000); /* wait 5 sec before trying again */ 49235878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 49335878b55SSascha Wildner { 49435878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n", 49535878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 49635878b55SSascha Wildner return -1; 49735878b55SSascha Wildner } 49835878b55SSascha Wildner } 49935878b55SSascha Wildner 50035878b55SSascha Wildner /* identify device*/ 50135878b55SSascha Wildner if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE) 50235878b55SSascha Wildner { 50335878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n" 50435878b55SSascha Wildner , pMvSataAdapter->adapterId, channelNum); 50535878b55SSascha Wildner return -1; 50635878b55SSascha Wildner } 50735878b55SSascha Wildner if (hptmv_parse_identify_results(pMvSataChannel)) 50835878b55SSascha Wildner { 50935878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n" 51035878b55SSascha Wildner , pMvSataAdapter->adapterId, channelNum); 51135878b55SSascha Wildner return -1; 51235878b55SSascha Wildner } 51335878b55SSascha Wildner 51435878b55SSascha Wildner /* mvStorageDevATASetFeatures */ 51535878b55SSascha Wildner /* Disable 8 bit PIO in case CFA enabled */ 51635878b55SSascha Wildner if (pMvSataChannel->identifyDevice[86] & 4) 51735878b55SSascha Wildner { 51835878b55SSascha Wildner KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n", 51935878b55SSascha Wildner pMvSataAdapter->adapterId)); 52035878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 52135878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, 52235878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 52335878b55SSascha Wildner { 52435878b55SSascha Wildner MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures" 52535878b55SSascha Wildner " failed\n", pMvSataAdapter->adapterId, channelNum); 52635878b55SSascha Wildner return -1; 52735878b55SSascha Wildner } 52835878b55SSascha Wildner } 52935878b55SSascha Wildner /* Write cache */ 53035878b55SSascha Wildner #ifdef ENABLE_WRITE_CACHE 53135878b55SSascha Wildner if (pMvSataChannel->identifyDevice[82] & 0x20) 53235878b55SSascha Wildner { 53335878b55SSascha Wildner if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */ 53435878b55SSascha Wildner { 53535878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 53635878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 53735878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 53835878b55SSascha Wildner { 53935878b55SSascha Wildner MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 54035878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 54135878b55SSascha Wildner return -1; 54235878b55SSascha Wildner } 54335878b55SSascha Wildner } 54435878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n", 54535878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 54635878b55SSascha Wildner } 54735878b55SSascha Wildner else 54835878b55SSascha Wildner { 54935878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n", 55035878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 55135878b55SSascha Wildner } 55235878b55SSascha Wildner #else /* disable write cache */ 55335878b55SSascha Wildner { 55435878b55SSascha Wildner if (pMvSataChannel->identifyDevice[85] & 0x20) 55535878b55SSascha Wildner { 55635878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n", 55735878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 55835878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 55935878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 56035878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 56135878b55SSascha Wildner { 56235878b55SSascha Wildner MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 56335878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 56435878b55SSascha Wildner return -1; 56535878b55SSascha Wildner } 56635878b55SSascha Wildner } 56735878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n", 56835878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 56935878b55SSascha Wildner } 57035878b55SSascha Wildner #endif 57135878b55SSascha Wildner 57235878b55SSascha Wildner /* Set transfer mode */ 57335878b55SSascha Wildner KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n", 57435878b55SSascha Wildner pMvSataAdapter->adapterId)); 57535878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 57635878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 57735878b55SSascha Wildner MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == 57835878b55SSascha Wildner MV_FALSE) 57935878b55SSascha Wildner { 58035878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 58135878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 58235878b55SSascha Wildner return -1; 58335878b55SSascha Wildner } 58435878b55SSascha Wildner 58535878b55SSascha Wildner if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) 58635878b55SSascha Wildner { 58735878b55SSascha Wildner pioMode = MV_ATA_TRANSFER_PIO_4; 58835878b55SSascha Wildner } 58935878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) 59035878b55SSascha Wildner { 59135878b55SSascha Wildner pioMode = MV_ATA_TRANSFER_PIO_3; 59235878b55SSascha Wildner } 59335878b55SSascha Wildner else 59435878b55SSascha Wildner { 59535878b55SSascha Wildner MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n"); 59635878b55SSascha Wildner pioMode = MV_ATA_TRANSFER_PIO_SLOW; 59735878b55SSascha Wildner } 59835878b55SSascha Wildner 59935878b55SSascha Wildner KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n", 60035878b55SSascha Wildner pMvSataAdapter->adapterId)); 60135878b55SSascha Wildner pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode; 60235878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 60335878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 60435878b55SSascha Wildner pioMode, 0, 0, 0) == MV_FALSE) 60535878b55SSascha Wildner { 60635878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 60735878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 60835878b55SSascha Wildner return -1; 60935878b55SSascha Wildner } 61035878b55SSascha Wildner 61135878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_0; 61235878b55SSascha Wildner if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) 61335878b55SSascha Wildner { 61435878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_6; 61535878b55SSascha Wildner } 61635878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) 61735878b55SSascha Wildner { 61835878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_5; 61935878b55SSascha Wildner } 62035878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) 62135878b55SSascha Wildner { 62235878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_4; 62335878b55SSascha Wildner } 62435878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) 62535878b55SSascha Wildner { 62635878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_3; 62735878b55SSascha Wildner } 62835878b55SSascha Wildner else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) 62935878b55SSascha Wildner { 63035878b55SSascha Wildner udmaMode = MV_ATA_TRANSFER_UDMA_2; 63135878b55SSascha Wildner } 63235878b55SSascha Wildner 63335878b55SSascha Wildner KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n", 63435878b55SSascha Wildner pMvSataAdapter->adapterId, udmaMode & 0xf)); 63535878b55SSascha Wildner pChannelInfo->maxUltraDmaModeSupported = udmaMode; 63635878b55SSascha Wildner 63735878b55SSascha Wildner /*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 63835878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, udmaMode, 63935878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 64035878b55SSascha Wildner { 64135878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 64235878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 64335878b55SSascha Wildner return -1; 64435878b55SSascha Wildner }*/ 64535878b55SSascha Wildner if (pChannelInfo->maxUltraDmaModeSupported == 0xFF) 64635878b55SSascha Wildner return TRUE; 64735878b55SSascha Wildner else 64835878b55SSascha Wildner do 64935878b55SSascha Wildner { 65035878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 65135878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 65235878b55SSascha Wildner pChannelInfo->maxUltraDmaModeSupported, 65335878b55SSascha Wildner 0, 0, 0) == MV_FALSE) 65435878b55SSascha Wildner { 65535878b55SSascha Wildner if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0) 65635878b55SSascha Wildner { 65735878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 65835878b55SSascha Wildner { 65935878b55SSascha Wildner MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress, 66035878b55SSascha Wildner pMvSataChannel->eDmaRegsOffset + 66135878b55SSascha Wildner 0x11c, /* command reg */ 66235878b55SSascha Wildner MV_ATA_COMMAND_IDLE_IMMEDIATE); 66335878b55SSascha Wildner mvMicroSecondsDelay(10000); 66435878b55SSascha Wildner mvSataChannelHardReset(pMvSataAdapter, channelNum); 66535878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 66635878b55SSascha Wildner return FALSE; 66735878b55SSascha Wildner } 66835878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 66935878b55SSascha Wildner return FALSE; 67035878b55SSascha Wildner pChannelInfo->maxUltraDmaModeSupported--; 67135878b55SSascha Wildner continue; 67235878b55SSascha Wildner } 67335878b55SSascha Wildner else return FALSE; 67435878b55SSascha Wildner } 67535878b55SSascha Wildner break; 67635878b55SSascha Wildner }while (1); 67735878b55SSascha Wildner 67835878b55SSascha Wildner /* Read look ahead */ 67935878b55SSascha Wildner #ifdef ENABLE_READ_AHEAD 68035878b55SSascha Wildner if (pMvSataChannel->identifyDevice[82] & 0x40) 68135878b55SSascha Wildner { 68235878b55SSascha Wildner if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */ 68335878b55SSascha Wildner { 68435878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 68535878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 68635878b55SSascha Wildner 0, 0) == MV_FALSE) 68735878b55SSascha Wildner { 68835878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n", 68935878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 69035878b55SSascha Wildner return -1; 69135878b55SSascha Wildner } 69235878b55SSascha Wildner } 69335878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n", 69435878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 69535878b55SSascha Wildner } 69635878b55SSascha Wildner else 69735878b55SSascha Wildner { 69835878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n", 69935878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 70035878b55SSascha Wildner } 70135878b55SSascha Wildner #else 70235878b55SSascha Wildner { 70335878b55SSascha Wildner if (pMvSataChannel->identifyDevice[86] & 0x20) 70435878b55SSascha Wildner { 70535878b55SSascha Wildner KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n", 70635878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 70735878b55SSascha Wildner if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 70835878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 70935878b55SSascha Wildner 0, 0) == MV_FALSE) 71035878b55SSascha Wildner { 71135878b55SSascha Wildner MV_ERROR("RR18xx [%d]:channel %d: ATA Set Features failed\n", 71235878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 71335878b55SSascha Wildner return -1; 71435878b55SSascha Wildner } 71535878b55SSascha Wildner } 71635878b55SSascha Wildner KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n", 71735878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum)); 71835878b55SSascha Wildner } 71935878b55SSascha Wildner #endif 72035878b55SSascha Wildner 72135878b55SSascha Wildner 72235878b55SSascha Wildner { 72335878b55SSascha Wildner KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n", 72435878b55SSascha Wildner pMvSataAdapter->adapterId, 72535878b55SSascha Wildner channelNum)); 72635878b55SSascha Wildner if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, 72735878b55SSascha Wildner MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) 72835878b55SSascha Wildner { 72935878b55SSascha Wildner MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n", 73035878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 73135878b55SSascha Wildner return -1; 73235878b55SSascha Wildner } 73335878b55SSascha Wildner } 73435878b55SSascha Wildner /* Enable EDMA */ 73535878b55SSascha Wildner if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) 73635878b55SSascha Wildner { 73735878b55SSascha Wildner MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n", 73835878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 73935878b55SSascha Wildner return -1; 74035878b55SSascha Wildner } 74135878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: channel started successfully\n", 74235878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum); 74335878b55SSascha Wildner 74435878b55SSascha Wildner #ifndef FOR_DEMO 74535878b55SSascha Wildner set_fail_led(pMvSataAdapter, channelNum, 0); 74635878b55SSascha Wildner #endif 74735878b55SSascha Wildner return 0; 74835878b55SSascha Wildner } 74935878b55SSascha Wildner 75035878b55SSascha Wildner static void 75135878b55SSascha Wildner hptmv_handle_event(void * data, int flag) 75235878b55SSascha Wildner { 75335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)data; 75435878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 75535878b55SSascha Wildner MV_U8 channelIndex; 75635878b55SSascha Wildner 75735878b55SSascha Wildner /* mvOsSemTake(&pMvSataAdapter->semaphore); */ 75835878b55SSascha Wildner for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++) 75935878b55SSascha Wildner { 76035878b55SSascha Wildner switch(pAdapter->sataEvents[channelIndex]) 76135878b55SSascha Wildner { 76235878b55SSascha Wildner case SATA_EVENT_CHANNEL_CONNECTED: 76335878b55SSascha Wildner /* Handle only connects */ 76435878b55SSascha Wildner if (flag == 1) 76535878b55SSascha Wildner break; 76635878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: new device connected\n", 76735878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 76835878b55SSascha Wildner hptmv_init_channel(pAdapter, channelIndex); 76935878b55SSascha Wildner if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE) 77035878b55SSascha Wildner { 77135878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d] Failed to configure\n", 77235878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex); 77335878b55SSascha Wildner hptmv_free_channel(pAdapter, channelIndex); 77435878b55SSascha Wildner } 77535878b55SSascha Wildner else 77635878b55SSascha Wildner { 77735878b55SSascha Wildner /*mvSataChannelHardReset(pMvSataAdapter, channel);*/ 77835878b55SSascha Wildner if (start_channel( pAdapter, channelIndex)) 77935878b55SSascha Wildner { 78035878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]Failed to start channel\n", 78135878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex); 78235878b55SSascha Wildner hptmv_free_channel(pAdapter, channelIndex); 78335878b55SSascha Wildner } 78435878b55SSascha Wildner else 78535878b55SSascha Wildner { 78635878b55SSascha Wildner device_change(pAdapter, channelIndex, TRUE); 78735878b55SSascha Wildner } 78835878b55SSascha Wildner } 78935878b55SSascha Wildner pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 79035878b55SSascha Wildner break; 79135878b55SSascha Wildner 79235878b55SSascha Wildner case SATA_EVENT_CHANNEL_DISCONNECTED: 79335878b55SSascha Wildner /* Handle only disconnects */ 79435878b55SSascha Wildner if (flag == 0) 79535878b55SSascha Wildner break; 79635878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: device disconnected\n", 79735878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 79835878b55SSascha Wildner /* Flush pending commands */ 79935878b55SSascha Wildner if(pMvSataAdapter->sataChannel[channelIndex]) 80035878b55SSascha Wildner { 80135878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 80235878b55SSascha Wildner mvSataFlushDmaQueue (pMvSataAdapter, channelIndex, 80335878b55SSascha Wildner MV_FLUSH_TYPE_CALLBACK); 80435878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 80535878b55SSascha Wildner mvSataRemoveChannel(pMvSataAdapter,channelIndex); 80635878b55SSascha Wildner hptmv_free_channel(pAdapter, channelIndex); 80735878b55SSascha Wildner pMvSataAdapter->sataChannel[channelIndex] = NULL; 80835878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: channel removed\n", 80935878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 81035878b55SSascha Wildner if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 81135878b55SSascha Wildner Check_Idle_Call(pAdapter); 81235878b55SSascha Wildner } 81335878b55SSascha Wildner else 81435878b55SSascha Wildner { 81535878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: channel already removed!!\n", 81635878b55SSascha Wildner pMvSataAdapter->adapterId, channelIndex)); 81735878b55SSascha Wildner } 81835878b55SSascha Wildner pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 81935878b55SSascha Wildner break; 82035878b55SSascha Wildner 82135878b55SSascha Wildner case SATA_EVENT_NO_CHANGE: 82235878b55SSascha Wildner break; 82335878b55SSascha Wildner 82435878b55SSascha Wildner default: 82535878b55SSascha Wildner break; 82635878b55SSascha Wildner } 82735878b55SSascha Wildner } 82835878b55SSascha Wildner /* mvOsSemRelease(&pMvSataAdapter->semaphore); */ 82935878b55SSascha Wildner } 83035878b55SSascha Wildner 83135878b55SSascha Wildner #define EVENT_CONNECT 1 83235878b55SSascha Wildner #define EVENT_DISCONNECT 0 83335878b55SSascha Wildner 83435878b55SSascha Wildner static void 83535878b55SSascha Wildner hptmv_handle_event_connect(void *data) 83635878b55SSascha Wildner { 83735878b55SSascha Wildner hptmv_handle_event (data, 0); 83835878b55SSascha Wildner } 83935878b55SSascha Wildner 84035878b55SSascha Wildner static void 84135878b55SSascha Wildner hptmv_handle_event_disconnect(void *data) 84235878b55SSascha Wildner { 84335878b55SSascha Wildner hptmv_handle_event (data, 1); 84435878b55SSascha Wildner } 84535878b55SSascha Wildner 84635878b55SSascha Wildner static MV_BOOLEAN 84735878b55SSascha Wildner hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType, 84835878b55SSascha Wildner MV_U32 param1, MV_U32 param2) 84935878b55SSascha Wildner { 85035878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; 85135878b55SSascha Wildner 85235878b55SSascha Wildner switch (eventType) 85335878b55SSascha Wildner { 85435878b55SSascha Wildner case MV_EVENT_TYPE_SATA_CABLE: 85535878b55SSascha Wildner { 85635878b55SSascha Wildner MV_U8 channel = param2; 85735878b55SSascha Wildner 85835878b55SSascha Wildner if (param1 == EVENT_CONNECT) 85935878b55SSascha Wildner { 86035878b55SSascha Wildner pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED; 86135878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: device connected event received\n", 86235878b55SSascha Wildner pMvSataAdapter->adapterId, channel)); 86335878b55SSascha Wildner /* Delete previous timers (if multiple drives connected in the same time */ 86435878b55SSascha Wildner callout_reset(&pAdapter->event_timer_connect, 10*hz, hptmv_handle_event_connect, pAdapter); 86535878b55SSascha Wildner } 86635878b55SSascha Wildner else if (param1 == EVENT_DISCONNECT) 86735878b55SSascha Wildner { 86835878b55SSascha Wildner pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED; 86935878b55SSascha Wildner KdPrint(("RR18xx [%d,%d]: device disconnected event received \n", 87035878b55SSascha Wildner pMvSataAdapter->adapterId, channel)); 87135878b55SSascha Wildner device_change(pAdapter, channel, FALSE); 87235878b55SSascha Wildner /* Delete previous timers (if multiple drives disconnected in the same time */ 87335878b55SSascha Wildner /* callout_reset(&pAdapter->event_timer_disconnect, 10*hz, hptmv_handle_event_disconnect, pAdapter); */ 87435878b55SSascha Wildner /*It is not necessary to wait, handle it directly*/ 87535878b55SSascha Wildner hptmv_handle_event_disconnect(pAdapter); 87635878b55SSascha Wildner } 87735878b55SSascha Wildner else 87835878b55SSascha Wildner { 87935878b55SSascha Wildner 88035878b55SSascha Wildner MV_ERROR("RR18xx: illigal value for param1(%d) at " 88135878b55SSascha Wildner "connect/disconect event, host=%d\n", param1, 88235878b55SSascha Wildner pMvSataAdapter->adapterId ); 88335878b55SSascha Wildner 88435878b55SSascha Wildner } 88535878b55SSascha Wildner } 88635878b55SSascha Wildner break; 88735878b55SSascha Wildner case MV_EVENT_TYPE_ADAPTER_ERROR: 88835878b55SSascha Wildner KdPrint(("RR18xx: DEVICE error event received, pci cause " 88935878b55SSascha Wildner "reg=%x, don't how to handle this\n", param1)); 89035878b55SSascha Wildner return MV_TRUE; 89135878b55SSascha Wildner default: 89235878b55SSascha Wildner MV_ERROR("RR18xx[%d]: unknown event type (%d)\n", 89335878b55SSascha Wildner pMvSataAdapter->adapterId, eventType); 89435878b55SSascha Wildner return MV_FALSE; 89535878b55SSascha Wildner } 89635878b55SSascha Wildner return MV_TRUE; 89735878b55SSascha Wildner } 89835878b55SSascha Wildner 89935878b55SSascha Wildner static int 90035878b55SSascha Wildner hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) 90135878b55SSascha Wildner { 90235878b55SSascha Wildner pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE, 90335878b55SSascha Wildner M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 90435878b55SSascha Wildner if (pAdapter->requestsArrayBaseAddr == NULL) 90535878b55SSascha Wildner { 90635878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request" 90735878b55SSascha Wildner " queues\n", pAdapter->mvSataAdapter.adapterId); 90835878b55SSascha Wildner return -1; 90935878b55SSascha Wildner } 91035878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr); 91135878b55SSascha Wildner pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr; 91235878b55SSascha Wildner pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 91335878b55SSascha Wildner pAdapter->requestsArrayBaseAlignedAddr = (MV_U8 *) 91435878b55SSascha Wildner (((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); 91535878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr; 91635878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 91735878b55SSascha Wildner pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); 91835878b55SSascha Wildner 91935878b55SSascha Wildner if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) != 92035878b55SSascha Wildner (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr)) 92135878b55SSascha Wildner { 92235878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n", 92335878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId); 92435878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 92535878b55SSascha Wildner return -1; 92635878b55SSascha Wildner } 92735878b55SSascha Wildner /* response queues */ 92835878b55SSascha Wildner pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE, 92935878b55SSascha Wildner M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 93035878b55SSascha Wildner if (pAdapter->responsesArrayBaseAddr == NULL) 93135878b55SSascha Wildner { 93235878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response" 93335878b55SSascha Wildner " queues\n", pAdapter->mvSataAdapter.adapterId); 93435878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 93535878b55SSascha Wildner return -1; 93635878b55SSascha Wildner } 93735878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr); 93835878b55SSascha Wildner pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr; 93935878b55SSascha Wildner pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 94035878b55SSascha Wildner pAdapter->responsesArrayBaseAlignedAddr = (MV_U8 *) 94135878b55SSascha Wildner (((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); 94235878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr; 94335878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 94435878b55SSascha Wildner pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); 94535878b55SSascha Wildner 94635878b55SSascha Wildner if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) != 94735878b55SSascha Wildner (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr)) 94835878b55SSascha Wildner { 94935878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Error in Response Quueues Alignment\n", 95035878b55SSascha Wildner pAdapter->mvSataAdapter.adapterId); 95135878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 95235878b55SSascha Wildner contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 95335878b55SSascha Wildner return -1; 95435878b55SSascha Wildner } 95535878b55SSascha Wildner return 0; 95635878b55SSascha Wildner } 95735878b55SSascha Wildner 95835878b55SSascha Wildner static void 95935878b55SSascha Wildner hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter) 96035878b55SSascha Wildner { 96135878b55SSascha Wildner contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 96235878b55SSascha Wildner contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 96335878b55SSascha Wildner } 96435878b55SSascha Wildner 96535878b55SSascha Wildner static PVOID 96635878b55SSascha Wildner AllocatePRDTable(IAL_ADAPTER_T *pAdapter) 96735878b55SSascha Wildner { 96835878b55SSascha Wildner PVOID ret; 96935878b55SSascha Wildner if (pAdapter->pFreePRDLink) { 97035878b55SSascha Wildner KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink)); 97135878b55SSascha Wildner ret = pAdapter->pFreePRDLink; 97235878b55SSascha Wildner pAdapter->pFreePRDLink = *(void**)ret; 97335878b55SSascha Wildner return ret; 97435878b55SSascha Wildner } 97535878b55SSascha Wildner return NULL; 97635878b55SSascha Wildner } 97735878b55SSascha Wildner 97835878b55SSascha Wildner static void 97935878b55SSascha Wildner FreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable) 98035878b55SSascha Wildner { 98135878b55SSascha Wildner *(void**)PRDTable = pAdapter->pFreePRDLink; 98235878b55SSascha Wildner pAdapter->pFreePRDLink = PRDTable; 98335878b55SSascha Wildner } 98435878b55SSascha Wildner 98535878b55SSascha Wildner extern PVDevice fGetFirstChild(PVDevice pLogical); 98635878b55SSascha Wildner extern void fResetBootMark(PVDevice pLogical); 98735878b55SSascha Wildner static void 98835878b55SSascha Wildner fRegisterVdevice(IAL_ADAPTER_T *pAdapter) 98935878b55SSascha Wildner { 99035878b55SSascha Wildner PVDevice pPhysical, pLogical; 99135878b55SSascha Wildner PVBus pVBus; 99235878b55SSascha Wildner int i,j; 99335878b55SSascha Wildner 99435878b55SSascha Wildner for(i=0;i<MV_SATA_CHANNELS_NUM;i++) { 99535878b55SSascha Wildner pPhysical = &(pAdapter->VDevices[i]); 99635878b55SSascha Wildner pLogical = pPhysical; 99735878b55SSascha Wildner while (pLogical->pParent) pLogical = pLogical->pParent; 99835878b55SSascha Wildner if (pLogical->vf_online==0) { 99935878b55SSascha Wildner pPhysical->vf_bootmark = pLogical->vf_bootmark = 0; 100035878b55SSascha Wildner continue; 100135878b55SSascha Wildner } 100235878b55SSascha Wildner if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical)) 100335878b55SSascha Wildner continue; 100435878b55SSascha Wildner 100535878b55SSascha Wildner pVBus = &pAdapter->VBus; 100635878b55SSascha Wildner if(pVBus) 100735878b55SSascha Wildner { 100835878b55SSascha Wildner j=0; 100935878b55SSascha Wildner while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++; 101035878b55SSascha Wildner if(j<MAX_VDEVICE_PER_VBUS){ 101135878b55SSascha Wildner pVBus->pVDevice[j] = pLogical; 101235878b55SSascha Wildner pLogical->pVBus = pVBus; 101335878b55SSascha Wildner 101435878b55SSascha Wildner if (j>0 && pLogical->vf_bootmark) { 101535878b55SSascha Wildner if (pVBus->pVDevice[0]->vf_bootmark) { 101635878b55SSascha Wildner fResetBootMark(pLogical); 101735878b55SSascha Wildner } 101835878b55SSascha Wildner else { 101935878b55SSascha Wildner do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j); 102035878b55SSascha Wildner pVBus->pVDevice[0] = pLogical; 102135878b55SSascha Wildner } 102235878b55SSascha Wildner } 102335878b55SSascha Wildner } 102435878b55SSascha Wildner } 102535878b55SSascha Wildner } 102635878b55SSascha Wildner } 102735878b55SSascha Wildner 102835878b55SSascha Wildner PVDevice 102935878b55SSascha Wildner GetSpareDisk(_VBUS_ARG PVDevice pArray) 103035878b55SSascha Wildner { 103135878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; 103235878b55SSascha Wildner LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); 103335878b55SSascha Wildner LBA_T thiscap, maxcap = MAX_LBA_T; 103435878b55SSascha Wildner PVDevice pVDevice, pFind = NULL; 103535878b55SSascha Wildner int i; 103635878b55SSascha Wildner 103735878b55SSascha Wildner for(i=0;i<MV_SATA_CHANNELS_NUM;i++) 103835878b55SSascha Wildner { 103935878b55SSascha Wildner pVDevice = &pAdapter->VDevices[i]; 104035878b55SSascha Wildner if(!pVDevice) 104135878b55SSascha Wildner continue; 104235878b55SSascha Wildner thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; 104335878b55SSascha Wildner /* find the smallest usable spare disk */ 104435878b55SSascha Wildner if (pVDevice->VDeviceType==VD_SPARE && 104535878b55SSascha Wildner pVDevice->u.disk.df_on_line && 104635878b55SSascha Wildner thiscap < maxcap && 104735878b55SSascha Wildner thiscap >= capacity) 104835878b55SSascha Wildner { 104935878b55SSascha Wildner maxcap = pVDevice->VDeviceCapacity; 105035878b55SSascha Wildner pFind = pVDevice; 105135878b55SSascha Wildner } 105235878b55SSascha Wildner } 105335878b55SSascha Wildner return pFind; 105435878b55SSascha Wildner } 105535878b55SSascha Wildner 105635878b55SSascha Wildner /****************************************************************** 105735878b55SSascha Wildner * IO ATA Command 105835878b55SSascha Wildner *******************************************************************/ 105935878b55SSascha Wildner int HPTLIBAPI 106035878b55SSascha Wildner fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer) 106135878b55SSascha Wildner { 106235878b55SSascha Wildner return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer); 106335878b55SSascha Wildner } 106435878b55SSascha Wildner 106535878b55SSascha Wildner void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) 106635878b55SSascha Wildner { 106735878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 106835878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 106935878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 107035878b55SSascha Wildner UCHAR mvMode; 107135878b55SSascha Wildner /* 508x don't use MW-DMA? */ 107235878b55SSascha Wildner if (NewMode>4 && NewMode<8) NewMode = 4; 107335878b55SSascha Wildner pDev->bDeModeSetting = NewMode; 107435878b55SSascha Wildner if (NewMode<=4) 107535878b55SSascha Wildner mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode; 107635878b55SSascha Wildner else 107735878b55SSascha Wildner mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8); 107835878b55SSascha Wildner 107935878b55SSascha Wildner /*To fix 88i8030 bug*/ 108035878b55SSascha Wildner if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4) 108135878b55SSascha Wildner mvMode = MV_ATA_TRANSFER_UDMA_0; 108235878b55SSascha Wildner 108335878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 108435878b55SSascha Wildner /* Flush pending commands */ 108535878b55SSascha Wildner mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE); 108635878b55SSascha Wildner 108735878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 108835878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 108935878b55SSascha Wildner mvMode, 0, 0, 0) == MV_FALSE) 109035878b55SSascha Wildner { 109135878b55SSascha Wildner KdPrint(("channel %d: Set Features failed\n", channelIndex)); 109235878b55SSascha Wildner } 109335878b55SSascha Wildner /* Enable EDMA */ 109435878b55SSascha Wildner if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE) 109535878b55SSascha Wildner KdPrint(("Failed to enable DMA, channel=%d", channelIndex)); 109635878b55SSascha Wildner } 109735878b55SSascha Wildner 109835878b55SSascha Wildner int HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth) 109935878b55SSascha Wildner { 110035878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 110135878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 110235878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 110335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 110435878b55SSascha Wildner MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 110535878b55SSascha Wildner int dmaActive = pSataChannel->queueCommandsEnabled; 110635878b55SSascha Wildner int ret = 0; 110735878b55SSascha Wildner 110835878b55SSascha Wildner if (dmaActive) { 110935878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 111035878b55SSascha Wildner mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 111135878b55SSascha Wildner } 111235878b55SSascha Wildner 111335878b55SSascha Wildner if (enable) { 111435878b55SSascha Wildner if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED && 111535878b55SSascha Wildner (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) { 111635878b55SSascha Wildner UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1; 111735878b55SSascha Wildner channelInfo->queueDepth = (depth==32)? 31 : depth; 111835878b55SSascha Wildner mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth); 111935878b55SSascha Wildner ret = 1; 112035878b55SSascha Wildner } 112135878b55SSascha Wildner } 112235878b55SSascha Wildner else 112335878b55SSascha Wildner { 112435878b55SSascha Wildner if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) { 112535878b55SSascha Wildner channelInfo->queueDepth = 2; 112635878b55SSascha Wildner mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0); 112735878b55SSascha Wildner ret = 1; 112835878b55SSascha Wildner } 112935878b55SSascha Wildner } 113035878b55SSascha Wildner 113135878b55SSascha Wildner if (dmaActive) 113235878b55SSascha Wildner mvSataEnableChannelDma(pSataAdapter,channelIndex); 113335878b55SSascha Wildner return ret; 113435878b55SSascha Wildner } 113535878b55SSascha Wildner 113635878b55SSascha Wildner int HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth) 113735878b55SSascha Wildner { 113835878b55SSascha Wildner return 0; 113935878b55SSascha Wildner } 114035878b55SSascha Wildner 114135878b55SSascha Wildner int HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable) 114235878b55SSascha Wildner { 114335878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 114435878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 114535878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 114635878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 114735878b55SSascha Wildner MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 114835878b55SSascha Wildner int dmaActive = pSataChannel->queueCommandsEnabled; 114935878b55SSascha Wildner int ret = 0; 115035878b55SSascha Wildner 115135878b55SSascha Wildner if (dmaActive) { 115235878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 115335878b55SSascha Wildner mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 115435878b55SSascha Wildner } 115535878b55SSascha Wildner 115635878b55SSascha Wildner if ((pSataChannel->identifyDevice[82] & (0x20))) { 115735878b55SSascha Wildner if (enable) { 115835878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 115935878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0)) 116035878b55SSascha Wildner { 116135878b55SSascha Wildner channelInfo->writeCacheEnabled = MV_TRUE; 116235878b55SSascha Wildner ret = 1; 116335878b55SSascha Wildner } 116435878b55SSascha Wildner } 116535878b55SSascha Wildner else { 116635878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 116735878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0)) 116835878b55SSascha Wildner { 116935878b55SSascha Wildner channelInfo->writeCacheEnabled = MV_FALSE; 117035878b55SSascha Wildner ret = 1; 117135878b55SSascha Wildner } 117235878b55SSascha Wildner } 117335878b55SSascha Wildner } 117435878b55SSascha Wildner 117535878b55SSascha Wildner if (dmaActive) 117635878b55SSascha Wildner mvSataEnableChannelDma(pSataAdapter,channelIndex); 117735878b55SSascha Wildner return ret; 117835878b55SSascha Wildner } 117935878b55SSascha Wildner 118035878b55SSascha Wildner int HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable) 118135878b55SSascha Wildner { 118235878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel = pDev->mv; 118335878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 118435878b55SSascha Wildner MV_U8 channelIndex = pSataChannel->channelNumber; 118535878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData; 118635878b55SSascha Wildner MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]); 118735878b55SSascha Wildner int dmaActive = pSataChannel->queueCommandsEnabled; 118835878b55SSascha Wildner int ret = 0; 118935878b55SSascha Wildner 119035878b55SSascha Wildner if (dmaActive) { 119135878b55SSascha Wildner mvSataDisableChannelDma(pSataAdapter, channelIndex); 119235878b55SSascha Wildner mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK); 119335878b55SSascha Wildner } 119435878b55SSascha Wildner 119535878b55SSascha Wildner if ((pSataChannel->identifyDevice[82] & (0x40))) { 119635878b55SSascha Wildner if (enable) { 119735878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 119835878b55SSascha Wildner MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0)) 119935878b55SSascha Wildner { 120035878b55SSascha Wildner channelInfo->readAheadEnabled = MV_TRUE; 120135878b55SSascha Wildner ret = 1; 120235878b55SSascha Wildner } 120335878b55SSascha Wildner } 120435878b55SSascha Wildner else { 120535878b55SSascha Wildner if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 120635878b55SSascha Wildner MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0)) 120735878b55SSascha Wildner { 120835878b55SSascha Wildner channelInfo->readAheadEnabled = MV_FALSE; 120935878b55SSascha Wildner ret = 1; 121035878b55SSascha Wildner } 121135878b55SSascha Wildner } 121235878b55SSascha Wildner } 121335878b55SSascha Wildner 121435878b55SSascha Wildner if (dmaActive) 121535878b55SSascha Wildner mvSataEnableChannelDma(pSataAdapter,channelIndex); 121635878b55SSascha Wildner return ret; 121735878b55SSascha Wildner } 121835878b55SSascha Wildner 121935878b55SSascha Wildner #ifdef SUPPORT_ARRAY 122035878b55SSascha Wildner #define IdeRegisterVDevice fCheckArray 122135878b55SSascha Wildner #else 122235878b55SSascha Wildner void 122335878b55SSascha Wildner IdeRegisterVDevice(PDevice pDev) 122435878b55SSascha Wildner { 122535878b55SSascha Wildner PVDevice pVDev = Map2pVDevice(pDev); 122635878b55SSascha Wildner 122735878b55SSascha Wildner pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI : 122835878b55SSascha Wildner pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 122935878b55SSascha Wildner pVDev->vf_online = 1; 123035878b55SSascha Wildner pVDev->VDeviceCapacity = pDev->dDeRealCapacity; 123135878b55SSascha Wildner pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 123235878b55SSascha Wildner pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 123335878b55SSascha Wildner } 123435878b55SSascha Wildner #endif 123535878b55SSascha Wildner 123635878b55SSascha Wildner static __inline PBUS_DMAMAP 123735878b55SSascha Wildner dmamap_get(struct IALAdapter * pAdapter) 123835878b55SSascha Wildner { 123935878b55SSascha Wildner PBUS_DMAMAP p = pAdapter->pbus_dmamap_list; 124035878b55SSascha Wildner if (p) 124135878b55SSascha Wildner pAdapter->pbus_dmamap_list = p-> next; 124235878b55SSascha Wildner return p; 124335878b55SSascha Wildner } 124435878b55SSascha Wildner 124535878b55SSascha Wildner static __inline void 124635878b55SSascha Wildner dmamap_put(PBUS_DMAMAP p) 124735878b55SSascha Wildner { 124835878b55SSascha Wildner p->next = p->pAdapter->pbus_dmamap_list; 124935878b55SSascha Wildner p->pAdapter->pbus_dmamap_list = p; 125035878b55SSascha Wildner } 125135878b55SSascha Wildner 125235878b55SSascha Wildner /*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/ 125335878b55SSascha Wildner #define override_kernel_driver() 125435878b55SSascha Wildner 125535878b55SSascha Wildner static void hpt_init(void *dummy) 125635878b55SSascha Wildner { 125735878b55SSascha Wildner override_kernel_driver(); 125835878b55SSascha Wildner lockinit(&driver_lock, "hptsleeplock", 0, LK_CANRECURSE); 125935878b55SSascha Wildner } 126035878b55SSascha Wildner SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 126135878b55SSascha Wildner 126235878b55SSascha Wildner static int num_adapters = 0; 126335878b55SSascha Wildner static int 126435878b55SSascha Wildner init_adapter(IAL_ADAPTER_T *pAdapter) 126535878b55SSascha Wildner { 126635878b55SSascha Wildner PVBus _vbus_p = &pAdapter->VBus; 126735878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter; 126835878b55SSascha Wildner int i, channel, rid; 126935878b55SSascha Wildner 127035878b55SSascha Wildner PVDevice pVDev; 127135878b55SSascha Wildner 1272c898d682SSascha Wildner lock_driver(); 127335878b55SSascha Wildner 127435878b55SSascha Wildner pAdapter->next = 0; 127535878b55SSascha Wildner 12764090d6ffSSascha Wildner if(gIal_Adapter == NULL){ 127735878b55SSascha Wildner gIal_Adapter = pAdapter; 127835878b55SSascha Wildner pCurAdapter = gIal_Adapter; 127935878b55SSascha Wildner } 128035878b55SSascha Wildner else { 128135878b55SSascha Wildner pCurAdapter->next = pAdapter; 128235878b55SSascha Wildner pCurAdapter = pAdapter; 128335878b55SSascha Wildner } 128435878b55SSascha Wildner 128535878b55SSascha Wildner pAdapter->outstandingCommands = 0; 128635878b55SSascha Wildner 128735878b55SSascha Wildner pMvSataAdapter = &(pAdapter->mvSataAdapter); 128835878b55SSascha Wildner _vbus_p->OsExt = (void *)pAdapter; 128935878b55SSascha Wildner pMvSataAdapter->IALData = pAdapter; 129035878b55SSascha Wildner 129135878b55SSascha Wildner if (bus_dma_tag_create(NULL,/* parent */ 129235878b55SSascha Wildner 4, /* alignment */ 129335878b55SSascha Wildner BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 129435878b55SSascha Wildner BUS_SPACE_MAXADDR, /* lowaddr */ 129535878b55SSascha Wildner BUS_SPACE_MAXADDR, /* highaddr */ 129635878b55SSascha Wildner NULL, NULL, /* filter, filterarg */ 129735878b55SSascha Wildner PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */ 129835878b55SSascha Wildner MAX_SG_DESCRIPTORS, /* nsegments */ 129935878b55SSascha Wildner 0x10000, /* maxsegsize */ 130035878b55SSascha Wildner BUS_DMA_WAITOK, /* flags */ 130135878b55SSascha Wildner &pAdapter->io_dma_parent /* tag */)) 130235878b55SSascha Wildner { 130335878b55SSascha Wildner return ENXIO; 130435878b55SSascha Wildner } 130535878b55SSascha Wildner 130635878b55SSascha Wildner 130735878b55SSascha Wildner if (hptmv_allocate_edma_queues(pAdapter)) 130835878b55SSascha Wildner { 130935878b55SSascha Wildner MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n"); 1310c898d682SSascha Wildner unlock_driver(); 131135878b55SSascha Wildner return ENOMEM; 131235878b55SSascha Wildner } 131335878b55SSascha Wildner 131435878b55SSascha Wildner /* also map EPROM address */ 131535878b55SSascha Wildner rid = 0x10; 131635878b55SSascha Wildner if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid, 131735878b55SSascha Wildner 0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE)) 131835878b55SSascha Wildner || 131935878b55SSascha Wildner !(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res))) 132035878b55SSascha Wildner { 132135878b55SSascha Wildner MV_ERROR("RR18xx: Failed to remap memory space\n"); 132235878b55SSascha Wildner hptmv_free_edma_queues(pAdapter); 1323c898d682SSascha Wildner unlock_driver(); 132435878b55SSascha Wildner return ENXIO; 132535878b55SSascha Wildner } 132635878b55SSascha Wildner else 132735878b55SSascha Wildner { 132835878b55SSascha Wildner KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress)); 132935878b55SSascha Wildner } 133035878b55SSascha Wildner 133135878b55SSascha Wildner pMvSataAdapter->adapterId = num_adapters++; 133235878b55SSascha Wildner /* get the revision ID */ 133335878b55SSascha Wildner pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); 133435878b55SSascha Wildner pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev); 133535878b55SSascha Wildner 133635878b55SSascha Wildner /* init RR18xx */ 133735878b55SSascha Wildner pMvSataAdapter->intCoalThre[0]= 1; 133835878b55SSascha Wildner pMvSataAdapter->intCoalThre[1]= 1; 133935878b55SSascha Wildner pMvSataAdapter->intTimeThre[0] = 1; 134035878b55SSascha Wildner pMvSataAdapter->intTimeThre[1] = 1; 134135878b55SSascha Wildner pMvSataAdapter->pciCommand = 0x0107E371; 134235878b55SSascha Wildner pMvSataAdapter->pciSerrMask = 0xd77fe6ul; 134335878b55SSascha Wildner pMvSataAdapter->pciInterruptMask = 0xd77fe6ul; 134435878b55SSascha Wildner pMvSataAdapter->mvSataEventNotify = hptmv_event_notify; 134535878b55SSascha Wildner 134635878b55SSascha Wildner if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) 134735878b55SSascha Wildner { 134835878b55SSascha Wildner MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n", 134935878b55SSascha Wildner pMvSataAdapter->adapterId); 135035878b55SSascha Wildner unregister: 135135878b55SSascha Wildner bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res); 135235878b55SSascha Wildner hptmv_free_edma_queues(pAdapter); 1353c898d682SSascha Wildner unlock_driver(); 135435878b55SSascha Wildner return ENXIO; 135535878b55SSascha Wildner } 135635878b55SSascha Wildner pAdapter->ver_601 = pMvSataAdapter->pcbVersion; 135735878b55SSascha Wildner 135835878b55SSascha Wildner #ifndef FOR_DEMO 135935878b55SSascha Wildner set_fail_leds(pMvSataAdapter, 0); 136035878b55SSascha Wildner #endif 136135878b55SSascha Wildner 136235878b55SSascha Wildner /* setup command blocks */ 136335878b55SSascha Wildner KdPrint(("Allocate command blocks\n")); 13644c0cc8bbSSascha Wildner _vbus_(pFreeCommands) = NULL; 136535878b55SSascha Wildner pAdapter->pCommandBlocks = 136635878b55SSascha Wildner kmalloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT); 136735878b55SSascha Wildner KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks)); 136835878b55SSascha Wildner if (!pAdapter->pCommandBlocks) { 136935878b55SSascha Wildner MV_ERROR("insufficient memory\n"); 137035878b55SSascha Wildner goto unregister; 137135878b55SSascha Wildner } 137235878b55SSascha Wildner 137335878b55SSascha Wildner for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) { 137435878b55SSascha Wildner FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i])); 137535878b55SSascha Wildner } 137635878b55SSascha Wildner 137735878b55SSascha Wildner /*Set up the bus_dmamap*/ 137835878b55SSascha Wildner pAdapter->pbus_dmamap = (PBUS_DMAMAP)kmalloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT); 137935878b55SSascha Wildner if(!pAdapter->pbus_dmamap) { 138035878b55SSascha Wildner MV_ERROR("insufficient memory\n"); 138135878b55SSascha Wildner kfree(pAdapter->pCommandBlocks, M_DEVBUF); 138235878b55SSascha Wildner goto unregister; 138335878b55SSascha Wildner } 138435878b55SSascha Wildner 138535878b55SSascha Wildner memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM); 138635878b55SSascha Wildner pAdapter->pbus_dmamap_list = 0; 138735878b55SSascha Wildner for (i=0; i < MAX_QUEUE_COMM; i++) { 138835878b55SSascha Wildner PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]); 138935878b55SSascha Wildner pmap->pAdapter = pAdapter; 139035878b55SSascha Wildner dmamap_put(pmap); 139135878b55SSascha Wildner 139235878b55SSascha Wildner if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) { 139335878b55SSascha Wildner MV_ERROR("Can not allocate dma map\n"); 139435878b55SSascha Wildner kfree(pAdapter->pCommandBlocks, M_DEVBUF); 139535878b55SSascha Wildner kfree(pAdapter->pbus_dmamap, M_DEVBUF); 139635878b55SSascha Wildner goto unregister; 139735878b55SSascha Wildner } 139835878b55SSascha Wildner } 139935878b55SSascha Wildner /* setup PRD Tables */ 140035878b55SSascha Wildner KdPrint(("Allocate PRD Tables\n")); 140135878b55SSascha Wildner pAdapter->pFreePRDLink = 0; 140235878b55SSascha Wildner 140335878b55SSascha Wildner pAdapter->prdTableAddr = (PUCHAR)contigmalloc( 140435878b55SSascha Wildner (PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 140535878b55SSascha Wildner 140635878b55SSascha Wildner KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr)); 140735878b55SSascha Wildner if (!pAdapter->prdTableAddr) { 140835878b55SSascha Wildner MV_ERROR("insufficient PRD Tables\n"); 140935878b55SSascha Wildner goto unregister; 141035878b55SSascha Wildner } 141135878b55SSascha Wildner pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL); 141235878b55SSascha Wildner { 141335878b55SSascha Wildner PUCHAR PRDTable = pAdapter->prdTableAlignedAddr; 141435878b55SSascha Wildner for (i=0; i<PRD_TABLES_FOR_VBUS; i++) 141535878b55SSascha Wildner { 141635878b55SSascha Wildner /* KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */ 141735878b55SSascha Wildner FreePRDTable(pAdapter, PRDTable); 141835878b55SSascha Wildner PRDTable += PRD_ENTRIES_SIZE; 141935878b55SSascha Wildner } 142035878b55SSascha Wildner } 142135878b55SSascha Wildner 142235878b55SSascha Wildner /* enable the adapter interrupts */ 142335878b55SSascha Wildner 142435878b55SSascha Wildner /* configure and start the connected channels*/ 142535878b55SSascha Wildner for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 142635878b55SSascha Wildner { 142735878b55SSascha Wildner pAdapter->mvChannel[channel].online = MV_FALSE; 142835878b55SSascha Wildner if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) 142935878b55SSascha Wildner == MV_TRUE) 143035878b55SSascha Wildner { 143135878b55SSascha Wildner KdPrint(("RR18xx[%d]: channel %d is connected\n", 143235878b55SSascha Wildner pMvSataAdapter->adapterId, channel)); 143335878b55SSascha Wildner 143435878b55SSascha Wildner if (hptmv_init_channel(pAdapter, channel) == 0) 143535878b55SSascha Wildner { 143635878b55SSascha Wildner if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE) 143735878b55SSascha Wildner { 143835878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to configure channel" 143935878b55SSascha Wildner " %d\n",pMvSataAdapter->adapterId, channel); 144035878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 144135878b55SSascha Wildner } 144235878b55SSascha Wildner else 144335878b55SSascha Wildner { 144435878b55SSascha Wildner if (start_channel(pAdapter, channel)) 144535878b55SSascha Wildner { 144635878b55SSascha Wildner MV_ERROR("RR18xx[%d]: Failed to start channel," 144735878b55SSascha Wildner " channel=%d\n",pMvSataAdapter->adapterId, 144835878b55SSascha Wildner channel); 144935878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 145035878b55SSascha Wildner } 145135878b55SSascha Wildner pAdapter->mvChannel[channel].online = MV_TRUE; 145235878b55SSascha Wildner /* mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter, 145335878b55SSascha Wildner channel, 145435878b55SSascha Wildner MV_TRUE);*/ 145535878b55SSascha Wildner } 145635878b55SSascha Wildner } 145735878b55SSascha Wildner } 145835878b55SSascha Wildner KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n", 145935878b55SSascha Wildner pAdapter->mvChannel[channel].online, channel)); 146035878b55SSascha Wildner } 146135878b55SSascha Wildner 146235878b55SSascha Wildner #ifdef SUPPORT_ARRAY 146335878b55SSascha Wildner for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) { 146435878b55SSascha Wildner pVDev = ArrayTables(i); 146535878b55SSascha Wildner mArFreeArrayTable(pVDev); 146635878b55SSascha Wildner } 146735878b55SSascha Wildner #endif 146835878b55SSascha Wildner 146935878b55SSascha Wildner KdPrint(("Initialize Devices\n")); 147035878b55SSascha Wildner for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { 147135878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 147235878b55SSascha Wildner if (pMvSataChannel) { 147335878b55SSascha Wildner init_vdev_params(pAdapter, channel); 147435878b55SSascha Wildner IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk); 147535878b55SSascha Wildner } 147635878b55SSascha Wildner } 147735878b55SSascha Wildner #ifdef SUPPORT_ARRAY 147835878b55SSascha Wildner CheckArrayCritical(_VBUS_P0); 147935878b55SSascha Wildner #endif 148035878b55SSascha Wildner _vbus_p->nInstances = 1; 148135878b55SSascha Wildner fRegisterVdevice(pAdapter); 148235878b55SSascha Wildner 148335878b55SSascha Wildner for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) { 148435878b55SSascha Wildner pVDev = _vbus_p->pVDevice[channel]; 148535878b55SSascha Wildner if (pVDev && pVDev->vf_online) 148635878b55SSascha Wildner fCheckBootable(pVDev); 148735878b55SSascha Wildner } 148835878b55SSascha Wildner 148935878b55SSascha Wildner #if defined(SUPPORT_ARRAY) && defined(_RAID5N_) 149035878b55SSascha Wildner init_raid5_memory(_VBUS_P0); 149135878b55SSascha Wildner _vbus_(r5).enable_write_back = 1; 149235878b55SSascha Wildner kprintf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled"); 149335878b55SSascha Wildner #endif 149435878b55SSascha Wildner 149535878b55SSascha Wildner mvSataUnmaskAdapterInterrupt(pMvSataAdapter); 1496c898d682SSascha Wildner unlock_driver(); 149735878b55SSascha Wildner return 0; 149835878b55SSascha Wildner } 149935878b55SSascha Wildner 150035878b55SSascha Wildner int 150135878b55SSascha Wildner MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) 150235878b55SSascha Wildner { 150335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; 150435878b55SSascha Wildner 150535878b55SSascha Wildner mvSataDisableChannelDma(pMvSataAdapter, channel); 150635878b55SSascha Wildner /* Flush pending commands */ 150735878b55SSascha Wildner mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 150835878b55SSascha Wildner 150935878b55SSascha Wildner /* Software reset channel */ 151035878b55SSascha Wildner if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE) 151135878b55SSascha Wildner { 151235878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n", 151335878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 151435878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 151535878b55SSascha Wildner return -1; 151635878b55SSascha Wildner } 151735878b55SSascha Wildner 151835878b55SSascha Wildner /* Hardware reset channel */ 151935878b55SSascha Wildner if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) 152035878b55SSascha Wildner { 152135878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n", 152235878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 152335878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 152435878b55SSascha Wildner return -1; 152535878b55SSascha Wildner } 152635878b55SSascha Wildner 152735878b55SSascha Wildner if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE) 152835878b55SSascha Wildner { 152935878b55SSascha Wildner MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n", 153035878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 153135878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 153235878b55SSascha Wildner return -1; 153335878b55SSascha Wildner }else 153435878b55SSascha Wildner { 153535878b55SSascha Wildner MV_ERROR("channel %d: perform recalibrate command", channel); 153635878b55SSascha Wildner if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 153735878b55SSascha Wildner MV_NON_UDMA_PROTOCOL_NON_DATA, 153835878b55SSascha Wildner MV_FALSE, 153935878b55SSascha Wildner NULL, /* pBuffer*/ 154035878b55SSascha Wildner 0, /* count */ 154135878b55SSascha Wildner 0, /*features*/ 154235878b55SSascha Wildner /* sectorCount */ 154335878b55SSascha Wildner 0, 154435878b55SSascha Wildner 0, /* lbaLow */ 154535878b55SSascha Wildner 0, /* lbaMid */ 154635878b55SSascha Wildner /* lbaHigh */ 154735878b55SSascha Wildner 0, 154835878b55SSascha Wildner 0, /* device */ 154935878b55SSascha Wildner /* command */ 155035878b55SSascha Wildner 0x10)) 155135878b55SSascha Wildner MV_ERROR("channel %d: recalibrate failed", channel); 155235878b55SSascha Wildner 155335878b55SSascha Wildner /* Set transfer mode */ 155435878b55SSascha Wildner if((mvStorageDevATASetFeatures(pMvSataAdapter, channel, 155535878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 155635878b55SSascha Wildner MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) || 155735878b55SSascha Wildner (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 155835878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 155935878b55SSascha Wildner pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) || 156035878b55SSascha Wildner (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 156135878b55SSascha Wildner MV_ATA_SET_FEATURES_TRANSFER, 156235878b55SSascha Wildner pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) ) 156335878b55SSascha Wildner { 156435878b55SSascha Wildner MV_ERROR("channel %d: Set Features failed", channel); 156535878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 156635878b55SSascha Wildner return -1; 156735878b55SSascha Wildner } 156835878b55SSascha Wildner /* Enable EDMA */ 156935878b55SSascha Wildner if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE) 157035878b55SSascha Wildner { 157135878b55SSascha Wildner MV_ERROR("Failed to enable DMA, channel=%d", channel); 157235878b55SSascha Wildner hptmv_free_channel(pAdapter, channel); 157335878b55SSascha Wildner return -1; 157435878b55SSascha Wildner } 157535878b55SSascha Wildner } 157635878b55SSascha Wildner return 0; 157735878b55SSascha Wildner } 157835878b55SSascha Wildner 157935878b55SSascha Wildner static int 158035878b55SSascha Wildner fResetActiveCommands(PVBus _vbus_p) 158135878b55SSascha Wildner { 158235878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 158335878b55SSascha Wildner MV_U8 channel; 158435878b55SSascha Wildner for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 158535878b55SSascha Wildner if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands) 158635878b55SSascha Wildner MvSataResetChannel(pMvSataAdapter,channel); 158735878b55SSascha Wildner } 158835878b55SSascha Wildner return 0; 158935878b55SSascha Wildner } 159035878b55SSascha Wildner 159135878b55SSascha Wildner void fCompleteAllCommandsSynchronously(PVBus _vbus_p) 159235878b55SSascha Wildner { 159335878b55SSascha Wildner UINT cont; 159435878b55SSascha Wildner ULONG ticks = 0; 159535878b55SSascha Wildner MV_U8 channel; 159635878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 159735878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel; 159835878b55SSascha Wildner 159935878b55SSascha Wildner do { 160035878b55SSascha Wildner check_cmds: 160135878b55SSascha Wildner cont = 0; 160235878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 160335878b55SSascha Wildner #ifdef _RAID5N_ 160435878b55SSascha Wildner dataxfer_poll(); 160535878b55SSascha Wildner xor_poll(); 160635878b55SSascha Wildner #endif 160735878b55SSascha Wildner for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 160835878b55SSascha Wildner pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 160935878b55SSascha Wildner if (pMvSataChannel && pMvSataChannel->outstandingCommands) 161035878b55SSascha Wildner { 161135878b55SSascha Wildner while (pMvSataChannel->outstandingCommands) { 161235878b55SSascha Wildner if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) { 161335878b55SSascha Wildner StallExec(1000); 161435878b55SSascha Wildner if (ticks++ > 3000) { 161535878b55SSascha Wildner MvSataResetChannel(pMvSataAdapter,channel); 161635878b55SSascha Wildner goto check_cmds; 161735878b55SSascha Wildner } 161835878b55SSascha Wildner } 161935878b55SSascha Wildner else 162035878b55SSascha Wildner ticks = 0; 162135878b55SSascha Wildner } 162235878b55SSascha Wildner cont = 1; 162335878b55SSascha Wildner } 162435878b55SSascha Wildner } 162535878b55SSascha Wildner } while (cont); 162635878b55SSascha Wildner } 162735878b55SSascha Wildner 162835878b55SSascha Wildner void 162935878b55SSascha Wildner fResetVBus(_VBUS_ARG0) 163035878b55SSascha Wildner { 163135878b55SSascha Wildner KdPrint(("fMvResetBus(%p)", _vbus_p)); 163235878b55SSascha Wildner 163335878b55SSascha Wildner /* some commands may already finished. */ 163435878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 163535878b55SSascha Wildner 163635878b55SSascha Wildner fResetActiveCommands(_vbus_p); 163735878b55SSascha Wildner /* 163835878b55SSascha Wildner * the other pending commands may still be finished successfully. 163935878b55SSascha Wildner */ 164035878b55SSascha Wildner fCompleteAllCommandsSynchronously(_vbus_p); 164135878b55SSascha Wildner 164235878b55SSascha Wildner /* Now there should be no pending commands. No more action needed. */ 164335878b55SSascha Wildner CheckIdleCall(_VBUS_P0); 164435878b55SSascha Wildner 164535878b55SSascha Wildner KdPrint(("fMvResetBus() done")); 164635878b55SSascha Wildner } 164735878b55SSascha Wildner 164835878b55SSascha Wildner /*No rescan function*/ 164935878b55SSascha Wildner void 165035878b55SSascha Wildner fRescanAllDevice(_VBUS_ARG0) 165135878b55SSascha Wildner { 165235878b55SSascha Wildner } 165335878b55SSascha Wildner 165435878b55SSascha Wildner static MV_BOOLEAN 165535878b55SSascha Wildner CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 165635878b55SSascha Wildner MV_U8 channelNum, 165735878b55SSascha Wildner MV_COMPLETION_TYPE comp_type, 165835878b55SSascha Wildner MV_VOID_PTR commandId, 165935878b55SSascha Wildner MV_U16 responseFlags, 166035878b55SSascha Wildner MV_U32 timeStamp, 166135878b55SSascha Wildner MV_STORAGE_DEVICE_REGISTERS *registerStruct) 166235878b55SSascha Wildner { 166335878b55SSascha Wildner PCommand pCmd = (PCommand) commandId; 166435878b55SSascha Wildner _VBUS_INST(pCmd->pVDevice->pVBus) 166535878b55SSascha Wildner 166635878b55SSascha Wildner if (pCmd->uScratch.sata_param.prdAddr) 166735878b55SSascha Wildner FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr); 166835878b55SSascha Wildner 166935878b55SSascha Wildner switch (comp_type) 167035878b55SSascha Wildner { 167135878b55SSascha Wildner case MV_COMPLETION_TYPE_NORMAL: 167235878b55SSascha Wildner pCmd->Result = RETURN_SUCCESS; 167335878b55SSascha Wildner break; 167435878b55SSascha Wildner case MV_COMPLETION_TYPE_ABORT: 167535878b55SSascha Wildner pCmd->Result = RETURN_BUS_RESET; 167635878b55SSascha Wildner break; 167735878b55SSascha Wildner case MV_COMPLETION_TYPE_ERROR: 167835878b55SSascha Wildner MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n", 167935878b55SSascha Wildner pMvSataAdapter->adapterId, channelNum, responseFlags); 168035878b55SSascha Wildner 168135878b55SSascha Wildner if (responseFlags & 4) { 168235878b55SSascha Wildner MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x," 168335878b55SSascha Wildner " LBA high %x, device %x, status %x\n", 168435878b55SSascha Wildner registerStruct->errorRegister, 168535878b55SSascha Wildner registerStruct->sectorCountRegister, 168635878b55SSascha Wildner registerStruct->lbaLowRegister, 168735878b55SSascha Wildner registerStruct->lbaMidRegister, 168835878b55SSascha Wildner registerStruct->lbaHighRegister, 168935878b55SSascha Wildner registerStruct->deviceRegister, 169035878b55SSascha Wildner registerStruct->statusRegister); 169135878b55SSascha Wildner } 169235878b55SSascha Wildner /*We can't do handleEdmaError directly here, because CommandCompletionCB is called by 169335878b55SSascha Wildner * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/ 169435878b55SSascha Wildner pCmd->uScratch.sata_param.responseFlags = responseFlags; 169535878b55SSascha Wildner pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister; 169635878b55SSascha Wildner pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister; 169735878b55SSascha Wildner pCmd->pVDevice->u.disk.QueueLength--; 169835878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd); 169935878b55SSascha Wildner return TRUE; 170035878b55SSascha Wildner 170135878b55SSascha Wildner default: 170235878b55SSascha Wildner MV_ERROR(" Unknown completion type (%d)\n", comp_type); 170335878b55SSascha Wildner return MV_FALSE; 170435878b55SSascha Wildner } 170535878b55SSascha Wildner 170635878b55SSascha Wildner if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) { 170735878b55SSascha Wildner pCmd->uScratch.sata_param.cmd_priv --; 170835878b55SSascha Wildner return TRUE; 170935878b55SSascha Wildner } 171035878b55SSascha Wildner pCmd->pVDevice->u.disk.QueueLength--; 171135878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 171235878b55SSascha Wildner return TRUE; 171335878b55SSascha Wildner } 171435878b55SSascha Wildner 171535878b55SSascha Wildner void 171635878b55SSascha Wildner fDeviceSendCommand(_VBUS_ARG PCommand pCmd) 171735878b55SSascha Wildner { 17184c0cc8bbSSascha Wildner MV_SATA_EDMA_PRD_ENTRY *pPRDTable = NULL; 171935878b55SSascha Wildner MV_SATA_ADAPTER *pMvSataAdapter; 172035878b55SSascha Wildner MV_SATA_CHANNEL *pMvSataChannel; 172135878b55SSascha Wildner PVDevice pVDevice = pCmd->pVDevice; 172235878b55SSascha Wildner PDevice pDevice = &pVDevice->u.disk; 172335878b55SSascha Wildner LBA_T Lba = pCmd->uCmd.Ide.Lba; 172435878b55SSascha Wildner USHORT nSector = pCmd->uCmd.Ide.nSectors; 172535878b55SSascha Wildner 172635878b55SSascha Wildner MV_QUEUE_COMMAND_RESULT result; 172735878b55SSascha Wildner MV_QUEUE_COMMAND_INFO commandInfo; 172835878b55SSascha Wildner MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand; 172935878b55SSascha Wildner MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; 173035878b55SSascha Wildner 173135878b55SSascha Wildner MV_BOOLEAN is48bit; 173235878b55SSascha Wildner MV_U8 channel; 173335878b55SSascha Wildner int i=0; 173435878b55SSascha Wildner 173535878b55SSascha Wildner DECLARE_BUFFER(FPSCAT_GATH, tmpSg); 173635878b55SSascha Wildner 173735878b55SSascha Wildner if (!pDevice->df_on_line) { 173835878b55SSascha Wildner MV_ERROR("Device is offline"); 173935878b55SSascha Wildner pCmd->Result = RETURN_BAD_DEVICE; 174035878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 174135878b55SSascha Wildner return; 174235878b55SSascha Wildner } 174335878b55SSascha Wildner 174435878b55SSascha Wildner pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors; 174535878b55SSascha Wildner pMvSataChannel = pDevice->mv; 174635878b55SSascha Wildner pMvSataAdapter = pMvSataChannel->mvSataAdapter; 174735878b55SSascha Wildner channel = pMvSataChannel->channelNumber; 174835878b55SSascha Wildner 174935878b55SSascha Wildner /* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */ 175035878b55SSascha Wildner Lba += pDevice->dDeHiddenLba; 175135878b55SSascha Wildner /* check LBA */ 175235878b55SSascha Wildner if (Lba+nSector-1 > pDevice->dDeRealCapacity) { 175335878b55SSascha Wildner pCmd->Result = RETURN_INVALID_REQUEST; 175435878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 175535878b55SSascha Wildner return; 175635878b55SSascha Wildner } 175735878b55SSascha Wildner 175835878b55SSascha Wildner /* 175935878b55SSascha Wildner * always use 48bit LBA if drive supports it. 176035878b55SSascha Wildner * Some Seagate drives report error if you use a 28-bit command 176135878b55SSascha Wildner * to access sector 0xfffffff. 176235878b55SSascha Wildner */ 176335878b55SSascha Wildner is48bit = pMvSataChannel->lba48Address; 176435878b55SSascha Wildner 176535878b55SSascha Wildner switch (pCmd->uCmd.Ide.Command) 176635878b55SSascha Wildner { 176735878b55SSascha Wildner case IDE_COMMAND_READ: 176835878b55SSascha Wildner case IDE_COMMAND_WRITE: 176935878b55SSascha Wildner if (pDevice->bDeModeSetting<8) goto pio; 177035878b55SSascha Wildner 177135878b55SSascha Wildner commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA; 177235878b55SSascha Wildner pUdmaParams->isEXT = is48bit; 177335878b55SSascha Wildner pUdmaParams->numOfSectors = nSector; 177435878b55SSascha Wildner pUdmaParams->lowLBAAddress = Lba; 177535878b55SSascha Wildner pUdmaParams->highLBAAddress = 0; 177635878b55SSascha Wildner pUdmaParams->prdHighAddr = 0; 177735878b55SSascha Wildner pUdmaParams->callBack = CommandCompletionCB; 177835878b55SSascha Wildner pUdmaParams->commandId = (MV_VOID_PTR )pCmd; 177935878b55SSascha Wildner if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ) 178035878b55SSascha Wildner pUdmaParams->readWrite = MV_UDMA_TYPE_READ; 178135878b55SSascha Wildner else 178235878b55SSascha Wildner pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE; 178335878b55SSascha Wildner 178435878b55SSascha Wildner if (pCmd->pSgTable && pCmd->cf_physical_sg) { 178535878b55SSascha Wildner FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 178635878b55SSascha Wildner do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 178735878b55SSascha Wildner } 178835878b55SSascha Wildner else { 178935878b55SSascha Wildner if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { 179035878b55SSascha Wildner pio: 179135878b55SSascha Wildner mvSataDisableChannelDma(pMvSataAdapter, channel); 179235878b55SSascha Wildner mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 179335878b55SSascha Wildner 179435878b55SSascha Wildner if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { 179535878b55SSascha Wildner FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 179635878b55SSascha Wildner do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 179735878b55SSascha Wildner } 179835878b55SSascha Wildner else { 179935878b55SSascha Wildner if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) { 180035878b55SSascha Wildner pCmd->Result = RETURN_NEED_LOGICAL_SG; 180135878b55SSascha Wildner goto finish_cmd; 180235878b55SSascha Wildner } 180335878b55SSascha Wildner } 180435878b55SSascha Wildner 180535878b55SSascha Wildner do { 180635878b55SSascha Wildner ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; 180735878b55SSascha Wildner ULONG_PTR addr = tmpSg->dSgAddress; 180835878b55SSascha Wildner if (size & 0x1ff) { 180935878b55SSascha Wildner pCmd->Result = RETURN_INVALID_REQUEST; 181035878b55SSascha Wildner goto finish_cmd; 181135878b55SSascha Wildner } 181235878b55SSascha Wildner if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 181335878b55SSascha Wildner (pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, 181435878b55SSascha Wildner is48bit, 181535878b55SSascha Wildner (MV_U16_PTR)addr, 181635878b55SSascha Wildner size >> 1, /* count */ 181735878b55SSascha Wildner 0, /* features N/A */ 181835878b55SSascha Wildner (MV_U16)(size>>9), /*sector count*/ 181935878b55SSascha Wildner (MV_U16)( (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | (UCHAR)(Lba & 0xFF) ), /*lbalow*/ 182035878b55SSascha Wildner (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ 182135878b55SSascha Wildner (MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh */ 182235878b55SSascha Wildner (MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device */ 182335878b55SSascha Wildner (MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command) 182435878b55SSascha Wildner )==MV_FALSE) 182535878b55SSascha Wildner { 182635878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 182735878b55SSascha Wildner goto finish_cmd; 182835878b55SSascha Wildner } 182935878b55SSascha Wildner Lba += size>>9; 183035878b55SSascha Wildner if(Lba & 0xF0000000) is48bit = MV_TRUE; 183135878b55SSascha Wildner } 183235878b55SSascha Wildner while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 183335878b55SSascha Wildner pCmd->Result = RETURN_SUCCESS; 183435878b55SSascha Wildner finish_cmd: 183535878b55SSascha Wildner mvSataEnableChannelDma(pMvSataAdapter,channel); 183635878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 183735878b55SSascha Wildner return; 183835878b55SSascha Wildner } 183935878b55SSascha Wildner } 184035878b55SSascha Wildner 184135878b55SSascha Wildner pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData); 184235878b55SSascha Wildner KdPrint(("pPRDTable:%p\n",pPRDTable)); 184335878b55SSascha Wildner if (!pPRDTable) { 184435878b55SSascha Wildner pCmd->Result = RETURN_DEVICE_BUSY; 184535878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 184635878b55SSascha Wildner HPT_ASSERT(0); 184735878b55SSascha Wildner return; 184835878b55SSascha Wildner } 184935878b55SSascha Wildner 185035878b55SSascha Wildner do{ 185135878b55SSascha Wildner pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0); 185235878b55SSascha Wildner pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag; 185335878b55SSascha Wildner pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize; 185435878b55SSascha Wildner pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress; 185535878b55SSascha Wildner pPRDTable[i].reserved = 0; 185635878b55SSascha Wildner i++; 185735878b55SSascha Wildner }while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 185835878b55SSascha Wildner 185935878b55SSascha Wildner pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable); 186035878b55SSascha Wildner if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) { 186135878b55SSascha Wildner pUdmaParams->numOfSectors = 0; 186235878b55SSascha Wildner } 186335878b55SSascha Wildner 186435878b55SSascha Wildner pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable; 186535878b55SSascha Wildner 186635878b55SSascha Wildner result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 186735878b55SSascha Wildner 186835878b55SSascha Wildner if (result != MV_QUEUE_COMMAND_RESULT_OK) 186935878b55SSascha Wildner { 187035878b55SSascha Wildner queue_failed: 187135878b55SSascha Wildner switch (result) 187235878b55SSascha Wildner { 187335878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS: 187435878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA " 187535878b55SSascha Wildner "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress); 187635878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 187735878b55SSascha Wildner break; 187835878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED: 187935878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. EDMA" 188035878b55SSascha Wildner " disabled adapter %d channel %d\n", 188135878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 188235878b55SSascha Wildner mvSataEnableChannelDma(pMvSataAdapter,channel); 188335878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 188435878b55SSascha Wildner break; 188535878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_FULL: 188635878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. Queue is" 188735878b55SSascha Wildner " Full adapter %d channel %d\n", 188835878b55SSascha Wildner pMvSataAdapter->adapterId, channel); 188935878b55SSascha Wildner pCmd->Result = RETURN_DEVICE_BUSY; 189035878b55SSascha Wildner break; 189135878b55SSascha Wildner case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS: 189235878b55SSascha Wildner MV_ERROR("IAL Error: Edma Queue command failed. (Bad " 189335878b55SSascha Wildner "Params), pMvSataAdapter: %p, pSataChannel: %p.\n", 189435878b55SSascha Wildner pMvSataAdapter, pMvSataAdapter->sataChannel[channel]); 189535878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 189635878b55SSascha Wildner break; 189735878b55SSascha Wildner default: 189835878b55SSascha Wildner MV_ERROR("IAL Error: Bad result value (%d) from queue" 189935878b55SSascha Wildner " command\n", result); 190035878b55SSascha Wildner pCmd->Result = RETURN_IDE_ERROR; 190135878b55SSascha Wildner } 190235878b55SSascha Wildner if(pPRDTable) 190335878b55SSascha Wildner FreePRDTable(pMvSataAdapter->IALData,pPRDTable); 190435878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 190535878b55SSascha Wildner } 190635878b55SSascha Wildner pDevice->QueueLength++; 190735878b55SSascha Wildner return; 190835878b55SSascha Wildner 190935878b55SSascha Wildner case IDE_COMMAND_VERIFY: 191035878b55SSascha Wildner commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA; 191135878b55SSascha Wildner pNoUdmaParams->bufPtr = NULL; 191235878b55SSascha Wildner pNoUdmaParams->callBack = CommandCompletionCB; 191335878b55SSascha Wildner pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd; 191435878b55SSascha Wildner pNoUdmaParams->count = 0; 191535878b55SSascha Wildner pNoUdmaParams->features = 0; 191635878b55SSascha Wildner pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA; 191735878b55SSascha Wildner 191835878b55SSascha Wildner pCmd->uScratch.sata_param.cmd_priv = 1; 191935878b55SSascha Wildner if (pMvSataChannel->lba48Address == MV_TRUE){ 192035878b55SSascha Wildner pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; 192135878b55SSascha Wildner pNoUdmaParams->isEXT = MV_TRUE; 192235878b55SSascha Wildner pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 192335878b55SSascha Wildner pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 192435878b55SSascha Wildner pNoUdmaParams->lbaLow = 192535878b55SSascha Wildner (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); 192635878b55SSascha Wildner pNoUdmaParams->sectorCount = nSector; 192735878b55SSascha Wildner pNoUdmaParams->device = 0x40; 192835878b55SSascha Wildner result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 192935878b55SSascha Wildner if (result != MV_QUEUE_COMMAND_RESULT_OK){ 193035878b55SSascha Wildner goto queue_failed; 193135878b55SSascha Wildner } 193235878b55SSascha Wildner return; 193335878b55SSascha Wildner } 193435878b55SSascha Wildner else{ 193535878b55SSascha Wildner pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; 193635878b55SSascha Wildner pNoUdmaParams->isEXT = MV_FALSE; 193735878b55SSascha Wildner pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 193835878b55SSascha Wildner pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 193935878b55SSascha Wildner pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); 194035878b55SSascha Wildner pNoUdmaParams->sectorCount = 0xff & nSector; 194135878b55SSascha Wildner pNoUdmaParams->device = (MV_U8)(0x40 | 194235878b55SSascha Wildner ((Lba & 0xf000000) >> 24)); 194335878b55SSascha Wildner pNoUdmaParams->callBack = CommandCompletionCB; 194435878b55SSascha Wildner result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 194535878b55SSascha Wildner /*FIXME: how about the commands already queued? but marvel also forgets to consider this*/ 194635878b55SSascha Wildner if (result != MV_QUEUE_COMMAND_RESULT_OK){ 194735878b55SSascha Wildner goto queue_failed; 194835878b55SSascha Wildner } 194935878b55SSascha Wildner } 195035878b55SSascha Wildner break; 195135878b55SSascha Wildner default: 195235878b55SSascha Wildner pCmd->Result = RETURN_INVALID_REQUEST; 195335878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 195435878b55SSascha Wildner break; 195535878b55SSascha Wildner } 195635878b55SSascha Wildner } 195735878b55SSascha Wildner 195835878b55SSascha Wildner /********************************************************** 195935878b55SSascha Wildner * 196035878b55SSascha Wildner * Probe the hostadapter. 196135878b55SSascha Wildner * 196235878b55SSascha Wildner **********************************************************/ 196335878b55SSascha Wildner static int 196435878b55SSascha Wildner hpt_probe(device_t dev) 196535878b55SSascha Wildner { 196635878b55SSascha Wildner if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) && 196735878b55SSascha Wildner (pci_get_device(dev) == MV_SATA_DEVICE_ID_5081 196835878b55SSascha Wildner #ifdef FOR_DEMO 196935878b55SSascha Wildner || pci_get_device(dev) == MV_SATA_DEVICE_ID_5080 197035878b55SSascha Wildner #endif 197135878b55SSascha Wildner )) 197235878b55SSascha Wildner { 197335878b55SSascha Wildner KdPrintI((CONTROLLER_NAME " found\n")); 197435878b55SSascha Wildner device_set_desc(dev, CONTROLLER_NAME); 197535878b55SSascha Wildner return 0; 197635878b55SSascha Wildner } 197735878b55SSascha Wildner else 197835878b55SSascha Wildner return(ENXIO); 197935878b55SSascha Wildner } 198035878b55SSascha Wildner 198135878b55SSascha Wildner /*********************************************************** 198235878b55SSascha Wildner * 198335878b55SSascha Wildner * Auto configuration: attach and init a host adapter. 198435878b55SSascha Wildner * 198535878b55SSascha Wildner ***********************************************************/ 198635878b55SSascha Wildner static int 198735878b55SSascha Wildner hpt_attach(device_t dev) 198835878b55SSascha Wildner { 198935878b55SSascha Wildner IAL_ADAPTER_T * pAdapter = device_get_softc(dev); 199035878b55SSascha Wildner int rid; 199135878b55SSascha Wildner union ccb *ccb; 199235878b55SSascha Wildner struct cam_devq *devq; 199335878b55SSascha Wildner struct cam_sim *hpt_vsim; 199435878b55SSascha Wildner 199535878b55SSascha Wildner kprintf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION); 199635878b55SSascha Wildner 199735878b55SSascha Wildner if (!pAdapter) 199835878b55SSascha Wildner { 199935878b55SSascha Wildner pAdapter = (IAL_ADAPTER_T *)kmalloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT); 200035878b55SSascha Wildner device_set_softc(dev, (void *)pAdapter); 200135878b55SSascha Wildner } 200235878b55SSascha Wildner 200335878b55SSascha Wildner if (!pAdapter) return (ENOMEM); 200435878b55SSascha Wildner bzero(pAdapter, sizeof(IAL_ADAPTER_T)); 200535878b55SSascha Wildner 200635878b55SSascha Wildner pAdapter->hpt_dev = dev; 200735878b55SSascha Wildner 200835878b55SSascha Wildner rid = init_adapter(pAdapter); 200935878b55SSascha Wildner if (rid) 201035878b55SSascha Wildner return rid; 201135878b55SSascha Wildner 201235878b55SSascha Wildner rid = 0; 201335878b55SSascha Wildner if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 201435878b55SSascha Wildner { 201535878b55SSascha Wildner hpt_printk(("can't allocate interrupt\n")); 201635878b55SSascha Wildner return(ENXIO); 201735878b55SSascha Wildner } 201835878b55SSascha Wildner 201935878b55SSascha Wildner if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, 0, 202035878b55SSascha Wildner hpt_intr, pAdapter, &pAdapter->hpt_intr, NULL)) 202135878b55SSascha Wildner { 202235878b55SSascha Wildner hpt_printk(("can't set up interrupt\n")); 202335878b55SSascha Wildner kfree(pAdapter, M_DEVBUF); 202435878b55SSascha Wildner return(ENXIO); 202535878b55SSascha Wildner } 202635878b55SSascha Wildner 202735878b55SSascha Wildner 2028a2d0f739SSascha Wildner ccb = kmalloc(sizeof(*ccb), M_DEVBUF, M_WAITOK | M_ZERO); 202935878b55SSascha Wildner ccb->ccb_h.pinfo.priority = 1; 203035878b55SSascha Wildner ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; 203199eeb924SSascha Wildner 203235878b55SSascha Wildner /* 203335878b55SSascha Wildner * Create the device queue for our SIM(s). 203435878b55SSascha Wildner */ 203535878b55SSascha Wildner if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) 203635878b55SSascha Wildner { 203735878b55SSascha Wildner KdPrint(("ENXIO\n")); 203835878b55SSascha Wildner return ENOMEM; 203935878b55SSascha Wildner } 204035878b55SSascha Wildner 204135878b55SSascha Wildner /* 204235878b55SSascha Wildner * Construct our SIM entry 204335878b55SSascha Wildner */ 204435878b55SSascha Wildner hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), 204535878b55SSascha Wildner pAdapter, device_get_unit(pAdapter->hpt_dev), &sim_mplock, 1, 8, devq); 204635878b55SSascha Wildner cam_simq_release(devq); 204735878b55SSascha Wildner if (hpt_vsim == NULL) { 204835878b55SSascha Wildner return ENOMEM; 204935878b55SSascha Wildner } 205035878b55SSascha Wildner 205135878b55SSascha Wildner if (xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS) 205235878b55SSascha Wildner { 205335878b55SSascha Wildner cam_sim_free(hpt_vsim); 205435878b55SSascha Wildner hpt_vsim = NULL; 205535878b55SSascha Wildner return ENXIO; 205635878b55SSascha Wildner } 205735878b55SSascha Wildner 205835878b55SSascha Wildner if(xpt_create_path(&pAdapter->path, /*periph */ NULL, 205935878b55SSascha Wildner cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, 206035878b55SSascha Wildner CAM_LUN_WILDCARD) != CAM_REQ_CMP) 206135878b55SSascha Wildner { 206235878b55SSascha Wildner xpt_bus_deregister(cam_sim_path(hpt_vsim)); 206335878b55SSascha Wildner cam_sim_free(hpt_vsim); 206435878b55SSascha Wildner hpt_vsim = NULL; 206535878b55SSascha Wildner return ENXIO; 206635878b55SSascha Wildner } 206735878b55SSascha Wildner 206835878b55SSascha Wildner xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5); 206935878b55SSascha Wildner ccb->ccb_h.func_code = XPT_SASYNC_CB; 207035878b55SSascha Wildner ccb->csa.event_enable = AC_LOST_DEVICE; 207135878b55SSascha Wildner ccb->csa.callback = hpt_async; 207235878b55SSascha Wildner ccb->csa.callback_arg = hpt_vsim; 2073362298e4SSascha Wildner xpt_action(ccb); 207435878b55SSascha Wildner kfree(ccb, M_DEVBUF); 207535878b55SSascha Wildner 207635878b55SSascha Wildner callout_init(&pAdapter->event_timer_connect); 207735878b55SSascha Wildner callout_init(&pAdapter->event_timer_disconnect); 207835878b55SSascha Wildner 207935878b55SSascha Wildner if (device_get_unit(dev) == 0) { 208035878b55SSascha Wildner /* Start the work thread. XXX */ 208135878b55SSascha Wildner launch_worker_thread(); 20822050a95dSSascha Wildner 20832050a95dSSascha Wildner /* 20842050a95dSSascha Wildner * hpt_worker_thread needs to be suspended after shutdown 20852050a95dSSascha Wildner * sync, when fs sync finished. 20862050a95dSSascha Wildner */ 20872050a95dSSascha Wildner pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, 20882050a95dSSascha Wildner shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST); 208935878b55SSascha Wildner } 209035878b55SSascha Wildner 209135878b55SSascha Wildner return 0; 209235878b55SSascha Wildner } 209335878b55SSascha Wildner 209435878b55SSascha Wildner static int 209535878b55SSascha Wildner hpt_detach(device_t dev) 209635878b55SSascha Wildner { 209735878b55SSascha Wildner return (EBUSY); 209835878b55SSascha Wildner } 209935878b55SSascha Wildner 210035878b55SSascha Wildner 210135878b55SSascha Wildner /*************************************************************** 210235878b55SSascha Wildner * The poll function is used to simulate the interrupt when 210335878b55SSascha Wildner * the interrupt subsystem is not functioning. 210435878b55SSascha Wildner * 210535878b55SSascha Wildner ***************************************************************/ 210635878b55SSascha Wildner static void 210735878b55SSascha Wildner hpt_poll(struct cam_sim *sim) 210835878b55SSascha Wildner { 210935878b55SSascha Wildner hpt_intr((void *)cam_sim_softc(sim)); 211035878b55SSascha Wildner } 211135878b55SSascha Wildner 211235878b55SSascha Wildner /**************************************************************** 211335878b55SSascha Wildner * Name: hpt_intr 211435878b55SSascha Wildner * Description: Interrupt handler. 211535878b55SSascha Wildner ****************************************************************/ 211635878b55SSascha Wildner static void 211735878b55SSascha Wildner hpt_intr(void *arg) 211835878b55SSascha Wildner { 211935878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg; 212035878b55SSascha Wildner 2121c898d682SSascha Wildner lock_driver(); 212235878b55SSascha Wildner /* KdPrintI(("----- Entering Isr() -----\n")); */ 212335878b55SSascha Wildner if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE) 212435878b55SSascha Wildner { 212535878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 212635878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 212735878b55SSascha Wildner } 212835878b55SSascha Wildner 212935878b55SSascha Wildner /* KdPrintI(("----- Leaving Isr() -----\n")); */ 2130c898d682SSascha Wildner unlock_driver(); 213135878b55SSascha Wildner } 213235878b55SSascha Wildner 213335878b55SSascha Wildner /********************************************************** 213435878b55SSascha Wildner * Asynchronous Events 213535878b55SSascha Wildner *********************************************************/ 213635878b55SSascha Wildner #if (!defined(UNREFERENCED_PARAMETER)) 213735878b55SSascha Wildner #define UNREFERENCED_PARAMETER(x) (void)(x) 213835878b55SSascha Wildner #endif 213935878b55SSascha Wildner 214035878b55SSascha Wildner static void 214135878b55SSascha Wildner hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, 214235878b55SSascha Wildner void * arg) 214335878b55SSascha Wildner { 214435878b55SSascha Wildner /* debug XXXX */ 214535878b55SSascha Wildner panic("Here"); 214635878b55SSascha Wildner UNREFERENCED_PARAMETER(callback_arg); 214735878b55SSascha Wildner UNREFERENCED_PARAMETER(code); 214835878b55SSascha Wildner UNREFERENCED_PARAMETER(path); 214935878b55SSascha Wildner UNREFERENCED_PARAMETER(arg); 215035878b55SSascha Wildner 215135878b55SSascha Wildner } 215235878b55SSascha Wildner 215335878b55SSascha Wildner static void 215435878b55SSascha Wildner FlushAdapter(IAL_ADAPTER_T *pAdapter) 215535878b55SSascha Wildner { 215635878b55SSascha Wildner int i; 215735878b55SSascha Wildner 215835878b55SSascha Wildner hpt_printk(("flush all devices\n")); 215935878b55SSascha Wildner 216035878b55SSascha Wildner /* flush all devices */ 216135878b55SSascha Wildner for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) { 216235878b55SSascha Wildner PVDevice pVDev = pAdapter->VBus.pVDevice[i]; 216335878b55SSascha Wildner if(pVDev) fFlushVDev(pVDev); 216435878b55SSascha Wildner } 216535878b55SSascha Wildner } 216635878b55SSascha Wildner 216735878b55SSascha Wildner static int 216835878b55SSascha Wildner hpt_shutdown(device_t dev) 216935878b55SSascha Wildner { 217035878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 217135878b55SSascha Wildner 217235878b55SSascha Wildner pAdapter = device_get_softc(dev); 217335878b55SSascha Wildner if (pAdapter == NULL) 217435878b55SSascha Wildner return (EINVAL); 217535878b55SSascha Wildner 21762050a95dSSascha Wildner EVENTHANDLER_DEREGISTER(shutdown_post_sync, pAdapter->eh); 217735878b55SSascha Wildner FlushAdapter(pAdapter); 217835878b55SSascha Wildner /* give the flush some time to happen, 217935878b55SSascha Wildner *otherwise "shutdown -p now" will make file system corrupted */ 218035878b55SSascha Wildner DELAY(1000 * 1000 * 5); 218135878b55SSascha Wildner return 0; 218235878b55SSascha Wildner } 218335878b55SSascha Wildner 218435878b55SSascha Wildner void 218535878b55SSascha Wildner Check_Idle_Call(IAL_ADAPTER_T *pAdapter) 218635878b55SSascha Wildner { 218735878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 218835878b55SSascha Wildner 218935878b55SSascha Wildner if (mWaitingForIdle(_VBUS_P0)) { 219035878b55SSascha Wildner CheckIdleCall(_VBUS_P0); 219135878b55SSascha Wildner #ifdef SUPPORT_ARRAY 219235878b55SSascha Wildner { 219335878b55SSascha Wildner int i; 219435878b55SSascha Wildner PVDevice pArray; 219535878b55SSascha Wildner for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ 219635878b55SSascha Wildner if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 219735878b55SSascha Wildner continue; 219835878b55SSascha Wildner else if (pArray->u.array.rf_auto_rebuild) { 219935878b55SSascha Wildner KdPrint(("auto rebuild.\n")); 220035878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 0; 220135878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 220235878b55SSascha Wildner } 220335878b55SSascha Wildner } 220435878b55SSascha Wildner } 220535878b55SSascha Wildner #endif 220635878b55SSascha Wildner } 220735878b55SSascha Wildner /* launch the awaiting commands blocked by mWaitingForIdle */ 220835878b55SSascha Wildner while(pAdapter->pending_Q!= NULL) 220935878b55SSascha Wildner { 221035878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 221135878b55SSascha Wildner union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; 221235878b55SSascha Wildner hpt_free_ccb(&pAdapter->pending_Q, ccb); 221335878b55SSascha Wildner CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb); 221435878b55SSascha Wildner } 221535878b55SSascha Wildner } 221635878b55SSascha Wildner 221735878b55SSascha Wildner static void 221835878b55SSascha Wildner ccb_done(union ccb *ccb) 221935878b55SSascha Wildner { 222035878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 222135878b55SSascha Wildner IAL_ADAPTER_T * pAdapter = pmap->pAdapter; 222235878b55SSascha Wildner KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status)); 222335878b55SSascha Wildner 222435878b55SSascha Wildner dmamap_put(pmap); 222535878b55SSascha Wildner xpt_done(ccb); 222635878b55SSascha Wildner 222735878b55SSascha Wildner pAdapter->outstandingCommands--; 222835878b55SSascha Wildner 222935878b55SSascha Wildner if (pAdapter->outstandingCommands == 0) 223035878b55SSascha Wildner { 223135878b55SSascha Wildner if(DPC_Request_Nums == 0) 223235878b55SSascha Wildner Check_Idle_Call(pAdapter); 223335878b55SSascha Wildner } 223435878b55SSascha Wildner } 223535878b55SSascha Wildner 223635878b55SSascha Wildner /**************************************************************** 223735878b55SSascha Wildner * Name: hpt_action 223835878b55SSascha Wildner * Description: Process a queued command from the CAM layer. 223935878b55SSascha Wildner * Parameters: sim - Pointer to SIM object 224035878b55SSascha Wildner * ccb - Pointer to SCSI command structure. 224135878b55SSascha Wildner ****************************************************************/ 224235878b55SSascha Wildner 224335878b55SSascha Wildner void 224435878b55SSascha Wildner hpt_action(struct cam_sim *sim, union ccb *ccb) 224535878b55SSascha Wildner { 224635878b55SSascha Wildner IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim); 224735878b55SSascha Wildner PBUS_DMAMAP pmap; 224835878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 224935878b55SSascha Wildner 225035878b55SSascha Wildner CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n")); 225135878b55SSascha Wildner KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code)); 225235878b55SSascha Wildner 225335878b55SSascha Wildner switch (ccb->ccb_h.func_code) 225435878b55SSascha Wildner { 225535878b55SSascha Wildner case XPT_SCSI_IO: /* Execute the requested I/O operation */ 225635878b55SSascha Wildner { 225735878b55SSascha Wildner /* ccb->ccb_h.path_id is not our bus id - don't check it */ 225835878b55SSascha Wildner 225935878b55SSascha Wildner if (ccb->ccb_h.target_lun) { 226035878b55SSascha Wildner ccb->ccb_h.status = CAM_LUN_INVALID; 226135878b55SSascha Wildner xpt_done(ccb); 226235878b55SSascha Wildner return; 226335878b55SSascha Wildner } 226435878b55SSascha Wildner if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || 226535878b55SSascha Wildner pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { 226635878b55SSascha Wildner ccb->ccb_h.status = CAM_TID_INVALID; 226735878b55SSascha Wildner xpt_done(ccb); 226835878b55SSascha Wildner return; 226935878b55SSascha Wildner } 227035878b55SSascha Wildner 2271c898d682SSascha Wildner lock_driver(); 227235878b55SSascha Wildner if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 227335878b55SSascha Wildner Check_Idle_Call(pAdapter); 227435878b55SSascha Wildner 227535878b55SSascha Wildner pmap = dmamap_get(pAdapter); 227635878b55SSascha Wildner HPT_ASSERT(pmap); 227735878b55SSascha Wildner ccb->ccb_adapter = pmap; 227835878b55SSascha Wildner memset((void *)pmap->psg, 0, sizeof(pmap->psg)); 227935878b55SSascha Wildner 228035878b55SSascha Wildner if (mWaitingForIdle(_VBUS_P0)) 228135878b55SSascha Wildner hpt_queue_ccb(&pAdapter->pending_Q, ccb); 228235878b55SSascha Wildner else 228335878b55SSascha Wildner OsSendCommand(_VBUS_P ccb); 2284c898d682SSascha Wildner unlock_driver(); 228535878b55SSascha Wildner 228635878b55SSascha Wildner /* KdPrint(("leave scsiio\n")); */ 228735878b55SSascha Wildner break; 228835878b55SSascha Wildner } 228935878b55SSascha Wildner 229035878b55SSascha Wildner case XPT_RESET_BUS: 229135878b55SSascha Wildner KdPrint(("reset bus\n")); 2292c898d682SSascha Wildner lock_driver(); 229335878b55SSascha Wildner fResetVBus(_VBUS_P0); 2294c898d682SSascha Wildner unlock_driver(); 229535878b55SSascha Wildner xpt_done(ccb); 229635878b55SSascha Wildner break; 229735878b55SSascha Wildner 229835878b55SSascha Wildner case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 229935878b55SSascha Wildner case XPT_EN_LUN: /* Enable LUN as a target */ 230035878b55SSascha Wildner case XPT_TARGET_IO: /* Execute target I/O request */ 230135878b55SSascha Wildner case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 230235878b55SSascha Wildner case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 230335878b55SSascha Wildner case XPT_ABORT: /* Abort the specified CCB */ 230435878b55SSascha Wildner case XPT_TERM_IO: /* Terminate the I/O process */ 230535878b55SSascha Wildner /* XXX Implement */ 230635878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 230735878b55SSascha Wildner xpt_done(ccb); 230835878b55SSascha Wildner break; 230935878b55SSascha Wildner 231035878b55SSascha Wildner case XPT_GET_TRAN_SETTINGS: 231135878b55SSascha Wildner case XPT_SET_TRAN_SETTINGS: 231235878b55SSascha Wildner /* XXX Implement */ 231335878b55SSascha Wildner ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 231435878b55SSascha Wildner xpt_done(ccb); 231535878b55SSascha Wildner break; 231635878b55SSascha Wildner 231735878b55SSascha Wildner case XPT_CALC_GEOMETRY: 2318c7e78657SSascha Wildner cam_calc_geometry(&ccb->ccg, 1); 231935878b55SSascha Wildner xpt_done(ccb); 232035878b55SSascha Wildner break; 232135878b55SSascha Wildner 232235878b55SSascha Wildner case XPT_PATH_INQ: /* Path routing inquiry */ 232335878b55SSascha Wildner { 232435878b55SSascha Wildner struct ccb_pathinq *cpi = &ccb->cpi; 232535878b55SSascha Wildner 232635878b55SSascha Wildner cpi->version_num = 1; /* XXX??? */ 232735878b55SSascha Wildner cpi->hba_inquiry = PI_SDTR_ABLE; 232835878b55SSascha Wildner cpi->target_sprt = 0; 232935878b55SSascha Wildner /* Not necessary to reset bus */ 233035878b55SSascha Wildner cpi->hba_misc = PIM_NOBUSRESET; 233135878b55SSascha Wildner cpi->hba_eng_cnt = 0; 233235878b55SSascha Wildner 233335878b55SSascha Wildner cpi->max_target = MAX_VDEVICE_PER_VBUS; 233435878b55SSascha Wildner cpi->max_lun = 0; 233535878b55SSascha Wildner cpi->initiator_id = MAX_VDEVICE_PER_VBUS; 233635878b55SSascha Wildner 233735878b55SSascha Wildner cpi->bus_id = cam_sim_bus(sim); 233835878b55SSascha Wildner cpi->base_transfer_speed = 3300; 233935878b55SSascha Wildner strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 234035878b55SSascha Wildner strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 234135878b55SSascha Wildner strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 234235878b55SSascha Wildner cpi->unit_number = cam_sim_unit(sim); 234335878b55SSascha Wildner cpi->transport = XPORT_SPI; 234435878b55SSascha Wildner cpi->transport_version = 2; 234535878b55SSascha Wildner cpi->protocol = PROTO_SCSI; 234635878b55SSascha Wildner cpi->protocol_version = SCSI_REV_2; 2347ea778d16SSascha Wildner cpi->maxio = HPTMV_DFLTPHYS; 234835878b55SSascha Wildner cpi->ccb_h.status = CAM_REQ_CMP; 234935878b55SSascha Wildner xpt_done(ccb); 235035878b55SSascha Wildner break; 235135878b55SSascha Wildner } 235235878b55SSascha Wildner 235335878b55SSascha Wildner default: 235435878b55SSascha Wildner KdPrint(("invalid cmd\n")); 235535878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 235635878b55SSascha Wildner xpt_done(ccb); 235735878b55SSascha Wildner break; 235835878b55SSascha Wildner } 235935878b55SSascha Wildner /* KdPrint(("leave hpt_action..............\n")); */ 236035878b55SSascha Wildner } 236135878b55SSascha Wildner 236235878b55SSascha Wildner /* shall be called at lock_driver() */ 236335878b55SSascha Wildner static void 236435878b55SSascha Wildner hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb) 236535878b55SSascha Wildner { 236635878b55SSascha Wildner if(*ccb_Q == NULL) 236735878b55SSascha Wildner ccb->ccb_h.ccb_ccb_ptr = ccb; 236835878b55SSascha Wildner else { 236935878b55SSascha Wildner ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr; 237035878b55SSascha Wildner (*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb; 237135878b55SSascha Wildner } 237235878b55SSascha Wildner 237335878b55SSascha Wildner *ccb_Q = ccb; 237435878b55SSascha Wildner } 237535878b55SSascha Wildner 237635878b55SSascha Wildner /* shall be called at lock_driver() */ 237735878b55SSascha Wildner static void 237835878b55SSascha Wildner hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb) 237935878b55SSascha Wildner { 238035878b55SSascha Wildner union ccb *TempCCB; 238135878b55SSascha Wildner 238235878b55SSascha Wildner TempCCB = *ccb_Q; 238335878b55SSascha Wildner 238435878b55SSascha Wildner if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/ 238535878b55SSascha Wildner *ccb_Q = NULL; 238635878b55SSascha Wildner else { 238735878b55SSascha Wildner while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb) 238835878b55SSascha Wildner TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr; 238935878b55SSascha Wildner 239035878b55SSascha Wildner TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr; 239135878b55SSascha Wildner 239235878b55SSascha Wildner if(*ccb_Q == ccb) 239335878b55SSascha Wildner *ccb_Q = TempCCB; 239435878b55SSascha Wildner } 239535878b55SSascha Wildner } 239635878b55SSascha Wildner 239735878b55SSascha Wildner #ifdef SUPPORT_ARRAY 239835878b55SSascha Wildner /*************************************************************************** 239935878b55SSascha Wildner * Function: hpt_worker_thread 240035878b55SSascha Wildner * Description: Do background rebuilding. Execute in kernel thread context. 240135878b55SSascha Wildner * Returns: None 240235878b55SSascha Wildner ***************************************************************************/ 240335878b55SSascha Wildner static void hpt_worker_thread(void) 240435878b55SSascha Wildner { 240535878b55SSascha Wildner for(;;) { 240635878b55SSascha Wildner while (DpcQueue_First!=DpcQueue_Last) { 240735878b55SSascha Wildner ST_HPT_DPC p; 2408c898d682SSascha Wildner lock_driver(); 240935878b55SSascha Wildner p = DpcQueue[DpcQueue_First]; 241035878b55SSascha Wildner DpcQueue_First++; 241135878b55SSascha Wildner DpcQueue_First %= MAX_DPC; 241235878b55SSascha Wildner DPC_Request_Nums++; 2413c898d682SSascha Wildner unlock_driver(); 241435878b55SSascha Wildner p.dpc(p.pAdapter, p.arg, p.flags); 241535878b55SSascha Wildner 2416c898d682SSascha Wildner lock_driver(); 241735878b55SSascha Wildner DPC_Request_Nums--; 241835878b55SSascha Wildner /* since we may have prevented Check_Idle_Call, do it here */ 241935878b55SSascha Wildner if (DPC_Request_Nums==0) { 242035878b55SSascha Wildner if (p.pAdapter->outstandingCommands == 0) { 242135878b55SSascha Wildner _VBUS_INST(&p.pAdapter->VBus); 242235878b55SSascha Wildner Check_Idle_Call(p.pAdapter); 242335878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 242435878b55SSascha Wildner } 242535878b55SSascha Wildner } 2426c898d682SSascha Wildner unlock_driver(); 242735878b55SSascha Wildner 242835878b55SSascha Wildner /*Schedule out*/ 242935878b55SSascha Wildner tsleep((caddr_t)hpt_worker_thread, 0, "sched", 1); 243035878b55SSascha Wildner if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) { 243135878b55SSascha Wildner /* abort rebuilding process. */ 243235878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 243335878b55SSascha Wildner PVDevice pArray; 243435878b55SSascha Wildner PVBus _vbus_p; 243535878b55SSascha Wildner int i; 243635878b55SSascha Wildner pAdapter = gIal_Adapter; 243735878b55SSascha Wildner 24384090d6ffSSascha Wildner while(pAdapter != NULL){ 243935878b55SSascha Wildner 244035878b55SSascha Wildner _vbus_p = &pAdapter->VBus; 244135878b55SSascha Wildner 244235878b55SSascha Wildner for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 244335878b55SSascha Wildner { 244435878b55SSascha Wildner if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 244535878b55SSascha Wildner continue; 244635878b55SSascha Wildner else if (pArray->u.array.rf_rebuilding || 244735878b55SSascha Wildner pArray->u.array.rf_verifying || 244835878b55SSascha Wildner pArray->u.array.rf_initializing) 244935878b55SSascha Wildner { 245035878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 1; 245135878b55SSascha Wildner } 245235878b55SSascha Wildner } 245335878b55SSascha Wildner pAdapter = pAdapter->next; 245435878b55SSascha Wildner } 245535878b55SSascha Wildner } 245635878b55SSascha Wildner } 245735878b55SSascha Wildner 245835878b55SSascha Wildner /*Remove this debug option*/ 245935878b55SSascha Wildner /* 246035878b55SSascha Wildner #ifdef DEBUG 246135878b55SSascha Wildner if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) 246235878b55SSascha Wildner tsleep((caddr_t)hpt_worker_thread, 0, "hptrdy", 2*hz); 246335878b55SSascha Wildner #endif 246435878b55SSascha Wildner */ 246535878b55SSascha Wildner kproc_suspend_loop(); 246635878b55SSascha Wildner tsleep((caddr_t)hpt_worker_thread, 0, "hptrdy", 2*hz); /* wait for something to do */ 246735878b55SSascha Wildner } 246835878b55SSascha Wildner } 246935878b55SSascha Wildner 247035878b55SSascha Wildner static struct kproc_desc hpt_kp = { 247135878b55SSascha Wildner "hpt_wt", 247235878b55SSascha Wildner hpt_worker_thread, 247335878b55SSascha Wildner &hptdaemonproc 247435878b55SSascha Wildner }; 247535878b55SSascha Wildner 247635878b55SSascha Wildner /*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/ 247735878b55SSascha Wildner static void 247835878b55SSascha Wildner launch_worker_thread(void) 247935878b55SSascha Wildner { 248035878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 248135878b55SSascha Wildner 248235878b55SSascha Wildner kproc_start(&hpt_kp); 248335878b55SSascha Wildner 248435878b55SSascha Wildner for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 248535878b55SSascha Wildner 248635878b55SSascha Wildner _VBUS_INST(&pAdapTemp->VBus) 248735878b55SSascha Wildner int i; 248835878b55SSascha Wildner PVDevice pVDev; 248935878b55SSascha Wildner 249035878b55SSascha Wildner for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 249135878b55SSascha Wildner if ((pVDev=ArrayTables(i))->u.array.dArStamp==0) 249235878b55SSascha Wildner continue; 249335878b55SSascha Wildner else{ 249435878b55SSascha Wildner if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding) 249535878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev, 249635878b55SSascha Wildner (UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 249735878b55SSascha Wildner } 249835878b55SSascha Wildner } 249935878b55SSascha Wildner } 250035878b55SSascha Wildner /* 250135878b55SSascha Wildner *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL); 250235878b55SSascha Wildner */ 250335878b55SSascha Wildner 250435878b55SSascha Wildner #endif 250535878b55SSascha Wildner 250635878b55SSascha Wildner /********************************************************************************/ 250735878b55SSascha Wildner 250835878b55SSascha Wildner int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) 250935878b55SSascha Wildner { 251035878b55SSascha Wildner union ccb *ccb = (union ccb *)pCmd->pOrgCommand; 251135878b55SSascha Wildner bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 251235878b55SSascha Wildner int idx; 251335878b55SSascha Wildner 251435878b55SSascha Wildner if(logical) { 251535878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_DATA_PHYS) 251635878b55SSascha Wildner panic("physical address unsupported"); 251735878b55SSascha Wildner 251835878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 251935878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 252035878b55SSascha Wildner panic("physical address unsupported"); 252135878b55SSascha Wildner 252235878b55SSascha Wildner for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 252335878b55SSascha Wildner pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 252435878b55SSascha Wildner pSg[idx].wSgSize = sgList[idx].ds_len; 252535878b55SSascha Wildner pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0; 252635878b55SSascha Wildner } 252735878b55SSascha Wildner } 252835878b55SSascha Wildner else { 252935878b55SSascha Wildner pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; 253035878b55SSascha Wildner pSg->wSgSize = ccb->csio.dxfer_len; 253135878b55SSascha Wildner pSg->wSgFlag = SG_FLAG_EOT; 253235878b55SSascha Wildner } 253335878b55SSascha Wildner return TRUE; 253435878b55SSascha Wildner } 253535878b55SSascha Wildner 253635878b55SSascha Wildner /* since we have provided physical sg, nobody will ask us to build physical sg */ 253735878b55SSascha Wildner HPT_ASSERT(0); 253835878b55SSascha Wildner return FALSE; 253935878b55SSascha Wildner } 254035878b55SSascha Wildner 254135878b55SSascha Wildner /*******************************************************************************/ 254235878b55SSascha Wildner ULONG HPTLIBAPI 254335878b55SSascha Wildner GetStamp(void) 254435878b55SSascha Wildner { 254535878b55SSascha Wildner /* 254635878b55SSascha Wildner * the system variable, ticks, can't be used since it hasn't yet been active 254735878b55SSascha Wildner * when our driver starts (ticks==0, it's a invalid stamp value) 254835878b55SSascha Wildner */ 254935878b55SSascha Wildner ULONG stamp; 255035878b55SSascha Wildner do { stamp = krandom(); } while (stamp==0); 255135878b55SSascha Wildner return stamp; 255235878b55SSascha Wildner } 255335878b55SSascha Wildner 255435878b55SSascha Wildner 255535878b55SSascha Wildner static void 255635878b55SSascha Wildner SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) 255735878b55SSascha Wildner { 255835878b55SSascha Wildner int i; 255935878b55SSascha Wildner IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; 256035878b55SSascha Wildner 256135878b55SSascha Wildner inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/ 256235878b55SSascha Wildner inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5); 256335878b55SSascha Wildner #ifndef SERIAL_CMDS 256435878b55SSascha Wildner inquiryData->CommandQueue = 1; 256535878b55SSascha Wildner #endif 256635878b55SSascha Wildner 256735878b55SSascha Wildner switch(pVDev->VDeviceType) { 256835878b55SSascha Wildner case VD_SINGLE_DISK: 256935878b55SSascha Wildner case VD_ATAPI: 257035878b55SSascha Wildner case VD_REMOVABLE: 257135878b55SSascha Wildner /* Set the removable bit, if applicable. */ 257235878b55SSascha Wildner if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80)) 257335878b55SSascha Wildner inquiryData->RemovableMedia = 1; 257435878b55SSascha Wildner 257535878b55SSascha Wildner /* Fill in vendor identification fields. */ 2576*bf0f83aeSSascha Wildner for (i = 0; i < 8; i += 2) { 257735878b55SSascha Wildner inquiryData->VendorId[i] = ((PUCHAR)pIdentify->ModelNumber)[i + 1]; 257835878b55SSascha Wildner inquiryData->VendorId[i+1] = ((PUCHAR)pIdentify->ModelNumber)[i]; 257935878b55SSascha Wildner 258035878b55SSascha Wildner } 258135878b55SSascha Wildner 258235878b55SSascha Wildner /* Initialize unused portion of product id. */ 258335878b55SSascha Wildner for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' '; 258435878b55SSascha Wildner 258535878b55SSascha Wildner /* firmware revision */ 258635878b55SSascha Wildner for (i = 0; i < 4; i += 2) 258735878b55SSascha Wildner { 258835878b55SSascha Wildner inquiryData->ProductRevisionLevel[i] = ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; 258935878b55SSascha Wildner inquiryData->ProductRevisionLevel[i+1] = ((PUCHAR)pIdentify->FirmwareRevision)[i]; 259035878b55SSascha Wildner } 259135878b55SSascha Wildner break; 259235878b55SSascha Wildner default: 259335878b55SSascha Wildner memcpy(&inquiryData->VendorId, "RR18xx ", 8); 259435878b55SSascha Wildner #ifdef SUPPORT_ARRAY 259535878b55SSascha Wildner switch(pVDev->VDeviceType){ 259635878b55SSascha Wildner case VD_RAID_0: 259735878b55SSascha Wildner if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 259835878b55SSascha Wildner (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 259935878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 1/0 Array ", 16); 260035878b55SSascha Wildner else 260135878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 0 Array ", 16); 260235878b55SSascha Wildner break; 260335878b55SSascha Wildner case VD_RAID_1: 260435878b55SSascha Wildner if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 260535878b55SSascha Wildner (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 260635878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 0/1 Array ", 16); 260735878b55SSascha Wildner else 260835878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 1 Array ", 16); 260935878b55SSascha Wildner break; 261035878b55SSascha Wildner case VD_RAID_5: 261135878b55SSascha Wildner memcpy(&inquiryData->ProductId, "RAID 5 Array ", 16); 261235878b55SSascha Wildner break; 261335878b55SSascha Wildner case VD_JBOD: 261435878b55SSascha Wildner memcpy(&inquiryData->ProductId, "JBOD Array ", 16); 261535878b55SSascha Wildner break; 261635878b55SSascha Wildner } 261735878b55SSascha Wildner #endif 261835878b55SSascha Wildner memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4); 261935878b55SSascha Wildner break; 262035878b55SSascha Wildner } 262135878b55SSascha Wildner } 262235878b55SSascha Wildner 262335878b55SSascha Wildner static void 262435878b55SSascha Wildner hpt_timeout(void *arg) 262535878b55SSascha Wildner { 262635878b55SSascha Wildner _VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus) 2627c898d682SSascha Wildner lock_driver(); 262835878b55SSascha Wildner fResetVBus(_VBUS_P0); 2629c898d682SSascha Wildner unlock_driver(); 263035878b55SSascha Wildner } 263135878b55SSascha Wildner 263235878b55SSascha Wildner static void 263335878b55SSascha Wildner hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 263435878b55SSascha Wildner { 263535878b55SSascha Wildner PCommand pCmd = (PCommand)arg; 263635878b55SSascha Wildner union ccb *ccb = pCmd->pOrgCommand; 263735878b55SSascha Wildner struct ccb_hdr *ccb_h = &ccb->ccb_h; 263835878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter; 263935878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 264035878b55SSascha Wildner PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 264135878b55SSascha Wildner FPSCAT_GATH psg = pCmd->pSgTable; 264235878b55SSascha Wildner int idx; 264335878b55SSascha Wildner _VBUS_INST(pVDev->pVBus) 264435878b55SSascha Wildner 264535878b55SSascha Wildner HPT_ASSERT(pCmd->cf_physical_sg); 264635878b55SSascha Wildner 264735878b55SSascha Wildner if (error || nsegs == 0) 264835878b55SSascha Wildner panic("busdma error"); 264935878b55SSascha Wildner 265035878b55SSascha Wildner HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); 265135878b55SSascha Wildner 265235878b55SSascha Wildner for (idx = 0; idx < nsegs; idx++, psg++) { 265335878b55SSascha Wildner psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; 265435878b55SSascha Wildner psg->wSgSize = segs[idx].ds_len; 265535878b55SSascha Wildner psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; 265635878b55SSascha Wildner /* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ 265735878b55SSascha Wildner } 265835878b55SSascha Wildner /* psg[-1].wSgFlag = SG_FLAG_EOT; */ 265935878b55SSascha Wildner 266035878b55SSascha Wildner if (pCmd->cf_data_in) { 266135878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD); 266235878b55SSascha Wildner } 266335878b55SSascha Wildner else if (pCmd->cf_data_out) { 266435878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE); 266535878b55SSascha Wildner } 266635878b55SSascha Wildner 266735878b55SSascha Wildner callout_reset(&ccb->ccb_h.timeout_ch, 20*hz, hpt_timeout, ccb); 266835878b55SSascha Wildner pVDev->pfnSendCommand(_VBUS_P pCmd); 266935878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 267035878b55SSascha Wildner } 267135878b55SSascha Wildner 267235878b55SSascha Wildner 267335878b55SSascha Wildner 267435878b55SSascha Wildner static void HPTLIBAPI 267535878b55SSascha Wildner OsSendCommand(_VBUS_ARG union ccb *ccb) 267635878b55SSascha Wildner { 267735878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 267835878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 267935878b55SSascha Wildner struct ccb_hdr *ccb_h = &ccb->ccb_h; 268035878b55SSascha Wildner struct ccb_scsiio *csio = &ccb->csio; 268135878b55SSascha Wildner PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 268235878b55SSascha Wildner 268335878b55SSascha Wildner KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", 268435878b55SSascha Wildner ccb, 268535878b55SSascha Wildner *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0], 268635878b55SSascha Wildner *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4], 268735878b55SSascha Wildner *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8] 268835878b55SSascha Wildner )); 268935878b55SSascha Wildner 269035878b55SSascha Wildner pAdapter->outstandingCommands++; 269135878b55SSascha Wildner 269235878b55SSascha Wildner if (pVDev == NULL || pVDev->vf_online == 0) { 269335878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 269435878b55SSascha Wildner ccb_done(ccb); 269535878b55SSascha Wildner goto Command_Complished; 269635878b55SSascha Wildner } 269735878b55SSascha Wildner 269835878b55SSascha Wildner switch(ccb->csio.cdb_io.cdb_bytes[0]) 269935878b55SSascha Wildner { 270035878b55SSascha Wildner case TEST_UNIT_READY: 270135878b55SSascha Wildner case START_STOP_UNIT: 270235878b55SSascha Wildner case SYNCHRONIZE_CACHE: 270335878b55SSascha Wildner /* FALLTHROUGH */ 270435878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP; 270535878b55SSascha Wildner break; 270635878b55SSascha Wildner 270735878b55SSascha Wildner case INQUIRY: 270835878b55SSascha Wildner ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); 270935878b55SSascha Wildner SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); 271035878b55SSascha Wildner ccb_h->status = CAM_REQ_CMP; 271135878b55SSascha Wildner break; 271235878b55SSascha Wildner 271335878b55SSascha Wildner case READ_CAPACITY: 271435878b55SSascha Wildner { 271535878b55SSascha Wildner UCHAR *rbuf=csio->data_ptr; 271635878b55SSascha Wildner unsigned int cap; 271735878b55SSascha Wildner 271835878b55SSascha Wildner if (pVDev->VDeviceCapacity > 0xfffffffful) { 271935878b55SSascha Wildner cap = 0xfffffffful; 272035878b55SSascha Wildner } else { 272135878b55SSascha Wildner cap = pVDev->VDeviceCapacity - 1; 272235878b55SSascha Wildner } 272335878b55SSascha Wildner 272435878b55SSascha Wildner rbuf[0] = (UCHAR)(cap>>24); 272535878b55SSascha Wildner rbuf[1] = (UCHAR)(cap>>16); 272635878b55SSascha Wildner rbuf[2] = (UCHAR)(cap>>8); 272735878b55SSascha Wildner rbuf[3] = (UCHAR)cap; 272835878b55SSascha Wildner /* Claim 512 byte blocks (big-endian). */ 272935878b55SSascha Wildner rbuf[4] = 0; 273035878b55SSascha Wildner rbuf[5] = 0; 273135878b55SSascha Wildner rbuf[6] = 2; 273235878b55SSascha Wildner rbuf[7] = 0; 273335878b55SSascha Wildner 273435878b55SSascha Wildner ccb_h->status = CAM_REQ_CMP; 273535878b55SSascha Wildner break; 273635878b55SSascha Wildner } 273735878b55SSascha Wildner 273835878b55SSascha Wildner case 0x9e: /*SERVICE_ACTION_IN*/ 273935878b55SSascha Wildner { 274035878b55SSascha Wildner UCHAR *rbuf = csio->data_ptr; 274135878b55SSascha Wildner LBA_T cap = pVDev->VDeviceCapacity - 1; 274235878b55SSascha Wildner 274335878b55SSascha Wildner rbuf[0] = (UCHAR)(cap>>56); 274435878b55SSascha Wildner rbuf[1] = (UCHAR)(cap>>48); 274535878b55SSascha Wildner rbuf[2] = (UCHAR)(cap>>40); 274635878b55SSascha Wildner rbuf[3] = (UCHAR)(cap>>32); 274735878b55SSascha Wildner rbuf[4] = (UCHAR)(cap>>24); 274835878b55SSascha Wildner rbuf[5] = (UCHAR)(cap>>16); 274935878b55SSascha Wildner rbuf[6] = (UCHAR)(cap>>8); 275035878b55SSascha Wildner rbuf[7] = (UCHAR)cap; 275135878b55SSascha Wildner rbuf[8] = 0; 275235878b55SSascha Wildner rbuf[9] = 0; 275335878b55SSascha Wildner rbuf[10] = 2; 275435878b55SSascha Wildner rbuf[11] = 0; 275535878b55SSascha Wildner 275635878b55SSascha Wildner ccb_h->status = CAM_REQ_CMP; 275735878b55SSascha Wildner break; 275835878b55SSascha Wildner } 275935878b55SSascha Wildner 276035878b55SSascha Wildner case READ_6: 276135878b55SSascha Wildner case WRITE_6: 276235878b55SSascha Wildner case READ_10: 276335878b55SSascha Wildner case WRITE_10: 276435878b55SSascha Wildner case 0x88: /* READ_16 */ 276535878b55SSascha Wildner case 0x8a: /* WRITE_16 */ 276635878b55SSascha Wildner case 0x13: 276735878b55SSascha Wildner case 0x2f: 276835878b55SSascha Wildner { 276935878b55SSascha Wildner UCHAR Cdb[16]; 277035878b55SSascha Wildner UCHAR CdbLength; 277135878b55SSascha Wildner _VBUS_INST(pVDev->pVBus) 277235878b55SSascha Wildner PCommand pCmd = AllocateCommand(_VBUS_P0); 277335878b55SSascha Wildner HPT_ASSERT(pCmd); 277435878b55SSascha Wildner 277535878b55SSascha Wildner CdbLength = csio->cdb_len; 277635878b55SSascha Wildner if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) 277735878b55SSascha Wildner { 277835878b55SSascha Wildner if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) 277935878b55SSascha Wildner { 278035878b55SSascha Wildner bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); 278135878b55SSascha Wildner } 278235878b55SSascha Wildner else 278335878b55SSascha Wildner { 278435878b55SSascha Wildner KdPrintE(("ERROR!!!\n")); 278535878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 278635878b55SSascha Wildner break; 278735878b55SSascha Wildner } 278835878b55SSascha Wildner } 278935878b55SSascha Wildner else 279035878b55SSascha Wildner { 279135878b55SSascha Wildner bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); 279235878b55SSascha Wildner } 279335878b55SSascha Wildner 279435878b55SSascha Wildner pCmd->pOrgCommand = ccb; 279535878b55SSascha Wildner pCmd->pVDevice = pVDev; 279635878b55SSascha Wildner pCmd->pfnCompletion = fOsCommandDone; 279735878b55SSascha Wildner pCmd->pfnBuildSgl = fOsBuildSgl; 279835878b55SSascha Wildner pCmd->pSgTable = pmap->psg; 279935878b55SSascha Wildner 280035878b55SSascha Wildner switch (Cdb[0]) 280135878b55SSascha Wildner { 280235878b55SSascha Wildner case READ_6: 280335878b55SSascha Wildner case WRITE_6: 280435878b55SSascha Wildner case 0x13: 280535878b55SSascha Wildner pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; 280635878b55SSascha Wildner pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; 280735878b55SSascha Wildner break; 280835878b55SSascha Wildner 280935878b55SSascha Wildner case 0x88: /* READ_16 */ 281035878b55SSascha Wildner case 0x8a: /* WRITE_16 */ 281135878b55SSascha Wildner pCmd->uCmd.Ide.Lba = 281235878b55SSascha Wildner (HPT_U64)Cdb[2] << 56 | 281335878b55SSascha Wildner (HPT_U64)Cdb[3] << 48 | 281435878b55SSascha Wildner (HPT_U64)Cdb[4] << 40 | 281535878b55SSascha Wildner (HPT_U64)Cdb[5] << 32 | 281635878b55SSascha Wildner (HPT_U64)Cdb[6] << 24 | 281735878b55SSascha Wildner (HPT_U64)Cdb[7] << 16 | 281835878b55SSascha Wildner (HPT_U64)Cdb[8] << 8 | 281935878b55SSascha Wildner (HPT_U64)Cdb[9]; 282035878b55SSascha Wildner pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13]; 282135878b55SSascha Wildner break; 282235878b55SSascha Wildner 282335878b55SSascha Wildner default: 282435878b55SSascha Wildner pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24); 282535878b55SSascha Wildner pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8); 282635878b55SSascha Wildner break; 282735878b55SSascha Wildner } 282835878b55SSascha Wildner 282935878b55SSascha Wildner switch (Cdb[0]) 283035878b55SSascha Wildner { 283135878b55SSascha Wildner case READ_6: 283235878b55SSascha Wildner case READ_10: 283335878b55SSascha Wildner case 0x88: /* READ_16 */ 283435878b55SSascha Wildner pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; 283535878b55SSascha Wildner pCmd->cf_data_in = 1; 283635878b55SSascha Wildner break; 283735878b55SSascha Wildner 283835878b55SSascha Wildner case WRITE_6: 283935878b55SSascha Wildner case WRITE_10: 284035878b55SSascha Wildner case 0x8a: /* WRITE_16 */ 284135878b55SSascha Wildner pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; 284235878b55SSascha Wildner pCmd->cf_data_out = 1; 284335878b55SSascha Wildner break; 284435878b55SSascha Wildner case 0x13: 284535878b55SSascha Wildner case 0x2f: 284635878b55SSascha Wildner pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; 284735878b55SSascha Wildner break; 284835878b55SSascha Wildner } 284935878b55SSascha Wildner /*///////////////////////// */ 285035878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 285135878b55SSascha Wildner int idx; 285235878b55SSascha Wildner bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 285335878b55SSascha Wildner 285435878b55SSascha Wildner if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 285535878b55SSascha Wildner pCmd->cf_physical_sg = 1; 285635878b55SSascha Wildner 285735878b55SSascha Wildner for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 285835878b55SSascha Wildner pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 285935878b55SSascha Wildner pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len; 286035878b55SSascha Wildner pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0; 286135878b55SSascha Wildner } 286235878b55SSascha Wildner 286335878b55SSascha Wildner callout_reset(&ccb->ccb_h.timeout_ch, 20*hz, hpt_timeout, ccb); 286435878b55SSascha Wildner pVDev->pfnSendCommand(_VBUS_P pCmd); 286535878b55SSascha Wildner } 286635878b55SSascha Wildner else { 286735878b55SSascha Wildner int error; 286835878b55SSascha Wildner pCmd->cf_physical_sg = 1; 286935878b55SSascha Wildner error = bus_dmamap_load(pAdapter->io_dma_parent, 287035878b55SSascha Wildner pmap->dma_map, 287135878b55SSascha Wildner ccb->csio.data_ptr, ccb->csio.dxfer_len, 287235878b55SSascha Wildner hpt_io_dmamap_callback, pCmd, 287335878b55SSascha Wildner BUS_DMA_WAITOK 287435878b55SSascha Wildner ); 287535878b55SSascha Wildner KdPrint(("bus_dmamap_load return %d\n", error)); 287635878b55SSascha Wildner if (error && error!=EINPROGRESS) { 287735878b55SSascha Wildner hpt_printk(("bus_dmamap_load error %d\n", error)); 287835878b55SSascha Wildner FreeCommand(_VBUS_P pCmd); 287935878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP_ERR; 288035878b55SSascha Wildner dmamap_put(pmap); 288135878b55SSascha Wildner pAdapter->outstandingCommands--; 288235878b55SSascha Wildner xpt_done(ccb); 288335878b55SSascha Wildner } 288435878b55SSascha Wildner } 288535878b55SSascha Wildner goto Command_Complished; 288635878b55SSascha Wildner } 288735878b55SSascha Wildner 288835878b55SSascha Wildner default: 288935878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 289035878b55SSascha Wildner break; 289135878b55SSascha Wildner } 289235878b55SSascha Wildner ccb_done(ccb); 289335878b55SSascha Wildner Command_Complished: 289435878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 289535878b55SSascha Wildner return; 289635878b55SSascha Wildner } 289735878b55SSascha Wildner 289835878b55SSascha Wildner static void HPTLIBAPI 289935878b55SSascha Wildner fOsCommandDone(_VBUS_ARG PCommand pCmd) 290035878b55SSascha Wildner { 290135878b55SSascha Wildner union ccb *ccb = pCmd->pOrgCommand; 290235878b55SSascha Wildner PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 290335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 290435878b55SSascha Wildner 290535878b55SSascha Wildner KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result)); 290635878b55SSascha Wildner 290735878b55SSascha Wildner callout_stop(&ccb->ccb_h.timeout_ch); 290835878b55SSascha Wildner 290935878b55SSascha Wildner switch(pCmd->Result) { 291035878b55SSascha Wildner case RETURN_SUCCESS: 291135878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_CMP; 291235878b55SSascha Wildner break; 291335878b55SSascha Wildner case RETURN_BAD_DEVICE: 291435878b55SSascha Wildner ccb->ccb_h.status = CAM_DEV_NOT_THERE; 291535878b55SSascha Wildner break; 291635878b55SSascha Wildner case RETURN_DEVICE_BUSY: 291735878b55SSascha Wildner ccb->ccb_h.status = CAM_BUSY; 291835878b55SSascha Wildner break; 291935878b55SSascha Wildner case RETURN_INVALID_REQUEST: 292035878b55SSascha Wildner ccb->ccb_h.status = CAM_REQ_INVALID; 292135878b55SSascha Wildner break; 292235878b55SSascha Wildner case RETURN_SELECTION_TIMEOUT: 292335878b55SSascha Wildner ccb->ccb_h.status = CAM_SEL_TIMEOUT; 292435878b55SSascha Wildner break; 292535878b55SSascha Wildner case RETURN_RETRY: 292635878b55SSascha Wildner ccb->ccb_h.status = CAM_BUSY; 292735878b55SSascha Wildner break; 292835878b55SSascha Wildner default: 292935878b55SSascha Wildner ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 293035878b55SSascha Wildner break; 293135878b55SSascha Wildner } 293235878b55SSascha Wildner 293335878b55SSascha Wildner if (pCmd->cf_data_in) { 293435878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD); 293535878b55SSascha Wildner } 2936814ffc96SSascha Wildner else if (pCmd->cf_data_out) { 293735878b55SSascha Wildner bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE); 293835878b55SSascha Wildner } 293935878b55SSascha Wildner 294035878b55SSascha Wildner bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map); 294135878b55SSascha Wildner 294235878b55SSascha Wildner FreeCommand(_VBUS_P pCmd); 294335878b55SSascha Wildner ccb_done(ccb); 294435878b55SSascha Wildner } 294535878b55SSascha Wildner 294635878b55SSascha Wildner int 294735878b55SSascha Wildner hpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags) 294835878b55SSascha Wildner { 294935878b55SSascha Wildner int p; 295035878b55SSascha Wildner 295135878b55SSascha Wildner p = (DpcQueue_Last + 1) % MAX_DPC; 295235878b55SSascha Wildner if (p==DpcQueue_First) { 295335878b55SSascha Wildner KdPrint(("DPC Queue full!\n")); 295435878b55SSascha Wildner return -1; 295535878b55SSascha Wildner } 295635878b55SSascha Wildner 295735878b55SSascha Wildner DpcQueue[DpcQueue_Last].dpc = dpc; 295835878b55SSascha Wildner DpcQueue[DpcQueue_Last].pAdapter = pAdapter; 295935878b55SSascha Wildner DpcQueue[DpcQueue_Last].arg = arg; 296035878b55SSascha Wildner DpcQueue[DpcQueue_Last].flags = flags; 296135878b55SSascha Wildner DpcQueue_Last = p; 296235878b55SSascha Wildner 296335878b55SSascha Wildner return 0; 296435878b55SSascha Wildner } 296535878b55SSascha Wildner 296635878b55SSascha Wildner #ifdef _RAID5N_ 296735878b55SSascha Wildner /* 296835878b55SSascha Wildner * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices. 296935878b55SSascha Wildner * How about the memory for 5081 request/response array and PRD table? 297035878b55SSascha Wildner */ 297135878b55SSascha Wildner void 297235878b55SSascha Wildner *os_alloc_page(_VBUS_ARG0) 297335878b55SSascha Wildner { 297435878b55SSascha Wildner return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 297535878b55SSascha Wildner } 297635878b55SSascha Wildner 297735878b55SSascha Wildner void 297835878b55SSascha Wildner *os_alloc_dma_page(_VBUS_ARG0) 297935878b55SSascha Wildner { 298035878b55SSascha Wildner return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 298135878b55SSascha Wildner } 298235878b55SSascha Wildner 298335878b55SSascha Wildner void 298435878b55SSascha Wildner os_free_page(_VBUS_ARG void *p) 298535878b55SSascha Wildner { 298635878b55SSascha Wildner contigfree(p, 0x1000, M_DEVBUF); 298735878b55SSascha Wildner } 298835878b55SSascha Wildner 298935878b55SSascha Wildner void 299035878b55SSascha Wildner os_free_dma_page(_VBUS_ARG void *p) 299135878b55SSascha Wildner { 299235878b55SSascha Wildner contigfree(p, 0x1000, M_DEVBUF); 299335878b55SSascha Wildner } 299435878b55SSascha Wildner 299535878b55SSascha Wildner void 299635878b55SSascha Wildner DoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes) 299735878b55SSascha Wildner { 299835878b55SSascha Wildner UINT i; 299935878b55SSascha Wildner for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++; 300035878b55SSascha Wildner } 300135878b55SSascha Wildner 300235878b55SSascha Wildner void 300335878b55SSascha Wildner DoXor2(ULONG *p0, ULONG *p2, UINT nBytes) 300435878b55SSascha Wildner { 300535878b55SSascha Wildner UINT i; 300635878b55SSascha Wildner for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++; 300735878b55SSascha Wildner } 300835878b55SSascha Wildner #endif 3009