tty driver
Notes
- 内核启动 arch/x86/kernel/setup.c 中间存在对于 IO 端口的硬编码来确定到底给谁使用。
- 即使是已经端口被注册了,但是还是可以使用为该端口注册 irq。
- 一共申请的资源为 :
- 设备号 : …
- 中断号 : register_irq
- io 端口 : request_region
- file->private 的作用
https://en.wikipedia.org/wiki/COM_(hardware_interface)
device address port is hard coded !
During the initialization function (init_module()), or in the function that opens the device, interrupts must be activated for the device. This operation is dependent on the device, but most often involves setting a bit from the control register.
Because the interrupt handlers run in interrupt context the actions that can be performed are limited: unable to access user space memory, can’t call blocking functions. Also synchronization using spinlocks is tricky and can lead to deadlocks if the spinlock used is already acquired by a process that has been interrupted by the running handler.
IFF you know that the spinlocks are never used in interrupt handlers, you can use the non-irq versions.
If we want to disable interrupts at the interrupt controller level (not recommended because disabling a particular interrupt is slower, we can not disable shared interrupts) we can do this with disable_irq(), disable_irq_nosync(), and enable_irq(). Using these functions will disable the interrupts on all processors.
https://stackoverflow.com/questions/5934402/can-an-interrupt-handler-be-preempted All irqs are not disabled by default only the same irq is disabled on all processors. but with flags in request_irq, you can disable all other interrupts on local processor while serving the interrupt.
The KeyBoard driver is really intesting :
- Keyboard initialization function i8042_setup_kbd()
- The AT or PS/2 keyboard interrupt function atkbd_interrupt()
static int __init i8042_setup_kbd(void)
{
int error;
error = i8042_create_kbd_port();
if (error)
return error;
error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED,
"i8042", i8042_platform_device);
if (error)
goto err_free_port;
error = i8042_enable_kbd_port(); // tell the device, everything is ok, start working now !
if (error)
goto err_free_irq;
i8042_kbd_irq_registered = true;
return 0;
err_free_irq:
free_irq(I8042_KBD_IRQ, i8042_platform_device);
err_free_port:
i8042_free_kbd_port();
return error;
}
/*
* i8042_interrupt() is the most important function in this driver -
* it handles the interrupts from the i8042, and sends incoming bytes
* to the upper layers.
*/
static irqreturn_t i8042_interrupt(int irq, void *dev_id)
// /home/shen/Core/linux/drivers/input/serio/i8042.c
// XXX although very important, but it's fairly simple
// read data by i8042_read_data
static inline int i8042_read_data(void)
{
return inb(I8042_DATA_REG);
}
struct serio_driver { // todo so, what's the relation between serio_driver and keyboard ?
const char *description;
const struct serio_device_id *id_table;
bool manual_bind;
void (*write_wakeup)(struct serio *);
irqreturn_t (*interrupt)(struct serio *, unsigned char, unsigned int);
int (*connect)(struct serio *, struct serio_driver *drv);
int (*reconnect)(struct serio *);
int (*fast_reconnect)(struct serio *);
void (*disconnect)(struct serio *);
void (*cleanup)(struct serio *);
struct device_driver driver;
};
Exercise
Let us do more thinking before fulfill the simple task :
- register_chrdev_region
- cdev_init
- cdev_add
why we have to register char device,
本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。