📄 config.c
字号:
* SCSI code. We'll have to take a look at this later */ request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL); /* start timer */ ciab.cra |= 0x11;}#define TICK_SIZE 10000/* This is always executed with interrupts disabled. */static unsigned long amiga_gettimeoffset (void){ unsigned short hi, lo, hi2; unsigned long ticks, offset = 0; /* read CIA B timer A current value */ hi = ciab.tahi; lo = ciab.talo; hi2 = ciab.tahi; if (hi != hi2) { lo = ciab.talo; hi = hi2; } ticks = hi << 8 | lo; if (ticks > jiffy_ticks / 2) /* check for pending interrupt */ if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA) offset = 10000; ticks = jiffy_ticks - ticks; ticks = (10000 * ticks) / jiffy_ticks; return ticks + offset;}static void a3000_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp){ volatile struct tod3000 *tod = TOD_3000; tod->cntrl1 = TOD3000_CNTRL1_HOLD; *secp = tod->second1 * 10 + tod->second2; *minp = tod->minute1 * 10 + tod->minute2; *hourp = tod->hour1 * 10 + tod->hour2; *dayp = tod->day1 * 10 + tod->day2; *monp = tod->month1 * 10 + tod->month2; *yearp = tod->year1 * 10 + tod->year2; tod->cntrl1 = TOD3000_CNTRL1_FREE;}static void a2000_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp){ volatile struct tod2000 *tod = TOD_2000; tod->cntrl1 = TOD2000_CNTRL1_HOLD; while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) ; *secp = tod->second1 * 10 + tod->second2; *minp = tod->minute1 * 10 + tod->minute2; *hourp = (tod->hour1 & 3) * 10 + tod->hour2; *dayp = tod->day1 * 10 + tod->day2; *monp = tod->month1 * 10 + tod->month2; *yearp = tod->year1 * 10 + tod->year2; if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){ if (!(tod->hour1 & TOD2000_HOUR1_PM) && *hourp == 12) *hourp = 0; else if ((tod->hour1 & TOD2000_HOUR1_PM) && *hourp != 12) *hourp += 12; } tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;}static int amiga_hwclk(int op, struct hwclk_time *t){ if (AMIGAHW_PRESENT(A3000_CLK)) { volatile struct tod3000 *tod = TOD_3000; tod->cntrl1 = TOD3000_CNTRL1_HOLD; if (!op) { /* read */ t->sec = tod->second1 * 10 + tod->second2; t->min = tod->minute1 * 10 + tod->minute2; t->hour = tod->hour1 * 10 + tod->hour2; t->day = tod->day1 * 10 + tod->day2; t->wday = tod->weekday; t->mon = tod->month1 * 10 + tod->month2 - 1; t->year = tod->year1 * 10 + tod->year2; if (t->year <= 69) t->year += 100; } else { tod->second1 = t->sec / 10; tod->second2 = t->sec % 10; tod->minute1 = t->min / 10; tod->minute2 = t->min % 10; tod->hour1 = t->hour / 10; tod->hour2 = t->hour % 10; tod->day1 = t->day / 10; tod->day2 = t->day % 10; if (t->wday != -1) tod->weekday = t->wday; tod->month1 = (t->mon + 1) / 10; tod->month2 = (t->mon + 1) % 10; if (t->year >= 100) t->year -= 100; tod->year1 = t->year / 10; tod->year2 = t->year % 10; } tod->cntrl1 = TOD3000_CNTRL1_FREE; } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { volatile struct tod2000 *tod = TOD_2000; tod->cntrl1 = TOD2000_CNTRL1_HOLD; while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) ; if (!op) { /* read */ t->sec = tod->second1 * 10 + tod->second2; t->min = tod->minute1 * 10 + tod->minute2; t->hour = (tod->hour1 & 3) * 10 + tod->hour2; t->day = tod->day1 * 10 + tod->day2; t->wday = tod->weekday; t->mon = tod->month1 * 10 + tod->month2 - 1; t->year = tod->year1 * 10 + tod->year2; if (t->year <= 69) t->year += 100; if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){ if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12) t->hour = 0; else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->hour != 12) t->hour += 12; } } else { tod->second1 = t->sec / 10; tod->second2 = t->sec % 10; tod->minute1 = t->min / 10; tod->minute2 = t->min % 10; if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE) tod->hour1 = t->hour / 10; else if (t->hour >= 12) tod->hour1 = TOD2000_HOUR1_PM + (t->hour - 12) / 10; else tod->hour1 = t->hour / 10; tod->hour2 = t->hour % 10; tod->day1 = t->day / 10; tod->day2 = t->day % 10; if (t->wday != -1) tod->weekday = t->wday; tod->month1 = (t->mon + 1) / 10; tod->month2 = (t->mon + 1) % 10; if (t->year >= 100) t->year -= 100; tod->year1 = t->year / 10; tod->year2 = t->year % 10; } tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; } return 0;}static int amiga_set_clock_mmss (unsigned long nowtime){ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; if (AMIGAHW_PRESENT(A3000_CLK)) { volatile struct tod3000 *tod = TOD_3000; tod->cntrl1 = TOD3000_CNTRL1_HOLD; tod->second1 = real_seconds / 10; tod->second2 = real_seconds % 10; tod->minute1 = real_minutes / 10; tod->minute2 = real_minutes % 10; tod->cntrl1 = TOD3000_CNTRL1_FREE; } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { volatile struct tod2000 *tod = TOD_2000; tod->cntrl1 = TOD2000_CNTRL1_HOLD; while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) ; tod->second1 = real_seconds / 10; tod->second2 = real_seconds % 10; tod->minute1 = real_minutes / 10; tod->minute2 = real_minutes % 10; tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; } return 0;}static int amiga_wait_key (struct console *co){ int i; while (1) { while (ciaa.pra & 0x40); /* debounce */ for (i = 0; i < 1000; i++); if (!(ciaa.pra & 0x40)) break; } /* wait for button up */ while (1) { while (!(ciaa.pra & 0x40)); /* debounce */ for (i = 0; i < 1000; i++); if (ciaa.pra & 0x40) break; } return 0;}void dbprintf(const char *fmt , ...){ static char buf[1024]; va_list args; extern void console_print (const char *str); extern int vsprintf(char * buf, const char * fmt, va_list args); va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); console_print (buf);}static NORET_TYPE void amiga_reset( void ) ATTRIB_NORET;static void amiga_reset (void){ unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040); unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label); cli(); if (CPU_IS_040_OR_060) /* Setup transparent translation registers for mapping * of 16 MB kernel segment before disabling translation */ __asm__ __volatile__ ("movel %0,%/d0\n\t" "andl #0xff000000,%/d0\n\t" "orw #0xe020,%/d0\n\t" /* map 16 MB, enable, cacheable */ ".chip 68040\n\t" "movec %%d0,%%itt0\n\t" "movec %%d0,%%dtt0\n\t" ".chip 68k\n\t" "jmp %0@\n\t" : /* no outputs */ : "a" (jmp_addr040)); else /* for 680[23]0, just disable translation and jump to the physical * address of the label */ __asm__ __volatile__ ("pmove %/tc,%@\n\t" "bclr #7,%@\n\t" "pmove %@,%/tc\n\t" "jmp %0@\n\t" : /* no outputs */ : "a" (jmp_addr)); jmp_addr_label040: /* disable translation on '040 now */ __asm__ __volatile__ ("moveq #0,%/d0\n\t" ".chip 68040\n\t" "movec %%d0,%%tc\n\t" /* disable MMU */ ".chip 68k\n\t" : /* no outputs */ : /* no inputs */ : "d0"); jmp_addr_label: /* pickup reset address from AmigaOS ROM, reset devices and jump * to reset address */ __asm__ __volatile__ ("movew #0x2700,%/sr\n\t" "leal 0x01000000,%/a0\n\t" "subl %/a0@(-0x14),%/a0\n\t" "movel %/a0@(4),%/a0\n\t" "subql #2,%/a0\n\t" "bra 1f\n\t" /* align on a longword boundary */ __ALIGN_STR "\n" "1:\n\t" "reset\n\t" "jmp %/a0@" : /* Just that gcc scans it for % escapes */ ); for (;;);} /* * Debugging */#define SAVEKMSG_MAXMEM 128*1024#define SAVEKMSG_MAGIC1 0x53415645 /* 'SAVE' */#define SAVEKMSG_MAGIC2 0x4B4D5347 /* 'KMSG' */struct savekmsg { unsigned long magic1; /* SAVEKMSG_MAGIC1 */ unsigned long magic2; /* SAVEKMSG_MAGIC2 */ unsigned long magicptr; /* address of magic1 */ unsigned long size; char data[0];};static struct savekmsg *savekmsg = NULL;static void amiga_mem_console_write(struct console *co, const char *s, unsigned int count){ if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) { memcpy(savekmsg->data+savekmsg->size, s, count); savekmsg->size += count; }}static void amiga_savekmsg_init(void){ static struct resource debug_res = { "Debug" }; savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; savekmsg->magicptr = virt_to_phys(savekmsg); savekmsg->size = 0;}static void amiga_serial_putc(char c){ custom.serdat = (unsigned char)c | 0x100; while (!(custom.serdatr & 0x2000)) ;}void amiga_serial_console_write(struct console *co, const char *s, unsigned int count){ while (count--) { if (*s == '\n') amiga_serial_putc('\r'); amiga_serial_putc(*s++); }}#ifdef CONFIG_SERIAL_CONSOLEvoid amiga_serial_puts(const char *s){ amiga_serial_console_write(NULL, s, strlen(s));}int amiga_serial_console_wait_key(struct console *co){ int ch; while (!(custom.intreqr & IF_RBF)) barrier(); ch = custom.serdatr & 0xff; /* clear the interrupt, so that another character can be read */ custom.intreq = IF_RBF; return ch;}void amiga_serial_gets(struct console *co, char *s, int len){ int ch, cnt = 0; while (1) { ch = amiga_serial_console_wait_key(co); /* Check for backspace. */ if (ch == 8 || ch == 127) { if (cnt == 0) { amiga_serial_putc('\007'); continue; } cnt--; amiga_serial_puts("\010 \010"); continue; } /* Check for enter. */ if (ch == 10 || ch == 13) break; /* See if line is too long. */ if (cnt >= len + 1) { amiga_serial_putc(7); cnt--; continue; } /* Store and echo character. */ s[cnt++] = ch; amiga_serial_putc(ch); } /* Print enter. */ amiga_serial_puts("\r\n"); s[cnt] = 0;}#endifstatic void __init amiga_debug_init(void){ if (!strcmp( m68k_debug_device, "ser" )) { /* no initialization required (?) */ amiga_console_driver.write = amiga_serial_console_write; register_console(&amiga_console_driver); }}#ifdef CONFIG_HEARTBEATstatic void amiga_heartbeat(int on){ if (on) ciaa.pra &= ~2; else ciaa.pra |= 2;}#endif /* * Amiga specific parts of /proc */static void amiga_get_model(char *model){ strcpy(model, amiga_model_name);}static int amiga_get_hardware_list(char *buffer){ int len = 0; if (AMIGAHW_PRESENT(CHIP_RAM)) len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10); len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n", amiga_psfreq, amiga_eclock); if (AMIGAHW_PRESENT(AMI_VIDEO)) { char *type; switch(amiga_chipset) { case CS_OCS: type = "OCS"; break; case CS_ECS: type = "ECS"; break; case CS_AGA: type = "AGA"; break; default: type = "Old or Unknown"; break; } len += sprintf(buffer+len, "Graphics:\t%s\n", type); }#define AMIGAHW_ANNOUNCE(name, str) \ if (AMIGAHW_PRESENT(name)) \ len += sprintf (buffer+len, "\t%s\n", str) len += sprintf (buffer + len, "Detected hardware:\n"); AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video"); AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter"); AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer"); AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio"); AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller"); AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)"); AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)"); AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)"); AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)"); AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive"); AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard"); AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port"); AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port"); AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port"); AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)"); AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)"); AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM"); AMIGAHW_ANNOUNCE(PAULA, "Paula 8364"); AMIGAHW_ANNOUNCE(DENISE, "Denise 8362"); AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373"); AMIGAHW_ANNOUNCE(LISA, "Lisa 8375"); AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371"); AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370"); AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372"); AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372"); AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374"); AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374"); AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick"); AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");#ifdef CONFIG_ZORRO if (AMIGAHW_PRESENT(ZORRO)) len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion " "Device%s\n", AMIGAHW_PRESENT(ZORRO3) ? "I" : "", zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");#endif /* CONFIG_ZORRO */#undef AMIGAHW_ANNOUNCE return(len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -