1 /* 2 * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms 3 * 4 * Copyright (c) 2003-2005, 2007, 2017 Jocelyn Mayer 5 * Copyright (c) 2013 Hervé Poussineau 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "qemu/osdep.h" 27 #include "qemu-common.h" 28 #include "hw/irq.h" 29 #include "hw/qdev-properties.h" 30 #include "hw/rtc/m48t59.h" 31 #include "qemu/timer.h" 32 #include "sysemu/runstate.h" 33 #include "sysemu/sysemu.h" 34 #include "hw/sysbus.h" 35 #include "exec/address-spaces.h" 36 #include "qapi/error.h" 37 #include "qemu/bcd.h" 38 #include "qemu/module.h" 39 #include "trace.h" 40 41 #include "m48t59-internal.h" 42 #include "migration/vmstate.h" 43 #include "qom/object.h" 44 45 #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx" 46 typedef struct M48txxSysBusDeviceClass M48txxSysBusDeviceClass; 47 typedef struct M48txxSysBusState M48txxSysBusState; 48 DECLARE_OBJ_CHECKERS(M48txxSysBusState, M48txxSysBusDeviceClass, 49 M48TXX_SYS_BUS, TYPE_M48TXX_SYS_BUS) 50 51 /* 52 * Chipset docs: 53 * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf 54 * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf 55 * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf 56 */ 57 58 struct M48txxSysBusState { 59 SysBusDevice parent_obj; 60 M48t59State state; 61 MemoryRegion io; 62 }; 63 64 struct M48txxSysBusDeviceClass { 65 SysBusDeviceClass parent_class; 66 M48txxInfo info; 67 }; 68 69 static M48txxInfo m48txx_sysbus_info[] = { 70 { 71 .bus_name = "sysbus-m48t02", 72 .model = 2, 73 .size = 0x800, 74 },{ 75 .bus_name = "sysbus-m48t08", 76 .model = 8, 77 .size = 0x2000, 78 },{ 79 .bus_name = "sysbus-m48t59", 80 .model = 59, 81 .size = 0x2000, 82 } 83 }; 84 85 86 /* Fake timer functions */ 87 88 /* Alarm management */ 89 static void alarm_cb (void *opaque) 90 { 91 struct tm tm; 92 uint64_t next_time; 93 M48t59State *NVRAM = opaque; 94 95 qemu_set_irq(NVRAM->IRQ, 1); 96 if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && 97 (NVRAM->buffer[0x1FF4] & 0x80) == 0 && 98 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 99 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 100 /* Repeat once a month */ 101 qemu_get_timedate(&tm, NVRAM->time_offset); 102 tm.tm_mon++; 103 if (tm.tm_mon == 13) { 104 tm.tm_mon = 1; 105 tm.tm_year++; 106 } 107 next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset; 108 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 109 (NVRAM->buffer[0x1FF4] & 0x80) == 0 && 110 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 111 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 112 /* Repeat once a day */ 113 next_time = 24 * 60 * 60; 114 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 115 (NVRAM->buffer[0x1FF4] & 0x80) != 0 && 116 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 117 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 118 /* Repeat once an hour */ 119 next_time = 60 * 60; 120 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 121 (NVRAM->buffer[0x1FF4] & 0x80) != 0 && 122 (NVRAM->buffer[0x1FF3] & 0x80) != 0 && 123 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 124 /* Repeat once a minute */ 125 next_time = 60; 126 } else { 127 /* Repeat once a second */ 128 next_time = 1; 129 } 130 timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) + 131 next_time * 1000); 132 qemu_set_irq(NVRAM->IRQ, 0); 133 } 134 135 static void set_alarm(M48t59State *NVRAM) 136 { 137 int diff; 138 if (NVRAM->alrm_timer != NULL) { 139 timer_del(NVRAM->alrm_timer); 140 diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset; 141 if (diff > 0) 142 timer_mod(NVRAM->alrm_timer, diff * 1000); 143 } 144 } 145 146 /* RTC management helpers */ 147 static inline void get_time(M48t59State *NVRAM, struct tm *tm) 148 { 149 qemu_get_timedate(tm, NVRAM->time_offset); 150 } 151 152 static void set_time(M48t59State *NVRAM, struct tm *tm) 153 { 154 NVRAM->time_offset = qemu_timedate_diff(tm); 155 set_alarm(NVRAM); 156 } 157 158 /* Watchdog management */ 159 static void watchdog_cb (void *opaque) 160 { 161 M48t59State *NVRAM = opaque; 162 163 NVRAM->buffer[0x1FF0] |= 0x80; 164 if (NVRAM->buffer[0x1FF7] & 0x80) { 165 NVRAM->buffer[0x1FF7] = 0x00; 166 NVRAM->buffer[0x1FFC] &= ~0x40; 167 /* May it be a hw CPU Reset instead ? */ 168 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 169 } else { 170 qemu_set_irq(NVRAM->IRQ, 1); 171 qemu_set_irq(NVRAM->IRQ, 0); 172 } 173 } 174 175 static void set_up_watchdog(M48t59State *NVRAM, uint8_t value) 176 { 177 uint64_t interval; /* in 1/16 seconds */ 178 179 NVRAM->buffer[0x1FF0] &= ~0x80; 180 if (NVRAM->wd_timer != NULL) { 181 timer_del(NVRAM->wd_timer); 182 if (value != 0) { 183 interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F); 184 timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) + 185 ((interval * 1000) >> 4)); 186 } 187 } 188 } 189 190 /* Direct access to NVRAM */ 191 void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val) 192 { 193 struct tm tm; 194 int tmp; 195 196 trace_m48txx_nvram_mem_write(addr, val); 197 198 /* check for NVRAM access */ 199 if ((NVRAM->model == 2 && addr < 0x7f8) || 200 (NVRAM->model == 8 && addr < 0x1ff8) || 201 (NVRAM->model == 59 && addr < 0x1ff0)) { 202 goto do_write; 203 } 204 205 /* TOD access */ 206 switch (addr) { 207 case 0x1FF0: 208 /* flags register : read-only */ 209 break; 210 case 0x1FF1: 211 /* unused */ 212 break; 213 case 0x1FF2: 214 /* alarm seconds */ 215 tmp = from_bcd(val & 0x7F); 216 if (tmp >= 0 && tmp <= 59) { 217 NVRAM->alarm.tm_sec = tmp; 218 NVRAM->buffer[0x1FF2] = val; 219 set_alarm(NVRAM); 220 } 221 break; 222 case 0x1FF3: 223 /* alarm minutes */ 224 tmp = from_bcd(val & 0x7F); 225 if (tmp >= 0 && tmp <= 59) { 226 NVRAM->alarm.tm_min = tmp; 227 NVRAM->buffer[0x1FF3] = val; 228 set_alarm(NVRAM); 229 } 230 break; 231 case 0x1FF4: 232 /* alarm hours */ 233 tmp = from_bcd(val & 0x3F); 234 if (tmp >= 0 && tmp <= 23) { 235 NVRAM->alarm.tm_hour = tmp; 236 NVRAM->buffer[0x1FF4] = val; 237 set_alarm(NVRAM); 238 } 239 break; 240 case 0x1FF5: 241 /* alarm date */ 242 tmp = from_bcd(val & 0x3F); 243 if (tmp != 0) { 244 NVRAM->alarm.tm_mday = tmp; 245 NVRAM->buffer[0x1FF5] = val; 246 set_alarm(NVRAM); 247 } 248 break; 249 case 0x1FF6: 250 /* interrupts */ 251 NVRAM->buffer[0x1FF6] = val; 252 break; 253 case 0x1FF7: 254 /* watchdog */ 255 NVRAM->buffer[0x1FF7] = val; 256 set_up_watchdog(NVRAM, val); 257 break; 258 case 0x1FF8: 259 case 0x07F8: 260 /* control */ 261 NVRAM->buffer[addr] = (val & ~0xA0) | 0x90; 262 break; 263 case 0x1FF9: 264 case 0x07F9: 265 /* seconds (BCD) */ 266 tmp = from_bcd(val & 0x7F); 267 if (tmp >= 0 && tmp <= 59) { 268 get_time(NVRAM, &tm); 269 tm.tm_sec = tmp; 270 set_time(NVRAM, &tm); 271 } 272 if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) { 273 if (val & 0x80) { 274 NVRAM->stop_time = time(NULL); 275 } else { 276 NVRAM->time_offset += NVRAM->stop_time - time(NULL); 277 NVRAM->stop_time = 0; 278 } 279 } 280 NVRAM->buffer[addr] = val & 0x80; 281 break; 282 case 0x1FFA: 283 case 0x07FA: 284 /* minutes (BCD) */ 285 tmp = from_bcd(val & 0x7F); 286 if (tmp >= 0 && tmp <= 59) { 287 get_time(NVRAM, &tm); 288 tm.tm_min = tmp; 289 set_time(NVRAM, &tm); 290 } 291 break; 292 case 0x1FFB: 293 case 0x07FB: 294 /* hours (BCD) */ 295 tmp = from_bcd(val & 0x3F); 296 if (tmp >= 0 && tmp <= 23) { 297 get_time(NVRAM, &tm); 298 tm.tm_hour = tmp; 299 set_time(NVRAM, &tm); 300 } 301 break; 302 case 0x1FFC: 303 case 0x07FC: 304 /* day of the week / century */ 305 tmp = from_bcd(val & 0x07); 306 get_time(NVRAM, &tm); 307 tm.tm_wday = tmp; 308 set_time(NVRAM, &tm); 309 NVRAM->buffer[addr] = val & 0x40; 310 break; 311 case 0x1FFD: 312 case 0x07FD: 313 /* date (BCD) */ 314 tmp = from_bcd(val & 0x3F); 315 if (tmp != 0) { 316 get_time(NVRAM, &tm); 317 tm.tm_mday = tmp; 318 set_time(NVRAM, &tm); 319 } 320 break; 321 case 0x1FFE: 322 case 0x07FE: 323 /* month */ 324 tmp = from_bcd(val & 0x1F); 325 if (tmp >= 1 && tmp <= 12) { 326 get_time(NVRAM, &tm); 327 tm.tm_mon = tmp - 1; 328 set_time(NVRAM, &tm); 329 } 330 break; 331 case 0x1FFF: 332 case 0x07FF: 333 /* year */ 334 tmp = from_bcd(val); 335 if (tmp >= 0 && tmp <= 99) { 336 get_time(NVRAM, &tm); 337 tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900; 338 set_time(NVRAM, &tm); 339 } 340 break; 341 default: 342 /* Check lock registers state */ 343 if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1)) 344 break; 345 if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2)) 346 break; 347 do_write: 348 if (addr < NVRAM->size) { 349 NVRAM->buffer[addr] = val & 0xFF; 350 } 351 break; 352 } 353 } 354 355 uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr) 356 { 357 struct tm tm; 358 uint32_t retval = 0xFF; 359 360 /* check for NVRAM access */ 361 if ((NVRAM->model == 2 && addr < 0x078f) || 362 (NVRAM->model == 8 && addr < 0x1ff8) || 363 (NVRAM->model == 59 && addr < 0x1ff0)) { 364 goto do_read; 365 } 366 367 /* TOD access */ 368 switch (addr) { 369 case 0x1FF0: 370 /* flags register */ 371 goto do_read; 372 case 0x1FF1: 373 /* unused */ 374 retval = 0; 375 break; 376 case 0x1FF2: 377 /* alarm seconds */ 378 goto do_read; 379 case 0x1FF3: 380 /* alarm minutes */ 381 goto do_read; 382 case 0x1FF4: 383 /* alarm hours */ 384 goto do_read; 385 case 0x1FF5: 386 /* alarm date */ 387 goto do_read; 388 case 0x1FF6: 389 /* interrupts */ 390 goto do_read; 391 case 0x1FF7: 392 /* A read resets the watchdog */ 393 set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]); 394 goto do_read; 395 case 0x1FF8: 396 case 0x07F8: 397 /* control */ 398 goto do_read; 399 case 0x1FF9: 400 case 0x07F9: 401 /* seconds (BCD) */ 402 get_time(NVRAM, &tm); 403 retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec); 404 break; 405 case 0x1FFA: 406 case 0x07FA: 407 /* minutes (BCD) */ 408 get_time(NVRAM, &tm); 409 retval = to_bcd(tm.tm_min); 410 break; 411 case 0x1FFB: 412 case 0x07FB: 413 /* hours (BCD) */ 414 get_time(NVRAM, &tm); 415 retval = to_bcd(tm.tm_hour); 416 break; 417 case 0x1FFC: 418 case 0x07FC: 419 /* day of the week / century */ 420 get_time(NVRAM, &tm); 421 retval = NVRAM->buffer[addr] | tm.tm_wday; 422 break; 423 case 0x1FFD: 424 case 0x07FD: 425 /* date */ 426 get_time(NVRAM, &tm); 427 retval = to_bcd(tm.tm_mday); 428 break; 429 case 0x1FFE: 430 case 0x07FE: 431 /* month */ 432 get_time(NVRAM, &tm); 433 retval = to_bcd(tm.tm_mon + 1); 434 break; 435 case 0x1FFF: 436 case 0x07FF: 437 /* year */ 438 get_time(NVRAM, &tm); 439 retval = to_bcd((tm.tm_year + 1900 - NVRAM->base_year) % 100); 440 break; 441 default: 442 /* Check lock registers state */ 443 if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1)) 444 break; 445 if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2)) 446 break; 447 do_read: 448 if (addr < NVRAM->size) { 449 retval = NVRAM->buffer[addr]; 450 } 451 break; 452 } 453 trace_m48txx_nvram_mem_read(addr, retval); 454 455 return retval; 456 } 457 458 /* IO access to NVRAM */ 459 static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val, 460 unsigned size) 461 { 462 M48t59State *NVRAM = opaque; 463 464 trace_m48txx_nvram_io_write(addr, val); 465 switch (addr) { 466 case 0: 467 NVRAM->addr &= ~0x00FF; 468 NVRAM->addr |= val; 469 break; 470 case 1: 471 NVRAM->addr &= ~0xFF00; 472 NVRAM->addr |= val << 8; 473 break; 474 case 3: 475 m48t59_write(NVRAM, NVRAM->addr, val); 476 NVRAM->addr = 0x0000; 477 break; 478 default: 479 break; 480 } 481 } 482 483 static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size) 484 { 485 M48t59State *NVRAM = opaque; 486 uint32_t retval; 487 488 switch (addr) { 489 case 3: 490 retval = m48t59_read(NVRAM, NVRAM->addr); 491 break; 492 default: 493 retval = -1; 494 break; 495 } 496 trace_m48txx_nvram_io_read(addr, retval); 497 498 return retval; 499 } 500 501 static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size) 502 { 503 M48t59State *NVRAM = opaque; 504 505 return m48t59_read(NVRAM, addr); 506 } 507 508 static void nvram_write(void *opaque, hwaddr addr, uint64_t value, 509 unsigned size) 510 { 511 M48t59State *NVRAM = opaque; 512 513 return m48t59_write(NVRAM, addr, value); 514 } 515 516 static const MemoryRegionOps nvram_ops = { 517 .read = nvram_read, 518 .write = nvram_write, 519 .impl.min_access_size = 1, 520 .impl.max_access_size = 1, 521 .valid.min_access_size = 1, 522 .valid.max_access_size = 4, 523 .endianness = DEVICE_BIG_ENDIAN, 524 }; 525 526 static const VMStateDescription vmstate_m48t59 = { 527 .name = "m48t59", 528 .version_id = 1, 529 .minimum_version_id = 1, 530 .fields = (VMStateField[]) { 531 VMSTATE_UINT8(lock, M48t59State), 532 VMSTATE_UINT16(addr, M48t59State), 533 VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, size), 534 VMSTATE_END_OF_LIST() 535 } 536 }; 537 538 void m48t59_reset_common(M48t59State *NVRAM) 539 { 540 NVRAM->addr = 0; 541 NVRAM->lock = 0; 542 if (NVRAM->alrm_timer != NULL) 543 timer_del(NVRAM->alrm_timer); 544 545 if (NVRAM->wd_timer != NULL) 546 timer_del(NVRAM->wd_timer); 547 } 548 549 static void m48t59_reset_sysbus(DeviceState *d) 550 { 551 M48txxSysBusState *sys = M48TXX_SYS_BUS(d); 552 M48t59State *NVRAM = &sys->state; 553 554 m48t59_reset_common(NVRAM); 555 } 556 557 const MemoryRegionOps m48t59_io_ops = { 558 .read = NVRAM_readb, 559 .write = NVRAM_writeb, 560 .impl = { 561 .min_access_size = 1, 562 .max_access_size = 1, 563 }, 564 .endianness = DEVICE_LITTLE_ENDIAN, 565 }; 566 567 /* Initialisation routine */ 568 Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, 569 uint32_t io_base, uint16_t size, int base_year, 570 int model) 571 { 572 DeviceState *dev; 573 SysBusDevice *s; 574 int i; 575 576 for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { 577 if (m48txx_sysbus_info[i].size != size || 578 m48txx_sysbus_info[i].model != model) { 579 continue; 580 } 581 582 dev = qdev_new(m48txx_sysbus_info[i].bus_name); 583 qdev_prop_set_int32(dev, "base-year", base_year); 584 s = SYS_BUS_DEVICE(dev); 585 sysbus_realize_and_unref(s, &error_fatal); 586 sysbus_connect_irq(s, 0, IRQ); 587 if (io_base != 0) { 588 memory_region_add_subregion(get_system_io(), io_base, 589 sysbus_mmio_get_region(s, 1)); 590 } 591 if (mem_base != 0) { 592 sysbus_mmio_map(s, 0, mem_base); 593 } 594 595 return NVRAM(s); 596 } 597 598 assert(false); 599 return NULL; 600 } 601 602 void m48t59_realize_common(M48t59State *s, Error **errp) 603 { 604 s->buffer = g_malloc0(s->size); 605 if (s->model == 59) { 606 s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s); 607 s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s); 608 } 609 qemu_get_timedate(&s->alarm, 0); 610 } 611 612 static void m48t59_init1(Object *obj) 613 { 614 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(obj); 615 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 616 SysBusDevice *dev = SYS_BUS_DEVICE(obj); 617 M48t59State *s = &d->state; 618 619 s->model = u->info.model; 620 s->size = u->info.size; 621 sysbus_init_irq(dev, &s->IRQ); 622 623 memory_region_init_io(&s->iomem, obj, &nvram_ops, s, "m48t59.nvram", 624 s->size); 625 memory_region_init_io(&d->io, obj, &m48t59_io_ops, s, "m48t59", 4); 626 } 627 628 static void m48t59_realize(DeviceState *dev, Error **errp) 629 { 630 M48txxSysBusState *d = M48TXX_SYS_BUS(dev); 631 M48t59State *s = &d->state; 632 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 633 634 sysbus_init_mmio(sbd, &s->iomem); 635 sysbus_init_mmio(sbd, &d->io); 636 m48t59_realize_common(s, errp); 637 } 638 639 static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr) 640 { 641 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 642 return m48t59_read(&d->state, addr); 643 } 644 645 static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val) 646 { 647 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 648 m48t59_write(&d->state, addr, val); 649 } 650 651 static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock) 652 { 653 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 654 m48t59_toggle_lock(&d->state, lock); 655 } 656 657 static Property m48t59_sysbus_properties[] = { 658 DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0), 659 DEFINE_PROP_END_OF_LIST(), 660 }; 661 662 static void m48txx_sysbus_class_init(ObjectClass *klass, void *data) 663 { 664 DeviceClass *dc = DEVICE_CLASS(klass); 665 NvramClass *nc = NVRAM_CLASS(klass); 666 667 dc->realize = m48t59_realize; 668 dc->reset = m48t59_reset_sysbus; 669 device_class_set_props(dc, m48t59_sysbus_properties); 670 dc->vmsd = &vmstate_m48t59; 671 nc->read = m48txx_sysbus_read; 672 nc->write = m48txx_sysbus_write; 673 nc->toggle_lock = m48txx_sysbus_toggle_lock; 674 } 675 676 static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data) 677 { 678 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass); 679 M48txxInfo *info = data; 680 681 u->info = *info; 682 } 683 684 static const TypeInfo nvram_info = { 685 .name = TYPE_NVRAM, 686 .parent = TYPE_INTERFACE, 687 .class_size = sizeof(NvramClass), 688 }; 689 690 static const TypeInfo m48txx_sysbus_type_info = { 691 .name = TYPE_M48TXX_SYS_BUS, 692 .parent = TYPE_SYS_BUS_DEVICE, 693 .instance_size = sizeof(M48txxSysBusState), 694 .instance_init = m48t59_init1, 695 .abstract = true, 696 .class_init = m48txx_sysbus_class_init, 697 .interfaces = (InterfaceInfo[]) { 698 { TYPE_NVRAM }, 699 { } 700 } 701 }; 702 703 static void m48t59_register_types(void) 704 { 705 TypeInfo sysbus_type_info = { 706 .parent = TYPE_M48TXX_SYS_BUS, 707 .class_size = sizeof(M48txxSysBusDeviceClass), 708 .class_init = m48txx_sysbus_concrete_class_init, 709 }; 710 int i; 711 712 type_register_static(&nvram_info); 713 type_register_static(&m48txx_sysbus_type_info); 714 715 for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { 716 sysbus_type_info.name = m48txx_sysbus_info[i].bus_name; 717 sysbus_type_info.class_data = &m48txx_sysbus_info[i]; 718 type_register(&sysbus_type_info); 719 } 720 } 721 722 type_init(m48t59_register_types) 723