diff options
-rw-r--r-- | drivers/ieee1394/sbp2.c | 64 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.h | 64 |
2 files changed, 59 insertions, 69 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 8963dd484eb..0672224fa10 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -748,11 +748,6 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud hi->host = ud->ne->host; INIT_LIST_HEAD(&hi->scsi_ids); - /* Register our sbp2 status address space... */ - hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops, - SBP2_STATUS_FIFO_ADDRESS, - SBP2_STATUS_FIFO_ADDRESS + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1)); #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA /* Handle data movement if physical dma is not * enabled/supportedon host controller */ @@ -765,6 +760,18 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); + /* Register the status FIFO address range. We could use the same FIFO + * for targets at different nodes. However we need different FIFOs per + * target in order to support multi-unit devices. */ + scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( + &sbp2_highlevel, ud->ne->host, &sbp2_ops, + sizeof(struct sbp2_status_block), sizeof(quadlet_t), + ~0ULL, ~0ULL); + if (!scsi_id->status_fifo_addr) { + SBP2_ERR("failed to allocate status FIFO address range"); + goto failed_alloc; + } + /* Register our host with the SCSI stack. */ scsi_host = scsi_host_alloc(&scsi_driver_template, sizeof(unsigned long)); @@ -1003,6 +1010,10 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) SBP2_DMA_FREE("single query logins data"); } + if (scsi_id->status_fifo_addr) + hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, + scsi_id->status_fifo_addr); + scsi_id->ud->device.driver_data = NULL; SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); @@ -1081,11 +1092,10 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); - scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | - SBP2_STATUS_FIFO_ADDRESS_HI); - SBP2_DEBUG("sbp2_query_logins: status FIFO initialized"); + scsi_id->query_logins_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->query_logins_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); @@ -1190,11 +1200,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized"); - scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | - SBP2_STATUS_FIFO_ADDRESS_HI); - SBP2_DEBUG("sbp2_login_device: status FIFO initialized"); + scsi_id->login_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->login_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); /* * Byte swap ORB if necessary @@ -1307,10 +1316,10 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); scsi_id->logout_orb->reserved5 = 0x0; - scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | - SBP2_STATUS_FIFO_ADDRESS_HI); + scsi_id->logout_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->logout_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); /* * Byte swap ORB if necessary @@ -1372,10 +1381,10 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); scsi_id->reconnect_orb->reserved5 = 0x0; - scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); - scsi_id->reconnect_orb->status_FIFO_hi = - (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); + scsi_id->reconnect_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); + scsi_id->reconnect_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); /* * Byte swap ORB if necessary @@ -2112,7 +2121,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest { struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; - u32 id; struct scsi_cmnd *SCpnt = NULL; u32 scsi_status = SBP2_SCSI_STATUS_GOOD; struct sbp2_command_info *command; @@ -2135,12 +2143,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest } /* - * Find our scsi_id structure by looking at the status fifo address written to by - * the sbp2 device. + * Find our scsi_id structure by looking at the status fifo address + * written to by the sbp2 device. */ - id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) { - if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) { + if (scsi_id_tmp->ne->nodeid == nodeid && + scsi_id_tmp->status_fifo_addr == addr) { scsi_id = scsi_id_tmp; break; } diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 900ea1d25e7..e2d357a9ea3 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -33,15 +33,17 @@ #define ORB_DIRECTION_NO_DATA_TRANSFER 0x2 #define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31) -#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31) -#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */ +#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31) +#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */ #define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16) -#define ORB_SET_DATA_SIZE(value) (value & 0xffff) -#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16) -#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19) -#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20) -#define ORB_SET_SPEED(value) ((value & 0x7) << 24) -#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) +#define ORB_SET_STATUS_FIFO_HI(value, id) (value >> 32 | ORB_SET_NODE_ID(id)) +#define ORB_SET_STATUS_FIFO_LO(value) (value & 0xffffffff) +#define ORB_SET_DATA_SIZE(value) (value & 0xffff) +#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16) +#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19) +#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20) +#define ORB_SET_SPEED(value) ((value & 0x7) << 24) +#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) struct sbp2_command_orb { volatile u32 next_ORB_hi; @@ -76,8 +78,8 @@ struct sbp2_login_orb { u32 login_response_lo; u32 lun_misc; u32 passwd_resp_lengths; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; #define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff) @@ -102,8 +104,8 @@ struct sbp2_query_logins_orb { u32 query_response_lo; u32 lun_misc; u32 reserved_resp_length; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; #define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff) @@ -123,8 +125,8 @@ struct sbp2_reconnect_orb { u32 reserved4; u32 login_ID_misc; u32 reserved5; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; struct sbp2_logout_orb { @@ -134,8 +136,8 @@ struct sbp2_logout_orb { u32 reserved4; u32 login_ID_misc; u32 reserved5; - u32 status_FIFO_hi; - u32 status_FIFO_lo; + u32 status_fifo_hi; + u32 status_fifo_lo; }; #define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff) @@ -195,30 +197,6 @@ struct sbp2_status_block { * Miscellaneous SBP2 related config rom defines */ -/* The status fifo address definition below is used as a base for each - * node, which a chunk seperately assigned to each unit directory in the - * node. For example, 0xfffe00000000ULL is used for the first sbp2 device - * detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node - * 0, and so on. - * - * Note: We could use a single status fifo address for all sbp2 devices, - * and figure out which sbp2 device the status belongs to by looking at - * the source node id of the status write... but, using separate addresses - * for each sbp2 unit directory allows for better code and the ability to - * support multiple luns within a single 1394 node. - * - * Also note that we choose the address range below as it is a region - * specified for write posting, where the ohci controller will - * automatically send an ack_complete when the status is written by the - * sbp2 device... saving a split transaction. =) - */ -#define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL -#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe -#define SBP2_STATUS_FIFO_ADDRESS_LO 0x0 - -#define SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(entry) ((entry) << 5) -#define SBP2_STATUS_FIFO_OFFSET_TO_ENTRY(offset) ((offset) >> 5) - #define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1 #define SBP2_CSR_OFFSET_KEY 0x54 #define SBP2_UNIT_SPEC_ID_KEY 0x12 @@ -258,7 +236,6 @@ struct sbp2_status_block { */ #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */ #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ #define SBP2_MAX_CMDS 8 /* This should be safe */ @@ -338,6 +315,11 @@ struct scsi_id_instance_data { u32 sbp2_firmware_revision; /* + * Address for the device to write status blocks to + */ + u64 status_fifo_addr; + + /* * Variable used for logins, reconnects, logouts, query logins */ atomic_t sbp2_login_complete; |