linux/arch/m68k/mac/misc.c
<<
>>
Prefs
   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}
 765