2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
5 Desc: functions for serial RawIOInit/RawPutChar
8 Note: serial io from "PC-intern" examples
10 #include <proto/exec.h>
14 #undef __restore_flags
18 #define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
19 #define __restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
20 #define __cli() __asm__ __volatile__("cli": : :"memory")
21 #define __sti() __asm__ __volatile__("sti": : :"memory")
23 #define SER_ERRSIGNALS 0x0300
25 #define SER_LSR_OVERRUNERROR 0x02
26 #define SER_LSR_PARITYERROR 0x04
27 #define SER_LSR_FRAMINGERROR 0x08
28 #define SER_LSR_BREAKDETECT 0x10
29 #define SER_LSR_ERRORMSK (SER_LSR_OVERRUNERROR|SER_LSR_PARITYERROR|\
30 SER_LSR_FRAMINGERROR|SER_LSR_BREAKDETECT)
31 #define SER_LSR_TSREMPTY 0x40
33 #define SER_LCR_8BITS 0x03
34 #define SER_LCR_1STOPBIT 0x00
35 #define SER_LCR_NOPARITY 0x00
36 #define SER_LCR_SETDIVISOR 0x80
38 #define SER_TXBUFFER 0x00
39 #define SER_DIVISOR_LSB 0x00
40 #define SER_DIVISOR_MSB 0x01
41 #define SER_IRQ_ENABLE 0x01
42 #define SER_IRQ_ID 0x02
44 #define SER_2FUNCTION 0x02
45 #define SER_LINE_CONTROL 0x03
46 #define SER_MODEM_CONTROL 0x04
47 #define SER_LINE_STATUS 0x05
48 #define SER_MODEM_STATUS 0x06
49 #define SER_SCRATCH 0x07
51 #define SER_MCR_DTR 0x01
52 #define SER_MCR_RTS 0x02
53 #define SER_MCR_LOOP 0x10
55 #define SER_FIFO_ENABLE 0x01
56 #define SER_FIFO_RESETRECEIVE 0x02
57 #define SER_FIFO_RESETTRANSMIT 0x04
59 #define SER_MAXBAUD 115200L
61 int ser_UARTType (short);
62 void ser_FIFOLevel(short, BYTE
);
63 int ser_Init(short, LONG
, BYTE
);
65 /*****i***********************************************************************
68 AROS_LH0(void, SerialRawIOInit
,
71 struct ExecBase
*, SysBase
, 84, Exec
)
74 This is a private function. It initializes raw IO. After you
75 have called this function, you can use (!RawMayGetChar()) and
85 This function is for very low level debugging only.
92 RawPutChar(), RawMayGetChar()
98 *****************************************************************************/
101 #if AROS_SERIAL_DEBUG == 1
102 if (ser_Init(0x3F8, 9600,SER_LCR_8BITS
| SER_LCR_1STOPBIT
| SER_LCR_NOPARITY
))
103 ser_FIFOLevel(0x3F8, 0);
105 #if AROS_SERIAL_DEBUG == 2
106 if (ser_Init(0x2F8, 9600,SER_LCR_8BITS
| SER_LCR_1STOPBIT
| SER_LCR_NOPARITY
))
107 ser_FIFOLevel(0x2F8, 0);
113 int ser_UARTType (short port
) {
115 outb_p(0xAA, port
+SER_LINE_CONTROL
); /* set Divisor-Latch */
116 if (inb_p(port
+SER_LINE_CONTROL
) != 0xAA)
118 outb_p(0x55, port
+SER_DIVISOR_MSB
); /* write Divisor */
119 if (inb_p(port
+SER_DIVISOR_MSB
) != 0x55)
121 outb_p(0x55, port
+SER_LINE_CONTROL
); /* clear Divisor-Latch */
122 if (inb_p(port
+SER_LINE_CONTROL
) != 0x55)
124 outb_p(0x55, port
+SER_IRQ_ENABLE
);
125 if (inb_p(port
+SER_IRQ_ENABLE
) != 0x05)
127 outb_p(0, port
+SER_FIFO
); /* clear FIFO and IRQ */
128 outb_p(0, port
+SER_IRQ_ENABLE
);
129 if (inb_p(port
+SER_IRQ_ID
) != 1)
131 outb_p(0xF5, port
+SER_MODEM_CONTROL
);
132 if (inb_p(port
+SER_MODEM_CONTROL
) != 0x15)
134 outb_p(SER_MCR_LOOP
, port
+SER_MODEM_CONTROL
); /* Looping */
135 inb_p(port
+SER_MODEM_STATUS
);
136 if ((inb_p(port
+SER_MODEM_STATUS
) & 0xF0) != 0)
138 outb_p(0x1F, port
+SER_MODEM_CONTROL
);
139 if ((inb_p(port
+SER_MODEM_STATUS
) & 0xF0) != 0xF0)
141 outb_p(SER_MCR_DTR
| SER_MCR_RTS
, port
+ SER_MODEM_CONTROL
);
143 outb_p(0x55, port
+SER_SCRATCH
); /* Scratch-Register ?*/
144 if (inb_p(port
+SER_SCRATCH
) != 0x55)
146 outb_p(0, port
+SER_SCRATCH
);
148 outb_p(0xCF, port
+SER_FIFO
); /* FIFO ? */
149 if ((inb_p(port
+SER_IRQ_ID
) & 0xC0) != 0xC0)
151 outb_p(0, port
+SER_FIFO
);
152 /* Alternate-Function Register ? */
153 outb_p(SER_LCR_SETDIVISOR
, port
+SER_LINE_CONTROL
);
154 outb_p(0x07, port
+SER_2FUNCTION
);
155 if (inb_p(port
+SER_2FUNCTION
) != 0x07)
157 outb_p(0, port
+SER_LINE_CONTROL
);
158 return 4; //NS16550A;
160 outb_p(0, port
+SER_LINE_CONTROL
); /* reset registers */
161 outb_p(0, port
+SER_2FUNCTION
);
162 return 5; //NS16C552;
165 void ser_FIFOLevel(short port
, BYTE level
) {
168 outb_p(level
| SER_FIFO_ENABLE
, port
+SER_FIFO
);
170 outb_p(SER_FIFO_RESETRECEIVE
| SER_FIFO_RESETTRANSMIT
, port
+SER_FIFO
);
173 int ser_Init(short port
, LONG baudRate
, BYTE params
) {
176 if (ser_UARTType(port
)!=1)
178 uDivisor
=(WORD
)(SER_MAXBAUD
/ baudRate
);
179 outb_p(inb_p(port
+SER_LINE_CONTROL
) | SER_LCR_SETDIVISOR
, port
+SER_LINE_CONTROL
);
180 outb_p(uDivisor
& 0xFF, port
+SER_DIVISOR_LSB
);
181 outb_p(uDivisor
>>8, port
+SER_DIVISOR_MSB
);
182 outb_p(inb_p(port
+SER_LINE_CONTROL
) & ~SER_LCR_SETDIVISOR
, port
+SER_LINE_CONTROL
);
184 outb_p(params
, port
+SER_LINE_CONTROL
);
185 inb_p(port
+SER_TXBUFFER
);
191 int ser_WriteByte(short, UBYTE
, ULONG
, BYTE
, BYTE
);
192 int ser_IsWritingPossible(short);
195 AROS_LH1(void, SerialRawPutChar
,
198 AROS_LHA(UBYTE
, chr
, D0
),
201 struct ExecBase
*, SysBase
, 86, Exec
)
204 Emits a single character.
207 chr - The character to emit
213 This function is for very low level debugging only.
220 RawIOInit(), RawPutChar(), RawMayGetChar()
226 *****************************************************************************/
230 /* stegerg: Don't use Disable/Enable, because we want
231 interrupt enabled flag to stay the same as
232 it was before the Disable() call */
241 /* Don't write 0 bytes */
245 // ser_WriteByte(0x2F8, 0x0D, 1, 0, 0);
246 #if AROS_SERIAL_DEBUG == 1
247 ser_WriteByte(0x3F8, chr
, 0, 0, 0);
249 #if AROS_SERIAL_DEBUG == 2
250 ser_WriteByte(0x2F8, chr
, 0, 0, 0);
254 __restore_flags(flags
);
261 int ser_IsWritingPossible(short port
) {
263 return inb_p(port
+SER_LINE_STATUS
) & SER_LSR_TSREMPTY
;
266 int ser_WriteByte(short port
, UBYTE data
, ULONG timeout
, BYTE sigmask
, BYTE sigvals
) {
270 while (!ser_IsWritingPossible(port
) && timeout
)
276 while (!ser_IsWritingPossible(port
));
278 if ((inb_p(port
+SER_MODEM_STATUS
) & sigmask
) == sigvals
)
280 outb_p(data
, port
+SER_TXBUFFER
);
281 return inb_p(port
+SER_LINE_STATUS
) & SER_LSR_ERRORMSK
;
284 return SER_ERRSIGNALS
;