@@ -13,7 +13,7 @@ use utils::eventfd::EventFd;
13
13
14
14
use crate :: bus:: { BusDevice , RawIOHandler } ;
15
15
16
- const LOOP_SIZE : usize = 0x40 ;
16
+ const FIFO_SIZE : usize = 64 ;
17
17
18
18
const DATA : u8 = 0 ;
19
19
const IER : u8 = 1 ;
@@ -59,6 +59,7 @@ pub struct Serial {
59
59
interrupt_enable : u8 ,
60
60
interrupt_identification : u8 ,
61
61
interrupt_evt : EventFd ,
62
+ buffer_ready_evt : Option < EventFd > ,
62
63
line_control : u8 ,
63
64
line_status : u8 ,
64
65
modem_control : u8 ,
@@ -70,11 +71,16 @@ pub struct Serial {
70
71
}
71
72
72
73
impl Serial {
73
- fn new ( interrupt_evt : EventFd , out : Option < Box < dyn io:: Write + Send > > ) -> Serial {
74
+ fn new (
75
+ interrupt_evt : EventFd ,
76
+ buffer_ready_evt : Option < EventFd > ,
77
+ out : Option < Box < dyn io:: Write + Send > > ,
78
+ ) -> Serial {
74
79
Serial {
75
80
interrupt_enable : 0 ,
76
81
interrupt_identification : DEFAULT_INTERRUPT_IDENTIFICATION ,
77
82
interrupt_evt,
83
+ buffer_ready_evt,
78
84
line_control : DEFAULT_LINE_CONTROL ,
79
85
line_status : DEFAULT_LINE_STATUS ,
80
86
modem_control : DEFAULT_MODEM_CONTROL ,
@@ -87,13 +93,17 @@ impl Serial {
87
93
}
88
94
89
95
/// Constructs a Serial port ready for output.
90
- pub fn new_out ( interrupt_evt : EventFd , out : Box < dyn io:: Write + Send > ) -> Serial {
91
- Self :: new ( interrupt_evt, Some ( out) )
96
+ pub fn new_out (
97
+ interrupt_evt : EventFd ,
98
+ buffer_ready_evt : Option < EventFd > ,
99
+ out : Box < dyn io:: Write + Send > ,
100
+ ) -> Serial {
101
+ Self :: new ( interrupt_evt, buffer_ready_evt, Some ( out) )
92
102
}
93
103
94
104
/// Constructs a Serial port with no connected output.
95
- pub fn new_sink ( interrupt_evt : EventFd ) -> Serial {
96
- Self :: new ( interrupt_evt, None )
105
+ pub fn new_sink ( interrupt_evt : EventFd , buffer_ready_evt : Option < EventFd > ) -> Serial {
106
+ Self :: new ( interrupt_evt, buffer_ready_evt , None )
97
107
}
98
108
99
109
fn is_dlab_set ( & self ) -> bool {
@@ -160,7 +170,7 @@ impl Serial {
160
170
}
161
171
DATA => {
162
172
if self . is_loop ( ) {
163
- if self . in_buffer . len ( ) < LOOP_SIZE {
173
+ if self . in_buffer . len ( ) < FIFO_SIZE {
164
174
self . in_buffer . push_back ( value) ;
165
175
self . recv_data ( ) ?;
166
176
}
@@ -192,6 +202,12 @@ impl Serial {
192
202
self . del_intr_bit ( IIR_RECV_BIT ) ;
193
203
if self . in_buffer . len ( ) <= 1 {
194
204
self . line_status &= !LSR_DATA_BIT ;
205
+ if !self . is_loop ( ) && self . in_buffer . len ( ) == 1 {
206
+ if let Some ( evt) = self . buffer_ready_evt . as_ref ( ) {
207
+ evt. write ( 1 )
208
+ . expect ( "Couldn't signal that the serial device buffer is ready." ) ;
209
+ }
210
+ }
195
211
}
196
212
METRICS . uart . read_count . inc ( ) ;
197
213
self . in_buffer . pop_front ( ) . unwrap_or_default ( )
@@ -214,12 +230,27 @@ impl Serial {
214
230
215
231
impl RawIOHandler for Serial {
216
232
fn raw_input ( & mut self , data : & [ u8 ] ) -> io:: Result < ( ) > {
233
+ // Fail fast if the serial is serviced with more data than it can buffer.
234
+ if data. len ( ) > self . avail_buffer_capacity ( ) {
235
+ return Err ( io:: Error :: from_raw_os_error ( libc:: ENOBUFS ) ) ;
236
+ }
237
+
217
238
if !self . is_loop ( ) {
218
239
self . in_buffer . extend ( data) ;
219
240
self . recv_data ( ) ?;
220
241
}
221
242
Ok ( ( ) )
222
243
}
244
+
245
+ fn avail_buffer_capacity ( & mut self ) -> usize {
246
+ FIFO_SIZE . checked_sub ( self . in_buffer . len ( ) ) . unwrap_or_else ( ||
247
+ panic ! (
248
+ "Errored out due to serial device buffer size greater than the maximum expected size: {} > {}." ,
249
+ self . in_buffer. len( ) ,
250
+ FIFO_SIZE
251
+ )
252
+ )
253
+ }
223
254
}
224
255
225
256
impl BusDevice for Serial {
@@ -277,7 +308,7 @@ mod tests {
277
308
let intr_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
278
309
let serial_out = SharedBuffer :: new ( ) ;
279
310
280
- let mut serial = Serial :: new_out ( intr_evt, Box :: new ( serial_out. clone ( ) ) ) ;
311
+ let mut serial = Serial :: new_out ( intr_evt, None , Box :: new ( serial_out. clone ( ) ) ) ;
281
312
282
313
serial. write ( u64:: from ( DATA ) , & [ b'x' , b'y' ] ) ;
283
314
serial. write ( u64:: from ( DATA ) , & [ b'a' ] ) ;
@@ -289,14 +320,47 @@ mod tests {
289
320
) ;
290
321
}
291
322
323
+ #[ test]
324
+ fn test_serial_buffer_ready ( ) {
325
+ let intr_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
326
+ let buffer_ready_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
327
+ let serial_out = SharedBuffer :: new ( ) ;
328
+
329
+ let mut serial = Serial :: new_out (
330
+ intr_evt,
331
+ Some ( buffer_ready_evt. try_clone ( ) . unwrap ( ) ) ,
332
+ Box :: new ( serial_out. clone ( ) ) ,
333
+ ) ;
334
+
335
+ let byte = 5u8 ;
336
+ serial. in_buffer . push_back ( byte) ;
337
+ let mut _dummy = [ 0u8 ; 1 ] ;
338
+ serial. read ( DATA as u64 , & mut _dummy) ;
339
+ assert_eq ! ( serial. buffer_ready_evt. as_ref( ) . unwrap( ) . read( ) . unwrap( ) , 1 ) ;
340
+
341
+ let byte = 5u8 ;
342
+ serial. in_buffer . push_back ( byte) ;
343
+ serial. in_buffer . push_back ( byte) ;
344
+ serial. in_buffer . push_back ( byte) ;
345
+ serial. read ( DATA as u64 , & mut _dummy) ;
346
+ assert ! ( serial. buffer_ready_evt. as_ref( ) . unwrap( ) . read( ) . is_err( ) ) ;
347
+ serial. read ( DATA as u64 , & mut _dummy) ;
348
+ assert ! ( serial. buffer_ready_evt. as_ref( ) . unwrap( ) . read( ) . is_err( ) ) ;
349
+ serial. read ( DATA as u64 , & mut _dummy) ;
350
+ assert_eq ! ( serial. buffer_ready_evt. as_ref( ) . unwrap( ) . read( ) . unwrap( ) , 1 ) ;
351
+ }
352
+
292
353
#[ test]
293
354
fn serial_input ( ) {
294
355
let intr_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
295
356
let serial_out = SharedBuffer :: new ( ) ;
296
357
let mut buffer: Vec < u8 > = Vec :: with_capacity ( 16 ) ;
297
358
298
- let mut serial =
299
- Serial :: new_out ( intr_evt. try_clone ( ) . unwrap ( ) , Box :: new ( serial_out. clone ( ) ) ) ;
359
+ let mut serial = Serial :: new_out (
360
+ intr_evt. try_clone ( ) . unwrap ( ) ,
361
+ None ,
362
+ Box :: new ( serial_out. clone ( ) ) ,
363
+ ) ;
300
364
301
365
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
302
366
// counter doesn't change (for 0 it blocks)
@@ -325,12 +389,16 @@ mod tests {
325
389
// check if reading from the largest u8 offset returns 0
326
390
serial. read ( 0xff , & mut data[ ..] ) ;
327
391
assert_eq ! ( data[ 0 ] , 0 ) ;
392
+
393
+ // Check if the serial buffer can hold more than FIFO_SIZE bytes.
394
+ let bytes = vec ! [ 0u8 ; FIFO_SIZE + 1 ] ;
395
+ serial. raw_input ( bytes. as_slice ( ) ) . unwrap_err ( ) ;
328
396
}
329
397
330
398
#[ test]
331
399
fn serial_thr ( ) {
332
400
let intr_evt = EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ;
333
- let mut serial = Serial :: new_sink ( intr_evt. try_clone ( ) . unwrap ( ) ) ;
401
+ let mut serial = Serial :: new_sink ( intr_evt. try_clone ( ) . unwrap ( ) , None ) ;
334
402
335
403
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
336
404
// counter doesn't change (for 0 it blocks)
@@ -348,7 +416,7 @@ mod tests {
348
416
349
417
#[ test]
350
418
fn serial_dlab ( ) {
351
- let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ) ;
419
+ let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) , None ) ;
352
420
353
421
serial. write ( u64:: from ( LCR ) , & [ LCR_DLAB_BIT as u8 ] ) ;
354
422
serial. write ( u64:: from ( DLAB_LOW ) , & [ 0x12 as u8 ] ) ;
@@ -365,7 +433,7 @@ mod tests {
365
433
366
434
#[ test]
367
435
fn serial_modem ( ) {
368
- let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ) ;
436
+ let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) , None ) ;
369
437
370
438
serial. write ( u64:: from ( MCR ) , & [ MCR_LOOP_BIT as u8 ] ) ;
371
439
serial. write ( u64:: from ( DATA ) , & [ b'a' ] ) ;
@@ -387,7 +455,7 @@ mod tests {
387
455
388
456
#[ test]
389
457
fn serial_scratch ( ) {
390
- let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ) ;
458
+ let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) , None ) ;
391
459
392
460
serial. write ( u64:: from ( SCR ) , & [ 0x12 as u8 ] ) ;
393
461
@@ -399,7 +467,7 @@ mod tests {
399
467
#[ test]
400
468
fn test_serial_data_len ( ) {
401
469
const LEN : usize = 1 ;
402
- let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ) ;
470
+ let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) , None ) ;
403
471
404
472
let missed_writes_before = METRICS . uart . missed_write_count . count ( ) ;
405
473
// Trying to write data of length different than the one that we initialized the device with
@@ -414,4 +482,31 @@ mod tests {
414
482
// metric stays the same.
415
483
assert_eq ! ( missed_writes_before, missed_writes_after - 1 ) ;
416
484
}
485
+
486
+ #[ test]
487
+ fn test_serial_avail_buffer_capacity ( ) {
488
+ let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) , None ) ;
489
+
490
+ let bytes = vec ! [ 0u8 ; FIFO_SIZE ] ;
491
+ serial. in_buffer . extend ( bytes. clone ( ) ) ;
492
+ assert_eq ! ( serial. avail_buffer_capacity( ) , 0 ) ;
493
+
494
+ let mut data = [ 0u8 ; 1 ] ;
495
+ for i in 0 ..FIFO_SIZE {
496
+ assert_eq ! ( serial. avail_buffer_capacity( ) , i) ;
497
+ serial. read ( DATA as u64 , & mut data) ;
498
+ }
499
+ assert_eq ! ( serial. avail_buffer_capacity( ) , FIFO_SIZE ) ;
500
+ }
501
+
502
+ #[ test]
503
+ #[ should_panic]
504
+ fn test_serial_avail_buffer_capacity_overflow ( ) {
505
+ let mut serial = Serial :: new_sink ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) , None ) ;
506
+
507
+ let bytes = vec ! [ 0u8 ; FIFO_SIZE + 1 ] ;
508
+ serial. in_buffer . extend ( bytes) ;
509
+ // Panic since serial device buffer size its greater than what is expected.
510
+ serial. avail_buffer_capacity ( ) ;
511
+ }
417
512
}
0 commit comments