Add the concept of a "user pointer" (similar to the void __user * in
[people/xl0/gpxe.git] / src / include / gpxe / scsi.h
1 #ifndef _GPXE_SCSI_H
2 #define _GPXE_SCSI_H
3
4 #include <stdint.h>
5 #include <gpxe/blockdev.h>
6 #include <gpxe/uaccess.h>
7
8 /**
9  * @defgroup scsiops SCSI operation codes
10  * @{
11  */
12
13 #define SCSI_OPCODE_READ_16             0x88    /**< READ (16) */
14 #define SCSI_OPCODE_WRITE_16            0x8a    /**< WRITE (16) */
15 #define SCSI_OPCODE_SERVICE_ACTION_IN   0x9e    /**< SERVICE ACTION IN */
16 #define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
17
18 /** @} */
19
20 /**
21  * @defgroup scsiflags SCSI flags
22  * @{
23  */
24
25 #define SCSI_FL_FUA_NV          0x02    /**< Force unit access to NVS */
26 #define SCSI_FL_FUA             0x08    /**< Force unit access */
27 #define SCSI_FL_DPO             0x10    /**< Disable cache page out */
28
29 /** @} */
30
31 /**
32  * @defgroup scsicdbs SCSI command data blocks
33  * @{
34  */
35
36 /** A SCSI "READ (16)" CDB */
37 struct scsi_cdb_read_16 {
38         /** Opcode (0x88) */
39         uint8_t opcode;
40         /** Flags */
41         uint8_t flags;
42         /** Start address
43          *
44          * This is a logical block number, in big-endian order.
45          */
46         uint64_t lba;
47         /** Transfer length
48          *
49          * This is a logical block count, in big-endian order.
50          */
51         uint32_t len;
52         /** Group number */
53         uint8_t group;
54         /** Control byte */
55         uint8_t control;
56 } __attribute__ (( packed ));
57
58 /** A SCSI "WRITE (16)" CDB */
59 struct scsi_cdb_write_16 {
60         /** Opcode (0x8a) */
61         uint8_t opcode;
62         /** Flags */
63         uint8_t flags;
64         /** Start address
65          *
66          * This is a logical block number, in big-endian order.
67          */
68         uint64_t lba;
69         /** Transfer length
70          *
71          * This is a logical block count, in big-endian order.
72          */
73         uint32_t len;
74         /** Group number */
75         uint8_t group;
76         /** Control byte */
77         uint8_t control;
78 } __attribute__ (( packed ));
79
80 /** A SCSI "READ CAPACITY (16)" CDB */
81 struct scsi_cdb_read_capacity_16 {
82         /** Opcode (0x9e) */
83         uint8_t opcode;
84         /** Service action */
85         uint8_t service_action;
86         /** Logical block address
87          *
88          * Applicable only if the PMI bit is set.
89          */
90         uint64_t lba;
91         /** Transfer length
92          *
93          * This is the size of the data-in buffer, in bytes.
94          */
95         uint32_t len;
96         /** Reserved */
97         uint8_t reserved;
98         /** Control byte */
99         uint8_t control;
100 } __attribute__ (( packed ));
101
102 /** SCSI "READ CAPACITY (16)" parameter data */
103 struct scsi_capacity_16 {
104         /** Maximum logical block number */
105         uint64_t lba;
106         /** Block length in bytes */
107         uint32_t blksize;
108         /** Reserved */
109         uint8_t reserved[20];
110 } __attribute__ (( packed ));
111
112 /** A SCSI Command Data Block */
113 union scsi_cdb {
114         struct scsi_cdb_read_16 read16;
115         struct scsi_cdb_write_16 write16;
116         struct scsi_cdb_read_capacity_16 readcap16;
117         char bytes[16];
118 };
119
120 /** @} */
121
122 /** A SCSI command */
123 struct scsi_command {
124         /** CDB for this command */
125         union scsi_cdb cdb;
126         /** Data-out buffer (may be NULL) */
127         userptr_t data_out;
128         /** Data-out buffer length
129          *
130          * Must be zero if @c data_out is NULL
131          */
132         size_t data_out_len;
133         /** Data-in buffer (may be NULL) */
134         userptr_t data_in;
135         /** Data-in buffer length
136          *
137          * Must be zero if @c data_in is NULL
138          */
139         size_t data_in_len;
140         /** SCSI statua code */
141         uint8_t status;
142         /** SCSI sense response code */
143         uint8_t sense_response;
144 };
145
146 /** A SCSI device */
147 struct scsi_device {
148         /** Block device interface */
149         struct block_device blockdev;
150         /** Logical unit number (LUN)
151          *
152          * This is a four-level LUN as specified by SAM-2, in
153          * big-endian order.
154          */
155         uint64_t lun;
156         /**
157          * Issue SCSI command
158          *
159          * @v scsi              SCSI device
160          * @v command           SCSI command
161          * @ret rc              Return status code
162          *
163          * Note that a successful return status code indicates only
164          * that the SCSI command completed.  The caller must check the
165          * status field in the command structure to see if, for
166          * example, the device returned CHECK CONDITION or some other
167          * non-success status code.
168          */
169         int ( * command ) ( struct scsi_device *scsi,
170                             struct scsi_command *command );
171 };
172
173 extern int init_scsidev ( struct scsi_device *scsi );
174
175 #endif /* _GPXE_SCSI_H */