Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.25 764 lines 18 kB view raw
1/* 2 * Miscellaneous Mac68K-specific stuff 3 */ 4 5#include <linux/types.h> 6#include <linux/errno.h> 7#include <linux/miscdevice.h> 8#include <linux/kernel.h> 9#include <linux/delay.h> 10#include <linux/sched.h> 11#include <linux/slab.h> 12#include <linux/time.h> 13#include <linux/rtc.h> 14#include <linux/mm.h> 15 16#include <linux/adb.h> 17#include <linux/cuda.h> 18#include <linux/pmu.h> 19 20#include <asm/uaccess.h> 21#include <asm/io.h> 22#include <asm/rtc.h> 23#include <asm/system.h> 24#include <asm/segment.h> 25#include <asm/setup.h> 26#include <asm/macintosh.h> 27#include <asm/mac_via.h> 28#include <asm/mac_oss.h> 29 30#define BOOTINFO_COMPAT_1_0 31#include <asm/bootinfo.h> 32#include <asm/machdep.h> 33 34/* Offset between Unix time (1970-based) and Mac time (1904-based) */ 35 36#define RTC_OFFSET 2082844800 37 38extern struct mac_booter_data mac_bi_data; 39static void (*rom_reset)(void); 40 41#ifdef CONFIG_ADB_CUDA 42static long cuda_read_time(void) 43{ 44 struct adb_request req; 45 long time; 46 47 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) 48 return 0; 49 while (!req.complete) 50 cuda_poll(); 51 52 time = (req.reply[3] << 24) | (req.reply[4] << 16) 53 | (req.reply[5] << 8) | req.reply[6]; 54 return time - RTC_OFFSET; 55} 56 57static void cuda_write_time(long data) 58{ 59 struct adb_request req; 60 data += RTC_OFFSET; 61 if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 62 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 63 (data >> 8) & 0xFF, data & 0xFF) < 0) 64 return; 65 while (!req.complete) 66 cuda_poll(); 67} 68 69static __u8 cuda_read_pram(int offset) 70{ 71 struct adb_request req; 72 if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, 73 (offset >> 8) & 0xFF, offset & 0xFF) < 0) 74 return 0; 75 while (!req.complete) 76 cuda_poll(); 77 return req.reply[3]; 78} 79 80static void cuda_write_pram(int offset, __u8 data) 81{ 82 struct adb_request req; 83 if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, 84 (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) 85 return; 86 while (!req.complete) 87 cuda_poll(); 88} 89#else 90#define cuda_read_time() 0 91#define cuda_write_time(n) 92#define cuda_read_pram NULL 93#define cuda_write_pram NULL 94#endif 95 96#ifdef CONFIG_ADB_PMU68K 97static long pmu_read_time(void) 98{ 99 struct adb_request req; 100 long time; 101 102 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) 103 return 0; 104 while (!req.complete) 105 pmu_poll(); 106 107 time = (req.reply[0] << 24) | (req.reply[1] << 16) 108 | (req.reply[2] << 8) | req.reply[3]; 109 return time - RTC_OFFSET; 110} 111 112static void pmu_write_time(long data) 113{ 114 struct adb_request req; 115 data += RTC_OFFSET; 116 if (pmu_request(&req, NULL, 5, PMU_SET_RTC, 117 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 118 (data >> 8) & 0xFF, data & 0xFF) < 0) 119 return; 120 while (!req.complete) 121 pmu_poll(); 122} 123 124static __u8 pmu_read_pram(int offset) 125{ 126 struct adb_request req; 127 if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 128 (offset >> 8) & 0xFF, offset & 0xFF) < 0) 129 return 0; 130 while (!req.complete) 131 pmu_poll(); 132 return req.reply[3]; 133} 134 135static void pmu_write_pram(int offset, __u8 data) 136{ 137 struct adb_request req; 138 if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, 139 (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) 140 return; 141 while (!req.complete) 142 pmu_poll(); 143} 144#else 145#define pmu_read_time() 0 146#define pmu_write_time(n) 147#define pmu_read_pram NULL 148#define pmu_write_pram NULL 149#endif 150 151#ifdef CONFIG_ADB_MACIISI 152extern int maciisi_request(struct adb_request *req, 153 void (*done)(struct adb_request *), int nbytes, ...); 154 155static long maciisi_read_time(void) 156{ 157 struct adb_request req; 158 long time; 159 160 if (maciisi_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME)) 161 return 0; 162 163 time = (req.reply[3] << 24) | (req.reply[4] << 16) 164 | (req.reply[5] << 8) | req.reply[6]; 165 return time - RTC_OFFSET; 166} 167 168static void maciisi_write_time(long data) 169{ 170 struct adb_request req; 171 data += RTC_OFFSET; 172 maciisi_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 173 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 174 (data >> 8) & 0xFF, data & 0xFF); 175} 176 177static __u8 maciisi_read_pram(int offset) 178{ 179 struct adb_request req; 180 if (maciisi_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, 181 (offset >> 8) & 0xFF, offset & 0xFF)) 182 return 0; 183 return req.reply[3]; 184} 185 186static void maciisi_write_pram(int offset, __u8 data) 187{ 188 struct adb_request req; 189 maciisi_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, 190 (offset >> 8) & 0xFF, offset & 0xFF, data); 191} 192#else 193#define maciisi_read_time() 0 194#define maciisi_write_time(n) 195#define maciisi_read_pram NULL 196#define maciisi_write_pram NULL 197#endif 198 199/* 200 * VIA PRAM/RTC access routines 201 * 202 * Must be called with interrupts disabled and 203 * the RTC should be enabled. 204 */ 205 206static __u8 via_pram_readbyte(void) 207{ 208 int i,reg; 209 __u8 data; 210 211 reg = via1[vBufB] & ~VIA1B_vRTCClk; 212 213 /* Set the RTC data line to be an input. */ 214 215 via1[vDirB] &= ~VIA1B_vRTCData; 216 217 /* The bits of the byte come out in MSB order */ 218 219 data = 0; 220 for (i = 0 ; i < 8 ; i++) { 221 via1[vBufB] = reg; 222 via1[vBufB] = reg | VIA1B_vRTCClk; 223 data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData); 224 } 225 226 /* Return RTC data line to output state */ 227 228 via1[vDirB] |= VIA1B_vRTCData; 229 230 return data; 231} 232 233static void via_pram_writebyte(__u8 data) 234{ 235 int i,reg,bit; 236 237 reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData); 238 239 /* The bits of the byte go in in MSB order */ 240 241 for (i = 0 ; i < 8 ; i++) { 242 bit = data & 0x80? 1 : 0; 243 data <<= 1; 244 via1[vBufB] = reg | bit; 245 via1[vBufB] = reg | bit | VIA1B_vRTCClk; 246 } 247} 248 249/* 250 * Execute a VIA PRAM/RTC command. For read commands 251 * data should point to a one-byte buffer for the 252 * resulting data. For write commands it should point 253 * to the data byte to for the command. 254 * 255 * This function disables all interrupts while running. 256 */ 257 258static void via_pram_command(int command, __u8 *data) 259{ 260 unsigned long flags; 261 int is_read; 262 263 local_irq_save(flags); 264 265 /* Enable the RTC and make sure the strobe line is high */ 266 267 via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb; 268 269 if (command & 0xFF00) { /* extended (two-byte) command */ 270 via_pram_writebyte((command & 0xFF00) >> 8); 271 via_pram_writebyte(command & 0xFF); 272 is_read = command & 0x8000; 273 } else { /* one-byte command */ 274 via_pram_writebyte(command); 275 is_read = command & 0x80; 276 } 277 if (is_read) { 278 *data = via_pram_readbyte(); 279 } else { 280 via_pram_writebyte(*data); 281 } 282 283 /* All done, disable the RTC */ 284 285 via1[vBufB] |= VIA1B_vRTCEnb; 286 287 local_irq_restore(flags); 288} 289 290static __u8 via_read_pram(int offset) 291{ 292 return 0; 293} 294 295static void via_write_pram(int offset, __u8 data) 296{ 297} 298 299/* 300 * Return the current time in seconds since January 1, 1904. 301 * 302 * This only works on machines with the VIA-based PRAM/RTC, which 303 * is basically any machine with Mac II-style ADB. 304 */ 305 306static long via_read_time(void) 307{ 308 union { 309 __u8 cdata[4]; 310 long idata; 311 } result, last_result; 312 int ct; 313 314 /* 315 * The NetBSD guys say to loop until you get the same reading 316 * twice in a row. 317 */ 318 319 ct = 0; 320 do { 321 if (++ct > 10) { 322 printk("via_read_time: couldn't get valid time, " 323 "last read = 0x%08lx and 0x%08lx\n", 324 last_result.idata, result.idata); 325 break; 326 } 327 328 last_result.idata = result.idata; 329 result.idata = 0; 330 331 via_pram_command(0x81, &result.cdata[3]); 332 via_pram_command(0x85, &result.cdata[2]); 333 via_pram_command(0x89, &result.cdata[1]); 334 via_pram_command(0x8D, &result.cdata[0]); 335 } while (result.idata != last_result.idata); 336 337 return result.idata - RTC_OFFSET; 338} 339 340/* 341 * Set the current time to a number of seconds since January 1, 1904. 342 * 343 * This only works on machines with the VIA-based PRAM/RTC, which 344 * is basically any machine with Mac II-style ADB. 345 */ 346 347static void via_write_time(long time) 348{ 349 union { 350 __u8 cdata[4]; 351 long idata; 352 } data; 353 __u8 temp; 354 355 /* Clear the write protect bit */ 356 357 temp = 0x55; 358 via_pram_command(0x35, &temp); 359 360 data.idata = time + RTC_OFFSET; 361 via_pram_command(0x01, &data.cdata[3]); 362 via_pram_command(0x05, &data.cdata[2]); 363 via_pram_command(0x09, &data.cdata[1]); 364 via_pram_command(0x0D, &data.cdata[0]); 365 366 /* Set the write protect bit */ 367 368 temp = 0xD5; 369 via_pram_command(0x35, &temp); 370} 371 372static void via_shutdown(void) 373{ 374 if (rbv_present) { 375 via2[rBufB] &= ~0x04; 376 } else { 377 /* Direction of vDirB is output */ 378 via2[vDirB] |= 0x04; 379 /* Send a value of 0 on that line */ 380 via2[vBufB] &= ~0x04; 381 mdelay(1000); 382 } 383} 384 385/* 386 * FIXME: not sure how this is supposed to work exactly... 387 */ 388 389static void oss_shutdown(void) 390{ 391 oss->rom_ctrl = OSS_POWEROFF; 392} 393 394#ifdef CONFIG_ADB_CUDA 395 396static void cuda_restart(void) 397{ 398 struct adb_request req; 399 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0) 400 return; 401 while (!req.complete) 402 cuda_poll(); 403} 404 405static void cuda_shutdown(void) 406{ 407 struct adb_request req; 408 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0) 409 return; 410 while (!req.complete) 411 cuda_poll(); 412} 413 414#endif /* CONFIG_ADB_CUDA */ 415 416#ifdef CONFIG_ADB_PMU68K 417 418void pmu_restart(void) 419{ 420 struct adb_request req; 421 if (pmu_request(&req, NULL, 422 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) 423 return; 424 while (!req.complete) 425 pmu_poll(); 426 if (pmu_request(&req, NULL, 1, PMU_RESET) < 0) 427 return; 428 while (!req.complete) 429 pmu_poll(); 430} 431 432void pmu_shutdown(void) 433{ 434 struct adb_request req; 435 if (pmu_request(&req, NULL, 436 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) 437 return; 438 while (!req.complete) 439 pmu_poll(); 440 if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0) 441 return; 442 while (!req.complete) 443 pmu_poll(); 444} 445 446#endif 447 448/* 449 *------------------------------------------------------------------- 450 * Below this point are the generic routines; they'll dispatch to the 451 * correct routine for the hardware on which we're running. 452 *------------------------------------------------------------------- 453 */ 454 455void mac_pram_read(int offset, __u8 *buffer, int len) 456{ 457 __u8 (*func)(int); 458 int i; 459 460 switch(macintosh_config->adb_type) { 461 case MAC_ADB_IISI: 462 func = maciisi_read_pram; break; 463 case MAC_ADB_PB1: 464 case MAC_ADB_PB2: 465 func = pmu_read_pram; break; 466 case MAC_ADB_CUDA: 467 func = cuda_read_pram; break; 468 default: 469 func = via_read_pram; 470 } 471 if (!func) 472 return; 473 for (i = 0 ; i < len ; i++) { 474 buffer[i] = (*func)(offset++); 475 } 476} 477 478void mac_pram_write(int offset, __u8 *buffer, int len) 479{ 480 void (*func)(int, __u8); 481 int i; 482 483 switch(macintosh_config->adb_type) { 484 case MAC_ADB_IISI: 485 func = maciisi_write_pram; break; 486 case MAC_ADB_PB1: 487 case MAC_ADB_PB2: 488 func = pmu_write_pram; break; 489 case MAC_ADB_CUDA: 490 func = cuda_write_pram; break; 491 default: 492 func = via_write_pram; 493 } 494 if (!func) 495 return; 496 for (i = 0 ; i < len ; i++) { 497 (*func)(offset++, buffer[i]); 498 } 499} 500 501void mac_poweroff(void) 502{ 503 /* 504 * MAC_ADB_IISI may need to be moved up here if it doesn't actually 505 * work using the ADB packet method. --David Kilzer 506 */ 507 508 if (oss_present) { 509 oss_shutdown(); 510 } else if (macintosh_config->adb_type == MAC_ADB_II) { 511 via_shutdown(); 512#ifdef CONFIG_ADB_CUDA 513 } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { 514 cuda_shutdown(); 515#endif 516#ifdef CONFIG_ADB_PMU68K 517 } else if (macintosh_config->adb_type == MAC_ADB_PB1 518 || macintosh_config->adb_type == MAC_ADB_PB2) { 519 pmu_shutdown(); 520#endif 521 } 522 local_irq_enable(); 523 printk("It is now safe to turn off your Macintosh.\n"); 524 while(1); 525} 526 527void mac_reset(void) 528{ 529 if (macintosh_config->adb_type == MAC_ADB_II) { 530 unsigned long flags; 531 532 /* need ROMBASE in booter */ 533 /* indeed, plus need to MAP THE ROM !! */ 534 535 if (mac_bi_data.rombase == 0) 536 mac_bi_data.rombase = 0x40800000; 537 538 /* works on some */ 539 rom_reset = (void *) (mac_bi_data.rombase + 0xa); 540 541 if (macintosh_config->ident == MAC_MODEL_SE30) { 542 /* 543 * MSch: Machines known to crash on ROM reset ... 544 */ 545 } else { 546 local_irq_save(flags); 547 548 rom_reset(); 549 550 local_irq_restore(flags); 551 } 552#ifdef CONFIG_ADB_CUDA 553 } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { 554 cuda_restart(); 555#endif 556#ifdef CONFIG_ADB_PMU68K 557 } else if (macintosh_config->adb_type == MAC_ADB_PB1 558 || macintosh_config->adb_type == MAC_ADB_PB2) { 559 pmu_restart(); 560#endif 561 } else if (CPU_IS_030) { 562 563 /* 030-specific reset routine. The idea is general, but the 564 * specific registers to reset are '030-specific. Until I 565 * have a non-030 machine, I can't test anything else. 566 * -- C. Scott Ananian <cananian@alumni.princeton.edu> 567 */ 568 569 unsigned long rombase = 0x40000000; 570 571 /* make a 1-to-1 mapping, using the transparent tran. reg. */ 572 unsigned long virt = (unsigned long) mac_reset; 573 unsigned long phys = virt_to_phys(mac_reset); 574 unsigned long addr = (phys&0xFF000000)|0x8777; 575 unsigned long offset = phys-virt; 576 local_irq_disable(); /* lets not screw this up, ok? */ 577 __asm__ __volatile__(".chip 68030\n\t" 578 "pmove %0,%/tt0\n\t" 579 ".chip 68k" 580 : : "m" (addr)); 581 /* Now jump to physical address so we can disable MMU */ 582 __asm__ __volatile__( 583 ".chip 68030\n\t" 584 "lea %/pc@(1f),%/a0\n\t" 585 "addl %0,%/a0\n\t"/* fixup target address and stack ptr */ 586 "addl %0,%/sp\n\t" 587 "pflusha\n\t" 588 "jmp %/a0@\n\t" /* jump into physical memory */ 589 "0:.long 0\n\t" /* a constant zero. */ 590 /* OK. Now reset everything and jump to reset vector. */ 591 "1:\n\t" 592 "lea %/pc@(0b),%/a0\n\t" 593 "pmove %/a0@, %/tc\n\t" /* disable mmu */ 594 "pmove %/a0@, %/tt0\n\t" /* disable tt0 */ 595 "pmove %/a0@, %/tt1\n\t" /* disable tt1 */ 596 "movel #0, %/a0\n\t" 597 "movec %/a0, %/vbr\n\t" /* clear vector base register */ 598 "movec %/a0, %/cacr\n\t" /* disable caches */ 599 "movel #0x0808,%/a0\n\t" 600 "movec %/a0, %/cacr\n\t" /* flush i&d caches */ 601 "movew #0x2700,%/sr\n\t" /* set up status register */ 602 "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */ 603 "movec %/a0, %/isp\n\t" 604 "movel %1@(0x4),%/a0\n\t" /* load reset vector */ 605 "reset\n\t" /* reset external devices */ 606 "jmp %/a0@\n\t" /* jump to the reset vector */ 607 ".chip 68k" 608 : : "r" (offset), "a" (rombase) : "a0"); 609 } 610 611 /* should never get here */ 612 local_irq_enable(); 613 printk ("Restart failed. Please restart manually.\n"); 614 while(1); 615} 616 617/* 618 * This function translates seconds since 1970 into a proper date. 619 * 620 * Algorithm cribbed from glibc2.1, __offtime(). 621 */ 622#define SECS_PER_MINUTE (60) 623#define SECS_PER_HOUR (SECS_PER_MINUTE * 60) 624#define SECS_PER_DAY (SECS_PER_HOUR * 24) 625 626static void unmktime(unsigned long time, long offset, 627 int *yearp, int *monp, int *dayp, 628 int *hourp, int *minp, int *secp) 629{ 630 /* How many days come before each month (0-12). */ 631 static const unsigned short int __mon_yday[2][13] = 632 { 633 /* Normal years. */ 634 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 635 /* Leap years. */ 636 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 637 }; 638 long int days, rem, y, wday, yday; 639 const unsigned short int *ip; 640 641 days = time / SECS_PER_DAY; 642 rem = time % SECS_PER_DAY; 643 rem += offset; 644 while (rem < 0) { 645 rem += SECS_PER_DAY; 646 --days; 647 } 648 while (rem >= SECS_PER_DAY) { 649 rem -= SECS_PER_DAY; 650 ++days; 651 } 652 *hourp = rem / SECS_PER_HOUR; 653 rem %= SECS_PER_HOUR; 654 *minp = rem / SECS_PER_MINUTE; 655 *secp = rem % SECS_PER_MINUTE; 656 /* January 1, 1970 was a Thursday. */ 657 wday = (4 + days) % 7; /* Day in the week. Not currently used */ 658 if (wday < 0) wday += 7; 659 y = 1970; 660 661#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) 662#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) 663#define __isleap(year) \ 664 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) 665 666 while (days < 0 || days >= (__isleap (y) ? 366 : 365)) 667 { 668 /* Guess a corrected year, assuming 365 days per year. */ 669 long int yg = y + days / 365 - (days % 365 < 0); 670 671 /* Adjust DAYS and Y to match the guessed year. */ 672 days -= ((yg - y) * 365 673 + LEAPS_THRU_END_OF (yg - 1) 674 - LEAPS_THRU_END_OF (y - 1)); 675 y = yg; 676 } 677 *yearp = y - 1900; 678 yday = days; /* day in the year. Not currently used. */ 679 ip = __mon_yday[__isleap(y)]; 680 for (y = 11; days < (long int) ip[y]; --y) 681 continue; 682 days -= ip[y]; 683 *monp = y; 684 *dayp = days + 1; /* day in the month */ 685 return; 686} 687 688/* 689 * Read/write the hardware clock. 690 */ 691 692int mac_hwclk(int op, struct rtc_time *t) 693{ 694 unsigned long now; 695 696 if (!op) { /* read */ 697 switch (macintosh_config->adb_type) { 698 case MAC_ADB_II: 699 case MAC_ADB_IOP: 700 now = via_read_time(); 701 break; 702 case MAC_ADB_IISI: 703 now = maciisi_read_time(); 704 break; 705 case MAC_ADB_PB1: 706 case MAC_ADB_PB2: 707 now = pmu_read_time(); 708 break; 709 case MAC_ADB_CUDA: 710 now = cuda_read_time(); 711 break; 712 default: 713 now = 0; 714 } 715 716 t->tm_wday = 0; 717 unmktime(now, 0, 718 &t->tm_year, &t->tm_mon, &t->tm_mday, 719 &t->tm_hour, &t->tm_min, &t->tm_sec); 720 printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n", 721 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); 722 } else { /* write */ 723 printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n", 724 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); 725 726#if 0 /* it trashes my rtc */ 727 now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 728 t->tm_hour, t->tm_min, t->tm_sec); 729 730 switch (macintosh_config->adb_type) { 731 case MAC_ADB_II: 732 case MAC_ADB_IOP: 733 via_write_time(now); 734 break; 735 case MAC_ADB_CUDA: 736 cuda_write_time(now); 737 break; 738 case MAC_ADB_PB1: 739 case MAC_ADB_PB2: 740 pmu_write_time(now); 741 break; 742 case MAC_ADB_IISI: 743 maciisi_write_time(now); 744 } 745#endif 746 } 747 return 0; 748} 749 750/* 751 * Set minutes/seconds in the hardware clock 752 */ 753 754int mac_set_clock_mmss (unsigned long nowtime) 755{ 756 struct rtc_time now; 757 758 mac_hwclk(0, &now); 759 now.tm_sec = nowtime % 60; 760 now.tm_min = (nowtime / 60) % 60; 761 mac_hwclk(1, &now); 762 763 return 0; 764}