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

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