hba_mod.c
来自「6440linuxDriver的源代码」· C语言 代码 · 共 1,621 行 · 第 1/3 页
C
1,621 行
struct mv_adp_desc *hba_desc; struct mv_mod_desc *mod_desc; hba_desc = __dev_to_desc(dev); BUG_ON(NULL == hba_desc); mod_desc = __get_lowest_module(hba_desc); if (NULL == mod_desc) return -1; mod_desc->ops->module_start(mod_desc->extension); /* * TBD : A hack due to CORE's module start process */ mod_desc = __get_highest_module(hba_desc); if (NULL == mod_desc) return -1; mod_desc->ops->module_start(mod_desc->extension); return 0;}static void __hba_module_stop(struct mv_adp_desc *hba_desc){ struct mv_mod_desc *mod_desc; mod_desc = __get_highest_module(hba_desc); if (NULL == mod_desc) return; /* starting from highest module, unlike module_start */ while (mod_desc) { if ((MV_MOD_STARTED == mod_desc->status)) { mod_desc->ops->module_stop(mod_desc->extension); mod_desc->status = MV_MOD_INITED; } mod_desc = mod_desc->child; }}/* stop all HBAs if dev == NULL */void mv_hba_stop(struct pci_dev *dev){ struct mv_adp_desc *hba_desc; if (dev) { hba_desc = __dev_to_desc(dev); __hba_module_stop(hba_desc); } else { list_for_each_entry(hba_desc, &mv_online_adapter_list, hba_entry) __hba_module_stop(hba_desc); }}void mv_hba_release(struct pci_dev *dev){ struct mv_adp_desc *hba_desc; hba_desc = __dev_to_desc(dev); if (NULL != hba_desc) { __unmap_pci_addr(hba_desc->dev, hba_desc->Base_Address); mv_release_module_resource(hba_desc); mv_hba_release_modmm(hba_desc->dev); }}int mv_hba_init(struct pci_dev *dev, MV_U32 max_io){ struct mv_adp_desc *hba_desc; struct mv_mod_desc *mod_desc; int dbg_ret = 0; hba_desc = mv_hba_init_modmm(dev); if (NULL == hba_desc) goto ext_err_init; if (register_online_modules(hba_desc)) goto ext_err_modmm; hba_desc->max_io = max_io; hba_desc->id = __mv_get_adapter_count() - 1; if (mv_alloc_module_resource(hba_desc)) goto ext_err_modmm; if (pci_read_config_byte(hba_desc->dev, PCI_REVISION_ID, &hba_desc->Revision_Id)) { printk("%s : Failed to get hba's revision id.\n", mv_product_name); goto ext_err_pci; } hba_desc->Vendor_Id = dev->vendor; hba_desc->Device_Id = dev->device; __map_pci_addr(dev, hba_desc->Base_Address); spin_lock_init(&hba_desc->lock); MV_DBG(DMSG_HBA, "%s : HBA ext struct init'ed at %p.\n", mv_product_name, hba_desc); mod_desc = __get_lowest_module(hba_desc); if (NULL == mod_desc) goto ext_err_pci; while (mod_desc) { if (MV_MOD_INITED != mod_desc->status) continue; mod_desc->ops->module_initialize(mod_desc, mod_desc->extension_size, hba_desc->max_io); /* there's no support for sibling module at the moment */ mod_desc = mod_desc->parent; } return 0;ext_err_pci: ++dbg_ret; mv_release_module_resource(hba_desc);ext_err_modmm: ++dbg_ret; mv_hba_release_modmm(dev);ext_err_init: ++dbg_ret; return dbg_ret;}static MV_U32 __hba_get_res_desc(enum Resource_Type type, MV_U16 maxIo){ MV_U32 size = 0; if (type == RESOURCE_CACHED_MEMORY) { /* Fixed memory */ size = OFFSET_OF(HBA_Extension, Memory_Pool); size = ROUNDING(size, 8);#ifdef SUPPORT_EVENT size += sizeof(Driver_Event_Entry) * MAX_EVENTS; MV_ASSERT(size == ROUNDING(size, 8));#endif /* SUPPORT_EVENT */ } return size;}static void __hba_ops_initialize(struct mv_mod_desc *mod_desc, MV_U32 size, MV_U16 max_io){ PHBA_Extension phba; MV_PTR_INTEGER temp; MV_U32 i; MV_U32 sg_num;#ifdef SUPPORT_EVENT PDriver_Event_Entry pEvent = NULL;#endif /* SUPPORT_EVENT */ phba = (PHBA_Extension) mod_desc->extension; temp = (MV_PTR_INTEGER) phba->Memory_Pool; WARN_ON(sizeof(MV_Request) != ROUNDING(sizeof(MV_Request), 8)); /* * Initialize data structure however following variables have been * set already. * Device_Extension * Is_Dump */ phba->State = DRIVER_STATUS_IDLE; phba->Io_Count = 0; phba->Max_Io = max_io; phba->desc = mod_desc; init_completion(&phba->cmpl); spin_lock_init(&phba->lock); spin_lock_init(&phba->irq_lock); temp = ROUNDING(((MV_PTR_INTEGER) temp), 8); if (max_io > 1) sg_num = MAX_SG_ENTRY; else sg_num = MAX_SG_ENTRY_REDUCED; phba->req_pool = (MV_PVOID) res_reserve_req_pool(MODULE_HBA, max_io, sg_num);#ifdef SUPPORT_EVENT INIT_LIST_HEAD(&phba->Stored_Events); INIT_LIST_HEAD(&phba->Free_Events); phba->Num_Stored_Events = 0; phba->SequenceNumber = 0; /* Event sequence number */ MV_ASSERT(sizeof(Driver_Event_Entry) == ROUNDING(sizeof(Driver_Event_Entry), 8)); temp = ROUNDING(((MV_PTR_INTEGER) temp), 8); for (i = 0; i < MAX_EVENTS; i++) { pEvent = (PDriver_Event_Entry) temp; list_add_tail(&pEvent->Queue_Pointer, &phba->Free_Events); temp += sizeof(Driver_Event_Entry); }#endif /* SUPPORT_EVENT */}static void __hba_ops_start(MV_PVOID extension){ struct Scsi_Host *host = NULL; struct hba_extension *hba; int ret; hba = (struct hba_extension *) extension; host = scsi_host_alloc(&mv_driver_template, sizeof(void *)); if (NULL == host) { printk("%s : Unable to allocate a scsi host.\n", mv_product_name); goto err_out; } *((MV_PVOID *) host->hostdata) = extension; hba->host = host; hba->dev = hba->desc->hba_desc->dev; host->irq = hba->dev->irq; host->max_id = MV_MAX_TARGET_NUMBER; host->max_lun = MV_MAX_LUN_NUMBER; host->max_channel = 0; host->max_cmd_len = 16;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15) host->transportt = &mv_transport_template;#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16) */#if USE_MSI pci_enable_msi(hba->dev);#endif /* USE_MSI */#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19) ret = request_irq(hba->dev->irq, mv_intr_handler, IRQF_SHARED, mv_driver_name, hba);#else ret = request_irq(hba->dev->irq, mv_intr_handler, SA_SHIRQ, mv_driver_name, hba);#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19) */ if (ret < 0) { printk("%s : Error upon requesting IRQ %d.\n", mv_product_name, hba->dev->irq); goto err_request_irq; } hba->desc->status = MV_MOD_STARTED; HBA_ModuleStarted(hba->desc); /* wait for MODULE(CORE,RAID,HBA) init */ if (0 == wait_for_completion_timeout(&hba->cmpl, 25*HZ)) goto err_wait_cmpl; hba_house_keeper_run(); if (scsi_add_host(host, &hba->dev->dev)) goto err_wait_cmpl; scsi_scan_host(host); if (mv_register_chdev(hba)) printk("Unable to register character device interface.\n"); return;err_wait_cmpl: printk("Timeout waiting for module start.\n"); free_irq(hba->dev->irq, hba);err_request_irq: scsi_host_put(host); hba->host = NULL;err_out: return;}extern void hba_send_shutdown_req(PHBA_Extension phba);static void __hba_ops_stop(MV_PVOID extension){ PHBA_Extension hba = (PHBA_Extension) extension; mv_unregister_chdev(hba); if (DRIVER_STATUS_STARTED == hba->State) { scsi_remove_host(hba->host); scsi_host_put(hba->host); hba->host = NULL; hba_send_shutdown_req(hba); free_irq(hba->dev->irq, hba); } res_release_req_pool(hba->req_pool); WARN_ON(hba->Io_Count != 0);}#ifdef SUPPORT_EVENTstatic MV_BOOLEAN add_event(IN MV_PVOID extension, IN MV_U32 eventID, IN MV_U16 deviceID, IN MV_U8 severityLevel, IN MV_U8 param_cnt, IN MV_PVOID params){ struct hba_extension * hba = (struct hba_extension *) extension; PDriver_Event_Entry pEvent; static MV_U32 sequenceNo = 1; if (param_cnt > MAX_EVENT_PARAMS) return MV_FALSE; if (list_empty(&hba->Free_Events)) { /* No free entry, we need to reuse the oldest entry from * Stored_Events. */ MV_ASSERT(!list_empty(&hba->Stored_Events)); MV_ASSERT(hba->Num_Stored_Events == MAX_EVENTS); pEvent = List_GetFirstEntry((&hba->Stored_Events), Driver_Event_Entry, Queue_Pointer); } else { pEvent = List_GetFirstEntry((&hba->Free_Events), Driver_Event_Entry, Queue_Pointer); hba->Num_Stored_Events++; MV_ASSERT(hba->Num_Stored_Events <= MAX_EVENTS); } pEvent->Event.AdapterID = hba->desc->hba_desc->id; pEvent->Event.EventID = eventID; pEvent->Event.SequenceNo = sequenceNo++; pEvent->Event.Severity = severityLevel; pEvent->Event.DeviceID = deviceID;// pEvent->Event.Param_Cnt = param_cnt; pEvent->Event.TimeStamp = ossw_get_time_in_sec(); if (param_cnt > 0 && params != NULL) MV_CopyMemory( (MV_PVOID)pEvent->Event.Params, (MV_PVOID)params, param_cnt * 4 ); list_add_tail(&pEvent->Queue_Pointer, &hba->Stored_Events); return MV_TRUE;}static void get_event(MV_PVOID This, PMV_Request pReq){ struct hba_extension * hba = (struct hba_extension *) This; PEventRequest pEventReq = (PEventRequest)pReq->Data_Buffer; PDriver_Event_Entry pfirst_event; MV_U8 count = 0; pEventReq->Count = 0; if ( hba->Num_Stored_Events > 0 ) { MV_DASSERT( !list_empty(&hba->Stored_Events) ); while (!list_empty(&hba->Stored_Events) && (count < MAX_EVENTS_RETURNED)) { pfirst_event = List_GetFirstEntry((&hba->Stored_Events), Driver_Event_Entry, Queue_Pointer); MV_CopyMemory(&pEventReq->Events[count], &pfirst_event->Event, sizeof(DriverEvent)); hba->Num_Stored_Events--; list_add_tail(&pfirst_event->Queue_Pointer, &hba->Free_Events ); count++; } pEventReq->Count = count; } pReq->Scsi_Status = REQ_STATUS_SUCCESS; return;}#else /* SUPPORT_EVENT */static inline MV_BOOLEAN add_event(IN MV_PVOID extension, IN MV_U32 eventID, IN MV_U16 deviceID, IN MV_U8 severityLevel, IN MV_U8 param_cnt, IN MV_PVOID params) {}static inline void get_event(MV_PVOID This, PMV_Request pReq) {}#endif /* SUPPORT_EVENT */static void __hba_ops_notify(MV_PVOID This, enum Module_Event event, struct mod_notif_param *event_param){ switch (event) { case EVENT_LOG_GENERATED: add_event(This, event_param->event_id, event_param->dev_id, event_param->severity_lvl, event_param->param_count, event_param->p_param); break; case EVENT_DEVICE_REMOVAL: case EVENT_DEVICE_ARRIVAL: hba_msg_insert(This, event, (event_param == NULL)?0:event_param->lo); break; default: break; }}static void mvGetAdapterInfo(MV_PVOID This, PMV_Request pReq){ PHBA_Extension hba = (PHBA_Extension)This; struct mv_adp_desc *hba_desc; PAdapter_Info pAdInfo; /* initialize */ hba_desc = hba->desc->hba_desc; pAdInfo = (PAdapter_Info)pReq->Data_Buffer; MV_ZeroMemory(pAdInfo, sizeof(Adapter_Info)); pAdInfo->DriverVersion.VerMajor = VER_MAJOR; pAdInfo->DriverVersion.VerMinor = VER_MINOR; pAdInfo->DriverVersion.VerOEM = VER_OEM; pAdInfo->DriverVersion.VerBuild = VER_BUILD; pAdInfo->SystemIOBusNumber = hba_desc->Adapter_Bus_Number; pAdInfo->SlotNumber = hba_desc->Adapter_Device_Number; pAdInfo->VenDevID = hba_desc->Vendor_Id; pAdInfo->SubVenDevID = hba_desc->Device_Id; if (hba_desc->Device_Id == DEVICE_ID_THORLITE_2S1P || hba_desc->Device_Id == DEVICE_ID_THORLITE_2S1P_WITH_FLASH) pAdInfo->PortCount = 3; else if (hba_desc->Device_Id == DEVICE_ID_THORLITE_0S1P) pAdInfo->PortCount = 1; else pAdInfo->PortCount = 5; pAdInfo->AlarmSupport = MV_FALSE; pAdInfo->MaxBlockPerPD = MAX_BLOCK_PER_HD_SUPPORTED; pAdInfo->MaxHD = MAX_DEVICE_SUPPORTED_PERFORMANCE; pAdInfo->MaxExpander = MAX_EXPANDER_SUPPORTED_PERFORMANCE; pAdInfo->MaxPM = MAX_PM_SUPPORTED; pAdInfo->MaxLogicalDrive = MAX_LD_SUPPORTED_PERFORMANCE;#ifdef RAID_DRIVER pAdInfo->AlarmSupport = MV_FALSE; pAdInfo->MaxTotalBlocks = MAX_BLOCK_SUPPORTED_PERFORMANCE; pAdInfo->MaxBlockPerPD = MAX_BLOCK_PER_HD_SUPPORTED; pAdInfo->MaxLogicalDrive = MAX_LD_SUPPORTED_PERFORMANCE;#if BGA_REBUILD_SUPPORT pAdInfo->Features |= FEATURE_BGA_REBUILD_SUPPORT;#endif /* BGA_REBUILD_SUPPORT */#if BGA_BKINIT_SUPPORT pAdInfo->Features |= FEATURE_BGA_BKINIT_SUPPORT;#endif /* BGA_BKINIT_SUPPORT */#if BGA_SYNC_SUPPORT pAdInfo->Features |= FEATURE_BGA_SYNC_SUPPORT;#endif /* BGA_SYNC_SUPPORT */#if BGA_MIGRATION_SUPPORT pAdInfo->Features |= FEATURE_BGA_MIGRATION_SUPPORT;#endif /* BGA_MIGRATION_SUPPORT */#endif /* RAID_DRIVER */ /* About Logical Driver Mode */#ifdef SUPPORT_RAID6 pAdInfo->LogicalDriverMode = SUPPORT_LD_MODE_RAID0 | SUPPORT_LD_MODE_RAID1 | SUPPORT_LD_MODE_RAID5 | SUPPORT_LD_MODE_RAID10 | SUPPORT_LD_MODE_RAID1E | SUPPORT_LD_MODE_RAID50;#elif defined(RAID_DRIVER) pAdInfo->LogicalDriverMode = SUPPORT_LD_MODE_RAID0 | SUPPORT_LD_MODE_RAID1 | SUPPORT_LD_MODE_RAID10;#else pAdInfo->LogicalDriverMode = 0;#endif /* SUPPORT_RAID6 */ pReq->Scsi_Status = REQ_STATUS_SUCCESS;}static void __hba_ops_send_request(MV_PVOID this, PMV_Request req){ PHBA_Extension phba = (PHBA_Extension) this; switch (req->Cdb[0]) { case APICDB0_ADAPTER: if (req->Cdb[1] == APICDB1_ADAPTER_GETINFO) mvGetAdapterInfo(phba, req); else req->Scsi_Status = REQ_STATUS_INVALID_REQUEST; req->Completion(req->Cmd_Initiator, req); break; case APICDB0_EVENT: if (req->Cdb[1] == APICDB1_EVENT_GETEVENT) get_event(phba, req); else req->Scsi_Status = REQ_STATUS_INVALID_REQUEST; req->Completion(req->Cmd_Initiator, req); break; default: /* submit to child layer */ phba->desc->child->ops->module_sendrequest( phba->desc->child->extension, req); break; }}static struct mv_module_ops hba_module_interface = { .module_id = MODULE_HBA, .get_res_desc = __hba_get_res_desc, .module_initialize = __hba_ops_initialize, .module_start = __hba_ops_start, .module_stop = __hba_ops_stop, .module_notification = __hba_ops_notify, .module_sendrequest = __hba_ops_send_request,};struct mv_module_ops *mv_hba_register_module(void){ return &hba_module_interface;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?