Project

General

Profile

Revision 9

Added Makefile, keyboard files and i8xxx.h files

View differences:

lab3/Makefile
1
# name of the program (Minix service)
2
PROG=lab3 
3

  
4
# source code files to be compiled
5
SRCS = lab3.c keyboard.c
6

  
7
# additional compilation flags
8
# "-Wall -Wextra -Werror -I . -std=c11 -Wno-unused-parameter" are already set
9
CFLAGS += -pedantic -DLAB3
10

  
11
# list of library dependencies (for Lab 3, only LCF library)
12
DPADD += ${LIBLCF}
13
LDADD += -llcf
14

  
15
# include LCOM's makefile that does all the "heavy lifting"
16
.include <minix.lcom.mk>
lab3/i8042.h
1
#ifndef _LCOM_I8042_H_
2
#define _LCOM_I8042_H_
3

  
4
#include <lcom/lcf.h>
5

  
6
/** @defgroup i8042 i8042
7
 * @{
8
 *
9
 * Constants for programming the i8042 Keyboard.
10
 */
11

  
12
#define KEYBOARD_IRQ 0x09 /* Keyboard IRQ address */
13

  
14
#define BIT(n) (0x01<<(n))
15

  
16
#define DELAY_US        20000
17

  
18
#define STAT_REG_PAR		  BIT(7)  /* Parity Error */
19
#define STAT_REG_TIMEOUT	BIT(6)  /* Timeout Error */
20
#define STAT_REG_AUX		  BIT(5)  /* Mouse Data */
21
#define STAT_REG_INH		  BIT(4)  /* Inhibit Flag */
22
#define STAT_REG_A2       BIT(3)  /* A2 Input Line */
23
#define STAT_REG_SYS		  BIT(2)  /* System Flag */ 
24
#define STAT_REG_IBF	   	BIT(1)  /* Input Buffer Full */
25
#define STAT_REG_OBF		  BIT(0)  /* Output Buffer Full */
26

  
27
#define OUTPUT_BUF         0x60    /* Output Buffer */
28
#define INPUT_BUF          0x60    /* Input Buffer */
29
#define STATUS_REG        0x64    /* Status Register */
30
#define KBC_CMD_REG     0x64    /* Command Register */
31
#define KBC_CMD_ARG     0x60    /* Command Arguments Adress */
32

  
33
#define ESC_BREAK      0x81
34
#define TWO_BYTE_SCANCODE   0xE0  /* Two-byte long scancodes use 0xE0 as their first byte */
35
#define MAKE_CODE            BIT(7)
36

  
37
#endif /* _LCOM_I8042_H */
lab3/i8254.h
1
#ifndef _LCOM_I8254_H_
2
#define _LCOM_I8254_H_
3

  
4
#include <lcom/lcf.h>
5

  
6
/** @defgroup i8254 i8254
7
 * @{
8
 *
9
 * Constants for programming the i8254 Timer. Needs to be completed.
10
 */
