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 "qemu/bcd.h" 37 #include "qemu/module.h" 38 39 #include "m48t59-internal.h" 40 #include "migration/vmstate.h" 41 42 #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx" 43 #define M48TXX_SYS_BUS_GET_CLASS(obj) \ 44 OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS) 45 #define M48TXX_SYS_BUS_CLASS(klass) \ 46 OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS) 47 #define M48TXX_SYS_BUS(obj) \ 48 OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS) 49 50 /* 51 * Chipset docs: 52 * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf 53 * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf 54 * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf 55 */ 56 57 typedef struct M48txxSysBusState { 58 SysBusDevice parent_obj; 59 M48t59State state; 60 MemoryRegion io; 61 } M48txxSysBusState; 62 63 typedef struct M48txxSysBusDeviceClass { 64 SysBusDeviceClass parent_class; 65 M48txxInfo info; 66 } M48txxSysBusDeviceClass; 67 68 static M48txxInfo m48txx_sysbus_info[] = { 69 { 70 .bus_name = "sysbus-m48t02", 71 .model = 2, 72 .size = 0x800, 73 },{ 74 .bus_name = "sysbus-m48t08", 75 .model = 8, 76 .size = 0x2000, 77 },{ 78 .bus_name = "sysbus-m48t59", 79 .model = 59, 80 .size = 0x2000, 81 } 82 }; 83 84 85 /* Fake timer functions */ 86 87 /* Alarm management */ 88 static void alarm_cb (void *opaque) 89 { 90 struct tm tm; 91 uint64_t next_time; 92 M48t59State *NVRAM = opaque; 93 94 qemu_set_irq(NVRAM->IRQ, 1); 95 if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && 96 (NVRAM->buffer[0x1FF4] & 0x80) == 0 && 97 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 98 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 99 /* Repeat once a month */ 100 qemu_get_timedate(&tm, NVRAM->time_offset); 101 tm.tm_mon++; 102 if (tm.tm_mon == 13) { 103 tm.tm_mon = 1; 104 tm.tm_year++; 105 } 106 next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset; 107 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 108 (NVRAM->buffer[0x1FF4] & 0x80) == 0 && 109 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 110 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 111 /* Repeat once a day */ 112 next_time = 24 * 60 * 60; 113 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 114 (NVRAM->buffer[0x1FF4] & 0x80) != 0 && 115 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 116 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 117 /* Repeat once an hour */ 118 next_time = 60 * 60; 119 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 120 (NVRAM->buffer[0x1FF4] & 0x80) != 0 && 121 (NVRAM->buffer[0x1FF3] & 0x80) != 0 && 122 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 123 /* Repeat once a minute */ 124 next_time = 60; 125 } else { 126 /* Repeat once a second */ 127 next_time = 1; 128 } 129 timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) + 130 next_time * 1000); 131 qemu_set_irq(NVRAM->IRQ, 0); 132 } 133 134 static void set_alarm(M48t59State *NVRAM) 135 { 136 int diff; 137 if (NVRAM->alrm_timer != NULL) { 138 timer_del(NVRAM->alrm_timer); 139 diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset; 140 if (diff > 0) 141 timer_mod(NVRAM->alrm_timer, diff * 1000); 142 } 143 } 144 145 /* RTC management helpers */ 146 static inline void get_time(M48t59State *NVRAM, struct tm *tm) 147 { 148 qemu_get_timedate(tm, NVRAM->time_offset); 149 } 150 151 static void set_time(M48t59State *NVRAM, struct tm *tm) 152 { 153 NVRAM->time_offset = qemu_timedate_diff(tm); 154 set_alarm(NVRAM); 155 } 156 157 /* Watchdog management */ 158 static void watchdog_cb (void *opaque) 159 { 160 M48t59State *NVRAM = opaque; 161 162 NVRAM->buffer[0x1FF0] |= 0x80; 163 if (NVRAM->buffer[0x1FF7] & 0x80) { 164 NVRAM->buffer[0x1FF7] = 0x00; 165 NVRAM->buffer[0x1FFC] &= ~0x40; 166 /* May it be a hw CPU Reset instead ? */ 167 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 168 } else { 169 qemu_set_irq(NVRAM->IRQ, 1); 170 qemu_set_irq(NVRAM->IRQ, 0); 171 } 172 } 173 174 static void set_up_watchdog(M48t59State *NVRAM, uint8_t value) 175 { 176 uint64_t interval; /* in 1/16 seconds */ 177 178 NVRAM->buffer[0x1FF0] &= ~0x80; 179 if (NVRAM->wd_timer != NULL) { 180 timer_del(NVRAM->wd_timer); 181 if (value != 0) { 182 interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F); 183 timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) + 184 ((interval * 1000) >> 4)); 185 } 186 } 187 } 188 189 /* Direct access to NVRAM */ 190 void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val) 191 { 192 struct tm tm; 193 int tmp; 194 195 if (addr > 0x1FF8 && addr < 0x2000) 196 NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, 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 if (addr > 0x1FF9 && addr < 0x2000) 454 NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval); 455 456 return retval; 457 } 458 459 /* IO access to NVRAM */ 460 static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val, 461 unsigned size) 462 { 463 M48t59State *NVRAM = opaque; 464 465 NVRAM_PRINTF("%s: 0x%"HWADDR_PRIx" => 0x%"PRIx64"\n", __func__, addr, val); 466 switch (addr) { 467 case 0: 468 NVRAM->addr &= ~0x00FF; 469 NVRAM->addr |= val; 470 break; 471 case 1: 472 NVRAM->addr &= ~0xFF00; 473 NVRAM->addr |= val << 8; 474 break; 475 case 3: 476 m48t59_write(NVRAM, NVRAM->addr, val); 477 NVRAM->addr = 0x0000; 478 break; 479 default: 480 break; 481 } 482 } 483 484 static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size) 485 { 486 M48t59State *NVRAM = opaque; 487 uint32_t retval; 488 489 switch (addr) { 490 case 3: 491 retval = m48t59_read(NVRAM, NVRAM->addr); 492 break; 493 default: 494 retval = -1; 495 break; 496 } 497 NVRAM_PRINTF("%s: 0x%"HWADDR_PRIx" <= 0x%08x\n", __func__, addr, retval); 498 499 return retval; 500 } 501 502 static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size) 503 { 504 M48t59State *NVRAM = opaque; 505 506 return m48t59_read(NVRAM, addr); 507 } 508 509 static void nvram_write(void *opaque, hwaddr addr, uint64_t value, 510 unsigned size) 511 { 512 M48t59State *NVRAM = opaque; 513 514 return m48t59_write(NVRAM, addr, value); 515 } 516 517 static const MemoryRegionOps nvram_ops = { 518 .read = nvram_read, 519 .write = nvram_write, 520 .impl.min_access_size = 1, 521 .impl.max_access_size = 1, 522 .valid.min_access_size = 1, 523 .valid.max_access_size = 4, 524 .endianness = DEVICE_BIG_ENDIAN, 525 }; 526 527 static const VMStateDescription vmstate_m48t59 = { 528 .name = "m48t59", 529 .version_id = 1, 530 .minimum_version_id = 1, 531 .fields = (VMStateField[]) { 532 VMSTATE_UINT8(lock, M48t59State), 533 VMSTATE_UINT16(addr, M48t59State), 534 VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, size), 535 VMSTATE_END_OF_LIST() 536 } 537 }; 538 539 void m48t59_reset_common(M48t59State *NVRAM) 540 { 541 NVRAM->addr = 0; 542 NVRAM->lock = 0; 543 if (NVRAM->alrm_timer != NULL) 544 timer_del(NVRAM->alrm_timer); 545 546 if (NVRAM->wd_timer != NULL) 547 timer_del(NVRAM->wd_timer); 548 } 549 550 static void m48t59_reset_sysbus(DeviceState *d) 551 { 552 M48txxSysBusState *sys = M48TXX_SYS_BUS(d); 553 M48t59State *NVRAM = &sys->state; 554 555 m48t59_reset_common(NVRAM); 556 } 557 558 const MemoryRegionOps m48t59_io_ops = { 559 .read = NVRAM_readb, 560 .write = NVRAM_writeb, 561 .impl = { 562 .min_access_size = 1, 563 .max_access_size = 1, 564 }, 565 .endianness = DEVICE_LITTLE_ENDIAN, 566 }; 567 568 /* Initialisation routine */ 569 Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, 570 uint32_t io_base, uint16_t size, int base_year, 571 int model) 572 { 573 DeviceState *dev; 574 SysBusDevice *s; 575 int i; 576 577 for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { 578 if (m48txx_sysbus_info[i].size != size || 579 m48txx_sysbus_info[i].model != model) { 580 continue; 581 } 582 583 dev = qdev_create(NULL, m48txx_sysbus_info[i].bus_name); 584 qdev_prop_set_int32(dev, "base-year", base_year); 585 qdev_init_nofail(dev); 586 s = SYS_BUS_DEVICE(dev); 587 sysbus_connect_irq(s, 0, IRQ); 588 if (io_base != 0) { 589 memory_region_add_subregion(get_system_io(), io_base, 590 sysbus_mmio_get_region(s, 1)); 591 } 592 if (mem_base != 0) { 593 sysbus_mmio_map(s, 0, mem_base); 594 } 595 596 return NVRAM(s); 597 } 598 599 assert(false); 600 return NULL; 601 } 602 603 void m48t59_realize_common(M48t59State *s, Error **errp) 604 { 605 s->buffer = g_malloc0(s->size); 606 if (s->model == 59) { 607 s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s); 608 s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s); 609 } 610 qemu_get_timedate(&s->alarm, 0); 611 } 612 613 static void m48t59_init1(Object *obj) 614 { 615 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(obj); 616 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 617 SysBusDevice *dev = SYS_BUS_DEVICE(obj); 618 M48t59State *s = &d->state; 619 620 s->model = u->info.model; 621 s->size = u->info.size; 622 sysbus_init_irq(dev, &s->IRQ); 623 624 memory_region_init_io(&s->iomem, obj, &nvram_ops, s, "m48t59.nvram", 625 s->size); 626 memory_region_init_io(&d->io, obj, &m48t59_io_ops, s, "m48t59", 4); 627 } 628 629 static void m48t59_realize(DeviceState *dev, Error **errp) 630 { 631 M48txxSysBusState *d = M48TXX_SYS_BUS(dev); 632 M48t59State *s = &d->state; 633 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 634 635 sysbus_init_mmio(sbd, &s->iomem); 636 sysbus_init_mmio(sbd, &d->io); 637 m48t59_realize_common(s, errp); 638 } 639 640 static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr) 641 { 642 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 643 return m48t59_read(&d->state, addr); 644 } 645 646 static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val) 647 { 648 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 649 m48t59_write(&d->state, addr, val); 650 } 651 652 static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock) 653 { 654 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 655 m48t59_toggle_lock(&d->state, lock); 656 } 657 658 static Property m48t59_sysbus_properties[] = { 659 DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0), 660 DEFINE_PROP_END_OF_LIST(), 661 }; 662 663 static void m48txx_sysbus_class_init(ObjectClass *klass, void *data) 664 { 665 DeviceClass *dc = DEVICE_CLASS(klass); 666 NvramClass *nc = NVRAM_CLASS(klass); 667 668 dc->realize = m48t59_realize; 669 dc->reset = m48t59_reset_sysbus; 670 dc->props = m48t59_sysbus_properties; 671 dc->vmsd = &vmstate_m48t59; 672 nc->read = m48txx_sysbus_read; 673 nc->write = m48txx_sysbus_write; 674 nc->toggle_lock = m48txx_sysbus_toggle_lock; 675 } 676 677 static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data) 678 { 679 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass); 680 M48txxInfo *info = data; 681 682 u->info = *info; 683 } 684 685 static const TypeInfo nvram_info = { 686 .name = TYPE_NVRAM, 687 .parent = TYPE_INTERFACE, 688 .class_size = sizeof(NvramClass), 689 }; 690 691 static const TypeInfo m48txx_sysbus_type_info = { 692 .name = TYPE_M48TXX_SYS_BUS, 693 .parent = TYPE_SYS_BUS_DEVICE, 694 .instance_size = sizeof(M48txxSysBusState), 695 .instance_init = m48t59_init1, 696 .abstract = true, 697 .class_init = m48txx_sysbus_class_init, 698 .interfaces = (InterfaceInfo[]) { 699 { TYPE_NVRAM }, 700 { } 701 } 702 }; 703 704 static void m48t59_register_types(void) 705 { 706 TypeInfo sysbus_type_info = { 707 .parent = TYPE_M48TXX_SYS_BUS, 708 .class_size = sizeof(M48txxSysBusDeviceClass), 709 .class_init = m48txx_sysbus_concrete_class_init, 710 }; 711 int i; 712 713 type_register_static(&nvram_info); 714 type_register_static(&m48txx_sysbus_type_info); 715 716 for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { 717 sysbus_type_info.name = m48txx_sysbus_info[i].bus_name; 718 sysbus_type_info.class_data = &m48txx_sysbus_info[i]; 719 type_register(&sysbus_type_info); 720 } 721 } 722 723 type_init(m48t59_register_types) 724