root/kernel/chr_drv/rs_io.s

/* [previous][next][first][last][top][bottom][index][help] */
   1 /*
   2  *  linux/kernel/rs_io.s
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 /*
   8  *      rs_io.s
   9  *
  10  * This module implements the rs232 io interrupts.
  11  */
  12 
  13 .text
  14 .globl _rs1_interrupt,_rs2_interrupt
  15 
  16 size    = 2048                          /* must be power of two !
  17                                            and must match the value
  18                                            in tty_io.c!!! */
  19 
  20 /* these are the offsets into the read/write buffer structures */
  21 rs_addr = 0
  22 head = 4
  23 tail = 8
  24 proc_list = 12
  25 buf = 16
  26 
  27 startup = 256           /* chars left in write queue when we restart it */
  28 
  29 /*
  30  * These are the actual interrupt routines. They look where
  31  * the interrupt is coming from, and take appropriate action.
  32  *
  33  * rs1_interrupt (IRQ 4) takes care of com1 and com3
  34  * rs2_interrupt (IRQ 3) takes care of com2 and com4
  35  */
  36 .align 2
  37 _rs1_interrupt:
  38         pushl $_table_list+8
  39         pushl $_table_list+24
  40         jmp rs_int
  41 
  42 .align 2
  43 _rs2_interrupt:
  44         pushl $_table_list+16
  45         pushl $_table_list+32
  46 rs_int: cld
  47         pushl %edx
  48         pushl %ecx
  49         pushl %ebx
  50         pushl %eax
  51         push %es
  52         push %ds                /* as this is an interrupt, we cannot */
  53         pushl $0x10             /* know that bs is ok. Load it */
  54         pop %ds
  55         pushl $0x10
  56         pop %es
  57         movl 24(%esp),%edx
  58         call do_rs_intr
  59         movl 28(%esp),%edx
  60         call do_rs_intr
  61         movb $0x20,%al
  62         outb %al,$0x20          /* EOI */
  63         pop %ds
  64         pop %es
  65         popl %eax
  66         popl %ebx
  67         popl %ecx
  68         popl %edx
  69         addl $8,%esp            # jump over the _table_list entries
  70         iret
  71 
  72 do_rs_intr:
  73         pushl %edx
  74         movl (%edx),%edx
  75         movl rs_addr(%edx),%edx
  76         addl $2,%edx            /* interrupt ident. reg */
  77 1:      xorl %eax,%eax
  78         inb %dx,%al
  79         testb $1,%al
  80         jne 2f
  81         cmpb $6,%al             /* this shouldn't happen, but ... */
  82         ja 2f
  83         movl (%esp),%ecx
  84         pushl %edx
  85         subl $2,%edx
  86         call jmp_table(,%eax,2)         /* NOTE! not *4, bit0 is 0 already */
  87         popl %edx
  88         jmp 1b
  89 2:      popl %edx
  90         ret
  91 
  92 jmp_table:
  93         .long modem_status,write_char,read_char,line_status
  94 
  95 .align 2
  96 modem_status:
  97         addl $6,%edx            /* clear intr by reading modem status reg */
  98         inb %dx,%al
  99         ret
 100 
 101 .align 2
 102 line_status:
 103         addl $5,%edx            /* clear intr by reading line status reg. */
 104         inb %dx,%al
 105         ret
 106 
 107 .align 2
 108 read_char:
 109         inb %dx,%al
 110         movl %ecx,%edx
 111         subl $_table_list,%edx
 112         shrl $3,%edx
 113         movl (%ecx),%ecx                # read-queue
 114         movl head(%ecx),%ebx
 115         movb %al,buf(%ecx,%ebx)
 116         incl %ebx
 117         andl $size-1,%ebx
 118         cmpl tail(%ecx),%ebx
 119         je 1f
 120         movl %ebx,head(%ecx)
 121 1:      movl mask_table(,%edx,4),%edx
 122         orl %edx,_timer_active
 123         ret
 124 
 125 .align 2
 126 mask_table:
 127         .long 0,4,8,16,32
 128 
 129 .align 2
 130 write_char:
 131         movl 4(%ecx),%ecx               # write-queue
 132         movl head(%ecx),%ebx
 133         subl tail(%ecx),%ebx
 134         andl $size-1,%ebx               # nr chars in queue
 135         je write_buffer_empty
 136         cmpl $startup,%ebx
 137         ja 1f
 138         movl proc_list(%ecx),%ebx       # wake up sleeping process
 139         testl %ebx,%ebx                 # is there any?
 140         je 1f
 141         movl $0,(%ebx)
 142 1:      movl tail(%ecx),%ebx
 143         movb buf(%ecx,%ebx),%al
 144         outb %al,%dx
 145         incl %ebx
 146         andl $size-1,%ebx
 147         movl %ebx,tail(%ecx)
 148         cmpl head(%ecx),%ebx
 149         je write_buffer_empty
 150         ret
 151 
 152 .align 2
 153 write_buffer_empty:
 154         movl proc_list(%ecx),%ebx       # wake up sleeping process
 155         testl %ebx,%ebx                 # is there any?
 156         je 1f
 157         movl $0,(%ebx)
 158 1:      incl %edx
 159         inb %dx,%al
 160         jmp 1f
 161 1:      jmp 1f
 162 1:      andb $0xd,%al                   # disable transmit interrupt
 163         outb %al,%dx
 164         ret

/* [previous][next][first][last][top][bottom][index][help] */