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    = 1024                          /* 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 .align 2
  34 _rs1_interrupt:
  35         pushl $_table_list+8
  36         jmp rs_int
  37 .align 2
  38 _rs2_interrupt:
  39         pushl $_table_list+16
  40 rs_int:
  41         pushl %edx
  42         pushl %ecx
  43         pushl %ebx
  44         pushl %eax
  45         push %es
  46         push %ds                /* as this is an interrupt, we cannot */
  47         pushl $0x10             /* know that bs is ok. Load it */
  48         pop %ds
  49         pushl $0x10
  50         pop %es
  51         movl 24(%esp),%edx
  52         movl (%edx),%edx
  53         movl rs_addr(%edx),%edx
  54         addl $2,%edx            /* interrupt ident. reg */
  55 rep_int:
  56         xorl %eax,%eax
  57         inb %dx,%al
  58         testb $1,%al
  59         jne end
  60         cmpb $6,%al             /* this shouldn't happen, but ... */
  61         ja end
  62         movl 24(%esp),%ecx
  63         pushl %edx
  64         subl $2,%edx
  65         call jmp_table(,%eax,2)         /* NOTE! not *4, bit0 is 0 already */
  66         popl %edx
  67         jmp rep_int
  68 end:    movb $0x20,%al
  69         outb %al,$0x20          /* EOI */
  70         pop %ds
  71         pop %es
  72         popl %eax
  73         popl %ebx
  74         popl %ecx
  75         popl %edx
  76         addl $4,%esp            # jump over _table_list entry
  77         iret
  78 
  79 jmp_table:
  80         .long modem_status,write_char,read_char,line_status
  81 
  82 .align 2
  83 modem_status:
  84         addl $6,%edx            /* clear intr by reading modem status reg */
  85         inb %dx,%al
  86         ret
  87 
  88 .align 2
  89 line_status:
  90         addl $5,%edx            /* clear intr by reading line status reg. */
  91         inb %dx,%al
  92         ret
  93 
  94 .align 2
  95 read_char:
  96         inb %dx,%al
  97         movl %ecx,%edx
  98         subl $_table_list,%edx
  99         shrl $3,%edx
 100         movl (%ecx),%ecx                # read-queue
 101         movl head(%ecx),%ebx
 102         movb %al,buf(%ecx,%ebx)
 103         incl %ebx
 104         andl $size-1,%ebx
 105         cmpl tail(%ecx),%ebx
 106         je 1f
 107         movl %ebx,head(%ecx)
 108 1:      pushl %edx
 109         call _do_tty_interrupt
 110         addl $4,%esp
 111         ret
 112 
 113 .align 2
 114 write_char:
 115         movl 4(%ecx),%ecx               # write-queue
 116         movl head(%ecx),%ebx
 117         subl tail(%ecx),%ebx
 118         andl $size-1,%ebx               # nr chars in queue
 119         je write_buffer_empty
 120         cmpl $startup,%ebx
 121         ja 1f
 122         movl proc_list(%ecx),%ebx       # wake up sleeping process
 123         testl %ebx,%ebx                 # is there any?
 124         je 1f
 125         movl $0,(%ebx)
 126 1:      movl tail(%ecx),%ebx
 127         movb buf(%ecx,%ebx),%al
 128         outb %al,%dx
 129         incl %ebx
 130         andl $size-1,%ebx
 131         movl %ebx,tail(%ecx)
 132         cmpl head(%ecx),%ebx
 133         je write_buffer_empty
 134         ret
 135 .align 2
 136 write_buffer_empty:
 137         movl proc_list(%ecx),%ebx       # wake up sleeping process
 138         testl %ebx,%ebx                 # is there any?
 139         je 1f
 140         movl $0,(%ebx)
 141 1:      incl %edx
 142         inb %dx,%al
 143         jmp 1f
 144 1:      jmp 1f
 145 1:      andb $0xd,%al           /* disable transmit interrupt */
 146         outb %al,%dx
 147         ret

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