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

1.1       root        1: /*
1.1.1.3   root        2:   Hatari - hdc.c
1.1       root        3: 
1.1.1.3   root        4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
1.1.1.3   root        7:   Low-level hard drive emulation
1.1       root        8: */
1.1.1.4 ! root        9: char HDC_rcsid[] = "Hatari $Id: hdc.c,v 1.6 2004/04/23 15:33:58 thothy Exp $";
1.1       root       10: 
                     11: #include "main.h"
                     12: #include "debug.h"
1.1.1.3   root       13: #include "configuration.h"
1.1       root       14: #include "fdc.h"
                     15: #include "hdc.h"
                     16: #include "floppy.h"
                     17: #include "ikbd.h"
                     18: #include "m68000.h"
                     19: #include "memorySnapShot.h"
                     20: #include "mfp.h"
                     21: #include "misc.h"
                     22: #include "psg.h"
                     23: #include "stMemory.h"
                     24: #include "debugui.h"
                     25: 
                     26: /*
                     27:   ACSI emulation: 
                     28:   ACSI commands are six byte-packets sent to the
                     29:   hard drive controller (which is on the HD unit, not in the ST)
                     30: 
                     31:   While the hard drive is busy, DRQ is high, polling the DRQ during
                     32:   operation interrupts the current operation. The DRQ status can
                     33:   be polled non-destructively in GPIP.
                     34:   
                     35:   (For simplicity, the operation is finished immediatly,
                     36:   this is a potential bug, but I doubt it is significant,
                     37:   we just appear to have a very fast hard drive.)
                     38: 
                     39:   The ACSI command set is a subset of the SCSI standard.
                     40:   (for details, see the X3T9.2 SCSI draft documents
                     41:   from 1985, for an example of writing ACSI commands,
                     42:   see the TOS DMA boot code) 
                     43: */
                     44: 
                     45: /* #define DISALLOW_HDC_WRITE */
                     46: /* #define HDC_VERBOSE */        /* display operations */
                     47: /* #define HDC_REALLY_VERBOSE */ /* display command packets */
                     48: 
                     49: /* HDC globals */
                     50: HDCOMMAND HDCCommand;
                     51: FILE *hd_image_file = NULL;
                     52: int nPartitions = 0;
                     53: short int HDCSectorCount;
                     54: 
                     55: /* 
1.1.1.4 ! root       56:   FDC registers used:
        !            57:   - FDCSectorCountRegister
        !            58:   - DiscControllerStatus_ff8604rd
        !            59:   - DMAModeControl_ff8606wr
1.1       root       60: */
                     61: 
                     62: 
                     63: /* Our dummy INQUIRY response data */
1.1.1.4 ! root       64: static unsigned char inquiry_bytes[] = 
1.1       root       65: {
                     66:   0,                /* device type 0 = direct access device */
                     67:   0,                /* device type qualifier (nonremovable) */
                     68:   1,                /* ANSI version */
                     69:   0,                /* reserved */            
                     70:   26,               /* length of the following data */
                     71:   ' ', ' ', ' ',                         /* Vendor specific data */
                     72:   'H','a','t','a','r','i',' ','E',       /* Vendor */
                     73:   'm','u','l','a','t','e','d',' ',       /* Model */
                     74:   ' ',' ',' ',' ',                       /* Revision */
                     75:   0,0,0,0,0,0,0,0,0,0                    /* ?? */
                     76: };
                     77: 
                     78: /*---------------------------------------------------------------------*/
                     79: /*
                     80:   Return the file offset of the sector specified in the current
                     81:   ACSI command block.
                     82: */
