📄 scsi_target.h
字号:
* The pointer to the /proc/scsi_target directory entry */ struct proc_dir_entry *proc_dir; /* proc-fs info function. * Can be used to export driver statistics and other infos to the world * outside the kernel ie. userspace and it also provides an interface * to feed the driver with information. Check eata_dma_proc.c for reference */ int (*proc_info)(char *, char **, off_t, int, int, int); /* * name of the template. Must be unique so as to help identify * the template. I have restricted the name length to 16 chars * which should be sufficient for most purposes. MUST HAVE */ const char name[TWOBYTE]; /* * detect function: This function should detect the devices that * are present in the system. The function should return a value * >= 0 to signify the number of front end devices within the * system. A negative value should be returned whenever there is * an error. MUST HAVE */ int (* detect) (struct STT*); /* * release function: This function should free up the resources * allocated to the device defined by the STD. The function should * return 0 to indicate successful release or a negative value if * there are some issues with the release. OPTIONAL */ int (* release)(struct STD*); /* * xmit_response: This function is equivalent to the SCSI * queuecommand. The front-end should transmit the response * buffer and the status in the Scsi_Request struct. * The expectation is that this executing this command is * NON-BLOCKING. * * After the response is actually transmitted, the front-end * should call the front_end_done function in the mid-level * which will allow the mid-level to free up the command * Return 0 for success and < 0 for trouble * MUST HAVE */ int (* xmit_response)(struct SC*); /* * rdy_to_xfer: This function informs the driver that data * buffer corresponding to the said command have now been * allocated and it is okay to receive data for this command. * This function is necessary because a SCSI target does not * have any control over the commands it receives. Most lower * level protocols have a corresponding function which informs * the initiator that buffers have been allocated e.g., XFER_ * RDY in Fibre Channel. After the data is actually received * the low-level driver needs to call rx_data provided by the * mid-level in order to continue processing this command. * Return 0 for success and < 0 for trouble * This command is expected to be NON-BLOCKING. * MUST HAVE. */ int (* rdy_to_xfer)(struct SC*); /* * task_mgmt_fn_done: This function informs the driver that a * received task management function has been completed. This * function is necessary because low-level protocols have some * means of informing the initiator about the completion of a * Task Management function. This function being called will * signify that a Task Management function is completed as far * as the mid-level is concerned. Any information that must be * stored about the command is the responsibility of the low- * level driver. The field SC is relevant only for ABORT tasks * No return value expected. * This function is expected to be NON-BLOCKING * MUST HAVE if the front-end supports ABORTs */ void (* task_mgmt_fn_done)(struct SM*); /* * report_aen: This function is used for Asynchronous Event * Notification. Since the Mid-Level does not have a mechanism * to know about initiators logged in with low-level driver, it * is the responsibility of the driver to notify any/all * initiators about the Asynchronous Event reported. * 0 for success, and < 0 for trouble * This command is expected to be NON-BLOCKING * MUST HAVE if low-level protocol supports AEN */ void (* report_aen)(int /* MGMT FN */, __u64 /* LUN */);} Scsi_Target_Template;/* * Scsi_Target_Device: This is an internal struct that is created to define * a device list in the struct GTE. Thus one STT could potentially * correspond to multiple devices. The only thing that the front end should * actually care about is the device id. This is defined by SAM as a 64 bit * entity. I should change this one pretty soon. */typedef struct STD{ __u64 id; /* device id */ struct STD *next; /* next one in the list */ /* dev_specific: my idea behind keeping this field was that this * should help the front end target driver store a pointer to a * struct that is a super-set of the Scsi_Target_Device where it * stores system specific values. This should help the front-end * locate the front-end easily instead of doing a search every * time. (kind of like hostdata in Scsi_Host). Allocation and * deallocation of memory for it is the responsibility of the * front-end. THIS IS THE ONLY FIELD THAT SHOULD BE MODIFIED BY * THE FRONT-END DRIVER */ void *dev_specific; Scsi_Target_Template *template; /* ptr to available functions */} Scsi_Target_Device;/* * Target_Emulator: This is the "global" target struct. All information * within the system flows from this target struct. It also serves as a * repository for all that is global to the target emulator system */typedef struct GTE{ /* * command_id: This is a counter to decide what command_id gets * assigned to a command that gets queued. 0 is not a valid command. * Also, command_ids can wrap around. I also assume that if command * _ids wrap-around, then all commands with that particular command * _id have already been dealt with. There is a miniscule (?) chance * that this may not be the case - but I do not deal with it */ int command_id; /* * thread_sem: semaphore to control the synchronization of * killing the thread */ struct semaphore thread_sem; /* * signal_sem: semaphore to control the killing of the signal * processing thread */ struct semaphore signal_sem; /* * sig_thr_sem: the signal thread sleeps on this semaphore */ struct semaphore sig_thr_sem; /* * signal_id: pointer to the signal_process_thread. Will be used * to kill the thread when necessary */ struct task_struct *signal_id; /* * target_sem: semaphore to control the mid-level thread synchronizn * i.e., when it sleeps and when it awakens */ struct semaphore target_sem; /* * thread_id: this task struct will store the pointer to the SCSI * Mid-level thread - useful to kill the thread when necessary */ struct task_struct *thread_id; /* * st_device_list: pointer to the list of devices. I have not added * any semaphores around this list simply because I do not expect * multiple devices to register simultaneously (Am I correct ?) */ Scsi_Target_Device *st_device_list; /* * st_target_template: pointer to the target template. Each template * in this list can have multiple devices */ Scsi_Target_Template *st_target_template; /* this may change */ /* * cmd_queue_lock: this spinlock must be acquired whenever the * cmd_queue is accessed. The spinlock is essential because * received CDBs can get queued up in the context of an * interrupt handler so we have to a spinlock, not a semaphore. */ spinlock_t cmd_queue_lock; /* * cmd_queue: doubly linked circular queue of commands */ struct list_head cmd_queue; /* * msgq_start: pointer to the start of the message queue */ Target_Scsi_Message *msgq_start; /* * msgq_end: pointer to the end of the message queue */ Target_Scsi_Message *msgq_end; /* * msg_lock: spinlock for the message */ spinlock_t msg_lock;} Target_Emulator;/* number of devices target currently has access to */extern int target_count;/* function prototypes *//* these are entry points provided to the low-level driver */int register_target_template (Scsi_Target_Template*);int deregister_target_template (Scsi_Target_Template*);int scsi_target_done (Target_Scsi_Cmnd*);int deregister_target_front_end (Scsi_Target_Device*);int scsi_rx_data (Target_Scsi_Cmnd*);int scsi_release (Target_Scsi_Cmnd*);Scsi_Target_Device* register_target_front_end (Scsi_Target_Template*);Target_Scsi_Cmnd* rx_cmnd (Scsi_Target_Device*, __u64, __u64, unsigned char*, int, int, int, Target_Scsi_Cmnd**);Target_Scsi_Message* rx_task_mgmt_fn (Scsi_Target_Device*,int,void*);/* * Returns 1 if any luns for this target are in use. * Returns 0 otherwise. */extern inttarget_in_use(__u32 target_id);#if !defined(list_for_each_entry)/* include/linux/list.h is out of date *//** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop counter. * @head: the head for your list. * @member: the name of the list_struct within the struct. */#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ prefetch(pos->member.next); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member), \ prefetch(pos->member.next))#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -