/*******************************************/ /* Intel 28F008SA 5 Volt Flash-File Memory */ #include "driver.h" #include "includes/am29f080.h" /* commands */ enum { AMD_FLASH_MODE_READ_ARRAY, AMD_FLASH_MODE_AUTOSELECT, AMD_FLASH_MODE_BYTE_PROGRAM, AMD_FLASH_MODE_WAITING_ERASE_TYPE }; #define AMD_FLASH_COMMAND_RESET 0x0F0 #define AMD_FLASH_COMMAND_ERASE_SUSPEND 0x0B0 #define AMD_FLASH_COMMAND_ERASE_RESUME 0x030 #define AMD_FLASH_COMMAND_AUTOSELECT 0x090 #define AMD_FLASH_COMMAND_ERASE 0x080 #define AMD_FLASH_COMMAND_BYTE_PROGRAM 0x0A0 #define AMD_FLASH_COMMAND_ERASE_CHIP 0x010 #define AMD_FLASH_COMMAND_ERASE_SECTOR 0x030 #define AMD_FLASH_MANUFACTURER_CODE 0x001 #define AMD_FLASH_DEVICE_CODE 0x0d5 struct amd_flash_interface { /* ready/busy# output callback */ void (*amd_flash_ry_by_output)(int state); }; typedef struct AMD_FLASH_FILE_MEMORY { unsigned long amd_autoselect_state; unsigned long mode; unsigned char sector_group_protection; // /* internal status register */ // unsigned long flash_status; // /* command */ // unsigned long flash_command; // /* number of command cycles required */ // unsigned long flash_command_parameters_required; // // /* index of 64k block to erase */ // unsigned long flash_erase_block; // // /* offset we were last suspended at, or offset the erase procedure started at*/ // unsigned long flash_offset; void *flash_timer; int flash_erase_status; /* address of 1mb data */ char *base; struct amd_flash_interface interface; } AMD_FLASH_FILE_MEMORY; #define MAX_FLASH_DEVICES 4 static AMD_FLASH_FILE_MEMORY amd_flash[MAX_FLASH_DEVICES]; #if 0 void amd_flash_set_interface(int index1, struct amd_flash_interface *interface) { if ((index1<0) || (index1>=MAX_FLASH_DEVICES)) return; memcpy(&amd_flash[index1].interface, interface, sizeof(struct amd_flash_interface)); } /* set sector group protection status */ void amd_flash_set_sector_group_protection(int index1, int group_index, int is_protected) { if ((index1<0) || (index1>=MAX_FLASH_DEVICES)) return; if ((group_index<0) || (group_index>=7)) return; amd_flash[index1].sector_group_protection &= ~(1<>17) & 0x07; /* return bit indicating protection status */ return (amd_flash[index1].sector_group_protection>>sector_group) & 0x01; } break; /* 3 - not defined! */ default: break; } } break; } return 0x0ff; } static void amd_autoselect_sequence_update(int index1, int offset, int data) { switch (amd_flash[index1].amd_autoselect_state) { case 0: { int addr = offset & 0x07ff; if ((addr==0x0555) && (data==0x0aa)) { logerror("amd flash: recognised address 0x0555 and data 0x0aa\n"); amd_flash[index1].amd_autoselect_state++; } else { amd_flash[index1].amd_autoselect_state = 0; } } break; case 1: { int addr = offset & 0x07ff; if ((addr==0x02aa) && (data==0x055)) { logerror("amd flash: recognised address 0x02aa and data 0x055\n"); amd_flash[index1].amd_autoselect_state++; amd_flash[index1].mode = AMD_FLASH_MODE_AUTOSELECT; } else { amd_flash[index1].amd_autoselect_state = 0; } } break; case 2: { int addr = offset & 0x07ff; amd_flash[index1].amd_autoselect_state = 0; if (addr==0x0555) { logerror("amd flash: recognised address 0x0555, command: %02x\n",data); switch (data) { /* not sure if this is correct for amd flash! */ case AMD_FLASH_COMMAND_RESET: { /* return to read array */ amd_flash[index1].mode = AMD_FLASH_MODE_READ_ARRAY; amd_flash[index1].amd_autoselect_state = 0; } break; case AMD_FLASH_COMMAND_AUTOSELECT: { amd_flash[index1].mode = AMD_FLASH_MODE_AUTOSELECT; } break; case AMD_FLASH_COMMAND_BYTE_PROGRAM: { amd_flash[index1].mode = AMD_FLASH_MODE_BYTE_PROGRAM; } break; case AMD_FLASH_COMMAND_ERASE: { /* reset state */ amd_flash[index1].amd_autoselect_state = 0; amd_flash[index1].mode = AMD_FLASH_MODE_WAITING_ERASE_TYPE; } break; } } } break; } } /* flash write - offset is offset within flash-file (offset within 1mb)*/ void amd_flash_bank_handler_w(int index1, int offset, int data) { logerror("amd flash write: offs: %04x data: %02x\n",offset,data); // /* reset? */ // if (data==AMD_FLASH_COMMAND_RESET) // { // /* return to read array */ // amd_flash[index1].mode = AMD_FLASH_MODE_READ_ARRAY; // amd_flash[index1].amd_autoselect_state = 0; // return; // } amd_autoselect_sequence_update(index1, offset, data); switch (amd_flash[index1].mode) { case AMD_FLASH_MODE_BYTE_PROGRAM: { /* cannot turn a 0 into 1! */ /* write the byte */ amd_flash[index1].base[offset] &=data; } break; default: break; } } /*******************************************/