📄 sbp2.c
字号:
if (command->sge_buffer) { pci_unmap_sg(hi->host->pdev, command->sge_buffer, command->dma_size, command->dma_dir); SBP2_DMA_FREE("scatter list"); command->sge_buffer = NULL; }}/* * This function moves a command to the completed orb list. */static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command){ unsigned long flags; sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags); list_del(&command->list); sbp2util_free_command_dma(command); list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);}/********************************************* * IEEE-1394 core driver stack related section *********************************************//* * This function is called at SCSI init in order to register our driver * with the IEEE-1394 stack. */int sbp2_init(void){ SBP2_DEBUG("sbp2_init"); /* * Register our high level driver with 1394 stack */ sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops); if (sbp2_hl_handle == NULL) { SBP2_ERR("sbp2 failed to register with ieee1394 highlevel"); return(-ENOMEM); } /* * Register our sbp2 status address space... */ hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS, SBP2_STATUS_FIFO_ADDRESS + sizeof(struct sbp2_status_block)); hpsb_register_protocol(&sbp2_driver); return 0;}/* * This function is called from cleanup module, or during shut-down, in * order to unregister our driver. */void sbp2_cleanup(void){ SBP2_DEBUG("sbp2_cleanup"); hpsb_unregister_protocol(&sbp2_driver); if (sbp2_hl_handle) { hpsb_unregister_highlevel(sbp2_hl_handle); sbp2_hl_handle = NULL; }}static int sbp2_probe(struct unit_directory *ud){ struct sbp2scsi_host_info *hi; SBP2_DEBUG("sbp2_probe"); hi = sbp2_find_host_info(ud->ne->host); return sbp2_start_device(hi, ud);}static void sbp2_disconnect(struct unit_directory *ud){ struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = ud->driver_data; SBP2_DEBUG("sbp2_disconnect"); hi = sbp2_find_host_info(ud->ne->host); if (hi != NULL) { sbp2_logout_device(hi, scsi_id); sbp2_remove_device(hi, scsi_id); }}static void sbp2_update(struct unit_directory *ud){ struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = ud->driver_data; unsigned long flags; SBP2_DEBUG("sbp2_update"); hi = sbp2_find_host_info(ud->ne->host); if (sbp2_reconnect_device(hi, scsi_id)) { /* Ok, reconnect has failed. Perhaps we didn't * reconnect fast enough. Try doing a regular login. */ if (sbp2_login_device(hi, scsi_id)) { /* Login failed too, just remove the device. */ SBP2_ERR("sbp2_reconnect_device failed!"); sbp2_remove_device(hi, scsi_id); hpsb_release_unit_directory(ud); return; } } /* Set max retries to something large on the device. */ sbp2_set_busy_timeout(hi, scsi_id); /* Do a SBP-2 fetch agent reset. */ sbp2_agent_reset(hi, scsi_id, 0); /* Get the max speed and packet size that we can use. */ sbp2_max_speed_and_size(hi, scsi_id); /* Complete any pending commands with busy (so they get * retried) and remove them from our queue */ sbp2_spin_lock(&hi->sbp2_command_lock, flags); sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY); sbp2_spin_unlock(&hi->sbp2_command_lock, flags);}/* * This function is called after registering our operations in sbp2_init. * We go ahead and allocate some memory for our host info structure, and * init some structures. */static void sbp2_add_host(struct hpsb_host *host){ struct sbp2scsi_host_info *hi; unsigned long flags; SBP2_DEBUG("sbp2_add_host"); /* Allocate some memory for our host info structure */ hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info), GFP_KERNEL); if (hi == NULL) { SBP2_ERR("out of memory in sbp2_add_host"); return; } /* Initialize some host stuff */ memset(hi, 0, sizeof(struct sbp2scsi_host_info)); INIT_LIST_HEAD(&hi->list); INIT_LIST_HEAD(&hi->sbp2_req_inuse); INIT_LIST_HEAD(&hi->sbp2_req_free); hi->host = host; hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED; /* Create our request packet pool (pool of packets for use in I/O) */ if (sbp2util_create_request_packet_pool(hi)) { SBP2_ERR("sbp2util_create_request_packet_pool failed!"); return; } sbp2_spin_lock(&sbp2_host_info_lock, flags); list_add_tail(&hi->list, &sbp2_host_info_list); sbp2_host_count++; sbp2_spin_unlock(&sbp2_host_info_lock, flags); /* Register our host with the SCSI stack. */ hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *)); if (hi->scsi_host) hi->scsi_host->hostdata[0] = (unsigned long)hi; scsi_driver_template.present++; return;}/* * This fuction returns a host info structure from the host structure, in * case we have multiple hosts. */static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host){ struct list_head *lh; struct sbp2scsi_host_info *hi; list_for_each (lh, &sbp2_host_info_list) { hi = list_entry(lh, struct sbp2scsi_host_info, list); if (hi->host == host) { return hi; } } return(NULL);}/* * This function is called when a host is removed. */static void sbp2_remove_host(struct hpsb_host *host){ struct sbp2scsi_host_info *hi; unsigned long flags; SBP2_DEBUG("sbp2_remove_host"); sbp2_spin_lock(&sbp2_host_info_lock, flags); hi = sbp2_find_host_info(host); if (hi != NULL) { sbp2util_remove_request_packet_pool(hi); sbp2_host_count--; list_del(&hi->list); scsi_unregister(hi->scsi_host); scsi_driver_template.present--; kfree(hi); } else SBP2_ERR("attempt to remove unknown host %p", host); sbp2_spin_unlock(&sbp2_host_info_lock, flags);}/* * This function is where we first pull the node unique ids, and then * allocate memory and register a SBP-2 device. */static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud){ struct scsi_id_instance_data *scsi_id = NULL; struct node_entry *ne; int i; SBP2_DEBUG("sbp2_start_device"); ne = ud->ne; /* * This really is a "new" device plugged in. Let's allocate memory * for our scsi id instance data. */ scsi_id = (struct scsi_id_instance_data *)kmalloc(sizeof(struct scsi_id_instance_data), GFP_KERNEL); if (!scsi_id) goto alloc_fail_first; memset(scsi_id, 0, sizeof(struct scsi_id_instance_data)); /* Login FIFO DMA */ scsi_id->login_response = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response), &scsi_id->login_response_dma); if (!scsi_id->login_response) goto alloc_fail; SBP2_DMA_ALLOC("consistent DMA region for login FIFO"); /* Reconnect ORB DMA */ scsi_id->reconnect_orb = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb), &scsi_id->reconnect_orb_dma); if (!scsi_id->reconnect_orb) goto alloc_fail; SBP2_DMA_ALLOC("consistent DMA region for reconnect ORB"); /* Logout ORB DMA */ scsi_id->logout_orb = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb), &scsi_id->logout_orb_dma); if (!scsi_id->logout_orb) goto alloc_fail; SBP2_DMA_ALLOC("consistent DMA region for logout ORB"); /* Login ORB DMA */ scsi_id->login_orb = pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb), &scsi_id->login_orb_dma); if (scsi_id->login_orb == NULL) {alloc_fail: if (scsi_id->logout_orb) { pci_free_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb), scsi_id->logout_orb, scsi_id->logout_orb_dma); SBP2_DMA_FREE("logout ORB DMA"); } if (scsi_id->reconnect_orb) { pci_free_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb), scsi_id->reconnect_orb, scsi_id->reconnect_orb_dma); SBP2_DMA_FREE("reconnect ORB DMA"); } if (scsi_id->login_response) { pci_free_consistent(hi->host->pdev, sizeof(struct sbp2_login_response), scsi_id->login_response, scsi_id->login_response_dma); SBP2_DMA_FREE("login FIFO DMA"); } kfree(scsi_id);alloc_fail_first: SBP2_ERR ("Could not allocate memory for scsi_id"); return(-ENOMEM); } SBP2_DMA_ALLOC("consistent DMA region for login ORB"); /* * Initialize some of the fields in this structure */ scsi_id->ne = ne; scsi_id->ud = ud; scsi_id->speed_code = SPEED_100; scsi_id->max_payload_size = sbp2_speedto_maxrec[SPEED_100]; ud->driver_data = scsi_id; init_waitqueue_head(&scsi_id->sbp2_login_wait); /* * Initialize structures needed for the command orb pool. */ INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; scsi_id->sbp2_total_command_orbs = 0; /* * Make sure that we've gotten ahold of the sbp2 management agent * address. Also figure out the command set being used (SCSI or * RBC). */ sbp2_parse_unit_directory(scsi_id); scsi_id->sbp2_total_command_orbs = SBP2_MAX_COMMAND_ORBS; /* * Knock the total command orbs down if we are serializing I/O */ if (serialize_io) { scsi_id->sbp2_total_command_orbs = 2; /* one extra for good measure */ } /* * Allocate some extra command orb structures for devices with * 128KB limit. */ if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) { scsi_id->sbp2_total_command_orbs *= 4; } /* * Find an empty spot to stick our scsi id instance data. */ for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) { if (!hi->scsi_id[i]) { hi->scsi_id[i] = scsi_id; scsi_id->id = i; SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i); break; } } /* * Create our command orb pool */ if (sbp2util_create_command_orb_pool(scsi_id, hi)) { SBP2_ERR("sbp2util_create_command_orb_pool failed!"); sbp2_remove_device(hi, scsi_id); return -ENOMEM; } /* * Make sure we are not out of space */ if (i == SBP2SCSI_MAX_SCSI_IDS) { SBP2_ERR("No slots left for SBP-2 device"); sbp2_remove_device(hi, scsi_id); return -EBUSY; } /* * Login to the sbp-2 device */ if (sbp2_login_device(hi, scsi_id)) { /* Login failed, just remove the device. */ SBP2_ERR("sbp2_login_device failed"); sbp2_remove_device(hi, scsi_id); return -EBUSY; } /* * Set max retries to something large on the device */ sbp2_set_busy_timeout(hi, scsi_id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -