Skip to content

Commit dee947a

Browse files
authored
Merge pull request #1 from phil-opp/simplify_pr_15
Simplify cargo features by making `x86_64` a target-specific dependency
2 parents 11acb5b + 42b7c0d commit dee947a

File tree

4 files changed

+262
-262
lines changed

4 files changed

+262
-262
lines changed

Cargo.toml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ edition = "2018"
99

1010
[dependencies]
1111
bitflags = "1.1.0"
12-
x86_64 = { version = "0.14.0", default-features = false, features = ["instructions"], optional = true }
12+
13+
[target.'cfg(target_arch = "x86_64")'.dependencies]
14+
x86_64 = { version = "0.14.0", default-features = false, features = ["instructions"] }
1315

1416
[features]
15-
default = [ "port_nightly"]
16-
#default = [ "port", "nightly" ]
17-
port_stable = [ "x86_64/external_asm" ]
18-
port_nightly = [ "x86_64/inline_asm" ]
19-
mmio_stable = []
20-
mmio_nightly = []
17+
default = [ "nightly"]
18+
stable = [ "x86_64/external_asm" ]
19+
nightly = [ "x86_64/inline_asm" ]
2120

2221
[package.metadata.release]
2322
no-dev-version = true

src/lib.rs

Lines changed: 11 additions & 255 deletions
Original file line numberDiff line numberDiff line change
@@ -37,32 +37,12 @@
3737
3838
#![no_std]
3939
#![warn(missing_docs)]
40-
#![cfg_attr(feature = "mmio_nightly", feature(const_ptr_offset))]
41-
42-
use core::fmt;
40+
#![cfg_attr(feature = "nightly", feature(const_ptr_offset))]
4341

4442
use bitflags::bitflags;
4543

46-
#[cfg(any(
47-
all(
48-
not(any(feature = "port_stable", feature = "port_nightly")),
49-
not(any(feature = "mmio_stable", feature = "mmio_nightly"))
50-
),
51-
all(
52-
any(feature = "port_stable", feature = "port_nightly"),
53-
any(feature = "mmio_stable", feature = "mmio_nightly")
54-
)
55-
))]
56-
compile_error!("One of these features must be enabled: `port_{stable, nightly}`, `mmio_{stable, nightly}`");
57-
58-
#[cfg(any(feature = "mmio_stable", feature = "mmio_nightly"))]
59-
use core::sync::atomic::{
60-
AtomicPtr,
61-
Ordering,
62-
};
63-
64-
#[cfg(any(feature = "port_stable", feature = "port_nightly"))]
65-
use x86_64::instructions::port::Port;
44+
#[cfg(not(any(feature = "stable", feature = "nightly")))]
45+
compile_error!("Either the `stable` or `nightly` feature must be enabled");
6646

