COMPLETE.TXT
资源名称:os_source.zip [点击查看]
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:2565k
源码类别:
操作系统开发
开发平台:
C/C++
- 25157 register struct proc *rp; /* current head of held queue */
- 25158
- 25159 if (switching) return;
- 25160 rp = held_head;
- 25161 do {
- 25162 if ( (held_head = rp->p_nextheld) == NIL_PROC) held_tail = NIL_PROC;
- 25163 rp->p_int_held = FALSE;
- 25164 unlock(); /* reduce latency; held queue may change! */
- 25165 interrupt(proc_number(rp));
- 25166 lock(); /* protect the held queue again */
- 25167 }
- 25168 while ( (rp = held_head) != NIL_PROC);
- 25169 }
- 25171 #if (CHIP == M68000)
- 25172 /*==========================================================================*
- 25173 * cp_mess *
- 25174 *==========================================================================*/
- 25175 PRIVATE void cp_mess(src, src_p, src_m, dst_p, dst_m)
- 25176 int src; /* sender process */
- 25177 register struct proc *src_p; /* source proc entry */
- 25178 message *src_m; /* source message */
- 25179 register struct proc *dst_p; /* destination proc entry */
- 25180 message *dst_m; /* destination buffer */
- 25181 {
- 25182 #if (SHADOWING == 0)
- 25183 /* convert virtual address to physical address */
- 25184 /* The caller has already checked if all addresses are within bounds */
- 25185
- 25186 src_m = (message *)((char *)src_m + (((phys_bytes)src_p->p_map[D].mem_phys
- 25187 - src_p->p_map[D].mem_vir) << CLICK_SHIFT));
- 25188 dst_m = (message *)((char *)dst_m + (((phys_bytes)dst_p->p_map[D].mem_phys
- 25189 - dst_p->p_map[D].mem_vir) << CLICK_SHIFT));
- 25190 #else
- 25191 register phys_bytes correction;
- 25192
- 25193 if (correction = src_p->p_shadow) {
- 25194 correction = (correction - src_p->p_map[D].mem_phys) << CLICK_SHIFT;
- 25195 src_m = (message *)((char *)src_m + correction);
- 25196 }
- 25197 if (correction = dst_p->p_shadow) {
- 25198 correction = (correction - dst_p->p_map[D].mem_phys) << CLICK_SHIFT;
- 25199 dst_m = (message *)((char *)dst_m + correction);
- 25200 }
- 25201 #endif
- 25202 #ifdef NEEDFSTRUCOPY
- 25203 phys_copy(src_m,dst_m,(phys_bytes) sizeof(message));
- 25204 #else
- 25205 *dst_m = *src_m;
- 25206 #endif
- 25207 dst_m->m_source = src;
- 25208 }
- 25209 #endif
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/protect.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 25300 /* This file contains code for initialization of protected mode, to initialize
- 25301 * code and data segment descriptors, and to initialize global descriptors
- 25302 * for local descriptors in the process table.
- 25303 */
- 25304
- 25305 #include "kernel.h"
- 25306 #include "proc.h"
- 25307 #include "protect.h"
- 25308
- 25309 #if _WORD_SIZE == 4
- 25310 #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
- 25311 #define TSS_TYPE (AVL_286_TSS | DESC_386_BIT)
- 25312 #else
- 25313 #define INT_GATE_TYPE INT_286_GATE
- 25314 #define TSS_TYPE AVL_286_TSS
- 25315 #endif
- 25316
- 25317 struct desctableptr_s {
- 25318 char limit[sizeof(u16_t)];
- 25319 char base[sizeof(u32_t)]; /* really u24_t + pad for 286 */
- 25320 };
- 25321
- 25322 struct gatedesc_s {
- 25323 u16_t offset_low;
- 25324 u16_t selector;
- 25325 u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
- 25326 u8_t p_dpl_type; /* |P|DL|0|TYPE| */
- 25327 #if _WORD_SIZE == 4
- 25328 u16_t offset_high;
- 25329 #else
- 25330 u16_t reserved;
- 25331 #endif
- 25332 };
- 25333
- 25334 struct tss_s {
- 25335 reg_t backlink;
- 25336 reg_t sp0; /* stack pointer to use during interrupt */
- 25337 reg_t ss0; /* " segment " " " " */
- 25338 reg_t sp1;
- 25339 reg_t ss1;
- 25340 reg_t sp2;
- 25341 reg_t ss2;
- 25342 #if _WORD_SIZE == 4
- 25343 reg_t cr3;
- 25344 #endif
- 25345 reg_t ip;
- 25346 reg_t flags;
- 25347 reg_t ax;
- 25348 reg_t cx;
- 25349 reg_t dx;
- 25350 reg_t bx;
- 25351 reg_t sp;
- 25352 reg_t bp;
- 25353 reg_t si;
- 25354 reg_t di;
- 25355 reg_t es;
- 25356 reg_t cs;
- 25357 reg_t ss;
- 25358 reg_t ds;
- 25359 #if _WORD_SIZE == 4
- 25360 reg_t fs;
- 25361 reg_t gs;
- 25362 #endif
- 25363 reg_t ldt;
- 25364 #if _WORD_SIZE == 4
- 25365 u16_t trap;
- 25366 u16_t iobase;
- 25367 /* u8_t iomap[0]; */
- 25368 #endif
- 25369 };
- 25370
- 25371 PUBLIC struct segdesc_s gdt[GDT_SIZE];
- 25372 PRIVATE struct gatedesc_s idt[IDT_SIZE]; /* zero-init so none present */
- 25373 PUBLIC struct tss_s tss; /* zero init */
- 25374
- 25375 FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, phys_bytes base,
- 25376 unsigned dpl_type) );
- 25377 FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
- 25378 phys_bytes size) );
- 25379
- 25380 /*=========================================================================*
- 25381 * prot_init *
- 25382 *=========================================================================*/
- 25383 PUBLIC void prot_init()
- 25384 {
- 25385 /* Set up tables for protected mode.
- 25386 * All GDT slots are allocated at compile time.
- 25387 */
- 25388
- 25389 phys_bytes code_bytes;
- 25390 phys_bytes data_bytes;
- 25391 struct gate_table_s *gtp;
- 25392 struct desctableptr_s *dtp;
- 25393 unsigned ldt_selector;
- 25394 register struct proc *rp;
- 25395
- 25396 static struct gate_table_s {
- 25397 _PROTOTYPE( void (*gate), (void) );
- 25398 unsigned char vec_nr;
- 25399 unsigned char privilege;
- 25400 }
- 25401 gate_table[] = {
- 25402 divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE,
- 25403 single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE,
- 25404 nmi, NMI_VECTOR, INTR_PRIVILEGE,
- 25405 breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE,
- 25406 overflow, OVERFLOW_VECTOR, USER_PRIVILEGE,
- 25407 bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE,
- 25408 inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE,
- 25409 copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE,
- 25410 double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE,
- 25411 copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE,
- 25412 inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE,
- 25413 segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE,
- 25414 stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE,
- 25415 general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE,
- 25416 #if _WORD_SIZE == 4
- 25417 page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE,
- 25418 copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE,
- 25419 #endif
- 25420 { hwint00, VECTOR( 0), INTR_PRIVILEGE },
- 25421 { hwint01, VECTOR( 1), INTR_PRIVILEGE },
- 25422 { hwint02, VECTOR( 2), INTR_PRIVILEGE },
- 25423 { hwint03, VECTOR( 3), INTR_PRIVILEGE },
- 25424 { hwint04, VECTOR( 4), INTR_PRIVILEGE },
- 25425 { hwint05, VECTOR( 5), INTR_PRIVILEGE },
- 25426 { hwint06, VECTOR( 6), INTR_PRIVILEGE },
- 25427 { hwint07, VECTOR( 7), INTR_PRIVILEGE },
- 25428 { hwint08, VECTOR( 8), INTR_PRIVILEGE },
- 25429 { hwint09, VECTOR( 9), INTR_PRIVILEGE },
- 25430 { hwint10, VECTOR(10), INTR_PRIVILEGE },
- 25431 { hwint11, VECTOR(11), INTR_PRIVILEGE },
- 25432 { hwint12, VECTOR(12), INTR_PRIVILEGE },
- 25433 { hwint13, VECTOR(13), INTR_PRIVILEGE },
- 25434 { hwint14, VECTOR(14), INTR_PRIVILEGE },
- 25435 { hwint15, VECTOR(15), INTR_PRIVILEGE },
- 25436 };
- 25437
- 25438 /* This is called early and can't use tables set up by main(). */
- 25439 data_bytes = (phys_bytes) sizes[1] << CLICK_SHIFT;
- 25440 if (sizes[0] == 0)
- 25441 code_bytes = data_bytes; /* common I&D */
- 25442 else
- 25443 code_bytes = (phys_bytes) sizes[0] << CLICK_SHIFT;
- 25444
- 25445 /* Build gdt and idt pointers in GDT where the BIOS expects them. */
- 25446 dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];
- 25447 * (u16_t *) dtp->limit = (sizeof gdt) - 1;
- 25448 * (u32_t *) dtp->base = vir2phys(gdt);
- 25449
- 25450 dtp= (struct desctableptr_s *) &gdt[IDT_INDEX];
- 25451 * (u16_t *) dtp->limit = (sizeof idt) - 1;
- 25452 * (u32_t *) dtp->base = vir2phys(idt);
- 25453
- 25454 /* Build segment descriptors for tasks and interrupt handlers. */
- 25455 init_codeseg(&gdt[CS_INDEX], code_base, code_bytes, INTR_PRIVILEGE);
- 25456 init_dataseg(&gdt[DS_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
- 25457 init_dataseg(&gdt[ES_INDEX], 0L, 0L, TASK_PRIVILEGE);
- 25458
- 25459 /* Build scratch descriptors for functions in klib88. */
- 25460 init_dataseg(&gdt[DS_286_INDEX], (phys_bytes) 0,
- 25461 (phys_bytes) MAX_286_SEG_SIZE, TASK_PRIVILEGE);
- 25462 init_dataseg(&gdt[ES_286_INDEX], (phys_bytes) 0,
- 25463 (phys_bytes) MAX_286_SEG_SIZE, TASK_PRIVILEGE);
- 25464
- 25465 /* Build local descriptors in GDT for LDT's in process table.
- 25466 * The LDT's are allocated at compile time in the process table, and
- 25467 * initialized whenever a process' map is initialized or changed.
- 25468 */
- 25469 for (rp = BEG_PROC_ADDR, ldt_selector = FIRST_LDT_INDEX * DESC_SIZE;
- 25470 rp < END_PROC_ADDR; ++rp, ldt_selector += DESC_SIZE) {
- 25471 init_dataseg(&gdt[ldt_selector / DESC_SIZE], vir2phys(rp->p_ldt),
- 25472 (phys_bytes) sizeof rp->p_ldt, INTR_PRIVILEGE);
- 25473 gdt[ldt_selector / DESC_SIZE].access = PRESENT | LDT;
- 25474 rp->p_ldt_sel = ldt_selector;
- 25475 }
- 25476
- 25477 /* Build main TSS.
- 25478 * This is used only to record the stack pointer to be used after an
- 25479 * interrupt.
- 25480 * The pointer is set up so that an interrupt automatically saves the
- 25481 * current process's registers ip:cs:f:sp:ss in the correct slots in the
- 25482 * process table.
- 25483 */
- 25484 tss.ss0 = DS_SELECTOR;
- 25485 init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), (phys_bytes) sizeof tss,
- 25486 INTR_PRIVILEGE);
- 25487 gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE;
- 25488
- 25489 /* Build descriptors for interrupt gates in IDT. */
- 25490 for (gtp = &gate_table[0];
- 25491 gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) {
- 25492 int_gate(gtp->vec_nr, (phys_bytes) (vir_bytes) gtp->gate,
- 25493 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
- 25494 }
- 25495 int_gate(SYS_VECTOR, (phys_bytes) (vir_bytes) p_s_call,
- 25496 PRESENT | (USER_PRIVILEGE << DPL_SHIFT) | INT_GATE_TYPE);
- 25497 int_gate(LEVEL0_VECTOR, (phys_bytes) (vir_bytes) level0_call,
- 25498 PRESENT | (TASK_PRIVILEGE << DPL_SHIFT) | INT_GATE_TYPE);
- 25499
- 25500 #if _WORD_SIZE == 4
- 25501 /* Complete building of main TSS. */
- 25502 tss.iobase = sizeof tss; /* empty i/o permissions map */
- 25503
- 25504 /* Complete building of interrupt gates. */
- 25505 int_gate(SYS386_VECTOR, (phys_bytes) (vir_bytes) s_call,
- 25506 PRESENT | (USER_PRIVILEGE << DPL_SHIFT) | INT_GATE_TYPE);
- 25507 #endif
- 25508 }
- 25510 /*=========================================================================*
- 25511 * init_codeseg *
- 25512 *=========================================================================*/
- 25513 PUBLIC void init_codeseg(segdp, base, size, privilege)
- 25514 register struct segdesc_s *segdp;
- 25515 phys_bytes base;
- 25516 phys_bytes size;
- 25517 int privilege;
- 25518 {
- 25519 /* Build descriptor for a code segment. */
- 25520
- 25521 sdesc(segdp, base, size);
- 25522 segdp->access = (privilege << DPL_SHIFT)
- 25523 | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
- 25524 /* CONFORMING = 0, ACCESSED = 0 */
- 25525 }
- 25527 /*=========================================================================*
- 25528 * init_dataseg *
- 25529 *=========================================================================*/
- 25530 PUBLIC void init_dataseg(segdp, base, size, privilege)
- 25531 register struct segdesc_s *segdp;
- 25532 phys_bytes base;
- 25533 phys_bytes size;
- 25534 int privilege;
- 25535 {
- 25536 /* Build descriptor for a data segment. */
- 25537
- 25538 sdesc(segdp, base, size);
- 25539 segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
- 25540 /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
- 25541 }
- 25543 /*=========================================================================*
- 25544 * sdesc *
- 25545 *=========================================================================*/
- 25546 PRIVATE void sdesc(segdp, base, size)
- 25547 register struct segdesc_s *segdp;
- 25548 phys_bytes base;
- 25549 phys_bytes size;
- 25550 {
- 25551 /* Fill in the size fields (base, limit and granularity) of a descriptor. */
- 25552
- 25553 segdp->base_low = base;
- 25554 segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
- 25555
- 25556 #if _WORD_SIZE == 4
- 25557 segdp->base_high = base >> BASE_HIGH_SHIFT;
- 25558 --size; /* convert to a limit, 0 size means 4G */
- 25559 if (size > BYTE_GRAN_MAX) {
- 25560 segdp->limit_low = size >> PAGE_GRAN_SHIFT;
- 25561 segdp->granularity = GRANULAR | (size >>
- 25562 (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
- 25563 } else {
- 25564 segdp->limit_low = size;
- 25565 segdp->granularity = size >> GRANULARITY_SHIFT;
- 25566 }
- 25567 segdp->granularity |= DEFAULT; /* means BIG for data seg */
- 25568 #else
- 25569 segdp->limit_low = size - 1;
- 25570 #endif
- 25571 }
- 25573 /*=========================================================================*
- 25574 * seg2phys *
- 25575 *=========================================================================*/
- 25576 PUBLIC phys_bytes seg2phys(seg)
- 25577 U16_t seg;
- 25578 {
- 25579 /* Return the base address of a segment, with seg being either a 8086 segment
- 25580 * register, or a 286/386 segment selector.
- 25581 */
- 25582 phys_bytes base;
- 25583 struct segdesc_s *segdp;
- 25584
- 25585 if (!protected_mode) {
- 25586 base = hclick_to_physb(seg);
- 25587 } else {
- 25588 segdp = &gdt[seg >> 3];
- 25589 base = segdp->base_low | ((u32_t) segdp->base_middle << 16);
- 25590 #if _WORD_SIZE == 4
- 25591 base |= ((u32_t) segdp->base_high << 24);
- 25592 #endif
- 25593 }
- 25594 return base;
- 25595 }
- 25597 /*=========================================================================*
- 25598 * int_gate *
- 25599 *=========================================================================*/
- 25600 PRIVATE void int_gate(vec_nr, base, dpl_type)
- 25601 unsigned vec_nr;
- 25602 phys_bytes base;
- 25603 unsigned dpl_type;
- 25604 {
- 25605 /* Build descriptor for an interrupt gate. */
- 25606
- 25607 register struct gatedesc_s *idp;
- 25608
- 25609 idp = &idt[vec_nr];
- 25610 idp->offset_low = base;
- 25611 idp->selector = CS_SELECTOR;
- 25612 idp->p_dpl_type = dpl_type;
- 25613 #if _WORD_SIZE == 4
- 25614 idp->offset_high = base >> OFFSET_HIGH_SHIFT;
- 25615 #endif
- 25616 }
- 25618 /*=========================================================================*
- 25619 * enable_iop *
- 25620 *=========================================================================*/
- 25621 PUBLIC void enable_iop(pp)
- 25622 struct proc *pp;
- 25623 {
- 25624 /* Allow a user process to use I/O instructions. Change the I/O Permission
- 25625 * Level bits in the psw. These specify least-privileged Current Permission
- 25626 * Level allowed to execute I/O instructions. Users and servers have CPL 3.
- 25627 * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
- 25628 */
- 25629 pp->p_reg.psw |= 0x3000;
- 25630 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/pty.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 25700 /* pty.c - pseudo terminal driver Author: Kees J. Bot
- 25701 * 30 Dec 1995
- 25702 * PTYs can be seen as a bidirectional pipe with TTY
- 25703 * input and output processing. For example a simple rlogin session:
- 25704 *
- 25705 * keyboard -> rlogin -> in.rld -> /dev/ptypX -> /dev/ttypX -> shell
- 25706 * shell -> /dev/ttypX -> /dev/ptypX -> in.rld -> rlogin -> screen
- 25707 *
- 25708 * This file takes care of copying data between the tty/pty device pairs and
- 25709 * the open/read/write/close calls on the pty devices. The TTY task takes
- 25710 * care of the input and output processing (interrupt, backspace, raw I/O,
- 25711 * etc.) using the pty_read() and pty_write() functions as the "keyboard" and
- 25712 * "screen" functions of the ttypX devices.
- 25713 * Be careful when reading this code, the terms "reading" and "writing" are
- 25714 * used both for the tty and the pty end of the pseudo tty. Writes to one
- 25715 * end are to be read at the other end and vice-versa.
- 25716 */
- 25717
- 25718 #include "kernel.h"
- 25719 #include <termios.h>
- 25720 #include <signal.h>
- 25721 #include <minix/com.h>
- 25722 #include <minix/callnr.h>
- 25723 #include "tty.h"
- 25724 #include "proc.h"
- 25725
- 25726 #if NR_PTYS > 0
- 25727
- 25728 /* PTY bookkeeping structure, one per pty/tty pair. */
- 25729 typedef struct pty {
- 25730 tty_t *tty; /* associated TTY structure */
- 25731 char state; /* flags: busy, closed, ... */
- 25732
- 25733 /* Read call on /dev/ptypX. */
- 25734 char rdrepcode; /* reply code, TASK_REPLY or REVIVE */
- 25735 char rdcaller; /* process making the call (usually FS) */
- 25736 char rdproc; /* process that wants to read from the pty */
- 25737 vir_bytes rdvir; /* virtual address in readers address space */
- 25738 int rdleft; /* # bytes yet to be read */
- 25739 int rdcum; /* # bytes written so far */
- 25740
- 25741 /* Write call to /dev/ptypX. */
- 25742 char wrrepcode; /* reply code, TASK_REPLY or REVIVE */
- 25743 char wrcaller; /* process making the call (usually FS) */
- 25744 char wrproc; /* process that wants to write to the pty */
- 25745 vir_bytes wrvir; /* virtual address in writers address space */
- 25746 int wrleft; /* # bytes yet to be written */
- 25747 int wrcum; /* # bytes written so far */
- 25748
- 25749 /* Output buffer. */
- 25750 int ocount; /* # characters in the buffer */
- 25751 char *ohead, *otail; /* head and tail of the circular buffer */
- 25752 char obuf[128]; /* buffer for bytes going to the pty reader */
- 25753 } pty_t;
- 25754
- 25755 #define PTY_ACTIVE 0x01 /* pty is open/active */
- 25756 #define TTY_CLOSED 0x02 /* tty side has closed down */
- 25757 #define PTY_CLOSED 0x04 /* pty side has closed down */
- 25758
- 25759 PRIVATE pty_t pty_table[NR_PTYS]; /* PTY bookkeeping */
- 25760
- 25761
- 25762 FORWARD _PROTOTYPE( void pty_write, (tty_t *tp) );
- 25763 FORWARD _PROTOTYPE( void pty_echo, (tty_t *tp, int c) );
- 25764 FORWARD _PROTOTYPE( void pty_start, (pty_t *pp) );
- 25765 FORWARD _PROTOTYPE( void pty_finish, (pty_t *pp) );
- 25766 FORWARD _PROTOTYPE( void pty_read, (tty_t *tp) );
- 25767 FORWARD _PROTOTYPE( void pty_close, (tty_t *tp) );
- 25768 FORWARD _PROTOTYPE( void pty_icancel, (tty_t *tp) );
- 25769 FORWARD _PROTOTYPE( void pty_ocancel, (tty_t *tp) );
- 25770
- 25771
- 25772 /*==========================================================================*
- 25773 * do_pty *
- 25774 *==========================================================================*/
- 25775 PUBLIC void do_pty(tp, m_ptr)
- 25776 tty_t *tp;
- 25777 message *m_ptr;
- 25778 {
- 25779 /* Perform an open/close/read/write call on a /dev/ptypX device. */
- 25780 pty_t *pp = tp->tty_priv;
- 25781 int r;
- 25782
- 25783 switch (m_ptr->m_type) {
- 25784 case DEV_READ:
- 25785 /* Check, store information on the reader, do I/O. */
- 25786 if (pp->state & TTY_CLOSED) {
- 25787 r = 0;
- 25788 break;
- 25789 }
- 25790 if (pp->rdleft != 0) {
- 25791 r = EIO;
- 25792 break;
- 25793 }
- 25794 if (m_ptr->COUNT <= 0) {
- 25795 r = EINVAL;
- 25796 break;
- 25797 }
- 25798 if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 25799 m_ptr->COUNT) == 0) {
- 25800 r = EFAULT;
- 25801 break;
- 25802 }
- 25803 pp->rdrepcode = TASK_REPLY;
- 25804 pp->rdcaller = m_ptr->m_source;
- 25805 pp->rdproc = m_ptr->PROC_NR;
- 25806 pp->rdvir = (vir_bytes) m_ptr->ADDRESS;
- 25807 pp->rdleft = m_ptr->COUNT;
- 25808 pty_start(pp);
- 25809 handle_events(tp);
- 25810 if (pp->rdleft == 0) return; /* already done */
- 25811
- 25812 if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
- 25813 r = EAGAIN; /* don't suspend */
- 25814 pp->rdleft = pp->rdcum = 0;
- 25815 } else {
- 25816 r = SUSPEND; /* do suspend */
- 25817 pp->rdrepcode = REVIVE;
- 25818 }
- 25819 break;
- 25820
- 25821 case DEV_WRITE:
- 25822 /* Check, store information on the writer, do I/O. */
- 25823 if (pp->state & TTY_CLOSED) {
- 25824 r = EIO;
- 25825 break;
- 25826 }
- 25827 if (pp->wrleft != 0) {
- 25828 r = EIO;
- 25829 break;
- 25830 }
- 25831 if (m_ptr->COUNT <= 0) {
- 25832 r = EINVAL;
- 25833 break;
- 25834 }
- 25835 if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 25836 m_ptr->COUNT) == 0) {
- 25837 r = EFAULT;
- 25838 break;
- 25839 }
- 25840 pp->wrrepcode = TASK_REPLY;
- 25841 pp->wrcaller = m_ptr->m_source;
- 25842 pp->wrproc = m_ptr->PROC_NR;
- 25843 pp->wrvir = (vir_bytes) m_ptr->ADDRESS;
- 25844 pp->wrleft = m_ptr->COUNT;
- 25845 handle_events(tp);
- 25846 if (pp->wrleft == 0) return; /* already done */
- 25847
- 25848 if (m_ptr->TTY_FLAGS & O_NONBLOCK) { /* don't suspend */
- 25849 r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
- 25850 pp->wrleft = pp->wrcum = 0;
- 25851 } else {
- 25852 pp->wrrepcode = REVIVE; /* do suspend */
- 25853 r = SUSPEND;
- 25854 }
- 25855 break;
- 25856
- 25857 case DEV_IOCTL:
- 25858 /* No ioctl's allowed on the pty side. */
- 25859 r = ENOTTY;
- 25860 break;
- 25861
- 25862 case DEV_OPEN:
- 25863 r = pp->state != 0 ? EIO : OK;
- 25864 pp->state |= PTY_ACTIVE;
- 25865 break;
- 25866
- 25867 case DEV_CLOSE:
- 25868 r = OK;
- 25869 if (pp->state & TTY_CLOSED) {
- 25870 pp->state = 0;
- 25871 } else {
- 25872 pp->state |= PTY_CLOSED;
- 25873 sigchar(tp, SIGHUP);
- 25874 }
- 25875 break;
- 25876
- 25877 case CANCEL:
- 25878 if (m_ptr->PROC_NR == pp->rdproc) {
- 25879 /* Cancel a read from a PTY. */
- 25880 pp->rdleft = pp->rdcum = 0;
- 25881 }
- 25882 if (m_ptr->PROC_NR == pp->wrproc) {
- 25883 /* Cancel a write to a PTY. */
- 25884 pp->wrleft = pp->wrcum = 0;
- 25885 }
- 25886 r = EINTR;
- 25887 break;
- 25888
- 25889 default:
- 25890 r = EINVAL;
- 25891 }
- 25892 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
- 25893 }
- 25896 /*==========================================================================*
- 25897 * pty_write *
- 25898 *==========================================================================*/
- 25899 PRIVATE void pty_write(tp)
- 25900 tty_t *tp;
- 25901 {
- 25902 /* (*dev_write)() routine for PTYs. Transfer bytes from the writer on
- 25903 * /dev/ttypX to the output buffer.
- 25904 */
- 25905 pty_t *pp = tp->tty_priv;
- 25906 int count, ocount;
- 25907 phys_bytes user_phys;
- 25908
- 25909 /* PTY closed down? */
- 25910 if (pp->state & PTY_CLOSED) {
- 25911 if (tp->tty_outleft > 0) {
- 25912 tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
- 25913 tp->tty_outproc, EIO);
- 25914 tp->tty_outleft = tp->tty_outcum = 0;
- 25915 }
- 25916 return;
- 25917 }
- 25918
- 25919 /* While there is something to do. */
- 25920 for (;;) {
- 25921 ocount = buflen(pp->obuf) - pp->ocount;
- 25922 count = bufend(pp->obuf) - pp->ohead;
- 25923 if (count > ocount) count = ocount;
- 25924 if (count > tp->tty_outleft) count = tp->tty_outleft;
- 25925 if (count == 0 || tp->tty_inhibited) break;
- 25926
- 25927 /* Copy from user space to the PTY output buffer. */
- 25928 user_phys = proc_vir2phys(proc_addr(tp->tty_outproc), tp->tty_out_vir);
- 25929 phys_copy(user_phys, vir2phys(pp->ohead), (phys_bytes) count);
- 25930
- 25931 /* Perform output processing on the output buffer. */
- 25932 out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
- 25933 if (count == 0) break;
- 25934
- 25935 /* Assume echoing messed up by output. */
- 25936 tp->tty_reprint = TRUE;
- 25937
- 25938 /* Bookkeeping. */
- 25939 pp->ocount += ocount;
- 25940 if ((pp->ohead += ocount) >= bufend(pp->obuf))
- 25941 pp->ohead -= buflen(pp->obuf);
- 25942 pty_start(pp);
- 25943 tp->tty_out_vir += count;
- 25944 tp->tty_outcum += count;
- 25945 if ((tp->tty_outleft -= count) == 0) {
- 25946 /* Output is finished, reply to the writer. */
- 25947 tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
- 25948 tp->tty_outproc, tp->tty_outcum);
- 25949 tp->tty_outcum = 0;
- 25950 }
- 25951 }
- 25952 pty_finish(pp);
- 25953 }
- 25956 /*==========================================================================*
- 25957 * pty_echo *
- 25958 *==========================================================================*/
- 25959 PRIVATE void pty_echo(tp, c)
- 25960 tty_t *tp;
- 25961 int c;
- 25962 {
- 25963 /* Echo one character. (Like pty_write, but only one character, optionally.) */
- 25964
- 25965 pty_t *pp = tp->tty_priv;
- 25966 int count, ocount;
- 25967
- 25968 ocount = buflen(pp->obuf) - pp->ocount;
- 25969 if (ocount == 0) return; /* output buffer full */
- 25970 count = 1;
- 25971 *pp->ohead = c; /* add one character */
- 25972
- 25973 out_process(tp, pp->obuf, pp->ohead, bufend(pp->obuf), &count, &ocount);
- 25974 if (count == 0) return;
- 25975
- 25976 pp->ocount += ocount;
- 25977 if ((pp->ohead += ocount) >= bufend(pp->obuf)) pp->ohead -= buflen(pp->obuf);
- 25978 pty_start(pp);
- 25979 }
- 25982 /*==========================================================================*
- 25983 * pty_start *
- 25984 *==========================================================================*/
- 25985 PRIVATE void pty_start(pp)
- 25986 pty_t *pp;
- 25987 {
- 25988 /* Transfer bytes written to the output buffer to the PTY reader. */
- 25989 int count;
- 25990 phys_bytes user_phys;
- 25991
- 25992 /* While there are things to do. */
- 25993 for (;;) {
- 25994 count = bufend(pp->obuf) - pp->otail;
- 25995 if (count > pp->ocount) count = pp->ocount;
- 25996 if (count > pp->rdleft) count = pp->rdleft;
- 25997 if (count == 0) break;
- 25998
- 25999 /* Copy from the output buffer to the readers address space. */
- 26000 user_phys = proc_vir2phys(proc_addr(pp->rdproc), pp->rdvir);
- 26001 phys_copy(vir2phys(pp->otail), user_phys, (phys_bytes) count);
- 26002
- 26003 /* Bookkeeping. */
- 26004 pp->ocount -= count;
- 26005 if ((pp->otail += count) == bufend(pp->obuf)) pp->otail = pp->obuf;
- 26006 pp->rdvir += count;
- 26007 pp->rdcum += count;
- 26008 pp->rdleft -= count;
- 26009 }
- 26010 }
- 26013 /*==========================================================================*
- 26014 * pty_finish *
- 26015 *==========================================================================*/
- 26016 PRIVATE void pty_finish(pp)
- 26017 pty_t *pp;
- 26018 {
- 26019 /* Finish the read request of a PTY reader if there is at least one byte
- 26020 * transferred.
- 26021 */
- 26022
- 26023 if (pp->rdcum > 0) {
- 26024 tty_reply(pp->rdrepcode, pp->rdcaller, pp->rdproc, pp->rdcum);
- 26025 pp->rdleft = pp->rdcum = 0;
- 26026 }
- 26027 }
- 26030 /*==========================================================================*
- 26031 * pty_read *
- 26032 *==========================================================================*/
- 26033 PRIVATE void pty_read(tp)
- 26034 tty_t *tp;
- 26035 {
- 26036 /* Offer bytes from the PTY writer for input on the TTY. (Do it one byte at
- 26037 * a time, 99% of the writes will be for one byte, so no sense in being smart.)
- 26038 */
- 26039 pty_t *pp = tp->tty_priv;
- 26040 phys_bytes user_phys;
- 26041 char c;
- 26042
- 26043 if (pp->state & PTY_CLOSED) {
- 26044 if (tp->tty_inleft > 0) {
- 26045 tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
- 26046 tp->tty_incum);
- 26047 tp->tty_inleft = tp->tty_incum = 0;
- 26048 }
- 26049 return;
- 26050 }
- 26051
- 26052 while (pp->wrleft > 0) {
- 26053 /* Transfer one character to 'c'. */
- 26054 user_phys = proc_vir2phys(proc_addr(pp->wrproc), pp->wrvir);
- 26055 phys_copy(user_phys, vir2phys(&c), 1L);
- 26056
- 26057 /* Input processing. */
- 26058 if (in_process(tp, &c, 1) == 0) break;
- 26059
- 26060 /* PTY writer bookkeeping. */
- 26061 pp->wrvir++;
- 26062 pp->wrcum++;
- 26063 if (--pp->wrleft == 0) {
- 26064 tty_reply(pp->wrrepcode, pp->wrcaller, pp->wrproc, pp->wrcum);
- 26065 pp->wrcum = 0;
- 26066 }
- 26067 }
- 26068 }
- 26071 /*==========================================================================*
- 26072 * pty_close *
- 26073 *==========================================================================*/
- 26074 PRIVATE void pty_close(tp)
- 26075 tty_t *tp;
- 26076 {
- 26077 /* The tty side has closed, so shut down the pty side. */
- 26078 pty_t *pp = tp->tty_priv;
- 26079
- 26080 if (!(pp->state & PTY_ACTIVE)) return;
- 26081
- 26082 if (pp->rdleft > 0) {
- 26083 tty_reply(pp->rdrepcode, pp->rdcaller, pp->rdproc, 0);
- 26084 pp->rdleft = pp->rdcum = 0;
- 26085 }
- 26086
- 26087 if (pp->wrleft > 0) {
- 26088 tty_reply(pp->wrrepcode, pp->wrcaller, pp->wrproc, EIO);
- 26089 pp->wrleft = pp->wrcum = 0;
- 26090 }
- 26091
- 26092 if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;
- 26093 }
- 26096 /*==========================================================================*
- 26097 * pty_icancel *
- 26098 *==========================================================================*/
- 26099 PRIVATE void pty_icancel(tp)
- 26100 tty_t *tp;
- 26101 {
- 26102 /* Discard waiting input. */
- 26103 pty_t *pp = tp->tty_priv;
- 26104
- 26105 if (pp->wrleft > 0) {
- 26106 tty_reply(pp->wrrepcode, pp->wrcaller, pp->wrproc,
- 26107 pp->wrcum + pp->wrleft);
- 26108 pp->wrleft = pp->wrcum = 0;
- 26109 }
- 26110 }
- 26113 /*==========================================================================*
- 26114 * pty_ocancel *
- 26115 *==========================================================================*/
- 26116 PRIVATE void pty_ocancel(tp)
- 26117 tty_t *tp;
- 26118 {
- 26119 /* Drain the output buffer. */
- 26120 pty_t *pp = tp->tty_priv;
- 26121
- 26122 pp->ocount = 0;
- 26123 pp->otail = pp->ohead;
- 26124 }
- 26127 /*==========================================================================*
- 26128 * pty_init *
- 26129 *==========================================================================*/
- 26130 PUBLIC void pty_init(tp)
- 26131 tty_t *tp;
- 26132 {
- 26133 pty_t *pp;
- 26134 int line;
- 26135
- 26136 /* Associate PTY and TTY structures. */
- 26137 line = tp - &tty_table[NR_CONS + NR_RS_LINES];
- 26138 pp = tp->tty_priv = &pty_table[line];
- 26139 pp->tty = tp;
- 26140
- 26141 /* Set up output queue. */
- 26142 pp->ohead = pp->otail = pp->obuf;
- 26143
- 26144 /* Fill in TTY function hooks. */
- 26145 tp->tty_devread = pty_read;
- 26146 tp->tty_devwrite = pty_write;
- 26147 tp->tty_echo = pty_echo;
- 26148 tp->tty_icancel = pty_icancel;
- 26149 tp->tty_ocancel = pty_ocancel;
- 26150 tp->tty_close = pty_close;
- 26151 }
- 26152 #endif /* NR_PTYS > 0 */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/rs232.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 26200 /*==========================================================================*
- 26201 * rs232.c - serial driver for 8250 and 16450 UARTs *
- 26202 * Added support for Atari ST M68901 and YM-2149 --kub *
- 26203 *==========================================================================*/
- 26204
- 26205 #include "kernel.h"
- 26206 #include <termios.h>
- 26207 #include <signal.h>
- 26208 #include "tty.h"
- 26209 #include "proc.h"
- 26210
- 26211 #if NR_RS_LINES > 0
- 26212
- 26213 #if (MACHINE != IBM_PC) && (MACHINE != ATARI)
- 26214 #error /* rs232.c only supports PC and Atari ST */
- 26215 #endif
- 26216
- 26217 #if (MACHINE == ATARI)
- 26218 #include "staddr.h"
- 26219 #include "stsound.h"
- 26220 #include "stmfp.h"
- 26221 #if (NR_RS_LINES > 1)
- 26222 #error /* Only one physical RS232 line available */
- 26223 #endif
- 26224 #endif
- 26225
- 26226 #if (MACHINE == IBM_PC) /* PC/AT 8250/16450 chip combination */
- 26227
- 26228 /* 8250 constants. */
- 26229 #define UART_FREQ 115200L /* timer frequency */
- 26230
- 26231 /* Interrupt enable bits. */
- 26232 #define IE_RECEIVER_READY 1
- 26233 #define IE_TRANSMITTER_READY 2
- 26234 #define IE_LINE_STATUS_CHANGE 4
- 26235 #define IE_MODEM_STATUS_CHANGE 8
- 26236
- 26237 /* Interrupt status bits. */
- 26238 #define IS_MODEM_STATUS_CHANGE 0
- 26239 #define IS_TRANSMITTER_READY 2
- 26240 #define IS_RECEIVER_READY 4
- 26241 #define IS_LINE_STATUS_CHANGE 6
- 26242
- 26243 /* Line control bits. */
- 26244 #define LC_2STOP_BITS 0x04
- 26245 #define LC_PARITY 0x08
- 26246 #define LC_PAREVEN 0x10
- 26247 #define LC_BREAK 0x40
- 26248 #define LC_ADDRESS_DIVISOR 0x80
- 26249
- 26250 /* Line status bits. */
- 26251 #define LS_OVERRUN_ERR 2
- 26252 #define LS_PARITY_ERR 4
- 26253 #define LS_FRAMING_ERR 8
- 26254 #define LS_BREAK_INTERRUPT 0x10
- 26255 #define LS_TRANSMITTER_READY 0x20
- 26256
- 26257 /* Modem control bits. */
- 26258 #define MC_DTR 1
- 26259 #define MC_RTS 2
- 26260 #define MC_OUT2 8 /* required for PC & AT interrupts */
- 26261
- 26262 /* Modem status bits. */
- 26263 #define MS_CTS 0x10
- 26264 #define MS_RLSD 0x80 /* Received Line Signal Detect */
- 26265 #define MS_DRLSD 0x08 /* RLSD Delta */
- 26266
- 26267 #else /* MACHINE == ATARI */ /* Atari ST 68901 USART */
- 26268
- 26269 /* Most of the USART constants are already defined in stmfp.h . The local
- 26270 * definitions made here are for keeping C code changes smaller. --kub
- 26271 */
- 26272
- 26273 #define UART_FREQ 19200L /* timer frequency */
- 26274
- 26275 /* Line status bits. */
- 26276 #define LS_OVERRUN_ERR R_OE
- 26277 #define LS_PARITY_ERR R_PE
- 26278 #define LS_FRAMING_ERR R_FE
- 26279 #define LS_BREAK_INTERRUPT R_BREAK
- 26280
- 26281 /* Modem status bits. */
- 26282 #define MS_CTS IO_SCTS /* 0x04 */
- 26283
- 26284 #endif /* MACHINE == ATARI */
- 26285
- 26286 #define DATA_BITS_SHIFT 8 /* amount data bits shifted in mode */
- 26287 #define DEF_BAUD 1200 /* default baud rate */
- 26288
- 26289 #define RS_IBUFSIZE 1024 /* RS232 input buffer size */
- 26290 #define RS_OBUFSIZE 1024 /* RS232 output buffer size */
- 26291
- 26292 /* Input buffer watermarks.
- 26293 * The external device is asked to stop sending when the buffer
- 26294 * exactly reaches high water, or when TTY requests it. Sending restarts
- 26295 * when the input buffer empties below the low watermark.
- 26296 */
- 26297 #define RS_ILOWWATER (1 * RS_IBUFSIZE / 4)
- 26298 #define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
- 26299
- 26300 /* Output buffer low watermark.
- 26301 * TTY is notified when the output buffer empties below the low watermark, so
- 26302 * it may continue filling the buffer if doing a large write.
- 26303 */
- 26304 #define RS_OLOWWATER (1 * RS_OBUFSIZE / 4)
- 26305
- 26306 #if (MACHINE == IBM_PC)
- 26307
- 26308 /* Macros to handle flow control.
- 26309 * Interrupts must be off when they are used.
- 26310 * Time is critical - already the function call for out_byte() is annoying.
- 26311 * If out_byte() can be done in-line, tests to avoid it can be dropped.
- 26312 * istart() tells external device we are ready by raising RTS.
- 26313 * istop() tells external device we are not ready by dropping RTS.
- 26314 * DTR is kept high all the time (it probably should be raised by open and
- 26315 * dropped by close of the device).
- 26316 * OUT2 is also kept high all the time.
- 26317 */
- 26318 #define istart(rs)
- 26319 (out_byte((rs)->modem_ctl_port, MC_OUT2 | MC_RTS | MC_DTR),
- 26320 (rs)->idevready = TRUE)
- 26321 #define istop(rs)
- 26322 (out_byte((rs)->modem_ctl_port, MC_OUT2 | MC_DTR),
- 26323 (rs)->idevready = FALSE)
- 26324
- 26325 /* Macro to tell if device is ready. The rs->cts field is set to MS_CTS if
- 26326 * CLOCAL is in effect for a line without a CTS wire.
- 26327 */
- 26328 #define devready(rs) ((in_byte(rs->modem_status_port) | rs->cts) & MS_CTS)
- 26329
- 26330 /* Macro to tell if transmitter is ready. */
- 26331 #define txready(rs) (in_byte(rs->line_status_port) & LS_TRANSMITTER_READY)
- 26332
- 26333 /* Macro to tell if carrier has dropped.
- 26334 * The RS232 Carrier Detect (CD) line is usually connected to the 8250
- 26335 * Received Line Signal Detect pin, reflected by bit MS_RLSD in the Modem
- 26336 * Status Register. The MS_DRLSD bit tells if MS_RLSD has just changed state.
- 26337 * So if MS_DRLSD is set and MS_RLSD cleared, we know that carrier has just
- 26338 * dropped.
- 26339 */
- 26340 #define devhup(rs)
- 26341 (in_byte(rs->modem_status_port) & (MS_RLSD|MS_DRLSD) == MS_DRLSD)
- 26342
- 26343 #else /* MACHINE == ATARI */
- 26344
- 26345 /* Macros to handle flow control.
- 26346 * Time is critical - already the function call for lock()/restore() is
- 26347 * annoying.
- 26348 * istart() tells external device we are ready by raising RTS.
- 26349 * istop() tells external device we are not ready by dropping RTS.
- 26350 * DTR is kept high all the time (it probably should be raised by open and
- 26351 * dropped by close of the device). NOTE: The modem lines are active low.
- 26352 */
- 26353 #define set_porta(msk,val) { register int s = lock();
- 26354 SOUND->sd_selr = YM_IOA;
- 26355 SOUND->sd_wdat =
- 26356 SOUND->sd_rdat & (msk) | (val);
- 26357 restore(s); }
- 26358 #define istart(rs) { set_porta( ~(PA_SRTS|PA_SDTR),0 );
- 26359 (rs)->idevready = TRUE; }
- 26360 #define istop(rs) { set_porta( ~PA_SDTR, PA_SRTS );
- 26361 (rs)->idevready = FALSE; }
- 26362
- 26363 /* Macro to tell if device is ready. The rs->cts field is set to MS_CTS if
- 26364 * CLOCAL is in effect for a line without a CTS wire.
- 26365 */
- 26366 #define devready(rs) ((~MFP->mf_gpip | rs->cts) & MS_CTS)
- 26367
- 26368 /* Transmitter ready test */
- 26369 #define txready(rs) (MFP->mf_tsr & (T_EMPTY | T_UE))
- 26370
- 26371 #endif /* MACHINE == ATARI */
- 26372
- 26373 /* Types. */
- 26374 typedef unsigned char bool_t; /* boolean */
- 26375
- 26376 /* RS232 device structure, one per device. */
- 26377 typedef struct rs232 {
- 26378 tty_t *tty; /* associated TTY structure */
- 26379
- 26380 int icount; /* number of bytes in the input buffer */
- 26381 char *ihead; /* next free spot in input buffer */
- 26382 char *itail; /* first byte to give to TTY */
- 26383 bool_t idevready; /* nonzero if we are ready to receive (RTS) */
- 26384 char cts; /* normally 0, but MS_CTS if CLOCAL is set */
- 26385
- 26386 unsigned char ostate; /* combination of flags: */
- 26387 #define ODONE 1 /* output completed (< output enable bits) */
- 26388 #define ORAW 2 /* raw mode for xoff disable (< enab. bits) */
- 26389 #define OWAKEUP 4 /* tty_wakeup() pending (asm code only) */
- 26390 #define ODEVREADY MS_CTS /* external device hardware ready (CTS) */
- 26391 #define OQUEUED 0x20 /* output buffer not empty */
- 26392 #define OSWREADY 0x40 /* external device software ready (no xoff) */
- 26393 #define ODEVHUP MS_RLSD /* external device has dropped carrier */
- 26394 #define OSOFTBITS (ODONE | ORAW | OWAKEUP | OQUEUED | OSWREADY)
- 26395 /* user-defined bits */
- 26396 #if (OSOFTBITS | ODEVREADY | ODEVHUP) == OSOFTBITS
- 26397 /* a weak sanity check */
- 26398 #error /* bits are not unique */
- 26399 #endif
- 26400 unsigned char oxoff; /* char to stop output */
- 26401 bool_t inhibited; /* output inhibited? (follows tty_inhibited) */
- 26402 bool_t drain; /* if set drain output and reconfigure line */
- 26403 int ocount; /* number of bytes in the output buffer */
- 26404 char *ohead; /* next free spot in output buffer */
- 26405 char *otail; /* next char to output */
- 26406
- 26407 #if (MACHINE == IBM_PC)
- 26408 port_t xmit_port; /* i/o ports */
- 26409 port_t recv_port;
- 26410 port_t div_low_port;
- 26411 port_t div_hi_port;
- 26412 port_t int_enab_port;
- 26413 port_t int_id_port;
- 26414 port_t line_ctl_port;
- 26415 port_t modem_ctl_port;
- 26416 port_t line_status_port;
- 26417 port_t modem_status_port;
- 26418 #endif
- 26419
- 26420 unsigned char lstatus; /* last line status */
- 26421 unsigned char pad; /* ensure alignment for 16-bit ints */
- 26422 unsigned framing_errors; /* error counts (no reporting yet) */
- 26423 unsigned overrun_errors;
- 26424 unsigned parity_errors;
- 26425 unsigned break_interrupts;
- 26426
- 26427 char ibuf[RS_IBUFSIZE]; /* input buffer */
- 26428 char obuf[RS_OBUFSIZE]; /* output buffer */
- 26429 } rs232_t;
- 26430
- 26431 PUBLIC rs232_t rs_lines[NR_RS_LINES];
- 26432
- 26433 /* Table and macro to translate an RS232 line number to its rs_lines entry. */
- 26434 PRIVATE rs232_t *p_rs_addr[NR_RS_LINES];
- 26435
- 26436 #define rs_addr(line) (p_rs_addr[line])
- 26437
- 26438 #if (MACHINE == IBM_PC)
- 26439 /* 8250 base addresses. */
- 26440 PRIVATE port_t addr_8250[] = {
- 26441 0x3F8, /* COM1: (line 0); COM3 might be at 0x3E8 */
- 26442 0x2F8, /* COM2: (line 1); COM4 might be at 0x2E8 */
- 26443 };
- 26444 #endif
- 26445
- 26446 FORWARD _PROTOTYPE( int rs232_1handler, (int irq) );
- 26447 FORWARD _PROTOTYPE( int rs232_2handler, (int irq) );
- 26448 FORWARD _PROTOTYPE( void in_int, (rs232_t *rs) );
- 26449 FORWARD _PROTOTYPE( void line_int, (rs232_t *rs) );
- 26450 FORWARD _PROTOTYPE( void modem_int, (rs232_t *rs) );
- 26451 FORWARD _PROTOTYPE( void rs_write, (tty_t *tp) );
- 26452 FORWARD _PROTOTYPE( void rs_echo, (tty_t *tp, int c) );
- 26453 FORWARD _PROTOTYPE( void rs_ioctl, (tty_t *tp) );
- 26454 FORWARD _PROTOTYPE( void rs_config, (rs232_t *rs) );
- 26455 FORWARD _PROTOTYPE( void rs_read, (tty_t *tp) );
- 26456 FORWARD _PROTOTYPE( void rs_icancel, (tty_t *tp) );
- 26457 FORWARD _PROTOTYPE( void rs_ocancel, (tty_t *tp) );
- 26458 FORWARD _PROTOTYPE( void rs_ostart, (rs232_t *rs) );
- 26459 FORWARD _PROTOTYPE( void rs_break, (tty_t *tp) );
- 26460 FORWARD _PROTOTYPE( void out_int, (rs232_t *rs) );
- 26461
- 26462
- 26463 /*==========================================================================*
- 26464 * rs_write *
- 26465 *==========================================================================*/
- 26466 PRIVATE void rs_write(tp)
- 26467 register tty_t *tp;
- 26468 {
- 26469 /* (*devwrite)() routine for RS232. */
- 26470
- 26471 rs232_t *rs = tp->tty_priv;
- 26472 int count, ocount;
- 26473 phys_bytes user_phys;
- 26474
- 26475 if (rs->inhibited != tp->tty_inhibited) {
- 26476 /* Inhibition state has changed. */
- 26477 lock();
- 26478 rs->ostate |= OSWREADY;
- 26479 if (tp->tty_inhibited) rs->ostate &= ~OSWREADY;
- 26480 unlock();
- 26481 rs->inhibited = tp->tty_inhibited;
- 26482 }
- 26483
- 26484 if (rs->drain) {
- 26485 /* Wait for the line to drain then reconfigure and continue output. */
- 26486 if (rs->ocount > 0) return;
- 26487 rs->drain = FALSE;
- 26488 rs_config(rs);
- 26489 }
- 26490
- 26491 /* While there is something to do. */
- 26492 for (;;) {
- 26493 ocount = buflen(rs->obuf) - rs->ocount;
- 26494 count = bufend(rs->obuf) - rs->ohead;
- 26495 if (count > ocount) count = ocount;
- 26496 if (count > tp->tty_outleft) count = tp->tty_outleft;
- 26497 if (count == 0 || tp->tty_inhibited) return;
- 26498
- 26499 /* Copy from user space to the RS232 output buffer. */
- 26500 user_phys = proc_vir2phys(proc_addr(tp->tty_outproc), tp->tty_out_vir);
- 26501 phys_copy(user_phys, vir2phys(rs->ohead), (phys_bytes) count);
- 26502
- 26503 /* Perform output processing on the output buffer. */
- 26504 out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
- 26505 if (count == 0) break;
- 26506
- 26507 /* Assume echoing messed up by output. */
- 26508 tp->tty_reprint = TRUE;
- 26509
- 26510 /* Bookkeeping. */
- 26511 lock(); /* protect interrupt sensitive rs->ocount */
- 26512 rs->ocount += ocount;
- 26513 rs_ostart(rs);
- 26514 unlock();
- 26515 if ((rs->ohead += ocount) >= bufend(rs->obuf))
- 26516 rs->ohead -= buflen(rs->obuf);
- 26517 tp->tty_out_vir += count;
- 26518 tp->tty_outcum += count;
- 26519 if ((tp->tty_outleft -= count) == 0) {
- 26520 /* Output is finished, reply to the writer. */
- 26521 tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
- 26522 tp->tty_outproc, tp->tty_outcum);
- 26523 tp->tty_outcum = 0;
- 26524 }
- 26525 }
- 26526 }
- 26529 /*==========================================================================*
- 26530 * rs_echo *
- 26531 *==========================================================================*/
- 26532 PRIVATE void rs_echo(tp, c)
- 26533 tty_t *tp; /* which TTY */
- 26534 int c; /* character to echo */
- 26535 {
- 26536 /* Echo one character. (Like rs_write, but only one character, optionally.) */
- 26537
- 26538 rs232_t *rs = tp->tty_priv;
- 26539 int count, ocount;
- 26540
- 26541 ocount = buflen(rs->obuf) - rs->ocount;
- 26542 if (ocount == 0) return; /* output buffer full */
- 26543 count = 1;
- 26544 *rs->ohead = c; /* add one character */
- 26545
- 26546 out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
- 26547 if (count == 0) return;
- 26548
- 26549 lock();
- 26550 rs->ocount += ocount;
- 26551 rs_ostart(rs);
- 26552 unlock();
- 26553 if ((rs->ohead += ocount) >= bufend(rs->obuf)) rs->ohead -= buflen(rs->obuf);
- 26554 }
- 26557 /*==========================================================================*
- 26558 * rs_ioctl *
- 26559 *==========================================================================*/
- 26560 PRIVATE void rs_ioctl(tp)
- 26561 tty_t *tp; /* which TTY */
- 26562 {
- 26563 /* Reconfigure the line as soon as the output has drained. */
- 26564 rs232_t *rs = tp->tty_priv;
- 26565
- 26566 rs->drain = TRUE;
- 26567 }
- 26570 /*==========================================================================*
- 26571 * rs_config *
- 26572 *==========================================================================*/
- 26573 PRIVATE void rs_config(rs)
- 26574 rs232_t *rs; /* which line */
- 26575 {
- 26576 /* Set various line control parameters for RS232 I/O.
- 26577 * If DataBits == 5 and StopBits == 2, 8250 will generate 1.5 stop bits.
- 26578 * The 8250 can't handle split speed, so we use the input speed.
- 26579 */
- 26580
- 26581 tty_t *tp = rs->tty;
- 26582 int divisor;
- 26583 int line_controls;
- 26584 static struct speed2divisor {
- 26585 speed_t speed;
- 26586 int divisor;
- 26587 } s2d[] = {
- 26588 #if (MACHINE == IBM_PC)
- 26589 { B50, UART_FREQ / 50 },
- 26590 #endif
- 26591 { B75, UART_FREQ / 75 },
- 26592 { B110, UART_FREQ / 110 },
- 26593 { B134, UART_FREQ * 10 / 1345 },
- 26594 { B150, UART_FREQ / 150 },
- 26595 { B200, UART_FREQ / 200 },
- 26596 { B300, UART_FREQ / 300 },
- 26597 { B600, UART_FREQ / 600 },
- 26598 { B1200, UART_FREQ / 1200 },
- 26599 #if (MACHINE == IBM_PC)
- 26600 { B1800, UART_FREQ / 1800 },
- 26601 #endif
- 26602 { B2400, UART_FREQ / 2400 },
- 26603 { B4800, UART_FREQ / 4800 },
- 26604 { B9600, UART_FREQ / 9600 },
- 26605 { B19200, UART_FREQ / 19200 },
- 26606 #if (MACHINE == IBM_PC)
- 26607 { B38400, UART_FREQ / 38400 },
- 26608 { B57600, UART_FREQ / 57600 },
- 26609 { B115200, UART_FREQ / 115200L },
- 26610 #endif
- 26611 };
- 26612 struct speed2divisor *s2dp;
- 26613
- 26614 /* RS232 needs to know the xoff character, and if CTS works. */
- 26615 rs->oxoff = tp->tty_termios.c_cc[VSTOP];
- 26616 rs->cts = (tp->tty_termios.c_cflag & CLOCAL) ? MS_CTS : 0;
- 26617
- 26618 /* Look up the 8250 rate divisor from the output speed. */
- 26619 divisor = 0;
- 26620 for (s2dp = s2d; s2dp < s2d + sizeof(s2d)/sizeof(s2d[0]); s2dp++) {
- 26621 if (s2dp->speed == tp->tty_termios.c_ospeed) divisor = s2dp->divisor;
- 26622 }
- 26623 if (divisor == 0) return; /* B0? */
- 26624
- 26625 #if (MACHINE == IBM_PC)
- 26626 /* Compute line control flag bits. */
- 26627 line_controls = 0;
- 26628 if (tp->tty_termios.c_cflag & PARENB) {
- 26629 line_controls |= LC_PARITY;
- 26630 if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= LC_PAREVEN;
- 26631 }
- 26632 if (divisor >= (UART_FREQ / 110)) line_controls |= LC_2STOP_BITS;
- 26633 line_controls |= (tp->tty_termios.c_cflag & CSIZE) >> 2;
- 26634
- 26635 /* Lock out interrupts while setting the speed. The receiver register is
- 26636 * going to be hidden by the div_low register, but the input interrupt
- 26637 * handler relies on reading it to clear the interrupt and avoid looping
- 26638 * forever.
- 26639 */
- 26640 lock();
- 26641
- 26642 /* Select the baud rate divisor registers and change the rate. */
- 26643 out_byte(rs->line_ctl_port, LC_ADDRESS_DIVISOR);
- 26644 out_byte(rs->div_low_port, divisor);
- 26645 out_byte(rs->div_hi_port, divisor >> 8);
- 26646
- 26647 /* Change the line controls and reselect the usual registers. */
- 26648 out_byte(rs->line_ctl_port, line_controls);
- 26649
- 26650 rs->ostate |= ORAW;
- 26651 if ((tp->tty_termios.c_lflag & IXON) && rs->oxoff != _POSIX_VDISABLE)
- 26652 rs->ostate &= ~ORAW;
- 26653
- 26654 unlock();
- 26655
- 26656 #else /* MACHINE == ATARI */
- 26657
- 26658 line_controls = U_Q16;
- 26659 if (tp->tty_termios.c_cflag & PARENB) {
- 26660 line_controls |= U_PAR;
- 26661 if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= U_EVEN;
- 26662 }
- 26663 line_controls |= (divisor >= (UART_FREQ / 110)) ? U_ST2 : U_ST1;
- 26664
- 26665 switch (tp->tty_termios.c_cflag & CSIZE) { /* XXX - are U_Dn like CSn? */
- 26666 case CS5: line_controls |= U_D5; break;
- 26667 case CS5: line_controls |= U_D6; break;
- 26668 case CS5: line_controls |= U_D7; break;
- 26669 case CS5: line_controls |= U_D8; break;
- 26670 }
- 26671 lock();
- 26672 MFP->mf_ucr = line_controls;
- 26673 MFP->mf_tddr = divisor;
- 26674 unlock();
- 26675 #endif /* MACHINE == ATARI */
- 26676 }
- 26679 /*==========================================================================*
- 26680 * rs_init *
- 26681 *==========================================================================*/
- 26682 PUBLIC void rs_init(tp)
- 26683 tty_t *tp; /* which TTY */
- 26684 {
- 26685 /* Initialize RS232 for one line. */
- 26686
- 26687 register rs232_t *rs;
- 26688 int line;
- 26689 #if (MACHINE == IBM_PC)
- 26690 port_t this_8250;
- 26691 int irq;
- 26692 long v;
- 26693 #endif
- 26694
- 26695 /* Associate RS232 and TTY structures. */
- 26696 line = tp - &tty_table[NR_CONS];
- 26697 rs = tp->tty_priv = &rs_lines[line];
- 26698 rs->tty = tp;
- 26699
- 26700 /* Set up input queue. */
- 26701 rs->ihead = rs->itail = rs->ibuf;
- 26702
- 26703 #if (MACHINE == IBM_PC)
- 26704 /* Precalculate port numbers for speed. Magic numbers in the code (once). */
- 26705 this_8250 = addr_8250[line];
- 26706 rs->xmit_port = this_8250 + 0;
- 26707 rs->recv_port = this_8250 + 0;
- 26708 rs->div_low_port = this_8250 + 0;
- 26709 rs->div_hi_port = this_8250 + 1;
- 26710 rs->int_enab_port = this_8250 + 1;
- 26711 rs->int_id_port = this_8250 + 2;
- 26712 rs->line_ctl_port = this_8250 + 3;
- 26713 rs->modem_ctl_port = this_8250 + 4;
- 26714 rs->line_status_port = this_8250 + 5;
- 26715 rs->modem_status_port = this_8250 + 6;
- 26716 #endif
- 26717
- 26718 /* Set up the hardware to a base state, in particular
- 26719 * o turn off DTR (MC_DTR) to try to stop the external device.
- 26720 * o be careful about the divisor latch. Some BIOS's leave it enabled
- 26721 * here and that caused trouble (no interrupts) in version 1.5 by
- 26722 * hiding the interrupt enable port in the next step, and worse trouble
- 26723 * (continual interrupts) in an old version by hiding the receiver
- 26724 * port in the first interrupt. Call rs_ioctl() early to avoid this.
- 26725 * o disable interrupts at the chip level, to force an edge transition
- 26726 * on the 8259 line when interrupts are next enabled and active.
- 26727 * RS232 interrupts are guaranteed to be disabled now by the 8259
- 26728 * mask, but there used to be trouble if the mask was set without
- 26729 * handling a previous interrupt.
- 26730 */
- 26731 istop(rs); /* sets modem_ctl_port */
- 26732 rs_config(rs);
- 26733 #if (MACHINE == IBM_PC)
- 26734 out_byte(rs->int_enab_port, 0);
- 26735 #endif
- 26736
- 26737 /* Clear any harmful leftover interrupts. An output interrupt is harmless
- 26738 * and will occur when interrupts are enabled anyway. Set up the output
- 26739 * queue using the status from clearing the modem status interrupt.
- 26740 */
- 26741 #if (MACHINE == IBM_PC)
- 26742 in_byte(rs->line_status_port);
- 26743 in_byte(rs->recv_port);
- 26744 #endif
- 26745 rs->ostate = devready(rs) | ORAW | OSWREADY; /* reads modem_ctl_port */
- 26746 rs->ohead = rs->otail = rs->obuf;
- 26747
- 26748 #if (MACHINE == IBM_PC)
- 26749 /* Enable interrupts for both interrupt controller and device. */
- 26750 irq = (line & 1) ? SECONDARY_IRQ : RS232_IRQ;
- 26751
- 26752 #if ENABLE_NETWORKING
- 26753 /* The ethernet driver may steal the IRQ of an RS232 line. */
- 26754 v = ETHER_IRQ;
- 26755 switch (env_parse("DPETH0", "x:d:x", 1, &v, 0L, (long) NR_IRQ_VECTORS-1)) {
- 26756 case EP_ON:
- 26757 case EP_SET:
- 26758 if (v == irq) return; /* IRQ in use, don't configure line */
- 26759 }
- 26760 #endif
- 26761
- 26762 put_irq_handler(irq, (line & 1) ? rs232_2handler : rs232_1handler);
- 26763 enable_irq(irq);
- 26764 out_byte(rs->int_enab_port, IE_LINE_STATUS_CHANGE | IE_MODEM_STATUS_CHANGE
- 26765 | IE_RECEIVER_READY | IE_TRANSMITTER_READY);
- 26766 #else /* MACHINE == ATARI */
- 26767 /* Initialize the 68901 chip, then enable interrupts. */
- 26768 MFP->mf_scr = 0x00;
- 26769 MFP->mf_tcdcr |= T_Q004;
- 26770 MFP->mf_rsr = R_ENA;
- 26771 MFP->mf_tsr = T_ENA;
- 26772 MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
- 26773 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
- 26774 MFP->mf_ddr = (MFP->mf_ddr & ~ (IO_SCTS|IO_SDCD));
- 26775 MFP->mf_iera |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
- 26776 MFP->mf_imra |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
- 26777 MFP->mf_ierb |= (IB_SCTS|IB_SDCD);
- 26778 MFP->mf_imrb |= (IB_SCTS|IB_SDCD);
- 26779 #endif /* MACHINE == ATARI */
- 26780
- 26781 /* Fill in TTY function hooks. */
- 26782 tp->tty_devread = rs_read;
- 26783 tp->tty_devwrite = rs_write;
- 26784 tp->tty_echo = rs_echo;
- 26785 tp->tty_icancel = rs_icancel;
- 26786 tp->tty_ocancel = rs_ocancel;
- 26787 tp->tty_ioctl = rs_ioctl;
- 26788 tp->tty_break = rs_break;
- 26789
- 26790 /* Tell external device we are ready. */
- 26791 istart(rs);
- 26792 }
- 26795 /*==========================================================================*
- 26796 * rs_icancel *
- 26797 *==========================================================================*/
- 26798 PRIVATE void rs_icancel(tp)
- 26799 tty_t *tp; /* which TTY */
- 26800 {
- 26801 /* Cancel waiting input. */
- 26802 rs232_t *rs = tp->tty_priv;
- 26803
- 26804 lock();
- 26805 rs->icount = 0;
- 26806 rs->itail = rs->ihead;
- 26807 istart(rs);
- 26808 unlock();
- 26809 }
- 26812 /*==========================================================================*
- 26813 * rs_ocancel *
- 26814 *==========================================================================*/
- 26815 PRIVATE void rs_ocancel(tp)
- 26816 tty_t *tp; /* which TTY */
- 26817 {
- 26818 /* Cancel pending output. */
- 26819 rs232_t *rs = tp->tty_priv;
- 26820
- 26821 lock();
- 26822 rs->ostate &= ~(ODONE | OQUEUED);
- 26823 rs->ocount = 0;
- 26824 rs->otail = rs->ohead;
- 26825 unlock();
- 26826 }
- 26829 /*==========================================================================*
- 26830 * rs_read *
- 26831 *==========================================================================*/
- 26832 PRIVATE void rs_read(tp)
- 26833 tty_t *tp; /* which tty */
- 26834 {
- 26835 /* Process characters from the circular input buffer. */
- 26836
- 26837 rs232_t *rs = tp->tty_priv;
- 26838 int icount, count, ostate;
- 26839
- 26840 if (!(tp->tty_termios.c_cflag & CLOCAL)) {
- 26841 /* Send a SIGHUP if hangup detected. */
- 26842 lock();
- 26843 ostate = rs->ostate;
- 26844 rs->ostate &= ~ODEVHUP; /* save ostate, clear DEVHUP */
- 26845 unlock();
- 26846 if (ostate & ODEVHUP) { sigchar(tp, SIGHUP); return; }
- 26847 }
- 26848
- 26849 while ((count = rs->icount) > 0) {
- 26850 icount = bufend(rs->ibuf) - rs->itail;
- 26851 if (count > icount) count = icount;
- 26852
- 26853 /* Perform input processing on (part of) the input buffer. */
- 26854 if ((count = in_process(tp, rs->itail, count)) == 0) break;
- 26855
- 26856 lock(); /* protect interrupt sensitive variables */
- 26857 rs->icount -= count;
- 26858 if (!rs->idevready && rs->icount < RS_ILOWWATER) istart(rs);
- 26859 unlock();
- 26860 if ((rs->itail += count) == bufend(rs->ibuf)) rs->itail = rs->ibuf;
- 26861 }
- 26862 }
- 26865 /*==========================================================================*
- 26866 * rs_ostart *
- 26867 *==========================================================================*/
- 26868 PRIVATE void rs_ostart(rs)
- 26869 rs232_t *rs; /* which rs line */
- 26870 {
- 26871 /* Tell RS232 there is something waiting in the output buffer. */
- 26872
- 26873 rs->ostate |= OQUEUED;
- 26874 if (txready(rs)) out_int(rs);
- 26875 }
- 26878 /*==========================================================================*
- 26879 * rs_break *
- 26880 *==========================================================================*/
- 26881 PRIVATE void rs_break(tp)
- 26882 tty_t *tp; /* which tty */
- 26883 {
- 26884 /* Generate a break condition by setting the BREAK bit for 0.4 sec. */
- 26885 rs232_t *rs = tp->tty_priv;
- 26886 int line_controls;
- 26887
- 26888 line_controls = in_byte(rs->line_ctl_port);
- 26889 out_byte(rs->line_ctl_port, line_controls | LC_BREAK);
- 26890 milli_delay(400); /* ouch */
- 26891 out_byte(rs->line_ctl_port, line_controls);
- 26892 }
- 26895 /* Low level (interrupt) routines. */
- 26896
- 26897 #if (MACHINE == IBM_PC)
- 26898 /*==========================================================================*
- 26899 * rs232_1handler *
- 26900 *==========================================================================*/
- 26901 PRIVATE int rs232_1handler(irq)
- 26902 int irq;
- 26903 {
- 26904 /* Interrupt hander for IRQ4.
- 26905 * Only 1 line (usually COM1) should use it.
- 26906 */
- 26907
- 26908 register rs232_t *rs = &rs_lines[0];
- 26909
- 26910 while (TRUE) {
- 26911 /* Loop to pick up ALL pending interrupts for device.
- 26912 * This usually just wastes time unless the hardware has a buffer
- 26913 * (and then we have to worry about being stuck in the loop too long).
- 26914 * Unfortunately, some serial cards lock up without this.
- 26915 */
- 26916 switch (in_byte(rs->int_id_port)) {
- 26917 case IS_RECEIVER_READY:
- 26918 in_int(rs);
- 26919 continue;
- 26920 case IS_TRANSMITTER_READY:
- 26921 out_int(rs);
- 26922 continue;
- 26923 case IS_MODEM_STATUS_CHANGE:
- 26924 modem_int(rs);
- 26925 continue;
- 26926 case IS_LINE_STATUS_CHANGE:
- 26927 line_int(rs);
- 26928 continue;
- 26929 }
- 26930 return(1); /* reenable serial interrupt */
- 26931 }
- 26932 }
- 26935 /*==========================================================================*
- 26936 * rs232_2handler *
- 26937 *==========================================================================*/
- 26938 PRIVATE int rs232_2handler(irq)
- 26939 int irq;
- 26940 {
- 26941 /* Interrupt hander for IRQ3.
- 26942 * Only 1 line (usually COM2) should use it.
- 26943 */
- 26944
- 26945 register rs232_t *rs = &rs_lines[1];
- 26946
- 26947 while (TRUE) {
- 26948 switch (in_byte(rs->int_id_port)) {
- 26949 case IS_RECEIVER_READY:
- 26950 in_int(rs);
- 26951 continue;
- 26952 case IS_TRANSMITTER_READY:
- 26953 out_int(rs);
- 26954 continue;
- 26955 case IS_MODEM_STATUS_CHANGE:
- 26956 modem_int(rs);
- 26957 continue;
- 26958 case IS_LINE_STATUS_CHANGE:
- 26959 line_int(rs);
- 26960 continue;
- 26961 }
- 26962 return(1); /* reenable serial interrupt */
- 26963 }
- 26964 }
- 26965 #else /* MACHINE == ATARI */
- 26966 /*==========================================================================*
- 26967 * siaint *
- 26968 *==========================================================================*/
- 26969 PRIVATE void siaint(type)
- 26970 int type; /* interrupt type */
- 26971 {
- 26972 /* siaint is the rs232 interrupt procedure for Atari ST's. For ST there are
- 26973 * as much as 5 interrupt lines used for rs232. The trap type byte left on the
- 26974 * stack by the assembler interrupt handler identifies the interrupt cause.
- 26975 */
- 26976
- 26977 register unsigned char code;
- 26978 register rs232_t *rs = &rs_lines[0];
- 26979 int s = lock();
- 26980
- 26981 switch (type & 0x00FF)
- 26982 {
- 26983 case 0x00: /* receive buffer full */
- 26984 in_int(rs);
- 26985 break;
- 26986 case 0x01: /* receive error */
- 26987 line_int(rs);
- 26988 break;
- 26989 case 0x02: /* transmit buffer empty */
- 26990 out_int(rs);
- 26991 break;
- 26992 case 0x03: /* transmit error */
- 26993 code = MFP->mf_tsr;
- 26994 if (code & ~(T_ENA | T_UE | T_EMPTY))
- 26995 {
- 26996 printf("sia: transmit error: status=%xrn", code);
- 26997 /* MFP->mf_udr = lastchar; */ /* retry */
- 26998 }
- 26999 break;
- 27000 case 0x04: /* modem lines change */
- 27001 modem_int(rs);
- 27002 break;
- 27003 }
- 27004 restore(s);
- 27005 }
- 27006 #endif /* MACHINE == ATARI */
- 27007
- 27008
- 27009 /*==========================================================================*
- 27010 * in_int *
- 27011 *==========================================================================*/
- 27012 PRIVATE void in_int(rs)
- 27013 register rs232_t *rs; /* line with input interrupt */
- 27014 {
- 27015 /* Read the data which just arrived.
- 27016 * If it is the oxoff char, clear OSWREADY, else if OSWREADY was clear, set
- 27017 * it and restart output (any char does this, not just xon).
- 27018 * Put data in the buffer if room, otherwise discard it.
- 27019 * Set a flag for the clock interrupt handler to eventually notify TTY.
- 27020 */
- 27021
- 27022 int c;
- 27023
- 27024 #if (MACHINE == IBM_PC)
- 27025 c = in_byte(rs->recv_port);
- 27026 #else /* MACHINE == ATARI */
- 27027 c = MFP->mf_udr;
- 27028 #endif
- 27029
- 27030 if (!(rs->ostate & ORAW)) {
- 27031 if (c == rs->oxoff) {
- 27032 rs->ostate &= ~OSWREADY;
- 27033 } else
- 27034 if (!(rs->ostate & OSWREADY)) {
- 27035 rs->ostate |= OSWREADY;
- 27036 if (txready(rs)) out_int(rs);
- 27037 }
- 27038 }
- 27039
- 27040 if (rs->icount == buflen(rs->ibuf)) return; /* input buffer full, discard */
- 27041
- 27042 if (++rs->icount == RS_IHIGHWATER && rs->idevready) istop(rs);
- 27043 *rs->ihead = c;
- 27044 if (++rs->ihead == bufend(rs->ibuf)) rs->ihead = rs->ibuf;
- 27045 if (rs->icount == 1) {
- 27046 rs->tty->tty_events = 1;
- 27047 force_timeout();
- 27048 }
- 27049 }
- 27052 /*==========================================================================*
- 27053 * line_int *
- 27054 *==========================================================================*/
- 27055 PRIVATE void line_int(rs)
- 27056 register rs232_t *rs; /* line with line status interrupt */
- 27057 {
- 27058 /* Check for and record errors. */
- 27059
- 27060 #if (MACHINE == IBM_PC)
- 27061 rs->lstatus = in_byte(rs->line_status_port);
- 27062 #else /* MACHINE == ATARI */
- 27063 rs->lstatus = MFP->mf_rsr;
- 27064 MFP->mf_rsr &= R_ENA;
- 27065 rs->pad = MFP->mf_udr; /* discard char in case of LS_OVERRUN_ERR */
- 27066 #endif /* MACHINE == ATARI */
- 27067 if (rs->lstatus & LS_FRAMING_ERR) ++rs->framing_errors;
- 27068 if (rs->lstatus & LS_OVERRUN_ERR) ++rs->overrun_errors;
- 27069 if (rs->lstatus & LS_PARITY_ERR) ++rs->parity_errors;
- 27070 if (rs->lstatus & LS_BREAK_INTERRUPT) ++rs->break_interrupts;
- 27071 }
- 27074 /*==========================================================================*
- 27075 * modem_int *
- 27076 *==========================================================================*/
- 27077 PRIVATE void modem_int(rs)
- 27078 register rs232_t *rs; /* line with modem interrupt */
- 27079 {
- 27080 /* Get possibly new device-ready status, and clear ODEVREADY if necessary.
- 27081 * If the device just became ready, restart output.
- 27082 */
- 27083
- 27084 #if (MACHINE == ATARI)
- 27085 /* Set active edge interrupt so that next change causes a new interrupt */
- 27086 MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
- 27087 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
- 27088 #endif
- 27089
- 27090 if (devhup(rs)) {
- 27091 rs->ostate |= ODEVHUP;
- 27092 rs->tty->tty_events = 1;
- 27093 force_timeout();
- 27094 }
- 27095
- 27096 if (!devready(rs))
- 27097 rs->ostate &= ~ODEVREADY;
- 27098 else if (!(rs->ostate & ODEVREADY)) {
- 27099 rs->ostate |= ODEVREADY;
- 27100 if (txready(rs)) out_int(rs);
- 27101 }
- 27102 }
- 27105 /*==========================================================================*
- 27106 * out_int *
- 27107 *==========================================================================*/
- 27108 PRIVATE void out_int(rs)
- 27109 register rs232_t *rs; /* line with output interrupt */
- 27110 {
- 27111 /* If there is output to do and everything is ready, do it (local device is
- 27112 * known ready).
- 27113 * Notify TTY when the buffer goes empty.
- 27114 */
- 27115
- 27116 if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) {
- 27117 /* Bit test allows ORAW and requires the others. */
- 27118 #if (MACHINE == IBM_PC)
- 27119 out_byte(rs->xmit_port, *rs->otail);
- 27120 #else /* MACHINE == ATARI */
- 27121 MFP->mf_udr = *rs->otail;
- 27122 #endif
- 27123 if (++rs->otail == bufend(rs->obuf)) rs->otail = rs->obuf;
- 27124 if (--rs->ocount == 0) {
- 27125 rs->ostate ^= (ODONE | OQUEUED); /* ODONE on, OQUEUED off */
- 27126 rs->tty->tty_events = 1;
- 27127 force_timeout();
- 27128 } else
- 27129 if (rs->ocount == RS_OLOWWATER) { /* running low? */
- 27130 rs->tty->tty_events = 1;
- 27131 force_timeout();
- 27132 }
- 27133 }
- 27134 }
- 27135 #endif /* NR_RS_LINES > 0 */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/sb16_dsp.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 27200 /* This file contains the driver for a DSP (Digital Sound Processor) on
- 27201 * a SoundBlaster 16 (ASP) soundcard.
- 27202 *
- 27203 * The driver supports the following operations (using message format m2):
- 27204 *
- 27205 * m_type DEVICE PROC_NR COUNT POSITION ADRRESS
- 27206 * ----------------------------------------------------------------
- 27207 * | DEV_OPEN | device | proc nr | | | |
- 27208 * |------------+---------+---------+---------+---------+---------|
- 27209 * | DEV_CLOSE | device | proc nr | | | |
- 27210 * |------------+---------+---------+---------+---------+---------|
- 27211 * | DEV_READ | device | proc nr | bytes | | buf ptr |
- 27212 * |------------+---------+---------+---------+---------+---------|
- 27213 * | DEV_WRITE | device | proc nr | bytes | | buf ptr |
- 27214 * |------------+---------+---------+---------+---------+---------|
- 27215 * | DEV_IOCTL | device | proc nr |func code| | buf ptr |
- 27216 * ----------------------------------------------------------------
- 27217 *
- 27218 * The file contains one entry point:
- 27219 *
- 27220 * dsp_task: main entry when system is brought up
- 27221 *
- 27222 * May 20 1995 Author: Michel R. Prevenier
- 27223 */
- 27224
- 27225
- 27226 #include "kernel.h"
- 27227 #include <minix/com.h>
- 27228 #include <minix/callnr.h>
- 27229 #include <sys/ioctl.h>
- 27230 #if __minix_vmd
- 27231 #include "proc.h"
- 27232 #include "config.h"
- 27233 #endif
- 27234 #include "sb16.h"
- 27235
- 27236 #if ENABLE_SB_AUDIO
- 27237
- 27238 /* prototypes */
- 27239 FORWARD _PROTOTYPE( void init_buffer, (void));
- 27240 FORWARD _PROTOTYPE( int dsp_init, (void));
- 27241 FORWARD _PROTOTYPE( int dsp_handler, (int irq));
- 27242 FORWARD _PROTOTYPE( int dsp_open, (message *m_ptr));
- 27243 FORWARD _PROTOTYPE( int dsp_close, (message *m_ptr));
- 27244 FORWARD _PROTOTYPE( int dsp_ioctl, (message *m_ptr));
- 27245 FORWARD _PROTOTYPE( int dsp_write, (message *m_ptr));
- 27246 FORWARD _PROTOTYPE( int dsp_read, (message *m_ptr));
- 27247 FORWARD _PROTOTYPE( int dsp_reset, (void));
- 27248 FORWARD _PROTOTYPE( int dsp_command, (int value));
- 27249 FORWARD _PROTOTYPE( int dsp_set_speed, (unsigned int speed));
- 27250 FORWARD _PROTOTYPE( int dsp_set_size, (unsigned int size));
- 27251 FORWARD _PROTOTYPE( int dsp_set_stereo, (unsigned int stereo));
- 27252 FORWARD _PROTOTYPE( int dsp_set_bits, (unsigned int bits));
- 27253 FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign));
- 27254 FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count));
- 27255 FORWARD _PROTOTYPE( void dsp_setup, (void));
- 27256
- 27257 /* globals */
- 27258 #if __minix_vmd
- 27259 PRIVATE int DspTasknr = ANY;
- 27260 #endif
- 27261 PRIVATE int DspVersion[2];
- 27262 PRIVATE unsigned int DspStereo = DEFAULT_STEREO;
- 27263 PRIVATE unsigned int DspSpeed = DEFAULT_SPEED;
- 27264 PRIVATE unsigned int DspBits = DEFAULT_BITS;
- 27265 PRIVATE unsigned int DspSign = DEFAULT_SIGN;
- 27266 PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;
- 27267 PRIVATE int DspAvail = 0;
- 27268 PRIVATE int DspBusy = 0;
- 27269 PRIVATE int DmaBusy = 0;
- 27270 PRIVATE int DmaDone = 1;
- 27271 PRIVATE int DmaMode = 0;
- 27272
- 27273 PRIVATE char DmaBuffer[(long)2 * DMA_SIZE];
- 27274 PRIVATE char *DmaPtr;
- 27275 PRIVATE phys_bytes DmaPhys;
- 27276
- 27277
- 27278 /*=========================================================================*
- 27279 * dsp_task *
- 27280 *=========================================================================*/
- 27281 PUBLIC void dsp_task()
- 27282 {
- 27283 message mess;
- 27284 int err, caller, proc_nr;
- 27285
- 27286 #if __minix_vmd
- 27287 DspTasknr = proc_number(proc_ptr);
- 27288 #endif
- 27289
- 27290 /* initialize the DMA buffer */
- 27291 init_buffer();
- 27292
- 27293 /* Here is the main loop of the sound task. It waits for a message, carries
- 27294 * it out, and sends a reply.
- 27295 */
- 27296 while (TRUE)
- 27297 {
- 27298 receive(ANY, &mess);
- 27299
- 27300 caller = mess.m_source;
- 27301 proc_nr = mess.PROC_NR;
- 27302
- 27303 switch (caller)
- 27304 {
- 27305 case HARDWARE:
- 27306 /* Leftover interrupt. */
- 27307 continue;
- 27308 case FS_PROC_NR:
- 27309 /* The only legitimate caller. */
- 27310 break;
- 27311 default:
- 27312 printf("sb16: got message from %dn", caller);
- 27313 continue;
- 27314 }
- 27315
- 27316 /* Now carry out the work. */
- 27317 switch(mess.m_type)
- 27318 {
- 27319 case DEV_OPEN: err = dsp_open(&mess);break;
- 27320 case DEV_CLOSE: err = dsp_close(&mess);break;
- 27321 case DEV_IOCTL: err = dsp_ioctl(&mess);break;
- 27322 case DEV_READ: err = dsp_read(&mess);break;
- 27323 case DEV_WRITE: err = dsp_write(&mess);break;
- 27324 default: err = EINVAL;break;
- 27325 }
- 27326
- 27327 /* Finally, prepare and send the reply message. */
- 27328 mess.m_type = TASK_REPLY;
- 27329 mess.REP_PROC_NR = proc_nr;
- 27330
- 27331 mess.REP_STATUS = err; /* #bytes transfered or error code */
- 27332 send(caller, &mess); /* send reply to caller */
- 27333 }
- 27334 }
- 27337 /*===========================================================================*
- 27338 * init_buffer *
- 27339 *===========================================================================*/
- 27340 PRIVATE void init_buffer()
- 27341 {
- 27342 /* Select a buffer that can safely be used for dma transfers.
- 27343 * Its absolute address is 'DmaPhys', the normal address is 'DmaPtr'.
- 27344 */
- 27345
- 27346 DmaPtr = DmaBuffer;
- 27347 DmaPhys = vir2phys(DmaBuffer);
- 27348
- 27349 if (dma_bytes_left(DmaPhys) < DMA_SIZE) {
- 27350 /* First half of buffer crosses a 64K boundary, can't DMA into that */
- 27351 DmaPtr += DMA_SIZE;
- 27352 DmaPhys += DMA_SIZE;
- 27353 }
- 27354 }
- 27357 /*=========================================================================*
- 27358 * dsp_open *
- 27359 *=========================================================================*/
- 27360 PRIVATE int dsp_open(m_ptr)
- 27361 message *m_ptr;
- 27362 {
- 27363
- 27364 #if SB_DEBUG
- 27365 printf("sb16_openn");
- 27366 #endif
- 27367
- 27368 /* try to detect SoundBlaster card */
- 27369 if (!DspAvail && dsp_init() != OK) return EIO;
- 27370
- 27371 /* Only one open at a time with soundcards */
- 27372 if (DspBusy) return EBUSY;
- 27373
- 27374 /* Start with a clean DSP */
- 27375 if (dsp_reset() != OK) return EIO;
- 27376
- 27377 /* Setup default values */
- 27378 DspStereo = DEFAULT_STEREO;
- 27379 DspSpeed = DEFAULT_SPEED;
- 27380 DspBits = DEFAULT_BITS;
- 27381 DspSign = DEFAULT_SIGN;
- 27382 DspFragmentSize = DMA_SIZE;
- 27383
- 27384 DspBusy = 1;
- 27385 DmaBusy = 0;
- 27386
- 27387 return OK;
- 27388 }
- 27391 /*=========================================================================*
- 27392 * dsp_close *
- 27393 *=========================================================================*/
- 27394 PRIVATE int dsp_close(m_ptr)
- 27395 message *m_ptr;
- 27396 {
- 27397
- 27398 #if SB_DEBUG
- 27399 printf("dsp_closen");
- 27400 #endif
- 27401
- 27402 DspBusy = 0; /* soundcard available again */
- 27403 DmaBusy = 0;
- 27404
- 27405 return OK;
- 27406 }
- 27409 /*=========================================================================*
- 27410 * dsp_ioctl *
- 27411 *=========================================================================*/
- 27412 PRIVATE int dsp_ioctl(m_ptr)
- 27413 message *m_ptr;
- 27414 {
- 27415 int status;
- 27416 phys_bytes user_phys;
- 27417 unsigned int val;
- 27418
- 27419 /* Cannot change parameters during play or recording */
- 27420 if (DmaBusy) return EBUSY;
- 27421
- 27422 /* Get user data */
- 27423 if (m_ptr->REQUEST != DSPIORESET)
- 27424 {
- 27425 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 27426 sizeof(unsigned int));
- 27427 if (user_phys == 0) return(EFAULT);
- 27428 phys_copy(user_phys, vir2phys(&val), (phys_bytes) sizeof(val));
- 27429 }
- 27430
- 27431 #if SB_DEBUG
- 27432 printf("dsp_ioctl: got ioctl %d, argument: %dn", m_ptr->REQUEST, val);
- 27433 #endif
- 27434
- 27435 switch(m_ptr->REQUEST)
- 27436 {
- 27437 case DSPIORATE: status = dsp_set_speed(val);break;
- 27438 case DSPIOSTEREO: status = dsp_set_stereo(val);break;
- 27439 case DSPIOBITS: status = dsp_set_bits(val);break;
- 27440 case DSPIOSIZE: status = dsp_set_size(val);break;
- 27441 case DSPIOSIGN: status = dsp_set_sign(val);break;
- 27442 case DSPIOMAX: {
- 27443 val = DMA_SIZE;
- 27444 phys_copy(vir2phys(&val), user_phys,
- 27445 (phys_bytes) sizeof(val));
- 27446 status = OK;
- 27447 };break;
- 27448 case DSPIORESET: status = dsp_reset();break;
- 27449 default: status = ENOTTY;break;
- 27450 }
- 27451
- 27452 return status;
- 27453 }
- 27456 /*=========================================================================*
- 27457 * dsp_init *
- 27458 *=========================================================================*/
- 27459 PRIVATE int dsp_init()
- 27460 {
- 27461 int i;
- 27462
- 27463 if (dsp_reset () != OK)
- 27464 {
- 27465 printf("sb16: No SoundBlaster card detectedn");
- 27466 return -1;
- 27467 }
- 27468
- 27469 DspVersion[0] = DspVersion[1] = 0;
- 27470 dsp_command(DSP_GET_VERSION); /* Get DSP version bytes */
- 27471
- 27472 for (i = 1000; i; i--)
- 27473 {
- 27474 if (in_byte (DSP_DATA_AVL) & 0x80)
- 27475 {
- 27476 if (DspVersion[0] == 0)
- 27477 DspVersion[0] = in_byte (DSP_READ);
- 27478 else
- 27479 {
- 27480 DspVersion[1] = in_byte (DSP_READ);
- 27481 break;
- 27482 }
- 27483 }
- 27484 }
- 27485
- 27486 if (DspVersion[0] < 4)
- 27487 {
- 27488 printf("sb16: No SoundBlaster 16 compatible card detectedn");
- 27489 return -1;
- 27490 }
- 27491 else
- 27492 printf ("sb16: SoundBlaster DSP version %d.%d detectedn",
- 27493 DspVersion[0], DspVersion[1]);
- 27494
- 27495 /* set IRQ and DMA channels */
- 27496 mixer_set(MIXER_SET_IRQ, (1 << (SB_IRQ / 2 - 1)));
- 27497 mixer_set(MIXER_SET_DMA, (1 << SB_DMA_8 | 1 << SB_DMA_16));
- 27498
- 27499 /* register interrupt vector and enable irq */
- 27500 put_irq_handler(SB_IRQ, dsp_handler);
- 27501 enable_irq(SB_IRQ);
- 27502
- 27503 DspAvail = 1;
- 27504 return OK;
- 27505 }
- 27508 /*=========================================================================*
- 27509 * dsp_handler *
- 27510 *=========================================================================*/
- 27511 PRIVATE int dsp_handler(irq)
- 27512 int irq;
- 27513 {
- 27514
- 27515 #if SB_DEBUG2
- 27516 printf("SoundBlaster interrupt %dn", irq);
- 27517 #endif
- 27518
- 27519 if (DmaDone) /* Dma transfer is done */
- 27520 {
- 27521 /* Send DSP command to stop dma */
- 27522 dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));
- 27523
- 27524 DmaBusy = 0; /* Dma available again */
- 27525 }
- 27526
- 27527 /* Send interrupt to audio task and enable again */
- 27528 #if __minix_vmd
- 27529 interrupt(DspTasknr);
- 27530 #else
- 27531 interrupt(AUDIO);
- 27532 #endif
- 27533
- 27534 /* Acknowledge the interrupt on the DSP */
- 27535 (void) in_byte((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));
- 27536
- 27537 return 1;
- 27538 }
- 27541 /*=========================================================================*
- 27542 * dsp_command *
- 27543 *=========================================================================*/
- 27544 PRIVATE int dsp_command(value)
- 27545 int value;
- 27546 {
- 27547 int i;
- 27548
- 27549 for (i = 0; i < SB_TIMEOUT; i++)
- 27550 {
- 27551 if ((in_byte (DSP_STATUS) & 0x80) == 0)
- 27552 {
- 27553 out_byte (DSP_COMMAND, value);
- 27554 return OK;
- 27555 }
- 27556 }
- 27557
- 27558 printf ("sb16: SoundBlaster: DSP Command(%x) timeoutn", value);
- 27559 return -1;
- 27560 }
- 27563 /*=========================================================================*
- 27564 * dsp_reset *
- 27565 *=========================================================================*/
- 27566 PRIVATE int dsp_reset(void)
- 27567 {
- 27568 int i;
- 27569
- 27570 out_byte (DSP_RESET, 1);
- 27571 for(i =0; i<1000; i++); /* wait a while */
- 27572 out_byte (DSP_RESET, 0);
- 27573
- 27574 for (i = 0; i < 1000 && !(in_byte (DSP_DATA_AVL) & 0x80); i++);
- 27575
- 27576 if (in_byte (DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */
- 27577
- 27578 DmaBusy = 0;
- 27579 DmaDone = 1;
- 27580
- 27581 return OK;
- 27582 }
- 27585 /*=========================================================================*
- 27586 * dsp_set_speed *
- 27587 *=========================================================================*/
- 27588 static int dsp_set_speed(speed)
- 27589 unsigned int speed;
- 27590 {
- 27591 #if SB_DEBUG
- 27592 printf("sb16: setting speed to %u, stereo = %dn", speed, DspStereo);
- 27593 #endif
- 27594
- 27595 if (speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED)
- 27596 return EPERM;
- 27597
- 27598 /* Soundblaster 16 can be programmed with real sample rates
- 27599 * instead of time constants
- 27600 *
- 27601 * Since you cannot sample and play at the same time
- 27602 * we set in- and output rate to the same value
- 27603 */
- 27604
- 27605 lock(); /* disable interrupts */
- 27606 dsp_command(DSP_INPUT_RATE); /* set input rate */
- 27607 dsp_command(speed >> 8); /* high byte of speed */
- 27608 dsp_command(speed); /* low byte of speed */
- 27609 dsp_command(DSP_OUTPUT_RATE); /* same for output rate */
- 27610 dsp_command(speed >> 8);
- 27611 dsp_command(speed);
- 27612 unlock(); /* enable interrupts */
- 27613
- 27614 DspSpeed = speed;
- 27615
- 27616 return OK;
- 27617 }
- 27620 /*=========================================================================*
- 27621 * dsp_set_stereo *
- 27622 *=========================================================================*/
- 27623 static int dsp_set_stereo(stereo)
- 27624 unsigned int stereo;
- 27625 {
- 27626 if (stereo)
- 27627 DspStereo = 1;
- 27628 else
- 27629 DspStereo = 0;
- 27630
- 27631 return OK;
- 27632 }
- 27635 /*=========================================================================*
- 27636 * dsp_set_bits *
- 27637 *=========================================================================*/
- 27638 static int dsp_set_bits(bits)
- 27639 unsigned int bits;
- 27640 {
- 27641 /* Sanity checks */
- 27642 if (bits != 8 && bits != 16) return EINVAL;
- 27643
- 27644 DspBits = bits;
- 27645
- 27646 return OK;
- 27647 }
- 27650 /*=========================================================================*
- 27651 * dsp_set_size *
- 27652 *=========================================================================*/
- 27653 static int dsp_set_size(size)
- 27654 unsigned int size;
- 27655 {
- 27656
- 27657 #if SB_DEBUG
- 27658 printf("sb16: set fragment size to %un", size);
- 27659 #endif
- 27660
- 27661 /* Sanity checks */
- 27662 if (size < DSP_MIN_FRAGMENT_SIZE ||
- 27663 size > DSP_MAX_FRAGMENT_SIZE ||
- 27664 size % 2 != 0)
- 27665 return EINVAL;
- 27666
- 27667 DspFragmentSize = size;
- 27668
- 27669 return OK;
- 27670 }
- 27673 /*=========================================================================*
- 27674 * dsp_set_sign *
- 27675 *=========================================================================*/
- 27676 static int dsp_set_sign(sign)
- 27677 unsigned int sign;
- 27678 {
- 27679
- 27680 #if SB_DEBUG
- 27681 printf("sb16: set sign to %un", sign);
- 27682 #endif
- 27683
- 27684 DspSign = (sign > 0 ? 1 : 0);
- 27685
- 27686 return OK;
- 27687 }
- 27690 /*===========================================================================*
- 27691 * dsp_dma_setup *
- 27692 *===========================================================================*/
- 27693 PRIVATE void dsp_dma_setup(address, count)
- 27694 phys_bytes address;
- 27695 int count;
- 27696
- 27697 {
- 27698 #if SB_DEBUG
- 27699 printf("Setting up %d bit DMAn", DspBits);
- 27700 #endif
- 27701
- 27702 if (DspBits == 8) /* 8 bit sound */
- 27703 {
- 27704 count--;
- 27705
- 27706 lock();
- 27707 out_byte(DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */
- 27708 out_byte(DMA8_CLEAR, 0x00); /* Clear flip flop */
- 27709
- 27710 /* set DMA mode */
- 27711 out_byte(DMA8_MODE,
- 27712 (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC));
- 27713
- 27714 out_byte(DMA8_ADDR, address >> 0); /* Low_byte of address */
- 27715 out_byte(DMA8_ADDR, address >> 8); /* High byte of address */
- 27716 out_byte(DMA8_PAGE, address >> 16); /* 64K page number */
- 27717 out_byte(DMA8_COUNT, count >> 0); /* Low byte of count */
- 27718 out_byte(DMA8_COUNT, count >> 8); /* High byte of count */
- 27719 out_byte(DMA8_MASK, SB_DMA_8); /* Enable DMA channel */
- 27720 unlock();
- 27721 }
- 27722 else /* 16 bit sound */
- 27723 {
- 27724 count-= 2;
- 27725
- 27726 lock();
- 27727 out_byte(DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */
- 27728 out_byte(DMA16_CLEAR, 0x00); /* Clear flip flop */
- 27729
- 27730 /* Set dma mode */
- 27731 out_byte(DMA16_MODE,
- 27732 (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC));
- 27733
- 27734 out_byte(DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */
- 27735 out_byte(DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */
- 27736 out_byte(DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */
- 27737 out_byte(DMA16_COUNT, count >> 1); /* Low byte of count */
- 27738 out_byte(DMA16_COUNT, count >> 9); /* High byte of count */
- 27739 out_byte(DMA16_MASK, SB_DMA_16 & 3); /* Enable DMA channel */
- 27740 unlock();
- 27741 }
- 27742 }
- 27745 /*===========================================================================*
- 27746 * dsp_setup *
- 27747 *===========================================================================*/
- 27748 PRIVATE void dsp_setup()
- 27749 {
- 27750 /* Set current sample speed */
- 27751 dsp_set_speed(DspSpeed);
- 27752
- 27753 /* Put the speaker on */
- 27754 if (DmaMode == DEV_WRITE)
- 27755 {
- 27756 dsp_command (DSP_CMD_SPKON); /* put speaker on */
- 27757
- 27758 /* Program DSP with dma mode */
- 27759 dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT));
- 27760 }
- 27761 else
- 27762 {
- 27763 dsp_command (DSP_CMD_SPKOFF); /* put speaker off */
- 27764
- 27765 /* Program DSP with dma mode */
- 27766 dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN));
- 27767 }
- 27768
- 27769 /* Program DSP with transfer mode */
- 27770 if (!DspSign)
- 27771 dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US));
- 27772 else
- 27773 dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S));
- 27774
- 27775 /* Give length of fragment to DSP */
- 27776 if (DspBits == 8) /* 8 bit transfer */
- 27777 {
- 27778 /* #bytes - 1 */
- 27779 dsp_command((DspFragmentSize - 1) >> 0);
- 27780 dsp_command((DspFragmentSize - 1) >> 8);
- 27781 }
- 27782 else /* 16 bit transfer */
- 27783 {
- 27784 /* #words - 1 */
- 27785 dsp_command((DspFragmentSize - 1) >> 1);
- 27786 dsp_command((DspFragmentSize - 1) >> 9);
- 27787 }
- 27788 }
- 27789
- 27790
- 27791 /*===========================================================================*
- 27792 * dsp_write *
- 27793 *===========================================================================*/
- 27794 PRIVATE int dsp_write(m_ptr)
- 27795 message *m_ptr;
- 27796 {
- 27797 phys_bytes user_phys;
- 27798 message mess;
- 27799
- 27800 if (m_ptr->COUNT != DspFragmentSize) return EINVAL;
- 27801
- 27802 /* From this user address */
- 27803 user_phys = numap(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, DspFragmentSize);
- 27804 if (user_phys == 0) return EINVAL;
- 27805
- 27806 if (DmaBusy) /* Dma already started */
- 27807 {
- 27808 if (DmaMode != m_ptr->m_type) return EBUSY;
- 27809
- 27810 DmaDone = 0; /* No, we're not done yet */
- 27811
- 27812 /* Wait for next block to become free */
- 27813 receive(HARDWARE, &mess);
- 27814
- 27815 /* Copy first block to dma buffer */
- 27816 phys_copy(user_phys, DmaPhys, (phys_bytes) DspFragmentSize);
- 27817
- 27818 }
- 27819 else /* A new dma transfer has started */
- 27820 {
- 27821 DmaMode = DEV_WRITE; /* Dma mode is writing */
- 27822
- 27823 /* Copy fragment to dma buffer */
- 27824 phys_copy(user_phys, DmaPhys, (phys_bytes) DspFragmentSize);
- 27825
- 27826 /* Set up the dma chip */
- 27827 dsp_dma_setup(DmaPhys, DspFragmentSize);
- 27828
- 27829 /* Set up the DSP */
- 27830 dsp_setup();
- 27831
- 27832 DmaBusy = 1; /* Dma is busy */
- 27833 }
- 27834
- 27835 DmaDone = 1; /* dma done for now */
- 27836
- 27837 return(DspFragmentSize);
- 27838 }
- 27841 /*===========================================================================*
- 27842 * dsp_read *
- 27843 *===========================================================================*/
- 27844 PRIVATE int dsp_read(m_ptr)
- 27845 message *m_ptr;
- 27846 {
- 27847 phys_bytes user_phys;
- 27848 message mess;
- 27849
- 27850 if (m_ptr->COUNT != DspFragmentSize) return EINVAL;
- 27851
- 27852 /* To this user address */
- 27853 user_phys = numap(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, DspFragmentSize);
- 27854 if (user_phys == 0) return EINVAL;
- 27855
- 27856 if (DmaBusy) /* Dma already started */
- 27857 {
- 27858 if (DmaMode != m_ptr->m_type) return EBUSY;
- 27859
- 27860 DmaDone = 0; /* No, we're not done yet */
- 27861
- 27862 /* Wait for a full dma buffer */
- 27863 receive(HARDWARE, &mess);
- 27864
- 27865 /* Copy the buffer */
- 27866 phys_copy(DmaPhys, user_phys, (phys_bytes) DspFragmentSize);
- 27867 }
- 27868 else /* A new dma transfer has started */
- 27869 {
- 27870 DmaMode = DEV_READ; /* Dma mode is reading */
- 27871
- 27872 /* Set up the dma chip */
- 27873 dsp_dma_setup(DmaPhys, DspFragmentSize);
- 27874
- 27875 /* Set up the DSP */
- 27876 dsp_setup();
- 27877
- 27878 DmaBusy = 1; /* Dma has started */
- 27879 DmaDone = 0; /* Dma not done */
- 27880
- 27881 /* Wait for dma to finish with first block */
- 27882 receive(HARDWARE, &mess);
- 27883
- 27884 /* Copy dma buffer to user */
- 27885 phys_copy(DmaPhys, user_phys, (phys_bytes) DspFragmentSize);
- 27886 }
- 27887
- 27888 DmaDone = 1; /* dma done for now */
- 27889
- 27890 return(DspFragmentSize);
- 27891 }
- 27892 #endif /* ENABLE_AUDIO */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/sb16_mixer.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 27900 /* This file contains the driver for the mixer on
- 27901 * a SoundBlaster 16 (ASP) soundcard.
- 27902 *
- 27903 * The driver supports the following operations (using message format m2):
- 27904 *
- 27905 * m_type DEVICE PROC_NR COUNT POSITION ADRRESS
- 27906 * ----------------------------------------------------------------
- 27907 * | DEV_OPEN | device | proc nr | | | |
- 27908 * |------------+---------+---------+---------+---------+---------|
- 27909 * | DEV_CLOSE | device | proc nr | | | |
- 27910 * |------------+---------+---------+---------+---------+---------|
- 27911 * | DEV_IOCTL | device | proc nr |func code| | buf_ptr |
- 27912 * ----------------------------------------------------------------
- 27913 *
- 27914 * The file contains one entry point:
- 27915 *
- 27916 * mixer_task: main entry when system is brought up
- 27917 *
- 27918 * May 20 1995 Author: Michel R. Prevenier
- 27919 */
- 27920
- 27921
- 27922 #include "kernel.h"
- 27923 #include <minix/com.h>
- 27924 #include <minix/callnr.h>
- 27925 #include <sys/ioctl.h>
- 27926 #include <minix/sound.h>
- 27927 #if __minix_vmd
- 27928 #include "config.h"
- 27929 #endif
- 27930 #include "sb16.h"
- 27931
- 27932 #if ENABLE_SB_AUDIO
- 27933
- 27934 /* Function prototypes */
- 27935 FORWARD _PROTOTYPE( int mixer_init, (void));
- 27936 FORWARD _PROTOTYPE( int mixer_open, (message *m_ptr));
- 27937 FORWARD _PROTOTYPE( int mixer_close, (message *m_ptr));
- 27938 FORWARD _PROTOTYPE( int mixer_ioctl, (message *m_ptr));
- 27939 FORWARD _PROTOTYPE( int mixer_get, (int reg));
- 27940 FORWARD _PROTOTYPE( int get_set_volume, (message *m_ptr, int flag));
- 27941 FORWARD _PROTOTYPE( int get_set_input, (message *m_ptr, int flag, int channel));
- 27942 FORWARD _PROTOTYPE( int get_set_output, (message *m_ptr, int flag));
- 27943
- 27944 PRIVATE int mixer_avail = 0; /* Mixer exists? */
- 27945
- 27946
- 27947 /*=========================================================================*
- 27948 * mixer_task *
- 27949 *=========================================================================*/
- 27950 PUBLIC void mixer_task()
- 27951 {
- 27952 message mess;
- 27953 int err, caller, proc_nr;
- 27954
- 27955 /* Here is the main loop of the mixer task. It waits for a message, carries
- 27956 * it out, and sends a reply.
- 27957 */
- 27958 while (TRUE)
- 27959 {
- 27960 receive(ANY, &mess);
- 27961
- 27962 caller = mess.m_source;
- 27963 proc_nr = mess.PROC_NR;
- 27964
- 27965 switch (caller)
- 27966 {
- 27967 case HARDWARE:
- 27968 /* Leftover interrupt. */
- 27969 continue;
- 27970 case FS_PROC_NR:
- 27971 /* The only legitimate caller. */
- 27972 break;
- 27973 default:
- 27974 printf("sb16: got message from %dn", caller);
- 27975 continue;
- 27976 }
- 27977
- 27978 /* Now carry out the work. */
- 27979 switch(mess.m_type)
- 27980 {
- 27981 case DEV_OPEN: err = mixer_open(&mess);break;
- 27982 case DEV_CLOSE: err = mixer_close(&mess);break;
- 27983 case DEV_IOCTL: err = mixer_ioctl(&mess);break;
- 27984 default: err = EINVAL;break;
- 27985 }
- 27986
- 27987 /* Finally, prepare and send the reply message. */
- 27988 mess.m_type = TASK_REPLY;
- 27989 mess.REP_PROC_NR = proc_nr;
- 27990
- 27991 mess.REP_STATUS = err; /* error code */
- 27992 send(caller, &mess); /* send reply to caller */
- 27993 }
- 27994 }
- 27997 /*=========================================================================*
- 27998 * mixer_open *
- 27999 *=========================================================================*/
- 28000 PRIVATE int mixer_open(m_ptr)
- 28001 message *m_ptr;
- 28002 {
- 28003
- 28004 #if SB_DEBUG
- 28005 printf("mixer_openn");
- 28006 #endif
- 28007
- 28008 /* try to detect the mixer type */
- 28009 if (!mixer_avail && !mixer_init() != OK) return EIO;
- 28010
- 28011 return OK;
- 28012 }
- 28015 /*=========================================================================*
- 28016 * mixer_close *
- 28017 *=========================================================================*/
- 28018 PRIVATE int mixer_close(m_ptr)
- 28019 message *m_ptr;
- 28020 {
- 28021
- 28022 #if SB_DEBUG
- 28023 printf("mixer_closen");
- 28024 #endif
- 28025
- 28026 return OK;
- 28027 }
- 28030 /*=========================================================================*
- 28031 * mixer_ioctl *
- 28032 *=========================================================================*/
- 28033 PRIVATE int mixer_ioctl(m_ptr)
- 28034 message *m_ptr;
- 28035 {
- 28036 int status;
- 28037
- 28038 #if SB_DEBUG
- 28039 printf("mixer: got ioctl %dn", m_ptr->REQUEST);
- 28040 #endif
- 28041
- 28042
- 28043 switch(m_ptr->REQUEST)
- 28044 {
- 28045 case MIXIOGETVOLUME: status = get_set_volume(m_ptr, 0);break;
- 28046 case MIXIOSETVOLUME: status = get_set_volume(m_ptr, 1);break;
- 28047 case MIXIOGETINPUTLEFT: status = get_set_input(m_ptr, 0, 0);break;
- 28048 case MIXIOGETINPUTRIGHT: status = get_set_input(m_ptr, 0, 1);break;
- 28049 case MIXIOGETOUTPUT: status = get_set_output(m_ptr, 0);break;
- 28050 case MIXIOSETINPUTLEFT: status = get_set_input(m_ptr, 1, 0);break;
- 28051 case MIXIOSETINPUTRIGHT: status = get_set_input(m_ptr, 1, 1);break;
- 28052 case MIXIOSETOUTPUT: status = get_set_output(m_ptr, 1);break;
- 28053 default: status = ENOTTY;
- 28054 }
- 28055
- 28056 return status;
- 28057 }
- 28060 /*=========================================================================*
- 28061 * mixer_init *
- 28062 *=========================================================================*/
- 28063 PRIVATE int mixer_init()
- 28064 {
- 28065 /* Try to detect the mixer by writing to MIXER_DAC_LEVEL if the
- 28066 * value written can be read back the mixer is there
- 28067 */
- 28068
- 28069 mixer_set(MIXER_DAC_LEVEL, 0x10); /* write something to it */
- 28070 if (mixer_get(MIXER_DAC_LEVEL) != 0x10)
- 28071 {
- 28072 printf("sb16: Mixer not detectedn");
- 28073 return EIO;
- 28074 }
- 28075
- 28076 /* Enable Automatic Gain Control */
- 28077 mixer_set(MIXER_AGC, 0x01);
- 28078
- 28079 #if SB_DEBUG
- 28080 printf("Mixer detectedn");
- 28081 #endif
- 28082
- 28083 mixer_avail = 1;
- 28084 return OK;
- 28085 }
- 28088 /*=========================================================================*
- 28089 * mixer_set *
- 28090 *=========================================================================*/
- 28091 PUBLIC int mixer_set(reg, data)
- 28092 int reg;
- 28093 int data;
- 28094 {
- 28095 int i;
- 28096
- 28097 out_byte(MIXER_REG, reg);
- 28098 for(i=0;i<100;i++);
- 28099 out_byte(MIXER_DATA, data);
- 28100
- 28101 return OK;
- 28102 }
- 28103
- 28104
- 28105 /*=========================================================================*
- 28106 * mixer_get *
- 28107 *=========================================================================*/
- 28108 PRIVATE int mixer_get(reg)
- 28109 int reg;
- 28110 {
- 28111 int i;
- 28112
- 28113 out_byte(MIXER_REG, reg);
- 28114 for(i=0;i<100;i++);
- 28115 return (in_byte(MIXER_DATA) & 0xff);
- 28116 }
- 28117
- 28118
- 28119 /*=========================================================================*
- 28120 * get_set_volume *
- 28121 *=========================================================================*/
- 28122 PRIVATE int get_set_volume(m_ptr, flag)
- 28123 message *m_ptr;
- 28124 int flag; /* 0 = get, 1 = set */
- 28125 {
- 28126 phys_bytes user_phys;
- 28127 struct volume_level level;
- 28128 int cmd_left, cmd_right, shift, max_level;
- 28129
- 28130 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 28131 sizeof(struct volume_level));
- 28132 if (user_phys == 0) return(EFAULT);
- 28133 phys_copy(user_phys, vir2phys(&level), (phys_bytes) sizeof(level));
- 28134
- 28135 shift = 3;
- 28136 max_level = 0x1F;
- 28137
- 28138 switch (level.device)
- 28139 {
- 28140 case Master: { cmd_left = MIXER_MASTER_LEFT;
- 28141 cmd_right = MIXER_MASTER_RIGHT;
- 28142 };break;
- 28143 case Dac: { cmd_left = MIXER_DAC_LEFT;
- 28144 cmd_right = MIXER_DAC_RIGHT;
- 28145 };break;
- 28146 case Fm: { cmd_left = MIXER_FM_LEFT;
- 28147 cmd_right = MIXER_FM_RIGHT;
- 28148 };break;
- 28149 case Cd: { cmd_left = MIXER_CD_LEFT;
- 28150 cmd_right = MIXER_CD_RIGHT;
- 28151 };break;
- 28152 case Line: { cmd_left = MIXER_LINE_LEFT;
- 28153 cmd_right = MIXER_LINE_RIGHT;
- 28154 };break;
- 28155 case Mic: { cmd_left = cmd_right = MIXER_MIC_LEVEL;
- 28156 };break;
- 28157 case Speaker: { cmd_left = cmd_right = MIXER_PC_LEVEL;
- 28158 shift = 6;
- 28159 max_level = 0x03;
- 28160 };break;
- 28161 case Treble: { cmd_left = MIXER_TREBLE_LEFT;
- 28162 cmd_right = MIXER_TREBLE_RIGHT;
- 28163 shift = 4;
- 28164 max_level = 0x0F;
- 28165 };break;
- 28166 case Bass: { cmd_left = MIXER_BASS_LEFT;
- 28167 cmd_right = MIXER_BASS_RIGHT;
- 28168 shift = 4;
- 28169 max_level = 0x0F;
- 28170 };break;
- 28171 default: return EINVAL;
- 28172 }
- 28173
- 28174 if (flag) /* Set volume level */
- 28175 {
- 28176 if (level.right < 0) level.right = 0;
- 28177 else if (level.right > max_level) level.right = max_level;
- 28178 if (level.left < 0) level.left = 0;
- 28179 else if (level.left > max_level) level.left = max_level;
- 28180
- 28181 mixer_set(cmd_right, (level.right << shift));
- 28182 mixer_set(cmd_left, (level.left << shift));
- 28183 }
- 28184 else /* Get volume level */
- 28185 {
- 28186 level.left = mixer_get(cmd_left);
- 28187 level.right = mixer_get(cmd_right);
- 28188
- 28189 level.left >>= shift;
- 28190 level.right >>= shift;
- 28191
- 28192 /* Copy back to user */
- 28193 phys_copy(vir2phys(&level), user_phys, (phys_bytes) sizeof(level));
- 28194 }
- 28195
- 28196 return OK;
- 28197 }
- 28200 /*=========================================================================*
- 28201 * get_set_input *
- 28202 *=========================================================================*/
- 28203 PRIVATE int get_set_input(m_ptr, flag, channel)
- 28204 message *m_ptr;
- 28205 int flag; /* 0 = get, 1 = set */
- 28206 int channel; /* 0 = left, 1 = right */
- 28207 {
- 28208 phys_bytes user_phys;
- 28209 struct inout_ctrl input;
- 28210 int input_cmd, input_mask, mask, del_mask, shift;
- 28211
- 28212 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 28213 sizeof(struct inout_ctrl));
- 28214 if (user_phys == 0) return(EFAULT);
- 28215 phys_copy(user_phys, vir2phys(&input), (phys_bytes) sizeof(input));
- 28216
- 28217 input_cmd = (channel == 0 ? MIXER_IN_LEFT : MIXER_IN_RIGHT);
- 28218
- 28219 mask = mixer_get(input_cmd);
- 28220
- 28221 switch (input.device)
- 28222 {
- 28223 case Fm: { shift = 5;
- 28224 del_mask = 0x1F;
- 28225 };break;
- 28226 case Cd: { shift = 1;
- 28227 del_mask = 0x79;
- 28228 };break;
- 28229 case Line: { shift = 3;
- 28230 del_mask = 0x67;
- 28231 };break;
- 28232 case Mic: { shift = 0;
- 28233 del_mask = 0x7E;
- 28234 };break;
- 28235 default: return EINVAL;
- 28236 }
- 28237
- 28238 if (flag) /* Set input */
- 28239 {
- 28240 input_mask =
- 28241 ((input.left == ON ? 1 : 0) << 1) | (input.right == ON ? 1 : 0);
- 28242
- 28243 if (shift > 0)
- 28244 input_mask <<= shift;
- 28245 else
- 28246 input_mask >>= 1;
- 28247
- 28248 mask &= del_mask;
- 28249 mask |= input_mask;
- 28250
- 28251 mixer_set(input_cmd, mask);
- 28252 }
- 28253 else /* Get input */
- 28254 {
- 28255 if (shift > 0)
- 28256 {
- 28257 input.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
- 28258 input.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
- 28259 }
- 28260 else
- 28261 input.left = ((mask & 1) == 1 ? ON : OFF);
- 28262
- 28263 /* Copy back to user */
- 28264 phys_copy(vir2phys(&input), user_phys, (phys_bytes) sizeof(input));
- 28265 }
- 28266
- 28267 return OK;
- 28268 }
- 28271 /*=========================================================================*
- 28272 * get_set_output *
- 28273 *=========================================================================*/
- 28274 PRIVATE int get_set_output(m_ptr, flag)
- 28275 message *m_ptr;
- 28276 int flag; /* 0 = get, 1 = set */
- 28277 {
- 28278 phys_bytes user_phys;
- 28279 struct inout_ctrl output;
- 28280 int output_mask, mask, del_mask, shift;
- 28281
- 28282 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 28283 sizeof(struct inout_ctrl));
- 28284 if (user_phys == 0) return(EFAULT);
- 28285 phys_copy(user_phys, vir2phys(&output), (phys_bytes) sizeof(output));
- 28286
- 28287 mask = mixer_get(MIXER_OUTPUT_CTRL);
- 28288
- 28289 switch (output.device)
- 28290 {
- 28291 case Cd: { shift = 1;
- 28292 del_mask = 0x79;
- 28293 };break;
- 28294 case Line: { shift = 3;
- 28295 del_mask = 0x67;
- 28296 };break;