int serial_getc (void) { #if 0 uint8 c; for (;;) { uint8 x = in_byte (0x3FD); if (x & 0x01) break; if (x & 0x0C) out_byte (0x3fd, 0x0c); } c = in_byte (0x3F8); return c; #else while ((in_byte (0x3FD) & 0x01) == 0) { if (console_changed != 0) { console_changed = 0; return 0; } } return in_byte (0x3F8); #endif }
/* * Get ethernet address and compute checksum to be sure * that there is a board at this address. */ int eth_init() { uint16 checksum, sum; register int i; for (i = 0; i < 6; i++) eth_myaddr[i] = in_byte(NE_BASEREG + i); sum = 0; for (i = 0x00; i <= 0x0B; i++) sum += in_byte(NE_BASEREG + i); for (i = 0x0E; i <= 0xF; i++) sum += in_byte(NE_BASEREG + i); checksum = in_byte(NE_BASEREG + 0x0C) | (in_byte(NE_BASEREG + 0x0D) << 8); if (sum != checksum) return 0; /* initblock, tmd, and rmd should be 8 byte aligned ! */ initblock = (initblock_t *) aalloc(sizeof(initblock_t), 8); tmd = (tmde_t *) aalloc(sizeof(tmde_t), 8); rmd = (rmde_t *) aalloc(NRCVRING * sizeof(rmde_t), 8); eth_reset(); return 1; }
/************************************************************************ kbhandler() is the kbd interrupt handler. PC's kbd generates 2 interrupts for each key typed; one when the key is pressed and another one when the key is released. Each key generates a scan code. The scan code of a key release is 0x80 + the scan code of key pressed. When the kbd interrupts, the scan code is in the data port (0x60) of the KBD interface. First, read the scan code from the data port. Then ack the key input by strobing its PORT_B at 0x61. Some special keys generate ESC key sequences,e.g. arrow keys. Then process the scan code: 1. Ignore key releases, thus no special keys, such as shift. For normal keys: translate into LOWER CASE ASCII char. 2. Raise the kbdata flag, allowing a busy waiting process to get the key ************************* Lower half driver ******************************/ int kbhandler() { int scode, value, c; /* Fetch the character from the keyboard hardware and acknowledge it. */ scode = in_byte(KEYBD);/* get the scan code of the key struck */ value = in_byte(PORT_B);/* strobe the keyboard to ack the char */ out_byte(PORT_B, value | KBIT);/* first, strobe the bit high */ out_byte(PORT_B, value); /* then strobe it low */ printf("kb interrupt %x\n", scode); // should see the scand code if (scode & 0x80) // ignore key release goto out; kbc = unshift[scode]; // translate scan code into ASCII char if(data != 128){ buf[head] = kbc; head ++; head %= 128; data ++; kwakeup(&buf); }else{ printf("kbderr"); } out: out_byte(0x20, 0x20); }
unsigned ide_read(int deviceIndex, unsigned port) { if (port == ATA_REG_ALTSTATUS) return in_byte(devices[deviceIndex].controlPort); else return in_byte(devices[deviceIndex].base + port); }
int enable_irq(u8 irq_nr) { lock(); if (irq_nr < 8) out_byte(INT_MASK, in_byte(INT_MASK) & ~(1 << irq_nr)); else out_byte(INT2_MASK,in_byte(INT2_MASK) & ~(1 << (irq_nr - 8))); unlock(); }
void Disable_IRQ(int irq) //关闭中断引脚 { if(irq<0||irq>15) return ; if(irq>=8) // slave out_byte(0xA1,(0x1<<(irq-8))|in_byte(0xA1)); else // master out_byte(0x21,(0x1<<irq)|in_byte(0x21)); }
void Enable_IRQ(int irq) //开启中断引脚 { if(irq<0||irq>15) return ; if(irq>=8) // slave out_byte(0xA1,(~(0x1<<(irq-8)))&in_byte(0xA1)); else // master out_byte(0x21,(~(0x1<<irq))&in_byte(0x21)); }
void serial_putc (const char sendme) { if (sendme == '\n') { while ((in_byte (0x3FD) & 0x40) == 0); out_byte (0x3f8, 0x0D); } while ((in_byte (0x3FD) & 0x40) == 0); out_byte (0x3f8, sendme); }
int hd_error() // test for error { int r; if (in_byte(0x1F7) & 0x01){ // status.ERROR bit on r = in_byte(0x1F1); // read error register printf("HD error=%x\n", r); return r; } return 0; // return 0 for OK }
/* Print the palette in use. */ void read_palette() { int i; uint8_t r,g,b; out_byte(VGA_DAC_READ_INDEX, 0); for(i = 0; i < NR_PALETTE_ENTRY; i ++) { r = in_byte(VGA_DAC_DATA); g = in_byte(VGA_DAC_DATA); b = in_byte(VGA_DAC_DATA); printk("r = %x, g = %x, b = %x\n", r, g, b); } }
/* TrapFrame的定义在include/x86/memory.h * 请仔细理解这段程序的含义,这些内容将在后续的实验中被反复使用。 */ void irq_handle(struct TrapFrame *tf) { if (tf->irq == 1000) { do_timer(); } else if (tf->irq == 1001) { uint32_t code = in_byte(0x60); uint32_t val = in_byte(0x61); out_byte(0x61, val | 0x80); out_byte(0x61, val); do_keyboard(code); } }
//等待 8042 的输入缓冲区空 PRIVATE void kb_wait() { u8 kb_stat; do{ kb_stat = in_byte(KB_CMD); }while(kb_stat & 0x02); }
char get_char() { uint8_t buf_head = in_byte(BUF_HEAD_PORT); uint8_t buf_tail = in_byte(BUF_TAIL_PORT); while(buf_head == buf_tail) { buf_tail = in_byte(BUF_TAIL_PORT); buf_head = in_byte(BUF_HEAD_PORT); } // get the first character char c = in_byte(KEYBOARD_PORT_BASE + buf_head); out_byte(VMEM_DATA_PORT_BASE, c); return c; }
PRIVATE void kb_ack() { u8 kb_read; do{ kb_read = in_byte(KB_DATA); }while(kb_read != KB_ACK); }
/* RING<0> This is the keyboard interrupt handler */ PUBLIC void key_interrupt() { /*get scan code from 8042,and append it in the buffer.*/ t_8 value; value=in_byte(0x60); add_tail(kb_input,value); }
void via_calibrate_bus_freq(void) { DECLARE_GLOBAL_DATA_PTR; unsigned long tb; /* This is 20 microseconds */ #define CALIBRATE_TIME 28636 /* Enable the timer (and disable speaker) */ unsigned char c; c = in_byte(0x61); out_byte(0x61, ((c & ~0x02) | 0x01)); /* Set timer 2 to low/high writing */ out_byte(0x43, 0xb0); out_byte(0x42, CALIBRATE_TIME & 0xff); out_byte(0x42, CALIBRATE_TIME >>8); /* Read the time base */ tb = via_calibrate_time_base(); if (tb >= 700000) gd->bus_clk = 133333333; else gd->bus_clk = 100000000; }
PUBLIC void keyboard_handler(int irq) { u8 scan_code = in_byte(KB_DATA); // disp_int(scan_code); // disp_str(" "); VirtualKey key = '\0'; bool make = !(scan_code & FLAG_BREAK); bool two_byte_code = FALSE; //若扫描码为0xe0则则直接插入缓冲区,然后返回 if(scan_code == 0xe0){ insert_kbuf(scan_code); return; } //先得到virtualkey if(keymap[(scan_code & 0x7f) * MAP_COLS + 2] == 0) { key = keymap[(scan_code & 0x7f) * MAP_COLS]; } else{ if(get_head_pre() == 0xe0){ key = keymap[(scan_code & 0x7f) * MAP_COLS + 2]; two_byte_code = TRUE; } else key = keymap[(scan_code & 0x7f) * MAP_COLS]; } //只有普通键(非装饰键)的扫描码装入vk缓冲区 if(make && !is_decorative_key(key)){ insert_vkbuf(key); } if(two_byte_code) insert_kbuf_revocation(); //若为装饰键则要修改状态 int i = 0; for(i = 0; i < NUM_DECORATIVE_KEY; i++){ if(key == decorativeKey[i]){ if(make) *(decorativeKeyStatus[i]) = VKEY_STATE_PRESSED; else *(decorativeKeyStatus[i]) = VKEY_STATE_RELEASED; } } kernelUnBlock(readKeyBlockEip); // u8 scan_code = in_byte(KB_DATA); // // if (kb_in.count < KB_IN_BYTES) { // *(kb_in.p_head) = scan_code; // kb_in.p_head++; // if(kb_in.p_head == kb_in.buf + KB_IN_BYTES){ // kb_in.p_head = kb_in.buf; // } // kb_in.count++; // } }
int phandler() { int status; int c; struct para *p = &printer; printf("printer interrupt!\n"); status = in_byte(p->port+1); if (status & 0x08){ // test for noERROR only if (p->room.value == PLEN){ // pbuf[] empty, nothing to print //out_byte(p->port+2, 0x0C); // turn off printer interrupts V(&p->done); // tell task print is DONE p->printing = 0; // is no longer printing goto out; } // p->pbuf[] not empty ==> print next char c = p->pbuf[p->tail++] & 0x7F; p->tail %= PLEN; out_byte(p->port, c); // print the char strobe(p); V(&p->room); goto out; } // abnormal printer status: should handle it but ignored here out: out_byte(0x20, 0x20); // re-enable the 8259 }
/* * static int send_hd_cmd(HD_CMD *cmd); * 通过传入命令指针,将相应的寄存器设置为HD_CMD的成员。 * 当设置command之后硬盘发生中断 * 之前需要测试REG_STATUS的BSY是否为0。 * 之后再设置REG_DEV_CONTROL的IEN为0。表示打开中断 * 如果成功则返回0 失败返回-1 */ static int send_hd_cmd(HD_CMD *cmd){ u8 status; int i; for(i = 0; i < 1000; i++){ status = in_byte((u32) REG_STATUS); if(status == STATUS_BSY){ //检查STATUS是否忙。如果忙延迟一段时间再检查。当循环结束还没有成功,返回-1否则成功返回0 delay(i); continue; } if(status != STATUS_BSY){ out_byte((u32)0 , (u32)REG_DEV_CONTROL); //设置IEN,表示中断打开 out_byte((u32)cmd -> feature , (u32)REG_FEATURE); out_byte((u32)cmd -> sec_counter , (u32)REG_SEC_COUNTER); out_byte((u32)cmd -> lba_low , (u32)REG_LBA_LOW); out_byte((u32)cmd -> lba_mid , (u32)REG_LBA_MID); out_byte((u32)cmd -> lba_hig , (u32)REG_LBA_HIG); out_byte((u32)cmd -> device , (u32)REG_DEVICE); out_byte((u32)cmd -> command , (u32)REG_COMMAND); return 0; } } return -1; }
/*======================================================================* kb_wait *======================================================================*/ PRIVATE void kb_wait() /* 等待 8042 的输入缓冲区空 */ { u8 kb_stat; do { kb_stat = in_byte(KB_CMD); } while (kb_stat & 0x02); }
int do_rx(struct stty *t) { int c; c = in_byte(tty->port) & 0x7F; /* read the char from port */ printf("\nrx interrupt c="); putc(c); // COMPLETE with YOUR C code }
/********************************************************* waitfor ********************************************************** @param mask Status mask @param val Required status @param timeout Timeout in milliseconds @return One if success, zero if timeout **********************************************************/ PRIVATE int waitfor(int mask, int val, int timeout) { int t = kernelGetTicks(); while(((kernelGetTicks() - t) * 1000 / HZ) < timeout) if((in_byte(REG_STATUS) & mask) == val) return 1; return 0; }
PUBLIC void keyboard_handler(u32 param) { u8 scan_code = in_byte(KB_DATA); if(kb_in.head >= KB_IN_BYTES - 1) kb_in.head = -1; kb_in.buf[++kb_in.head] = scan_code; ++kb_in.count; }
int get_cursor() { // The device uses its control register as an index // to select its internal registers , of which we are // interested in: // reg 14: which is the high byte of the cursor 's offset // reg 15: which is the low byte of the cursor 's offset // Once the internal register has been selected , we may read or // write a byte on the data register . out_byte(REG_SCREEN_CTRL, 14); int offset = in_byte(REG_SCREEN_DATA) << 8; out_byte(REG_SCREEN_CTRL, 15); offset += in_byte(REG_SCREEN_DATA); // Since the cursor offset reported by the VGA hardware is the // number of characters , we multiply by two to convert it to // a character cell offset . return offset * 2; }
void int_handler21(int* esp) { ///* out_byte(0x20, 0x61); char data = in_byte(0x60); print(data); //*/ print('K'); }
void serial_init (void) { #if 0 uint32 clock_divisor = 115200 / baudrate; uint8 cfg; uint8 a; uint16 devfn = 7 << 3; if (serial_init_done) return; /* Enter configuration mode */ cfg = pci_read_cfg_byte (0, devfn, 0x85); pci_write_cfg_byte (0, devfn, 0x85, cfg | 0x02); /* Set serial port COM1 as 3F8 */ out_byte (0x3F0, 0xE7); out_byte (0x3f1, 0xfe); /* Set serial port COM2 as 2F8 */ out_byte (0x3f0, 0xe8); out_byte (0x3f1, 0xeb); /* Enable */ out_byte (0x3f0, 0xe2); a = in_byte (0x3f1); a |= 0xc; out_byte (0x3f0, 0xe2); out_byte (0x3f1, a); /* Reset the configuration mode */ pci_write_cfg_byte (0, devfn, 0x85, cfg); #endif ComPort1 = 0x3F8; /* Disable interrupts */ COM_WRITE_BYTE (INTERRUPT_ENABLE, 0x00); /* Set baud rate */ /* COM_WRITE_BYTE(LINE_CONTROL, 0x83); */ /* COM_WRITE_BYTE(DIVISOR_LATCH_LSB, (uint8)(clock_divisor & 0xFF)); */ /* COM_WRITE_BYTE(DIVISOR_LATCH_MSB, (uint8)(clock_divisor >> 8)); */ /* __asm("eieio"); */ /* Set 8-N-1 */ COM_WRITE_BYTE (LINE_CONTROL, 0x03); __asm ("eieio"); /* Disable FIFO */ COM_WRITE_BYTE (MODEM_CONTROL, 0x03); COM_WRITE_BYTE (FIFO_CONTROL, 0x07); __asm ("eieio"); serial_init_done = 1; }
/* 功能: 在一定时间内等待某一状态,如果等到,则返回TRUE;否则返回假FALSE. 参数: mask:获取对应状态的掩码 val:想等待的状态值 time_out:最长等待时间(ms) 返回值: */ static BOOL wait_for(int mask,int val,int time_out){ int s=get_milli_seconds(); while((get_milli_seconds()-s)<time_out){ if((in_byte(REG_P_STATUS) & mask)==val){ return TRUE; } } return FALSE; }
PRIVATE int waitfor(int mask, int val, int timeout) { int t = get_ticks(); while (((get_ticks() -t) * 1000 / HZ) < timeout) { /* 注意优先级, `==` 高于 `&` */ if ((in_byte(REG_STATUS) & mask) == val) { return 1; } } return 0; }
int shandler(int port) { struct stty *t; int IntID, LineStatus, ModemStatus, intType, c; t = &stty[port]; /* IRQ 4 interrupt : COM1 = stty[0] */ IntID = in_byte(t->port+IIR); /* read InterruptID Reg */ LineStatus= in_byte(t->port+LSR); /* read LineStatus Reg */ ModemStatus=in_byte(t->port+MSR); /* read ModemStatus Reg */ intType = IntID & 7; /* mask out all except the lowest 3 bits */ switch(intType){ case 6 : do_errors(t); break; /* 110 = errors */ case 4 : do_rx(t); break; /* 100 = rx interrupt */ case 2 : do_tx(t); break; /* 010 = tx interrupt */ case 0 : do_modem(t); break; /* 000 = modem interrupt */ } out_byte(INT_CTL, ENABLE); /* reenable the 8259 controller */ }
/** * <Ring 1> Wait for a certain status. * * @param mask Status mask. * @param val Required status. * @param timeout Timeout in milliseconds. * * @return One if sucess, zero if timeout. *****************************************************************************/ PRIVATE int waitfor(int mask, int val, int timeout) { ERIC_DEBUG(",WHD"); int t = get_ticks(); while(((get_ticks() - t) * 1000 / HZ) < timeout) if ((in_byte(REG_STATUS) & mask) == val) return 1; return 0; }