11

  
12
#define TIMER_FREQ 1193182 /**< @brief clock frequency for timer in PC and AT */
13
#define TIMER0_IRQ 0 /**< @brief Timer 0 IRQ line */
14

  
15
/* I/O port addresses */
16

  
17
#define TIMER_0    0x40 /**< @brief Timer 0 count register */
18
#define TIMER_1    0x41 /**< @brief Timer 1 count register */
19
#define TIMER_2    0x42 /**< @brief Timer 2 count register */
20
#define TIMER_CTRL 0x43 /**< @brief Control register */
21

  
22
#define SPEAKER_CTRL 0x61 /**< @brief Register for speaker control  */
23

  
24
/* Timer control */
25

  
26
/* Timer selection: bits 7 and 6 */
27

  
28
#define TIMER_SEL0   0x00              /**< @brief Control Word for Timer 0 */
29
#define TIMER_SEL1   BIT(6)            /**< @brief Control Word for Timer 1 */
30
#define TIMER_SEL2   BIT(7)            /**< @brief Control Word for Timer 2 */
31
#define TIMER_RB_CMD (BIT(7) | BIT(6)) /**< @brief Read Back Command */
32

  
33
/* Register selection: bits 5 and 4 */
34

  
35
#define TIMER_LSB     BIT(4)                  /**< @brief Initialize Counter LSB only */
36
#define TIMER_MSB     BIT(5)                  /**< @brief Initialize Counter MSB only */
37
#define TIMER_LSB_MSB (TIMER_LSB | TIMER_MSB) /**< @brief Initialize LSB first and MSB afterwards */
38

  
39
/* Operating mode: bits 3, 2 and 1 */
40

  
41
#define TIMER_SQR_WAVE (BIT(2) | BIT(1)) /**< @brief Mode 3: square wave generator */
42
#define TIMER_RATE_GEN BIT(2)            /**< @brief Mode 2: rate generator */
43

  
44
/* Counting mode: bit 0 */
45

  
46
#define TIMER_BCD 0x01 /**< @brief Count in BCD */
47
#define TIMER_BIN 0x00 /**< @brief Count in binary */
48

  
49
/* READ-BACK COMMAND FORMAT */
50

  
51
#define TIMER_RB_COUNT_  BIT(5)
52
#define TIMER_RB_STATUS_ BIT(4)
53
#define TIMER_RB_SEL(n)  BIT((n) + 1)
54

  
55
/**@}*/
56

  
57
#endif /* _LCOM_I8254_H */
lab3/keyboard.c
1
#include <lcom/lcf.h>
2

  
3
#include <lcom/lab3.h>
4

  
5
#include <stdbool.h>
6
#include <stdint.h>
7
#include "i8042.h"
8

  
9

  
10
u8int_t scan_code=0;            // make code or break code
11
int keyboard_id = KEYBOARD_IRQ; 	// KEYBOARD_IRQ is defined in interrupt.h in .minix-src folder
12
uint32_t cnt = 0;									// counter of sys_inb calls
13
					
14
int (util_sys_inb)(int port, uint8_t *value) { //transform 8 bit into 32 bit
15

  
16
  uint32_t new_val;                           //initializing 32 bit variable
17

  
18
  if(sys_inb(port,&new_val)!=0){              //verifies if there is an error
19
      printf("Error in util_sys_inb\n");
20
      return 1;
21
  }
22
  *value=new_val & 0xFF;                      //dereferencing "value"
23
  #ifdef LAB3
24
  cnt++;
25
  #endif
26
  
27

  
28
  return 0;
29
}
30

  
31
void (kbc_ih)(void){
32
  u8int_t status_reg;
33

  
34
  if(util_sys_inb(STATUS_REG,status_reg)!=0){ //checks if there is an error
35
    return;
36
  }
37
  if(((status_reg & STAT_REG_OBF)==0) ||((status_reg&(STAT_REG_PAR|STAT_REG_TIMEOUT))!=0)){ //checks if there is a parity or timeout error (mask -> 0xC0, bit 7 and 6 set) and checks if output buffer is empty
38
    return;
39
  }
40
  util_sys_inb(OUTPUT_BUF,status_code);
41

  
42
}
43

  
44
int (kbc_subscribe_int)(uint8_t *bit_no) {    //similar function to that of timer_subscribe_int
45
    *bit_no = BIT(keyboard_id);
46
    if(sys_irqsetpolicy(KEYBOARD_IRQ,(IRQ_REENABLE|IRQ_EXCLUSIVE),&keyboard_id)==1){      //operation to subscribe int
47
        printf("Error subscribing int\n");
48
        return 1;
49
    }
50
  return 0;
51
}
52

  
53
int (kbc_unsubscribe_int)() {           //similar function to that of timer_unsubscribe_int
54
  if(sys_irqrmpolicy(&keyboard_id)==1){
55
      printf("Error unsubscribing int\n");
56
      return 1;
57
  }
58
  return 0;
59
}
lab3/keyboard.h
1
#include <lcom/lcf.h>
2

  
3
#include <lcom/lab3.h>
4

  
5
#include <stdbool.h>
6
#include <stdint.h>
7
/**
8
* @brief Handles keyboard interrupts (C implementation)
9
*
10
* Reads the status register and the output buffer (OB).
11
* If there was some error, the byte read from the OB should be discarded.
12
*
13
* All communication with other code must be done via global variables, static if possible.
14
*
15
* Must be defined using parenthesis around the function name:
16
*/
17
void (kbc_ih)(void);
18
/**
19
 * @brief Invokes sys_inb() system call but reads the value into a uint8_t variable.
20
 *
21
 * @param port the input port that is to be read
22
 * @param value address of 8-bit variable to be update with the value read
23
 * @return Return 0 upon success and non-zero otherwise
24
 */
