The translation is temporarily closed for contributions due to maintenance, please come back later.

Translation

(itstool) path: listitem/para
English
<emphasis>tag_action</emphasis> - the kind of tag to use:
Context English Chinese (Simplified) (zh_CN) State
<emphasis>timeout_ch</emphasis> - a convenience place for the SIM driver to store the timeout handle (the CAM subsystem itself does not make any assumptions about it) <emphasis>timeout_ch</emphasis> - 一个为SIM驱动 程序存储超时处理函数的方便之所(CAM子系统自身并不对此作任何假设)
<emphasis>flags</emphasis> - various bits of information about the request spriv_ptr0, spriv_ptr1 - fields reserved for private use by the SIM driver (such as linking to the SIM queues or SIM private control blocks); actually, they exist as unions: spriv_ptr0 and spriv_ptr1 have the type (void *), spriv_field0 and spriv_field1 have the type unsigned long, sim_priv.entries[0].bytes and sim_priv.entries[1].bytes are byte arrays of the size consistent with the other incarnations of the union and sim_priv.bytes is one array, twice bigger. <emphasis>flags</emphasis> - 有关请求的各个 信息位
The recommended way of using the SIM private fields of CCB is to define some meaningful names for them and use these meaningful names in the driver, like: 使用CCB的SIM私有字段的建议方法是为它们定义一些有意义的名字, 并且在驱动程序中使用这些有意义的名字,就像下面这样:
#define ccb_some_meaningful_name sim_priv.entries[0].bytes
#define ccb_hcb spriv_ptr1 /* for hardware control block */
#define ccb_some_meaningful_name sim_priv.entries[0].bytes
#define ccb_hcb spriv_ptr1 /* for hardware control block */
The most common initiator mode requests are: 最常见的发起者模式的请求是:
<emphasis>XPT_SCSI_IO</emphasis> - execute an I/O transaction <emphasis>XPT_SCSI_IO</emphasis> - 执行I/O事务
The instance <quote>struct ccb_scsiio csio</quote> of the union ccb is used to transfer the arguments. They are: 联合ccb的<quote>struct ccb_scsiio csio</quote>实例用于传递参量。 它们是:
<emphasis>cdb_io</emphasis> - pointer to the SCSI command buffer or the buffer itself <emphasis>cdb_io</emphasis> - 指向SCSI命令缓冲区的指针或缓冲区本身
<emphasis>cdb_len</emphasis> - SCSI command length <emphasis>cdb_len</emphasis> - SCSI 命令长度
<emphasis>data_ptr</emphasis> - pointer to the data buffer (gets a bit complicated if scatter/gather is used) <emphasis>data_ptr</emphasis> - 指向数据缓冲区的指针(如果使用分散/集中会复杂一点)
<emphasis>dxfer_len</emphasis> - length of the data to transfer <emphasis>dxfer_len</emphasis> - 待传输数据的长度
<emphasis>sglist_cnt</emphasis> - counter of the scatter/gather segments <emphasis>sglist_cnt</emphasis> - 分散/集中段的计数
<emphasis>scsi_status</emphasis> - place to return the SCSI status <emphasis>scsi_status</emphasis> - 返回SCSI状态的地方
<emphasis>sense_data</emphasis> - buffer for the SCSI sense information if the command returns an error (the SIM driver is supposed to run the REQUEST SENSE command automatically in this case if the CCB flag CAM_DIS_AUTOSENSE is not set) <emphasis>sense_data</emphasis> - 命令返回错误时保存SCSI sense信息的缓冲区(这种情况下,如果没有 设置CCB的旗标CAM_DIS_AUTOSENSE,则假定SIM驱动程序会自动运行 REQUEST SENSE命令)
<emphasis>sense_len</emphasis> - the length of that buffer (if it happens to be higher than size of sense_data the SIM driver must silently assume the smaller value) resid, sense_resid - if the transfer of data or SCSI sense returned an error these are the returned counters of the residual (not transferred) data. They do not seem to be especially meaningful, so in a case when they are difficult to compute (say, counting bytes in the SCSI controller's FIFO buffer) an approximate value will do as well. For a successfully completed transfer they must be set to zero. <emphasis>sense_len</emphasis> - 缓冲区的长度(如果碰巧大于sense_data的大小,SIM驱动程序必须 悄悄地采用较小值)(译注:一点改动,参考原文及代码)
<emphasis>tag_action</emphasis> - the kind of tag to use: <emphasis>tag_action</emphasis> - 使用的标签的种类有:
CAM_TAG_ACTION_NONE - do not use tags for this transaction CAM_TAG_ACTION_NONE - 事务不使用标签
MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG - value equal to the appropriate tag message (see /sys/cam/scsi/scsi_message.h); this gives only the tag type, the SIM driver must assign the tag value itself MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG - 值等于适当的标签信息 (见/sys/cam/scsi/scsi_message.h);仅给出标签类型,SIM驱动程序 必须自己赋标签值
The general logic of handling this request is the following: 处理请求的通常逻辑如下:
The first thing to do is to check for possible races, to make sure that the command did not get aborted when it was sitting in the queue: 要做的第一件事情是检查可能的竞争条件,确保命令位于队列中时 不会被中止:
struct ccb_scsiio *csio = &amp;ccb-&gt;csio;

if ((ccb_h-&gt;status &amp; CAM_STATUS_MASK) != CAM_REQ_INPROG) {
xpt_done(ccb);
return;
}
struct ccb_scsiio *csio = &amp;ccb-&gt;csio;

if ((ccb_h-&gt;status &amp; CAM_STATUS_MASK) != CAM_REQ_INPROG) {
xpt_done(ccb);
return;
}
Also we check that the device is supported at all by our controller: 我们也检查我们的控制器完全支持设备:
if(ccb_h-&gt;target_id &gt; OUR_MAX_SUPPORTED_TARGET_ID
|| cch_h-&gt;target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {
ccb_h-&gt;status = CAM_TID_INVALID;
xpt_done(ccb);
return;
}
if(ccb_h-&gt;target_lun &gt; OUR_MAX_SUPPORTED_LUN) {
ccb_h-&gt;status = CAM_LUN_INVALID;
xpt_done(ccb);
return;
}
if(ccb_h-&gt;target_id &gt; OUR_MAX_SUPPORTED_TARGET_ID
|| cch_h-&gt;target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {
ccb_h-&gt;status = CAM_TID_INVALID;
xpt_done(ccb);
return;
}
if(ccb_h-&gt;target_lun &gt; OUR_MAX_SUPPORTED_LUN) {
ccb_h-&gt;status = CAM_LUN_INVALID;
xpt_done(ccb);
return;
}
<primary>hardware control block</primary> <primary>hardware control block(硬件控制块)</primary>
Then allocate whatever data structures (such as card-dependent hardware control block<_:indexterm-1/>) we need to process this request. If we can not then freeze the SIM queue and remember that we have a pending operation, return the CCB back and ask CAM to re-queue it. Later when the resources become available the SIM queue must be unfrozen by returning a ccb with the <literal>CAM_SIMQ_RELEASE</literal> bit set in its status. Otherwise, if all went well, link the CCB with the hardware control block (HCB) and mark it as queued. 然后分配我们处理请求所需的数据结构(如卡相关的硬件控制块等)。 如果我们不能分配则冻结SIM队列,记录下我们有一个挂起的操作,返回 CCB,请求CAM将CCB重新入队。以后当资源可用时,必须通过返回其 状态中设置 <literal>CAM_SIMQ_RELEASE</literal> 位的ccb来解冻SIM队列。否则,如果所有 正常,则将CCB与硬件控制块(HCB)链接,并将其标志为已入队。
struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);

if(hcb == NULL) {
softc-&gt;flags |= RESOURCE_SHORTAGE;
xpt_freeze_simq(sim, /*count*/1);
ccb_h-&gt;status = CAM_REQUEUE_REQ;
xpt_done(ccb);
return;
}

hcb-&gt;ccb = ccb; ccb_h-&gt;ccb_hcb = (void *)hcb;
ccb_h-&gt;status |= CAM_SIM_QUEUED;
struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);

if(hcb == NULL) {
softc-&gt;flags |= RESOURCE_SHORTAGE;
xpt_freeze_simq(sim, /*count*/1);
ccb_h-&gt;status = CAM_REQUEUE_REQ;
xpt_done(ccb);
return;
}

hcb-&gt;ccb = ccb; ccb_h-&gt;ccb_hcb = (void *)hcb;
ccb_h-&gt;status |= CAM_SIM_QUEUED;
Extract the target data from CCB into the hardware control block. Check if we are asked to assign a tag and if yes then generate an unique tag and build the SCSI tag messages. The SIM driver is also responsible for negotiations with the devices to set the maximal mutually supported bus width, synchronous rate and offset. 从CCB中提取目标数据到硬件控制块。检查是否要求我们分配一个 标签,如果是则产生一个唯一的标签并构造SCSI标签信息。SIM驱动程序 也负责与设备协商设定彼此支持的最大总线宽度、同步速率和偏移。
hcb-&gt;target = ccb_h-&gt;target_id; hcb-&gt;lun = ccb_h-&gt;target_lun;
generate_identify_message(hcb);
if( ccb_h-&gt;tag_action != CAM_TAG_ACTION_NONE )
generate_unique_tag_message(hcb, ccb_h-&gt;tag_action);
if( !target_negotiated(hcb) )
generate_negotiation_messages(hcb);
hcb-&gt;target = ccb_h-&gt;target_id; hcb-&gt;lun = ccb_h-&gt;target_lun;
generate_identify_message(hcb);
if( ccb_h-&gt;tag_action != CAM_TAG_ACTION_NONE )
generate_unique_tag_message(hcb, ccb_h-&gt;tag_action);
if( !target_negotiated(hcb) )
generate_negotiation_messages(hcb);
Then set up the SCSI command. The command storage may be specified in the CCB in many interesting ways, specified by the CCB flags. The command buffer can be contained in CCB or pointed to, in the latter case the pointer may be physical or virtual. Since the hardware commonly needs physical address we always convert the address to the physical one, typically using the busdma API. 然后设置SCSI命令。可以在CCB中以多种有趣的方式指定命令的存储, 这些方式由CCB中的旗标指定。命令缓冲区可以包含在CCB中或者用指针 指向,后者情况下指针可以指向物理地址或虚地址。由于硬件通常需要 物理地址,因此我们总是将地址转换为物理地址。
In case if a physical address is requested it is OK to return the CCB with the status <errorname>CAM_REQ_INVALID</errorname>, the current drivers do that. If necessary a physical address can be also converted or mapped back to a virtual address but with big pain, so we do not do that. 在请求物理地址的情况下,返回带有状态 <errorname>CAM_REQ_INVALID</errorname> 的CCB是可以的,当前的驱动程序就是那样做的。但也 可能像这个例子(驱动程序中应当有不带条件编译的更直接做法)中那样 编译Alpha特定的代码片断。如果需要物理地址也能转换或映射回虚地址, 但那样代价很大,因此我们不那样做。
if(ccb_h-&gt;flags &amp; CAM_CDB_POINTER) {
/* CDB is a pointer */
if(!(ccb_h-&gt;flags &amp; CAM_CDB_PHYS)) {
/* CDB pointer is virtual */
hcb-&gt;cmd = vtobus(csio-&gt;cdb_io.cdb_ptr);
} else {
/* CDB pointer is physical */
hcb-&gt;cmd = csio-&gt;cdb_io.cdb_ptr ;
}
} else {
/* CDB is in the ccb (buffer) */
hcb-&gt;cmd = vtobus(csio-&gt;cdb_io.cdb_bytes);
}
hcb-&gt;cmdlen = csio-&gt;cdb_len;
if(ccb_h-&gt;flags &amp; CAM_CDB_POINTER) {
/* CDB is a pointer */
if(!(ccb_h-&gt;flags &amp; CAM_CDB_PHYS)) {
/* CDB pointer is virtual */
hcb-&gt;cmd = vtobus(csio-&gt;cdb_io.cdb_ptr);
} else {
/* CDB pointer is physical */
hcb-&gt;cmd = csio-&gt;cdb_io.cdb_ptr ;
}
} else {
/* CDB is in the ccb (buffer) */
hcb-&gt;cmd = vtobus(csio-&gt;cdb_io.cdb_bytes);
}
hcb-&gt;cmdlen = csio-&gt;cdb_len;

Loading…

<emphasis>tag_action</emphasis> - the kind of tag to use:
<emphasis>tag_action</emphasis> - 使用的标签的种类有:
a year ago
Browse all component changes

Glossary

English Chinese (Simplified) (zh_CN)
No related strings found in the glossary.

Source information

Source string comment
(itstool) path: listitem/para
Source string location
book.translate.xml:20108
String age
a year ago
Source string age
a year ago
Translation file
books/zh_CN/arch-handbook.po, string 2208