Annotation of hatari/src/hdc.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   Low-level hard drive emulation
        !             5: 
        !             6: */
        !             7: 
        !             8: #include "main.h"
        !             9: #include "debug.h"
        !            10: #include "decode.h"
        !            11: #include "dialog.h"
        !            12: #include "fdc.h"
        !            13: #include "hdc.h"
        !            14: #include "floppy.h"
        !            15: #include "ikbd.h"
        !            16: #include "m68000.h"
        !            17: #include "memorySnapShot.h"
        !            18: #include "mfp.h"
        !            19: #include "misc.h"
        !            20: #include "psg.h"
        !            21: #include "stMemory.h"
        !            22: #include "debugui.h"
        !            23: 
        !            24: /*
        !            25:   ACSI emulation: 
        !            26:   ACSI commands are six byte-packets sent to the
        !            27:   hard drive controller (which is on the HD unit, not in the ST)
        !            28: 
        !            29:   While the hard drive is busy, DRQ is high, polling the DRQ during
        !            30:   operation interrupts the current operation. The DRQ status can
        !            31:   be polled non-destructively in GPIP.
        !            32:   
        !            33:   (For simplicity, the operation is finished immediatly,
        !            34:   this is a potential bug, but I doubt it is significant,
        !            35:   we just appear to have a very fast hard drive.)
        !            36: 
        !            37:   The ACSI command set is a subset of the SCSI standard.
        !            38:   (for details, see the X3T9.2 SCSI draft documents
        !            39:   from 1985, for an example of writing ACSI commands,
        !            40:   see the TOS DMA boot code) 
        !            41: */
        !            42: 
        !            43: /* #define DISALLOW_HDC_WRITE */
        !            44: /* #define HDC_VERBOSE */        /* display operations */
        !            45: /* #define HDC_REALLY_VERBOSE */ /* display command packets */
        !            46: 
        !            47: /* HDC globals */
        !            48: HDCOMMAND HDCCommand;
        !            49: FILE *hd_image_file = NULL;
        !            50: int nPartitions = 0;
        !            51: short int HDCSectorCount;
        !            52: 
        !            53: /* 
        !            54:   FDC registers used 
        !            55: */
        !            56: extern short int HDCSectorCount;
        !            57: extern short int FDCSectorCountRegister;
        !            58: 
        !            59: extern unsigned short int DiscControllerStatus_ff8604rd;         /* 0xff8604 (read) */
        !            60: extern unsigned short int DiscControllerWord_ff8604wr;           /* 0xff8604 (write) */
        !            61: extern unsigned short int DMAStatus_ff8606rd;                    /* 0xff8606 (read) */
        !            62: extern unsigned short int DMAModeControl_ff8606wr,DMAModeControl_ff8606wr_prev;  /* 0xff8606 (write,store prev for 'toggle' checks) */
        !            63: 
        !            64: /* Our dummy INQUIRY response data */
        !            65: unsigned char inquiry_bytes[] = 
        !            66: {
        !            67:   0,                /* device type 0 = direct access device */
        !            68:   0,                /* device type qualifier (nonremovable) */
        !            69:   1,                /* ANSI version */
        !            70:   0,                /* reserved */            
        !            71:   26,               /* length of the following data */
        !            72:   ' ', ' ', ' ',                         /* Vendor specific data */
        !            73:   'H','a','t','a','r','i',' ','E',       /* Vendor */
        !            74:   'm','u','l','a','t','e','d',' ',       /* Model */
        !            75:   ' ',' ',' ',' ',                       /* Revision */
        !            76:   0,0,0,0,0,0,0,0,0,0                    /* ?? */
        !            77: };
        !            78: 
        !            79: /*---------------------------------------------------------------------*/
        !            80: /*
        !            81:   Return the file offset of the sector specified in the current
        !            82:   ACSI command block.
        !            83: */
        !            84: unsigned long HDC_GetOffset(){
        !            85:   unsigned long offset;
        !            86: 
        !            87:   /* construct the logical block adress */
        !            88:   offset = ((HD_LBA_MSB(HDCCommand) << 16) 
        !            89:            |  (HD_LBA_MID(HDCCommand)  << 8) 
        !            90:            |  (HD_LBA_LSB(HDCCommand))) ;
        !            91:   
        !            92:   /* return value in bytes */
        !            93:   return(offset * 512);
        !            94: }
        !            95: 
        !            96: /*---------------------------------------------------------------------*/
        !            97: /*
        !            98:   Seek - move to a sector
        !            99: */
        !           100: void HDC_Seek()
        !           101: {
        !           102: 
        !           103:   fseek(hd_image_file, HDC_GetOffset(),0);
        !           104: 
        !           105:   FDC_SetDMAStatus(FALSE);              /* no DMA error */
        !           106:   FDC_AcknowledgeInterrupt();
        !           107:   HDCCommand.returnCode = HD_STATUS_OK;
        !           108:   FDCSectorCountRegister = 0;
        !           109: }
        !           110: 
        !           111: /*---------------------------------------------------------------------*/
        !           112: /*
        !           113:   Inquiry - return some disk information
        !           114: */
        !           115: void HDC_Inquiry()
        !           116: {
        !           117:   inquiry_bytes[4] = HD_SECTORCOUNT(HDCCommand) - 8;
        !           118:   memcpy( (char *)((unsigned long)STRam+FDC_ReadDMAAddress()), inquiry_bytes, 
        !           119:          HD_SECTORCOUNT(HDCCommand));
        !           120: 
        !           121:   FDC_SetDMAStatus(FALSE);              /* no DMA error */
        !           122:   FDC_AcknowledgeInterrupt();
        !           123:   HDCCommand.returnCode = HD_STATUS_OK;
        !           124:   FDCSectorCountRegister = 0;
        !           125: }
        !           126: 
        !           127: /*---------------------------------------------------------------------*/
        !           128: /*
        !           129:   Write a sector off our disk - (seek implied)
        !           130: */
        !           131: void HDC_WriteSector()
        !           132: {
        !           133:   /* seek to the position */
        !           134:   fseek(hd_image_file, HDC_GetOffset(),0);
        !           135: 
        !           136:   /* write -if allowed */
        !           137: #ifndef DISALLOW_HDC_WRITE
        !           138:   fwrite((char *)((unsigned long)STRam+FDC_ReadDMAAddress()), 
        !           139:         512*HD_SECTORCOUNT(HDCCommand), 1, hd_image_file); 
        !           140: #endif
        !           141: 
        !           142:   FDC_SetDMAStatus(FALSE);              /* no DMA error */
        !           143:   FDC_AcknowledgeInterrupt();
        !           144:   HDCCommand.returnCode = HD_STATUS_OK;
        !           145:   FDCSectorCountRegister = 0;
        !           146: }
        !           147: 
        !           148: /*---------------------------------------------------------------------*/
        !           149: /*
        !           150:   Read a sector off our disk - (implied seek)
        !           151: */
        !           152: void HDC_ReadSector()
        !           153: {
        !           154:   /* seek to the position */
        !           155:   fseek(hd_image_file, HDC_GetOffset(),0);
        !           156: 
        !           157: #ifdef HDC_VERBOSE
        !           158:   fprintf(stderr,"Reading %i sectors from 0x%lx to addr:%lx\n", HD_SECTORCOUNT(HDCCommand), HDC_GetOffset() ,FDC_ReadDMAAddress()); 
        !           159: #endif
        !           160: 
        !           161:   fread((char *)((unsigned long)STRam+FDC_ReadDMAAddress()), 
        !           162:        512*HD_SECTORCOUNT(HDCCommand), 1, hd_image_file); 
        !           163: 
        !           164:   FDC_SetDMAStatus(FALSE);              /* no DMA error */
        !           165:   FDC_AcknowledgeInterrupt();
        !           166:   HDCCommand.returnCode = HD_STATUS_OK;
        !           167:   FDCSectorCountRegister = 0;
        !           168: }
        !           169: 
        !           170: /*---------------------------------------------------------------------*/
        !           171: /*
        !           172:   Emulation routine for HDC command packets.
        !           173: */
        !           174: void HDC_EmulateCommandPacket()
        !           175: {
        !           176: 
        !           177:   switch(HD_OPCODE(HDCCommand)){
        !           178: 
        !           179:   case HD_READ_SECTOR: 
        !           180:     HDC_ReadSector();
        !           181:     break;
        !           182:   case HD_WRITE_SECTOR:
        !           183:     HDC_WriteSector();
        !           184:     break;
        !           185:     
        !           186:   case HD_INQUIRY:
        !           187: #ifdef HDC_VERBOSE
        !           188:     fprintf(stderr,"Inquiry made.\n");
        !           189: #endif
        !           190:     HDC_Inquiry();
        !           191:     break;
        !           192: 
        !           193:   case HD_SEEK:        
        !           194:     HDC_Seek();
        !           195:     break;
        !           196: 
        !           197:   case HD_SHIP:
        !           198:     HDCCommand.returnCode = 0xFF;
        !           199:     FDC_AcknowledgeInterrupt();
        !           200:     break;
        !           201: 
        !           202:     /* as of yet unsupported commands */
        !           203:   case HD_VERIFY_TRACK:
        !           204:   case HD_FORMAT_TRACK:
        !           205:   case HD_CORRECTION:  
        !           206:   case HD_MODESENSE:   
        !           207:   case HD_REQ_SENSE:   
        !           208: 
        !           209:   default:
        !           210:     HDCCommand.returnCode = HD_STATUS_OPCODE;
        !           211:     FDC_AcknowledgeInterrupt();
        !           212:     break;
        !           213:   }
        !           214: }
        !           215: 
        !           216: /*---------------------------------------------------------------------*/
        !           217: /*
        !           218:   Debug routine for HDC command packets.
        !           219: */
        !           220: void HDC_DebugCommandPacket(FILE *hdlogFile)
        !           221: {
        !           222:   switch(HD_OPCODE(HDCCommand)){
        !           223:   case HD_VERIFY_TRACK:
        !           224:     fprintf(hdlogFile, "OpCode: VERIFY TRACK\n");
        !           225:     break;
        !           226:   case HD_FORMAT_TRACK:
        !           227:     fprintf(hdlogFile, "OpCode: FORMAT TRACK\n");
        !           228:     break;  
        !           229:   case HD_READ_SECTOR: 
        !           230:     fprintf(hdlogFile, "OpCode: READ SECTOR(S)\n");
        !           231:     break;
        !           232:   case HD_WRITE_SECTOR:
        !           233:     fprintf(hdlogFile, "OpCode: WRITE SECTOR(S)\n");
        !           234:     break;
        !           235:   case HD_INQUIRY:        
        !           236:     fprintf(hdlogFile, "OpCode: INQUIRY\n");
        !           237:     break;
        !           238:   case HD_SEEK:        
        !           239:     fprintf(hdlogFile, "OpCode: SEEK\n");
        !           240:     break;
        !           241:   case HD_CORRECTION:  
        !           242:     fprintf(hdlogFile, "OpCode: CORRECTION\n");
        !           243:     break;
        !           244:   case HD_MODESENSE:   
        !           245:     fprintf(hdlogFile, "OpCode: MODESENSE\n");
        !           246:     break;
        !           247: 
        !           248:   case HD_SHIP:   
        !           249:     fprintf(hdlogFile, "OpCode: SHIP\n");
        !           250:     break;
        !           251: 
        !           252:   case HD_REQ_SENSE:   
        !           253:     fprintf(hdlogFile, "OpCode: MODESENSE\n");
        !           254:     break;
        !           255: 
        !           256:   default:
        !           257:     fprintf(hdlogFile, "Unknown OpCode!! Value = %x\n", HD_OPCODE(HDCCommand));
        !           258:     break;
        !           259:   }
        !           260:   fprintf(hdlogFile, "Controller: %i\n", HD_CONTROLLER(HDCCommand));
        !           261:   fprintf(hdlogFile, "Drive: %i\n", HD_DRIVENUM(HDCCommand));
        !           262:   fprintf(hdlogFile, "LBA: %lx\n", HDC_GetOffset());
        !           263: 
        !           264:   fprintf(hdlogFile, "Sector count: %x\n", HD_SECTORCOUNT(HDCCommand));
        !           265:   fprintf(hdlogFile, "HDC sector count: %x\n", HDCSectorCount);
        !           266:   fprintf(hdlogFile, "FDC sector count: %x\n", FDCSectorCountRegister);
        !           267:   fprintf(hdlogFile, "Control byte: %x\n", HD_CONTROL(HDCCommand));
        !           268: }
        !           269: 
        !           270: /*---------------------------------------------------------------------*/
        !           271: /*
        !           272:   Print data about the hard drive image
        !           273: */
        !           274: void HDC_GetInfo()
        !           275: {
        !           276:   long offset;
        !           277:   unsigned char hdinfo[64];
        !           278:   unsigned long size;
        !           279:   int i;
        !           280: 
        !           281:   nPartitions = 0;
        !           282:   if(hd_image_file == NULL) return;
        !           283:   offset = ftell(hd_image_file); 
        !           284: 
        !           285:   fseek(hd_image_file, 0x1C2, 0);
        !           286:   fread(hdinfo, 64, 1, hd_image_file);
        !           287:  
        !           288: #ifdef HDC_VERBOSE
        !           289:   size = (((unsigned long) hdinfo[0] << 24)
        !           290:          | ((unsigned long) hdinfo[1] << 16)
        !           291:          | ((unsigned long) hdinfo[2] << 8)
        !           292:          | ((unsigned long) hdinfo[3]));
        !           293: 
        !           294:   fprintf(stderr, "Total disk size %li Mb\n", size>>11);
        !           295:   fprintf(stderr, "Partition 0 exists?: %s\n", (hdinfo[4] != 0)?"Yes":"No");
        !           296:   fprintf(stderr, "Partition 1 exists?: %s\n", (hdinfo[4+12] != 0)?"Yes":"No");
        !           297:   fprintf(stderr, "Partition 2 exists?: %s\n", (hdinfo[4+24] != 0)?"Yes":"No");
        !           298:   fprintf(stderr, "Partition 3 exists?: %s\n", (hdinfo[4+36] != 0)?"Yes":"No");
        !           299: #endif
        !           300: 
        !           301:   for(i=0;i<4;i++)
        !           302:     if(hdinfo[4 + 12*i]) nPartitions++;
        !           303: 
        !           304:   fseek(hd_image_file, offset, 0);
        !           305: }
        !           306: 
        !           307: /*---------------------------------------------------------------------*/
        !           308: /*
        !           309:   Open the disk image file, set partitions.
        !           310:  */
        !           311: BOOL HDC_Init(char *filename)
        !           312: {
        !           313:   if( (hd_image_file = fopen(filename, "r+")) == NULL)
        !           314:     return( FALSE );
        !           315: 
        !           316:   HDC_GetInfo();
        !           317:   if(!nPartitions) 
        !           318:     {
        !           319:       fclose( hd_image_file );
        !           320:       hd_image_file = NULL;
        !           321:       return( FALSE );
        !           322:     }
        !           323:   /* set number of partitions */
        !           324:   ConfigureParams.HardDisc.nDriveList += nPartitions;
        !           325: 
        !           326:   return( TRUE );
        !           327: }
        !           328: /*---------------------------------------------------------------------*/
        !           329: /*
        !           330:   HDC_UnInit - close image file
        !           331: 
        !           332:  */
        !           333: void HDC_UnInit()
        !           334: {
        !           335:   if(!(ACSI_EMU_ON)) return;
        !           336:   fclose(hd_image_file);
        !           337:   hd_image_file = NULL;
        !           338:   nPartitions = 0;
        !           339: }
        !           340: 
        !           341: /*---------------------------------------------------------------------*/
        !           342: /*
        !           343:   Process HDC command packets, called when bytes are 
        !           344:   written to $FFFF8606 and the HDC (not the FDC) is selected.
        !           345: */
        !           346: void HDC_WriteCommandPacket()
        !           347: {
        !           348: 
        !           349:   /* check status byte */
        !           350:   if(((DMAModeControl_ff8606wr & 0x0018) != 8)) return;
        !           351:  
        !           352:   /* is HDC emulation enabled? */
        !           353:   if(!(ACSI_EMU_ON)) return;
        !           354: 
        !           355:   /* command byte sent, store it. */
        !           356:   HDCCommand.command[HDCCommand.byteCount++] =  (DiscControllerWord_ff8604wr&0xFF);
        !           357:   
        !           358:   /* have we recived a complete 6-byte packet yet? */
        !           359:   if(HDCCommand.byteCount >= 6){
        !           360:     
        !           361: #ifdef HDC_REALLY_VERBOSE
        !           362:     HDC_DebugCommandPacket(stderr);
        !           363: #endif
        !           364: 
        !           365:     /* If it's aimed for our drive, emulate it! */
        !           366:     if((HD_CONTROLLER(HDCCommand)) == 0)
        !           367:       {
        !           368:        if(HD_DRIVENUM(HDCCommand) == 0) HDC_EmulateCommandPacket();
        !           369:       }
        !           370:     else 
        !           371:       {
        !           372:        FDC_SetDMAStatus(FALSE); 
        !           373:        FDC_AcknowledgeInterrupt();
        !           374:        HDCCommand.returnCode = HD_STATUS_NODRIVE; 
        !           375:        FDCSectorCountRegister = 0;
        !           376:        FDC_AcknowledgeInterrupt();
        !           377:       }
        !           378:     
        !           379:     HDCCommand.byteCount = 0;
        !           380:   }
        !           381: }
        !           382: 
        !           383: 
        !           384: 
        !           385: 
        !           386: 
        !           387: 
        !           388: 
        !           389: 
        !           390: 
        !           391: 
        !           392: 
        !           393: 
        !           394: 
        !           395: 
        !           396: 
        !           397: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.