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