| NUC472_NUC442_BSP V3.04.000 The Board Support Package for NUC472/NUC442

Umas_FATFS.c
Go to the documentation of this file.
1/**************************************************************************/
12#include <stdio.h>
13#include <string.h>
14
15#include "NUC472_442.h"
16#include "usbh_core.h"
17
18#include "Umas.h"
19#include "diskio.h"
20#include "usbh_umas.h"
21
23
24UMAS_DATA_T *g_umas = NULL;
25static int g_disk_lun;
26static uint32_t g_sector_size, g_total_sector_num;
27
28
29
30static uint8_t usb_stor_sense_notready[18] =
31{
32 0x70/* current error */, 0, 0x02/* not ready */, 0, 0,
33 0x0a/* additional length */, 0, 0, 0, 0,
34 0x04/* not ready */, 0x03 /* manual intervention */
35};
36
37
38/* run command */
39static int run_scsi_command(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
40{
41 /* reject the command if the direction indicator is UNKNOWN */
42 if (srb->sc_data_direction == SCSI_DATA_UNKNOWN)
43 {
44 UMAS_DEBUG("run_scsi_command - UNKNOWN data direction\n");
45 umas->srb.result = DID_ERROR << 16;
46 return -1;
47 }
48
49#if 0
50 /* reject if target != 0 or if LUN is higher than the maximum known LUN */
51 if (umas->srb.target && (!(umas->flags & UMAS_FL_SCM_MULT_TARG)))
52 {
53 UMAS_DEBUG("run_scsi_command - Bad target number (%d/%d)\n", umas->srb.target, umas->srb.lun);
54 umas->srb.result = DID_BAD_TARGET << 16;
55 return -1;
56 }
57#endif
58
59 if (umas->srb.lun > umas->max_lun)
60 {
61 UMAS_DEBUG("run_scsi_command - Bad LUN (%d/%d)\n", srb->target, srb->lun);
62 umas->srb.result = DID_BAD_TARGET << 16;
63 return -1;
64 }
65
66 /* handle those devices which can't do a START_STOP */
67 if ((srb->cmnd[0] == START_STOP) && (umas->flags & UMAS_FL_START_STOP))
68 {
69 UMAS_DEBUG("run_scsi_command - Skipping START_STOP command\n");
70 umas->srb.result = GOOD << 1;
71 return -1;
72 }
73
74 /* our device has gone - pretend not ready */
75 if (!umas->pusb_dev)
76 {
77 UMAS_DEBUG("run_scsi_command - Request is for removed device\n");
78 /*
79 * For REQUEST_SENSE, it's the data. But for anything else,
80 * it should look like we auto-sensed for it.
81 */
82 if (umas->srb.cmnd[0] == REQUEST_SENSE)
83 {
84 memcpy(srb->request_buff,
85 usb_stor_sense_notready, sizeof(usb_stor_sense_notready));
86 srb->result = GOOD << 1;
87 }
88 else
89 {
90 memcpy(srb->sense_buffer,
91 usb_stor_sense_notready, sizeof(usb_stor_sense_notready));
92 srb->result = CHECK_CONDITION << 1;
93 }
94 }
95 else /* !umas->pusb_dev */
96 {
97#ifdef UMAS_VERBOSE_DEBUG
98 UMAS_DEBUG_ShowCommand(srb);
99#endif
100 /* we've got a command, let's do it! */
101 umas->proto_handler(srb, umas);
102 }
103
104 /* indicate that the command is done */
105 if (umas->srb.result != DID_ABORT << 16)
106 {
107 UMAS_VDEBUG("run_scsi_command - scsi cmd done, result=0x%x\n", srb->result);
108 }
109 else
110 {
111 UMAS_DEBUG("run_scsi_command - scsi command aborted\n");
112 }
113
114 return srb->result;
115}
116
117
118int test_unit_ready(UMAS_DATA_T *umas, int lun)
119{
120 SCSI_CMD_T *srb = &umas->srb;
121
122 memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
123 srb->cmnd[0] = TEST_UNIT_READY;
124 srb->cmnd[1] = lun << 5;
125 srb->cmd_len = 6;
126 srb->request_bufflen = 0;
127 srb->use_sg = 0;
128 srb->sc_data_direction = SCSI_DATA_READ;
129 srb->sense_buffer[0] = 0;
130 srb->sense_buffer[2] = 0;
131 return run_scsi_command(srb, umas);
132}
133
134
135int request_sense(UMAS_DATA_T *umas, int lun)
136{
137 SCSI_CMD_T *srb = &umas->srb;
138
139 memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
140 srb->cmnd[0] = REQUEST_SENSE;
141 srb->cmnd[1] = lun << 5;
142 srb->cmnd[4] = 18;
143 srb->cmd_len = 12;
144 srb->request_bufflen = 18;
145 srb->use_sg = 0;
146 srb->sc_data_direction = SCSI_DATA_READ;
147 return run_scsi_command(srb, umas);
148}
149
150
151int try_test_unit_ready(UMAS_DATA_T *umas)
152{
153 int retries;
154
155 for (retries = 0; retries < 10; retries++)
156 {
157 if (test_unit_ready(umas, 0) == 0)
158 return 0;
159 }
160 return -1;
161}
162
163
164/*===========================================================================
165 *
166 * USB Disk Driver
167 *
168 *==========================================================================*/
169
170int usbh_umas_disk_status(void)
171{
172 if (g_umas == NULL)
173 return STA_NODISK;
174 return 0;
175}
176
177
178DRESULT usbh_umas_ioctl(int cmd, void *buff)
179{
180 switch (cmd)
181 {
182 case CTRL_SYNC:
183 return RES_OK;
184
185 case GET_SECTOR_COUNT:
186 *(uint32_t *)buff = g_total_sector_num;
187 return RES_OK;
188
189 case GET_SECTOR_SIZE:
190 *(uint32_t *)buff = g_sector_size;
191 return RES_OK;
192
193 case GET_BLOCK_SIZE:
194 *(uint32_t *)buff = g_sector_size;
195 return RES_OK;
196
197#if (_FATFS == 82786)
198 case CTRL_ERASE_SECTOR:
199 return RES_OK;
200#else
201 case CTRL_TRIM:
202 return RES_OK;
203#endif
204 }
205 return RES_PARERR;
206}
207
208
209DRESULT usbh_umas_read(uint8_t *buff, uint32_t sector_no, int number_of_sector)
210{
211 SCSI_CMD_T *srb;
212 int retry = 10;
213
214 if (g_umas == NULL)
215 return RES_ERROR;
216
217 //UMAS_DEBUG("usbh_umas_read - buff=0x%x, sector=%d, count=%d\n", (int)buff, sector_no, number_of_sector);
218 if (sector_no >= g_total_sector_num)
219 {
220 UMAS_DEBUG("usbh_umas_read - exceed disk size! (%d/%d)\n", sector_no, g_total_sector_num);
221 return RES_ERROR;
222 }
223
224 srb = &g_umas->srb;
225
226do_retry:
227
228 srb->request_buff = (uint8_t *)buff;
229
230 memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
231 srb->cmnd[0] = READ_10;
232 srb->cmnd[1] = g_disk_lun << 5;
233 srb->cmnd[2] = (sector_no >> 24) & 0xFF;
234 srb->cmnd[3] = (sector_no >> 16) & 0xFF;
235 srb->cmnd[4] = (sector_no >> 8) & 0xFF;
236 srb->cmnd[5] = sector_no & 0xFF;
237 srb->cmnd[7] = (number_of_sector >> 8) & 0xFF;
238 srb->cmnd[8] = number_of_sector & 0xFF;
239 srb->cmd_len = 10;
240
241 srb->request_bufflen = g_sector_size * number_of_sector;
242
243 srb->use_sg = 0;
244 srb->sc_data_direction = SCSI_DATA_READ;
245
246 if (run_scsi_command(srb, g_umas) != 0)
247 {
248 if (retry > 0)
249 {
250 retry--;
251 goto do_retry;
252 }
253
254 UMAS_DEBUG("usbh_umas_read - failed at sector %d (%d)\n", sector_no, number_of_sector);
255 return RES_ERROR;
256 }
257 return RES_OK;
258}
259
260
261
262DRESULT usbh_umas_write(uint8_t *buff, uint32_t sector_no, int number_of_sector)
263{
264 SCSI_CMD_T *srb;
265 int retry = 3;
266
267 if (g_umas == NULL)
268 return RES_ERROR;
269
270 if (sector_no >= g_total_sector_num)
271 {
272 UMAS_DEBUG("usbh_umas_write - exceed disk size! (%d/%d)\n", sector_no, g_total_sector_num);
273 return RES_ERROR;
274 }
275
276 srb = &g_umas->srb;
277
278do_retry:
279 //UMAS_DEBUG("usbh_umas_write - Write Sector: %d %d\n", sector_no, number_of_sector);
280 srb->request_buff = (uint8_t *)buff;
281
282 memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
283 srb->cmnd[0] = WRITE_10;
284 srb->cmnd[1] = g_disk_lun << 5;
285 srb->cmnd[2] = (sector_no >> 24) & 0xFF;
286 srb->cmnd[3] = (sector_no >> 16) & 0xFF;
287 srb->cmnd[4] = (sector_no >> 8) & 0xFF;
288 srb->cmnd[5] = sector_no & 0xFF;
289 srb->cmnd[7] = (number_of_sector >> 8) & 0xFF;
290 srb->cmnd[8] = number_of_sector & 0xFF;
291 srb->cmd_len = 10;
292
293 srb->request_bufflen = g_sector_size * number_of_sector;
294
295 srb->use_sg = 0;
296 srb->sc_data_direction = SCSI_DATA_WRITE;
297
298 if (run_scsi_command(srb, g_umas) != 0)
299 {
300 if (retry > 0)
301 {
302 retry--;
303 goto do_retry;
304 }
305
306 UMAS_DEBUG("usbh_umas_write - failed at sector %d (%d)\n", sector_no, number_of_sector);
307 return RES_ERROR;
308 }
309 return RES_OK;
310}
311
312
313int UMAS_InitUmasDevice(UMAS_DATA_T *umas)
314{
315 int retries;
316 SCSI_CMD_T *srb = &umas->srb;
317 int8_t bHasMedia;
318 uint32_t stack_buff[256/4];
319
320 memset(srb, 0, sizeof(SCSI_CMD_T));
321 srb->request_buff = (void *)&stack_buff[0];
322 memset(srb->request_buff, 0, 256);
323
324 for (g_disk_lun = umas->max_lun; g_disk_lun >= 0; g_disk_lun--)
325 {
326 UMAS_DEBUG("\n\n\n******* Read lun %d ******\n\n", g_disk_lun);
327
328 UMAS_DEBUG("INQUIRY ==>\n");
329 memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
330 srb->cmnd[0] = INQUIRY;
331 srb->cmnd[1] = g_disk_lun << 5;
332 srb->cmnd[4] = 36;
333 srb->cmd_len = 6;
334 srb->request_bufflen = 36;
335 srb->use_sg = 0;
336 srb->sc_data_direction = SCSI_DATA_READ;
337
338 if (run_scsi_command(srb, umas) != 0)
339 UMAS_DEBUG("INQUIRY - command failed!\n");
340
341 UMAS_DEBUG("TEST UNIT READY ==>\n");
342 bHasMedia = FALSE;
343 for (retries = 0; retries < 3; retries++)
344 {
345 if (test_unit_ready(umas, g_disk_lun) != 0)
346 {
347 //UMAS_DEBUG("TEST_UNIT_READY - command failed\n");
348 //break;
349 }
350 else if (srb->result == 0)
351 {
352 bHasMedia = TRUE;
353 break;
354 }
355
356 if ((srb->result < 0) || (srb->sense_buffer[2] != UNIT_ATTENTION))
357 {
358 UMAS_DEBUG("TEST_UNIT_READY not UNIT_ATTENTION!\n");
359 //break;
360 }
361
362 /*
363 * If the drive has indicated to us that it doesn't have
364 * any media in it, don't bother with any of the rest of
365 * this crap.
366 */
367 if ((srb->result < 0) &&
368 (srb->sense_buffer[2] == UNIT_ATTENTION) &&
369 (srb->sense_buffer[12] == 0x3A))
370 {
371 UMAS_DEBUG("TEST_UNIT_READY - no media\n");
372 //break;
373 }
374
375 /* Look for non-removable devices that return NOT_READY.
376 * Issue command to spin up drive for these cases. */
377 if ((srb->result < 0) && (srb->sense_buffer[2] == NOT_READY))
378 {
379 UMAS_DEBUG("TEST_UNIT_READY - not ready, will retry.\n");
380 }
381 usbh_mdelay(100);
382 }
383
384 if (bHasMedia == FALSE)
385 continue;
386
387 UMAS_DEBUG("REQUEST SENSE ==>\n");
388
389 if (request_sense(umas, g_disk_lun) == 0)
390 {
391 //HexDumpBuffer("REQUEST_SENSE result", srb->request_buff, 256);
392 if ((srb->request_buff[16] == 0) && (srb->request_buff[17] == 0))
393 UMAS_DEBUG("REQUEST_SENSE - no sense\n");
394 else
395 UMAS_DEBUG("REQUEST_SENSE - attention %02x %02x\n", srb->request_buff[16], srb->request_buff[17]);
396 }
397 else
398 UMAS_DEBUG("REQUEST_SENSE failed!\n");;
399
400 UMAS_DEBUG("READ CAPACITY ==>\n");
401 memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
402 srb->cmnd[0] = READ_CAPACITY;
403 srb->cmnd[1] = g_disk_lun << 5;
404 srb->cmd_len = 9;
405 srb->sense_buffer[0] = 0;
406 srb->sense_buffer[2] = 0;
407 srb->sc_data_direction = SCSI_DATA_READ;
408 if (run_scsi_command(srb, umas) != 0)
409 {
410 UMAS_DEBUG("READ_CAPACITY failed!\n");
411 continue;
412 }
413
414 g_total_sector_num = (srb->request_buff[0] << 24) | (srb->request_buff[1] << 16) |
415 (srb->request_buff[2] << 8) | srb->request_buff[3];
416 g_sector_size = (srb->request_buff[4] << 24) | (srb->request_buff[5] << 16) |
417 (srb->request_buff[6] << 8) | srb->request_buff[7];
418
419 UMAS_DEBUG("USB disk found: size=%d MB, uTotalSectorN=%d\n", g_total_sector_num / 2048, g_total_sector_num);
420
421 ((mass_disk_t*)umas)->sector_size = g_sector_size;
422 ((mass_disk_t *)umas)->sector_number = g_total_sector_num;
423
424 break;
425 }
426
427 printf("g_disk_lun = %d\n", g_disk_lun);
428
429 g_umas = umas;
430
431 return 0;
432}
433
434#if 0
435// dummy
436void UMAS_ScanDeviceLun(UMAS_DATA_T *umas)
437{
438}
439#endif
440
442
443
468int32_t USBH_MassRawRead(mass_disk_t * disk, uint32_t sectorN, int32_t scnt, uint8_t *buff)
469{
470 UMAS_DATA_T *backup_umas;
471 int ret;
472
473 if (!disk)
474 return -1;
475
476 backup_umas = g_umas;
477 g_umas = (UMAS_DATA_T *)disk;
478 ret = usbh_umas_read(buff, sectorN, scnt);
479 g_umas = backup_umas;
480
481 if (ret == RES_OK)
482 return 0;
483 else
484 return -1;
485}
486
487
498int32_t USBH_MassRawWrite(mass_disk_t *disk, uint32_t sectorN, int32_t scnt, uint8_t *buff)
499{
500 UMAS_DATA_T *backup_umas;
501 int ret;
502
503 if (!disk)
504 return -1;
505
506 backup_umas = g_umas;
507 g_umas = (UMAS_DATA_T *)disk;
508 ret = usbh_umas_write(buff, sectorN, scnt);
509 g_umas = backup_umas;
510
511 if (ret == RES_OK)
512 return 0;
513 else
514 return -1;
515}
516 /* end of group NUC472_442_USBH_MASS_EXPORTED_FUNCTIONS */
518 /* end of group NUC472_442_USBH_MASS_Driver */
520 /* end of group NUC472_442_Device_Driver */
522
523/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
NUC472_442.h
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
Umas.h
USBH_MassRawRead
int32_t USBH_MassRawRead(mass_disk_t *disk, uint32_t sectorN, int32_t scnt, uint8_t *buff)
Read raw data from connected USB Mass Storage disk.
Definition: Umas_FATFS.c:468
USBH_MassRawWrite
int32_t USBH_MassRawWrite(mass_disk_t *disk, uint32_t sectorN, int32_t scnt, uint8_t *buff)
Write raw data to connected USB Mass Storage disk.
Definition: Umas_FATFS.c:498
NULL
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018
TRUE
#define TRUE
Boolean true, define to use in API parameters or return value.
Definition: NUC472_442.h:29021
FALSE
#define FALSE
Boolean false, define to use in API parameters or return value.
Definition: NUC472_442.h:29022
mass_disk_t
Definition: usbh_umas.h:34
usbh_core.h
USB Host core driver header file.
usbh_umas.h
USB Host Mass Storage driver header file.