📄 misc.c
字号:
/* * Miscellaneous Mac68K-specific stuff */#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/miscdevice.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/time.h>#include <linux/mm.h>#include <linux/adb.h>#include <linux/cuda.h>#include <linux/pmu.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/rtc.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/setup.h>#include <asm/macintosh.h>#include <asm/mac_via.h>#include <asm/mac_oss.h>#define BOOTINFO_COMPAT_1_0#include <asm/bootinfo.h>#include <asm/machdep.h>/* Offset between Unix time (1970-based) and Mac time (1904-based) */#define RTC_OFFSET 2082844800extern struct mac_booter_data mac_bi_data;static void (*rom_reset)(void);/* * Return the current time as the number of seconds since January 1, 1904. */static long adb_read_time(void){ volatile struct adb_request req; long time; adb_request((struct adb_request *) &req, NULL, ADBREQ_RAW|ADBREQ_SYNC, 2, CUDA_PACKET, CUDA_GET_TIME); time = (req.reply[3] << 24) | (req.reply[4] << 16) | (req.reply[5] << 8) | req.reply[6]; return time - RTC_OFFSET;}/* * Set the current system time */static void adb_write_time(long data){ volatile struct adb_request req; data += RTC_OFFSET; adb_request((struct adb_request *) &req, NULL, ADBREQ_RAW|ADBREQ_SYNC, 6, CUDA_PACKET, CUDA_SET_TIME, (data >> 24) & 0xFF, (data >> 16) & 0xFF, (data >> 8) & 0xFF, data & 0xFF);}/* * Get a byte from the NVRAM */static __u8 adb_read_pram(int offset){ volatile struct adb_request req; adb_request((struct adb_request *) &req, NULL, ADBREQ_RAW|ADBREQ_SYNC, 4, CUDA_PACKET, CUDA_GET_PRAM, (offset >> 8) & 0xFF, offset & 0xFF); return req.reply[3];}/* * Write a byte to the NVRAM */static void adb_write_pram(int offset, __u8 data){ volatile struct adb_request req; adb_request((struct adb_request *) &req, NULL, ADBREQ_RAW|ADBREQ_SYNC, 5, CUDA_PACKET, CUDA_SET_PRAM, (offset >> 8) & 0xFF, offset & 0xFF, data);}/* * VIA PRAM/RTC access routines * * Must be called with interrupts disabled and * the RTC should be enabled. */static __u8 via_pram_readbyte(void){ int i,reg; __u8 data; reg = via1[vBufB] & ~VIA1B_vRTCClk; /* Set the RTC data line to be an input. */ via1[vDirB] &= ~VIA1B_vRTCData; /* The bits of the byte come out in MSB order */ data = 0; for (i = 0 ; i < 8 ; i++) { via1[vBufB] = reg; via1[vBufB] = reg | VIA1B_vRTCClk; data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData); } /* Return RTC data line to output state */ via1[vDirB] |= VIA1B_vRTCData; return data;}static void via_pram_writebyte(__u8 data){ int i,reg,bit; reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData); /* The bits of the byte go in in MSB order */ for (i = 0 ; i < 8 ; i++) { bit = data & 0x80? 1 : 0; data <<= 1; via1[vBufB] = reg | bit; via1[vBufB] = reg | bit | VIA1B_vRTCClk; }}/* * Execute a VIA PRAM/RTC command. For read commands * data should point to a one-byte buffer for the * resulting data. For write commands it should point * to the data byte to for the command. * * This function disables all interrupts while running. */static void via_pram_command(int command, __u8 *data){ unsigned long cpu_flags; int is_read; save_flags(cpu_flags); cli(); /* Enable the RTC and make sure the strobe line is high */ via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb; if (command & 0xFF00) { /* extended (two-byte) command */ via_pram_writebyte((command & 0xFF00) >> 8); via_pram_writebyte(command & 0xFF); is_read = command & 0x8000; } else { /* one-byte command */ via_pram_writebyte(command); is_read = command & 0x80; } if (is_read) { *data = via_pram_readbyte(); } else { via_pram_writebyte(*data); } /* All done, disable the RTC */ via1[vBufB] |= VIA1B_vRTCEnb; restore_flags(cpu_flags);}static __u8 via_read_pram(int offset){ return 0;}static void via_write_pram(int offset, __u8 data){}/* * Return the current time in seconds since January 1, 1904. * * This only works on machines with the VIA-based PRAM/RTC, which * is basically any machine with Mac II-style ADB. */static long via_read_time(void){ union { __u8 cdata[4]; long idata; } result, last_result; int ct; /* * The NetBSD guys say to loop until you get the same reading * twice in a row. */ ct = 0; do { if (++ct > 10) { printk("via_read_time: couldn't get valid time, " "last read = 0x%08X and 0x%08X\n", last_result.idata, result.idata); break; } last_result.idata = result.idata; result.idata = 0; via_pram_command(0x81, &result.cdata[3]); via_pram_command(0x85, &result.cdata[2]); via_pram_command(0x89, &result.cdata[1]); via_pram_command(0x8D, &result.cdata[0]); } while (result.idata != last_result.idata); return result.idata - RTC_OFFSET;}/* * Set the current time to a number of seconds since January 1, 1904. * * This only works on machines with the VIA-based PRAM/RTC, which * is basically any machine with Mac II-style ADB. */static void via_write_time(long time){ union { __u8 cdata[4]; long idata; } data; __u8 temp; /* Clear the write protect bit */ temp = 0x55; via_pram_command(0x35, &temp); data.idata = time + RTC_OFFSET; via_pram_command(0x01, &data.cdata[3]); via_pram_command(0x05, &data.cdata[2]); via_pram_command(0x09, &data.cdata[1]); via_pram_command(0x0D, &data.cdata[0]); /* Set the write protect bit */ temp = 0xD5; via_pram_command(0x35, &temp);}static void via_shutdown(void){ if (rbv_present) { via2[rBufB] &= ~0x04; } else { /* Direction of vDirB is output */ via2[vDirB] |= 0x04; /* Send a value of 0 on that line */ via2[vBufB] &= ~0x04; mdelay(1000); }}/* * FIXME: not sure how this is supposed to work exactly... */static void oss_shutdown(void){ oss->rom_ctrl = OSS_POWEROFF;}#ifdef CONFIG_ADB_CUDAstatic void cuda_restart(void){ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, 2, CUDA_PACKET, CUDA_RESET_SYSTEM);}static void cuda_shutdown(void){ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, 2, CUDA_PACKET, CUDA_POWERDOWN);}#endif /* CONFIG_ADB_CUDA */#ifdef CONFIG_ADB_PMUvoid pmu_restart(void){ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, 3, PMU_PACKET, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK); adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC, 2, PMU_PACKET, PMU_RESET);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -