V4.7 release fixes
[SCSI2SD.git] / software / SCSI2SD / src / scsi.h
1 //      Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
2 //
3 //      This file is part of SCSI2SD.
4 //
5 //      SCSI2SD is free software: you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation, either version 3 of the License, or
8 //      (at your option) any later version.
9 //
10 //      SCSI2SD is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
17 #ifndef SCSI_H
18 #define SCSI_H
19
20 #include "geometry.h"
21 #include "sense.h"
22
23 typedef enum
24 {
25         // internal bits
26         __scsiphase_msg = 1,
27         __scsiphase_cd = 2,
28         __scsiphase_io = 4,
29
30         BUS_FREE = -1,
31         BUS_BUSY = -2,
32         ARBITRATION = -3,
33         SELECTION = -4,
34         RESELECTION = -5,
35         STATUS = __scsiphase_cd | __scsiphase_io,
36         COMMAND = __scsiphase_cd,
37         DATA_IN = __scsiphase_io,
38         DATA_OUT = 0,
39         MESSAGE_IN = __scsiphase_msg | __scsiphase_cd | __scsiphase_io,
40         MESSAGE_OUT = __scsiphase_msg | __scsiphase_cd
41 } SCSI_PHASE;
42
43 typedef enum
44 {
45         GOOD = 0,
46         CHECK_CONDITION = 2,
47         BUSY = 0x8,
48         INTERMEDIATE = 0x10,
49         CONFLICT = 0x18
50 } SCSI_STATUS;
51
52 typedef enum
53 {
54         MSG_COMMAND_COMPLETE = 0,
55         MSG_REJECT = 0x7,
56         MSG_LINKED_COMMAND_COMPLETE = 0x0A,
57         MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG = 0x0B
58 } SCSI_MESSAGE;
59
60 typedef enum
61 {
62         COMPAT_UNKNOWN,
63         COMPAT_SCSI1,
64
65         // Messages are being used, yet SCSI 2 mode is disabled.
66         // This impacts interpretation of INQUIRY commands.
67         COMPAT_SCSI2_DISABLED,
68
69         COMPAT_SCSI2
70 } SCSI_COMPAT_MODE;
71
72 // Maximum value for bytes-per-sector.
73 #define MAX_SECTOR_SIZE 8192
74 #define MIN_SECTOR_SIZE 64
75
76 // Shadow parameters, possibly not saved to flash yet.
77 // Set via Mode Select
78 typedef struct
79 {
80         uint16_t bytesPerSector;
81 } LiveCfg;
82
83 typedef struct
84 {
85         uint8_t targetId;
86
87         const TargetConfig* cfg;
88
89         LiveCfg liveCfg;
90
91         ScsiSense sense;
92
93         uint16 unitAttention; // Set to the sense qualifier key to be returned.
94
95         // Only let the reserved initiator talk to us.
96         // A 3rd party may be sending the RESERVE/RELEASE commands
97         int reservedId; // 0 -> 7 if reserved. -1 if not reserved.
98         int reserverId; // 0 -> 7 if reserved. -1 if not reserved.
99 } TargetState;
100
101 typedef struct
102 {
103         TargetState targets[MAX_SCSI_TARGETS];
104         TargetState* target;
105         BoardConfig boardCfg;
106
107
108         // Set to true (1) if the ATN flag was set, and we need to
109         // enter the MESSAGE_OUT phase.
110         int atnFlag;
111
112         // Set to true (1) if the RST flag was set.
113         volatile int resetFlag;
114
115         // Set to true (1) if the SEL flag was set.
116         volatile int selFlag;
117         
118         // Set to true (1) if a parity error was observed.
119     int parityError;
120
121         volatile int selDBX;
122
123         int phase;
124
125         uint8 data[MAX_SECTOR_SIZE * 2];
126         int dataPtr; // Index into data, reset on [re]selection to savedDataPtr
127         int savedDataPtr; // Index into data, initially 0.
128         int dataLen;
129
130         uint8 cdb[12]; // command descriptor block
131         uint8 cdbLen; // 6, 10, or 12 byte message.
132         int8 lun; // Target lun, set by IDENTIFY message.
133         uint8 discPriv; // Disconnect priviledge.
134         uint8_t compatMode; // SCSI_COMPAT_MODE
135
136         // Only let the reserved initiator talk to us.
137         // A 3rd party may be sending the RESERVE/RELEASE commands
138         int initiatorId; // 0 -> 7. Set during the selection phase.
139
140         // SCSI_STATUS value.
141         // Change to CHECK_CONDITION when setting a SENSE value
142         uint8 status;
143
144         uint8 msgIn;
145         uint8 msgOut;
146
147         void (*postDataOutHook)(void);
148
149         uint8 cmdCount;
150         uint8 selCount;
151         uint8 rstCount;
152         uint8 msgCount;
153         uint8 watchdogTick;
154         uint8 lastStatus;
155         uint8 lastSense;
156         uint16_t lastSenseASC;
157 } ScsiDevice;
158
159 extern ScsiDevice scsiDev;
160
161 void process_Status(void);
162 void process_MessageIn(void);
163
164 void scsiInit(void);
165 void scsiPoll(void);
166 void scsiDisconnect(void);
167 int scsiReconnect(void);
168
169
170 // Utility macros, consistent with the Linux Kernel code.
171 #define likely(x)       __builtin_expect(!!(x), 1)
172 #define unlikely(x)     __builtin_expect(!!(x), 0)
173 //#define likely(x)       (x)
174 //#define unlikely(x)     (x)
175 #endif