1d2bd3ab9SScott Long /* 2d2bd3ab9SScott Long * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 31713e81bSScott Long * All rights reserved. 41713e81bSScott Long * 51713e81bSScott Long * Redistribution and use in source and binary forms, with or without 61713e81bSScott Long * modification, are permitted provided that the following conditions 71713e81bSScott Long * are met: 81713e81bSScott Long * 1. Redistributions of source code must retain the above copyright 91713e81bSScott Long * notice, this list of conditions and the following disclaimer. 101713e81bSScott Long * 2. Redistributions in binary form must reproduce the above copyright 111713e81bSScott Long * notice, this list of conditions and the following disclaimer in the 121713e81bSScott Long * documentation and/or other materials provided with the distribution. 131713e81bSScott Long * 141713e81bSScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151713e81bSScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161713e81bSScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171713e81bSScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181713e81bSScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191713e81bSScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201713e81bSScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211713e81bSScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221713e81bSScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231713e81bSScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241713e81bSScott Long * SUCH DAMAGE. 251713e81bSScott Long * 261713e81bSScott Long * $FreeBSD$ 271713e81bSScott Long */ 28d2bd3ab9SScott Long 291713e81bSScott Long #include <sys/param.h> 301713e81bSScott Long #include <sys/systm.h> 311713e81bSScott Long #include <sys/kernel.h> 321713e81bSScott Long #include <sys/bus.h> 331713e81bSScott Long #include <sys/malloc.h> 341713e81bSScott Long #include <sys/resource.h> 351713e81bSScott Long #include <sys/time.h> 361713e81bSScott Long #include <sys/callout.h> 371713e81bSScott Long #include <sys/signalvar.h> 381713e81bSScott Long #include <sys/eventhandler.h> 391713e81bSScott Long #include <sys/proc.h> 401713e81bSScott Long #include <sys/kthread.h> 411713e81bSScott Long 42d2bd3ab9SScott Long #if (__FreeBSD_version >= 500000) 43d2bd3ab9SScott Long #include <sys/mutex.h> 44d2bd3ab9SScott Long #include <sys/module.h> 45d2bd3ab9SScott Long #endif 46d2bd3ab9SScott Long 47d2bd3ab9SScott Long #if (__FreeBSD_version >= 500000) 481713e81bSScott Long #include <dev/pci/pcireg.h> 491713e81bSScott Long #include <dev/pci/pcivar.h> 50d2bd3ab9SScott Long #else 51d2bd3ab9SScott Long #include <pci/pcireg.h> 52d2bd3ab9SScott Long #include <pci/pcivar.h> 53d2bd3ab9SScott Long #include <sys/wait.h> 54d2bd3ab9SScott Long #include <sys/sysproto.h> 55d2bd3ab9SScott Long #endif 56d2bd3ab9SScott Long 57d2bd3ab9SScott Long #ifndef __KERNEL__ 58d2bd3ab9SScott Long #define __KERNEL__ 59d2bd3ab9SScott Long #endif 601713e81bSScott Long 611713e81bSScott Long #include <dev/hptmv/global.h> 621713e81bSScott Long #include <dev/hptmv/hptintf.h> 631713e81bSScott Long #include <dev/hptmv/osbsd.h> 64f7f3900bSScott Long #include <dev/hptmv/access601.h> 651713e81bSScott Long 66d2bd3ab9SScott Long 671713e81bSScott Long #ifdef DEBUG 681713e81bSScott Long #ifdef DEBUG_LEVEL 691713e81bSScott Long int hpt_dbg_level = DEBUG_LEVEL; 701713e81bSScott Long #else 711713e81bSScott Long int hpt_dbg_level = 0; 721713e81bSScott Long #endif 731713e81bSScott Long #endif 741713e81bSScott Long 751713e81bSScott Long #define MV_ERROR printf 76d2bd3ab9SScott Long 771713e81bSScott Long /* 781713e81bSScott Long * CAM SIM entry points 791713e81bSScott Long */ 801713e81bSScott Long static int hpt_probe (device_t dev); 81d2bd3ab9SScott Long static void launch_worker_thread(void); 821713e81bSScott Long static int hpt_attach(device_t dev); 831713e81bSScott Long static int hpt_detach(device_t dev); 841713e81bSScott Long static int hpt_shutdown(device_t dev); 851713e81bSScott Long static void hpt_poll(struct cam_sim *sim); 861713e81bSScott Long static void hpt_intr(void *arg); 87d2bd3ab9SScott Long static void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); 881713e81bSScott Long static void hpt_action(struct cam_sim *sim, union ccb *ccb); 89d2bd3ab9SScott Long 90d2bd3ab9SScott Long static device_method_t driver_methods[] = { 91d2bd3ab9SScott Long /* Device interface */ 92d2bd3ab9SScott Long DEVMETHOD(device_probe, hpt_probe), 93d2bd3ab9SScott Long DEVMETHOD(device_attach, hpt_attach), 94d2bd3ab9SScott Long DEVMETHOD(device_detach, hpt_detach), 95d2bd3ab9SScott Long 96d2bd3ab9SScott Long /* DEVMETHOD(device_shutdown, hpt_shutdown), */ 97d2bd3ab9SScott Long { 0, 0 } 98d2bd3ab9SScott Long }; 99d2bd3ab9SScott Long 100d2bd3ab9SScott Long static driver_t hpt_pci_driver = { 101d2bd3ab9SScott Long __str(PROC_DIR_NAME), 102d2bd3ab9SScott Long driver_methods, 103d2bd3ab9SScott Long sizeof(IAL_ADAPTER_T) 104d2bd3ab9SScott Long }; 105d2bd3ab9SScott Long 106d2bd3ab9SScott Long static devclass_t hpt_devclass; 107d2bd3ab9SScott Long 108d2bd3ab9SScott Long #define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 109d2bd3ab9SScott Long __DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 110d2bd3ab9SScott Long 111d2bd3ab9SScott Long #define ccb_ccb_ptr spriv_ptr0 112d2bd3ab9SScott Long #define ccb_adapter ccb_h.spriv_ptr1 113d2bd3ab9SScott Long 1141713e81bSScott Long static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); 1151713e81bSScott Long static void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); 1161713e81bSScott Long static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); 1171713e81bSScott Long static void ccb_done(union ccb *ccb); 1181713e81bSScott Long static void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); 1191713e81bSScott Long static void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); 1201713e81bSScott Long static void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter); 1211713e81bSScott Long static void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 1221713e81bSScott Long static void handleEdmaError(_VBUS_ARG PCommand pCmd); 1231713e81bSScott Long static int hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 1241713e81bSScott Long static int fResetActiveCommands(PVBus _vbus_p); 1251713e81bSScott Long static void fRegisterVdevice(IAL_ADAPTER_T *pAdapter); 1261713e81bSScott Long static int hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter); 1271713e81bSScott Long static void hptmv_handle_event_disconnect(void *data); 1281713e81bSScott Long static void hptmv_handle_event_connect(void *data); 1291713e81bSScott Long static int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); 1301713e81bSScott Long static void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel); 1311713e81bSScott Long static int hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel); 1321713e81bSScott Long static int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, 1331713e81bSScott Long int logical); 1341713e81bSScott Long static MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 1351713e81bSScott Long MV_U8 channelNum, MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId, 1361713e81bSScott Long MV_U16 responseFlags, MV_U32 timeStamp, 1371713e81bSScott Long MV_STORAGE_DEVICE_REGISTERS *registerStruct); 1381713e81bSScott Long static MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, 1391713e81bSScott Long MV_EVENT_TYPE eventType, MV_U32 param1, MV_U32 param2); 1401713e81bSScott Long 1411713e81bSScott Long #define ccb_ccb_ptr spriv_ptr0 1421713e81bSScott Long #define ccb_adapter ccb_h.spriv_ptr1 1431713e81bSScott Long 1441713e81bSScott Long IAL_ADAPTER_T *gIal_Adapter = 0; 1451713e81bSScott Long IAL_ADAPTER_T *pCurAdapter = 0; 146d2bd3ab9SScott Long static MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; 1471713e81bSScott Long 1481713e81bSScott Long typedef struct st_HPT_DPC { 1491713e81bSScott Long IAL_ADAPTER_T *pAdapter; 1501713e81bSScott Long void (*dpc)(IAL_ADAPTER_T *, void *, UCHAR); 1511713e81bSScott Long void *arg; 1521713e81bSScott Long UCHAR flags; 1531713e81bSScott Long } ST_HPT_DPC; 1541713e81bSScott Long 1551713e81bSScott Long #define MAX_DPC 16 1561713e81bSScott Long UCHAR DPC_Request_Nums = 0; 1571713e81bSScott Long static ST_HPT_DPC DpcQueue[MAX_DPC]; 1581713e81bSScott Long static int DpcQueue_First=0; 1591713e81bSScott Long static int DpcQueue_Last = 0; 1601713e81bSScott Long 161b49a9e5bSJens Schweikhardt char DRIVER_VERSION[] = "v1.12"; 1621713e81bSScott Long 163d2bd3ab9SScott Long #if (__FreeBSD_version >= 500000) 164d2bd3ab9SScott Long static struct mtx driver_lock; 165d2bd3ab9SScott Long intrmask_t lock_driver() 166d2bd3ab9SScott Long { 1671713e81bSScott Long 168d2bd3ab9SScott Long intrmask_t spl = 0; 1694ed23cf2SJohn Baldwin mtx_lock(&driver_lock); 170d2bd3ab9SScott Long return spl; 171d2bd3ab9SScott Long } 172d2bd3ab9SScott Long void unlock_driver(intrmask_t spl) 173d2bd3ab9SScott Long { 1744ed23cf2SJohn Baldwin mtx_unlock(&driver_lock); 175d2bd3ab9SScott Long } 176d2bd3ab9SScott Long #else 177d2bd3ab9SScott Long static int driver_locked = 0; 178d2bd3ab9SScott Long intrmask_t lock_driver() 1791713e81bSScott Long { 1801713e81bSScott Long intrmask_t spl = splcam(); 181d2bd3ab9SScott Long loop: 182d2bd3ab9SScott Long while (driver_locked) 183d2bd3ab9SScott Long tsleep(&driver_locked, PRIBIO, "hptlck", hz); 184d2bd3ab9SScott Long atomic_add_int(&driver_locked, 1); 185d2bd3ab9SScott Long if (driver_locked>1) { 186d2bd3ab9SScott Long atomic_subtract_int(&driver_locked, 1); 187d2bd3ab9SScott Long goto loop; 188d2bd3ab9SScott Long } 1891713e81bSScott Long return spl; 1901713e81bSScott Long } 1911713e81bSScott Long 192d2bd3ab9SScott Long void unlock_driver(intrmask_t spl) 1931713e81bSScott Long { 194d2bd3ab9SScott Long atomic_subtract_int(&driver_locked, 1); 195d2bd3ab9SScott Long if (driver_locked==0) { 196d2bd3ab9SScott Long wakeup(&driver_locked); 197d2bd3ab9SScott Long } 1981713e81bSScott Long splx(spl); 1991713e81bSScott Long } 200d2bd3ab9SScott Long #endif 2011713e81bSScott Long 2021713e81bSScott Long /******************************************************************************* 2031713e81bSScott Long * Name: hptmv_free_channel 2041713e81bSScott Long * 2051713e81bSScott Long * Description: free allocated queues for the given channel 2061713e81bSScott Long * 2071713e81bSScott Long * Parameters: pMvSataAdapter - pointer to the RR182x controler this 2081713e81bSScott Long * channel connected to. 2091713e81bSScott Long * channelNum - channel number. 2101713e81bSScott Long * 2111713e81bSScott Long ******************************************************************************/ 2121713e81bSScott Long static void 2131713e81bSScott Long hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 2141713e81bSScott Long { 2151713e81bSScott Long HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM); 2161713e81bSScott Long pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL; 217d2bd3ab9SScott Long } 2181713e81bSScott Long 219d2bd3ab9SScott Long static void failDevice(PVDevice pVDev) 2201713e81bSScott Long { 221d2bd3ab9SScott Long PVBus _vbus_p = pVDev->pVBus; 222d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 223d2bd3ab9SScott Long 2241713e81bSScott Long pVDev->u.disk.df_on_line = 0; 2251713e81bSScott Long pVDev->vf_online = 0; 226d2bd3ab9SScott Long if (pVDev->pfnDeviceFailed) 227d2bd3ab9SScott Long CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev); 228d2bd3ab9SScott Long 229d2bd3ab9SScott Long fNotifyGUI(ET_DEVICE_REMOVED, pVDev); 230d2bd3ab9SScott Long 231d2bd3ab9SScott Long #ifndef FOR_DEMO 232d2bd3ab9SScott Long if (pAdapter->ver_601==2 && !pAdapter->beeping) { 233d2bd3ab9SScott Long pAdapter->beeping = 1; 234d2bd3ab9SScott Long BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); 235d2bd3ab9SScott Long set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1); 2361713e81bSScott Long } 237d2bd3ab9SScott Long #endif 2381713e81bSScott Long } 2391713e81bSScott Long 2401713e81bSScott Long int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel); 241d2bd3ab9SScott Long /*void fDeviceSendCommand(_VBUS_ARG PCommand pCmd); */ 2421713e81bSScott Long 2431713e81bSScott Long static void 2441713e81bSScott Long handleEdmaError(_VBUS_ARG PCommand pCmd) 2451713e81bSScott Long { 2461713e81bSScott Long PDevice pDevice = &pCmd->pVDevice->u.disk; 2471713e81bSScott Long MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter; 2481713e81bSScott Long 2491713e81bSScott Long if (!pDevice->df_on_line) { 2501713e81bSScott Long KdPrint(("Device is offline")); 2511713e81bSScott Long pCmd->Result = RETURN_BAD_DEVICE; 2521713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 2531713e81bSScott Long return; 2541713e81bSScott Long } 2551713e81bSScott Long 2561713e81bSScott Long if (pCmd->RetryCount++>5) { 257d2bd3ab9SScott Long hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber)); 258d2bd3ab9SScott Long failed: 259d2bd3ab9SScott Long failDevice(pCmd->pVDevice); 2601713e81bSScott Long pCmd->Result = RETURN_IDE_ERROR; 2611713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 2621713e81bSScott Long return; 2631713e81bSScott Long } 264d2bd3ab9SScott Long 265d2bd3ab9SScott Long /* reset the channel and retry the command */ 266d2bd3ab9SScott Long if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber)) 267d2bd3ab9SScott Long goto failed; 268d2bd3ab9SScott Long 269d2bd3ab9SScott Long fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice)); 270d2bd3ab9SScott Long 271d2bd3ab9SScott Long hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber)); 2721713e81bSScott Long fDeviceSendCommand(_VBUS_P pCmd); 2731713e81bSScott Long } 2741713e81bSScott Long 2751713e81bSScott Long /**************************************************************** 2761713e81bSScott Long * Name: hptmv_init_channel 2771713e81bSScott Long * 278d2bd3ab9SScott Long * Description: allocate request and response queues for the EDMA of the 279d2bd3ab9SScott Long * given channel and sets other fields. 280d2bd3ab9SScott Long * 2811713e81bSScott Long * Parameters: 2821713e81bSScott Long * pAdapter - pointer to the emulated adapter data structure 2831713e81bSScott Long * channelNum - channel number. 2841713e81bSScott Long * Return: 0 on success, otherwise on failure 2851713e81bSScott Long ****************************************************************/ 2861713e81bSScott Long static int 2871713e81bSScott Long hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 2881713e81bSScott Long { 2891713e81bSScott Long MV_SATA_CHANNEL *pMvSataChannel; 2901713e81bSScott Long dma_addr_t req_dma_addr; 2911713e81bSScott Long dma_addr_t rsp_dma_addr; 2921713e81bSScott Long 2931713e81bSScott Long if (channelNum >= MV_SATA_CHANNELS_NUM) 2941713e81bSScott Long { 2951713e81bSScott Long MV_ERROR("RR182x[%d]: Bad channelNum=%d", 2961713e81bSScott Long pAdapter->mvSataAdapter.adapterId, channelNum); 2971713e81bSScott Long return -1; 2981713e81bSScott Long } 2991713e81bSScott Long 300d2bd3ab9SScott Long pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; 3011713e81bSScott Long pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel; 3021713e81bSScott Long pMvSataChannel->channelNumber = channelNum; 3031713e81bSScott Long pMvSataChannel->lba48Address = MV_FALSE; 3041713e81bSScott Long pMvSataChannel->maxReadTransfer = MV_FALSE; 3051713e81bSScott Long 306d2bd3ab9SScott Long pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *) 307d2bd3ab9SScott Long (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); 308d2bd3ab9SScott Long req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); 3091713e81bSScott Long 3101713e81bSScott Long 311d2bd3ab9SScott Long KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr)); 3121713e81bSScott Long 3131713e81bSScott Long /* check the 1K alignment of the request queue*/ 3141713e81bSScott Long if (req_dma_addr & 0x3ff) 3151713e81bSScott Long { 316d2bd3ab9SScott Long MV_ERROR("RR182x[%d]: request queue allocated isn't 1 K aligned," 317d2bd3ab9SScott Long " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId, 318d2bd3ab9SScott Long (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum); 3191713e81bSScott Long return -1; 3201713e81bSScott Long } 3211713e81bSScott Long pMvSataChannel->requestQueuePciLowAddress = req_dma_addr; 3221713e81bSScott Long pMvSataChannel->requestQueuePciHiAddress = 0; 3231713e81bSScott Long KdPrint(("RR182x[%d,%d]: request queue allocated: 0x%p", 3241713e81bSScott Long pAdapter->mvSataAdapter.adapterId, channelNum, 3251713e81bSScott Long pMvSataChannel->requestQueue)); 326d2bd3ab9SScott Long pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) 327d2bd3ab9SScott Long (pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); 328d2bd3ab9SScott Long rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); 3291713e81bSScott Long 3301713e81bSScott Long /* check the 256 alignment of the response queue*/ 3311713e81bSScott Long if (rsp_dma_addr & 0xff) 3321713e81bSScott Long { 333d2bd3ab9SScott Long MV_ERROR("RR182x[%d,%d]: response queue allocated isn't 256 byte " 334d2bd3ab9SScott Long "aligned, dma_addr=%llx\n", 335d2bd3ab9SScott Long pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr); 3361713e81bSScott Long return -1; 3371713e81bSScott Long } 3381713e81bSScott Long pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr; 3391713e81bSScott Long pMvSataChannel->responseQueuePciHiAddress = 0; 3401713e81bSScott Long KdPrint(("RR182x[%d,%d]: response queue allocated: 0x%p", 3411713e81bSScott Long pAdapter->mvSataAdapter.adapterId, channelNum, 3421713e81bSScott Long pMvSataChannel->responseQueue)); 3431713e81bSScott Long 3441713e81bSScott Long pAdapter->mvChannel[channelNum].online = MV_TRUE; 3451713e81bSScott Long return 0; 3461713e81bSScott Long } 3471713e81bSScott Long 3481713e81bSScott Long /****************************************************************************** 3491713e81bSScott Long * Name: hptmv_parse_identify_results 3501713e81bSScott Long * 351d2bd3ab9SScott Long * Description: this functions parses the identify command results, checks 352d2bd3ab9SScott Long * that the connected deives can be accesed by RR182x EDMA, 353d2bd3ab9SScott Long * and updates the channel stucture accordingly. 354d2bd3ab9SScott Long * 3551713e81bSScott Long * Parameters: pMvSataChannel, pointer to the channel data structure. 3561713e81bSScott Long * 3571713e81bSScott Long * Returns: =0 ->success, < 0 ->failure. 3581713e81bSScott Long * 3591713e81bSScott Long ******************************************************************************/ 3601713e81bSScott Long static int 3611713e81bSScott Long hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) 3621713e81bSScott Long { 3631713e81bSScott Long MV_U16 *iden = pMvSataChannel->identifyDevice; 3641713e81bSScott Long 3651713e81bSScott Long /*LBA addressing*/ 366d2bd3ab9SScott Long if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) 367d2bd3ab9SScott Long { 3681713e81bSScott Long KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n")); 3691713e81bSScott Long return -1; 370d2bd3ab9SScott Long } 371d2bd3ab9SScott Long else 372d2bd3ab9SScott Long { 3731713e81bSScott Long KdPrint(("%25s - %s\n", "Capabilities", "LBA supported")); 3741713e81bSScott Long } 3751713e81bSScott Long /*DMA support*/ 376d2bd3ab9SScott Long if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) 377d2bd3ab9SScott Long { 3781713e81bSScott Long KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n")); 3791713e81bSScott Long return -1; 380d2bd3ab9SScott Long } 381d2bd3ab9SScott Long else 382d2bd3ab9SScott Long { 3831713e81bSScott Long KdPrint(("%25s - %s\n", "Capabilities", "DMA supported")); 3841713e81bSScott Long } 3851713e81bSScott Long /* PIO */ 386d2bd3ab9SScott Long if ((iden[IDEN_VALID] & 2) == 0) 387d2bd3ab9SScott Long { 388d2bd3ab9SScott Long KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n")); 3891713e81bSScott Long return -1; 3901713e81bSScott Long } 3911713e81bSScott Long KdPrint(("%25s - 0x%02x\n", "PIO modes supported", 3921713e81bSScott Long iden[IDEN_PIO_MODE_SPPORTED] & 0xff)); 3931713e81bSScott Long 3941713e81bSScott Long /*UDMA*/ 395d2bd3ab9SScott Long if ((iden[IDEN_VALID] & 4) == 0) 396d2bd3ab9SScott Long { 397d2bd3ab9SScott Long KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n")); 3981713e81bSScott Long return -1; 3991713e81bSScott Long } 4001713e81bSScott Long 4011713e81bSScott Long /* 48 bit address */ 402d2bd3ab9SScott Long if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) 403d2bd3ab9SScott Long { 4041713e81bSScott Long KdPrint(("%25s - %s\n", "LBA48 addressing", "supported")); 4051713e81bSScott Long pMvSataChannel->lba48Address = MV_TRUE; 406d2bd3ab9SScott Long } 407d2bd3ab9SScott Long else 408d2bd3ab9SScott Long { 4091713e81bSScott Long KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported")); 4101713e81bSScott Long pMvSataChannel->lba48Address = MV_FALSE; 4111713e81bSScott Long } 4121713e81bSScott Long return 0; 4131713e81bSScott Long } 4141713e81bSScott Long 4151713e81bSScott Long static void 4161713e81bSScott Long init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) 4171713e81bSScott Long { 418d2bd3ab9SScott Long PVDevice pVDev = &pAdapter->VDevices[channel]; 419d2bd3ab9SScott Long MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; 420d2bd3ab9SScott Long MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice; 4211713e81bSScott Long 4221713e81bSScott Long pMvSataChannel->outstandingCommands = 0; 4231713e81bSScott Long 4241713e81bSScott Long pVDev->u.disk.mv = pMvSataChannel; 4251713e81bSScott Long pVDev->u.disk.df_on_line = 1; 4261713e81bSScott Long pVDev->u.disk.pVBus = &pAdapter->VBus; 4271713e81bSScott Long pVDev->pVBus = &pAdapter->VBus; 4281713e81bSScott Long 4291713e81bSScott Long #ifdef SUPPORT_48BIT_LBA 4301713e81bSScott Long if (pMvSataChannel->lba48Address == MV_TRUE) 431d2bd3ab9SScott Long pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; 4321713e81bSScott Long else 4331713e81bSScott Long #endif 4341713e81bSScott Long if(IdentifyData[53] & 1) { 4351713e81bSScott Long pVDev->u.disk.dDeRealCapacity = 436d2bd3ab9SScott Long (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ? 4371713e81bSScott Long (IdentifyData[61]<<16 | IdentifyData[60]) : 4381713e81bSScott Long (IdentifyData[58]<<16 | IdentifyData[57])) - 1; 4391713e81bSScott Long } else 4401713e81bSScott Long pVDev->u.disk.dDeRealCapacity = 4411713e81bSScott Long (IdentifyData[61]<<16 | IdentifyData[60]) - 1; 4421713e81bSScott Long 4431713e81bSScott Long pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 444d2bd3ab9SScott Long pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0; 4451713e81bSScott Long 4461713e81bSScott Long if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) { 4471713e81bSScott Long pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = 448d2bd3ab9SScott Long pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8; 4491713e81bSScott Long } 4501713e81bSScott Long } 4511713e81bSScott Long 452d2bd3ab9SScott Long static void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) 4531713e81bSScott Long { 4541713e81bSScott Long PVDevice pVDev; 455d2bd3ab9SScott Long MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 456d2bd3ab9SScott Long MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; 4571713e81bSScott Long 458d2bd3ab9SScott Long if (!pMvSataChannel) return; 4591713e81bSScott Long 460d2bd3ab9SScott Long if (plugged) 461d2bd3ab9SScott Long { 4621713e81bSScott Long pVDev = &(pAdapter->VDevices[channelIndex]); 4631713e81bSScott Long init_vdev_params(pAdapter, channelIndex); 4641713e81bSScott Long 4651713e81bSScott Long pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI : 466d2bd3ab9SScott Long pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 4671713e81bSScott Long 468d2bd3ab9SScott Long pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO; 4691713e81bSScott Long pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 4701713e81bSScott Long pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 4711713e81bSScott Long pVDev->vf_online = 1; 4721713e81bSScott Long 4731713e81bSScott Long #ifdef SUPPORT_ARRAY 474d2bd3ab9SScott Long if(pVDev->pParent) 475d2bd3ab9SScott Long { 4761713e81bSScott Long int iMember; 477d2bd3ab9SScott Long for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++) 4781713e81bSScott Long if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) 4791713e81bSScott Long pVDev->pParent->u.array.pMember[iMember] = NULL; 4801713e81bSScott Long pVDev->pParent = NULL; 4811713e81bSScott Long } 4821713e81bSScott Long #endif 4831713e81bSScott Long fNotifyGUI(ET_DEVICE_PLUGGED,pVDev); 4841713e81bSScott Long fCheckBootable(pVDev); 4851713e81bSScott Long RegisterVDevice(pVDev); 4861713e81bSScott Long 4871713e81bSScott Long #ifndef FOR_DEMO 4881713e81bSScott Long if (pAdapter->beeping) { 4891713e81bSScott Long pAdapter->beeping = 0; 4901713e81bSScott Long BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 4911713e81bSScott Long } 4921713e81bSScott Long #endif 4931713e81bSScott Long 494d2bd3ab9SScott Long } 495d2bd3ab9SScott Long else 496d2bd3ab9SScott Long { 4971713e81bSScott Long pVDev = &(pAdapter->VDevices[channelIndex]); 498d2bd3ab9SScott Long failDevice(pVDev); 4991713e81bSScott Long } 5001713e81bSScott Long } 5011713e81bSScott Long 5021713e81bSScott Long static int 5031713e81bSScott Long start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) 5041713e81bSScott Long { 505d2bd3ab9SScott Long MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 506d2bd3ab9SScott Long MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; 507d2bd3ab9SScott Long MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]); 5081713e81bSScott Long MV_U32 udmaMode,pioMode; 5091713e81bSScott Long 5101713e81bSScott Long KdPrint(("RR182x [%d]: start channel (%d)", pMvSataAdapter->adapterId, 5111713e81bSScott Long channelNum)); 5121713e81bSScott Long 5131713e81bSScott Long 5141713e81bSScott Long /* Software reset channel */ 515d2bd3ab9SScott Long if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 516d2bd3ab9SScott Long { 5171713e81bSScott Long MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n", 5181713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 5191713e81bSScott Long return -1; 5201713e81bSScott Long } 5211713e81bSScott Long 5221713e81bSScott Long /* Hardware reset channel */ 523d2bd3ab9SScott Long if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 524d2bd3ab9SScott Long { 525d2bd3ab9SScott Long /* If failed, try again - this is when trying to hardreset a channel */ 526d2bd3ab9SScott Long /* when drive is just spinning up */ 5271713e81bSScott Long StallExec(5000000); /* wait 5 sec before trying again */ 528d2bd3ab9SScott Long if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 529d2bd3ab9SScott Long { 530d2bd3ab9SScott Long MV_ERROR("RR182x [%d,%d]: failed to perform Hard reset\n", 5311713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 5321713e81bSScott Long return -1; 5331713e81bSScott Long } 5341713e81bSScott Long } 5351713e81bSScott Long 536d2bd3ab9SScott Long /* identify device*/ 537d2bd3ab9SScott Long if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE) 538d2bd3ab9SScott Long { 539d2bd3ab9SScott Long MV_ERROR("RR182x [%d,%d]: failed to perform ATA Identify command\n" 540d2bd3ab9SScott Long , pMvSataAdapter->adapterId, channelNum); 541d2bd3ab9SScott Long return -1; 542d2bd3ab9SScott Long } 543d2bd3ab9SScott Long if (hptmv_parse_identify_results(pMvSataChannel)) 544d2bd3ab9SScott Long { 545d2bd3ab9SScott Long MV_ERROR("RR182x [%d,%d]: Error in parsing ATA Identify message\n" 546d2bd3ab9SScott Long , pMvSataAdapter->adapterId, channelNum); 547d2bd3ab9SScott Long return -1; 548d2bd3ab9SScott Long } 549d2bd3ab9SScott Long 550d2bd3ab9SScott Long /* mvStorageDevATASetFeatures */ 551d2bd3ab9SScott Long /* Disable 8 bit PIO in case CFA enabled */ 552d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[86] & 4) 553d2bd3ab9SScott Long { 554d2bd3ab9SScott Long KdPrint(("RR182x [%d]: Disable 8 bit PIO (CFA enabled) \n", 555d2bd3ab9SScott Long pMvSataAdapter->adapterId)); 556d2bd3ab9SScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 557d2bd3ab9SScott Long MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, 558d2bd3ab9SScott Long 0, 0, 0) == MV_FALSE) 559d2bd3ab9SScott Long { 560d2bd3ab9SScott Long MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures" 561d2bd3ab9SScott Long " failed\n", pMvSataAdapter->adapterId, channelNum); 562d2bd3ab9SScott Long return -1; 563d2bd3ab9SScott Long } 564d2bd3ab9SScott Long } 5651713e81bSScott Long /* Write cache */ 566d2bd3ab9SScott Long #ifdef ENABLE_WRITE_CACHE 567d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[82] & 0x20) 568d2bd3ab9SScott Long { 569d2bd3ab9SScott Long if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */ 570d2bd3ab9SScott Long { 571d2bd3ab9SScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 572d2bd3ab9SScott Long MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 573d2bd3ab9SScott Long 0, 0, 0) == MV_FALSE) 574d2bd3ab9SScott Long { 575d2bd3ab9SScott Long MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 5761713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 5771713e81bSScott Long return -1; 5781713e81bSScott Long } 5791713e81bSScott Long } 5801713e81bSScott Long KdPrint(("RR182x [%d]: channel %d, write cache enabled\n", 5811713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 582d2bd3ab9SScott Long } 583d2bd3ab9SScott Long else 584d2bd3ab9SScott Long { 5851713e81bSScott Long KdPrint(("RR182x [%d]: channel %d, write cache not supported\n", 5861713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 5871713e81bSScott Long } 588d2bd3ab9SScott Long #else /* disable write cache */ 589d2bd3ab9SScott Long { 590d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[85] & 0x20) 591d2bd3ab9SScott Long { 5921713e81bSScott Long KdPrint(("RR182x [%d]: channel =%d, disable write cache\n", 5931713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 5941713e81bSScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 595d2bd3ab9SScott Long MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 596d2bd3ab9SScott Long 0, 0, 0) == MV_FALSE) 597d2bd3ab9SScott Long { 598d2bd3ab9SScott Long MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n", 5991713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 6001713e81bSScott Long return -1; 6011713e81bSScott Long } 6021713e81bSScott Long } 6031713e81bSScott Long KdPrint(("RR182x [%d]: channel=%d, write cache disabled\n", 6041713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 605d2bd3ab9SScott Long } 6061713e81bSScott Long #endif 6071713e81bSScott Long 6081713e81bSScott Long /* Set transfer mode */ 6091713e81bSScott Long KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_SLOW\n", 6101713e81bSScott Long pMvSataAdapter->adapterId)); 6111713e81bSScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 612d2bd3ab9SScott Long MV_ATA_SET_FEATURES_TRANSFER, 613d2bd3ab9SScott Long MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == 614d2bd3ab9SScott Long MV_FALSE) 615d2bd3ab9SScott Long { 6161713e81bSScott Long MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", 6171713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 6181713e81bSScott Long return -1; 6191713e81bSScott Long } 6201713e81bSScott Long 621d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) 622d2bd3ab9SScott Long { 6231713e81bSScott Long pioMode = MV_ATA_TRANSFER_PIO_4; 624d2bd3ab9SScott Long } 625d2bd3ab9SScott Long else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) 626d2bd3ab9SScott Long { 6271713e81bSScott Long pioMode = MV_ATA_TRANSFER_PIO_3; 628d2bd3ab9SScott Long } 629d2bd3ab9SScott Long else 630d2bd3ab9SScott Long { 631d2bd3ab9SScott Long MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n"); 6321713e81bSScott Long pioMode = MV_ATA_TRANSFER_PIO_SLOW; 6331713e81bSScott Long } 6341713e81bSScott Long 6351713e81bSScott Long KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_4\n", 6361713e81bSScott Long pMvSataAdapter->adapterId)); 6371713e81bSScott Long pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode; 6381713e81bSScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 639d2bd3ab9SScott Long MV_ATA_SET_FEATURES_TRANSFER, 640d2bd3ab9SScott Long pioMode, 0, 0, 0) == MV_FALSE) 641d2bd3ab9SScott Long { 6421713e81bSScott Long MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", 6431713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 6441713e81bSScott Long return -1; 6451713e81bSScott Long } 6461713e81bSScott Long 6471713e81bSScott Long udmaMode = MV_ATA_TRANSFER_UDMA_0; 648d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) 649d2bd3ab9SScott Long { 6501713e81bSScott Long udmaMode = MV_ATA_TRANSFER_UDMA_6; 651d2bd3ab9SScott Long } 652d2bd3ab9SScott Long else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) 653d2bd3ab9SScott Long { 6541713e81bSScott Long udmaMode = MV_ATA_TRANSFER_UDMA_5; 655d2bd3ab9SScott Long } 656d2bd3ab9SScott Long else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) 657d2bd3ab9SScott Long { 6581713e81bSScott Long udmaMode = MV_ATA_TRANSFER_UDMA_4; 659d2bd3ab9SScott Long } 660d2bd3ab9SScott Long else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) 661d2bd3ab9SScott Long { 6621713e81bSScott Long udmaMode = MV_ATA_TRANSFER_UDMA_3; 663d2bd3ab9SScott Long } 664d2bd3ab9SScott Long else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) 665d2bd3ab9SScott Long { 6661713e81bSScott Long udmaMode = MV_ATA_TRANSFER_UDMA_2; 6671713e81bSScott Long } 6681713e81bSScott Long 6691713e81bSScott Long KdPrint(("RR182x [%d] Set transfer mode XFER_UDMA_%d\n", 6701713e81bSScott Long pMvSataAdapter->adapterId, udmaMode & 0xf)); 6711713e81bSScott Long pChannelInfo->maxUltraDmaModeSupported = udmaMode; 6721713e81bSScott Long 673d2bd3ab9SScott Long /*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 674d2bd3ab9SScott Long MV_ATA_SET_FEATURES_TRANSFER, udmaMode, 675d2bd3ab9SScott Long 0, 0, 0) == MV_FALSE) 676d2bd3ab9SScott Long { 6771713e81bSScott Long MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", 6781713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 6791713e81bSScott Long return -1; 680d2bd3ab9SScott Long }*/ 6811713e81bSScott Long if (pChannelInfo->maxUltraDmaModeSupported == 0xFF) 6821713e81bSScott Long return TRUE; 683d2bd3ab9SScott Long else 684d2bd3ab9SScott Long do 685d2bd3ab9SScott Long { 6861713e81bSScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 6871713e81bSScott Long MV_ATA_SET_FEATURES_TRANSFER, 688d2bd3ab9SScott Long pChannelInfo->maxUltraDmaModeSupported, 689d2bd3ab9SScott Long 0, 0, 0) == MV_FALSE) 690d2bd3ab9SScott Long { 691d2bd3ab9SScott Long if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0) 692d2bd3ab9SScott Long { 693d2bd3ab9SScott Long if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 694d2bd3ab9SScott Long { 695d2bd3ab9SScott Long MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress, 696d2bd3ab9SScott Long pMvSataChannel->eDmaRegsOffset + 697d2bd3ab9SScott Long 0x11c, /* command reg */ 698d2bd3ab9SScott Long MV_ATA_COMMAND_IDLE_IMMEDIATE); 6991713e81bSScott Long mvMicroSecondsDelay(10000); 7001713e81bSScott Long mvSataChannelHardReset(pMvSataAdapter, channelNum); 701d2bd3ab9SScott Long if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) 7021713e81bSScott Long return FALSE; 7031713e81bSScott Long } 704d2bd3ab9SScott Long if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) 7051713e81bSScott Long return FALSE; 7061713e81bSScott Long pChannelInfo->maxUltraDmaModeSupported--; 707d2bd3ab9SScott Long continue; 708d2bd3ab9SScott Long } 709d2bd3ab9SScott Long else return FALSE; 710d2bd3ab9SScott Long } 711d2bd3ab9SScott Long break; 7121713e81bSScott Long }while (1); 7131713e81bSScott Long 7141713e81bSScott Long /* Read look ahead */ 715d2bd3ab9SScott Long #ifdef ENABLE_READ_AHEAD 716d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[82] & 0x40) 717d2bd3ab9SScott Long { 718d2bd3ab9SScott Long if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */ 719d2bd3ab9SScott Long { 720d2bd3ab9SScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 721d2bd3ab9SScott Long MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 722d2bd3ab9SScott Long 0, 0) == MV_FALSE) 723d2bd3ab9SScott Long { 724d2bd3ab9SScott Long MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", 725d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelNum); 7261713e81bSScott Long return -1; 7271713e81bSScott Long } 7281713e81bSScott Long } 7291713e81bSScott Long KdPrint(("RR182x [%d]: channel=%d, read look ahead enabled\n", 7301713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 731d2bd3ab9SScott Long } 732d2bd3ab9SScott Long else 733d2bd3ab9SScott Long { 734d2bd3ab9SScott Long KdPrint(("RR182x [%d]: channel %d, Read Look Ahead not supported\n", 735d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelNum)); 7361713e81bSScott Long } 7371713e81bSScott Long #else 738d2bd3ab9SScott Long { 739d2bd3ab9SScott Long if (pMvSataChannel->identifyDevice[86] & 0x20) 740d2bd3ab9SScott Long { 7411713e81bSScott Long KdPrint(("RR182x [%d]:channel %d, disable read look ahead\n", 7421713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 7431713e81bSScott Long if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, 744d2bd3ab9SScott Long MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 745d2bd3ab9SScott Long 0, 0) == MV_FALSE) 746d2bd3ab9SScott Long { 747d2bd3ab9SScott Long MV_ERROR("RR182x [%d]:channel %d: ATA Set Features failed\n", 748d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelNum); 7491713e81bSScott Long return -1; 7501713e81bSScott Long } 7511713e81bSScott Long } 7521713e81bSScott Long KdPrint(("RR182x [%d]:channel %d, read look ahead disabled\n", 7531713e81bSScott Long pMvSataAdapter->adapterId, channelNum)); 754d2bd3ab9SScott Long } 7551713e81bSScott Long #endif 7561713e81bSScott Long 757d2bd3ab9SScott Long 758d2bd3ab9SScott Long { 759d2bd3ab9SScott Long KdPrint(("RR182x [%d]: channel %d config EDMA, Non Queued Mode\n", 760d2bd3ab9SScott Long pMvSataAdapter->adapterId, 761d2bd3ab9SScott Long channelNum)); 762d2bd3ab9SScott Long if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, 763d2bd3ab9SScott Long MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) 764d2bd3ab9SScott Long { 765d2bd3ab9SScott Long MV_ERROR("RR182x [%d] channel %d Error: mvSataConfigEdmaMode failed\n", 7661713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 7671713e81bSScott Long return -1; 7681713e81bSScott Long } 7691713e81bSScott Long } 7701713e81bSScott Long /* Enable EDMA */ 771d2bd3ab9SScott Long if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) 772d2bd3ab9SScott Long { 7731713e81bSScott Long MV_ERROR("RR182x [%d] Failed to enable DMA, channel=%d\n", 7741713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 7751713e81bSScott Long return -1; 7761713e81bSScott Long } 7771713e81bSScott Long MV_ERROR("RR182x [%d,%d]: channel started successfully\n", 7781713e81bSScott Long pMvSataAdapter->adapterId, channelNum); 7791713e81bSScott Long 7801713e81bSScott Long #ifndef FOR_DEMO 7811713e81bSScott Long set_fail_led(pMvSataAdapter, channelNum, 0); 7821713e81bSScott Long #endif 7831713e81bSScott Long return 0; 7841713e81bSScott Long } 7851713e81bSScott Long 7861713e81bSScott Long static void 7871713e81bSScott Long hptmv_handle_event(void * data, int flag) 7881713e81bSScott Long { 789d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)data; 790d2bd3ab9SScott Long MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; 7911713e81bSScott Long MV_U8 channelIndex; 7921713e81bSScott Long 793d2bd3ab9SScott Long /* mvOsSemTake(&pMvSataAdapter->semaphore); */ 794d2bd3ab9SScott Long for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++) 795d2bd3ab9SScott Long { 796d2bd3ab9SScott Long switch(pAdapter->sataEvents[channelIndex]) 797d2bd3ab9SScott Long { 7981713e81bSScott Long case SATA_EVENT_CHANNEL_CONNECTED: 7991713e81bSScott Long /* Handle only connects */ 8001713e81bSScott Long if (flag == 1) 8011713e81bSScott Long break; 8021713e81bSScott Long KdPrint(("RR182x [%d,%d]: new device connected\n", 8031713e81bSScott Long pMvSataAdapter->adapterId, channelIndex)); 8041713e81bSScott Long hptmv_init_channel(pAdapter, channelIndex); 805d2bd3ab9SScott Long if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE) 806d2bd3ab9SScott Long { 8071713e81bSScott Long MV_ERROR("RR182x [%d,%d] Failed to configure\n", 808d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelIndex); 8091713e81bSScott Long hptmv_free_channel(pAdapter, channelIndex); 810d2bd3ab9SScott Long } 811d2bd3ab9SScott Long else 812d2bd3ab9SScott Long { 813d2bd3ab9SScott Long /*mvSataChannelHardReset(pMvSataAdapter, channel);*/ 814d2bd3ab9SScott Long if (start_channel( pAdapter, channelIndex)) 815d2bd3ab9SScott Long { 816d2bd3ab9SScott Long MV_ERROR("RR182x [%d,%d]Failed to start channel\n", 817d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelIndex); 818d2bd3ab9SScott Long hptmv_free_channel(pAdapter, channelIndex); 819d2bd3ab9SScott Long } 820d2bd3ab9SScott Long else 821d2bd3ab9SScott Long { 822d2bd3ab9SScott Long device_change(pAdapter, channelIndex, TRUE); 8231713e81bSScott Long } 8241713e81bSScott Long } 825d2bd3ab9SScott Long pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 8261713e81bSScott Long break; 8271713e81bSScott Long 8281713e81bSScott Long case SATA_EVENT_CHANNEL_DISCONNECTED: 8291713e81bSScott Long /* Handle only disconnects */ 8301713e81bSScott Long if (flag == 0) 8311713e81bSScott Long break; 8321713e81bSScott Long KdPrint(("RR182x [%d,%d]: device disconnected\n", 8331713e81bSScott Long pMvSataAdapter->adapterId, channelIndex)); 8341713e81bSScott Long /* Flush pending commands */ 835d2bd3ab9SScott Long if(pMvSataAdapter->sataChannel[channelIndex]) 836d2bd3ab9SScott Long { 8371713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 838d2bd3ab9SScott Long mvSataFlushDmaQueue (pMvSataAdapter, channelIndex, 839d2bd3ab9SScott Long MV_FLUSH_TYPE_CALLBACK); 8401713e81bSScott Long CheckPendingCall(_VBUS_P0); 841d2bd3ab9SScott Long mvSataRemoveChannel(pMvSataAdapter,channelIndex); 8421713e81bSScott Long hptmv_free_channel(pAdapter, channelIndex); 843d2bd3ab9SScott Long pMvSataAdapter->sataChannel[channelIndex] = NULL; 8441713e81bSScott Long KdPrint(("RR182x [%d,%d]: channel removed\n", 845d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelIndex)); 846d2bd3ab9SScott Long if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 8471713e81bSScott Long Check_Idle_Call(pAdapter); 8481713e81bSScott Long } 849d2bd3ab9SScott Long else 850d2bd3ab9SScott Long { 851d2bd3ab9SScott Long KdPrint(("RR182x [%d,%d]: channel already removed!!\n", 852d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelIndex)); 853d2bd3ab9SScott Long } 854d2bd3ab9SScott Long pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; 8551713e81bSScott Long break; 8561713e81bSScott Long 8571713e81bSScott Long case SATA_EVENT_NO_CHANGE: 8581713e81bSScott Long break; 8591713e81bSScott Long 8601713e81bSScott Long default: 8611713e81bSScott Long break; 8621713e81bSScott Long } 8631713e81bSScott Long } 864d2bd3ab9SScott Long /* mvOsSemRelease(&pMvSataAdapter->semaphore); */ 8651713e81bSScott Long } 8661713e81bSScott Long 8671713e81bSScott Long #define EVENT_CONNECT 1 8681713e81bSScott Long #define EVENT_DISCONNECT 0 8691713e81bSScott Long 8701713e81bSScott Long static void 8711713e81bSScott Long hptmv_handle_event_connect(void *data) 8721713e81bSScott Long { 8731713e81bSScott Long hptmv_handle_event (data, 0); 8741713e81bSScott Long } 8751713e81bSScott Long 8761713e81bSScott Long static void 8771713e81bSScott Long hptmv_handle_event_disconnect(void *data) 8781713e81bSScott Long { 8791713e81bSScott Long hptmv_handle_event (data, 1); 8801713e81bSScott Long } 8811713e81bSScott Long 8821713e81bSScott Long static MV_BOOLEAN 8831713e81bSScott Long hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType, 8841713e81bSScott Long MV_U32 param1, MV_U32 param2) 8851713e81bSScott Long { 8861713e81bSScott Long IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; 8871713e81bSScott Long 888d2bd3ab9SScott Long switch (eventType) 889d2bd3ab9SScott Long { 8901713e81bSScott Long case MV_EVENT_TYPE_SATA_CABLE: 8911713e81bSScott Long { 8921713e81bSScott Long MV_U8 channel = param2; 8931713e81bSScott Long 894d2bd3ab9SScott Long if (param1 == EVENT_CONNECT) 895d2bd3ab9SScott Long { 896d2bd3ab9SScott Long pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED; 897d2bd3ab9SScott Long KdPrint(("RR182x [%d,%d]: device connected event received\n", 898d2bd3ab9SScott Long pMvSataAdapter->adapterId, channel)); 899d2bd3ab9SScott Long /* Delete previous timers (if multiple drives connected in the same time */ 900d2bd3ab9SScott Long pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz); 901d2bd3ab9SScott Long } 902d2bd3ab9SScott Long else if (param1 == EVENT_DISCONNECT) 903d2bd3ab9SScott Long { 904d2bd3ab9SScott Long pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED; 905d2bd3ab9SScott Long KdPrint(("RR182x [%d,%d]: device disconnected event received \n", 906d2bd3ab9SScott Long pMvSataAdapter->adapterId, channel)); 9071713e81bSScott Long device_change(pAdapter, channel, FALSE); 908d2bd3ab9SScott Long /* Delete previous timers (if multiple drives disconnected in the same time */ 909d2bd3ab9SScott Long /*pAdapter->event_timer_disconnect = timeout(hptmv_handle_event_disconnect, pAdapter, 10*hz); */ 910d2bd3ab9SScott Long /*It is not necessary to wait, handle it directly*/ 911d2bd3ab9SScott Long hptmv_handle_event_disconnect(pAdapter); 912d2bd3ab9SScott Long } 913d2bd3ab9SScott Long else 914d2bd3ab9SScott Long { 915d2bd3ab9SScott Long 9161713e81bSScott Long MV_ERROR("RR182x: illigal value for param1(%d) at " 9171713e81bSScott Long "connect/disconect event, host=%d\n", param1, 9181713e81bSScott Long pMvSataAdapter->adapterId ); 9191713e81bSScott Long 9201713e81bSScott Long } 9211713e81bSScott Long } 922d2bd3ab9SScott Long break; 9231713e81bSScott Long case MV_EVENT_TYPE_ADAPTER_ERROR: 9241713e81bSScott Long KdPrint(("RR182x: DEVICE error event received, pci cause " 9251713e81bSScott Long "reg=%x, don't how to handle this\n", param1)); 9261713e81bSScott Long return MV_TRUE; 9271713e81bSScott Long default: 9281713e81bSScott Long MV_ERROR("RR182x[%d]: unknown event type (%d)\n", 9291713e81bSScott Long pMvSataAdapter->adapterId, eventType); 9301713e81bSScott Long return MV_FALSE; 9311713e81bSScott Long } 9321713e81bSScott Long return MV_TRUE; 9331713e81bSScott Long } 9341713e81bSScott Long 9351713e81bSScott Long static int 9361713e81bSScott Long hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) 9371713e81bSScott Long { 938d2bd3ab9SScott Long pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE, 939d2bd3ab9SScott Long M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 940d2bd3ab9SScott Long if (pAdapter->requestsArrayBaseAddr == NULL) 941d2bd3ab9SScott Long { 942d2bd3ab9SScott Long MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA request" 943d2bd3ab9SScott Long " queues\n", pAdapter->mvSataAdapter.adapterId); 9441713e81bSScott Long return -1; 9451713e81bSScott Long } 946d2bd3ab9SScott Long pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr); 947d2bd3ab9SScott Long pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr; 9481713e81bSScott Long pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 949d2bd3ab9SScott Long pAdapter->requestsArrayBaseAlignedAddr = (MV_U8 *) 950d2bd3ab9SScott Long (((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); 951d2bd3ab9SScott Long pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr; 9521713e81bSScott Long pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; 953d2bd3ab9SScott Long pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); 9541713e81bSScott Long 955d2bd3ab9SScott Long if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) != 956d2bd3ab9SScott Long (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr)) 957d2bd3ab9SScott Long { 9581713e81bSScott Long MV_ERROR("RR182x[%d]: Error in Request Quueues Alignment\n", 9591713e81bSScott Long pAdapter->mvSataAdapter.adapterId); 960d2bd3ab9SScott Long contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 9611713e81bSScott Long return -1; 9621713e81bSScott Long } 9631713e81bSScott Long /* response queues */ 964d2bd3ab9SScott Long pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE, 965d2bd3ab9SScott Long M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 966d2bd3ab9SScott Long if (pAdapter->responsesArrayBaseAddr == NULL) 967d2bd3ab9SScott Long { 968d2bd3ab9SScott Long MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA response" 969d2bd3ab9SScott Long " queues\n", pAdapter->mvSataAdapter.adapterId); 970d2bd3ab9SScott Long contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 9711713e81bSScott Long return -1; 9721713e81bSScott Long } 973d2bd3ab9SScott Long pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr); 974d2bd3ab9SScott Long pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr; 9751713e81bSScott Long pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 976d2bd3ab9SScott Long pAdapter->responsesArrayBaseAlignedAddr = (MV_U8 *) 977d2bd3ab9SScott Long (((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); 978d2bd3ab9SScott Long pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr; 979d2bd3ab9SScott Long pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; 980d2bd3ab9SScott Long pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); 9811713e81bSScott Long 982d2bd3ab9SScott Long if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) != 983d2bd3ab9SScott Long (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr)) 984d2bd3ab9SScott Long { 9851713e81bSScott Long MV_ERROR("RR182x[%d]: Error in Response Quueues Alignment\n", 9861713e81bSScott Long pAdapter->mvSataAdapter.adapterId); 987d2bd3ab9SScott Long contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 988d2bd3ab9SScott Long contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 9891713e81bSScott Long return -1; 9901713e81bSScott Long } 9911713e81bSScott Long return 0; 9921713e81bSScott Long } 9931713e81bSScott Long 9941713e81bSScott Long static void 9951713e81bSScott Long hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter) 9961713e81bSScott Long { 997d2bd3ab9SScott Long contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); 998d2bd3ab9SScott Long contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); 9991713e81bSScott Long } 10001713e81bSScott Long 10011713e81bSScott Long static PVOID 10021713e81bSScott Long AllocatePRDTable(IAL_ADAPTER_T *pAdapter) 10031713e81bSScott Long { 10041713e81bSScott Long PVOID ret; 10051713e81bSScott Long if (pAdapter->pFreePRDLink) { 1006d2bd3ab9SScott Long KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink)); 10071713e81bSScott Long ret = pAdapter->pFreePRDLink; 10081713e81bSScott Long pAdapter->pFreePRDLink = *(void**)ret; 10091713e81bSScott Long return ret; 10101713e81bSScott Long } 10111713e81bSScott Long return NULL; 10121713e81bSScott Long } 10131713e81bSScott Long 10141713e81bSScott Long static void 10151713e81bSScott Long FreePRDTable(IAL_ADAPTER_T *pAdapter, PVOID PRDTable) 10161713e81bSScott Long { 10171713e81bSScott Long *(void**)PRDTable = pAdapter->pFreePRDLink; 10181713e81bSScott Long pAdapter->pFreePRDLink = PRDTable; 10191713e81bSScott Long } 10201713e81bSScott Long 10211713e81bSScott Long extern PVDevice fGetFirstChild(PVDevice pLogical); 10221713e81bSScott Long extern void fResetBootMark(PVDevice pLogical); 10231713e81bSScott Long static void 10241713e81bSScott Long fRegisterVdevice(IAL_ADAPTER_T *pAdapter) 10251713e81bSScott Long { 10261713e81bSScott Long PVDevice pPhysical, pLogical; 10271713e81bSScott Long PVBus pVBus; 10281713e81bSScott Long int i,j; 10291713e81bSScott Long 10301713e81bSScott Long for(i=0;i<MV_SATA_CHANNELS_NUM;i++) { 10311713e81bSScott Long pPhysical = &(pAdapter->VDevices[i]); 10321713e81bSScott Long pLogical = pPhysical; 10331713e81bSScott Long while (pLogical->pParent) pLogical = pLogical->pParent; 10341713e81bSScott Long if (pLogical->vf_online==0) { 10351713e81bSScott Long pPhysical->vf_bootmark = pLogical->vf_bootmark = 0; 10361713e81bSScott Long continue; 10371713e81bSScott Long } 1038d2bd3ab9SScott Long if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical)) 10391713e81bSScott Long continue; 10401713e81bSScott Long 10411713e81bSScott Long pVBus = &pAdapter->VBus; 1042d2bd3ab9SScott Long if(pVBus) 1043d2bd3ab9SScott Long { 10441713e81bSScott Long j=0; 1045d2bd3ab9SScott Long while(j<MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) j++; 10461713e81bSScott Long if(j<MAX_VDEVICE_PER_VBUS){ 10471713e81bSScott Long pVBus->pVDevice[j] = pLogical; 10481713e81bSScott Long pLogical->pVBus = pVBus; 10491713e81bSScott Long 10501713e81bSScott Long if (j>0 && pLogical->vf_bootmark) { 10511713e81bSScott Long if (pVBus->pVDevice[0]->vf_bootmark) { 10521713e81bSScott Long fResetBootMark(pLogical); 1053d2bd3ab9SScott Long } 1054d2bd3ab9SScott Long else { 1055d2bd3ab9SScott Long do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j); 10561713e81bSScott Long pVBus->pVDevice[0] = pLogical; 10571713e81bSScott Long } 10581713e81bSScott Long } 10591713e81bSScott Long } 10601713e81bSScott Long } 10611713e81bSScott Long } 10621713e81bSScott Long } 10631713e81bSScott Long 10641713e81bSScott Long PVDevice 10651713e81bSScott Long GetSpareDisk(_VBUS_ARG PVDevice pArray) 10661713e81bSScott Long { 1067d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; 1068d2bd3ab9SScott Long ULONG capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); 10691713e81bSScott Long ULONG thiscap, maxcap = MAX_LBA_T; 10701713e81bSScott Long PVDevice pVDevice, pFind = NULL; 10711713e81bSScott Long int i; 10721713e81bSScott Long 1073d2bd3ab9SScott Long for(i=0;i<MV_SATA_CHANNELS_NUM;i++) 1074d2bd3ab9SScott Long { 10751713e81bSScott Long pVDevice = &pAdapter->VDevices[i]; 10761713e81bSScott Long if(!pVDevice) 10771713e81bSScott Long continue; 1078d2bd3ab9SScott Long thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; 10791713e81bSScott Long /* find the smallest usable spare disk */ 10801713e81bSScott Long if (pVDevice->VDeviceType==VD_SPARE && 1081d2bd3ab9SScott Long pVDevice->u.disk.df_on_line && 1082d2bd3ab9SScott Long thiscap < maxcap && 1083d2bd3ab9SScott Long thiscap >= capacity) 1084d2bd3ab9SScott Long { 10851713e81bSScott Long maxcap = pVDevice->VDeviceCapacity; 10861713e81bSScott Long pFind = pVDevice; 10871713e81bSScott Long } 10881713e81bSScott Long } 10891713e81bSScott Long return pFind; 10901713e81bSScott Long } 10911713e81bSScott Long 10921713e81bSScott Long /****************************************************************** 10931713e81bSScott Long * IO ATA Command 10941713e81bSScott Long *******************************************************************/ 10951713e81bSScott Long int HPTLIBAPI 10961713e81bSScott Long fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer) 10971713e81bSScott Long { 10981713e81bSScott Long return mvReadWrite(pDev->mv, Lba, Cmd, tmpBuffer); 10991713e81bSScott Long } 11001713e81bSScott Long 11011713e81bSScott Long void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) 11021713e81bSScott Long { 1103d2bd3ab9SScott Long MV_SATA_CHANNEL *pSataChannel = pDev->mv; 1104d2bd3ab9SScott Long MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; 1105d2bd3ab9SScott Long MV_U8 channelIndex = pSataChannel->channelNumber; 11061713e81bSScott Long UCHAR mvMode; 11071713e81bSScott Long /* 508x don't use MW-DMA? */ 11081713e81bSScott Long if (NewMode>4 && NewMode<8) NewMode = 4; 11091713e81bSScott Long pDev->bDeModeSetting = NewMode; 11101713e81bSScott Long if (NewMode<=4) 11111713e81bSScott Long mvMode = MV_ATA_TRANSFER_PIO_0 + NewMode; 11121713e81bSScott Long else 11131713e81bSScott Long mvMode = MV_ATA_TRANSFER_UDMA_0 + (NewMode-8); 11141713e81bSScott Long 11151713e81bSScott Long /*To fix 88i8030 bug*/ 11161713e81bSScott Long if (mvMode > MV_ATA_TRANSFER_UDMA_0 && mvMode < MV_ATA_TRANSFER_UDMA_4) 11171713e81bSScott Long mvMode = MV_ATA_TRANSFER_UDMA_0; 11181713e81bSScott Long 11191713e81bSScott Long mvSataDisableChannelDma(pSataAdapter, channelIndex); 11201713e81bSScott Long /* Flush pending commands */ 11211713e81bSScott Long mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE); 11221713e81bSScott Long 11231713e81bSScott Long if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, 1124d2bd3ab9SScott Long MV_ATA_SET_FEATURES_TRANSFER, 1125d2bd3ab9SScott Long mvMode, 0, 0, 0) == MV_FALSE) 1126d2bd3ab9SScott Long { 11271713e81bSScott Long KdPrint(("channel %d: Set Features failed\n", channelIndex)); 11281713e81bSScott Long } 11291713e81bSScott Long /* Enable EDMA */ 11301713e81bSScott Long if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE) 11311713e81bSScott Long KdPrint(("Failed to enable DMA, channel=%d", channelIndex)); 11321713e81bSScott Long } 11331713e81bSScott Long 11341713e81bSScott Long #ifdef SUPPORT_ARRAY 11351713e81bSScott Long #define IdeRegisterVDevice fCheckArray 11361713e81bSScott Long #else 11371713e81bSScott Long void 11381713e81bSScott Long IdeRegisterVDevice(PDevice pDev) 11391713e81bSScott Long { 11401713e81bSScott Long PVDevice pVDev = Map2pVDevice(pDev); 11411713e81bSScott Long 11421713e81bSScott Long pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI : 11431713e81bSScott Long pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; 11441713e81bSScott Long pVDev->vf_online = 1; 11451713e81bSScott Long pVDev->VDeviceCapacity = pDev->dDeRealCapacity; 11461713e81bSScott Long pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; 11471713e81bSScott Long pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; 11481713e81bSScott Long } 11491713e81bSScott Long #endif 11501713e81bSScott Long 1151d2bd3ab9SScott Long static __inline PBUS_DMAMAP 1152d2bd3ab9SScott Long dmamap_get(struct IALAdapter * pAdapter) 1153d2bd3ab9SScott Long { 1154d2bd3ab9SScott Long PBUS_DMAMAP p = pAdapter->pbus_dmamap_list; 1155d2bd3ab9SScott Long if (p) 1156d2bd3ab9SScott Long pAdapter->pbus_dmamap_list = p-> next; 1157d2bd3ab9SScott Long return p; 1158d2bd3ab9SScott Long } 1159d2bd3ab9SScott Long 1160d2bd3ab9SScott Long static __inline void 1161d2bd3ab9SScott Long dmamap_put(PBUS_DMAMAP p) 1162d2bd3ab9SScott Long { 1163d2bd3ab9SScott Long p->next = p->pAdapter->pbus_dmamap_list; 1164d2bd3ab9SScott Long p->pAdapter->pbus_dmamap_list = p; 1165d2bd3ab9SScott Long } 1166d2bd3ab9SScott Long 1167d2bd3ab9SScott Long /*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/ 1168d2bd3ab9SScott Long #if __FreeBSD_version >= 500000 1169d2bd3ab9SScott Long static void hpt_init(void *dummy) 1170d2bd3ab9SScott Long { 11714ed23cf2SJohn Baldwin mtx_init(&driver_lock, "hptlock", NULL, MTX_DEF); 1172d2bd3ab9SScott Long } 1173d2bd3ab9SScott Long SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1174d2bd3ab9SScott Long #endif 1175d2bd3ab9SScott Long 11761713e81bSScott Long static int num_adapters = 0; 11771713e81bSScott Long static int 11781713e81bSScott Long init_adapter(IAL_ADAPTER_T *pAdapter) 11791713e81bSScott Long { 11801713e81bSScott Long PVBus _vbus_p = &pAdapter->VBus; 11811713e81bSScott Long MV_SATA_ADAPTER *pMvSataAdapter; 1182d2bd3ab9SScott Long int i, channel, rid; 11831713e81bSScott Long 11841713e81bSScott Long PVDevice pVDev; 11851713e81bSScott Long 11861713e81bSScott Long pAdapter->next = 0; 11871713e81bSScott Long 11881713e81bSScott Long if(gIal_Adapter == 0){ 11891713e81bSScott Long gIal_Adapter = pAdapter; 11901713e81bSScott Long pCurAdapter = gIal_Adapter; 1191d2bd3ab9SScott Long } 1192d2bd3ab9SScott Long else { 11931713e81bSScott Long pCurAdapter->next = pAdapter; 11941713e81bSScott Long pCurAdapter = pAdapter; 11951713e81bSScott Long } 11961713e81bSScott Long 11971713e81bSScott Long pAdapter->outstandingCommands = 0; 11981713e81bSScott Long 11991713e81bSScott Long pMvSataAdapter = &(pAdapter->mvSataAdapter); 12001713e81bSScott Long _vbus_p->OsExt = (void *)pAdapter; 12011713e81bSScott Long pMvSataAdapter->IALData = pAdapter; 12021713e81bSScott Long 1203d2bd3ab9SScott Long if (bus_dma_tag_create(NULL,/* parent */ 1204d2bd3ab9SScott Long 4, /* alignment */ 1205d2bd3ab9SScott Long BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1206d2bd3ab9SScott Long BUS_SPACE_MAXADDR, /* lowaddr */ 1207d2bd3ab9SScott Long BUS_SPACE_MAXADDR, /* highaddr */ 1208d2bd3ab9SScott Long NULL, NULL, /* filter, filterarg */ 1209d2bd3ab9SScott Long PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */ 1210d2bd3ab9SScott Long MAX_SG_DESCRIPTORS, /* nsegments */ 1211d2bd3ab9SScott Long 0x10000, /* maxsegsize */ 1212d2bd3ab9SScott Long BUS_DMA_WAITOK, /* flags */ 1213d2bd3ab9SScott Long #if __FreeBSD_version>502000 1214d2bd3ab9SScott Long busdma_lock_mutex, /* lockfunc */ 1215d2bd3ab9SScott Long &driver_lock, /* lockfuncarg */ 1216d2bd3ab9SScott Long #endif 1217d2bd3ab9SScott Long &pAdapter->io_dma_parent /* tag */)) 1218d2bd3ab9SScott Long { 1219d2bd3ab9SScott Long return ENXIO;; 12201713e81bSScott Long } 12211713e81bSScott Long 12221713e81bSScott Long 1223d2bd3ab9SScott Long if (hptmv_allocate_edma_queues(pAdapter)) 1224d2bd3ab9SScott Long { 12251713e81bSScott Long MV_ERROR("RR182x: Failed to allocate memory for EDMA queues\n"); 1226d2bd3ab9SScott Long return ENOMEM; 12271713e81bSScott Long } 12281713e81bSScott Long 12291713e81bSScott Long /* also map EPROM address */ 12301713e81bSScott Long rid = 0x10; 1231d2bd3ab9SScott Long if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid, 1232d2bd3ab9SScott Long 0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE)) 1233d2bd3ab9SScott Long || 1234d2bd3ab9SScott Long !(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res))) 1235d2bd3ab9SScott Long { 12361713e81bSScott Long MV_ERROR("RR182x: Failed to remap memory space\n"); 1237d2bd3ab9SScott Long hptmv_free_edma_queues(pAdapter); 1238d2bd3ab9SScott Long return ENXIO; 12391713e81bSScott Long } 1240d2bd3ab9SScott Long else 1241d2bd3ab9SScott Long { 1242d2bd3ab9SScott Long KdPrint(("RR182x: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress)); 1243d2bd3ab9SScott Long } 12441713e81bSScott Long 12451713e81bSScott Long pMvSataAdapter->adapterId = num_adapters++; 12461713e81bSScott Long /* get the revision ID */ 1247d2bd3ab9SScott Long pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); 12481713e81bSScott Long pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev); 12491713e81bSScott Long 12501713e81bSScott Long /* init RR182x */ 12511713e81bSScott Long pMvSataAdapter->intCoalThre[0]= 1; 12521713e81bSScott Long pMvSataAdapter->intCoalThre[1]= 1; 12531713e81bSScott Long pMvSataAdapter->intTimeThre[0] = 1; 12541713e81bSScott Long pMvSataAdapter->intTimeThre[1] = 1; 12551713e81bSScott Long pMvSataAdapter->pciCommand = 0x0107E371; 12561713e81bSScott Long pMvSataAdapter->pciSerrMask = 0xd77fe6ul; 12571713e81bSScott Long pMvSataAdapter->pciInterruptMask = 0xd77fe6ul; 12581713e81bSScott Long pMvSataAdapter->mvSataEventNotify = hptmv_event_notify; 12591713e81bSScott Long 1260d2bd3ab9SScott Long if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) 1261d2bd3ab9SScott Long { 12621713e81bSScott Long MV_ERROR("RR182x[%d]: core failed to initialize the adapter\n", 12631713e81bSScott Long pMvSataAdapter->adapterId); 1264d2bd3ab9SScott Long unregister: 1265d2bd3ab9SScott Long bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res); 1266d2bd3ab9SScott Long hptmv_free_edma_queues(pAdapter); 1267d2bd3ab9SScott Long return ENXIO; 12681713e81bSScott Long } 12691713e81bSScott Long pAdapter->ver_601 = pMvSataAdapter->pcbVersion; 12701713e81bSScott Long 12711713e81bSScott Long #ifndef FOR_DEMO 12721713e81bSScott Long set_fail_leds(pMvSataAdapter, 0); 12731713e81bSScott Long #endif 12741713e81bSScott Long 12751713e81bSScott Long /* setup command blocks */ 12761713e81bSScott Long KdPrint(("Allocate command blocks\n")); 12771713e81bSScott Long _vbus_(pFreeCommands) = 0; 1278d2bd3ab9SScott Long pAdapter->pCommandBlocks = 1279d2bd3ab9SScott Long malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT); 12807d9aed9cSScott Long KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks)); 1281d2bd3ab9SScott Long if (!pAdapter->pCommandBlocks) { 1282d2bd3ab9SScott Long MV_ERROR("insufficient memory\n"); 1283d2bd3ab9SScott Long goto unregister; 12841713e81bSScott Long } 12851713e81bSScott Long 1286d2bd3ab9SScott Long for (i=0; i<MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) { 1287d2bd3ab9SScott Long FreeCommand(_VBUS_P &(pAdapter->pCommandBlocks[i])); 1288d2bd3ab9SScott Long } 1289d2bd3ab9SScott Long 1290d2bd3ab9SScott Long /*Set up the bus_dmamap*/ 1291d2bd3ab9SScott Long pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT); 1292d2bd3ab9SScott Long if(!pAdapter->pbus_dmamap) { 1293d2bd3ab9SScott Long MV_ERROR("insufficient memory\n"); 1294d2bd3ab9SScott Long free(pAdapter->pCommandBlocks, M_DEVBUF); 1295d2bd3ab9SScott Long goto unregister; 1296d2bd3ab9SScott Long } 1297d2bd3ab9SScott Long 1298d2bd3ab9SScott Long memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM); 1299d2bd3ab9SScott Long pAdapter->pbus_dmamap_list = 0; 1300d2bd3ab9SScott Long for (i=0; i < MAX_QUEUE_COMM; i++) { 1301d2bd3ab9SScott Long PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]); 1302d2bd3ab9SScott Long pmap->pAdapter = pAdapter; 1303d2bd3ab9SScott Long dmamap_put(pmap); 1304d2bd3ab9SScott Long 1305d2bd3ab9SScott Long if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) { 1306d2bd3ab9SScott Long MV_ERROR("Can not allocate dma map\n"); 1307d2bd3ab9SScott Long free(pAdapter->pCommandBlocks, M_DEVBUF); 1308d2bd3ab9SScott Long free(pAdapter->pbus_dmamap, M_DEVBUF); 1309d2bd3ab9SScott Long goto unregister; 1310d2bd3ab9SScott Long } 1311d2bd3ab9SScott Long } 13121713e81bSScott Long /* setup PRD Tables */ 13131713e81bSScott Long KdPrint(("Allocate PRD Tables\n")); 13141713e81bSScott Long pAdapter->pFreePRDLink = 0; 13151713e81bSScott Long 1316d2bd3ab9SScott Long pAdapter->prdTableAddr = (PUCHAR)contigmalloc( 1317d2bd3ab9SScott Long (PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); 13181713e81bSScott Long 13197d9aed9cSScott Long KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr)); 13201713e81bSScott Long if (!pAdapter->prdTableAddr) { 13211713e81bSScott Long MV_ERROR("insufficient PRD Tables\n"); 13221713e81bSScott Long goto unregister; 13231713e81bSScott Long } 1324d2bd3ab9SScott Long pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL); 1325d2bd3ab9SScott Long { 1326d2bd3ab9SScott Long PUCHAR PRDTable = pAdapter->prdTableAlignedAddr; 1327d2bd3ab9SScott Long for (i=0; i<PRD_TABLES_FOR_VBUS; i++) 1328d2bd3ab9SScott Long { 1329d2bd3ab9SScott Long /* KdPrint(("i=%d,pAdapter->pFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */ 13301713e81bSScott Long FreePRDTable(pAdapter, PRDTable); 13311713e81bSScott Long PRDTable += PRD_ENTRIES_SIZE; 13321713e81bSScott Long } 1333d2bd3ab9SScott Long } 13341713e81bSScott Long 13351713e81bSScott Long /* enable the adapter interrupts */ 13361713e81bSScott Long 13371713e81bSScott Long /* configure and start the connected channels*/ 1338d2bd3ab9SScott Long for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) 1339d2bd3ab9SScott Long { 13401713e81bSScott Long pAdapter->mvChannel[channel].online = MV_FALSE; 13411713e81bSScott Long if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) 1342d2bd3ab9SScott Long == MV_TRUE) 1343d2bd3ab9SScott Long { 13441713e81bSScott Long KdPrint(("RR182x[%d]: channel %d is connected\n", 13451713e81bSScott Long pMvSataAdapter->adapterId, channel)); 13461713e81bSScott Long 1347d2bd3ab9SScott Long if (hptmv_init_channel(pAdapter, channel) == 0) 1348d2bd3ab9SScott Long { 1349d2bd3ab9SScott Long if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE) 1350d2bd3ab9SScott Long { 1351d2bd3ab9SScott Long MV_ERROR("RR182x[%d]: Failed to configure channel" 1352d2bd3ab9SScott Long " %d\n",pMvSataAdapter->adapterId, channel); 13531713e81bSScott Long hptmv_free_channel(pAdapter, channel); 13541713e81bSScott Long } 1355d2bd3ab9SScott Long else 1356d2bd3ab9SScott Long { 1357d2bd3ab9SScott Long if (start_channel(pAdapter, channel)) 1358d2bd3ab9SScott Long { 13591713e81bSScott Long MV_ERROR("RR182x[%d]: Failed to start channel," 13601713e81bSScott Long " channel=%d\n",pMvSataAdapter->adapterId, 13611713e81bSScott Long channel); 13621713e81bSScott Long hptmv_free_channel(pAdapter, channel); 13631713e81bSScott Long } 13641713e81bSScott Long pAdapter->mvChannel[channel].online = MV_TRUE; 1365d2bd3ab9SScott Long /* mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter, 1366d2bd3ab9SScott Long channel, 1367d2bd3ab9SScott Long MV_TRUE);*/ 1368d2bd3ab9SScott Long } 1369d2bd3ab9SScott Long } 13701713e81bSScott Long } 13711713e81bSScott Long KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n", 13721713e81bSScott Long pAdapter->mvChannel[channel].online, channel)); 13731713e81bSScott Long } 13741713e81bSScott Long 13751713e81bSScott Long #ifdef SUPPORT_ARRAY 13761713e81bSScott Long for(i = MAX_ARRAY_DEVICE - 1; i >= 0; i--) { 13771713e81bSScott Long pVDev = ArrayTables(i); 13781713e81bSScott Long mArFreeArrayTable(pVDev); 13791713e81bSScott Long } 13801713e81bSScott Long #endif 13811713e81bSScott Long 13821713e81bSScott Long KdPrint(("Initialize Devices\n")); 13831713e81bSScott Long for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { 1384d2bd3ab9SScott Long MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 13851713e81bSScott Long if (pMvSataChannel) { 13861713e81bSScott Long init_vdev_params(pAdapter, channel); 13871713e81bSScott Long IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk); 13881713e81bSScott Long } 13891713e81bSScott Long } 13901713e81bSScott Long #ifdef SUPPORT_ARRAY 13911713e81bSScott Long CheckArrayCritical(_VBUS_P0); 13921713e81bSScott Long #endif 13931713e81bSScott Long _vbus_p->nInstances = 1; 13941713e81bSScott Long fRegisterVdevice(pAdapter); 13951713e81bSScott Long 13961713e81bSScott Long for (channel=0;channel<MV_SATA_CHANNELS_NUM;channel++) { 13971713e81bSScott Long pVDev = _vbus_p->pVDevice[channel]; 13981713e81bSScott Long if (pVDev && pVDev->vf_online) 13991713e81bSScott Long fCheckBootable(pVDev); 14001713e81bSScott Long } 14011713e81bSScott Long 14021713e81bSScott Long #if defined(SUPPORT_ARRAY) && defined(_RAID5N_) 14031713e81bSScott Long init_raid5_memory(_VBUS_P0); 14041713e81bSScott Long _vbus_(r5).enable_write_back = 1; 1405d2bd3ab9SScott Long printf("RR182x: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled"); 14061713e81bSScott Long #endif 14071713e81bSScott Long 14081713e81bSScott Long mvSataUnmaskAdapterInterrupt(pMvSataAdapter); 14091713e81bSScott Long return 0; 14101713e81bSScott Long } 14111713e81bSScott Long 14121713e81bSScott Long int 14131713e81bSScott Long MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) 14141713e81bSScott Long { 14151713e81bSScott Long IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; 14161713e81bSScott Long 14171713e81bSScott Long mvSataDisableChannelDma(pMvSataAdapter, channel); 14181713e81bSScott Long /* Flush pending commands */ 14191713e81bSScott Long mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 14201713e81bSScott Long 14211713e81bSScott Long /* Software reset channel */ 1422d2bd3ab9SScott Long if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE) 1423d2bd3ab9SScott Long { 14241713e81bSScott Long MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n", 14251713e81bSScott Long pMvSataAdapter->adapterId, channel); 1426d2bd3ab9SScott Long hptmv_free_channel(pAdapter, channel); 14271713e81bSScott Long return -1; 14281713e81bSScott Long } 14291713e81bSScott Long 14301713e81bSScott Long /* Hardware reset channel */ 1431d2bd3ab9SScott Long if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) 1432d2bd3ab9SScott Long { 1433d2bd3ab9SScott Long MV_ERROR("RR182x [%d,%d] Failed to Hard reser the SATA channel\n", 1434d2bd3ab9SScott Long pMvSataAdapter->adapterId, channel); 14351713e81bSScott Long hptmv_free_channel(pAdapter, channel); 14361713e81bSScott Long return -1; 14371713e81bSScott Long } 14381713e81bSScott Long 1439d2bd3ab9SScott Long if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE) 1440d2bd3ab9SScott Long { 14411713e81bSScott Long MV_ERROR("RR182x [%d,%d] Failed to Connect Device\n", 14421713e81bSScott Long pMvSataAdapter->adapterId, channel); 14431713e81bSScott Long hptmv_free_channel(pAdapter, channel); 14441713e81bSScott Long return -1; 1445d2bd3ab9SScott Long }else 1446d2bd3ab9SScott Long { 1447d2bd3ab9SScott Long MV_ERROR("channel %d: perform recalibrate command", channel); 1448d2bd3ab9SScott Long if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1449d2bd3ab9SScott Long MV_NON_UDMA_PROTOCOL_NON_DATA, 1450d2bd3ab9SScott Long MV_FALSE, 1451d2bd3ab9SScott Long NULL, /* pBuffer*/ 1452d2bd3ab9SScott Long 0, /* count */ 1453d2bd3ab9SScott Long 0, /*features*/ 1454d2bd3ab9SScott Long /* sectorCount */ 1455d2bd3ab9SScott Long 0, 1456d2bd3ab9SScott Long 0, /* lbaLow */ 1457d2bd3ab9SScott Long 0, /* lbaMid */ 1458d2bd3ab9SScott Long /* lbaHigh */ 1459d2bd3ab9SScott Long 0, 1460d2bd3ab9SScott Long 0, /* device */ 1461d2bd3ab9SScott Long /* command */ 1462d2bd3ab9SScott Long 0x10)) 1463d2bd3ab9SScott Long MV_ERROR("channel %d: recalibrate failed", channel); 1464d2bd3ab9SScott Long 14651713e81bSScott Long /* Set transfer mode */ 14661713e81bSScott Long if((mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1467d2bd3ab9SScott Long MV_ATA_SET_FEATURES_TRANSFER, 1468d2bd3ab9SScott Long MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) || 14691713e81bSScott Long (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 14701713e81bSScott Long MV_ATA_SET_FEATURES_TRANSFER, 1471d2bd3ab9SScott Long pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) || 1472d2bd3ab9SScott Long (mvStorageDevATASetFeatures(pMvSataAdapter, channel, 1473d2bd3ab9SScott Long MV_ATA_SET_FEATURES_TRANSFER, 1474d2bd3ab9SScott Long pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) ) 1475d2bd3ab9SScott Long { 14761713e81bSScott Long MV_ERROR("channel %d: Set Features failed", channel); 14771713e81bSScott Long hptmv_free_channel(pAdapter, channel); 14781713e81bSScott Long return -1; 14791713e81bSScott Long } 14801713e81bSScott Long /* Enable EDMA */ 1481d2bd3ab9SScott Long if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE) 1482d2bd3ab9SScott Long { 14831713e81bSScott Long MV_ERROR("Failed to enable DMA, channel=%d", channel); 14841713e81bSScott Long hptmv_free_channel(pAdapter, channel); 14851713e81bSScott Long return -1; 14861713e81bSScott Long } 14871713e81bSScott Long } 14881713e81bSScott Long return 0; 14891713e81bSScott Long } 14901713e81bSScott Long 14911713e81bSScott Long static int 14921713e81bSScott Long fResetActiveCommands(PVBus _vbus_p) 14931713e81bSScott Long { 1494d2bd3ab9SScott Long MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 14951713e81bSScott Long MV_U8 channel; 14961713e81bSScott Long for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 1497d2bd3ab9SScott Long if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands) 1498d2bd3ab9SScott Long MvSataResetChannel(pMvSataAdapter,channel); 14991713e81bSScott Long } 15001713e81bSScott Long return 0; 15011713e81bSScott Long } 15021713e81bSScott Long 1503d2bd3ab9SScott Long void fCompleteAllCommandsSynchronously(PVBus _vbus_p) 15041713e81bSScott Long { 15051713e81bSScott Long UINT cont; 15061713e81bSScott Long ULONG ticks = 0; 15071713e81bSScott Long MV_U8 channel; 1508d2bd3ab9SScott Long MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; 15091713e81bSScott Long MV_SATA_CHANNEL *pMvSataChannel; 15101713e81bSScott Long 15111713e81bSScott Long do { 15121713e81bSScott Long check_cmds: 15131713e81bSScott Long cont = 0; 15141713e81bSScott Long CheckPendingCall(_VBUS_P0); 15151713e81bSScott Long #ifdef _RAID5N_ 15161713e81bSScott Long dataxfer_poll(); 15171713e81bSScott Long xor_poll(); 15181713e81bSScott Long #endif 15191713e81bSScott Long for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { 15201713e81bSScott Long pMvSataChannel = pMvSataAdapter->sataChannel[channel]; 1521d2bd3ab9SScott Long if (pMvSataChannel && pMvSataChannel->outstandingCommands) 1522d2bd3ab9SScott Long { 15231713e81bSScott Long while (pMvSataChannel->outstandingCommands) { 1524d2bd3ab9SScott Long if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) { 15251713e81bSScott Long StallExec(1000); 15261713e81bSScott Long if (ticks++ > 3000) { 1527d2bd3ab9SScott Long MvSataResetChannel(pMvSataAdapter,channel); 15281713e81bSScott Long goto check_cmds; 15291713e81bSScott Long } 1530d2bd3ab9SScott Long } 1531d2bd3ab9SScott Long else 15321713e81bSScott Long ticks = 0; 15331713e81bSScott Long } 15341713e81bSScott Long cont = 1; 15351713e81bSScott Long } 15361713e81bSScott Long } 15371713e81bSScott Long } while (cont); 15381713e81bSScott Long } 15391713e81bSScott Long 15401713e81bSScott Long void 15411713e81bSScott Long fResetVBus(_VBUS_ARG0) 15421713e81bSScott Long { 15437d9aed9cSScott Long KdPrint(("fMvResetBus(%p)", _vbus_p)); 15441713e81bSScott Long 15451713e81bSScott Long /* some commands may already finished. */ 15461713e81bSScott Long CheckPendingCall(_VBUS_P0); 15471713e81bSScott Long 15481713e81bSScott Long fResetActiveCommands(_vbus_p); 15491713e81bSScott Long /* 15501713e81bSScott Long * the other pending commands may still be finished successfully. 15511713e81bSScott Long */ 15521713e81bSScott Long fCompleteAllCommandsSynchronously(_vbus_p); 15531713e81bSScott Long 15541713e81bSScott Long /* Now there should be no pending commands. No more action needed. */ 15551713e81bSScott Long CheckIdleCall(_VBUS_P0); 15561713e81bSScott Long 15571713e81bSScott Long KdPrint(("fMvResetBus() done")); 15581713e81bSScott Long } 15591713e81bSScott Long 1560d2bd3ab9SScott Long /*No rescan function*/ 15611713e81bSScott Long void 15621713e81bSScott Long fRescanAllDevice(_VBUS_ARG0) 15631713e81bSScott Long { 15641713e81bSScott Long } 15651713e81bSScott Long 15661713e81bSScott Long static MV_BOOLEAN 1567d2bd3ab9SScott Long CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, 1568d2bd3ab9SScott Long MV_U8 channelNum, 1569d2bd3ab9SScott Long MV_COMPLETION_TYPE comp_type, 1570d2bd3ab9SScott Long MV_VOID_PTR commandId, 1571d2bd3ab9SScott Long MV_U16 responseFlags, 1572d2bd3ab9SScott Long MV_U32 timeStamp, 1573d2bd3ab9SScott Long MV_STORAGE_DEVICE_REGISTERS *registerStruct) 15741713e81bSScott Long { 15751713e81bSScott Long PCommand pCmd = (PCommand) commandId; 15761713e81bSScott Long _VBUS_INST(pCmd->pVDevice->pVBus) 15771713e81bSScott Long 15781713e81bSScott Long if (pCmd->uScratch.sata_param.prdAddr) 1579d2bd3ab9SScott Long FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr); 15801713e81bSScott Long 1581d2bd3ab9SScott Long switch (comp_type) 1582d2bd3ab9SScott Long { 15831713e81bSScott Long case MV_COMPLETION_TYPE_NORMAL: 15841713e81bSScott Long pCmd->Result = RETURN_SUCCESS; 15851713e81bSScott Long break; 15861713e81bSScott Long case MV_COMPLETION_TYPE_ABORT: 15871713e81bSScott Long pCmd->Result = RETURN_BUS_RESET; 15881713e81bSScott Long break; 15891713e81bSScott Long case MV_COMPLETION_TYPE_ERROR: 1590d2bd3ab9SScott Long MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n", 1591d2bd3ab9SScott Long pMvSataAdapter->adapterId, channelNum, responseFlags); 15921713e81bSScott Long 15931713e81bSScott Long if (responseFlags & 4) { 1594d2bd3ab9SScott Long MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x," 1595d2bd3ab9SScott Long " LBA high %x, device %x, status %x\n", 1596d2bd3ab9SScott Long registerStruct->errorRegister, 15971713e81bSScott Long registerStruct->sectorCountRegister, 15981713e81bSScott Long registerStruct->lbaLowRegister, 15991713e81bSScott Long registerStruct->lbaMidRegister, 16001713e81bSScott Long registerStruct->lbaHighRegister, 16011713e81bSScott Long registerStruct->deviceRegister, 16021713e81bSScott Long registerStruct->statusRegister); 16031713e81bSScott Long } 1604d2bd3ab9SScott Long /*We can't do handleEdmaError directly here, because CommandCompletionCB is called by 1605d2bd3ab9SScott Long * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/ 16061713e81bSScott Long pCmd->uScratch.sata_param.responseFlags = responseFlags; 1607d2bd3ab9SScott Long pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister; 1608d2bd3ab9SScott Long pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister; 16091713e81bSScott Long pCmd->pVDevice->u.disk.QueueLength--; 16101713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd); 16111713e81bSScott Long return TRUE; 16121713e81bSScott Long 16131713e81bSScott Long default: 16141713e81bSScott Long MV_ERROR(" Unknown completion type (%d)\n", comp_type); 16151713e81bSScott Long return MV_FALSE; 16161713e81bSScott Long } 16171713e81bSScott Long 1618d2bd3ab9SScott Long if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) { 16191713e81bSScott Long pCmd->uScratch.sata_param.cmd_priv --; 16201713e81bSScott Long return TRUE; 16211713e81bSScott Long } 16221713e81bSScott Long pCmd->pVDevice->u.disk.QueueLength--; 16231713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 16241713e81bSScott Long return TRUE; 16251713e81bSScott Long } 16261713e81bSScott Long 16271713e81bSScott Long void 16281713e81bSScott Long fDeviceSendCommand(_VBUS_ARG PCommand pCmd) 16291713e81bSScott Long { 16301713e81bSScott Long MV_SATA_EDMA_PRD_ENTRY *pPRDTable = 0; 16311713e81bSScott Long MV_SATA_ADAPTER *pMvSataAdapter; 16321713e81bSScott Long MV_SATA_CHANNEL *pMvSataChannel; 1633d2bd3ab9SScott Long PVDevice pVDevice = pCmd->pVDevice; 1634d2bd3ab9SScott Long PDevice pDevice = &pVDevice->u.disk; 1635d2bd3ab9SScott Long ULONG Lba = pCmd->uCmd.Ide.Lba; 1636d2bd3ab9SScott Long USHORT nSector = pCmd->uCmd.Ide.nSectors; 1637d2bd3ab9SScott Long 16381713e81bSScott Long MV_QUEUE_COMMAND_RESULT result; 16391713e81bSScott Long MV_QUEUE_COMMAND_INFO commandInfo; 1640d2bd3ab9SScott Long MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand; 1641d2bd3ab9SScott Long MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; 1642d2bd3ab9SScott Long 16431713e81bSScott Long MV_BOOLEAN is48bit = MV_FALSE; 16441713e81bSScott Long MV_U8 channel; 16451713e81bSScott Long int i=0; 16461713e81bSScott Long 16471713e81bSScott Long DECLARE_BUFFER(FPSCAT_GATH, tmpSg); 16481713e81bSScott Long 16491713e81bSScott Long if (!pDevice->df_on_line) { 16501713e81bSScott Long MV_ERROR("Device is offline"); 16511713e81bSScott Long pCmd->Result = RETURN_BAD_DEVICE; 16521713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 16531713e81bSScott Long return; 16541713e81bSScott Long } 16551713e81bSScott Long 16561713e81bSScott Long pDevice->HeadPosition = pCmd->uCmd.Ide.Lba + pCmd->uCmd.Ide.nSectors; 16571713e81bSScott Long pMvSataChannel = pDevice->mv; 16581713e81bSScott Long pMvSataAdapter = pMvSataChannel->mvSataAdapter; 16591713e81bSScott Long channel = pMvSataChannel->channelNumber; 16601713e81bSScott Long 1661d2bd3ab9SScott Long /* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */ 16621713e81bSScott Long Lba += pDevice->dDeHiddenLba; 16631713e81bSScott Long /* check LBA */ 16641713e81bSScott Long if (Lba+nSector-1 > pDevice->dDeRealCapacity) { 16651713e81bSScott Long pCmd->Result = RETURN_INVALID_REQUEST; 16661713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 16671713e81bSScott Long return; 16681713e81bSScott Long } 16691713e81bSScott Long 16701713e81bSScott Long if(Lba & 0xF0000000){ 16711713e81bSScott Long is48bit = MV_TRUE; 16721713e81bSScott Long } 16731713e81bSScott Long 1674d2bd3ab9SScott Long switch (pCmd->uCmd.Ide.Command) 1675d2bd3ab9SScott Long { 16761713e81bSScott Long case IDE_COMMAND_READ: 16771713e81bSScott Long case IDE_COMMAND_WRITE: 16781713e81bSScott Long if (pDevice->bDeModeSetting<8) goto pio; 16791713e81bSScott Long 16801713e81bSScott Long commandInfo.type = MV_QUEUED_COMMAND_TYPE_UDMA; 16811713e81bSScott Long pUdmaParams->isEXT = is48bit; 16821713e81bSScott Long pUdmaParams->numOfSectors = nSector; 16831713e81bSScott Long pUdmaParams->lowLBAAddress = Lba; 16841713e81bSScott Long pUdmaParams->highLBAAddress = 0; 16851713e81bSScott Long pUdmaParams->prdHighAddr = 0; 16861713e81bSScott Long pUdmaParams->callBack = CommandCompletionCB; 16871713e81bSScott Long pUdmaParams->commandId = (MV_VOID_PTR )pCmd; 16881713e81bSScott Long if(pCmd->uCmd.Ide.Command == IDE_COMMAND_READ) 16891713e81bSScott Long pUdmaParams->readWrite = MV_UDMA_TYPE_READ; 16901713e81bSScott Long else 16911713e81bSScott Long pUdmaParams->readWrite = MV_UDMA_TYPE_WRITE; 16921713e81bSScott Long 16931713e81bSScott Long if (pCmd->pSgTable && pCmd->cf_physical_sg) { 16941713e81bSScott Long FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1695d2bd3ab9SScott Long do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1696d2bd3ab9SScott Long } 1697d2bd3ab9SScott Long else { 1698d2bd3ab9SScott Long if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { 16991713e81bSScott Long pio: 17001713e81bSScott Long mvSataDisableChannelDma(pMvSataAdapter, channel); 1701d2bd3ab9SScott Long mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); 17021713e81bSScott Long 17031713e81bSScott Long if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { 17041713e81bSScott Long FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; 1705d2bd3ab9SScott Long do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); 1706d2bd3ab9SScott Long } 1707d2bd3ab9SScott Long else { 1708d2bd3ab9SScott Long if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) { 17091713e81bSScott Long pCmd->Result = RETURN_NEED_LOGICAL_SG; 17101713e81bSScott Long goto finish_cmd; 17111713e81bSScott Long } 1712d2bd3ab9SScott Long } 17131713e81bSScott Long 17141713e81bSScott Long do { 1715d2bd3ab9SScott Long ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; 17161713e81bSScott Long ULONG_PTR addr = tmpSg->dSgAddress; 17171713e81bSScott Long if (size & 0x1ff) { 17181713e81bSScott Long pCmd->Result = RETURN_INVALID_REQUEST; 17191713e81bSScott Long goto finish_cmd; 17201713e81bSScott Long } 1721d2bd3ab9SScott Long if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, 1722d2bd3ab9SScott Long (pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, 1723d2bd3ab9SScott Long is48bit, 1724d2bd3ab9SScott Long (MV_U16_PTR)addr, 17251713e81bSScott Long size >> 1, /* count */ 17261713e81bSScott Long 0, /* features N/A */ 17271713e81bSScott Long (MV_U16)(size>>9), /*sector count*/ 1728d2bd3ab9SScott Long (MV_U16)( (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | (UCHAR)(Lba & 0xFF) ), /*lbalow*/ 17291713e81bSScott Long (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ 1730d2bd3ab9SScott Long (MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh */ 1731d2bd3ab9SScott Long (MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device */ 1732d2bd3ab9SScott Long (MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command) 1733d2bd3ab9SScott Long )==MV_FALSE) 1734d2bd3ab9SScott Long { 17351713e81bSScott Long pCmd->Result = RETURN_IDE_ERROR; 17361713e81bSScott Long goto finish_cmd; 17371713e81bSScott Long } 17381713e81bSScott Long Lba += size>>9; 17391713e81bSScott Long if(Lba & 0xF0000000) is48bit = MV_TRUE; 17401713e81bSScott Long } 17411713e81bSScott Long while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 17421713e81bSScott Long pCmd->Result = RETURN_SUCCESS; 17431713e81bSScott Long finish_cmd: 17441713e81bSScott Long mvSataEnableChannelDma(pMvSataAdapter,channel); 1745d2bd3ab9SScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 17461713e81bSScott Long return; 17471713e81bSScott Long } 1748d2bd3ab9SScott Long } 17491713e81bSScott Long 1750d2bd3ab9SScott Long pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData); 17517d9aed9cSScott Long KdPrint(("pPRDTable:%p\n",pPRDTable)); 17521713e81bSScott Long if (!pPRDTable) { 17531713e81bSScott Long pCmd->Result = RETURN_DEVICE_BUSY; 1754d2bd3ab9SScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 17551713e81bSScott Long HPT_ASSERT(0); 17561713e81bSScott Long return; 17571713e81bSScott Long } 17581713e81bSScott Long 17591713e81bSScott Long do{ 1760d2bd3ab9SScott Long pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0); 17611713e81bSScott Long pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag; 17621713e81bSScott Long pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize; 17631713e81bSScott Long pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress; 17641713e81bSScott Long pPRDTable[i].reserved = 0; 17651713e81bSScott Long i++; 17661713e81bSScott Long }while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); 17671713e81bSScott Long 1768d2bd3ab9SScott Long pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable); 1769d2bd3ab9SScott Long if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) { 17701713e81bSScott Long pUdmaParams->numOfSectors = 0; 17711713e81bSScott Long } 17721713e81bSScott Long 17731713e81bSScott Long pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable; 17741713e81bSScott Long 1775d2bd3ab9SScott Long result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 17761713e81bSScott Long 1777d2bd3ab9SScott Long if (result != MV_QUEUE_COMMAND_RESULT_OK) 1778d2bd3ab9SScott Long { 17791713e81bSScott Long queue_failed: 1780d2bd3ab9SScott Long switch (result) 1781d2bd3ab9SScott Long { 17821713e81bSScott Long case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS: 1783d2bd3ab9SScott Long MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA " 1784d2bd3ab9SScott Long "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress); 17851713e81bSScott Long pCmd->Result = RETURN_IDE_ERROR; 17861713e81bSScott Long break; 17871713e81bSScott Long case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED: 1788d2bd3ab9SScott Long MV_ERROR("IAL Error: Edma Queue command failed. EDMA" 1789d2bd3ab9SScott Long " disabled adapter %d channel %d\n", 17901713e81bSScott Long pMvSataAdapter->adapterId, channel); 17911713e81bSScott Long mvSataEnableChannelDma(pMvSataAdapter,channel); 17921713e81bSScott Long pCmd->Result = RETURN_IDE_ERROR; 17931713e81bSScott Long break; 17941713e81bSScott Long case MV_QUEUE_COMMAND_RESULT_FULL: 1795d2bd3ab9SScott Long MV_ERROR("IAL Error: Edma Queue command failed. Queue is" 1796d2bd3ab9SScott Long " Full adapter %d channel %d\n", 17971713e81bSScott Long pMvSataAdapter->adapterId, channel); 17981713e81bSScott Long pCmd->Result = RETURN_DEVICE_BUSY; 17991713e81bSScott Long break; 18001713e81bSScott Long case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS: 1801d2bd3ab9SScott Long MV_ERROR("IAL Error: Edma Queue command failed. (Bad " 1802d2bd3ab9SScott Long "Params), pMvSataAdapter: %p, pSataChannel: %p.\n", 1803d2bd3ab9SScott Long pMvSataAdapter, pMvSataAdapter->sataChannel[channel]); 18041713e81bSScott Long pCmd->Result = RETURN_IDE_ERROR; 18051713e81bSScott Long break; 18061713e81bSScott Long default: 1807d2bd3ab9SScott Long MV_ERROR("IAL Error: Bad result value (%d) from queue" 1808d2bd3ab9SScott Long " command\n", result); 18091713e81bSScott Long pCmd->Result = RETURN_IDE_ERROR; 18101713e81bSScott Long } 18111713e81bSScott Long if(pPRDTable) 1812d2bd3ab9SScott Long FreePRDTable(pMvSataAdapter->IALData,pPRDTable); 1813d2bd3ab9SScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 18141713e81bSScott Long } 18151713e81bSScott Long pDevice->QueueLength++; 18161713e81bSScott Long return; 18171713e81bSScott Long 18181713e81bSScott Long case IDE_COMMAND_VERIFY: 18191713e81bSScott Long commandInfo.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA; 18201713e81bSScott Long pNoUdmaParams->bufPtr = NULL; 18211713e81bSScott Long pNoUdmaParams->callBack = CommandCompletionCB; 18221713e81bSScott Long pNoUdmaParams->commandId = (MV_VOID_PTR)pCmd; 18231713e81bSScott Long pNoUdmaParams->count = 0; 18241713e81bSScott Long pNoUdmaParams->features = 0; 18251713e81bSScott Long pNoUdmaParams->protocolType = MV_NON_UDMA_PROTOCOL_NON_DATA; 18261713e81bSScott Long 18271713e81bSScott Long pCmd->uScratch.sata_param.cmd_priv = 1; 18281713e81bSScott Long if (pMvSataChannel->lba48Address == MV_TRUE){ 1829d2bd3ab9SScott Long pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; 18301713e81bSScott Long pNoUdmaParams->isEXT = MV_TRUE; 1831d2bd3ab9SScott Long pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 18321713e81bSScott Long pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 18331713e81bSScott Long pNoUdmaParams->lbaLow = 18341713e81bSScott Long (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); 18351713e81bSScott Long pNoUdmaParams->sectorCount = nSector; 18361713e81bSScott Long pNoUdmaParams->device = 0x40; 1837d2bd3ab9SScott Long result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 18381713e81bSScott Long if (result != MV_QUEUE_COMMAND_RESULT_OK){ 18391713e81bSScott Long goto queue_failed; 18401713e81bSScott Long } 18411713e81bSScott Long return; 18421713e81bSScott Long } 1843d2bd3ab9SScott Long else{ 18441713e81bSScott Long pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; 18451713e81bSScott Long pNoUdmaParams->isEXT = MV_FALSE; 18461713e81bSScott Long pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); 18471713e81bSScott Long pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); 18481713e81bSScott Long pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); 18491713e81bSScott Long pNoUdmaParams->sectorCount = 0xff & nSector; 18501713e81bSScott Long pNoUdmaParams->device = (MV_U8)(0x40 | 18511713e81bSScott Long ((Lba & 0xf000000) >> 24)); 18521713e81bSScott Long pNoUdmaParams->callBack = CommandCompletionCB; 1853d2bd3ab9SScott Long result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); 1854d2bd3ab9SScott Long /*FIXME: how about the commands already queued? but marvel also forgets to consider this*/ 18551713e81bSScott Long if (result != MV_QUEUE_COMMAND_RESULT_OK){ 18561713e81bSScott Long goto queue_failed; 18571713e81bSScott Long } 1858d2bd3ab9SScott Long } 18591713e81bSScott Long break; 18601713e81bSScott Long default: 18611713e81bSScott Long pCmd->Result = RETURN_INVALID_REQUEST; 18621713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); 18631713e81bSScott Long break; 18641713e81bSScott Long } 18651713e81bSScott Long } 18661713e81bSScott Long 18671713e81bSScott Long /********************************************************** 18681713e81bSScott Long * 18691713e81bSScott Long * Probe the hostadapter. 18701713e81bSScott Long * 18711713e81bSScott Long **********************************************************/ 18721713e81bSScott Long static int 18731713e81bSScott Long hpt_probe(device_t dev) 18741713e81bSScott Long { 18751713e81bSScott Long if ((pci_get_vendor(dev) == MV_SATA_VENDOR_ID) && 18761713e81bSScott Long (pci_get_device(dev) == MV_SATA_DEVICE_ID_5081 18771713e81bSScott Long #ifdef FOR_DEMO 18781713e81bSScott Long || pci_get_device(dev) == MV_SATA_DEVICE_ID_5080 18791713e81bSScott Long #endif 1880d2bd3ab9SScott Long )) 1881d2bd3ab9SScott Long { 18821713e81bSScott Long KdPrintI((CONTROLLER_NAME " found\n")); 18831713e81bSScott Long device_set_desc(dev, CONTROLLER_NAME); 18841713e81bSScott Long return 0; 18851713e81bSScott Long } 18861713e81bSScott Long else 18871713e81bSScott Long return(ENXIO); 18881713e81bSScott Long } 18891713e81bSScott Long 18901713e81bSScott Long /*********************************************************** 18911713e81bSScott Long * 18921713e81bSScott Long * Auto configuration: attach and init a host adapter. 18931713e81bSScott Long * 18941713e81bSScott Long ***********************************************************/ 18951713e81bSScott Long static int 18961713e81bSScott Long hpt_attach(device_t dev) 18971713e81bSScott Long { 1898d2bd3ab9SScott Long IAL_ADAPTER_T * pAdapter = device_get_softc(dev); 18991713e81bSScott Long int rid; 19001713e81bSScott Long union ccb *ccb; 19011713e81bSScott Long struct cam_devq *devq; 19021713e81bSScott Long struct cam_sim *hpt_vsim; 19031713e81bSScott Long 19041713e81bSScott Long printf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION); 19051713e81bSScott Long 1906d2bd3ab9SScott Long if (!pAdapter) 1907d2bd3ab9SScott Long { 1908d2bd3ab9SScott Long pAdapter = (IAL_ADAPTER_T *)malloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT); 1909d2bd3ab9SScott Long #if __FreeBSD_version > 410000 1910d2bd3ab9SScott Long device_set_softc(dev, (void *)pAdapter); 1911d2bd3ab9SScott Long #else 1912d2bd3ab9SScott Long device_set_driver(dev, (driver_t *)pAdapter); 1913d2bd3ab9SScott Long #endif 1914d2bd3ab9SScott Long } 1915d2bd3ab9SScott Long 1916d2bd3ab9SScott Long if (!pAdapter) return (ENOMEM); 1917d2bd3ab9SScott Long bzero(pAdapter, sizeof(IAL_ADAPTER_T)); 1918d2bd3ab9SScott Long 19191713e81bSScott Long pAdapter->hpt_dev = dev; 19201713e81bSScott Long 19211713e81bSScott Long rid = init_adapter(pAdapter); 19221713e81bSScott Long if (rid) 19231713e81bSScott Long return rid; 19241713e81bSScott Long 19251713e81bSScott Long rid = 0; 1926d2bd3ab9SScott Long if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1927d2bd3ab9SScott Long { 19281713e81bSScott Long hpt_printk(("can't allocate interrupt\n")); 19291713e81bSScott Long return(ENXIO); 19301713e81bSScott Long } 19311713e81bSScott Long 1932ef544f63SPaolo Pisati if(bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr)) 1933d2bd3ab9SScott Long { 19341713e81bSScott Long hpt_printk(("can't set up interrupt\n")); 19351713e81bSScott Long free(pAdapter, M_DEVBUF); 19361713e81bSScott Long return(ENXIO); 19371713e81bSScott Long } 19381713e81bSScott Long 1939d2bd3ab9SScott Long 1940d2bd3ab9SScott Long if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL) 1941d2bd3ab9SScott Long { 1942d2bd3ab9SScott Long bzero(ccb, sizeof(*ccb)); 19431713e81bSScott Long ccb->ccb_h.pinfo.priority = 1; 19441713e81bSScott Long ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; 1945d2bd3ab9SScott Long } 1946d2bd3ab9SScott Long else 1947d2bd3ab9SScott Long { 19481713e81bSScott Long return ENOMEM; 19491713e81bSScott Long } 19501713e81bSScott Long /* 19511713e81bSScott Long * Create the device queue for our SIM(s). 19521713e81bSScott Long */ 1953d2bd3ab9SScott Long if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) 1954d2bd3ab9SScott Long { 19551713e81bSScott Long KdPrint(("ENXIO\n")); 19561713e81bSScott Long return ENOMEM; 19571713e81bSScott Long } 19581713e81bSScott Long 19591713e81bSScott Long /* 19601713e81bSScott Long * Construct our SIM entry 19611713e81bSScott Long */ 19621713e81bSScott Long if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), 1963d2bd3ab9SScott Long pAdapter, device_get_unit(pAdapter->hpt_dev), /*untagged*/1, /*tagged*/8, devq)) == NULL) { 19641713e81bSScott Long cam_simq_free(devq); 19651713e81bSScott Long return ENOMEM; 19661713e81bSScott Long } 19671713e81bSScott Long 1968d2bd3ab9SScott Long if(xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS) 1969d2bd3ab9SScott Long { 19701713e81bSScott Long cam_sim_free(hpt_vsim, /*free devq*/ TRUE); 19711713e81bSScott Long hpt_vsim = NULL; 19721713e81bSScott Long return ENXIO; 19731713e81bSScott Long } 19741713e81bSScott Long 19751713e81bSScott Long if(xpt_create_path(&pAdapter->path, /*periph */ NULL, 1976d2bd3ab9SScott Long cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, 1977d2bd3ab9SScott Long CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1978d2bd3ab9SScott Long { 19791713e81bSScott Long xpt_bus_deregister(cam_sim_path(hpt_vsim)); 19801713e81bSScott Long cam_sim_free(hpt_vsim, /*free_devq*/TRUE); 19811713e81bSScott Long hpt_vsim = NULL; 19821713e81bSScott Long return ENXIO; 19831713e81bSScott Long } 19841713e81bSScott Long 19851713e81bSScott Long xpt_setup_ccb(&(ccb->ccb_h), pAdapter->path, /*priority*/5); 19861713e81bSScott Long ccb->ccb_h.func_code = XPT_SASYNC_CB; 19871713e81bSScott Long ccb->csa.event_enable = AC_LOST_DEVICE; 19881713e81bSScott Long ccb->csa.callback = hpt_async; 19891713e81bSScott Long ccb->csa.callback_arg = hpt_vsim; 19901713e81bSScott Long xpt_action((union ccb *)ccb); 19911713e81bSScott Long free(ccb, M_DEVBUF); 19921713e81bSScott Long 1993d2bd3ab9SScott Long /* Register shutdown handler, and start the work thread. */ 19946e0e5d36SNate Lawson if (device_get_unit(dev) == 0) { 19956e0e5d36SNate Lawson pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_final, 19966e0e5d36SNate Lawson hpt_shutdown, dev, SHUTDOWN_PRI_DEFAULT); 1997d2bd3ab9SScott Long if (pAdapter->eh) 19986e0e5d36SNate Lawson launch_worker_thread(); 19996e0e5d36SNate Lawson else 2000d2bd3ab9SScott Long hpt_printk(("shutdown event registration failed\n")); 20016e0e5d36SNate Lawson } 20021713e81bSScott Long 20031713e81bSScott Long return 0; 20041713e81bSScott Long } 20051713e81bSScott Long 20061713e81bSScott Long static int 20071713e81bSScott Long hpt_detach(device_t dev) 20081713e81bSScott Long { 20091713e81bSScott Long return (EBUSY); 20101713e81bSScott Long } 20111713e81bSScott Long 2012d2bd3ab9SScott Long 20131713e81bSScott Long /*************************************************************** 20141713e81bSScott Long * The poll function is used to simulate the interrupt when 20151713e81bSScott Long * the interrupt subsystem is not functioning. 20161713e81bSScott Long * 20171713e81bSScott Long ***************************************************************/ 20181713e81bSScott Long static void 20191713e81bSScott Long hpt_poll(struct cam_sim *sim) 20201713e81bSScott Long { 20211713e81bSScott Long hpt_intr((void *)cam_sim_softc(sim)); 20221713e81bSScott Long } 20231713e81bSScott Long 20241713e81bSScott Long /**************************************************************** 20251713e81bSScott Long * Name: hpt_intr 20261713e81bSScott Long * Description: Interrupt handler. 20271713e81bSScott Long ****************************************************************/ 20281713e81bSScott Long static void 20291713e81bSScott Long hpt_intr(void *arg) 20301713e81bSScott Long { 20311713e81bSScott Long IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg; 2032d2bd3ab9SScott Long intrmask_t oldspl = lock_driver(); 20331713e81bSScott Long 20341713e81bSScott Long /* KdPrintI(("----- Entering Isr() -----\n")); */ 2035d2bd3ab9SScott Long if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE) 2036d2bd3ab9SScott Long { 20371713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 20381713e81bSScott Long CheckPendingCall(_VBUS_P0); 20391713e81bSScott Long } 20401713e81bSScott Long 20411713e81bSScott Long /* KdPrintI(("----- Leaving Isr() -----\n")); */ 20421713e81bSScott Long unlock_driver(oldspl); 20431713e81bSScott Long } 20441713e81bSScott Long 20451713e81bSScott Long /********************************************************** 20461713e81bSScott Long * Asynchronous Events 20471713e81bSScott Long *********************************************************/ 20481713e81bSScott Long #if (!defined(UNREFERENCED_PARAMETER)) 20491713e81bSScott Long #define UNREFERENCED_PARAMETER(x) (void)(x) 20501713e81bSScott Long #endif 20511713e81bSScott Long 20521713e81bSScott Long static void 20531713e81bSScott Long hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, 20541713e81bSScott Long void * arg) 20551713e81bSScott Long { 20561713e81bSScott Long /* debug XXXX */ 20571713e81bSScott Long panic("Here"); 20581713e81bSScott Long UNREFERENCED_PARAMETER(callback_arg); 20591713e81bSScott Long UNREFERENCED_PARAMETER(code); 20601713e81bSScott Long UNREFERENCED_PARAMETER(path); 20611713e81bSScott Long UNREFERENCED_PARAMETER(arg); 20621713e81bSScott Long 20631713e81bSScott Long } 20641713e81bSScott Long 20651713e81bSScott Long static void 20661713e81bSScott Long FlushAdapter(IAL_ADAPTER_T *pAdapter) 20671713e81bSScott Long { 20681713e81bSScott Long int i; 20691713e81bSScott Long 20701713e81bSScott Long hpt_printk(("flush all devices\n")); 20711713e81bSScott Long 20721713e81bSScott Long /* flush all devices */ 20731713e81bSScott Long for (i=0; i<MAX_VDEVICE_PER_VBUS; i++) { 20741713e81bSScott Long PVDevice pVDev = pAdapter->VBus.pVDevice[i]; 2075d2bd3ab9SScott Long if(pVDev) fFlushVDev(pVDev); 20761713e81bSScott Long } 20771713e81bSScott Long } 20781713e81bSScott Long 20791713e81bSScott Long static int 20801713e81bSScott Long hpt_shutdown(device_t dev) 20811713e81bSScott Long { 20821713e81bSScott Long IAL_ADAPTER_T *pAdapter; 20831713e81bSScott Long 20841713e81bSScott Long pAdapter = device_get_softc(dev); 20851713e81bSScott Long if (pAdapter == NULL) 20861713e81bSScott Long return (EINVAL); 20871713e81bSScott Long 20881713e81bSScott Long EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh); 20891713e81bSScott Long FlushAdapter(pAdapter); 2090d2bd3ab9SScott Long /* give the flush some time to happen, 2091d2bd3ab9SScott Long *otherwise "shutdown -p now" will make file system corrupted */ 2092d2bd3ab9SScott Long DELAY(1000 * 1000 * 5); 20931713e81bSScott Long return 0; 20941713e81bSScott Long } 20951713e81bSScott Long 20961713e81bSScott Long void 20971713e81bSScott Long Check_Idle_Call(IAL_ADAPTER_T *pAdapter) 20981713e81bSScott Long { 20991713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 21001713e81bSScott Long 21011713e81bSScott Long if (mWaitingForIdle(_VBUS_P0)) { 21021713e81bSScott Long CheckIdleCall(_VBUS_P0); 21031713e81bSScott Long #ifdef SUPPORT_ARRAY 2104d2bd3ab9SScott Long { 2105d2bd3ab9SScott Long int i; 21061713e81bSScott Long PVDevice pArray; 2107d2bd3ab9SScott Long for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ 21081713e81bSScott Long if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 21091713e81bSScott Long continue; 21101713e81bSScott Long else if (pArray->u.array.rf_auto_rebuild) { 21111713e81bSScott Long KdPrint(("auto rebuild.\n")); 21121713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0; 2113d2bd3ab9SScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 2114d2bd3ab9SScott Long } 21151713e81bSScott Long } 21161713e81bSScott Long } 21171713e81bSScott Long #endif 21181713e81bSScott Long } 21191713e81bSScott Long /* launch the awaiting commands blocked by mWaitingForIdle */ 2120d2bd3ab9SScott Long while(pAdapter->pending_Q!= NULL) 2121d2bd3ab9SScott Long { 21221713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 2123d2bd3ab9SScott Long union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; 21241713e81bSScott Long hpt_free_ccb(&pAdapter->pending_Q, ccb); 21251713e81bSScott Long CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb); 21261713e81bSScott Long } 21271713e81bSScott Long } 21281713e81bSScott Long 21291713e81bSScott Long static void 21301713e81bSScott Long ccb_done(union ccb *ccb) 21311713e81bSScott Long { 2132d2bd3ab9SScott Long PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2133d2bd3ab9SScott Long IAL_ADAPTER_T * pAdapter = pmap->pAdapter; 2134d2bd3ab9SScott Long KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status)); 21351713e81bSScott Long 2136d2bd3ab9SScott Long dmamap_put(pmap); 21371713e81bSScott Long xpt_done(ccb); 21381713e81bSScott Long 21391713e81bSScott Long pAdapter->outstandingCommands--; 21401713e81bSScott Long 2141d2bd3ab9SScott Long if (pAdapter->outstandingCommands == 0) 2142d2bd3ab9SScott Long { 21431713e81bSScott Long if(DPC_Request_Nums == 0) 21441713e81bSScott Long Check_Idle_Call(pAdapter); 21451713e81bSScott Long } 21461713e81bSScott Long } 21471713e81bSScott Long 21481713e81bSScott Long /**************************************************************** 21491713e81bSScott Long * Name: hpt_action 21501713e81bSScott Long * Description: Process a queued command from the CAM layer. 21511713e81bSScott Long * Parameters: sim - Pointer to SIM object 21521713e81bSScott Long * ccb - Pointer to SCSI command structure. 21531713e81bSScott Long ****************************************************************/ 21541713e81bSScott Long 21551713e81bSScott Long void 21561713e81bSScott Long hpt_action(struct cam_sim *sim, union ccb *ccb) 21571713e81bSScott Long { 21581713e81bSScott Long intrmask_t oldspl; 21591713e81bSScott Long IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim); 2160d2bd3ab9SScott Long PBUS_DMAMAP pmap; 21611713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 21621713e81bSScott Long 2163e1ab829aSScott Long CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n")); 2164d2bd3ab9SScott Long KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code)); 21651713e81bSScott Long 2166d2bd3ab9SScott Long switch (ccb->ccb_h.func_code) 2167d2bd3ab9SScott Long { 21681713e81bSScott Long case XPT_SCSI_IO: /* Execute the requested I/O operation */ 2169d2bd3ab9SScott Long { 21701713e81bSScott Long /* ccb->ccb_h.path_id is not our bus id - don't check it */ 21711713e81bSScott Long 21721713e81bSScott Long if (ccb->ccb_h.target_lun) { 21731713e81bSScott Long ccb->ccb_h.status = CAM_LUN_INVALID; 21741713e81bSScott Long xpt_done(ccb); 21751713e81bSScott Long return; 21761713e81bSScott Long } 21771713e81bSScott Long if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || 21781713e81bSScott Long pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { 21791713e81bSScott Long ccb->ccb_h.status = CAM_TID_INVALID; 21801713e81bSScott Long xpt_done(ccb); 21811713e81bSScott Long return; 21821713e81bSScott Long } 21831713e81bSScott Long 21841713e81bSScott Long oldspl = lock_driver(); 21851713e81bSScott Long if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) 21861713e81bSScott Long Check_Idle_Call(pAdapter); 21871713e81bSScott Long 2188d2bd3ab9SScott Long pmap = dmamap_get(pAdapter); 2189d2bd3ab9SScott Long HPT_ASSERT(pmap); 2190d2bd3ab9SScott Long ccb->ccb_adapter = pmap; 2191d2bd3ab9SScott Long memset((void *)pmap->psg, 0, sizeof(pmap->psg)); 2192d2bd3ab9SScott Long 21931713e81bSScott Long if (mWaitingForIdle(_VBUS_P0)) 21941713e81bSScott Long hpt_queue_ccb(&pAdapter->pending_Q, ccb); 21951713e81bSScott Long else 21961713e81bSScott Long OsSendCommand(_VBUS_P ccb); 21971713e81bSScott Long unlock_driver(oldspl); 21981713e81bSScott Long 21991713e81bSScott Long /* KdPrint(("leave scsiio\n")); */ 22001713e81bSScott Long break; 2201d2bd3ab9SScott Long } 22021713e81bSScott Long 22031713e81bSScott Long case XPT_RESET_BUS: 22041713e81bSScott Long KdPrint(("reset bus\n")); 22051713e81bSScott Long oldspl = lock_driver(); 22061713e81bSScott Long fResetVBus(_VBUS_P0); 22071713e81bSScott Long unlock_driver(oldspl); 22081713e81bSScott Long xpt_done(ccb); 22091713e81bSScott Long break; 22101713e81bSScott Long 22111713e81bSScott Long case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 22121713e81bSScott Long case XPT_EN_LUN: /* Enable LUN as a target */ 22131713e81bSScott Long case XPT_TARGET_IO: /* Execute target I/O request */ 22141713e81bSScott Long case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 22151713e81bSScott Long case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 22161713e81bSScott Long case XPT_ABORT: /* Abort the specified CCB */ 22171713e81bSScott Long case XPT_TERM_IO: /* Terminate the I/O process */ 22181713e81bSScott Long /* XXX Implement */ 22191713e81bSScott Long ccb->ccb_h.status = CAM_REQ_INVALID; 22201713e81bSScott Long xpt_done(ccb); 22211713e81bSScott Long break; 22221713e81bSScott Long 22231713e81bSScott Long case XPT_GET_TRAN_SETTINGS: 22241713e81bSScott Long case XPT_SET_TRAN_SETTINGS: 22251713e81bSScott Long /* XXX Implement */ 22261713e81bSScott Long ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 22271713e81bSScott Long xpt_done(ccb); 22281713e81bSScott Long break; 22291713e81bSScott Long 22301713e81bSScott Long case XPT_CALC_GEOMETRY: 22311713e81bSScott Long { 22321713e81bSScott Long struct ccb_calc_geometry *ccg; 22331713e81bSScott Long u_int32_t size_mb; 22341713e81bSScott Long u_int32_t secs_per_cylinder; 22351713e81bSScott Long 22361713e81bSScott Long ccg = &ccb->ccg; 22371713e81bSScott Long size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); 22381713e81bSScott Long 22391713e81bSScott Long if (size_mb > 1024 ) { 22401713e81bSScott Long ccg->heads = 255; 22411713e81bSScott Long ccg->secs_per_track = 63; 22421713e81bSScott Long } else { 22431713e81bSScott Long ccg->heads = 64; 22441713e81bSScott Long ccg->secs_per_track = 32; 22451713e81bSScott Long } 22461713e81bSScott Long secs_per_cylinder = ccg->heads * ccg->secs_per_track; 22471713e81bSScott Long ccg->cylinders = ccg->volume_size / secs_per_cylinder; 22481713e81bSScott Long ccb->ccb_h.status = CAM_REQ_CMP; 22491713e81bSScott Long xpt_done(ccb); 22501713e81bSScott Long break; 22511713e81bSScott Long } 22521713e81bSScott Long 22531713e81bSScott Long case XPT_PATH_INQ: /* Path routing inquiry */ 22541713e81bSScott Long { 22551713e81bSScott Long struct ccb_pathinq *cpi = &ccb->cpi; 22561713e81bSScott Long 22571713e81bSScott Long cpi->version_num = 1; /* XXX??? */ 22581713e81bSScott Long cpi->hba_inquiry = PI_SDTR_ABLE; 22591713e81bSScott Long cpi->target_sprt = 0; 22601713e81bSScott Long /* Not necessary to reset bus */ 22611713e81bSScott Long cpi->hba_misc = PIM_NOBUSRESET; 22621713e81bSScott Long cpi->hba_eng_cnt = 0; 22631713e81bSScott Long 22641713e81bSScott Long cpi->max_target = MAX_VDEVICE_PER_VBUS; 22651713e81bSScott Long cpi->max_lun = 0; 22661713e81bSScott Long cpi->initiator_id = MAX_VDEVICE_PER_VBUS; 22671713e81bSScott Long 22681713e81bSScott Long cpi->bus_id = cam_sim_bus(sim); 22691713e81bSScott Long cpi->base_transfer_speed = 3300; 22701713e81bSScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 22711713e81bSScott Long strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 22721713e81bSScott Long strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 22731713e81bSScott Long cpi->unit_number = cam_sim_unit(sim); 22741713e81bSScott Long cpi->ccb_h.status = CAM_REQ_CMP; 22751713e81bSScott Long xpt_done(ccb); 22761713e81bSScott Long break; 22771713e81bSScott Long } 22781713e81bSScott Long 22791713e81bSScott Long default: 22801713e81bSScott Long KdPrint(("invalid cmd\n")); 22811713e81bSScott Long ccb->ccb_h.status = CAM_REQ_INVALID; 22821713e81bSScott Long xpt_done(ccb); 22831713e81bSScott Long break; 22841713e81bSScott Long } 22851713e81bSScott Long /* KdPrint(("leave hpt_action..............\n")); */ 22861713e81bSScott Long } 22871713e81bSScott Long 22881713e81bSScott Long /* shall be called at lock_driver() */ 22891713e81bSScott Long static void 22901713e81bSScott Long hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb) 22911713e81bSScott Long { 22921713e81bSScott Long if(*ccb_Q == NULL) 22931713e81bSScott Long ccb->ccb_h.ccb_ccb_ptr = ccb; 22941713e81bSScott Long else { 22951713e81bSScott Long ccb->ccb_h.ccb_ccb_ptr = (*ccb_Q)->ccb_h.ccb_ccb_ptr; 22961713e81bSScott Long (*ccb_Q)->ccb_h.ccb_ccb_ptr = (char *)ccb; 22971713e81bSScott Long } 22981713e81bSScott Long 22991713e81bSScott Long *ccb_Q = ccb; 23001713e81bSScott Long } 23011713e81bSScott Long 23021713e81bSScott Long /* shall be called at lock_driver() */ 23031713e81bSScott Long static void 23041713e81bSScott Long hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb) 23051713e81bSScott Long { 23061713e81bSScott Long union ccb *TempCCB; 23071713e81bSScott Long 23081713e81bSScott Long TempCCB = *ccb_Q; 23091713e81bSScott Long 2310d2bd3ab9SScott Long if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/ 23111713e81bSScott Long *ccb_Q = NULL; 23121713e81bSScott Long else { 23131713e81bSScott Long while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb) 23141713e81bSScott Long TempCCB = (union ccb *)TempCCB->ccb_h.ccb_ccb_ptr; 23151713e81bSScott Long 23161713e81bSScott Long TempCCB->ccb_h.ccb_ccb_ptr = ccb->ccb_h.ccb_ccb_ptr; 23171713e81bSScott Long 23181713e81bSScott Long if(*ccb_Q == ccb) 23191713e81bSScott Long *ccb_Q = TempCCB; 23201713e81bSScott Long } 23211713e81bSScott Long } 23221713e81bSScott Long 23231713e81bSScott Long #ifdef SUPPORT_ARRAY 23241713e81bSScott Long /*************************************************************************** 23251713e81bSScott Long * Function: hpt_worker_thread 23261713e81bSScott Long * Description: Do background rebuilding. Execute in kernel thread context. 23271713e81bSScott Long * Returns: None 23281713e81bSScott Long ***************************************************************************/ 23291713e81bSScott Long static void hpt_worker_thread(void) 23301713e81bSScott Long { 23311713e81bSScott Long intrmask_t oldspl; 23321713e81bSScott Long 23331713e81bSScott Long for(;;) { 23341713e81bSScott Long while (DpcQueue_First!=DpcQueue_Last) { 23351713e81bSScott Long ST_HPT_DPC p; 23361713e81bSScott Long oldspl = lock_driver(); 23371713e81bSScott Long p = DpcQueue[DpcQueue_First]; 23381713e81bSScott Long DpcQueue_First++; 23391713e81bSScott Long DpcQueue_First %= MAX_DPC; 23401713e81bSScott Long DPC_Request_Nums++; 23411713e81bSScott Long unlock_driver(oldspl); 23421713e81bSScott Long p.dpc(p.pAdapter, p.arg, p.flags); 23431713e81bSScott Long 23441713e81bSScott Long oldspl = lock_driver(); 23451713e81bSScott Long DPC_Request_Nums--; 2346d2bd3ab9SScott Long /* since we may have prevented Check_Idle_Call, do it here */ 23471713e81bSScott Long if (DPC_Request_Nums==0) { 23481713e81bSScott Long if (p.pAdapter->outstandingCommands == 0) { 23491713e81bSScott Long _VBUS_INST(&p.pAdapter->VBus); 23501713e81bSScott Long Check_Idle_Call(p.pAdapter); 23511713e81bSScott Long CheckPendingCall(_VBUS_P0); 23521713e81bSScott Long } 23531713e81bSScott Long } 23541713e81bSScott Long unlock_driver(oldspl); 23551713e81bSScott Long 2356d2bd3ab9SScott Long /*Schedule out*/ 2357d2bd3ab9SScott Long #if (__FreeBSD_version < 500000) 2358d2bd3ab9SScott Long YIELD_THREAD; 2359d2bd3ab9SScott Long #else 23604d70511aSJohn Baldwin pause("sched", 1); 2361d2bd3ab9SScott Long #endif 2362d2bd3ab9SScott Long if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) { 23631713e81bSScott Long /* abort rebuilding process. */ 2364d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter; 2365d2bd3ab9SScott Long PVDevice pArray; 2366d2bd3ab9SScott Long PVBus _vbus_p; 2367d2bd3ab9SScott Long int i; 23681713e81bSScott Long pAdapter = gIal_Adapter; 2369d2bd3ab9SScott Long 23701713e81bSScott Long while(pAdapter != 0){ 2371d2bd3ab9SScott Long 23721713e81bSScott Long _vbus_p = &pAdapter->VBus; 2373d2bd3ab9SScott Long 2374d2bd3ab9SScott Long for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 2375d2bd3ab9SScott Long { 23761713e81bSScott Long if ((pArray=ArrayTables(i))->u.array.dArStamp==0) 23771713e81bSScott Long continue; 2378d2bd3ab9SScott Long else if (pArray->u.array.rf_rebuilding || 23791713e81bSScott Long pArray->u.array.rf_verifying || 2380d2bd3ab9SScott Long pArray->u.array.rf_initializing) 2381d2bd3ab9SScott Long { 23821713e81bSScott Long pArray->u.array.rf_abort_rebuild = 1; 23831713e81bSScott Long } 23841713e81bSScott Long } 23851713e81bSScott Long pAdapter = pAdapter->next; 23861713e81bSScott Long } 23871713e81bSScott Long } 2388d2bd3ab9SScott Long } 23891713e81bSScott Long 2390d2bd3ab9SScott Long /*Remove this debug option*/ 2391d2bd3ab9SScott Long /* 23921713e81bSScott Long #ifdef DEBUG 23931713e81bSScott Long if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) 23944d70511aSJohn Baldwin pause("hptrdy", 2*hz); 23951713e81bSScott Long #endif 2396d2bd3ab9SScott Long */ 23971713e81bSScott Long #if (__FreeBSD_version >= 500043) 23981713e81bSScott Long kthread_suspend_check(curproc); 23991713e81bSScott Long #else 24001713e81bSScott Long kproc_suspend_loop(curproc); 24011713e81bSScott Long #endif 24024d70511aSJohn Baldwin pause("hptrdy", 2*hz); /* wait for something to do */ 24031713e81bSScott Long } 24041713e81bSScott Long } 24051713e81bSScott Long 24061713e81bSScott Long static struct proc *hptdaemonproc; 24071713e81bSScott Long static struct kproc_desc hpt_kp = { 24081713e81bSScott Long "hpt_wt", 24091713e81bSScott Long hpt_worker_thread, 24101713e81bSScott Long &hptdaemonproc 24111713e81bSScott Long }; 24121713e81bSScott Long 2413d2bd3ab9SScott Long /*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/ 24141713e81bSScott Long static void 24151713e81bSScott Long launch_worker_thread(void) 24161713e81bSScott Long { 24171713e81bSScott Long IAL_ADAPTER_T *pAdapTemp; 24181713e81bSScott Long 24191713e81bSScott Long kproc_start(&hpt_kp); 24201713e81bSScott Long 24211713e81bSScott Long for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 24221713e81bSScott Long 24231713e81bSScott Long _VBUS_INST(&pAdapTemp->VBus) 24241713e81bSScott Long int i; 24251713e81bSScott Long PVDevice pVDev; 24261713e81bSScott Long 24271713e81bSScott Long for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) 24281713e81bSScott Long if ((pVDev=ArrayTables(i))->u.array.dArStamp==0) 24291713e81bSScott Long continue; 2430d2bd3ab9SScott Long else{ 2431d2bd3ab9SScott Long if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding) 2432d2bd3ab9SScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev, 2433d2bd3ab9SScott Long (UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 24341713e81bSScott Long } 24351713e81bSScott Long } 24361713e81bSScott Long 24371713e81bSScott Long /* 2438d2bd3ab9SScott Long * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished. 24391713e81bSScott Long */ 24401713e81bSScott Long #if (__FreeBSD_version < 500043) 2441d2bd3ab9SScott Long EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST); 24421713e81bSScott Long #else 2443d2bd3ab9SScott Long EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, SHUTDOWN_PRI_FIRST); 24441713e81bSScott Long #endif 24451713e81bSScott Long } 2446d2bd3ab9SScott Long /* 2447d2bd3ab9SScott Long *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL); 2448d2bd3ab9SScott Long */ 24491713e81bSScott Long 2450d2bd3ab9SScott Long #endif 24511713e81bSScott Long 24521713e81bSScott Long /********************************************************************************/ 24531713e81bSScott Long 2454d2bd3ab9SScott Long int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) 24551713e81bSScott Long { 2456d2bd3ab9SScott Long union ccb *ccb = (union ccb *)pCmd->pOrgCommand; 2457d2bd3ab9SScott Long bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 24581713e81bSScott Long int idx; 24591713e81bSScott Long 24601713e81bSScott Long if(logical) { 2461d2bd3ab9SScott Long if (ccb->ccb_h.flags & CAM_DATA_PHYS) 2462d2bd3ab9SScott Long panic("physical address unsupported"); 24631713e81bSScott Long 2464d2bd3ab9SScott Long if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2465d2bd3ab9SScott Long if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 2466d2bd3ab9SScott Long panic("physical address unsupported"); 2467d2bd3ab9SScott Long 2468d2bd3ab9SScott Long for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 2469d2bd3ab9SScott Long pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 2470d2bd3ab9SScott Long pSg[idx].wSgSize = sgList[idx].ds_len; 2471d2bd3ab9SScott Long pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0; 2472d2bd3ab9SScott Long } 2473d2bd3ab9SScott Long } 2474d2bd3ab9SScott Long else { 2475d2bd3ab9SScott Long pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; 2476d2bd3ab9SScott Long pSg->wSgSize = ccb->csio.dxfer_len; 24771713e81bSScott Long pSg->wSgFlag = SG_FLAG_EOT; 2478d2bd3ab9SScott Long } 24791713e81bSScott Long return TRUE; 24801713e81bSScott Long } 24811713e81bSScott Long 2482d2bd3ab9SScott Long /* since we have provided physical sg, nobody will ask us to build physical sg */ 2483d2bd3ab9SScott Long HPT_ASSERT(0); 24841713e81bSScott Long return FALSE; 24851713e81bSScott Long } 24861713e81bSScott Long 24871713e81bSScott Long /*******************************************************************************/ 24881713e81bSScott Long ULONG HPTLIBAPI 24891713e81bSScott Long GetStamp(void) 24901713e81bSScott Long { 24911713e81bSScott Long /* 24921713e81bSScott Long * the system variable, ticks, can't be used since it hasn't yet been active 24931713e81bSScott Long * when our driver starts (ticks==0, it's a invalid stamp value) 24941713e81bSScott Long */ 2495d2bd3ab9SScott Long ULONG stamp; 2496d2bd3ab9SScott Long do { stamp = random(); } while (stamp==0); 24971713e81bSScott Long return stamp; 24981713e81bSScott Long } 24991713e81bSScott Long 25001713e81bSScott Long 25011713e81bSScott Long static void 25021713e81bSScott Long SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) 25031713e81bSScott Long { 25041713e81bSScott Long int i; 2505d2bd3ab9SScott Long IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; 25061713e81bSScott Long 25071713e81bSScott Long inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/ 25081713e81bSScott Long inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5); 25091713e81bSScott Long #ifndef SERIAL_CMDS 25101713e81bSScott Long inquiryData->CommandQueue = 1; 25111713e81bSScott Long #endif 25121713e81bSScott Long 25131713e81bSScott Long switch(pVDev->VDeviceType) { 25141713e81bSScott Long case VD_SINGLE_DISK: 25151713e81bSScott Long case VD_ATAPI: 25161713e81bSScott Long case VD_REMOVABLE: 25171713e81bSScott Long /* Set the removable bit, if applicable. */ 2518d2bd3ab9SScott Long if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80)) 25191713e81bSScott Long inquiryData->RemovableMedia = 1; 25201713e81bSScott Long 25211713e81bSScott Long /* Fill in vendor identification fields. */ 2522d2bd3ab9SScott Long for (i = 0; i < 20; i += 2) { 2523d2bd3ab9SScott Long inquiryData->VendorId[i] = ((PUCHAR)pIdentify->ModelNumber)[i + 1]; 2524d2bd3ab9SScott Long inquiryData->VendorId[i+1] = ((PUCHAR)pIdentify->ModelNumber)[i]; 25251713e81bSScott Long 25261713e81bSScott Long } 25271713e81bSScott Long 25281713e81bSScott Long /* Initialize unused portion of product id. */ 25291713e81bSScott Long for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' '; 25301713e81bSScott Long 25311713e81bSScott Long /* firmware revision */ 2532d2bd3ab9SScott Long for (i = 0; i < 4; i += 2) 2533d2bd3ab9SScott Long { 2534d2bd3ab9SScott Long inquiryData->ProductRevisionLevel[i] = ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; 2535d2bd3ab9SScott Long inquiryData->ProductRevisionLevel[i+1] = ((PUCHAR)pIdentify->FirmwareRevision)[i]; 25361713e81bSScott Long } 25371713e81bSScott Long break; 25381713e81bSScott Long default: 25391713e81bSScott Long memcpy(&inquiryData->VendorId, "RR182x ", 8); 25401713e81bSScott Long #ifdef SUPPORT_ARRAY 25411713e81bSScott Long switch(pVDev->VDeviceType){ 25421713e81bSScott Long case VD_RAID_0: 2543d2bd3ab9SScott Long if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2544d2bd3ab9SScott Long (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2545d2bd3ab9SScott Long memcpy(&inquiryData->ProductId, "RAID 1/0 Array ", 16); 25461713e81bSScott Long else 2547d2bd3ab9SScott Long memcpy(&inquiryData->ProductId, "RAID 0 Array ", 16); 25481713e81bSScott Long break; 25491713e81bSScott Long case VD_RAID_1: 2550d2bd3ab9SScott Long if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || 2551d2bd3ab9SScott Long (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) 2552d2bd3ab9SScott Long memcpy(&inquiryData->ProductId, "RAID 0/1 Array ", 16); 25531713e81bSScott Long else 2554d2bd3ab9SScott Long memcpy(&inquiryData->ProductId, "RAID 1 Array ", 16); 25551713e81bSScott Long break; 25561713e81bSScott Long case VD_RAID_5: 25571713e81bSScott Long memcpy(&inquiryData->ProductId, "RAID 5 Array ", 16); 25581713e81bSScott Long break; 25591713e81bSScott Long case VD_JBOD: 25601713e81bSScott Long memcpy(&inquiryData->ProductId, "JBOD Array ", 16); 25611713e81bSScott Long break; 25621713e81bSScott Long } 25631713e81bSScott Long #endif 25641713e81bSScott Long memcpy(&inquiryData->ProductRevisionLevel, "3.00", 4); 25651713e81bSScott Long break; 25661713e81bSScott Long } 25671713e81bSScott Long } 25681713e81bSScott Long 25691713e81bSScott Long static void 25701713e81bSScott Long hpt_timeout(void *arg) 25711713e81bSScott Long { 2572d2bd3ab9SScott Long _VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus) 2573d2bd3ab9SScott Long intrmask_t oldspl = lock_driver(); 25741713e81bSScott Long fResetVBus(_VBUS_P0); 25751713e81bSScott Long unlock_driver(oldspl); 25761713e81bSScott Long } 25771713e81bSScott Long 2578d2bd3ab9SScott Long static void 2579d2bd3ab9SScott Long hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 2580d2bd3ab9SScott Long { 2581d2bd3ab9SScott Long PCommand pCmd = (PCommand)arg; 2582d2bd3ab9SScott Long union ccb *ccb = pCmd->pOrgCommand; 2583d2bd3ab9SScott Long struct ccb_hdr *ccb_h = &ccb->ccb_h; 2584d2bd3ab9SScott Long PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter; 2585d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2586d2bd3ab9SScott Long PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 2587d2bd3ab9SScott Long FPSCAT_GATH psg = pCmd->pSgTable; 2588d2bd3ab9SScott Long int idx; 2589d2bd3ab9SScott Long _VBUS_INST(pVDev->pVBus) 2590d2bd3ab9SScott Long 2591d2bd3ab9SScott Long HPT_ASSERT(pCmd->cf_physical_sg); 2592d2bd3ab9SScott Long 2593d2bd3ab9SScott Long if (error || nsegs == 0) 2594d2bd3ab9SScott Long panic("busdma error"); 2595d2bd3ab9SScott Long 2596d2bd3ab9SScott Long HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); 2597d2bd3ab9SScott Long 2598d2bd3ab9SScott Long for (idx = 0; idx < nsegs; idx++, psg++) { 2599d2bd3ab9SScott Long psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; 2600d2bd3ab9SScott Long psg->wSgSize = segs[idx].ds_len; 2601d2bd3ab9SScott Long psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; 2602d2bd3ab9SScott Long /* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ 2603d2bd3ab9SScott Long } 2604d2bd3ab9SScott Long /* psg[-1].wSgFlag = SG_FLAG_EOT; */ 2605d2bd3ab9SScott Long 2606d2bd3ab9SScott Long if (pCmd->cf_data_in) { 2607d2bd3ab9SScott Long bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD); 2608d2bd3ab9SScott Long } 2609d2bd3ab9SScott Long else if (pCmd->cf_data_out) { 2610d2bd3ab9SScott Long bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE); 2611d2bd3ab9SScott Long } 2612d2bd3ab9SScott Long 2613d2bd3ab9SScott Long ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); 2614d2bd3ab9SScott Long pVDev->pfnSendCommand(_VBUS_P pCmd); 2615d2bd3ab9SScott Long CheckPendingCall(_VBUS_P0); 2616d2bd3ab9SScott Long } 2617d2bd3ab9SScott Long 2618d2bd3ab9SScott Long 2619d2bd3ab9SScott Long 26201713e81bSScott Long static void HPTLIBAPI 26211713e81bSScott Long OsSendCommand(_VBUS_ARG union ccb *ccb) 26221713e81bSScott Long { 2623d2bd3ab9SScott Long PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2624d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 2625d2bd3ab9SScott Long struct ccb_hdr *ccb_h = &ccb->ccb_h; 2626d2bd3ab9SScott Long struct ccb_scsiio *csio = &ccb->csio; 2627d2bd3ab9SScott Long PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; 26281713e81bSScott Long 26297d9aed9cSScott Long KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", 26301713e81bSScott Long ccb, 26311713e81bSScott Long *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0], 26321713e81bSScott Long *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4], 26331713e81bSScott Long *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[8] 26341713e81bSScott Long )); 26351713e81bSScott Long 26361713e81bSScott Long pAdapter->outstandingCommands++; 26371713e81bSScott Long 26381713e81bSScott Long if (pVDev == NULL || pVDev->vf_online == 0) { 26391713e81bSScott Long ccb->ccb_h.status = CAM_REQ_INVALID; 26401713e81bSScott Long ccb_done(ccb); 26411713e81bSScott Long goto Command_Complished; 26421713e81bSScott Long } 26431713e81bSScott Long 26441713e81bSScott Long switch(ccb->csio.cdb_io.cdb_bytes[0]) 26451713e81bSScott Long { 26461713e81bSScott Long case TEST_UNIT_READY: 26471713e81bSScott Long case START_STOP_UNIT: 26481713e81bSScott Long case SYNCHRONIZE_CACHE: 26491713e81bSScott Long /* FALLTHROUGH */ 26501713e81bSScott Long ccb->ccb_h.status = CAM_REQ_CMP; 26511713e81bSScott Long break; 26521713e81bSScott Long 26531713e81bSScott Long case INQUIRY: 26541713e81bSScott Long ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); 26551713e81bSScott Long SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); 26561713e81bSScott Long ccb_h->status = CAM_REQ_CMP; 26571713e81bSScott Long break; 26581713e81bSScott Long 26591713e81bSScott Long case READ_CAPACITY: 26601713e81bSScott Long { 26611713e81bSScott Long UCHAR swip[4]; 26621713e81bSScott Long /* Claim 512 byte blocks (big-endian). */ 26631713e81bSScott Long ((PREAD_CAPACITY_DATA)csio->data_ptr)->BytesPerBlock = 0x20000; 26641713e81bSScott Long *(ULONG*)swip = pVDev->VDeviceCapacity - 1; 26651713e81bSScott Long ((PREAD_CAPACITY_DATA)csio->data_ptr)->LogicalBlockAddress = 26661713e81bSScott Long (swip[0] << 24) | (swip[1] << 16) | (swip[2] << 8) | swip[3]; 26671713e81bSScott Long ccb_h->status = CAM_REQ_CMP; 26681713e81bSScott Long break; 26691713e81bSScott Long } 26701713e81bSScott Long 26711713e81bSScott Long case READ_6: 26721713e81bSScott Long case WRITE_6: 26731713e81bSScott Long case READ_10: 26741713e81bSScott Long case WRITE_10: 26751713e81bSScott Long case 0x13: 26761713e81bSScott Long case 0x2f: 26771713e81bSScott Long { 26781713e81bSScott Long UCHAR Cdb[16]; 26791713e81bSScott Long UCHAR CdbLength; 26801713e81bSScott Long _VBUS_INST(pVDev->pVBus) 2681d2bd3ab9SScott Long PCommand pCmd = AllocateCommand(_VBUS_P0); 26821713e81bSScott Long HPT_ASSERT(pCmd); 26831713e81bSScott Long 26841713e81bSScott Long CdbLength = csio->cdb_len; 2685d2bd3ab9SScott Long if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) 2686d2bd3ab9SScott Long { 2687d2bd3ab9SScott Long if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) 2688d2bd3ab9SScott Long { 26891713e81bSScott Long bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); 2690d2bd3ab9SScott Long } 2691d2bd3ab9SScott Long else 2692d2bd3ab9SScott Long { 26931713e81bSScott Long KdPrintE(("ERROR!!!\n")); 26941713e81bSScott Long ccb->ccb_h.status = CAM_REQ_INVALID; 26951713e81bSScott Long break; 26961713e81bSScott Long } 2697d2bd3ab9SScott Long } 2698d2bd3ab9SScott Long else 2699d2bd3ab9SScott Long { 27001713e81bSScott Long bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); 27011713e81bSScott Long } 27021713e81bSScott Long 2703d2bd3ab9SScott Long pCmd->pOrgCommand = ccb; 27041713e81bSScott Long pCmd->pVDevice = pVDev; 27051713e81bSScott Long pCmd->pfnCompletion = fOsCommandDone; 27061713e81bSScott Long pCmd->pfnBuildSgl = fOsBuildSgl; 2707d2bd3ab9SScott Long pCmd->pSgTable = pmap->psg; 27081713e81bSScott Long 2709d2bd3ab9SScott Long switch (Cdb[0]) 2710d2bd3ab9SScott Long { 27111713e81bSScott Long case READ_6: 27121713e81bSScott Long case WRITE_6: 27131713e81bSScott Long case 0x13: 2714d2bd3ab9SScott Long pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; 27151713e81bSScott Long pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; 27161713e81bSScott Long break; 2717d2bd3ab9SScott Long 27181713e81bSScott Long default: 2719d2bd3ab9SScott Long pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24); 2720d2bd3ab9SScott Long pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8); 27211713e81bSScott Long break; 27221713e81bSScott Long } 27231713e81bSScott Long 2724d2bd3ab9SScott Long switch (Cdb[0]) 2725d2bd3ab9SScott Long { 27261713e81bSScott Long case READ_6: 27271713e81bSScott Long case READ_10: 27281713e81bSScott Long pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; 27291713e81bSScott Long pCmd->cf_data_in = 1; 27301713e81bSScott Long break; 27311713e81bSScott Long 27321713e81bSScott Long case WRITE_6: 27331713e81bSScott Long case WRITE_10: 27341713e81bSScott Long pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; 27351713e81bSScott Long pCmd->cf_data_out = 1; 27361713e81bSScott Long break; 27371713e81bSScott Long case 0x13: 27381713e81bSScott Long case 0x2f: 27391713e81bSScott Long pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; 27401713e81bSScott Long break; 27411713e81bSScott Long } 2742d2bd3ab9SScott Long /*///////////////////////// */ 2743d2bd3ab9SScott Long if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2744d2bd3ab9SScott Long int idx; 2745d2bd3ab9SScott Long bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 2746d2bd3ab9SScott Long 2747d2bd3ab9SScott Long if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 2748d2bd3ab9SScott Long pCmd->cf_physical_sg = 1; 2749d2bd3ab9SScott Long 2750d2bd3ab9SScott Long for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 2751d2bd3ab9SScott Long pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; 2752d2bd3ab9SScott Long pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len; 2753d2bd3ab9SScott Long pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0; 2754d2bd3ab9SScott Long } 27551713e81bSScott Long 27561713e81bSScott Long ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); 27571713e81bSScott Long pVDev->pfnSendCommand(_VBUS_P pCmd); 2758d2bd3ab9SScott Long } 2759d2bd3ab9SScott Long else { 2760d2bd3ab9SScott Long int error; 2761d2bd3ab9SScott Long pCmd->cf_physical_sg = 1; 2762d2bd3ab9SScott Long error = bus_dmamap_load(pAdapter->io_dma_parent, 2763d2bd3ab9SScott Long pmap->dma_map, 2764d2bd3ab9SScott Long ccb->csio.data_ptr, ccb->csio.dxfer_len, 2765d2bd3ab9SScott Long hpt_io_dmamap_callback, pCmd, 2766d2bd3ab9SScott Long BUS_DMA_WAITOK 2767d2bd3ab9SScott Long ); 2768d2bd3ab9SScott Long KdPrint(("bus_dmamap_load return %d\n", error)); 2769d2bd3ab9SScott Long if (error && error!=EINPROGRESS) { 2770d2bd3ab9SScott Long hpt_printk(("bus_dmamap_load error %d\n", error)); 2771d2bd3ab9SScott Long FreeCommand(_VBUS_P pCmd); 2772d2bd3ab9SScott Long ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2773d2bd3ab9SScott Long dmamap_put(pmap); 2774d2bd3ab9SScott Long pAdapter->outstandingCommands--; 2775d2bd3ab9SScott Long xpt_done(ccb); 2776d2bd3ab9SScott Long } 2777d2bd3ab9SScott Long } 27781713e81bSScott Long goto Command_Complished; 27791713e81bSScott Long } 27801713e81bSScott Long 27811713e81bSScott Long default: 27821713e81bSScott Long ccb->ccb_h.status = CAM_REQ_INVALID; 27831713e81bSScott Long break; 27841713e81bSScott Long } 27851713e81bSScott Long ccb_done(ccb); 27861713e81bSScott Long Command_Complished: 27871713e81bSScott Long CheckPendingCall(_VBUS_P0); 27881713e81bSScott Long return; 27891713e81bSScott Long } 27901713e81bSScott Long 27911713e81bSScott Long static void HPTLIBAPI 27921713e81bSScott Long fOsCommandDone(_VBUS_ARG PCommand pCmd) 27931713e81bSScott Long { 2794d2bd3ab9SScott Long union ccb *ccb = pCmd->pOrgCommand; 2795d2bd3ab9SScott Long PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; 2796d2bd3ab9SScott Long IAL_ADAPTER_T *pAdapter = pmap->pAdapter; 27971713e81bSScott Long 2798d2bd3ab9SScott Long KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result)); 27991713e81bSScott Long 28001713e81bSScott Long untimeout(hpt_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch); 28011713e81bSScott Long 28021713e81bSScott Long switch(pCmd->Result) { 28031713e81bSScott Long case RETURN_SUCCESS: 28041713e81bSScott Long ccb->ccb_h.status = CAM_REQ_CMP; 28051713e81bSScott Long break; 28061713e81bSScott Long case RETURN_BAD_DEVICE: 28071713e81bSScott Long ccb->ccb_h.status = CAM_DEV_NOT_THERE; 28081713e81bSScott Long break; 28091713e81bSScott Long case RETURN_DEVICE_BUSY: 28101713e81bSScott Long ccb->ccb_h.status = CAM_BUSY; 28111713e81bSScott Long break; 28121713e81bSScott Long case RETURN_INVALID_REQUEST: 28131713e81bSScott Long ccb->ccb_h.status = CAM_REQ_INVALID; 28141713e81bSScott Long break; 28151713e81bSScott Long case RETURN_SELECTION_TIMEOUT: 28161713e81bSScott Long ccb->ccb_h.status = CAM_SEL_TIMEOUT; 28171713e81bSScott Long break; 28181713e81bSScott Long case RETURN_RETRY: 28191713e81bSScott Long ccb->ccb_h.status = CAM_BUSY; 28201713e81bSScott Long break; 28211713e81bSScott Long default: 28221713e81bSScott Long ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 28231713e81bSScott Long break; 28241713e81bSScott Long } 28251713e81bSScott Long 2826d2bd3ab9SScott Long if (pCmd->cf_data_in) { 2827d2bd3ab9SScott Long bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD); 28281713e81bSScott Long } 2829d2bd3ab9SScott Long else if (pCmd->cf_data_in) { 2830d2bd3ab9SScott Long bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE); 2831d2bd3ab9SScott Long } 28321713e81bSScott Long 2833d2bd3ab9SScott Long bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map); 2834d2bd3ab9SScott Long 28351713e81bSScott Long FreeCommand(_VBUS_P pCmd); 28361713e81bSScott Long ccb_done(ccb); 28371713e81bSScott Long } 28381713e81bSScott Long 28391713e81bSScott Long int 28401713e81bSScott Long hpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags) 28411713e81bSScott Long { 28421713e81bSScott Long int p; 28431713e81bSScott Long 28441713e81bSScott Long p = (DpcQueue_Last + 1) % MAX_DPC; 28451713e81bSScott Long if (p==DpcQueue_First) { 28461713e81bSScott Long KdPrint(("DPC Queue full!\n")); 28471713e81bSScott Long return -1; 28481713e81bSScott Long } 28491713e81bSScott Long 28501713e81bSScott Long DpcQueue[DpcQueue_Last].dpc = dpc; 28511713e81bSScott Long DpcQueue[DpcQueue_Last].pAdapter = pAdapter; 28521713e81bSScott Long DpcQueue[DpcQueue_Last].arg = arg; 28531713e81bSScott Long DpcQueue[DpcQueue_Last].flags = flags; 28541713e81bSScott Long DpcQueue_Last = p; 28551713e81bSScott Long 28561713e81bSScott Long return 0; 28571713e81bSScott Long } 28581713e81bSScott Long 28591713e81bSScott Long #ifdef _RAID5N_ 28601713e81bSScott Long /* 2861d2bd3ab9SScott Long * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices. 2862d2bd3ab9SScott Long * How about the memory for 5081 request/response array and PRD table? 28631713e81bSScott Long */ 28641713e81bSScott Long void 28651713e81bSScott Long *os_alloc_page(_VBUS_ARG0) 28661713e81bSScott Long { 2867d2bd3ab9SScott Long return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 28681713e81bSScott Long } 2869d2bd3ab9SScott Long 28701713e81bSScott Long void 28711713e81bSScott Long *os_alloc_dma_page(_VBUS_ARG0) 28721713e81bSScott Long { 2873d2bd3ab9SScott Long return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); 28741713e81bSScott Long } 28751713e81bSScott Long 28761713e81bSScott Long void 28771713e81bSScott Long os_free_page(_VBUS_ARG void *p) 28781713e81bSScott Long { 28791713e81bSScott Long contigfree(p, 0x1000, M_DEVBUF); 28801713e81bSScott Long } 28811713e81bSScott Long 28821713e81bSScott Long void 28831713e81bSScott Long os_free_dma_page(_VBUS_ARG void *p) 28841713e81bSScott Long { 28851713e81bSScott Long contigfree(p, 0x1000, M_DEVBUF); 28861713e81bSScott Long } 28871713e81bSScott Long 28881713e81bSScott Long void 28891713e81bSScott Long DoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes) 28901713e81bSScott Long { 28911713e81bSScott Long UINT i; 2892d2bd3ab9SScott Long for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++; 28931713e81bSScott Long } 28941713e81bSScott Long 28951713e81bSScott Long void 28961713e81bSScott Long DoXor2(ULONG *p0, ULONG *p2, UINT nBytes) 28971713e81bSScott Long { 28981713e81bSScott Long UINT i; 2899d2bd3ab9SScott Long for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++; 29001713e81bSScott Long } 29011713e81bSScott Long #endif 2902