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 #if AROS_SERIAL_DEBUG == 2
62 UWORD __serial_rawio_port
= 0x2F8;
64 UWORD __serial_rawio_port
= 0x3F8;
67 int ser_UARTType (short);
68 void ser_FIFOLevel(short, BYTE
);
69 int ser_Init(short, LONG
, BYTE
);
71 /*****i***********************************************************************
74 AROS_LH0(void, SerialRawIOInit
,
77 struct ExecBase
*, SysBase
, 84, Exec
)
80 This is a private function. It initializes raw IO. After you
81 have called this function, you can use (!RawMayGetChar()) and
91 This function is for very low level debugging only.
98 RawPutChar(), RawMayGetChar()
104 *****************************************************************************/
107 if (__serial_rawio_port
> 0)
109 if (ser_Init(__serial_rawio_port
, SER_MAXBAUD
, SER_LCR_8BITS
| SER_LCR_1STOPBIT
| SER_LCR_NOPARITY
))
110 ser_FIFOLevel(__serial_rawio_port
, 0);
117 int ser_UARTType (short port
) {
119 outb_p(0xAA, port
+SER_LINE_CONTROL
); /* set Divisor-Latch */
120 if (inb_p(port
+SER_LINE_CONTROL
) != 0xAA)
122 outb_p(0x55, port
+SER_DIVISOR_MSB
); /* write Divisor */
123 if (inb_p(port
+SER_DIVISOR_MSB
) != 0x55)
125 outb_p(0x55, port
+SER_LINE_CONTROL
); /* clear Divisor-Latch */
126 if (inb_p(port
+SER_LINE_CONTROL
) != 0x55)
128 outb_p(0x55, port
+SER_IRQ_ENABLE
);
129 if (inb_p(port
+SER_IRQ_ENABLE
) != 0x05)
131 outb_p(0, port
+SER_FIFO
); /* clear FIFO and IRQ */
132 outb_p(0, port
+SER_IRQ_ENABLE
);
133 if (inb_p(port
+SER_IRQ_ID
) != 1)
135 outb_p(0xF5, port
+SER_MODEM_CONTROL
);
136 if (inb_p(port
+SER_MODEM_CONTROL
) != 0x15)
138 outb_p(SER_MCR_LOOP
, port
+SER_MODEM_CONTROL
); /* Looping */
139 inb_p(port
+SER_MODEM_STATUS
);
140 if ((inb_p(port
+SER_MODEM_STATUS
) & 0xF0) != 0)
142 outb_p(0x1F, port
+SER_MODEM_CONTROL
);
143 if ((inb_p(port
+SER_MODEM_STATUS
) & 0xF0) != 0xF0)
145 outb_p(SER_MCR_DTR
| SER_MCR_RTS
, port
+ SER_MODEM_CONTROL
);
147 outb_p(0x55, port
+SER_SCRATCH
); /* Scratch-Register ?*/
148 if (inb_p(port
+SER_SCRATCH
) != 0x55)
150 outb_p(0, port
+SER_SCRATCH
);
152 outb_p(0xCF, port
+SER_FIFO
); /* FIFO ? */
153 if ((inb_p(port
+SER_IRQ_ID
) & 0xC0) != 0xC0)
155 outb_p(0, port
+SER_FIFO
);
156 /* Alternate-Function Register ? */
157 outb_p(SER_LCR_SETDIVISOR
, port
+SER_LINE_CONTROL
);
158 outb_p(0x07, port
+SER_2FUNCTION
);
159 if (inb_p(port
+SER_2FUNCTION
) != 0x07)
161 outb_p(0, port
+SER_LINE_CONTROL
);
162 return 4; //NS16550A;
164 outb_p(0, port
+SER_LINE_CONTROL
); /* reset registers */
165 outb_p(0, port
+SER_2FUNCTION
);
166 return 5; //NS16C552;
169 void ser_FIFOLevel(short port
, BYTE level
) {
172 outb_p(level
| SER_FIFO_ENABLE
, port
+SER_FIFO
);
174 outb_p(SER_FIFO_RESETRECEIVE
| SER_FIFO_RESETTRANSMIT
, port
+SER_FIFO
);
177 int ser_Init(short port
, LONG baudRate
, BYTE params
) {
180 if (ser_UARTType(port
)!=1)
182 uDivisor
=(WORD
)(SER_MAXBAUD
/ baudRate
);
183 outb_p(inb_p(port
+SER_LINE_CONTROL
) | SER_LCR_SETDIVISOR
, port
+SER_LINE_CONTROL
);
184 outb_p(uDivisor
& 0xFF, port
+SER_DIVISOR_LSB
);
185 outb_p(uDivisor
>>8, port
+SER_DIVISOR_MSB
);
186 outb_p(inb_p(port
+SER_LINE_CONTROL
) & ~SER_LCR_SETDIVISOR
, port
+SER_LINE_CONTROL
);
188 outb_p(params
, port
+SER_LINE_CONTROL
);
189 inb_p(port
+SER_TXBUFFER
);
195 int ser_WriteByte(short, UBYTE
, ULONG
, BYTE
, BYTE
);
196 int ser_IsWritingPossible(short);
199 AROS_LH1(void, SerialRawPutChar
,
202 AROS_LHA(UBYTE
, chr
, D0
),
205 struct ExecBase
*, SysBase
, 86, Exec
)
208 Emits a single character.
211 chr - The character to emit
217 This function is for very low level debugging only.
224 RawIOInit(), RawPutChar(), RawMayGetChar()
230 *****************************************************************************/
236 if ((__serial_rawio_port
> 0) && (chr
))
240 /* stegerg: Don't use Disable/Enable, because we want
241 interrupt enabled flag to stay the same as
242 it was before the Disable() call */
247 // Send <CR> before <LF>
248 ser_WriteByte(__serial_rawio_port
, 0x0D, 0, 0, 0);
250 ser_WriteByte(__serial_rawio_port
, chr
, 0, 0, 0);
252 /* Interrupt flag is stored in flags - if it was
253 enabled before, it will be renabled when the flags
255 __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
;