| 162 | } |
| 163 | |
| 164 | void SCSIST::ModeSelect(scsi_command cmd, cdb_t cdb, span<const uint8_t> buff, int length) |
| 165 | { |
| 166 | /* |
| 167 | +=====-========-========-========-========-========-========-========-========+ |
| 168 | | Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
| 169 | |Byte | | | | | | | | | |
| 170 | |=====+=======================================================================| |
| 171 | | 0 | Operation code (15h) | |
| 172 | |-----+-----------------------------------------------------------------------| |
| 173 | | 1 | Logical unit number | PF | Reserved | SP | |
| 174 | |-----+-----------------------------------------------------------------------| |
| 175 | | 2 | Reserved | |
| 176 | |-----+-----------------------------------------------------------------------| |
| 177 | | 3 | Reserved | |
| 178 | |-----+-----------------------------------------------------------------------| |
| 179 | | 4 | Parameter list length | |
| 180 | |-----+-----------------------------------------------------------------------| |
| 181 | | 5 | Control | |
| 182 | +=============================================================================+ |
| 183 | */ |
| 184 | if (cmd != scsi_command::eCmdModeSelect6 || length < 12) |
| 185 | throw scsi_exception(sense_key::illegal_request, asc::invalid_command_operation_code); |
| 186 | |
| 187 | // If the PF-bit is set to zero, the |
| 188 | // Drive will not accept any Mode Pages in the parameter list; only the |
| 189 | // Header List and a Block Descriptor List will be accepted. If the Drive |
| 190 | // receives a parameter list containing bytes beyond the Header List and a |
| 191 | // Block Descriptor List, it will terminate the MODE SELECT command |
| 192 | // with CHECK CONDITION and set the Sense Key to ILLEGAL REQUEST and the AS/AQ sense bytes to PARAMETER LIST LENGTH |
| 193 | // ERROR. The Error Code will be set to E$STE_PLEN. |
| 194 | bool pf = cdb[1] & 0x10; |
| 195 | |
| 196 | |
| 197 | // A Save Page (SP) bit of zero indicates that the Drive will perform the |
| 198 | // specified MODE SELECT operation, but not save any mode parameters. |
| 199 | // A SP bit of one indicates that the Drive will perform the specified |
| 200 | // MODE SELECT operation and also save all saveable MODE SELECT |
| 201 | // parameters received during the DATA OUT phase. |
| 202 | bool sp = cdb[1] & 0x01;// this one is tricky, should we have two sets of settings ?!?!? |
| 203 | |
| 204 | |
| 205 | // This field specifies the length in bytes of the MODE SELECT parameter |
| 206 | // list that will be transferred from the Initiator to the Drive during the |
| 207 | // DATA OUT phase. A Parameter List Length of zero indicates that no |
| 208 | // data will be transferred. No mode selection parameters are then |
| 209 | // changed. A parameter list length must never result in the truncation of |
| 210 | // any header, descriptor or page of parameters. |
| 211 | uint8_t params_list_len = cdb[4] & 0xff; |
| 212 | if ((!pf && params_list_len != 12) || params_list_len < 12 || params_list_len > length) |
| 213 | throw scsi_exception(sense_key::illegal_request, asc::parameter_list_length_error); |
| 214 | |
| 215 | // Header List |
| 216 | |
| 217 | // Check Block Descriptor Length |
| 218 | if (buff[3] != 0x08) |
| 219 | throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_parameter_list); |
| 220 | |
| 221 | // Block Descriptor List |
nothing calls this directly
no test coverage detected