25
int (util_sys_inb)(int port, uint8_t *value);
26
/**
27
 * @brief Subscribes and enables Keyboard interrupts
28
 *
29
 * @param bit_no address of memory to be initialized with the
30
 *         bit number to be set in the mask returned upon an interrupt
31
 * @return Return 0 upon success and non-zero otherwise
32
 */
33
int(kbc_subscribe_int)(uint8_t *bit_no);
34

  
35
/**
36
 * @brief Unsubscribes Keyboard interrupts
37
 *
38
 * @return Return 0 upon success and non-zero otherwise
39
 */
40
int(kbc_unsubscribe_int)();
lab3/lab3.c
4 4

  
5 5
#include <stdbool.h>
6 6
#include <stdint.h>
7

  
7
#include "keyboard.h"
8 8
int main(int argc, char *argv[]) {
9 9
  // sets the language of LCF messages (can be either EN-US or PT-PT)
10 10
  lcf_set_language("EN-US");
......
29 29
  return 0;
30 30
}
31 31

  
32
extern uint8_t scan_reg;
33

  
32 34
int(kbd_test_scan)() {
33
  /* To be completed by the students */
34
  printf("%s is not yet implemented!\n", __func__);
35
  int r, ipc_status;
36
  uint8_t keyboard_irq, size, byte[2]; //size of scancode can be 2 byte long
37
  message msg;
38
  bool make=false; //to check if code is make or break
35 39

  
36
  return 1;
40
  if(kbc_subscribe_int(keyboard_irq)==1){
41
    printf("Error subscribing int\n");
42
    return 1;
43
  }
44

  
45
  while(scan_code!=ESC_BREAK){      //looping until status_reg is the breakcode of ESC key
46
    if ((r = driver_receive(ANY, &msg, &ipc_status))==1){ 
47
      printf("driver_receive failed with: %d",r);
48
      continue;
49
    }
50
    if (is_ipc_notify(ipc_status)){                             //received notification
51
      switch (_ENDPOINT_P(msg.m_source)){
52
        case HARDWARE:                                          //hardware interrupt notification				
53
                if (msg.m_notify.interrupts &keyboard_irq){          // subscribed interrupt
54
                  
55
                  kbc_ih();
56
                  bytes[0]=scan_code;
57
                  bytes[1]=scan_code;
58

  
59
                  if(bytes[0]==TWO_BYTE_SCANCODE){
60
                    size=2;
61
                  }
62
                  else{
63
                    size=1;
64
                  }
65

  
66
                  if (scan_code & MAKE_CODE){	// 4 - Checks if code is make or break
67
                      make = false;	//break code
68
                    }
69
                  else {
70
                    make = true;  //make code
71
                  }
72
                  kbd_print_scancode(make, size, bytes); //prints the code
73
                      }
74
               break;
75
        default:
76
              break;                                            //no other notifications expected: do nothing	
77
        }
78
    } 
79
    else {                                                      //received a standard message, not a notification
80
      //no standard messages expected: do nothing
81
    }
82
  }
83

  
84
   if (kbc_unsubscribe_int() != 0) { // Check if subscription worked
85
		printf("Error unsubscribing int \n");
86
		return 1;
87
	}
88

  
89
  return 0;
37 90
}
38 91

  
39 92
int(kbd_test_poll)() {

Also available in: Unified diff