6747
macro_rules! wait_for {
6848
($cond:expr) => {
@@ -72,6 +52,14 @@ macro_rules! wait_for {
7252
};
7353
}
7454

55+
pub mod mmio;
56+
#[cfg(target_arch = "x86_64")]
57+
pub mod x86_64;
58+
59+
#[cfg(target_arch = "x86_64")]
60+
pub use crate::x86_64::SerialPort;
61+
pub use crate::mmio::MmioSerialPort;
62+
7563
bitflags! {
7664
/// Interrupt enable flags
7765
struct IntEnFlags: u8 {
@@ -92,235 +80,3 @@ bitflags! {
9280
// 6 and 7 unknown
9381
}
9482
}
95-
96-
#[cfg(any(feature = "port_stable", feature = "port_nightly"))]
97-
/// An interface to a serial port that allows sending out individual bytes.
98-
pub struct SerialPort {
99-
data: Port<u8>,
100-
int_en: Port<u8>,
101-
fifo_ctrl: Port<u8>,
102-
line_ctrl: Port<u8>,
103-
modem_ctrl: Port<u8>,
104-
line_sts: Port<u8>,
105-
}
106-
107-
#[cfg(any(feature = "port_stable", feature = "port_nightly"))]
108-
impl SerialPort {
109-
/// Creates a new serial port interface on the given I/O port.
110-
///
111-
/// This function is unsafe because the caller must ensure that the given base address
112-
/// really points to a serial port device.
113-
#[cfg(feature = "port_nightly")]
114-
pub const unsafe fn new(base: u16) -> Self {
115-
Self {
116-
data: Port::new(base),
117-
int_en: Port::new(base + 1),
118-
fifo_ctrl: Port::new(base + 2),
119-
line_ctrl: Port::new(base + 3),
120-
modem_ctrl: Port::new(base + 4),
121-
line_sts: Port::new(base + 5),
122-
}
123-
}
124-
125-
/// Creates a new serial port interface on the given I/O port.
126-
///
127-
/// This function is unsafe because the caller must ensure that the given base address
128-
/// really points to a serial port device.
129-
#[cfg(feature = "port_stable")]
130-
pub unsafe fn new(base: u16) -> Self {
131-
Self {
132-
data: Port::new(base),
133-
int_en: Port::new(base + 1),
134-
fifo_ctrl: Port::new(base + 2),
135-
line_ctrl: Port::new(base + 3),
136-
modem_ctrl: Port::new(base + 4),
137-
line_sts: Port::new(base + 5),
138-
}
139-
}
140-
141-
/// Initializes the serial port.
142-
///
143-
/// The default configuration of [38400/8-N-1](https://en.wikipedia.org/wiki/8-N-1) is used.
144-
pub fn init(&mut self) {
145-
unsafe {
146-
// Disable interrupts
147-
self.int_en.write(0x00);
148-
149-
// Enable DLAB
150-
self.line_ctrl.write(0x80);
151-
152-
// Set maximum speed to 38400 bps by configuring DLL and DLM
153-
self.data.write(0x03);
154-
self.int_en.write(0x00);
155-
156-
// Disable DLAB and set data word length to 8 bits
157-
self.line_ctrl.write(0x03);
158-
159-
// Enable FIFO, clear TX/RX queues and
160-
// set interrupt watermark at 14 bytes
161-
self.fifo_ctrl.write(0xC7);
162-
163-
// Mark data terminal ready, signal request to send
164-
// and enable auxilliary output #2 (used as interrupt line for CPU)
165-
self.modem_ctrl.write(0x0B);
166-
167-
// Enable interrupts
168-
self.int_en.write(0x01);
169-
}
170-
}
171-
172-
fn line_sts(&mut self) -> LineStsFlags {
173-
unsafe { LineStsFlags::from_bits_truncate(self.line_sts.read()) }
174-
}
175-
176-
/// Sends a byte on the serial port.
177-
pub fn send(&mut self, data: u8) {
178-
unsafe {
179-
match data {
180-
8 | 0x7F => {
181-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
182-
self.data.write(8);
183-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
184-
self.data.write(b' ');
185-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
186-
self.data.write(8)
187-
},
188-
_ => {
189-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
190-
self.data.write(data);
191-
},
192-
}
193-
}
194-
}
195-
196-
/// Receives a byte on the serial port.
197-
pub fn receive(&mut self) -> u8 {
198-
unsafe {
199-
wait_for!(self.line_sts().contains(LineStsFlags::INPUT_FULL));
200-
self.data.read()
201-
}
202-
}
203-
}
204-
205-
/// An interface to a serial port that allows sending out individual bytes.
206-
#[cfg(any(feature = "mmio_stable", feature = "mmio_nightly"))]
207-
pub struct MmioSerialPort {
208-
data: AtomicPtr<u8>,
209-
int_en: AtomicPtr<u8>,
210-
fifo_ctrl: AtomicPtr<u8>,
211-
line_ctrl: AtomicPtr<u8>,
212-
modem_ctrl: AtomicPtr<u8>,
213-
line_sts: AtomicPtr<u8>,
214-
}
215-
216-
#[cfg(any(feature = "mmio_stable", feature = "mmio_nightly"))]
217-
impl SerialPort {
218-
/// Creates a new serial port interface on the given memory mapped address.
219-
///
220-
/// This function is unsafe because the caller must ensure that the given base address
221-
/// really points to a serial port device.
222-
#[cfg(feature = "mmio_nightly")]
223-
pub const unsafe fn new(base: usize) -> Self {
224-
let base_pointer = base as *mut u8;
225-
Self {
226-
data: AtomicPtr::new(base_pointer),
227-
int_en: AtomicPtr::new(base_pointer.add(1)),
228-
fifo_ctrl: AtomicPtr::new(base_pointer.add(2)),
229-
line_ctrl: AtomicPtr::new(base_pointer.add(3)),
230-
modem_ctrl: AtomicPtr::new(base_pointer.add(4)),
231-
line_sts: AtomicPtr::new(base_pointer.add(5)),
232-
}
233-
}
234-
235-
#[cfg(feature = "mmio_stable")]
236-
pub unsafe fn new(base: usize) -> Self {
237-
let base_pointer = base as *mut u8;
238-
Self {
239-
data: AtomicPtr::new(base_pointer),
240-
int_en: AtomicPtr::new(base_pointer.add(1)),
241-
fifo_ctrl: AtomicPtr::new(base_pointer.add(2)),
242-
line_ctrl: AtomicPtr::new(base_pointer.add(3)),
243-
modem_ctrl: AtomicPtr::new(base_pointer.add(4)),
244-
line_sts: AtomicPtr::new(base_pointer.add(5)),
245-
}
246-
}
247-
248-
/// Initializes the serial port.
249-
///
250-
/// The default configuration of [38400/8-N-1](https://en.wikipedia.org/wiki/8-N-1) is used.
251-
pub fn init(&mut self) {
252-
let self_int_en = self.int_en.load(Ordering::Relaxed);
253-
let self_line_ctrl = self.line_ctrl.load(Ordering::Relaxed);
254-
let self_data = self.data.load(Ordering::Relaxed);
255-
let self_fifo_ctrl = self.fifo_ctrl.load(Ordering::Relaxed);
256-
let self_modem_ctrl = self.modem_ctrl.load(Ordering::Relaxed);
257-
unsafe {
258-
// Disable interrupts
259-
self_int_en.write(0x00);
260-
261-
// Enable DLAB
262-
self_line_ctrl.write(0x80);
263-
264-
// Set maximum speed to 38400 bps by configuring DLL and DLM
265-
self_data.write(0x03);
266-
self_int_en.write(0x00);
267-
268-
// Disable DLAB and set data word length to 8 bits
269-
self_line_ctrl.write(0x03);
270-
271-
// Enable FIFO, clear TX/RX queues and
272-
// set interrupt watermark at 14 bytes
273-
self_fifo_ctrl.write(0xC7);
274-
275-
// Mark data terminal ready, signal request to send
276-
// and enable auxilliary output #2 (used as interrupt line for CPU)
277-
self_modem_ctrl.write(0x0B);
278-
279-
// Enable interrupts
280-
self_int_en.write(0x01);
281-
}
282-
}
283-
284-
fn line_sts(&mut self) -> LineStsFlags {
285-
unsafe { LineStsFlags::from_bits_truncate(*self.line_sts.load(Ordering::Relaxed)) }
286-
}
287-
288-
/// Sends a byte on the serial port.
289-
pub fn send(&mut self, data: u8) {
290-
let self_data = self.data.load(Ordering::Relaxed);
291-
unsafe {
292-
match data {
293-
8 | 0x7F => {
294-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
295-
self_data.write(8);
296-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
297-
self_data.write(b' ');
298-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
299-
self_data.write(8)
300-
},
301-
_ => {
302-
wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY));
303-
self_data.write(data);
304-
},
305-
}
306-
}
307-
}
308-
309-
/// Receives a byte on the serial port.
310-
pub fn receive(&mut self) -> u8 {
311-
let self_data = self.data.load(Ordering::Relaxed);
312-
unsafe {
313-
wait_for!(self.line_sts().contains(LineStsFlags::INPUT_FULL));
314-
self_data.read()
315-
}
316-
}
317-
}
318-
319-
impl fmt::Write for SerialPort {
320-
fn write_str(&mut self, s: &str) -> fmt::Result {
321-
for byte in s.bytes() {
322-
self.send(byte);
323-
}
324-
Ok(())
325-
}
326-
}

0 commit comments

Comments
 (0)