1.1.1.4 ! root       83: static unsigned long HDC_GetOffset(void)
        !            84: {
1.1       root       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: */
1.1.1.4 ! root      100: static void HDC_Seek(void)
1.1       root      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: */
1.1.1.4 ! root      115: static void HDC_Inquiry(void)
1.1       root      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: */
1.1.1.4 ! root      131: static void HDC_WriteSector(void)
1.1       root      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: */
1.1.1.4 ! root      152: static void HDC_ReadSector(void)
1.1       root      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: */
1.1.1.4 ! root      274: static void HDC_GetInfo(void)
1.1       root      275: {
                    276:   long offset;
                    277:   unsigned char hdinfo[64];
                    278:   int i;
1.1.1.2   root      279: #ifdef HDC_VERBOSE
                    280:   unsigned long size;
                    281: #endif
1.1       root      282: 
                    283:   nPartitions = 0;
                    284:   if(hd_image_file == NULL) return;
                    285:   offset = ftell(hd_image_file); 
                    286: 
                    287:   fseek(hd_image_file, 0x1C2, 0);
                    288:   fread(hdinfo, 64, 1, hd_image_file);
                    289:  
                    290: #ifdef HDC_VERBOSE
                    291:   size = (((unsigned long) hdinfo[0] << 24)
                    292:          | ((unsigned long) hdinfo[1] << 16)
                    293:          | ((unsigned long) hdinfo[2] << 8)
                    294:          | ((unsigned long) hdinfo[3]));
                    295: 
                    296:   fprintf(stderr, "Total disk size %li Mb\n", size>>11);
                    297:   fprintf(stderr, "Partition 0 exists?: %s\n", (hdinfo[4] != 0)?"Yes":"No");
                    298:   fprintf(stderr, "Partition 1 exists?: %s\n", (hdinfo[4+12] != 0)?"Yes":"No");
                    299:   fprintf(stderr, "Partition 2 exists?: %s\n", (hdinfo[4+24] != 0)?"Yes":"No");
                    300:   fprintf(stderr, "Partition 3 exists?: %s\n", (hdinfo[4+36] != 0)?"Yes":"No");
                    301: #endif
                    302: 
                    303:   for(i=0;i<4;i++)
                    304:     if(hdinfo[4 + 12*i]) nPartitions++;
                    305: 
                    306:   fseek(hd_image_file, offset, 0);
                    307: }
                    308: 
                    309: /*---------------------------------------------------------------------*/
                    310: /*
                    311:   Open the disk image file, set partitions.
                    312:  */
                    313: BOOL HDC_Init(char *filename)
                    314: {
                    315:   if( (hd_image_file = fopen(filename, "r+")) == NULL)
                    316:     return( FALSE );
                    317: 
                    318:   HDC_GetInfo();
                    319:   if(!nPartitions) 
                    320:     {
                    321:       fclose( hd_image_file );
                    322:       hd_image_file = NULL;
1.1.1.3   root      323:       ConfigureParams.HardDisc.bUseHardDiscImage = FALSE;
1.1       root      324:       return( FALSE );
                    325:     }
                    326:   /* set number of partitions */
                    327:   ConfigureParams.HardDisc.nDriveList += nPartitions;
                    328: 
1.1.1.3   root      329:   ConfigureParams.HardDisc.bUseHardDiscImage = TRUE;
                    330: 
1.1       root      331:   return( TRUE );
                    332: }
1.1.1.3   root      333: 
1.1       root      334: /*---------------------------------------------------------------------*/
                    335: /*
                    336:   HDC_UnInit - close image file
                    337: 
                    338:  */
1.1.1.4 ! root      339: void HDC_UnInit(void)
1.1       root      340: {
                    341:   if(!(ACSI_EMU_ON)) return;
                    342:   fclose(hd_image_file);
                    343:   hd_image_file = NULL;
                    344:   nPartitions = 0;
1.1.1.3   root      345:   ConfigureParams.HardDisc.bUseHardDiscImage = FALSE;
1.1       root      346: }
                    347: 
                    348: /*---------------------------------------------------------------------*/
                    349: /*
                    350:   Process HDC command packets, called when bytes are 
                    351:   written to $FFFF8606 and the HDC (not the FDC) is selected.
                    352: */
1.1.1.4 ! root      353: void HDC_WriteCommandPacket(void)
1.1       root      354: {
                    355: 
                    356:   /* check status byte */
                    357:   if(((DMAModeControl_ff8606wr & 0x0018) != 8)) return;
                    358:  
                    359:   /* is HDC emulation enabled? */
                    360:   if(!(ACSI_EMU_ON)) return;
                    361: 
                    362:   /* command byte sent, store it. */
                    363:   HDCCommand.command[HDCCommand.byteCount++] =  (DiscControllerWord_ff8604wr&0xFF);
                    364:   
                    365:   /* have we recived a complete 6-byte packet yet? */
                    366:   if(HDCCommand.byteCount >= 6){
                    367:     
                    368: #ifdef HDC_REALLY_VERBOSE
                    369:     HDC_DebugCommandPacket(stderr);
                    370: #endif
                    371: 
                    372:     /* If it's aimed for our drive, emulate it! */
                    373:     if((HD_CONTROLLER(HDCCommand)) == 0)
                    374:       {
                    375:        if(HD_DRIVENUM(HDCCommand) == 0) HDC_EmulateCommandPacket();
                    376:       }
                    377:     else 
                    378:       {
                    379:        FDC_SetDMAStatus(FALSE); 
                    380:        FDC_AcknowledgeInterrupt();
                    381:        HDCCommand.returnCode = HD_STATUS_NODRIVE; 
                    382:        FDCSectorCountRegister = 0;
                    383:        FDC_AcknowledgeInterrupt();
                    384:       }
                    385:     
                    386:     HDCCommand.byteCount = 0;
                    387:   }
                    388: }
                    389: 
                    390: 
                    391: 
                    392: 
                    393: 
                    394: 
                    395: 
                    396: 
                    397: 
                    398: 
                    399: 
                    400: 
                    401: 
                    402: 
                    403: 
                    404: 

unix.superglobalmegacorp.com

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