trunk/src/mess/machine/at45dbxx.c
| r20958 | r20959 | |
| 12 | 12 | |
| 13 | 13 | #include "at45dbxx.h" |
| 14 | 14 | |
| 15 | | enum |
| 16 | | { |
| 17 | | TYPE_AT45DB041, |
| 18 | | TYPE_AT45DB081, |
| 19 | | TYPE_AT45DB161 |
| 20 | | }; |
| 21 | | |
| 22 | 15 | #define LOG_LEVEL 1 |
| 23 | 16 | #define _logerror(level,x) do { if (LOG_LEVEL > level) logerror x; } while (0) |
| 24 | 17 | |
| r20958 | r20959 | |
| 32 | 25 | #define FLASH_MODE_SO 2 // output |
| 33 | 26 | |
| 34 | 27 | |
| 35 | | /*************************************************************************** |
| 36 | | TYPE DEFINITIONS |
| 37 | | ***************************************************************************/ |
| 28 | //************************************************************************** |
| 29 | // GLOBAL VARIABLES |
| 30 | //************************************************************************** |
| 38 | 31 | |
| 39 | | struct AT45DBXX_PINS |
| 40 | | { |
| 41 | | int cs; // chip select |
| 42 | | int sck; // serial clock |
| 43 | | int si; // serial input |
| 44 | | int so; // serial output |
| 45 | | int wp; // write protect |
| 46 | | int reset; // reset |
| 47 | | int busy; // busy |
| 48 | | }; |
| 32 | // device type definition |
| 33 | const device_type AT45DB041 = &device_creator<at45db041_device>; |
| 34 | const device_type AT45DB081 = &device_creator<at45db081_device>; |
| 35 | const device_type AT45DB161 = &device_creator<at45db161_device>; |
| 49 | 36 | |
| 50 | | struct AT45DBXX_CMD |
| 51 | | { |
| 52 | | UINT8 data[8], size; |
| 53 | | }; |
| 54 | 37 | |
| 55 | | struct AT45DBXX_IO |
| 56 | | { |
| 57 | | UINT8 *data; |
| 58 | | UINT32 size, pos; |
| 59 | | }; |
| 38 | //************************************************************************** |
| 39 | // LIVE DEVICE |
| 40 | //************************************************************************** |
| 60 | 41 | |
| 61 | | struct at45dbxx_t |
| 42 | //------------------------------------------------- |
| 43 | // at45db041_device - constructor |
| 44 | //------------------------------------------------- |
| 45 | |
| 46 | at45db041_device::at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 47 | : device_t(mconfig, AT45DB041, "AT45DB041", tag, owner, clock), |
| 48 | device_nvram_interface(mconfig, *this) |
| 62 | 49 | { |
| 63 | | UINT8 *data; |
| 64 | | UINT32 size; |
| 65 | | UINT32 pages, page_size; |
| 66 | | UINT8 mode, status, devid, *buffer1, *buffer2; |
| 67 | | AT45DBXX_PINS pin; |
| 68 | | UINT8 si_byte, si_bits, so_byte, so_bits; |
| 69 | | AT45DBXX_CMD cmd; |
| 70 | | AT45DBXX_IO io; |
| 71 | | }; |
| 50 | } |
| 72 | 51 | |
| 73 | 52 | |
| 74 | | /*************************************************************************** |
| 75 | | INLINE FUNCTIONS |
| 76 | | ***************************************************************************/ |
| 53 | at45db041_device::at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) |
| 54 | : device_t(mconfig, type, name, tag, owner, clock), |
| 55 | device_nvram_interface(mconfig, *this) |
| 56 | { |
| 57 | } |
| 77 | 58 | |
| 78 | | INLINE at45dbxx_t *get_token(device_t *device) |
| 59 | |
| 60 | at45db081_device::at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 61 | : at45db041_device(mconfig, AT45DB081, "AT45DB081", tag, owner, clock) |
| 79 | 62 | { |
| 80 | | assert(device != NULL); |
| 81 | | assert(device->type() == AT45DB041 || device->type() == AT45DB081 || device->type() == AT45DB161); |
| 63 | } |
| 82 | 64 | |
| 83 | | return (at45dbxx_t *) downcast<at45db041_device *>(device)->token(); |
| 65 | |
| 66 | at45db161_device::at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 67 | : at45db041_device(mconfig, AT45DB161, "AT45DB161", tag, owner, clock) |
| 68 | { |
| 84 | 69 | } |
| 85 | 70 | |
| 86 | 71 | |
| 87 | | /*************************************************************************** |
| 88 | | IMPLEMENTATION |
| 89 | | ***************************************************************************/ |
| 72 | //------------------------------------------------- |
| 73 | // device_start - device-specific startup |
| 74 | //------------------------------------------------- |
| 90 | 75 | |
| 91 | | static void common_start(device_t *device, int device_type) |
| 76 | void at45db041_device::device_start() |
| 92 | 77 | { |
| 93 | | at45dbxx_t *flash = get_token(device); |
| 78 | m_size = num_pages() * page_size(); |
| 79 | m_data = auto_alloc_array(machine(), UINT8, m_size); |
| 80 | m_buffer1 = auto_alloc_array(machine(), UINT8, page_size()); |
| 81 | m_buffer2 = auto_alloc_array(machine(), UINT8, page_size()); |
| 94 | 82 | |
| 95 | | _logerror( 0, ("at45dbxx_init (%d)\n", device_type)); |
| 96 | | memset(flash, 0, sizeof(at45dbxx_t)); |
| 97 | | switch (device_type) |
| 98 | | { |
| 99 | | case TYPE_AT45DB041 : flash->pages = 2048; flash->page_size = 264; flash->devid = 0x18; break; |
| 100 | | case TYPE_AT45DB081 : flash->pages = 4096; flash->page_size = 264; flash->devid = 0x20; break; |
| 101 | | case TYPE_AT45DB161 : flash->pages = 4096; flash->page_size = 528; flash->devid = 0x28; break; |
| 102 | | } |
| 103 | | flash->size = flash->pages * flash->page_size; |
| 104 | | flash->data = auto_alloc_array(device->machine(), UINT8, flash->size); |
| 105 | | flash->buffer1 = auto_alloc_array(device->machine(), UINT8, flash->page_size); |
| 106 | | flash->buffer2 = auto_alloc_array(device->machine(), UINT8, flash->page_size); |
| 107 | | |
| 108 | 83 | // data |
| 109 | | state_save_register_item_pointer(device->machine(), "at45dbxx", device->tag(), 0, flash->data, flash->size); |
| 84 | save_pointer(NAME(m_data), m_size); |
| 110 | 85 | // pins |
| 111 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.cs); |
| 112 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.sck); |
| 113 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.si); |
| 114 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.so); |
| 115 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.wp); |
| 116 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.reset); |
| 117 | | state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.busy); |
| 86 | save_item(NAME(m_pin.cs)); |
| 87 | save_item(NAME(m_pin.sck)); |
| 88 | save_item(NAME(m_pin.si)); |
| 89 | save_item(NAME(m_pin.so)); |
| 90 | save_item(NAME(m_pin.wp)); |
| 91 | save_item(NAME(m_pin.reset)); |
| 92 | save_item(NAME(m_pin.busy)); |
| 118 | 93 | } |
| 119 | 94 | |
| 120 | | static DEVICE_START( at45db041 ) |
| 121 | | { |
| 122 | | common_start(device, TYPE_AT45DB041); |
| 123 | | } |
| 124 | 95 | |
| 125 | | static DEVICE_START( at45db081 ) |
| 126 | | { |
| 127 | | common_start(device, TYPE_AT45DB081); |
| 128 | | } |
| 96 | //------------------------------------------------- |
| 97 | // device_reset - device-specific reset |
| 98 | //------------------------------------------------- |
| 129 | 99 | |
| 130 | | static DEVICE_START( at45db161 ) |
| 100 | void at45db041_device::device_reset() |
| 131 | 101 | { |
| 132 | | common_start(device, TYPE_AT45DB161); |
| 133 | | } |
| 134 | | |
| 135 | | static DEVICE_RESET( at45dbxx ) |
| 136 | | { |
| 137 | | at45dbxx_t *flash = get_token(device); |
| 138 | 102 | _logerror( 1, ("at45dbxx_reset\n")); |
| 139 | 103 | // mode |
| 140 | | flash->mode = FLASH_MODE_SI; |
| 104 | m_mode = FLASH_MODE_SI; |
| 141 | 105 | // command |
| 142 | | memset( &flash->cmd.data[0], 0, sizeof( flash->cmd.data)); |
| 143 | | flash->cmd.size = 0; |
| 106 | memset(&m_cmd.data[0], 0, sizeof(m_cmd.data)); |
| 107 | m_cmd.size = 0; |
| 144 | 108 | // input/output |
| 145 | | flash->io.data = NULL; |
| 146 | | flash->io.size = 0; |
| 147 | | flash->io.pos = 0; |
| 109 | m_io.data = NULL; |
| 110 | m_io.size = 0; |
| 111 | m_io.pos = 0; |
| 148 | 112 | // pins |
| 149 | | flash->pin.cs = 0; |
| 150 | | flash->pin.sck = 0; |
| 151 | | flash->pin.si = 0; |
| 152 | | flash->pin.so = 0; |
| 153 | | flash->pin.wp = 0; |
| 154 | | flash->pin.reset = 0; |
| 155 | | flash->pin.busy = 0; |
| 113 | m_pin.cs = 0; |
| 114 | m_pin.sck = 0; |
| 115 | m_pin.si = 0; |
| 116 | m_pin.so = 0; |
| 117 | m_pin.wp = 0; |
| 118 | m_pin.reset = 0; |
| 119 | m_pin.busy = 0; |
| 156 | 120 | // output |
| 157 | | flash->so_byte = 0; |
| 158 | | flash->so_bits = 0; |
| 121 | m_so_byte = 0; |
| 122 | m_so_bits = 0; |
| 159 | 123 | // input |
| 160 | | flash->si_byte = 0; |
| 161 | | flash->si_bits = 0; |
| 124 | m_si_byte = 0; |
| 125 | m_si_bits = 0; |
| 162 | 126 | } |
| 163 | 127 | |
| 164 | | static UINT8 at45dbxx_read_byte( device_t *device) |
| 128 | |
| 129 | //------------------------------------------------- |
| 130 | // nvram_default - called to initialize NVRAM to |
| 131 | // its default state |
| 132 | //------------------------------------------------- |
| 133 | |
| 134 | void at45db041_device::nvram_default() |
| 165 | 135 | { |
| 136 | memset(m_data, 0xff, m_size); |
| 137 | |
| 138 | if (region() != NULL) |
| 139 | { |
| 140 | UINT32 bytes = region()->bytes(); |
| 141 | if (bytes > m_size) |
| 142 | bytes = m_size; |
| 143 | |
| 144 | memcpy(m_data, region()->base(), bytes); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | //------------------------------------------------- |
| 149 | // nvram_read - called to read NVRAM from the |
| 150 | // .nv file |
| 151 | //------------------------------------------------- |
| 152 | |
| 153 | void at45db041_device::nvram_read(emu_file &file) |
| 154 | { |
| 155 | file.read(m_data, m_size); |
| 156 | } |
| 157 | |
| 158 | //------------------------------------------------- |
| 159 | // nvram_write - called to write NVRAM to the |
| 160 | // .nv file |
| 161 | //------------------------------------------------- |
| 162 | |
| 163 | void at45db041_device::nvram_write(emu_file &file) |
| 164 | { |
| 165 | file.write(m_data, m_size); |
| 166 | } |
| 167 | |
| 168 | UINT8 at45db041_device::read_byte() |
| 169 | { |
| 166 | 170 | UINT8 data; |
| 167 | | at45dbxx_t *flash = get_token(device); |
| 168 | 171 | // check mode |
| 169 | | if ((flash->mode != FLASH_MODE_SO) || (!flash->io.data)) return 0; |
| 172 | if ((m_mode != FLASH_MODE_SO) || (!m_io.data)) return 0; |
| 170 | 173 | // read byte |
| 171 | | data = flash->io.data[flash->io.pos++]; |
| 172 | | _logerror( 2, ("at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, flash->io.pos, flash->io.size)); |
| 173 | | if (flash->io.pos == flash->io.size) flash->io.pos = 0; |
| 174 | data = m_io.data[m_io.pos++]; |
| 175 | _logerror( 2, ("at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, m_io.pos, m_io.size)); |
| 176 | if (m_io.pos == m_io.size) m_io.pos = 0; |
| 174 | 177 | return data; |
| 175 | 178 | } |
| 176 | 179 | |
| 177 | | static void flash_set_io( device_t *device, UINT8* data, UINT32 size, UINT32 pos) |
| 180 | void at45db041_device::flash_set_io(UINT8* data, UINT32 size, UINT32 pos) |
| 178 | 181 | { |
| 179 | | at45dbxx_t *flash = get_token(device); |
| 180 | | flash->io.data = data; |
| 181 | | flash->io.size = size; |
| 182 | | flash->io.pos = pos; |
| 182 | m_io.data = data; |
| 183 | m_io.size = size; |
| 184 | m_io.pos = pos; |
| 183 | 185 | } |
| 184 | 186 | |
| 185 | | static UINT32 flash_get_page_addr( device_t *device) |
| 187 | UINT32 at45db041_device::flash_get_page_addr() |
| 186 | 188 | { |
| 187 | | at45dbxx_t *flash = get_token(device); |
| 188 | | switch (flash->devid) |
| 189 | | { |
| 190 | | case 0x18 : return ((flash->cmd.data[1] & 0x0F) << 7) | ((flash->cmd.data[2] & 0xFE) >> 1); |
| 191 | | case 0x20 : return ((flash->cmd.data[1] & 0x1F) << 7) | ((flash->cmd.data[2] & 0xFE) >> 1); |
| 192 | | case 0x28 : return ((flash->cmd.data[1] & 0x3F) << 6) | ((flash->cmd.data[2] & 0xFC) >> 2); |
| 193 | | default : return 0; |
| 194 | | } |
| 189 | return ((m_cmd.data[1] & 0x0F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1); |
| 195 | 190 | } |
| 196 | 191 | |
| 197 | | static UINT32 flash_get_byte_addr( device_t *device) |
| 192 | UINT32 at45db041_device::flash_get_byte_addr() |
| 198 | 193 | { |
| 199 | | at45dbxx_t *flash = get_token(device); |
| 200 | | switch (flash->devid) |
| 201 | | { |
| 202 | | case 0x18 : // fall-through |
| 203 | | case 0x20 : return ((flash->cmd.data[2] & 0x01) << 8) | ((flash->cmd.data[3] & 0xFF) >> 0); |
| 204 | | case 0x28 : return ((flash->cmd.data[2] & 0x03) << 8) | ((flash->cmd.data[3] & 0xFF) >> 0); |
| 205 | | default : return 0; |
| 206 | | } |
| 194 | return ((m_cmd.data[2] & 0x01) << 8) | ((m_cmd.data[3] & 0xFF) >> 0); |
| 207 | 195 | } |
| 208 | 196 | |
| 209 | | static void at45dbxx_write_byte(device_t *device, UINT8 data) |
| 197 | UINT32 at45db081_device::flash_get_page_addr() |
| 210 | 198 | { |
| 211 | | at45dbxx_t *flash = get_token(device); |
| 199 | return ((m_cmd.data[1] & 0x1F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1); |
| 200 | } |
| 201 | |
| 202 | UINT32 at45db161_device::flash_get_page_addr() |
| 203 | { |
| 204 | return ((m_cmd.data[1] & 0x3F) << 6) | ((m_cmd.data[2] & 0xFC) >> 2); |
| 205 | } |
| 206 | |
| 207 | UINT32 at45db161_device::flash_get_byte_addr() |
| 208 | { |
| 209 | return ((m_cmd.data[2] & 0x03) << 8) | ((m_cmd.data[3] & 0xFF) >> 0); |
| 210 | } |
| 211 | |
| 212 | void at45db041_device::write_byte(UINT8 data) |
| 213 | { |
| 212 | 214 | // check mode |
| 213 | | if (flash->mode != FLASH_MODE_SI) return; |
| 215 | if (m_mode != FLASH_MODE_SI) return; |
| 214 | 216 | // process byte |
| 215 | | if (flash->cmd.size < 8) |
| 217 | if (m_cmd.size < 8) |
| 216 | 218 | { |
| 217 | 219 | UINT8 opcode; |
| 218 | 220 | _logerror( 2, ("at45dbxx_write_byte (%02X)\n", data)); |
| 219 | 221 | // add to command buffer |
| 220 | | flash->cmd.data[flash->cmd.size++] = data; |
| 222 | m_cmd.data[m_cmd.size++] = data; |
| 221 | 223 | // check opcode |
| 222 | | opcode = flash->cmd.data[0]; |
| 224 | opcode = m_cmd.data[0]; |
| 223 | 225 | switch (opcode) |
| 224 | 226 | { |
| 225 | 227 | // status register read |
| 226 | 228 | case FLASH_CMD_57 : |
| 227 | 229 | { |
| 228 | 230 | // 8 bits command |
| 229 | | if (flash->cmd.size == 1) |
| 231 | if (m_cmd.size == 1) |
| 230 | 232 | { |
| 231 | 233 | _logerror( 1, ("at45dbxx opcode %02X - status register read\n", opcode)); |
| 232 | | flash->status = (flash->status & 0xC7) | flash->devid; // 80 = busy / 40 = compare fail |
| 233 | | flash_set_io( device, &flash->status, 1, 0); |
| 234 | | flash->mode = FLASH_MODE_SO; |
| 235 | | flash->cmd.size = 8; |
| 234 | m_status = (m_status & 0xC7) | device_id(); // 80 = busy / 40 = compare fail |
| 235 | flash_set_io(&m_status, 1, 0); |
| 236 | m_mode = FLASH_MODE_SO; |
| 237 | m_cmd.size = 8; |
| 236 | 238 | } |
| 237 | 239 | } |
| 238 | 240 | break; |
| r20958 | r20959 | |
| 240 | 242 | case FLASH_CMD_60 : |
| 241 | 243 | { |
| 242 | 244 | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care |
| 243 | | if (flash->cmd.size == 4) |
| 245 | if (m_cmd.size == 4) |
| 244 | 246 | { |
| 245 | 247 | UINT32 page; |
| 246 | 248 | UINT8 comp; |
| 247 | | page = flash_get_page_addr(device); |
| 249 | page = flash_get_page_addr(); |
| 248 | 250 | _logerror( 1, ("at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page)); |
| 249 | | comp = memcmp( flash->data + page * flash->page_size, flash->buffer1, flash->page_size) == 0 ? 0 : 1; |
| 250 | | if (comp) flash->status |= 0x40; else flash->status &= ~0x40; |
| 251 | comp = memcmp( m_data + page * page_size(), m_buffer1, page_size()) == 0 ? 0 : 1; |
| 252 | if (comp) m_status |= 0x40; else m_status &= ~0x40; |
| 251 | 253 | _logerror( 1, ("at45dbxx page compare %s\n", comp ? "failure" : "success")); |
| 252 | | flash->mode = FLASH_MODE_SI; |
| 253 | | flash->cmd.size = 8; |
| 254 | m_mode = FLASH_MODE_SI; |
| 255 | m_cmd.size = 8; |
| 254 | 256 | } |
| 255 | 257 | } |
| 256 | 258 | break; |
| r20958 | r20959 | |
| 258 | 260 | case FLASH_CMD_52 : |
| 259 | 261 | { |
| 260 | 262 | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care |
| 261 | | if (flash->cmd.size == 8) |
| 263 | if (m_cmd.size == 8) |
| 262 | 264 | { |
| 263 | 265 | UINT32 page, byte; |
| 264 | | page = flash_get_page_addr(device); |
| 265 | | byte = flash_get_byte_addr(device); |
| 266 | page = flash_get_page_addr(); |
| 267 | byte = flash_get_byte_addr(); |
| 266 | 268 | _logerror( 1, ("at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte)); |
| 267 | | flash_set_io( device, flash->data + page * flash->page_size, flash->page_size, byte); |
| 268 | | flash->mode = FLASH_MODE_SO; |
| 269 | | flash->cmd.size = 8; |
| 269 | flash_set_io(m_data + page * page_size(), page_size(), byte); |
| 270 | m_mode = FLASH_MODE_SO; |
| 271 | m_cmd.size = 8; |
| 270 | 272 | } |
| 271 | 273 | } |
| 272 | 274 | break; |
| r20958 | r20959 | |
| 274 | 276 | case FLASH_CMD_82 : |
| 275 | 277 | { |
| 276 | 278 | // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address |
| 277 | | if (flash->cmd.size == 4) |
| 279 | if (m_cmd.size == 4) |
| 278 | 280 | { |
| 279 | 281 | UINT32 page, byte; |
| 280 | | page = flash_get_page_addr(device); |
| 281 | | byte = flash_get_byte_addr(device); |
| 282 | page = flash_get_page_addr(); |
| 283 | byte = flash_get_byte_addr(); |
| 282 | 284 | _logerror( 1, ("at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte)); |
| 283 | | flash_set_io( device, flash->buffer1, flash->page_size, byte); |
| 284 | | memset( flash->buffer1, 0xFF, flash->page_size); |
| 285 | | flash->mode = FLASH_MODE_SI; |
| 286 | | flash->cmd.size = 8; |
| 285 | flash_set_io(m_buffer1, page_size(), byte); |
| 286 | memset( m_buffer1, 0xFF, page_size()); |
| 287 | m_mode = FLASH_MODE_SI; |
| 288 | m_cmd.size = 8; |
| 287 | 289 | } |
| 288 | 290 | } |
| 289 | 291 | break; |
| r20958 | r20959 | |
| 291 | 293 | default : |
| 292 | 294 | { |
| 293 | 295 | _logerror( 1, ("at45dbxx opcode %02X - unknown\n", opcode)); |
| 294 | | flash->cmd.data[0] = 0; |
| 295 | | flash->cmd.size = 0; |
| 296 | m_cmd.data[0] = 0; |
| 297 | m_cmd.size = 0; |
| 296 | 298 | } |
| 297 | 299 | break; |
| 298 | 300 | } |
| 299 | 301 | } |
| 300 | 302 | else |
| 301 | 303 | { |
| 302 | | _logerror( 2, ("at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, flash->io.pos + 1, flash->io.size)); |
| 304 | _logerror( 2, ("at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, m_io.pos + 1, m_io.size)); |
| 303 | 305 | // store byte |
| 304 | | flash->io.data[flash->io.pos] = data; |
| 305 | | flash->io.pos++; |
| 306 | | if (flash->io.pos == flash->io.size) flash->io.pos = 0; |
| 306 | m_io.data[m_io.pos] = data; |
| 307 | m_io.pos++; |
| 308 | if (m_io.pos == m_io.size) m_io.pos = 0; |
| 307 | 309 | } |
| 308 | 310 | } |
| 309 | 311 | |
| 310 | | int at45dbxx_pin_so( device_t *device) |
| 312 | READ_LINE_MEMBER(at45db041_device::so_r) |
| 311 | 313 | { |
| 312 | | at45dbxx_t *flash = get_token(device); |
| 313 | | if (flash->pin.cs == 0) return 0; |
| 314 | | return flash->pin.so; |
| 314 | if (m_pin.cs == 0) return 0; |
| 315 | return m_pin.so; |
| 315 | 316 | } |
| 316 | 317 | |
| 317 | | void at45dbxx_pin_si(device_t *device, int data) |
| 318 | WRITE_LINE_MEMBER(at45db041_device::si_w) |
| 318 | 319 | { |
| 319 | | at45dbxx_t *flash = get_token(device); |
| 320 | | if (flash->pin.cs == 0) return; |
| 321 | | flash->pin.si = data; |
| 320 | if (m_pin.cs == 0) return; |
| 321 | m_pin.si = state; |
| 322 | 322 | } |
| 323 | 323 | |
| 324 | | void at45dbxx_pin_cs(device_t *device, int data) |
| 324 | WRITE_LINE_MEMBER(at45db041_device::cs_w) |
| 325 | 325 | { |
| 326 | | at45dbxx_t *flash = get_token(device); |
| 327 | 326 | // check if changed |
| 328 | | if (flash->pin.cs == data) return; |
| 327 | if (m_pin.cs == state) return; |
| 329 | 328 | // cs low-to-high |
| 330 | | if (data != 0) |
| 329 | if (state != 0) |
| 331 | 330 | { |
| 332 | 331 | // complete program command |
| 333 | | if ((flash->cmd.size >= 4) && (flash->cmd.data[0] == FLASH_CMD_82)) |
| 332 | if ((m_cmd.size >= 4) && (m_cmd.data[0] == FLASH_CMD_82)) |
| 334 | 333 | { |
| 335 | 334 | UINT32 page, byte; |
| 336 | | page = flash_get_page_addr(device); |
| 337 | | byte = flash_get_byte_addr(device); |
| 335 | page = flash_get_page_addr(); |
| 336 | byte = flash_get_byte_addr(); |
| 338 | 337 | _logerror( 1, ("at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte)); |
| 339 | | memcpy( flash->data + page * flash->page_size, flash->buffer1, flash->page_size); |
| 338 | memcpy( m_data + page * page_size(), m_buffer1, page_size()); |
| 340 | 339 | } |
| 341 | 340 | // reset |
| 342 | | DEVICE_RESET_CALL( at45dbxx ); |
| 341 | at45db041_device::device_reset(); |
| 343 | 342 | } |
| 344 | 343 | // save cs |
| 345 | | flash->pin.cs = data; |
| 344 | m_pin.cs = state; |
| 346 | 345 | } |
| 347 | 346 | |
| 348 | | void at45dbxx_pin_sck(device_t *device, int data) |
| 347 | WRITE_LINE_MEMBER(at45db041_device::sck_w) |
| 349 | 348 | { |
| 350 | | at45dbxx_t *flash = get_token(device); |
| 351 | 349 | // check if changed |
| 352 | | if (flash->pin.sck == data) return; |
| 350 | if (m_pin.sck == state) return; |
| 353 | 351 | // sck high-to-low |
| 354 | | if (data == 0) |
| 352 | if (state == 0) |
| 355 | 353 | { |
| 356 | 354 | // output (part 1) |
| 357 | | if (flash->so_bits == 8) |
| 355 | if (m_so_bits == 8) |
| 358 | 356 | { |
| 359 | | flash->so_bits = 0; |
| 360 | | flash->so_byte = at45dbxx_read_byte(device); |
| 357 | m_so_bits = 0; |
| 358 | m_so_byte = read_byte(); |
| 361 | 359 | } |
| 362 | 360 | // input |
| 363 | | if (flash->pin.si) flash->si_byte = flash->si_byte | (1 << flash->si_bits); |
| 364 | | flash->si_bits++; |
| 365 | | if (flash->si_bits == 8) |
| 361 | if (m_pin.si) m_si_byte = m_si_byte | (1 << m_si_bits); |
| 362 | m_si_bits++; |
| 363 | if (m_si_bits == 8) |
| 366 | 364 | { |
| 367 | | flash->si_bits = 0; |
| 368 | | at45dbxx_write_byte( device, flash->si_byte); |
| 369 | | flash->si_byte = 0; |
| 365 | m_si_bits = 0; |
| 366 | write_byte(m_si_byte); |
| 367 | m_si_byte = 0; |
| 370 | 368 | } |
| 371 | 369 | // output (part 2) |
| 372 | | flash->pin.so = (flash->so_byte >> flash->so_bits) & 1; |
| 373 | | flash->so_bits++; |
| 370 | m_pin.so = (m_so_byte >> m_so_bits) & 1; |
| 371 | m_so_bits++; |
| 374 | 372 | } |
| 375 | 373 | // save sck |
| 376 | | flash->pin.sck = data; |
| 374 | m_pin.sck = state; |
| 377 | 375 | } |
| 378 | | |
| 379 | | void at45dbxx_load(device_t *device, emu_file *file) |
| 380 | | { |
| 381 | | at45dbxx_t *flash = get_token(device); |
| 382 | | _logerror( 0, ("at45dbxx_load (%p)\n", file)); |
| 383 | | file->read(flash->data, flash->size); |
| 384 | | } |
| 385 | | |
| 386 | | void at45dbxx_save(device_t *device, emu_file *file) |
| 387 | | { |
| 388 | | at45dbxx_t *flash = get_token(device); |
| 389 | | _logerror( 0, ("at45dbxx_save (%p)\n", file)); |
| 390 | | file->write(flash->data, flash->size); |
| 391 | | } |
| 392 | | |
| 393 | | #ifdef UNUSED_FUNCTION |
| 394 | | NVRAM_HANDLER( at45dbxx ) |
| 395 | | { |
| 396 | | _logerror( 0, ("nvram_handler_at45dbxx (%p/%d)\n", file, read_or_write)); |
| 397 | | if (read_or_write) |
| 398 | | { |
| 399 | | at45dbxx_save( file); |
| 400 | | } |
| 401 | | else |
| 402 | | { |
| 403 | | if (file) |
| 404 | | { |
| 405 | | at45dbxx_load( file); |
| 406 | | } |
| 407 | | else |
| 408 | | { |
| 409 | | memset( flash->data, 0xFF, flash->size); |
| 410 | | } |
| 411 | | } |
| 412 | | } |
| 413 | | #endif |
| 414 | | |
| 415 | | |
| 416 | | const device_type AT45DB041 = &device_creator<at45db041_device>; |
| 417 | | |
| 418 | | at45db041_device::at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 419 | | : device_t(mconfig, AT45DB041, "AT45DB041", tag, owner, clock) |
| 420 | | { |
| 421 | | m_token = global_alloc_clear(at45dbxx_t); |
| 422 | | } |
| 423 | | at45db041_device::at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) |
| 424 | | : device_t(mconfig, type, name, tag, owner, clock) |
| 425 | | { |
| 426 | | m_token = global_alloc_clear(at45dbxx_t); |
| 427 | | } |
| 428 | | |
| 429 | | //------------------------------------------------- |
| 430 | | // device_config_complete - perform any |
| 431 | | // operations now that the configuration is |
| 432 | | // complete |
| 433 | | //------------------------------------------------- |
| 434 | | |
| 435 | | void at45db041_device::device_config_complete() |
| 436 | | { |
| 437 | | } |
| 438 | | |
| 439 | | //------------------------------------------------- |
| 440 | | // device_start - device-specific startup |
| 441 | | //------------------------------------------------- |
| 442 | | |
| 443 | | void at45db041_device::device_start() |
| 444 | | { |
| 445 | | DEVICE_START_NAME( at45db041 )(this); |
| 446 | | } |
| 447 | | |
| 448 | | //------------------------------------------------- |
| 449 | | // device_reset - device-specific reset |
| 450 | | //------------------------------------------------- |
| 451 | | |
| 452 | | void at45db041_device::device_reset() |
| 453 | | { |
| 454 | | DEVICE_RESET_NAME( at45dbxx )(this); |
| 455 | | } |
| 456 | | |
| 457 | | |
| 458 | | const device_type AT45DB081 = &device_creator<at45db081_device>; |
| 459 | | |
| 460 | | at45db081_device::at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 461 | | : at45db041_device(mconfig, AT45DB081, "AT45DB081", tag, owner, clock) |
| 462 | | { |
| 463 | | } |
| 464 | | |
| 465 | | //------------------------------------------------- |
| 466 | | // device_start - device-specific startup |
| 467 | | //------------------------------------------------- |
| 468 | | |
| 469 | | void at45db081_device::device_start() |
| 470 | | { |
| 471 | | DEVICE_START_NAME( at45db081 )(this); |
| 472 | | } |
| 473 | | |
| 474 | | |
| 475 | | const device_type AT45DB161 = &device_creator<at45db161_device>; |
| 476 | | |
| 477 | | at45db161_device::at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 478 | | : at45db041_device(mconfig, AT45DB161, "AT45DB161", tag, owner, clock) |
| 479 | | { |
| 480 | | } |
| 481 | | |
| 482 | | //------------------------------------------------- |
| 483 | | // device_start - device-specific startup |
| 484 | | //------------------------------------------------- |
| 485 | | |
| 486 | | void at45db161_device::device_start() |
| 487 | | { |
| 488 | | DEVICE_START_NAME( at45db161 )(this); |
| 489 | | } |
trunk/src/mess/machine/at45dbxx.h
| r20958 | r20959 | |
| 16 | 16 | #include "emu.h" |
| 17 | 17 | |
| 18 | 18 | |
| 19 | | /*************************************************************************** |
| 20 | | MACROS |
| 21 | | ***************************************************************************/ |
| 19 | //************************************************************************** |
| 20 | // INTERFACE CONFIGURATION MACROS |
| 21 | //************************************************************************** |
| 22 | 22 | |
| 23 | | class at45db041_device : public device_t |
| 23 | #define MCFG_AT45DB041_ADD(_tag) \ |
| 24 | MCFG_DEVICE_ADD(_tag, AT45DB041, 0) |
| 25 | |
| 26 | #define MCFG_AT45DB081_ADD(_tag) \ |
| 27 | MCFG_DEVICE_ADD(_tag, AT45DB081, 0) |
| 28 | |
| 29 | #define MCFG_AT45DB161_ADD(_tag) \ |
| 30 | MCFG_DEVICE_ADD(_tag, AT45DB161, 0) |
| 31 | |
| 32 | |
| 33 | // ======================> at45db041_device |
| 34 | |
| 35 | class at45db041_device : public device_t, |
| 36 | public device_nvram_interface |
| 24 | 37 | { |
| 25 | 38 | public: |
| 26 | 39 | at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 27 | 40 | at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock); |
| 28 | | ~at45db041_device() { global_free(m_token); } |
| 29 | 41 | |
| 30 | | // access to legacy token |
| 31 | | void *token() const { assert(m_token != NULL); return m_token; } |
| 42 | DECLARE_WRITE_LINE_MEMBER(cs_w); |
| 43 | DECLARE_WRITE_LINE_MEMBER(sck_w); |
| 44 | DECLARE_WRITE_LINE_MEMBER(si_w); |
| 45 | DECLARE_READ_LINE_MEMBER(so_r); |
| 46 | |
| 32 | 47 | protected: |
| 33 | 48 | // device-level overrides |
| 34 | | virtual void device_config_complete(); |
| 35 | 49 | virtual void device_start(); |
| 36 | 50 | virtual void device_reset(); |
| 37 | | private: |
| 51 | |
| 52 | // device_nvram_interface overrides |
| 53 | virtual void nvram_default(); |
| 54 | virtual void nvram_read(emu_file &file); |
| 55 | virtual void nvram_write(emu_file &file); |
| 56 | |
| 57 | protected: |
| 58 | virtual int num_pages() const { return 2048; } |
| 59 | virtual int page_size() const { return 264; } |
| 60 | virtual UINT8 device_id() const { return 0x18; } |
| 61 | |
| 62 | UINT8 read_byte(); |
| 63 | void flash_set_io(UINT8* data, UINT32 size, UINT32 pos); |
| 64 | virtual UINT32 flash_get_page_addr(); |
| 65 | virtual UINT32 flash_get_byte_addr(); |
| 66 | void write_byte(UINT8 data); |
| 67 | |
| 38 | 68 | // internal state |
| 39 | | void *m_token; |
| 69 | UINT8 * m_data; |
| 70 | UINT32 m_size; |
| 71 | UINT8 m_mode; |
| 72 | UINT8 m_status; |
| 73 | UINT8 * m_buffer1; |
| 74 | UINT8 * m_buffer2; |
| 75 | UINT8 m_si_byte; |
| 76 | UINT8 m_si_bits; |
| 77 | UINT8 m_so_byte; |
| 78 | UINT8 m_so_bits; |
| 79 | |
| 80 | struct AT45DBXX_PINS |
| 81 | { |
| 82 | int cs; // chip select |
| 83 | int sck; // serial clock |
| 84 | int si; // serial input |
| 85 | int so; // serial output |
| 86 | int wp; // write protect |
| 87 | int reset; // reset |
| 88 | int busy; // busy |
| 89 | } m_pin; |
| 90 | |
| 91 | struct AT45DBXX_IO |
| 92 | { |
| 93 | UINT8 *data; |
| 94 | UINT32 size; |
| 95 | UINT32 pos; |
| 96 | } m_io; |
| 97 | |
| 98 | struct AT45DBXX_CMD |
| 99 | { |
| 100 | UINT8 data[8]; |
| 101 | UINT8 size; |
| 102 | } m_cmd; |
| 40 | 103 | }; |
| 41 | 104 | |
| 42 | | extern const device_type AT45DB041; |
| 105 | // ======================> at45db081_device |
| 43 | 106 | |
| 44 | | |
| 45 | | #define MCFG_AT45DB041_ADD(_tag) \ |
| 46 | | MCFG_DEVICE_ADD(_tag, AT45DB041, 0) |
| 47 | 107 | class at45db081_device : public at45db041_device |
| 48 | 108 | { |
| 49 | 109 | public: |
| 50 | 110 | at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 111 | |
| 51 | 112 | protected: |
| 52 | | // device-level overrides |
| 53 | | virtual void device_start(); |
| 113 | virtual int num_pages() const { return 4096; } |
| 114 | virtual int page_size() const { return 264; } |
| 115 | virtual UINT8 device_id() const { return 0x20; } |
| 116 | |
| 117 | virtual UINT32 flash_get_page_addr(); |
| 54 | 118 | }; |
| 55 | 119 | |
| 56 | | extern const device_type AT45DB081; |
| 120 | // ======================> at45db161_device |
| 57 | 121 | |
| 58 | | |
| 59 | | #define MCFG_AT45DB081_ADD(_tag) \ |
| 60 | | MCFG_DEVICE_ADD(_tag, AT45DB081, 0) |
| 61 | 122 | class at45db161_device : public at45db041_device |
| 62 | 123 | { |
| 63 | 124 | public: |
| 64 | 125 | at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 126 | |
| 65 | 127 | protected: |
| 66 | | // device-level overrides |
| 67 | | virtual void device_start(); |
| 128 | virtual int num_pages() const { return 4096; } |
| 129 | virtual int page_size() const { return 528; } |
| 130 | virtual UINT8 device_id() const { return 0x28; } |
| 131 | |
| 132 | virtual UINT32 flash_get_page_addr(); |
| 133 | virtual UINT32 flash_get_byte_addr(); |
| 68 | 134 | }; |
| 69 | 135 | |
| 136 | |
| 137 | // device type definition |
| 138 | extern const device_type AT45DB041; |
| 139 | extern const device_type AT45DB081; |
| 70 | 140 | extern const device_type AT45DB161; |
| 71 | 141 | |
| 72 | | |
| 73 | | #define MCFG_AT45DB161_ADD(_tag) \ |
| 74 | | MCFG_DEVICE_ADD(_tag, AT45DB161, 0) |
| 75 | | |
| 76 | | /*************************************************************************** |
| 77 | | FUNCTION PROTOTYPES |
| 78 | | ***************************************************************************/ |
| 79 | | // pins |
| 80 | | void at45dbxx_pin_cs(device_t *device, int data); |
| 81 | | void at45dbxx_pin_sck(device_t *device, int data); |
| 82 | | void at45dbxx_pin_si(device_t *device, int data); |
| 83 | | int at45dbxx_pin_so(device_t *device); |
| 84 | | |
| 85 | | // load/save |
| 86 | | void at45dbxx_load(device_t *device, emu_file *file); |
| 87 | | void at45dbxx_save(device_t *device, emu_file *file); |
| 88 | | |
| 89 | | // non-volatile ram handler |
| 90 | | //NVRAM_HANDLER( at45dbxx ); |
| 91 | | |
| 92 | 142 | #endif |