📄 periph.lst
字号:
265 2 if (scsi)
266 2 sendUSBS(generalSCSIInCommand());
267 2 else
268 2 sendUSBS(generalIDEInCommand());
269 2 }
270 1 else
271 1 {
272 2 currentState = RECEIVED_OUT_CMD;
273 2 if (scsi)
274 2 sendUSBS(generalSCSIOutCommand());
275 2 else
276 2 sendUSBS(generalIDEOutCommand());
277 2 }
278 1 currentState = WAIT_FOR_CBW;
279 1 }
280
281
282
283 void sendUSBS(BYTE passOrFail)
284 {
285 1 bit done = 0;
286 1
287 1 // generalIDEx/generalSCSIx command returns here with passOrFail status bit
288 1 // which is re-cast as the error byte of CSW
289 1
290 1 while (!done)
291 1 {
292 2 if( (!(EP8CS & bmEPFULL)) && (!(EP8CS & bmEPSTALL))) // Wait for an available buffer
293 2 {
294 3
295 3 // check to see if there is any data in our OUT endpoint. If there is,
C51 COMPILER V7.10 PERIPH 05/28/2007 19:12:34 PAGE 6
296 3 // do a fifo reset before sending the CSW. How could this happen? If we
297 3 // stalled this CBW, it is possible that the host sent us data after the
298 3 // the CBW.
299 3 if (!(EP2CS & bmEPEMPTY))
300 3 {
301 4 ResetAndArmEp2();
302 4 }
303 3
304 3 // Fill the buffer & send the data back to the host
305 3 EP8FIFOBUF[0] = 'U'; // Believe it or not, this is pretty efficient!
306 3 EP8FIFOBUF[1] = 'S';
307 3 EP8FIFOBUF[2] = 'B';
308 3 EP8FIFOBUF[3] = 'S';
309 3
310 3 *((WORD volatile xdata*)(EP8FIFOBUF+CBW_TAG)) = cbwTagLow;
311 3 *((WORD volatile xdata*)(EP8FIFOBUF+CBW_TAG+2)) = cbwTagHi;
312 3
313 3 // have to store LSB first
314 3 EP8FIFOBUF[8+0] = ((BYTE *)&dataTransferLen)[3]; // "Residue"
315 3 EP8FIFOBUF[8+1] = ((BYTE *)&dataTransferLen)[2]; // "Residue"
316 3 EP8FIFOBUF[8+2] = ((BYTE *)&dataTransferLen)[1]; // "Residue"
317 3 EP8FIFOBUF[8+3] = ((BYTE *)&dataTransferLen)[0]; // "Residue"
318 3
319 3 *((BYTE xdata *) (EP8FIFOBUF+12)) = passOrFail; // Status
320 3 EP8BCH = 0;
321 3 EP8BCL = 13;
322 3 done = 1;
323 3 }
324 2 }
325 1 }
326
327 void failedIn()
328 {
329 1 // Stall if the host is still expecting data. Make sure
330 1 // endpoint is empty before doing the stall.
331 1
332 1 if (dataTransferLen /*&& !bShortPacketSent*/)
333 1 {
334 2 while( !(EP8CS & bmEPEMPTY) )
335 2 ;
336 2
337 2 //EP8BCH = 0; // Terminate with NULL packet, not STALL.
338 2 //EP8BCL = 0;
339 2 EP8CS = bmEPSTALL; // TPM
340 2 }
341 1 }
342
343 // Read data from the drive
344 // Issues repeated calls to readPIO16 to pull in multiple blocks
345 // of data from the drive
346 // Returns amount of data reported by drive else returns 0
347 WORD readPIO16toXdata(char addr, char xdata *inbuffer, WORD count, bit ignoreDriveLen)
348 {
349 1 WORD driveDataLen = 0;
350 1 WORD saveDriveDataLen;
351 1 BYTE driveStatus;
352 1 WORD timeout = PROCESS_CBW_TIMEOUT_RELOAD;
353 1 WORD i;
354 1
355 1 for (driveStatus = 0; !(driveStatus & ATAPI_STATUS_DRQ_BIT) && (timeout-- > 0); )
356 1 driveStatus = readATAPI_STATUS_REG();
357 1 if (!timeout)
C51 COMPILER V7.10 PERIPH 05/28/2007 19:12:34 PAGE 7
358 1 return(count);
359 1
360 1 if (timeout == 0xffff)
361 1 return(0);
362 1
363 1 if (ignoreDriveLen)
364 1 {
365 2 count = saveDriveDataLen = ATA_SECTOR_SIZE;
366 2 driveDataLen = 0;
367 2 }
368 1
369 1 if (scsi)
370 1 {
371 2 saveDriveDataLen = driveDataLen = getDriveDataLen();
372 2 count = min(count, driveDataLen);
373 2 }
374 1 else
375 1 {
376 2 saveDriveDataLen = driveDataLen = ATA_SECTOR_SIZE;
377 2 count = min(count, driveDataLen);
378 2 driveDataLen -= count;
379 2 }
380 1
381 1
382 1 for (i=0; i<count; i+=2)
383 1 {
384 2 ((WORD*)inbuffer)[0] = readWordPIO8(addr);
385 2 inbuffer +=2;
386 2 }
387 1
388 1 // while (count)
389 1 // {
390 1 // readLen = min(count, 0x200); // Read and write routines are limited to one USB buffer si
-ze
391 1 // readPIO16(addr, EP8FIFOBUF, readLen);
392 1 // mymemmovexx(inbuffer, EP8FIFOBUF, readLen);
393 1 // count -= readLen;
394 1 // inbuffer += readLen;
395 1 // }
396 1
397 1 // For IDE, must empty the buffer after the relavent data has been read.
398 1 if (!scsi)
399 1 while (driveDataLen)
400 1 {
401 2 readPIO16(addr, 2);
402 2 driveDataLen -= 2;
403 2 }
404 1
405 1 return(saveDriveDataLen);
406 1 }
407
408 bit waitForBusyBit()
409 {
410 1 BYTE driveStatus;
411 1
412 1 do
413 1 {
414 2 driveStatus = readATAPI_STATUS_REG();
415 2 }
416 1 while((driveStatus & (ATAPI_STATUS_BUSY_BIT))); // Do-while
417 1
418 1 // Some drives clear the busy bit asynchronously. Read the reg one more time to be sure.
C51 COMPILER V7.10 PERIPH 05/28/2007 19:12:34 PAGE 8
419 1 driveStatus = readATAPI_STATUS_REG();
420 1
421 1 if ((driveStatus & ATAPI_STATUS_ERROR_BIT))
422 1 return(USBS_FAILED);
423 1 else
424 1 return(USBS_PASSED);
425 1 }
426
427 void mymemmovexx(BYTE xdata * dest, BYTE xdata * src, WORD len)
428 {
429 1 while (len--)
430 1 {
431 2 *dest++ = *src++;
432 2 }
433 1 }
434
435
436 // Wait for interrupt from the drive.
437 // Clears the interrupt source on the drive, the INT0 is level triggered, so it clears automagically .
438 //
439 // Returns:
440 // USBS_FAILED -- Timeout
441 bit waitForIntrq()
442 {
443 1 int timeout;
444 1
445 1 // Make sure the drive has data ready for us
446 1 for (timeout = PROCESS_CBW_TIMEOUT_RELOAD;
447 1 timeout && IE0;
448 1 timeout--)
449 1 ;
450 1
451 1 // Clear the interrupt source
452 1 readATAPI_STATUS_REG();
453 1
454 1 return(USBS_PASSED);
455 1 }
456
457
458 //-----------------------------------------------------------------------------
459 // USB Interrupt Handlers
460 // The following functions are called by the USB interrupt jump table.
461 //-----------------------------------------------------------------------------
462
463 // Setup Data Available Interrupt Handler
464 void ISR_Sudav(void) interrupt 0
465 {
466 1 SetupCommand();
467 1 EZUSB_IRQ_CLEAR();
468 1 INT2CLR = bmSUDAV; // Clear SUDAV IRQ
469 1 }
470
471
472 void ISR_Ures(void) interrupt 0
473 {
474 1 // whenever we get a USB reset, we should revert to full speed mode
475 1 pConfigDscr = pFullSpeedConfigDscr;
476 1 ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
477 1 pOtherConfigDscr = pHighSpeedConfigDscr;
478 1 ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
479 1 wPacketSize = FS_BULK_PACKET_SIZE;
480 1 EP8FIFOPFH = 0x80;
C51 COMPILER V7.10 PERIPH 05/28/2007 19:12:34 PAGE 9
481 1 EP8FIFOPFL = 0x60;
482 1
483 1 EP8AUTOINLENH = MSB(wPacketSize);
484 1 EP8AUTOINLENL = LSB(wPacketSize);
485 1
486 1
487 1 FIFORESET = 8;
488 1
489 1 ResetAndArmEp2();
490 1
491 1 // clear the stall and busy bits that may be set
492 1 EP2CS = 0; // set EP2OUT to empty and clear stall
493 1 EP8CS = 0; // set EP8OUT to empty and clear stall
494 1
495 1
496 1 EZUSB_IRQ_CLEAR();
497 1 INT2CLR = bmURES; // Clear URES IRQ
498 1
499 1 if (currentState != UNCONFIGURED)
500 1 {
501 2 EA = 0;
502 2 // force a soft reset after the iret.
503 2 softReset();
504 2 }
505 1
506 1 }
507
508 void ISR_Susp(void) interrupt 0
509 {
510 1 Sleep = TRUE;
511 1 EZUSB_IRQ_CLEAR();
512 1 INT2CLR = bmSUSP;
513 1 }
514
515 void ISR_Highspeed(void) interrupt 0
516 {
517 1 if (EZUSB_HIGHSPEED())
518 1 {
519 2 pConfigDscr = pHighSpeedConfigDscr;
520 2 ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
521 2 pOtherConfigDscr = pFullSpeedConfigDscr;
522 2 ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
523 2 wPacketSize = HS_BULK_PACKET_SIZE;
524 2 EP8FIFOPFH = 0x89;
525 2 EP8FIFOPFL = 0x90;
526 2 }
527 1
528 1 EP8AUTOINLENH = MSB(wPacketSize);
529 1 EP8AUTOINLENL = LSB(wPacketSize);
530 1
531 1
532 1 EZUSB_IRQ_CLEAR();
533 1 INT2CLR = bmHSGRANT;
534 1 }
535
536 #define FW_STRETCH_VALUE_5 5
537
538 void ResetAndArmEp2()
539 {
540 1 // adjust stretch to allow for synchronization delay. We are about
541 1 // to do several back to back writes to registers that require a
542 1 // synchroniztion delay. Increasing stretch allows us to meet
C51 COMPILER V7.10 PERIPH 05/28/2007 19:12:34 PAGE 10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -