2a48af38d5aeb24de12c0d168703e5680e73fa50
[SCSI2SD-V6.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 // Maximum value for bytes-per-sector.
61 #define MAX_SECTOR_SIZE 8192
62 #define MIN_SECTOR_SIZE 64
63
64 // Shadow parameters, possibly not saved to flash yet.
65 // Set via Mode Select
66 typedef struct
67 {
68 uint16_t bytesPerSector;
69 } LiveCfg;
70
71 typedef struct
72 {
73 uint8_t targetId;
74
75 const TargetConfig* cfg;
76
77 LiveCfg liveCfg;
78
79 ScsiSense sense;
80
81 uint16 unitAttention; // Set to the sense qualifier key to be returned.
82
83 // Only let the reserved initiator talk to us.
84 // A 3rd party may be sending the RESERVE/RELEASE commands
85 int reservedId; // 0 -> 7 if reserved. -1 if not reserved.
86 int reserverId; // 0 -> 7 if reserved. -1 if not reserved.
87 } TargetState;
88
89 typedef struct
90 {
91 TargetState targets[MAX_SCSI_TARGETS];
92 TargetState* target;
93
94 // Set to true (1) if the ATN flag was set, and we need to
95 // enter the MESSAGE_OUT phase.
96 volatile int atnFlag;
97
98 // Set to true (1) if the RST flag was set.
99 volatile int resetFlag;
100
101 // Set to true (1) if a parity error was observed.
102 int parityError;
103
104 int phase;
105
106 uint8 data[MAX_SECTOR_SIZE * 2];
107 int dataPtr; // Index into data, reset on [re]selection to savedDataPtr
108 int savedDataPtr; // Index into data, initially 0.
109 int dataLen;
110
111 uint8 cdb[12]; // command descriptor block
112 uint8 cdbLen; // 6, 10, or 12 byte message.
113 int8 lun; // Target lun, set by IDENTIFY message.
114 uint8 discPriv; // Disconnect priviledge.
115 uint8_t compatMode; // true for SCSI1 and SASI hosts.
116
117 // Only let the reserved initiator talk to us.
118 // A 3rd party may be sending the RESERVE/RELEASE commands
119 int initiatorId; // 0 -> 7. Set during the selection phase.
120
121 // SCSI_STATUS value.
122 // Change to CHECK_CONDITION when setting a SENSE value
123 uint8 status;
124
125 uint8 msgIn;
126 uint8 msgOut;
127
128 void (*postDataOutHook)(void);
129
130 uint8 cmdCount;
131 uint8 selCount;
132 uint8 rstCount;
133 uint8 msgCount;
134 uint8 watchdogTick;
135 uint8 lastStatus;
136 uint8 lastSense;
137 uint16_t lastSenseASC;
138 } ScsiDevice;
139
140 extern ScsiDevice scsiDev;
141
142 void process_Status(void);
143 void process_MessageIn(void);
144
145 void scsiInit(void);
146 void scsiPoll(void);
147 void scsiDisconnect(void);
148 int scsiReconnect(void);
149
150
151 // Utility macros, consistent with the Linux Kernel code.
152 #define likely(x) __builtin_expect(!!(x), 1)
153 #define unlikely(x) __builtin_expect(!!(x), 0)
154 //#define likely(x) (x)
155 //#define unlikely(x) (x)
156 #endif