static void vga_recalc_vertical(void) { unsigned int font_size, rows; u16 crtc; u8 pt, ov; set_fs(0); font_size = rdfs8(0x485); rows = force_y ? force_y : rdfs8(0x484)+1; rows *= font_size; rows--; crtc = vga_crtc(); pt = in_idx(crtc, 0x11); pt &= ~0x80; out_idx(pt, crtc, 0x11); out_idx((u8)rows, crtc, 0x12); ov = in_idx(crtc, 0x07); ov &= 0xbd; ov |= (rows >> (8-1)) & 0x02; ov |= (rows >> (9-6)) & 0x40; out_idx(ov, crtc, 0x07); }
/* * Recalculate the vertical video cutoff (hack!) */ static void vga_recalc_vertical(void) { unsigned int font_size, rows; u16 crtc; u8 pt, ov; set_fs(0); font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */ rows *= font_size; /* Visible scan lines */ rows--; /* ... minus one */ crtc = vga_crtc(); pt = in_idx(crtc, 0x11); pt &= ~0x80; /* Unlock CR0-7 */ out_idx(pt, crtc, 0x11); out_idx((u8)rows, crtc, 0x12); /* Lower height register */ ov = in_idx(crtc, 0x07); /* Overflow register */ ov &= 0xbd; ov |= (rows >> (8-1)) & 0x02; ov |= (rows >> (9-6)) & 0x40; out_idx(ov, crtc, 0x07); }
/** @brief */ static void vga_recalc_vertical(void) { unsigned int font_size, rows; u16 crtc; u8 pt, ov; /* 0x485 : Point Height of Size (2Byte) 0x484 : Rows on the screen (2Byte) */ set_fs(0); font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */ rows *= font_size; /* Visible scan lines */ rows--; /* ... minus one */ crtc = vga_crtc(); /* CPU 에서 장치에 접근하는 방법은 Index Register Address, Data Register Address 을 이용하여 접근한다. Index Register Address 에는 장치에서 관리하는 Register 중, 몇 번째 Register 에 접근할지 에 대한 정보(Index)가 입력되며, 1 Byte 의 크기(0 ~ 255) 까지의 값이 할당가능하다. Data Register 에는 지정된 Index 번째에 해당하는 데이터가 입력된다. Index Register Address 와 Data Register Address 는 항상 쌍으로 구성되며, Index Register Address + 1 의 주소가 Data Register Address 가 된다 */ pt = in_idx(crtc, 0x11); pt &= ~0x80; /* Unlock CR0-7 */ // 최상위 비트를 끈다. out_idx(pt, crtc, 0x11); // 쓰기가능하게 해준다. // 11h R- native VGA with bit7=1 in end horizontal blanking (03h): // end vertical retrace // 11h -W end vertical retrace // bit7 : VGA: protection bit // =0 enable write access to 00h-07h // =1 read only regs 00h-07h with the exception // of bit4 in 07h. ET4000: protect 35h also. // rows의 아래 8비트를 먼저 써주고 8번 9번 비트를 위치에 맞게 OR해 넣는다. out_idx((u8)rows, crtc, 0x12); /* Lower height register */ ov = in_idx(crtc, 0x07); /* Overflow register */ ov &= 0xbd; // 1011 1101 ov |= (rows >> (8-1)) & 0x02; // bit 8 of vertical display end ov |= (rows >> (9-6)) & 0x40; // bit 9 of " out_idx(ov, crtc, 0x07); }
int cmdline_find_option_bool(const char *option) { u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr; addr_t cptr; char c; int pos = 0, wstart = 0; const char *opptr = NULL; enum { st_wordstart, st_wordcmp, st_wordskip, } state = st_wordstart; if (!cmdline_ptr || cmdline_ptr >= 0x100000) return -1; cptr = cmdline_ptr & 0xf; set_fs(cmdline_ptr >> 4); while (cptr < 0x10000) { c = rdfs8(cptr++); pos++; switch (state) { case st_wordstart: if (!c) return 0; else if (myisspace(c)) break; state = st_wordcmp; opptr = option; wstart = pos; case st_wordcmp: if (!*opptr) if (!c || myisspace(c)) return wstart; else state = st_wordskip; else if (!c) return 0; else if (c != *opptr++) state = st_wordskip; break; case st_wordskip: if (!c) return 0; else if (myisspace(c)) state = st_wordstart; break; } } return 0; }
/* * Find a boolean option (like quiet,noapic,nosmp....) * * Returns the position of that option (starts counting with 1) * or 0 on not found */ int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option) { addr_t cptr; char c; int pos = 0, wstart = 0; const char *opptr = NULL; enum { st_wordstart, /* Start of word/after whitespace */ st_wordcmp, /* Comparing this word */ st_wordskip, /* Miscompare, skip */ } state = st_wordstart; if (!cmdline_ptr || cmdline_ptr >= 0x100000) return -1; /* No command line, or inaccessible */ cptr = cmdline_ptr & 0xf; set_fs(cmdline_ptr >> 4); while (cptr < 0x10000) { c = rdfs8(cptr++); pos++; switch (state) { case st_wordstart: if (!c) return 0; else if (myisspace(c)) break; state = st_wordcmp; opptr = option; wstart = pos; /* fall through */ case st_wordcmp: if (!*opptr) if (!c || myisspace(c)) return wstart; else state = st_wordskip; else if (!c) return 0; else if (c != *opptr++) state = st_wordskip; break; case st_wordskip: if (!c) return 0; else if (myisspace(c)) state = st_wordstart; break; } } return 0; /* Buffer overrun */ }
static int bios_probe(void) { u8 mode; #ifdef _WAKEUP u8 saved_mode = 0x03; #else u8 saved_mode = boot_params.screen_info.orig_video_mode; #endif u16 crtc; struct mode_info *mi; int nmodes = 0; if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA) return 0; set_fs(0); crtc = vga_crtc(); video_bios.modes = GET_HEAP(struct mode_info, 0); for (mode = 0x14; mode <= 0x7f; mode++) { if (!heap_free(sizeof(struct mode_info))) break; if (mode_defined(VIDEO_FIRST_BIOS+mode)) continue; if (set_bios_mode(mode)) continue; /* Try to verify that it's a text mode. */ /* Attribute Controller: make graphics controller disabled */ if (in_idx(0x3c0, 0x10) & 0x01) continue; /* Graphics Controller: verify Alpha addressing enabled */ if (in_idx(0x3ce, 0x06) & 0x01) continue; /* CRTC cursor location low should be zero(?) */ if (in_idx(crtc, 0x0f)) continue; mi = GET_HEAP(struct mode_info, 1); mi->mode = VIDEO_FIRST_BIOS+mode; mi->depth = 0; /* text */ mi->x = rdfs16(0x44a); mi->y = rdfs8(0x484)+1; nmodes++; } set_bios_mode(saved_mode); return nmodes; }
/* * Find a non-boolean option, that is, "option=argument". In accordance * with standard Linux practice, if this option is repeated, this returns * the last instance on the command line. * * Returns the length of the argument (regardless of if it was * truncated to fit in the buffer), or -1 on not found. */ int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize) { addr_t cptr; char c; int len = -1; const char *opptr = NULL; char *bufptr = buffer; enum { st_wordstart, /* Start of word/after whitespace */ st_wordcmp, /* Comparing this word */ st_wordskip, /* Miscompare, skip */ st_bufcpy /* Copying this to buffer */ } state = st_wordstart; if (!cmdline_ptr || cmdline_ptr >= 0x100000) return -1; /* No command line, or inaccessible */ cptr = cmdline_ptr & 0xf; set_fs(cmdline_ptr >> 4); while (cptr < 0x10000 && (c = rdfs8(cptr++))) { switch (state) { case st_wordstart: if (myisspace(c)) break; /* else */ state = st_wordcmp; opptr = option; /* fall through */ case st_wordcmp: if (c == '=' && !*opptr) { len = 0; bufptr = buffer; state = st_bufcpy; } else if (myisspace(c)) { state = st_wordstart; } else if (c != *opptr++) { state = st_wordskip; } break; case st_wordskip: if (myisspace(c)) state = st_wordstart; break; case st_bufcpy: if (myisspace(c)) { state = st_wordstart; } else { if (len < bufsize-1) *bufptr++ = c; len++; } break; } } if (bufsize) *bufptr = '\0'; return len; }
int cmdline_find_option(const char *option, char *buffer, int bufsize) { u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr; addr_t cptr; char c; int len = -1; const char *opptr = NULL; char *bufptr = buffer; enum { st_wordstart, st_wordcmp, st_wordskip, st_bufcpy } state = st_wordstart; if (!cmdline_ptr || cmdline_ptr >= 0x100000) return -1; cptr = cmdline_ptr & 0xf; set_fs(cmdline_ptr >> 4); while (cptr < 0x10000 && (c = rdfs8(cptr++))) { switch (state) { case st_wordstart: if (myisspace(c)) break; state = st_wordcmp; opptr = option; case st_wordcmp: if (c == '=' && !*opptr) { len = 0; bufptr = buffer; state = st_bufcpy; } else if (myisspace(c)) { state = st_wordstart; } else if (c != *opptr++) { state = st_wordskip; } break; case st_wordskip: if (myisspace(c)) state = st_wordstart; break; case st_bufcpy: if (myisspace(c)) { state = st_wordstart; } else { if (len < bufsize-1) *bufptr++ = c; len++; } break; } } if (bufsize) *bufptr = '\0'; return len; }
/* * Find a non-boolean option, that is, "option=argument". In accordance * with standard Linux practice, if this option is repeated, this returns * the last instance on the command line. * * Returns the length of the argument (regardless of if it was * truncated to fit in the buffer), or -1 on not found. */ int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize) { addr_t cptr; char c; int len = -1; const char *opptr = NULL; char *bufptr = buffer; enum { st_wordstart, /* Start of word/after whitespace */ st_wordcmp, /* Comparing this word */ st_wordskip, /* Miscompare, skip */ st_bufcpy /* Copying this to buffer */ } state = st_wordstart; if (!cmdline_ptr || cmdline_ptr >= 0x100000) // cmdline 포인터가 없거나 1M이상이면 에러 return -1; /* No command line, or inaccessible */ cptr = cmdline_ptr & 0xf; // cmdline_ptr의 오프셋 set_fs(cmdline_ptr >> 4); // cmdline_ptr의 세그먼트 값 // cmdline에서 옵션을 찾는다. while (cptr < 0x10000 && (c = rdfs8(cptr++))) { switch (state) { case st_wordstart: if (myisspace(c)) // 맨 처음 혹은 스페이스(<32)가 여러개 오면 break 해버린다. break; /* else */ state = st_wordcmp; // 구분자 후에 문자가 있으면 wordcmp로 상태 변환 opptr = option; // 찾을 옵션 /* fall through */ // 아래로 계속된다. case st_wordcmp: if (c == '=' && !*opptr) { len = 0; // 길이 리셋 bufptr = buffer; state = st_bufcpy; // 일치한다. bufcpy로 상태전환 } else if (myisspace(c)) { state = st_wordstart; // "="이 없다. 다시 비교 } else if (c != *opptr++) { state = st_wordskip; // 일치하지 않음 } break; // 문자가 일치한다. cmp 상태 그대로 다시 비교 case st_wordskip: // skip은 문자열이 일치하지 않은 상태 if (myisspace(c)) // 구분자가 오면 새로 비교 시작 state = st_wordstart; break; case st_bufcpy: if (myisspace(c)) { state = st_wordstart; // 구분자가 오기전까지 복사 } else { if (len < bufsize-1) *bufptr++ = c; // 버퍼 크기를 넘지 않으면 복사 len++; } break; } } if (bufsize) *bufptr = '\0'; // 버퍼 끝은 NUL return len; // 옵션 길이를 리턴. 일치하는게 없으면 -1 }