8085 Architecture & Its Assembly language programming

Download Report

Transcript 8085 Architecture & Its Assembly language programming

Dr A Sahu
Dept of Comp Sc & Engg.
IIT Guwahati
• Character Device Driver
– Characteristics and functionality
– Basic IO functions
• Multi tasking (pre requisite to do this)
• Examples Drivers (in detail)
• ADC, Printer, Tape drive
$cd /dev/block/
$ ls –l
rwxrwxrwx 1 root root 7 2010-08-12 21:32 1:0 -> ../ram0
lrwxrwxrwx 1 root root 7 2010-08-12 21:32 1:1 -> ../ram1
# Formats, mounts, and sets permissions on my 16MB ramdisk
…
$/bin/mount /dev/ram0 /mnt/rd
lrwxrwxrwx 1 root root 8 2010-08-12 21:32 1:15 -> ../ram15
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 11:0 -> ../sr0
lrwxrwxrwx 1 root root 8 2010-08-13 03:02 7:0 -> ../loop0
lrwxrwxrwx 1 root root 8 2010-08-13 03:02 7:1 -> ../loop1
Mount –o loop CD.iso /mnt/cdrom
….
rwxrwxrwx 1 root root 8 2010-08-13 03:02 7:7 -> ../loop7
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 8:0 -> ../sda
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 8:1 -> ../sda1
….
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 8:5 -> ../sda5
$cd /dev/char/
$ ls –l
lrwxrwxrwx 1 root root 8 2010-08-13 03:02 10:144 -> ../nvram
lrwxrwxrwx 1 root root 15 2010-08-12 21:32 10:223 -> ../input/uinput
lrwxrwxrwx 1 root root 9 2010-08-13 03:02 10:227 -> ../mcelog
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 10:228 -> ../hpet
lrwxrwxrwx 1 root root 7 2010-08-12 21:33 10:229 -> ../fuse
lrwxrwxrwx 1 root root 11 2010-08-13 03:02 10:231 -> ../snapshot
lrwxrwxrwx 1 root root 6 2010-08-12 21:32 10:232 -> ../kvm
lrwxrwxrwx 1 root root 13 2010-08-12 21:32 10:57 -> ../vboxnetctl
lrwxrwxrwx 1 root root 10 2010-08-12 21:32 10:58 -> ../vboxdrv
lrwxrwxrwx 1 root root 21 2010-08-13 03:02 10:59 -> ../network_throughput
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 10:60 -> ../network_latency
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 10:61 -> ../cpu_dma_latency
lrwxrwxrwx 1 root root 17 2010-08-13 03:02 10:62 -> ../mapper/control
lrwxrwxrwx 1 root root 14 2010-08-13 03:02 10:63 -> ../vga_arbiter
$cd /dev/char/
$ ls –l
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 1:1 -> ../mem
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 1:11 -> ../kmsg
lrwxrwxrwx 1 root root 9 2010-08-13 03:02 1:12 -> ../oldmem
lrwxrwxrwx 1 root root 15 2010-10-06 22:42 116:10 -> ../snd/pcmC1D0c
lrwxrwxrwx 1 root root 16 2010-10-06 22:42 116:11 -> ../snd/controlC1
lrwxrwxrwx 1 root root 12 2010-08-12 21:32 116:2 -> ../snd/timer
lrwxrwxrwx 1 root root 10 2010-08-12 21:32 116:3 -> ../snd/seq
lrwxrwxrwx 1 root root 15 2010-08-12 21:32 116:4 -> ../snd/pcmC0D1p
lrwxrwxrwx 1 root root 15 2010-08-12 21:32 116:5 -> ../snd/pcmC0D0p
lrwxrwxrwx 1 root root 15 2010-08-12 21:32 116:6 -> ../snd/pcmC0D0c
lrwxrwxrwx 1 root root 13 2010-08-12 21:32 116:7 -> ../snd/hwC0D3
lrwxrwxrwx 1 root root 16 2010-08-12 21:32 116:8 -> ../snd/controlC0
lrwxrwxrwx 1 root root 15 2010-10-06 22:42 116:9 -> ../snd/pcmC1D0p
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 1:3 -> ../null
lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:32 -> ../input/mouse0
lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:33 -> ../input/mouse1
lrwxrwxrwx 1 root root 13 2010-08-13 03:02 13:63 -> ../input/mice
$cd /dev/char/
$ ls –l
lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:64 -> ../input/event0
lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:65 -> ../input/event1
lrwxrwxrwx 1 root root 15 2010-08-13 03:02 13:66 -> ../input/event2
rwxrwxrwx 1 root root 13 2010-08-13 03:02 162:0 -> ../raw/rawctl
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 1:7 -> ../full
lrwxrwxrwx 1 root root 9 2010-08-13 03:02 1:8 -> ../random
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:0 -> ../bus/usb/001/001
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:128 -> ../bus/usb/002/001
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:256 -> ../bus/usb/003/001
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:384 -> ../bus/usb/004/001
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:512 -> ../bus/usb/005/001
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:513 -> ../bus/usb/005/002
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:640 -> ../bus/usb/006/001
lrwxrwxrwx 1 root root 18 2010-10-06 22:42 189:649 -> ../bus/usb/006/010
lrwxrwxrwx 1 root root 18 2010-08-13 03:02 189:768 -> ../bus/usb/007/001
lrwxrwxrwx 1 root root 10 2010-08-13 03:02 1:9 -> ../urandom
lrwxrwxrwx 1 root root 12 2010-08-13 03:02 202:0 -> ../cpu/0/msr
lrwxrwxrwx 1 root root 12 2010-08-13 03:02 202:1 -> ../cpu/1/msr
lrwxrwxrwx 1 root root 12 2010-08-13 03:02 202:2 -> ../cpu/2/msr
lrwxrwxrwx 1 root root 14 2010-08-13 03:02 203:0 -> ../cpu/0/cpuid
lrwxrwxrwx 1 root root 14 2010-08-13 03:02 203:1 -> ../cpu/1/cpuid
lrwxrwxrwx 1 root root 14 2010-08-13 03:02 203:2 -> ../cpu/2/cpuid
$cd /dev/char/
$ ls –l
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 21:0 -> ../sg0
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 21:1 -> ../sg1
lrwxrwxrwx 1 root root 12 2010-08-13 03:02 226:0 -> ../dri/card0
lrwxrwxrwx 1 root root 17 2010-08-13 03:02 226:64 -> ../dri/controlD64
lrwxrwxrwx 1 root root 10 2010-08-13 03:02 250:0 -> ../hidraw0
lrwxrwxrwx 1 root root 10 2010-10-06 22:42 250:1 -> ../hidraw1
lrwxrwxrwx 1 root root 10 2010-08-13 03:02 251:0 -> ../usbmon0
…
lrwxrwxrwx 1 root root 10 2010-08-13 03:02 251:7 -> ../usbmon7
lrwxrwxrwx 1 root root 14 2010-08-13 03:02 252:0 -> ../bsg/0:0:0:0
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 254:0 -> ../rtc0
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 29:0 -> ../fb0
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 4:0 -> ../tty0
…
lrwxrwxrwx 1 root root 8 2010-08-13 03:02 4:38 -> ../tty38
lrwxrwxrwx 1 root root 10 2010-08-13 03:02 5:1 -> ../console
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 5:2 -> ../ptmx
lrwxrwxrwx 1 root root 6 2010-08-13 03:02 7:0 -> ../vcs
..
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 7:1 -> ../vcs6
lrwxrwxrwx 1 root root 7 2010-08-13 03:02 7:128 -> ../vcsa..
lrwxrwxrwx 1 root root 8 2010-08-12 21:32 7:134 -> ../vcsa6
lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:2 -> ../vcs2
lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:3 -> ../vcs3
lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:4 -> ../vcs4
lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:5 -> ../vcs5
lrwxrwxrwx 1 root root 7 2010-08-12 21:32 7:6 -> ../vcs6
lrwxrwxrwx 1 root root 11 2010-08-12 21:32 99:0 -> ../parport0
Device-driver LKM layout
module’s ‘payload’
is a collection of
callback-functions
having prescribed
prototypes
function
function
function
fops
...
the usual pair of
module-administration
functions
AND
a ‘package’ of
function-pointers
init
registers the ‘fops’
exit
unregisters the ‘fops’
• Character device drivers normally perform I/O
in a byte stream.
• Examples of devices using character drivers
include tape drives and serial ports.
• Character device drivers can also provide
additional interfaces not present in block
drivers,
– I/O control (ioctl) commands
– memory mapping
– device polling.
int open( char *pathname, int flags, … );
int read( int fd, void *buf, size_t count );
int write( int fd, void *buf, size_t count );
int lseek( int fd, loff_t offset, int whence );
int close( int fd );
(and other less-often-used file-I/O functions)
root# mknod /dev/cmos c 70 0
Read /dev/cmos as a FILE
• Modern operating systems allow multiple
users to share a computer’s resources
• Users are allowed to run multiple tasks
• The OS kernel must protect each task from
interference by other tasks, while allowing
every task to take its turn using some of the
processor’s available time
• To manage multitasking, the OS needs to use a
data-structure which can keep track of every
task’s progress and usage of the computer’s
available resources (physical memory, open
files, pending signals, etc.)
• Such a data-structure is called a ‘process
descriptor’ – every active task needs one
• Every task needs its own ‘private’ stack
Upon entering ‘main()’:
• A program’s exit-address is on user stack
• Command-line arguments on user stack
• Environment variables are on user stack
During execution of ‘main()’:
• Function parameters and return-addresses
• Storage locations for ‘automatic’ variables
A user process enters ‘kernel-mode’:
• when it decides to execute a system-call
• when it is ‘interrupted’ (e.g. by the timer)
• when ‘exceptions’ occur (e.g. divide by 0)
• Entering kernel-mode involves not only a
‘privilege-level transition’ (from level 3 to level
0), but also a stack-area ‘switch’
• This is necessary for robustness:
e.g., user-mode stack might be exhausted
• This is desirable for security:
e.g, privileged data might be accessible
Upon entering kernel-mode:
• task’s registers are saved on kernel stack
(e.g., address of task’s user-mode stack)
During execution of kernel functions:
• Function parameters and return-addresses
• Storage locations for ‘automatic’ variables
• So every task, in addition to having its own
code and data, will also have a stack-area that
is located in user-space, plus another stackarea that is located in kernel-space
• Each task also has a process-descriptor which
is accessible only in kernel-space
Privilege-level 0
Kernel space
User-mode stack-area
User space
Privilege-level 3
Shared runtime-libraries
Task’s code and data
process descriptor
and
kernel-mode stack
pagedir[]
task_struct
Each process
descriptor
contains many
fields
and some are
pointers to
other kernel
structures
which may
themselves
include fields
that point to
structures
state
*stack
flags
mm_struct
*pgd
*mm
exit_code
user_struct
*user
pid
files_struct
*files
*parent
*signal
signal_struct
• Linux uses part of a task’s kernel-stack
page-frame to store ‘thread information’
• The thread-info includes a pointer to the task’s
process-descriptor data-structure
Task’s kernel-stack
struct task_struct
Task’s
process-descriptor
8-KB
Task’s thread-info
page-frame aligned
From kernel-header: <linux/sched.h>
•
•
•
•
•
•
•
#define TASK_RUNNING
#define TASK_INTERRUPTIBLE
#define TASK_UNINTERRUPTIBLE
#define TASK_STOPPED
#define TASK_TRACED
#define TASK_NONINTERACTIVE
#define TASK_DEAD
0
1
2
4
8
64
128
struct task_struct
{
volatile long
state;
void
*stack;
unsigned long
flags;
struct mm_struct
*mm;
struct thread_struct
*thread;
pid_t
pid;
char
comm[16];
/* plus many other fields */
};
• During a task’s execution in kernel-mode, it’s very
quick to find that task’s thread-info object
• Just use two assembly-language instructions:
movl
andl
$0xFFFFF000, %eax
%esp, %eax
Ok, now %eax = the thread-info’s base-address
There’s a macro that implements this computation
• Use a macro ‘task_thread_info( task )’ to get a
pointer to the ‘thread_info’ structure:
struct thread_info *info = task_thread_info( task );
• Then one more step gets you back to the
address of the task’s process-descriptor:
struct task_struct *task = info->task;
•
•
•
•
•
Kernel keeps a list of process descriptors
A ‘doubly-linked’ circular list is used
The ‘init_task’ serves as a fixed header
Other tasks inserted/deleted dynamically
Tasks have forward & backward pointers,
implemented as fields in the ‘tasks’ field
• To go forward: task = next_task( task );
• To go backward: task = prev_task( task );
next_task
init_task
(pid=0)
prev_task
…
newest
task
• We can’t know ahead of time how many tasks
are active in our system – this will depend on
many varying factors, such as who else is
logged in, which commands have been issued,
whether we’re using text-mode console or
graphical desktop
• So it’s perfectly possible our pseudo-file might
‘overflow’ its kernel-supplied buffer!
• Our module’s ‘get_info()’ callback-function has four
parameter-values passed to it by the kernel:
•
•
•
•
char *buf
char **start
off_t offset
int
buflen
- address of a small kernel buffer
- address of a pointer variable
- current offset of file-pointer
- size of the kernel buffer
• The initial conditions are:
offset == 0 and *start == NULL
• Kernel’s behavior will vary if we modify *start
• We expect the ‘/proc’ file to deliver a small
amount of text-data (not more than would fit
in the kernel-supplied buffer (e.g., 3KB)
• So we make no change to ‘*start’
• Then kernel will deliver the data it finds in the
buffer it had supplied to ‘get_info()’
• The kernel will not call ‘get_info()’ again
(unless our file is closed and reopened)
• Our ‘get_info()’ function modifies the value of
the (initially NULL) ‘*start’ pointer – for
example, maybe assigning it the address of
some buffer we’ve allocated, or even assigning
the address of the kernel-buffer:
*start = buf;
• In this case, the kernel will again call our
module’s ‘get_info()’ function, provided we
returned a nonzero function-value before!
• Knowing about this alternative option, we can
design our ‘get_info()’ function so that it
delivers a big amount of data in several smallsize chunks, never overflowing the sizelimitations on the kernel’s buffer
• We just need to think carefully about the
differing senarios under which ‘get_info()’ will
be repeatedly called
• The value of ‘offset’ will be zero
• We set *start to a buffer-address where we
place a positive number of data-bytes
• Kernel delivers those bytes to the ‘reader’,
taking them from the *start address, then
advances the file-pointer by that amount
• Kernel calls our ‘get_info()’ again, but with a
non-zero ‘offset’ value this time!
• When our ‘get_info()’ function has finally
finished delivering all the desired data to the
file’s ‘reader’, and still we receive yet another
‘get_info()’ call, then we simply return a
function-value equal to zero, telling the kernel
that the data has been exhausted -- and so not
to call again!
struct task_struct
*task;
// ‘global’ variables’ values remembered
int my_get_info( char *buf, char **start, off_t offset, int buflen )
{
int
len = 0;
if ( offset == 0 )
// our first time through this function
{
task = &init_task;
// start of circular linked-list
}
else if ( task == &init_task ) return 0; // our final pass
// put some data into the kernel-supplied buffer
len += sprintf( buf+len, “pid=%d \n”, task->pid );
*start = buf;
// tell kernel where to find data, and to call again
task = next_task( task );
return len;
}
// advance to next node of circular list
// and tell kernel how far to advance
• Some tasks don’t have a page-directory of
their own – because they don’t need one
• They only execute code, and access data, that
resides in the kernel’s address space
• They can just ‘borrow’ the page-directory that
belongs to another task
• These ‘kernel thread’ tasks will store the
NULL-pointer value (i.e., zero) in the ‘mm’
field of their ‘task_struct’ descriptor
(mm:mem map)