Rev 4549 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4549 | Rev 5051 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | ; standard driver stuff |
1 | ; standard driver stuff; version of driver model = 5 |
2 | format MS COFF |
2 | format PE DLL native 0.05 |
- | 3 | entry START |
|
Line 3... | Line 4... | ||
3 | 4 | ||
4 | DEBUG = 1 |
5 | DEBUG = 1 |
Line 5... | Line 6... | ||
5 | DUMP_PACKETS = 0 |
6 | DUMP_PACKETS = 0 |
6 | 7 | ||
7 | ; this is for DEBUGF macro from 'fdo.inc' |
8 | ; this is for DEBUGF macro from 'fdo.inc' |
Line 8... | Line -... | ||
8 | __DEBUG__ = 1 |
- | |
9 | __DEBUG_LEVEL__ = 1 |
9 | __DEBUG__ = 1 |
10 | - | ||
11 | include 'proc32.inc' |
- | |
12 | include 'imports.inc' |
- | |
13 | include 'fdo.inc' |
- | |
Line 14... | Line 10... | ||
14 | 10 | __DEBUG_LEVEL__ = 1 |
|
15 | public START |
11 | |
16 | public version |
12 | include '../struct.inc' |
17 | 13 | ||
Line 27... | Line 23... | ||
27 | ISOCHRONOUS_PIPE = 1 |
23 | ISOCHRONOUS_PIPE = 1 |
28 | BULK_PIPE = 2 |
24 | BULK_PIPE = 2 |
29 | INTERRUPT_PIPE = 3 |
25 | INTERRUPT_PIPE = 3 |
Line 30... | Line 26... | ||
30 | 26 | ||
31 | ; USB structures |
- | |
32 | virtual at 0 |
27 | ; USB structures |
33 | config_descr: |
28 | struct config_descr |
34 | .bLength db ? |
29 | bLength db ? |
35 | .bDescriptorType db ? |
30 | bDescriptorType db ? |
36 | .wTotalLength dw ? |
31 | wTotalLength dw ? |
37 | .bNumInterfaces db ? |
32 | bNumInterfaces db ? |
38 | .bConfigurationValue db ? |
33 | bConfigurationValue db ? |
39 | .iConfiguration db ? |
34 | iConfiguration db ? |
40 | .bmAttributes db ? |
35 | bmAttributes db ? |
41 | .bMaxPower db ? |
- | |
42 | .sizeof: |
36 | bMaxPower db ? |
43 | end virtual |
37 | ends |
44 | - | ||
45 | virtual at 0 |
38 | |
46 | interface_descr: |
39 | struct interface_descr |
47 | .bLength db ? |
40 | bLength db ? |
48 | .bDescriptorType db ? |
41 | bDescriptorType db ? |
49 | .bInterfaceNumber db ? |
42 | bInterfaceNumber db ? |
50 | .bAlternateSetting db ? |
43 | bAlternateSetting db ? |
51 | .bNumEndpoints db ? |
44 | bNumEndpoints db ? |
52 | .bInterfaceClass db ? |
45 | bInterfaceClass db ? |
53 | .bInterfaceSubClass db ? |
46 | bInterfaceSubClass db ? |
54 | .bInterfaceProtocol db ? |
47 | bInterfaceProtocol db ? |
55 | .iInterface db ? |
- | |
56 | .sizeof: |
48 | iInterface db ? |
57 | end virtual |
49 | ends |
58 | - | ||
59 | virtual at 0 |
50 | |
60 | endpoint_descr: |
51 | struct endpoint_descr |
61 | .bLength db ? |
52 | bLength db ? |
62 | .bDescriptorType db ? |
53 | bDescriptorType db ? |
63 | .bEndpointAddress db ? |
54 | bEndpointAddress db ? |
64 | .bmAttributes db ? |
55 | bmAttributes db ? |
65 | .wMaxPacketSize dw ? |
56 | wMaxPacketSize dw ? |
66 | .bInterval db ? |
- | |
67 | .sizeof: |
57 | bInterval db ? |
Line 68... | Line 58... | ||
68 | end virtual |
58 | ends |
69 | 59 | ||
70 | ; Mass storage protocol constants, USB layer |
60 | ; Mass storage protocol constants, USB layer |
Line 71... | Line 61... | ||
71 | REQUEST_GETMAXLUN = 0xFE ; get max lun |
61 | REQUEST_GETMAXLUN = 0xFE ; get max lun |
72 | REQUEST_BORESET = 0xFF ; bulk-only reset |
62 | REQUEST_BORESET = 0xFF ; bulk-only reset |
73 | 63 | ||
74 | ; Mass storage protocol structures, USB layer |
- | |
75 | ; Sent from host to device in the first stage of an operation. |
64 | ; Mass storage protocol structures, USB layer |
76 | struc command_block_wrapper |
65 | ; Sent from host to device in the first stage of an operation. |
77 | { |
66 | struct command_block_wrapper |
78 | .Signature dd ? ; the constant 'USBC' |
67 | Signature dd ? ; the constant 'USBC' |
79 | .Tag dd ? ; identifies response with request |
68 | Tag dd ? ; identifies response with request |
80 | .Length dd ? ; length of data-transport phase |
69 | Length dd ? ; length of data-transport phase |
81 | .Flags db ? ; one of CBW_FLAG_* |
70 | Flags db ? ; one of CBW_FLAG_* |
82 | CBW_FLAG_OUT = 0 |
71 | CBW_FLAG_OUT = 0 |
83 | CBW_FLAG_IN = 80h |
72 | CBW_FLAG_IN = 80h |
84 | .LUN db ? ; addressed unit |
- | |
85 | .CommandLength db ? ; the length of the following field |
- | |
86 | .Command rb 16 |
- | |
87 | .sizeof: |
- | |
88 | } |
73 | LUN db ? ; addressed unit |
Line 89... | Line 74... | ||
89 | virtual at 0 |
74 | CommandLength db ? ; the length of the following field |
90 | command_block_wrapper command_block_wrapper |
75 | Command rb 16 |
91 | end virtual |
- | |
92 | 76 | ends |
|
93 | ; Sent from device to host in the last stage of an operation. |
77 | |
94 | struc command_status_wrapper |
78 | ; Sent from device to host in the last stage of an operation. |
95 | { |
79 | struct command_status_wrapper |
96 | .Signature dd ? ; the constant 'USBS' |
80 | Signature dd ? ; the constant 'USBS' |
97 | .Tag dd ? ; identifies response with request |
81 | Tag dd ? ; identifies response with request |
98 | .LengthRest dd ? ; .Length - (size of data which were transferred) |
82 | LengthRest dd ? ; .Length - (size of data which were transferred) |
99 | .Status db ? ; one of CSW_STATUS_* |
- | |
100 | CSW_STATUS_OK = 0 |
- | |
101 | CSW_STATUS_FAIL = 1 |
- | |
102 | CSW_STATUS_FATAL = 2 |
- | |
103 | .sizeof: |
83 | Status db ? ; one of CSW_STATUS_* |
Line 104... | Line 84... | ||
104 | } |
84 | CSW_STATUS_OK = 0 |
105 | virtual at 0 |
85 | CSW_STATUS_FAIL = 1 |
106 | command_status_wrapper command_status_wrapper |
86 | CSW_STATUS_FATAL = 2 |
107 | end virtual |
87 | ends |
Line 131... | Line 111... | ||
131 | SENSE_MISCOMPARE = 14 |
111 | SENSE_MISCOMPARE = 14 |
132 | ; 15 is reserved |
112 | ; 15 is reserved |
Line 133... | Line 113... | ||
133 | 113 | ||
134 | ; Structures of SCSI layer |
114 | ; Structures of SCSI layer |
135 | ; Result of SCSI INQUIRY request. |
115 | ; Result of SCSI INQUIRY request. |
136 | struc inquiry_data |
- | |
137 | { |
116 | struct inquiry_data |
138 | .PeripheralDevice db ? ; lower 5 bits are PeripheralDeviceType |
117 | PeripheralDevice db ? ; lower 5 bits are PeripheralDeviceType |
139 | ; upper 3 bits are PeripheralQualifier |
118 | ; upper 3 bits are PeripheralQualifier |
140 | .RemovableMedium db ? ; upper bit is RemovableMedium |
119 | RemovableMedium db ? ; upper bit is RemovableMedium |
141 | ; other bits are for compatibility |
120 | ; other bits are for compatibility |
142 | .Version db ? ; lower 3 bits are ANSI-Approved version |
121 | Version db ? ; lower 3 bits are ANSI-Approved version |
143 | ; next 3 bits are ECMA version |
122 | ; next 3 bits are ECMA version |
144 | ; upper 2 bits are ISO version |
123 | ; upper 2 bits are ISO version |
145 | .ResponseDataFormat db ? ; lower 4 bits are ResponseDataFormat |
124 | ResponseDataFormat db ? ; lower 4 bits are ResponseDataFormat |
146 | ; bit 6 is TrmIOP |
125 | ; bit 6 is TrmIOP |
147 | ; bit 7 is AENC |
126 | ; bit 7 is AENC |
148 | .AdditionalLength db ? |
127 | AdditionalLength db ? |
149 | dw ? ; reserved |
128 | dw ? ; reserved |
150 | .Flags db ? |
129 | Flags db ? |
151 | .VendorID rb 8 ; vendor ID, big-endian |
130 | VendorID rb 8 ; vendor ID, big-endian |
152 | .ProductID rb 16 ; product ID, big-endian |
131 | ProductID rb 16 ; product ID, big-endian |
153 | .ProductRevBE dd ? ; product revision, big-endian |
- | |
154 | .sizeof: |
- | |
155 | } |
- | |
156 | virtual at 0 |
- | |
157 | inquiry_data inquiry_data |
132 | ProductRevBE dd ? ; product revision, big-endian |
Line 158... | Line 133... | ||
158 | end virtual |
133 | ends |
159 | - | ||
160 | struc sense_data |
134 | |
161 | { |
135 | struct sense_data |
162 | .ErrorCode db ? ; lower 7 bits are error code: |
136 | ErrorCode db ? ; lower 7 bits are error code: |
163 | ; 70h = current error, |
137 | ; 70h = current error, |
164 | ; 71h = deferred error |
138 | ; 71h = deferred error |
165 | ; upper bit is InformationValid |
139 | ; upper bit is InformationValid |
166 | .SegmentNumber db ? ; number of segment descriptor |
140 | SegmentNumber db ? ; number of segment descriptor |
167 | ; for commands COPY [+VERIFY], COMPARE |
141 | ; for commands COPY [+VERIFY], COMPARE |
168 | .SenseKey db ? ; bits 0-3 are one of SENSE_* |
142 | SenseKey db ? ; bits 0-3 are one of SENSE_* |
169 | ; bit 4 is reserved |
143 | ; bit 4 is reserved |
170 | ; bit 5 is IncorrectLengthIndicator |
144 | ; bit 5 is IncorrectLengthIndicator |
171 | ; bits 6 and 7 are used by |
145 | ; bits 6 and 7 are used by |
172 | ; sequential-access devices |
146 | ; sequential-access devices |
173 | .Information dd ? ; command-specific |
147 | Information dd ? ; command-specific |
174 | .AdditionalLength db ? ; length of data starting here |
148 | AdditionalLength db ? ; length of data starting here |
175 | .CommandInformation dd ? ; command-specific |
149 | CommandInformation dd ? ; command-specific |
176 | .AdditionalSenseCode db ? ; \ more detailed error code |
150 | AdditionalSenseCode db ? ; \ more detailed error code |
177 | .AdditionalSenseQual db ? ; / standard has a large table of them |
151 | AdditionalSenseQual db ? ; / standard has a large table of them |
178 | .FRUCode db ? ; which part of device has failed |
152 | FRUCode db ? ; which part of device has failed |
179 | ; (device-specific, not regulated) |
- | |
180 | .SenseKeySpecific rb 3 ; depends on SenseKey |
- | |
181 | .sizeof: |
- | |
182 | } |
- | |
183 | virtual at 0 |
153 | ; (device-specific, not regulated) |
Line 184... | Line 154... | ||
184 | sense_data sense_data |
154 | SenseKeySpecific rb 3 ; depends on SenseKey |
185 | end virtual |
155 | ends |
186 | 156 | ||
187 | ; Device data |
157 | ; Device data |
188 | ; USB Mass storage device has one or more logical units, identified by LUN, |
- | |
189 | ; logical unit number. The highest value of LUN, that is, number of units |
158 | ; USB Mass storage device has one or more logical units, identified by LUN, |
190 | ; minus 1, can be obtained via control request Get Max LUN. |
159 | ; logical unit number. The highest value of LUN, that is, number of units |
191 | virtual at 0 |
160 | ; minus 1, can be obtained via control request Get Max LUN. |
192 | usb_device_data: |
161 | struct usb_device_data |
193 | .ConfigPipe dd ? ; configuration pipe |
162 | ConfigPipe dd ? ; configuration pipe |
194 | .OutPipe dd ? ; pipe for OUT bulk endpoint |
163 | OutPipe dd ? ; pipe for OUT bulk endpoint |
195 | .InPipe dd ? ; pipe for IN bulk endpoint |
164 | InPipe dd ? ; pipe for IN bulk endpoint |
196 | .MaxLUN dd ? ; maximum Logical Unit Number |
165 | MaxLUN dd ? ; maximum Logical Unit Number |
197 | .LogicalDevices dd ? ; pointer to array of usb_unit_data |
166 | LogicalDevices dd ? ; pointer to array of usb_unit_data |
198 | ; 1 for a connected USB device, 1 for each disk device |
167 | ; 1 for a connected USB device, 1 for each disk device |
199 | ; the structure can be freed when .NumReferences decreases to zero |
168 | ; the structure can be freed when .NumReferences decreases to zero |
200 | .NumReferences dd ? ; number of references |
169 | NumReferences dd ? ; number of references |
201 | .ConfigRequest rb 8 ; buffer for configuration requests |
170 | ConfigRequest rb 8 ; buffer for configuration requests |
202 | .LengthRest dd ? ; Length - (size of data which were transferred) |
171 | LengthRest dd ? ; Length - (size of data which were transferred) |
203 | ; All requests to a given device are serialized, |
172 | ; All requests to a given device are serialized, |
204 | ; only one request to a given device can be processed at a time. |
173 | ; only one request to a given device can be processed at a time. |
205 | ; The current request and all pending requests are organized in the following |
174 | ; The current request and all pending requests are organized in the following |
206 | ; queue, the head being the current request. |
175 | ; queue, the head being the current request. |
207 | ; NB: the queue must be device-wide due to the protocol: |
176 | ; NB: the queue must be device-wide due to the protocol: |
208 | ; data stage is not tagged (unlike command_*_wrapper), so the only way to know |
177 | ; data stage is not tagged (unlike command_*_wrapper), so the only way to know |
209 | ; what request the data are associated with is to guarantee that only one |
178 | ; what request the data are associated with is to guarantee that only one |
210 | ; request is processing at the time. |
179 | ; request is processing at the time. |
211 | .RequestsQueue rd 2 |
180 | RequestsQueue rd 2 |
212 | .QueueLock rd 3 ; protects .RequestsQueue |
181 | QueueLock rd 3 ; protects .RequestsQueue |
213 | .InquiryData inquiry_data ; information about device |
182 | InquiryData inquiry_data ; information about device |
214 | ; data for the current request |
183 | ; data for the current request |
215 | .Command command_block_wrapper |
184 | Command command_block_wrapper |
216 | .DeviceDisconnected db ? |
- | |
217 | .Status command_status_wrapper |
185 | DeviceDisconnected db ? |
Line 218... | Line 186... | ||
218 | .Sense sense_data |
186 | Status command_status_wrapper |
219 | .sizeof: |
- | |
220 | end virtual |
187 | Sense sense_data |
221 | 188 | ends |
|
222 | ; Information about one logical device. |
189 | |
223 | virtual at 0 |
190 | ; Information about one logical device. |
224 | usb_unit_data: |
191 | struct usb_unit_data |
225 | .Parent dd ? ; pointer to parent usb_device_data |
192 | Parent dd ? ; pointer to parent usb_device_data |
226 | .LUN db ? ; index in usb_device_data.LogicalDevices array |
193 | LUN db ? ; index in usb_device_data.LogicalDevices array |
227 | .DiskIndex db ? ; for name "usbhd |
194 | DiskIndex db ? ; for name "usbhd |
228 | .MediaPresent db ? |
195 | MediaPresent db ? |
229 | db ? ; alignment |
196 | db ? ; alignment |
230 | .DiskDevice dd ? ; handle of disk device or NULL |
197 | DiskDevice dd ? ; handle of disk device or NULL |
231 | .SectorSize dd ? ; sector size |
198 | SectorSize dd ? ; sector size |
232 | ; For some devices, the first request to the medium fails with 'unit not ready'. |
199 | ; For some devices, the first request to the medium fails with 'unit not ready'. |
233 | ; When the code sees this status, it retries the command several times. |
200 | ; When the code sees this status, it retries the command several times. |
234 | ; Two following variables track the retry count and total time for those; |
- | |
235 | ; total time is currently used only for debug output. |
201 | ; Two following variables track the retry count and total time for those; |
Line 236... | Line 202... | ||
236 | .UnitReadyAttempts dd ? |
202 | ; total time is currently used only for debug output. |
237 | .TimerTicks dd ? |
- | |
238 | .sizeof: |
203 | UnitReadyAttempts dd ? |
239 | end virtual |
204 | TimerTicks dd ? |
240 | 205 | ends |
|
241 | ; This is the structure for items in the queue usb_device_data.RequestsQueue. |
206 | |
242 | virtual at 0 |
207 | ; This is the structure for items in the queue usb_device_data.RequestsQueue. |
243 | request_queue_item: |
208 | struct request_queue_item |
244 | .Next dd ? ; next item in the queue |
209 | Next dd ? ; next item in the queue |
245 | .Prev dd ? ; prev item in the queue |
210 | Prev dd ? ; prev item in the queue |
246 | .ReqBuilder dd ? ; procedure to fill command_block_wrapper |
211 | ReqBuilder dd ? ; procedure to fill command_block_wrapper |
247 | .Buffer dd ? ; input or output data |
212 | Buffer dd ? ; input or output data |
248 | ; (length is command_block_wrapper.Length) |
213 | ; (length is command_block_wrapper.Length) |
249 | .Callback dd ? ; procedure to call in the end of transfer |
214 | Callback dd ? ; procedure to call in the end of transfer |
250 | .UserData dd ? ; passed as-is to .Callback |
215 | UserData dd ? ; passed as-is to .Callback |
251 | ; There are 3 possible stages of any request, one of them optional: |
216 | ; There are 3 possible stages of any request, one of them optional: |
252 | ; command stage (host sends command_block_wrapper to device), |
217 | ; command stage (host sends command_block_wrapper to device), |
253 | ; optional data stage, |
218 | ; optional data stage, |
254 | ; status stage (device sends command_status_wrapper to host). |
219 | ; status stage (device sends command_status_wrapper to host). |
- | 220 | ; Also, if a request fails, the code queues additional request |
|
- | 221 | ; SCSI_REQUEST_SENSE; sense_data from SCSI_REQUEST_SENSE |
|
- | 222 | ; contains some information about the error. |
|
255 | ; Also, if a request fails, the code queues additional request |
223 | Stage db ? |
- | 224 | ends |
|
- | 225 | ||
Line 256... | Line -... | ||
256 | ; SCSI_REQUEST_SENSE; sense_data from SCSI_REQUEST_SENSE |
- | |
257 | ; contains some information about the error. |
226 | section '.flat' code readable writable executable |
258 | .Stage db ? |
227 | include '../proc32.inc' |
259 | .sizeof: |
228 | include '../peimport.inc' |
260 | end virtual |
229 | include '../fdo.inc' |
261 | 230 | include '../macros.inc' |
|
- | 231 | ||
262 | section '.flat' code readable align 16 |
232 | ; The start procedure. |
263 | ; The start procedure. |
233 | proc START |
264 | proc START |
234 | virtual at esp |
265 | virtual at esp |
235 | dd ? ; return address |
266 | dd ? ; return address |
236 | .reason dd ? ; DRV_ENTRY or DRV_EXIT |
267 | .reason dd ? ; DRV_ENTRY or DRV_EXIT |
237 | .cmdline dd ? |
268 | end virtual |
238 | end virtual |
269 | ; 1. Test whether the procedure is called with the argument DRV_ENTRY. |
239 | ; 1. Test whether the procedure is called with the argument DRV_ENTRY. |
270 | ; If not, return 0. |
240 | ; If not, return 0. |
271 | xor eax, eax ; initialize return value |
241 | xor eax, eax ; initialize return value |
272 | cmp [.reason], 1 ; compare the argument |
242 | cmp [.reason], 1 ; compare the argument |
273 | jnz .nothing |
243 | jnz .nothing |
274 | ; 2. Initialize: we have one global mutex. |
244 | ; 2. Initialize: we have one global mutex. |
275 | mov ecx, free_numbers_lock |
245 | mov ecx, free_numbers_lock |
276 | call MutexInit |
246 | invoke MutexInit |
277 | ; 3. Register self as a USB driver. |
247 | ; 3. Register self as a USB driver. |
278 | ; The name is my_driver = 'usbstor'; IOCTL interface is not supported; |
248 | ; The name is my_driver = 'usbstor'; IOCTL interface is not supported; |
Line 279... | Line 249... | ||
279 | ; usb_functions is an offset of a structure with callback functions. |
249 | ; usb_functions is an offset of a structure with callback functions. |
Line 280... | Line 250... | ||
280 | stdcall RegUSBDriver, my_driver, 0, usb_functions |
250 | invoke RegUSBDriver, my_driver, 0, usb_functions |
Line 296... | Line 266... | ||
296 | .Buffer dd ? ; request_queue_item.Buffer |
266 | .Buffer dd ? ; request_queue_item.Buffer |
297 | .Callback dd ? ; request_queue_item.Callback |
267 | .Callback dd ? ; request_queue_item.Callback |
298 | .UserData dd ? ; request_queue_item.UserData |
268 | .UserData dd ? ; request_queue_item.UserData |
299 | end virtual |
269 | end virtual |
300 | ; 1. Allocate the memory for the request description. |
270 | ; 1. Allocate the memory for the request description. |
301 | movi eax, request_queue_item.sizeof |
271 | movi eax, sizeof.request_queue_item |
302 | call Kmalloc |
272 | invoke Kmalloc |
303 | test eax, eax |
273 | test eax, eax |
304 | jnz @f |
274 | jnz @f |
305 | mov esi, nomemory |
275 | mov esi, nomemory |
306 | call SysMsgBoardStr |
276 | invoke SysMsgBoardStr |
307 | pop esi ebx |
277 | pop esi ebx |
308 | ret 20 |
278 | ret 20 |
309 | @@: |
279 | @@: |
310 | ; 2. Fill user-provided parts of the request description. |
280 | ; 2. Fill user-provided parts of the request description. |
311 | push edi |
281 | push edi |
Line 320... | Line 290... | ||
320 | ; 3. Set stage to zero: not started. |
290 | ; 3. Set stage to zero: not started. |
321 | mov [ebx+request_queue_item.Stage], 0 |
291 | mov [ebx+request_queue_item.Stage], 0 |
322 | ; 4. Lock the queue. |
292 | ; 4. Lock the queue. |
323 | mov esi, [.device] |
293 | mov esi, [.device] |
324 | lea ecx, [esi+usb_device_data.QueueLock] |
294 | lea ecx, [esi+usb_device_data.QueueLock] |
325 | call MutexLock |
295 | invoke MutexLock |
326 | ; 5. Insert the request to the tail of the queue. |
296 | ; 5. Insert the request to the tail of the queue. |
327 | add esi, usb_device_data.RequestsQueue |
297 | add esi, usb_device_data.RequestsQueue |
328 | mov edx, [esi+request_queue_item.Prev] |
298 | mov edx, [esi+request_queue_item.Prev] |
329 | mov [ebx+request_queue_item.Next], esi |
299 | mov [ebx+request_queue_item.Next], esi |
330 | mov [ebx+request_queue_item.Prev], edx |
300 | mov [ebx+request_queue_item.Prev], edx |
Line 338... | Line 308... | ||
338 | ; start it. |
308 | ; start it. |
339 | sub esi, usb_device_data.RequestsQueue |
309 | sub esi, usb_device_data.RequestsQueue |
340 | call setup_request |
310 | call setup_request |
341 | jmp .nothing |
311 | jmp .nothing |
342 | .unlock: |
312 | .unlock: |
343 | call MutexUnlock |
313 | invoke MutexUnlock |
344 | ; 9. Return. |
314 | ; 9. Return. |
345 | .nothing: |
315 | .nothing: |
346 | pop esi ebx |
316 | pop esi ebx |
347 | ret 20 |
317 | ret 20 |
348 | endp |
318 | endp |
Line 367... | Line 337... | ||
367 | mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next] |
337 | mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next] |
368 | ; 3. Call the callback. |
338 | ; 3. Call the callback. |
369 | stdcall [ebx+request_queue_item.Callback], esi, [ebx+request_queue_item.UserData] |
339 | stdcall [ebx+request_queue_item.Callback], esi, [ebx+request_queue_item.UserData] |
370 | ; 4. Lock the queue. |
340 | ; 4. Lock the queue. |
371 | lea ecx, [esi+usb_device_data.QueueLock] |
341 | lea ecx, [esi+usb_device_data.QueueLock] |
372 | call MutexLock |
342 | invoke MutexLock |
373 | ; 5. Remove the request. |
343 | ; 5. Remove the request. |
374 | lea edx, [esi+usb_device_data.RequestsQueue] |
344 | lea edx, [esi+usb_device_data.RequestsQueue] |
375 | mov eax, [ebx+request_queue_item.Next] |
345 | mov eax, [ebx+request_queue_item.Next] |
376 | mov [eax+request_queue_item.Prev], edx |
346 | mov [eax+request_queue_item.Prev], edx |
377 | mov [edx+request_queue_item.Next], eax |
347 | mov [edx+request_queue_item.Next], eax |
378 | ; 6. Free the request memory. |
348 | ; 6. Free the request memory. |
379 | push eax edx |
349 | push eax edx |
380 | xchg eax, ebx |
350 | xchg eax, ebx |
381 | call Kfree |
351 | invoke Kfree |
382 | pop edx ebx |
352 | pop edx ebx |
383 | ; 7. If there is a next request, start processing. |
353 | ; 7. If there is a next request, start processing. |
384 | cmp ebx, edx |
354 | cmp ebx, edx |
385 | jnz setup_request |
355 | jnz setup_request |
386 | ; 8. Unlock the queue and return. |
356 | ; 8. Unlock the queue and return. |
387 | lea ecx, [esi+usb_device_data.QueueLock] |
357 | lea ecx, [esi+usb_device_data.QueueLock] |
388 | call MutexUnlock |
358 | invoke MutexUnlock |
389 | ret |
359 | ret |
390 | endp |
360 | endp |
Line 391... | Line 361... | ||
391 | 361 | ||
392 | ; Start processing the request. Called either by queue_request |
362 | ; Start processing the request. Called either by queue_request |
Line 408... | Line 378... | ||
408 | jb .norecovery |
378 | jb .norecovery |
409 | ; 2a. Send Bulk-Only Mass Storage Reset command to config pipe. |
379 | ; 2a. Send Bulk-Only Mass Storage Reset command to config pipe. |
410 | lea edx, [esi+usb_device_data.ConfigRequest] |
380 | lea edx, [esi+usb_device_data.ConfigRequest] |
411 | mov word [edx], (REQUEST_BORESET shl 8) + 21h ; class request |
381 | mov word [edx], (REQUEST_BORESET shl 8) + 21h ; class request |
412 | mov word [edx+6], ax ; length = 0 |
382 | mov word [edx+6], ax ; length = 0 |
413 | stdcall USBControlTransferAsync, [esi+usb_device_data.ConfigPipe], edx, eax, eax, recovery_callback1, esi, eax |
383 | invoke USBControlTransferAsync, [esi+usb_device_data.ConfigPipe], edx, eax, eax, recovery_callback1, esi, eax |
414 | ; 2b. Fail here = fatal error. |
384 | ; 2b. Fail here = fatal error. |
415 | test eax, eax |
385 | test eax, eax |
416 | jz .fatal |
386 | jz .fatal |
417 | ; 2c. Otherwise, unlock the queue and return. recovery_callback1 will continue processing. |
387 | ; 2c. Otherwise, unlock the queue and return. recovery_callback1 will continue processing. |
418 | .unlock_return: |
388 | .unlock_return: |
419 | lea ecx, [esi+usb_device_data.QueueLock] |
389 | lea ecx, [esi+usb_device_data.QueueLock] |
420 | call MutexUnlock |
390 | invoke MutexUnlock |
421 | ret |
391 | ret |
422 | .norecovery: |
392 | .norecovery: |
423 | ; 3. Send the command. Fail (no memory or device disconnected) = fatal error. |
393 | ; 3. Send the command. Fail (no memory or device disconnected) = fatal error. |
424 | ; Otherwise, go to 2c. |
394 | ; Otherwise, go to 2c. |
425 | call request_stage1 |
395 | call request_stage1 |
Line 427... | Line 397... | ||
427 | jnz .unlock_return |
397 | jnz .unlock_return |
428 | .fatal: |
398 | .fatal: |
429 | ; 4. Fatal error. Set status = FATAL, unlock the queue, complete the request. |
399 | ; 4. Fatal error. Set status = FATAL, unlock the queue, complete the request. |
430 | mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
400 | mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
431 | lea ecx, [esi+usb_device_data.QueueLock] |
401 | lea ecx, [esi+usb_device_data.QueueLock] |
432 | call MutexUnlock |
402 | invoke MutexUnlock |
433 | jmp complete_request |
403 | jmp complete_request |
434 | endp |
404 | endp |
Line 435... | Line 405... | ||
435 | 405 | ||
436 | ; Initiate USB transfer for the first stage of a request (send command). |
406 | ; Initiate USB transfer for the first stage of a request (send command). |
Line 451... | Line 421... | ||
451 | ; 4. Initiate USB transfer. |
421 | ; 4. Initiate USB transfer. |
452 | lea edx, [esi+usb_device_data.Command] |
422 | lea edx, [esi+usb_device_data.Command] |
453 | if DUMP_PACKETS |
423 | if DUMP_PACKETS |
454 | DEBUGF 1,'K : USBSTOR out:' |
424 | DEBUGF 1,'K : USBSTOR out:' |
455 | mov eax, edx |
425 | mov eax, edx |
456 | mov ecx, command_block_wrapper.sizeof |
426 | mov ecx, sizeof.command_block_wrapper |
457 | call debug_dump |
427 | call debug_dump |
458 | DEBUGF 1,'\n' |
428 | DEBUGF 1,'\n' |
459 | end if |
429 | end if |
460 | stdcall USBNormalTransferAsync, [esi+usb_device_data.OutPipe], edx, command_block_wrapper.sizeof, request_callback1, esi, 0 |
430 | invoke USBNormalTransferAsync, [esi+usb_device_data.OutPipe], edx, sizeof.command_block_wrapper, request_callback1, esi, 0 |
461 | test eax, eax |
431 | test eax, eax |
462 | jz .nothing |
432 | jz .nothing |
463 | ; 5. If the next stage is data stage in the same direction, enqueue it here. |
433 | ; 5. If the next stage is data stage in the same direction, enqueue it here. |
464 | cmp [esi+usb_device_data.Command.Flags], 0 |
434 | cmp [esi+usb_device_data.Command.Flags], 0 |
465 | js .nothing |
435 | js .nothing |
Line 471... | Line 441... | ||
471 | mov eax, [edx+request_queue_item.Buffer] |
441 | mov eax, [edx+request_queue_item.Buffer] |
472 | mov ecx, [esi+usb_device_data.Command.Length] |
442 | mov ecx, [esi+usb_device_data.Command.Length] |
473 | call debug_dump |
443 | call debug_dump |
474 | DEBUGF 1,'\n' |
444 | DEBUGF 1,'\n' |
475 | end if |
445 | end if |
476 | stdcall USBNormalTransferAsync, [esi+usb_device_data.OutPipe], [edx+request_queue_item.Buffer], [esi+usb_device_data.Command.Length], request_callback2, esi, 0 |
446 | invoke USBNormalTransferAsync, [esi+usb_device_data.OutPipe], [edx+request_queue_item.Buffer], [esi+usb_device_data.Command.Length], request_callback2, esi, 0 |
477 | .nothing: |
447 | .nothing: |
478 | ret |
448 | ret |
479 | endp |
449 | endp |
Line 480... | Line 450... | ||
480 | 450 | ||
Line 549... | Line 519... | ||
549 | jz ..request_get_status |
519 | jz ..request_get_status |
550 | ; 4b. If data were enqueued in the first stage, do nothing, wait for request_callback2. |
520 | ; 4b. If data were enqueued in the first stage, do nothing, wait for request_callback2. |
551 | cmp [ecx+usb_device_data.Command.Flags], 0 |
521 | cmp [ecx+usb_device_data.Command.Flags], 0 |
552 | jns .nothing |
522 | jns .nothing |
553 | ; 5. Initiate USB transfer. If this fails, go to the error handler. |
523 | ; 5. Initiate USB transfer. If this fails, go to the error handler. |
554 | stdcall USBNormalTransferAsync, [ecx+usb_device_data.InPipe], [edx+request_queue_item.Buffer], [ecx+usb_device_data.Command.Length], request_callback2, ecx, 0 |
524 | invoke USBNormalTransferAsync, [ecx+usb_device_data.InPipe], [edx+request_queue_item.Buffer], [ecx+usb_device_data.Command.Length], request_callback2, ecx, 0 |
555 | test eax, eax |
525 | test eax, eax |
556 | jz .error |
526 | jz .error |
557 | ; 6. The status stage goes to the same direction, enqueue it now. |
527 | ; 6. The status stage goes to the same direction, enqueue it now. |
558 | mov ecx, [.calldata] |
528 | mov ecx, [.calldata] |
559 | jmp ..enqueue_status |
529 | jmp ..enqueue_status |
Line 623... | Line 593... | ||
623 | mov edx, [ecx+usb_device_data.RequestsQueue+request_queue_item.Next] |
593 | mov edx, [ecx+usb_device_data.RequestsQueue+request_queue_item.Next] |
624 | inc [edx+request_queue_item.Stage] |
594 | inc [edx+request_queue_item.Stage] |
625 | ; 4. Initiate USB transfer. If this fails, go to the error handler. |
595 | ; 4. Initiate USB transfer. If this fails, go to the error handler. |
626 | ..enqueue_status: |
596 | ..enqueue_status: |
627 | lea edx, [ecx+usb_device_data.Status] |
597 | lea edx, [ecx+usb_device_data.Status] |
628 | stdcall USBNormalTransferAsync, [ecx+usb_device_data.InPipe], edx, command_status_wrapper.sizeof, request_callback3, ecx, 0 |
598 | invoke USBNormalTransferAsync, [ecx+usb_device_data.InPipe], edx, sizeof.command_status_wrapper, request_callback3, ecx, 0 |
629 | test eax, eax |
599 | test eax, eax |
630 | jz .error |
600 | jz .error |
631 | .nothing: |
601 | .nothing: |
632 | ret 20 |
602 | ret 20 |
633 | .error: |
603 | .error: |
Line 696... | Line 666... | ||
696 | jmp .complete |
666 | jmp .complete |
697 | .invalid: |
667 | .invalid: |
698 | ; 6. Invalid status block. Say error, set status to fatal and complete request. |
668 | ; 6. Invalid status block. Say error, set status to fatal and complete request. |
699 | push esi |
669 | push esi |
700 | mov esi, invresponse |
670 | mov esi, invresponse |
701 | call SysMsgBoardStr |
671 | invoke SysMsgBoardStr |
702 | pop esi |
672 | pop esi |
703 | mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
673 | mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL |
704 | jmp .complete |
674 | jmp .complete |
705 | .fail: |
675 | .fail: |
706 | ; 7. The command has failed. |
676 | ; 7. The command has failed. |
Line 726... | Line 696... | ||
726 | 696 | ||
727 | ; Builder for SCSI_REQUEST_SENSE request. |
697 | ; Builder for SCSI_REQUEST_SENSE request. |
728 | ; edx = first argument = pointer to usb_device_data.Command, |
698 | ; edx = first argument = pointer to usb_device_data.Command, |
729 | ; second argument = custom data given to queue_request (ignored). |
699 | ; second argument = custom data given to queue_request (ignored). |
730 | proc request_sense_req |
700 | proc request_sense_req |
731 | mov [edx+command_block_wrapper.Length], sense_data.sizeof |
701 | mov [edx+command_block_wrapper.Length], sizeof.sense_data |
732 | mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
702 | mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
733 | mov byte [edx+command_block_wrapper.Command+0], SCSI_REQUEST_SENSE |
703 | mov byte [edx+command_block_wrapper.Command+0], SCSI_REQUEST_SENSE |
734 | mov byte [edx+command_block_wrapper.Command+4], sense_data.sizeof |
704 | mov byte [edx+command_block_wrapper.Command+4], sizeof.sense_data |
735 | ret 8 |
705 | ret 8 |
Line 736... | Line 706... | ||
736 | endp |
706 | endp |
737 | 707 | ||
Line 778... | Line 748... | ||
778 | ; so allow them to proceed also. |
748 | ; so allow them to proceed also. |
779 | cmp cx, 0x5005 |
749 | cmp cx, 0x5005 |
780 | jz .known |
750 | jz .known |
781 | ; 1c. If the device is unknown, print a message and go to 11c. |
751 | ; 1c. If the device is unknown, print a message and go to 11c. |
782 | mov esi, unkdevice |
752 | mov esi, unkdevice |
783 | call SysMsgBoardStr |
753 | invoke SysMsgBoardStr |
784 | jmp .nothing |
754 | jmp .nothing |
785 | ; 1d. If the device uses known command set, print a message and continue |
755 | ; 1d. If the device uses known command set, print a message and continue |
786 | ; configuring. |
756 | ; configuring. |
787 | .known: |
757 | .known: |
788 | push esi |
758 | push esi |
789 | mov esi, okdevice |
759 | mov esi, okdevice |
790 | call SysMsgBoardStr |
760 | invoke SysMsgBoardStr |
791 | pop esi |
761 | pop esi |
792 | ; 2. Allocate memory for internal device data. |
762 | ; 2. Allocate memory for internal device data. |
793 | ; 2a. Call the kernel. |
763 | ; 2a. Call the kernel. |
794 | mov eax, usb_device_data.sizeof |
764 | mov eax, sizeof.usb_device_data |
795 | call Kmalloc |
765 | invoke Kmalloc |
796 | ; 2b. Check return value. |
766 | ; 2b. Check return value. |
797 | test eax, eax |
767 | test eax, eax |
798 | jnz @f |
768 | jnz @f |
799 | ; 2c. If failed, say a message and go to 11c. |
769 | ; 2c. If failed, say a message and go to 11c. |
800 | mov esi, nomemory |
770 | mov esi, nomemory |
801 | call SysMsgBoardStr |
771 | invoke SysMsgBoardStr |
802 | jmp .nothing |
772 | jmp .nothing |
803 | @@: |
773 | @@: |
804 | ; 2d. If succeeded, zero the contents and continue configuring. |
774 | ; 2d. If succeeded, zero the contents and continue configuring. |
805 | xchg ebx, eax ; ebx will point to usb_device_data |
775 | xchg ebx, eax ; ebx will point to usb_device_data |
806 | xor eax, eax |
776 | xor eax, eax |
Line 827... | Line 797... | ||
827 | ; 2i. Initialize requests queue. |
797 | ; 2i. Initialize requests queue. |
828 | lea eax, [ebx+usb_device_data.RequestsQueue] |
798 | lea eax, [ebx+usb_device_data.RequestsQueue] |
829 | mov [eax+request_queue_item.Next], eax |
799 | mov [eax+request_queue_item.Next], eax |
830 | mov [eax+request_queue_item.Prev], eax |
800 | mov [eax+request_queue_item.Prev], eax |
831 | lea ecx, [ebx+usb_device_data.QueueLock] |
801 | lea ecx, [ebx+usb_device_data.QueueLock] |
832 | call MutexInit |
802 | invoke MutexInit |
833 | ; Bulk-only mass storage devices use one OUT bulk endpoint for sending |
803 | ; Bulk-only mass storage devices use one OUT bulk endpoint for sending |
834 | ; command/data and one IN bulk endpoint for receiving data/status. |
804 | ; command/data and one IN bulk endpoint for receiving data/status. |
835 | ; Look for those endpoints. |
805 | ; Look for those endpoints. |
836 | ; 3. Get the upper bound of all descriptors' data. |
806 | ; 3. Get the upper bound of all descriptors' data. |
837 | mov edx, [.config] ; configuration descriptor |
807 | mov edx, [.config] ; configuration descriptor |
Line 860... | Line 830... | ||
860 | ; the loop. |
830 | ; the loop. |
861 | cmp byte [esi+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE |
831 | cmp byte [esi+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE |
862 | jnz .lookep |
832 | jnz .lookep |
863 | ; 5. Check that the descriptor contains all required data and all data are |
833 | ; 5. Check that the descriptor contains all required data and all data are |
864 | ; readable. The opposite is an error. |
834 | ; readable. The opposite is an error. |
865 | cmp byte [esi+endpoint_descr.bLength], endpoint_descr.sizeof |
835 | cmp byte [esi+endpoint_descr.bLength], sizeof.endpoint_descr |
866 | jb .errorep |
836 | jb .errorep |
867 | lea ecx, [esi+endpoint_descr.sizeof] |
837 | lea ecx, [esi+sizeof.endpoint_descr] |
868 | cmp ecx, edx |
838 | cmp ecx, edx |
869 | ja .errorep |
839 | ja .errorep |
870 | ; 6. Check that the endpoint is bulk endpoint. The opposite is an error. |
840 | ; 6. Check that the endpoint is bulk endpoint. The opposite is an error. |
871 | mov cl, [esi+endpoint_descr.bmAttributes] |
841 | mov cl, [esi+endpoint_descr.bmAttributes] |
872 | and cl, 3 |
842 | and cl, 3 |
Line 885... | Line 855... | ||
885 | ; 9b. Load parameters from the descriptor. |
855 | ; 9b. Load parameters from the descriptor. |
886 | movzx ecx, [esi+endpoint_descr.bEndpointAddress] |
856 | movzx ecx, [esi+endpoint_descr.bEndpointAddress] |
887 | movzx edx, [esi+endpoint_descr.wMaxPacketSize] |
857 | movzx edx, [esi+endpoint_descr.wMaxPacketSize] |
888 | movzx eax, [esi+endpoint_descr.bInterval] ; not used for USB1, may be important for USB2 |
858 | movzx eax, [esi+endpoint_descr.bInterval] ; not used for USB1, may be important for USB2 |
889 | ; 9c. Call the kernel. |
859 | ; 9c. Call the kernel. |
890 | stdcall USBOpenPipe, [ebx+usb_device_data.ConfigPipe], ecx, edx, BULK_PIPE, eax |
860 | invoke USBOpenPipe, [ebx+usb_device_data.ConfigPipe], ecx, edx, BULK_PIPE, eax |
891 | ; 9d. Restore registers. |
861 | ; 9d. Restore registers. |
892 | pop edx ecx |
862 | pop edx ecx |
893 | ; 9e. Check result. If failed, go to 11b. |
863 | ; 9e. Check result. If failed, go to 11b. |
894 | test eax, eax |
864 | test eax, eax |
895 | jz .free |
865 | jz .free |
Line 905... | Line 875... | ||
905 | ; 11a. Print a message. |
875 | ; 11a. Print a message. |
906 | DEBUGF 1,'K : error: invalid endpoint descriptor\n' |
876 | DEBUGF 1,'K : error: invalid endpoint descriptor\n' |
907 | .free: |
877 | .free: |
908 | ; 11b. Free the allocated usb_device_data. |
878 | ; 11b. Free the allocated usb_device_data. |
909 | xchg eax, ebx |
879 | xchg eax, ebx |
910 | call Kfree |
880 | invoke Kfree |
911 | .nothing: |
881 | .nothing: |
912 | ; 11c. Return an error. |
882 | ; 11c. Return an error. |
913 | xor eax, eax |
883 | xor eax, eax |
914 | jmp .return |
884 | jmp .return |
915 | .created: |
885 | .created: |
Line 920... | Line 890... | ||
920 | mov byte [eax+6], 1 ; transfer 1 byte |
890 | mov byte [eax+6], 1 ; transfer 1 byte |
921 | lea ecx, [ebx+usb_device_data.MaxLUN] |
891 | lea ecx, [ebx+usb_device_data.MaxLUN] |
922 | if DUMP_PACKETS |
892 | if DUMP_PACKETS |
923 | DEBUGF 1,'K : GETMAXLUN: %x %x %x %x %x %x %x %x\n',[eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2 |
893 | DEBUGF 1,'K : GETMAXLUN: %x %x %x %x %x %x %x %x\n',[eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2 |
924 | end if |
894 | end if |
925 | stdcall USBControlTransferAsync, [ebx+usb_device_data.ConfigPipe], eax, ecx, 1, known_lun_callback, ebx, 0 |
895 | invoke USBControlTransferAsync, [ebx+usb_device_data.ConfigPipe], eax, ecx, 1, known_lun_callback, ebx, 0 |
926 | ; 13. Return with pointer to device data as returned value. |
896 | ; 13. Return with pointer to device data as returned value. |
927 | xchg eax, ebx |
897 | xchg eax, ebx |
928 | .return: |
898 | .return: |
929 | pop esi ebx |
899 | pop esi ebx |
930 | ret 12 |
900 | ret 12 |
Line 953... | Line 923... | ||
953 | @@: |
923 | @@: |
954 | ; 2. Allocate the memory for logical devices. |
924 | ; 2. Allocate the memory for logical devices. |
955 | mov eax, [ebx+usb_device_data.MaxLUN] |
925 | mov eax, [ebx+usb_device_data.MaxLUN] |
956 | inc eax |
926 | inc eax |
957 | DEBUGF 1,'K : %d logical unit(s)\n',eax |
927 | DEBUGF 1,'K : %d logical unit(s)\n',eax |
958 | imul eax, usb_unit_data.sizeof |
928 | imul eax, sizeof.usb_unit_data |
959 | push ebx |
929 | push ebx |
960 | call Kmalloc |
930 | invoke Kmalloc |
961 | pop ebx |
931 | pop ebx |
962 | ; If failed, print a message and do nothing. |
932 | ; If failed, print a message and do nothing. |
963 | test eax, eax |
933 | test eax, eax |
964 | jnz @f |
934 | jnz @f |
965 | mov esi, nomemory |
935 | mov esi, nomemory |
966 | call SysMsgBoardStr |
936 | invoke SysMsgBoardStr |
967 | pop esi ebx |
937 | pop esi ebx |
968 | ret 20 |
938 | ret 20 |
969 | @@: |
939 | @@: |
970 | mov [ebx+usb_device_data.LogicalDevices], eax |
940 | mov [ebx+usb_device_data.LogicalDevices], eax |
971 | ; 3. Initialize logical devices and initiate TEST_UNIT_READY request. |
941 | ; 3. Initialize logical devices and initiate TEST_UNIT_READY request. |
Line 978... | Line 948... | ||
978 | mov [esi+usb_unit_data.MediaPresent], al |
948 | mov [esi+usb_unit_data.MediaPresent], al |
979 | mov [esi+usb_unit_data.DiskDevice], eax |
949 | mov [esi+usb_unit_data.DiskDevice], eax |
980 | mov [esi+usb_unit_data.SectorSize], eax |
950 | mov [esi+usb_unit_data.SectorSize], eax |
981 | mov [esi+usb_unit_data.UnitReadyAttempts], eax |
951 | mov [esi+usb_unit_data.UnitReadyAttempts], eax |
982 | push ecx |
952 | push ecx |
983 | call GetTimerTicks |
953 | invoke GetTimerTicks |
984 | mov [esi+usb_unit_data.TimerTicks], eax |
954 | mov [esi+usb_unit_data.TimerTicks], eax |
985 | stdcall queue_request, ebx, test_unit_ready_req, 0, test_unit_ready_callback, esi |
955 | stdcall queue_request, ebx, test_unit_ready_req, 0, test_unit_ready_callback, esi |
986 | pop ecx |
956 | pop ecx |
987 | inc ecx |
957 | inc ecx |
988 | add esi, usb_unit_data.sizeof |
958 | add esi, sizeof.usb_unit_data |
989 | cmp ecx, [ebx+usb_device_data.MaxLUN] |
959 | cmp ecx, [ebx+usb_device_data.MaxLUN] |
990 | jbe .looplun |
960 | jbe .looplun |
991 | ; 4. Return. |
961 | ; 4. Return. |
992 | pop esi ebx |
962 | pop esi ebx |
993 | ret 20 |
963 | ret 20 |
Line 997... | Line 967... | ||
997 | ; edx = first argument = pointer to usb_device_data.Command, |
967 | ; edx = first argument = pointer to usb_device_data.Command, |
998 | ; second argument = custom data given to queue_request. |
968 | ; second argument = custom data given to queue_request. |
999 | proc inquiry_req |
969 | proc inquiry_req |
1000 | mov eax, [esp+8] |
970 | mov eax, [esp+8] |
1001 | mov al, [eax+usb_unit_data.LUN] |
971 | mov al, [eax+usb_unit_data.LUN] |
1002 | mov [edx+command_block_wrapper.Length], inquiry_data.sizeof |
972 | mov [edx+command_block_wrapper.Length], sizeof.inquiry_data |
1003 | mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
973 | mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN |
1004 | mov [edx+command_block_wrapper.LUN], al |
974 | mov [edx+command_block_wrapper.LUN], al |
1005 | mov byte [edx+command_block_wrapper.Command+0], SCSI_INQUIRY |
975 | mov byte [edx+command_block_wrapper.Command+0], SCSI_INQUIRY |
1006 | mov byte [edx+command_block_wrapper.Command+4], inquiry_data.sizeof |
976 | mov byte [edx+command_block_wrapper.Command+4], sizeof.inquiry_data |
1007 | ret 8 |
977 | ret 8 |
1008 | endp |
978 | endp |
Line 1009... | Line 979... | ||
1009 | 979 | ||
1010 | ; Called when SCSI INQUIRY request is completed. |
980 | ; Called when SCSI INQUIRY request is completed. |
Line 1032... | Line 1002... | ||
1032 | mov edx, [esp+8] |
1002 | mov edx, [esp+8] |
1033 | push ebx ecx esi edi |
1003 | push ebx ecx esi edi |
1034 | movi ebx, 1 |
1004 | movi ebx, 1 |
1035 | mov ecx, new_disk_thread |
1005 | mov ecx, new_disk_thread |
1036 | ; edx = parameter |
1006 | ; edx = parameter |
1037 | call CreateThread |
1007 | invoke CreateThread |
1038 | pop edi esi ecx ebx |
1008 | pop edi esi ecx ebx |
1039 | cmp eax, -1 |
1009 | cmp eax, -1 |
1040 | jnz .nothing |
1010 | jnz .nothing |
1041 | ; on error, reverse step 3 |
1011 | ; on error, reverse step 3 |
1042 | lock dec [ecx+usb_device_data.NumReferences] |
1012 | lock dec [ecx+usb_device_data.NumReferences] |
Line 1044... | Line 1014... | ||
1044 | ret 8 |
1014 | ret 8 |
1045 | .fail: |
1015 | .fail: |
1046 | ; 4. The command has failed. Print a message and do nothing. |
1016 | ; 4. The command has failed. Print a message and do nothing. |
1047 | push esi |
1017 | push esi |
1048 | mov esi, inquiry_fail |
1018 | mov esi, inquiry_fail |
1049 | call SysMsgBoardStr |
1019 | invoke SysMsgBoardStr |
1050 | pop esi |
1020 | pop esi |
1051 | ret 8 |
1021 | ret 8 |
1052 | endp |
1022 | endp |
Line 1053... | Line 1023... | ||
1053 | 1023 | ||
Line 1077... | Line 1047... | ||
1077 | jnz .fail |
1047 | jnz .fail |
1078 | ; 2. The command has completed successfully, |
1048 | ; 2. The command has completed successfully, |
1079 | ; possibly after some repetitions. Print a debug message showing |
1049 | ; possibly after some repetitions. Print a debug message showing |
1080 | ; number and time of those. Remember that media is ready and go to 4. |
1050 | ; number and time of those. Remember that media is ready and go to 4. |
1081 | DEBUGF 1,'K : media is ready\n' |
1051 | DEBUGF 1,'K : media is ready\n' |
1082 | call GetTimerTicks |
1052 | invoke GetTimerTicks |
1083 | sub eax, [edx+usb_unit_data.TimerTicks] |
1053 | sub eax, [edx+usb_unit_data.TimerTicks] |
1084 | DEBUGF 1,'K : %d attempts, %d ticks\n',[edx+usb_unit_data.UnitReadyAttempts],eax |
1054 | DEBUGF 1,'K : %d attempts, %d ticks\n',[edx+usb_unit_data.UnitReadyAttempts],eax |
1085 | inc [edx+usb_unit_data.MediaPresent] |
1055 | inc [edx+usb_unit_data.MediaPresent] |
1086 | jmp .inquiry |
1056 | jmp .inquiry |
1087 | .fail: |
1057 | .fail: |
Line 1092... | Line 1062... | ||
1092 | inc [edx+usb_unit_data.UnitReadyAttempts] |
1062 | inc [edx+usb_unit_data.UnitReadyAttempts] |
1093 | cmp [edx+usb_unit_data.UnitReadyAttempts], 3 |
1063 | cmp [edx+usb_unit_data.UnitReadyAttempts], 3 |
1094 | jz @f |
1064 | jz @f |
1095 | push ecx edx esi |
1065 | push ecx edx esi |
1096 | movi esi, 10 |
1066 | movi esi, 10 |
1097 | call Sleep |
1067 | invoke Sleep |
1098 | pop esi edx ecx |
1068 | pop esi edx ecx |
1099 | stdcall queue_request, ecx, test_unit_ready_req, 0, test_unit_ready_callback, edx |
1069 | stdcall queue_request, ecx, test_unit_ready_req, 0, test_unit_ready_callback, edx |
1100 | ret 8 |
1070 | ret 8 |
1101 | @@: |
1071 | @@: |
1102 | DEBUGF 1,'K : media not ready\n' |
1072 | DEBUGF 1,'K : media not ready\n' |
Line 1118... | Line 1088... | ||
1118 | ; We are ready to notify the kernel about a new disk device. |
1088 | ; We are ready to notify the kernel about a new disk device. |
1119 | mov esi, [.param] |
1089 | mov esi, [.param] |
1120 | ; 1. Generate name. |
1090 | ; 1. Generate name. |
1121 | ; 1a. Find a free index. |
1091 | ; 1a. Find a free index. |
1122 | mov ecx, free_numbers_lock |
1092 | mov ecx, free_numbers_lock |
1123 | call MutexLock |
1093 | invoke MutexLock |
1124 | xor eax, eax |
1094 | xor eax, eax |
1125 | @@: |
1095 | @@: |
1126 | bsf edx, [free_numbers+eax] |
1096 | bsf edx, [free_numbers+eax] |
1127 | jnz @f |
1097 | jnz @f |
1128 | add eax, 4 |
1098 | add eax, 4 |
1129 | cmp eax, 4*4 |
1099 | cmp eax, 4*4 |
1130 | jnz @b |
1100 | jnz @b |
1131 | call MutexUnlock |
1101 | invoke MutexUnlock |
1132 | push esi |
1102 | push esi |
1133 | mov esi, noindex |
1103 | mov esi, noindex |
1134 | call SysMsgBoardStr |
1104 | invoke SysMsgBoardStr |
1135 | pop esi |
1105 | pop esi |
1136 | jmp .drop_reference |
1106 | jmp .drop_reference |
1137 | @@: |
1107 | @@: |
1138 | ; 1b. Mark the index as busy. |
1108 | ; 1b. Mark the index as busy. |
1139 | btr [free_numbers+eax], edx |
1109 | btr [free_numbers+eax], edx |
1140 | lea eax, [eax*8+edx] |
1110 | lea eax, [eax*8+edx] |
1141 | push eax |
1111 | push eax |
1142 | call MutexUnlock |
1112 | invoke MutexUnlock |
1143 | pop eax |
1113 | pop eax |
1144 | ; 1c. Generate a name of the form "usbhd |
1114 | ; 1c. Generate a name of the form "usbhd |
1145 | mov dword [esp], 'usbh' |
1115 | mov dword [esp], 'usbh' |
1146 | lea edi, [esp+5] |
1116 | lea edi, [esp+5] |
1147 | mov byte [edi-1], 'd' |
1117 | mov byte [edi-1], 'd' |
Line 1164... | Line 1134... | ||
1164 | ; 3d. Store the index in usb_unit_data to free it later. |
1134 | ; 3d. Store the index in usb_unit_data to free it later. |
1165 | mov [esi+usb_unit_data.DiskIndex], cl |
1135 | mov [esi+usb_unit_data.DiskIndex], cl |
1166 | ; 4. Notify the kernel about a new disk. |
1136 | ; 4. Notify the kernel about a new disk. |
1167 | ; 4a. Add a disk. |
1137 | ; 4a. Add a disk. |
1168 | ; stdcall queue_request, ecx, read_capacity_req, eax, read_capacity_callback, eax |
1138 | ; stdcall queue_request, ecx, read_capacity_req, eax, read_capacity_callback, eax |
1169 | stdcall DiskAdd, disk_functions, edx, esi, 0 |
1139 | invoke DiskAdd, disk_functions, edx, esi, 0 |
1170 | mov ebx, eax |
1140 | mov ebx, eax |
1171 | ; 4b. If it failed, release the index and do nothing. |
1141 | ; 4b. If it failed, release the index and do nothing. |
1172 | test eax, eax |
1142 | test eax, eax |
1173 | jz .free_index |
1143 | jz .free_index |
1174 | ; 4c. Notify the kernel that a media is present. |
1144 | ; 4c. Notify the kernel that a media is present. |
1175 | stdcall DiskMediaChanged, eax, 1 |
1145 | invoke DiskMediaChanged, eax, 1 |
1176 | ; 5. Lock the requests queue, check that device is not disconnected, |
1146 | ; 5. Lock the requests queue, check that device is not disconnected, |
1177 | ; store the disk handle, unlock the requests queue. |
1147 | ; store the disk handle, unlock the requests queue. |
1178 | mov ecx, [esi+usb_unit_data.Parent] |
1148 | mov ecx, [esi+usb_unit_data.Parent] |
1179 | add ecx, usb_device_data.QueueLock |
1149 | add ecx, usb_device_data.QueueLock |
1180 | call MutexLock |
1150 | invoke MutexLock |
1181 | cmp byte [ecx+usb_device_data.DeviceDisconnected-usb_device_data.QueueLock], 0 |
1151 | cmp byte [ecx+usb_device_data.DeviceDisconnected-usb_device_data.QueueLock], 0 |
1182 | jnz .disconnected |
1152 | jnz .disconnected |
1183 | mov [esi+usb_unit_data.DiskDevice], ebx |
1153 | mov [esi+usb_unit_data.DiskDevice], ebx |
1184 | call MutexUnlock |
1154 | invoke MutexUnlock |
1185 | jmp .exit |
1155 | jmp .exit |
1186 | .disconnected: |
1156 | .disconnected: |
1187 | call MutexUnlock |
1157 | invoke MutexUnlock |
1188 | stdcall disk_close, ebx |
1158 | stdcall disk_close, ebx |
1189 | jmp .exit |
1159 | jmp .exit |
1190 | .free_index: |
1160 | .free_index: |
1191 | mov ecx, free_numbers_lock |
1161 | mov ecx, free_numbers_lock |
1192 | call MutexLock |
1162 | invoke MutexLock |
1193 | movzx eax, [esi+usb_unit_data.DiskIndex] |
1163 | movzx eax, [esi+usb_unit_data.DiskIndex] |
1194 | bts [free_numbers], eax |
1164 | bts [free_numbers], eax |
1195 | call MutexUnlock |
1165 | invoke MutexUnlock |
1196 | .drop_reference: |
1166 | .drop_reference: |
1197 | mov esi, [esi+usb_unit_data.Parent] |
1167 | mov esi, [esi+usb_unit_data.Parent] |
1198 | lock dec [esi+usb_device_data.NumReferences] |
1168 | lock dec [esi+usb_device_data.NumReferences] |
1199 | jnz .exit |
1169 | jnz .exit |
1200 | mov eax, [esi+usb_device_data.LogicalDevices] |
1170 | mov eax, [esi+usb_device_data.LogicalDevices] |
1201 | call Kfree |
1171 | invoke Kfree |
1202 | xchg eax, esi |
1172 | xchg eax, esi |
1203 | call Kfree |
1173 | invoke Kfree |
1204 | .exit: |
1174 | .exit: |
1205 | or eax, -1 |
1175 | or eax, -1 |
1206 | int 0x40 |
1176 | int 0x40 |
1207 | endp |
1177 | endp |
Line 1214... | Line 1184... | ||
1214 | dd ? ; return address |
1184 | dd ? ; return address |
1215 | .device dd ? |
1185 | .device dd ? |
1216 | end virtual |
1186 | end virtual |
1217 | ; 1. Say a message. |
1187 | ; 1. Say a message. |
1218 | mov esi, disconnectmsg |
1188 | mov esi, disconnectmsg |
1219 | call SysMsgBoardStr |
1189 | invoke SysMsgBoardStr |
1220 | ; 2. Lock the requests queue, set .DeviceDisconnected to 1, |
1190 | ; 2. Lock the requests queue, set .DeviceDisconnected to 1, |
1221 | ; unlock the requests queue. |
1191 | ; unlock the requests queue. |
1222 | ; Locking is required for synchronization with queue_request: |
1192 | ; Locking is required for synchronization with queue_request: |
1223 | ; all USB callbacks are executed in the same thread and are |
1193 | ; all USB callbacks are executed in the same thread and are |
1224 | ; synchronized automatically, but queue_request can be running |
1194 | ; synchronized automatically, but queue_request can be running |
Line 1227... | Line 1197... | ||
1227 | ; been started, has checked that device is not yet disconnected, |
1197 | ; been started, has checked that device is not yet disconnected, |
1228 | ; then DeviceDisconnected completes and all handles become invalid, |
1198 | ; then DeviceDisconnected completes and all handles become invalid, |
1229 | ; then queue_request tries to use them. |
1199 | ; then queue_request tries to use them. |
1230 | mov esi, [.device] |
1200 | mov esi, [.device] |
1231 | lea ecx, [esi+usb_device_data.QueueLock] |
1201 | lea ecx, [esi+usb_device_data.QueueLock] |
1232 | call MutexLock |
1202 | invoke MutexLock |
1233 | mov [esi+usb_device_data.DeviceDisconnected], 1 |
1203 | mov [esi+usb_device_data.DeviceDisconnected], 1 |
1234 | call MutexUnlock |
1204 | invoke MutexUnlock |
1235 | ; 3. Drop one reference to the structure and check whether |
1205 | ; 3. Drop one reference to the structure and check whether |
1236 | ; that was the last reference. |
1206 | ; that was the last reference. |
1237 | lock dec [esi+usb_device_data.NumReferences] |
1207 | lock dec [esi+usb_device_data.NumReferences] |
1238 | jz .free |
1208 | jz .free |
1239 | ; 4. If not, there are some additional references due to disk devices; |
1209 | ; 4. If not, there are some additional references due to disk devices; |
Line 1245... | Line 1215... | ||
1245 | inc ebx |
1215 | inc ebx |
1246 | .diskdel: |
1216 | .diskdel: |
1247 | mov eax, [esi+usb_unit_data.DiskDevice] |
1217 | mov eax, [esi+usb_unit_data.DiskDevice] |
1248 | test eax, eax |
1218 | test eax, eax |
1249 | jz @f |
1219 | jz @f |
1250 | stdcall DiskDel, eax |
1220 | invoke DiskDel, eax |
1251 | @@: |
1221 | @@: |
1252 | add esi, usb_unit_data.sizeof |
1222 | add esi, sizeof.usb_unit_data |
1253 | dec ebx |
1223 | dec ebx |
1254 | jnz .diskdel |
1224 | jnz .diskdel |
1255 | ; In this case, some operations with those disks are still possible, |
1225 | ; In this case, some operations with those disks are still possible, |
1256 | ; so we can't do anything more now. disk_close will take care of the rest. |
1226 | ; so we can't do anything more now. disk_close will take care of the rest. |
1257 | .return: |
1227 | .return: |
Line 1260... | Line 1230... | ||
1260 | ; 5. If there are no disk devices, free all resources which were allocated. |
1230 | ; 5. If there are no disk devices, free all resources which were allocated. |
1261 | .free: |
1231 | .free: |
1262 | mov eax, [esi+usb_device_data.LogicalDevices] |
1232 | mov eax, [esi+usb_device_data.LogicalDevices] |
1263 | test eax, eax |
1233 | test eax, eax |
1264 | jz @f |
1234 | jz @f |
1265 | call Kfree |
1235 | invoke Kfree |
1266 | @@: |
1236 | @@: |
1267 | xchg eax, esi |
1237 | xchg eax, esi |
1268 | call Kfree |
1238 | invoke Kfree |
1269 | jmp .return |
1239 | jmp .return |
1270 | endp |
1240 | endp |
Line 1271... | Line 1241... | ||
1271 | 1241 | ||
1272 | ; Disk functions. |
1242 | ; Disk functions. |
Line 1284... | Line 1254... | ||
1284 | dd ? ; return address |
1254 | dd ? ; return address |
1285 | .userdata dd ? |
1255 | .userdata dd ? |
1286 | end virtual |
1256 | end virtual |
1287 | mov esi, [.userdata] |
1257 | mov esi, [.userdata] |
1288 | mov ecx, free_numbers_lock |
1258 | mov ecx, free_numbers_lock |
1289 | call MutexLock |
1259 | invoke MutexLock |
1290 | movzx eax, [esi+usb_unit_data.DiskIndex] |
1260 | movzx eax, [esi+usb_unit_data.DiskIndex] |
1291 | bts [free_numbers], eax |
1261 | bts [free_numbers], eax |
1292 | call MutexUnlock |
1262 | invoke MutexUnlock |
1293 | mov esi, [esi+usb_unit_data.Parent] |
1263 | mov esi, [esi+usb_unit_data.Parent] |
1294 | lock dec [esi+usb_device_data.NumReferences] |
1264 | lock dec [esi+usb_device_data.NumReferences] |
1295 | jnz .nothing |
1265 | jnz .nothing |
1296 | mov eax, [esi+usb_device_data.LogicalDevices] |
1266 | mov eax, [esi+usb_device_data.LogicalDevices] |
1297 | call Kfree |
1267 | invoke Kfree |
1298 | xchg eax, esi |
1268 | xchg eax, esi |
1299 | call Kfree |
1269 | invoke Kfree |
1300 | .nothing: |
1270 | .nothing: |
1301 | pop esi ebx |
1271 | pop esi ebx |
1302 | ret 4 |
1272 | ret 4 |
1303 | endp |
1273 | endp |
Line 1306... | Line 1276... | ||
1306 | proc disk_querymedia stdcall uses ebx esi edi, \ |
1276 | proc disk_querymedia stdcall uses ebx esi edi, \ |
1307 | userdata:dword, mediainfo:dword |
1277 | userdata:dword, mediainfo:dword |
1308 | ; 1. Create event for waiting. |
1278 | ; 1. Create event for waiting. |
1309 | xor esi, esi |
1279 | xor esi, esi |
1310 | xor ecx, ecx |
1280 | xor ecx, ecx |
1311 | call CreateEvent |
1281 | invoke CreateEvent |
1312 | test eax, eax |
1282 | test eax, eax |
1313 | jz .generic_fail |
1283 | jz .generic_fail |
1314 | push eax |
1284 | push eax |
1315 | push edx |
1285 | push edx |
1316 | push ecx |
1286 | push ecx |
Line 1338... | Line 1308... | ||
1338 | mov edx, esp |
1308 | mov edx, esp |
1339 | stdcall queue_request, ecx, read_capacity_req, edx, read_capacity_callback, edx |
1309 | stdcall queue_request, ecx, read_capacity_req, edx, read_capacity_callback, edx |
1340 | ; 3. Wait for event. This destroys it. |
1310 | ; 3. Wait for event. This destroys it. |
1341 | mov eax, [.event] |
1311 | mov eax, [.event] |
1342 | mov ebx, [.event_code] |
1312 | mov ebx, [.event_code] |
1343 | call WaitEvent |
1313 | invoke WaitEvent |
1344 | ; 4. Get the status and results. |
1314 | ; 4. Get the status and results. |
1345 | pop ecx |
1315 | pop ecx |
1346 | bswap ecx ; .LastLBA |
1316 | bswap ecx ; .LastLBA |
1347 | pop edx |
1317 | pop edx |
1348 | bswap edx ; .SectorSize |
1318 | bswap edx ; .SectorSize |
Line 1401... | Line 1371... | ||
1401 | push ebx esi edi |
1371 | push ebx esi edi |
1402 | mov eax, [ecx+disk_querymedia.event-disk_querymedia.locals] |
1372 | mov eax, [ecx+disk_querymedia.event-disk_querymedia.locals] |
1403 | mov ebx, [ecx+disk_querymedia.event_code-disk_querymedia.locals] |
1373 | mov ebx, [ecx+disk_querymedia.event_code-disk_querymedia.locals] |
1404 | xor edx, edx |
1374 | xor edx, edx |
1405 | xor esi, esi |
1375 | xor esi, esi |
1406 | call RaiseEvent |
1376 | invoke RaiseEvent |
1407 | pop edi esi ebx |
1377 | pop edi esi ebx |
1408 | ret 8 |
1378 | ret 8 |
1409 | endp |
1379 | endp |
Line 1410... | Line 1380... | ||
1410 | 1380 | ||
Line 1441... | Line 1411... | ||
1441 | cmp dword [startsector+4], 0 |
1411 | cmp dword [startsector+4], 0 |
1442 | jnz .generic_fail |
1412 | jnz .generic_fail |
1443 | ; 4. Create event for waiting. |
1413 | ; 4. Create event for waiting. |
1444 | xor esi, esi |
1414 | xor esi, esi |
1445 | xor ecx, ecx |
1415 | xor ecx, ecx |
1446 | call CreateEvent |
1416 | invoke CreateEvent |
1447 | test eax, eax |
1417 | test eax, eax |
1448 | jz .generic_fail |
1418 | jz .generic_fail |
1449 | push eax ; .event |
1419 | push eax ; .event |
1450 | push edx ; .event_code |
1420 | push edx ; .event_code |
1451 | push ecx ; .status |
1421 | push ecx ; .status |
Line 1474... | Line 1444... | ||
1474 | mov ecx, [eax+usb_unit_data.Parent] |
1444 | mov ecx, [eax+usb_unit_data.Parent] |
1475 | stdcall queue_request, ecx, read_write_req, [buffer], read_write_callback, esp |
1445 | stdcall queue_request, ecx, read_write_req, [buffer], read_write_callback, esp |
1476 | ; 6. Wait for event. This destroys it. |
1446 | ; 6. Wait for event. This destroys it. |
1477 | mov eax, [.event] |
1447 | mov eax, [.event] |
1478 | mov ebx, [.event_code] |
1448 | mov ebx, [.event_code] |
1479 | call WaitEvent |
1449 | invoke WaitEvent |
1480 | ; 7. Get the status. If the operation has failed, abort. |
1450 | ; 7. Get the status. If the operation has failed, abort. |
1481 | pop eax ; .status |
1451 | pop eax ; .status |
1482 | pop ecx ecx ; cleanup .event_code, .event |
1452 | pop ecx ecx ; cleanup .event_code, .event |
1483 | pop ecx ; .length_cur |
1453 | pop ecx ; .length_cur |
1484 | test eax, eax |
1454 | test eax, eax |
Line 1577... | Line 1547... | ||
1577 | ; 5. Set the event. |
1547 | ; 5. Set the event. |
1578 | mov eax, [esi+disk_read_write.event-disk_read_write.locals] |
1548 | mov eax, [esi+disk_read_write.event-disk_read_write.locals] |
1579 | mov ebx, [esi+disk_read_write.event_code-disk_read_write.locals] |
1549 | mov ebx, [esi+disk_read_write.event_code-disk_read_write.locals] |
1580 | xor edx, edx |
1550 | xor edx, edx |
1581 | xor esi, esi |
1551 | xor esi, esi |
1582 | call RaiseEvent |
1552 | invoke RaiseEvent |
1583 | ; 6. Return. |
1553 | ; 6. Return. |
1584 | pop edi esi ebx |
1554 | pop edi esi ebx |
1585 | ret 8 |
1555 | ret 8 |
1586 | endp |
1556 | endp |
Line 1597... | Line 1567... | ||
1597 | inquiry_fail db 'K : INQUIRY command failed',13,10,0 |
1567 | inquiry_fail db 'K : INQUIRY command failed',13,10,0 |
1598 | ;read_capacity_fail db 'K : READ CAPACITY command failed',13,10,0 |
1568 | ;read_capacity_fail db 'K : READ CAPACITY command failed',13,10,0 |
1599 | ;read_fail db 'K : READ command failed',13,10,0 |
1569 | ;read_fail db 'K : READ command failed',13,10,0 |
1600 | noindex db 'K : failed to generate disk name',13,10,0 |
1570 | noindex db 'K : failed to generate disk name',13,10,0 |
Line 1601... | Line -... | ||
1601 | - | ||
1602 | ; Exported variable: kernel API version. |
1571 | |
1603 | align 4 |
- | |
1604 | version dd 50005h |
1572 | align 4 |
1605 | ; Structure with callback functions. |
1573 | ; Structure with callback functions. |
1606 | usb_functions: |
1574 | usb_functions: |
1607 | dd usb_functions_end - usb_functions |
1575 | dd usb_functions_end - usb_functions |
1608 | dd AddDevice |
1576 | dd AddDevice |
Line 1618... | Line 1586... | ||
1618 | dd disk_write |
1586 | dd disk_write |
1619 | dd 0 ; flush |
1587 | dd 0 ; flush |
1620 | dd 0 ; adjust_cache_size: use default cache |
1588 | dd 0 ; adjust_cache_size: use default cache |
1621 | disk_functions_end: |
1589 | disk_functions_end: |
Line -... | Line 1590... | ||
- | 1590 | ||
- | 1591 | data fixups |
|
- | 1592 | end data |
|
1622 | 1593 | ||
1623 | free_numbers_lock rd 3 |
1594 | free_numbers_lock rd 3 |
1624 | ; 128 devices should be enough for everybody |
1595 | ; 128 devices should be enough for everybody |
Line 1625... | Line 1596... | ||
1625 | free_numbers dd -1, -1, -1, -1 |
1596 | free_numbers dd -1, -1, -1, -1 |
1626 | 1597 | ||
1627 | ; for DEBUGF macro |
- | |
1628 | include_debug_strings |
- | |
1629 | - |