COMPLETE.TXT
资源名称:os_source.zip [点击查看]
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:2565k
源码类别:
操作系统开发
开发平台:
C/C++
- 31402 flgs |= 0000100;
- 31403
- 31404 /* RAW - if not ICANON and not ISIG */
- 31405 if (!(tp->tty_termios.c_lflag & (ICANON|ISIG)))
- 31406 flgs |= 0000040;
- 31407
- 31408 /* CRMOD - if ICRNL */
- 31409 if (tp->tty_termios.c_iflag & ICRNL)
- 31410 flgs |= 0000020;
- 31411
- 31412 /* ECHO - if ECHO */
- 31413 if (tp->tty_termios.c_lflag & ECHO)
- 31414 flgs |= 0000010;
- 31415
- 31416 /* CBREAK - if not ICANON and ISIG */
- 31417 if ((tp->tty_termios.c_lflag & (ICANON|ISIG)) == ISIG)
- 31418 flgs |= 0000002;
- 31419
- 31420 sg->sg_flags = flgs;
- 31421 return(OK);
- 31422 }
- 31425 /*===========================================================================*
- 31426 * compat_getc *
- 31427 *===========================================================================*/
- 31428 PRIVATE int compat_getc(tp, tc)
- 31429 tty_t *tp;
- 31430 struct tchars *tc;
- 31431 {
- 31432 /* Translate an old TIOCGETC to the termios equivalent. */
- 31433
- 31434 tc->t_intrc = tp->tty_termios.c_cc[VINTR];
- 31435 tc->t_quitc = tp->tty_termios.c_cc[VQUIT];
- 31436 tc->t_startc = tp->tty_termios.c_cc[VSTART];
- 31437 tc->t_stopc = tp->tty_termios.c_cc[VSTOP];
- 31438 tc->t_brkc = tp->tty_termios.c_cc[VEOL];
- 31439 tc->t_eofc = tp->tty_termios.c_cc[VEOF];
- 31440 return(OK);
- 31441 }
- 31444 /*===========================================================================*
- 31445 * compat_setp *
- 31446 *===========================================================================*/
- 31447 PRIVATE int compat_setp(tp, sg)
- 31448 tty_t *tp;
- 31449 struct sgttyb *sg;
- 31450 {
- 31451 /* Translate an old TIOCSETP to the termios equivalent. */
- 31452 struct termios termios;
- 31453 int flags;
- 31454
- 31455 termios = tp->tty_termios;
- 31456
- 31457 termios.c_cc[VERASE] = sg->sg_erase;
- 31458 termios.c_cc[VKILL] = sg->sg_kill;
- 31459 cfsetispeed(&termios, sgspd2tspd(sg->sg_ispeed & BYTE));
- 31460 cfsetospeed(&termios, sgspd2tspd(sg->sg_ospeed & BYTE));
- 31461 flags = sg->sg_flags;
- 31462
- 31463 /* Input flags */
- 31464
- 31465 /* BRKINT - not changed */
- 31466 /* ICRNL - set if CRMOD is set and not RAW */
- 31467 /* (CRMOD also controls output) */
- 31468 termios.c_iflag &= ~ICRNL;
- 31469 if ((flags & 0000020) && !(flags & 0000040))
- 31470 termios.c_iflag |= ICRNL;
- 31471
- 31472 /* IGNBRK - not changed */
- 31473 /* IGNCR - forced off (ignoring cr's is not supported) */
- 31474 termios.c_iflag &= ~IGNCR;
- 31475
- 31476 /* IGNPAR - not changed */
- 31477 /* INLCR - forced off (mapping nl's to cr's is not supported) */
- 31478 termios.c_iflag &= ~INLCR;
- 31479
- 31480 /* INPCK - not changed */
- 31481 /* ISTRIP - not changed */
- 31482 /* IXOFF - not changed */
- 31483 /* IXON - forced on if not RAW */
- 31484 termios.c_iflag &= ~IXON;
- 31485 if (!(flags & 0000040))
- 31486 termios.c_iflag |= IXON;
- 31487
- 31488 /* PARMRK - not changed */
- 31489
- 31490 /* Output flags */
- 31491
- 31492 /* OPOST - forced on if not RAW */
- 31493 termios.c_oflag &= ~OPOST;
- 31494 if (!(flags & 0000040))
- 31495 termios.c_oflag |= OPOST;
- 31496
- 31497 /* ONLCR - forced on if CRMOD */
- 31498 termios.c_oflag &= ~ONLCR;
- 31499 if (flags & 0000020)
- 31500 termios.c_oflag |= ONLCR;
- 31501
- 31502 /* XTABS - forced on if XTABS */
- 31503 termios.c_oflag &= ~XTABS;
- 31504 if (flags & 0006000)
- 31505 termios.c_oflag |= XTABS;
- 31506
- 31507 /* CLOCAL - not changed */
- 31508 /* CREAD - forced on (receiver is always enabled) */
- 31509 termios.c_cflag |= CREAD;
- 31510
- 31511 /* CSIZE - CS5-CS8 correspond directly to BITS5-BITS8 */
- 31512 termios.c_cflag = (termios.c_cflag & ~CSIZE) | ((flags & 0001400) >> (8-2));
- 31513
- 31514 /* CSTOPB - not changed */
- 31515 /* HUPCL - not changed */
- 31516 /* PARENB - set if EVENP or ODDP is set */
- 31517 termios.c_cflag &= ~PARENB;
- 31518 if (flags & (0000200|0000100))
- 31519 termios.c_cflag |= PARENB;
- 31520
- 31521 /* PARODD - set if ODDP is set */
- 31522 termios.c_cflag &= ~PARODD;
- 31523 if (flags & 0000100)
- 31524 termios.c_cflag |= PARODD;
- 31525
- 31526 /* Local flags */
- 31527
- 31528 /* ECHO - set if ECHO is set */
- 31529 termios.c_lflag &= ~ECHO;
- 31530 if (flags & 0000010)
- 31531 termios.c_lflag |= ECHO;
- 31532
- 31533 /* ECHOE - not changed */
- 31534 /* ECHOK - not changed */
- 31535 /* ECHONL - not changed */
- 31536 /* ICANON - set if neither CBREAK nor RAW */
- 31537 termios.c_lflag &= ~ICANON;
- 31538 if (!(flags & (0000002|0000040)))
- 31539 termios.c_lflag |= ICANON;
- 31540
- 31541 /* IEXTEN - set if not RAW */
- 31542 /* ISIG - set if not RAW */
- 31543 termios.c_lflag &= ~(IEXTEN|ISIG);
- 31544 if (!(flags & 0000040))
- 31545 termios.c_lflag |= (IEXTEN|ISIG);
- 31546
- 31547 /* NOFLSH - not changed */
- 31548 /* TOSTOP - not changed */
- 31549
- 31550 tp->tty_termios = termios;
- 31551 setattr(tp);
- 31552 return(OK);
- 31553 }
- 31556 /*===========================================================================*
- 31557 * compat_setc *
- 31558 *===========================================================================*/
- 31559 PRIVATE int compat_setc(tp, tc)
- 31560 tty_t *tp;
- 31561 struct tchars *tc;
- 31562 {
- 31563 /* Translate an old TIOCSETC to the termios equivalent. */
- 31564 struct termios termios;
- 31565
- 31566 termios = tp->tty_termios;
- 31567
- 31568 termios.c_cc[VINTR] = tc->t_intrc;
- 31569 termios.c_cc[VQUIT] = tc->t_quitc;
- 31570 termios.c_cc[VSTART] = tc->t_startc;
- 31571 termios.c_cc[VSTOP] = tc->t_stopc;
- 31572 termios.c_cc[VEOL] = tc->t_brkc;
- 31573 termios.c_cc[VEOF] = tc->t_eofc;
- 31574
- 31575 tp->tty_termios = termios;
- 31576 setattr(tp);
- 31577 return(OK);
- 31578 }
- 31581 /* Table of termios line speed to sgtty line speed translations. All termios
- 31582 * speeds are present even if sgtty didn't know about them. (Now it does.)
- 31583 */
- 31584 PRIVATE struct s2s {
- 31585 speed_t tspd;
- 31586 u8_t sgspd;
- 31587 } ts2sgs[] = {
- 31588 { B0, 0 },
- 31589 { B50, 50 },
- 31590 { B75, 75 },
- 31591 { B110, 1 },
- 31592 { B134, 134 },
- 31593 { B200, 2 },
- 31594 { B300, 3 },
- 31595 { B600, 6 },
- 31596 { B1200, 12 },
- 31597 { B1800, 18 },
- 31598 { B2400, 24 },
- 31599 { B4800, 48 },
- 31600 { B9600, 96 },
- 31601 { B19200, 192 },
- 31602 { B38400, 195 },
- 31603 { B57600, 194 },
- 31604 { B115200, 193 },
- 31605 };
- 31606
- 31607 /*===========================================================================*
- 31608 * tspd2sgspd *
- 31609 *===========================================================================*/
- 31610 PRIVATE int tspd2sgspd(tspd)
- 31611 speed_t tspd;
- 31612 {
- 31613 /* Translate a termios speed to sgtty speed. */
- 31614 struct s2s *s;
- 31615
- 31616 for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
- 31617 if (s->tspd == tspd) return(s->sgspd);
- 31618 }
- 31619 return 96;
- 31620 }
- 31623 /*===========================================================================*
- 31624 * sgspd2tspd *
- 31625 *===========================================================================*/
- 31626 PRIVATE speed_t sgspd2tspd(sgspd)
- 31627 int sgspd;
- 31628 {
- 31629 /* Translate a sgtty speed to termios speed. */
- 31630 struct s2s *s;
- 31631
- 31632 for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
- 31633 if (s->sgspd == sgspd) return(s->tspd);
- 31634 }
- 31635 return B9600;
- 31636 }
- 31639 #if ENABLE_BINCOMPAT
- 31640 /*===========================================================================*
- 31641 * do_ioctl_compat *
- 31642 *===========================================================================*/
- 31643 PRIVATE void do_ioctl_compat(tp, m_ptr)
- 31644 tty_t *tp;
- 31645 message *m_ptr;
- 31646 {
- 31647 /* Handle the old sgtty ioctl's that packed the sgtty or tchars struct into
- 31648 * the Minix message. Efficient then, troublesome now.
- 31649 */
- 31650 int minor, proc, func, result, r;
- 31651 long flags, erki, spek;
- 31652 u8_t erase, kill, intr, quit, xon, xoff, brk, eof, ispeed, ospeed;
- 31653 struct sgttyb sg;
- 31654 struct tchars tc;
- 31655 message reply_mess;
- 31656
- 31657 minor = m_ptr->TTY_LINE;
- 31658 proc = m_ptr->PROC_NR;
- 31659 func = m_ptr->REQUEST;
- 31660 spek = m_ptr->m2_l1;
- 31661 flags = m_ptr->m2_l2;
- 31662
- 31663 switch(func)
- 31664 {
- 31665 case (('t'<<8) | 8): /* TIOCGETP */
- 31666 r = compat_getp(tp, &sg);
- 31667 erase = sg.sg_erase;
- 31668 kill = sg.sg_kill;
- 31669 ispeed = sg.sg_ispeed;
- 31670 ospeed = sg.sg_ospeed;
- 31671 flags = sg.sg_flags;
- 31672 erki = ((long)ospeed<<24) | ((long)ispeed<<16) | ((long)erase<<8) |kill;
- 31673 break;
- 31674 case (('t'<<8) | 18): /* TIOCGETC */
- 31675 r = compat_getc(tp, &tc);
- 31676 intr = tc.t_intrc;
- 31677 quit = tc.t_quitc;
- 31678 xon = tc.t_startc;
- 31679 xoff = tc.t_stopc;
- 31680 brk = tc.t_brkc;
- 31681 eof = tc.t_eofc;
- 31682 erki = ((long)intr<<24) | ((long)quit<<16) | ((long)xon<<8) | xoff;
- 31683 flags = (eof << 8) | brk;
- 31684 break;
- 31685 case (('t'<<8) | 17): /* TIOCSETC */
- 31686 tc.t_stopc = (spek >> 0) & 0xFF;
- 31687 tc.t_startc = (spek >> 8) & 0xFF;
- 31688 tc.t_quitc = (spek >> 16) & 0xFF;
- 31689 tc.t_intrc = (spek >> 24) & 0xFF;
- 31690 tc.t_brkc = (flags >> 0) & 0xFF;
- 31691 tc.t_eofc = (flags >> 8) & 0xFF;
- 31692 r = compat_setc(tp, &tc);
- 31693 break;
- 31694 case (('t'<<8) | 9): /* TIOCSETP */
- 31695 sg.sg_erase = (spek >> 8) & 0xFF;
- 31696 sg.sg_kill = (spek >> 0) & 0xFF;
- 31697 sg.sg_ispeed = (spek >> 16) & 0xFF;
- 31698 sg.sg_ospeed = (spek >> 24) & 0xFF;
- 31699 sg.sg_flags = flags;
- 31700 r = compat_setp(tp, &sg);
- 31701 break;
- 31702 default:
- 31703 r = ENOTTY;
- 31704 }
- 31705 reply_mess.m_type = TASK_REPLY;
- 31706 reply_mess.REP_PROC_NR = m_ptr->PROC_NR;
- 31707 reply_mess.REP_STATUS = r;
- 31708 reply_mess.m2_l1 = erki;
- 31709 reply_mess.m2_l2 = flags;
- 31710 send(m_ptr->m_source, &reply_mess);
- 31711 }
- 31712 #endif /* ENABLE_BINCOMPAT */
- 31713 #endif /* ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT */
- 31714
- 31715
- 31716
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/wdeth.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 31800 /*
- 31801 wdeth.c
- 31802
- 31803 Created: March 14, 1994 by Philip Homburg
- 31804 */
- 31805
- 31806 #include "kernel.h"
- 31807 #include <net/gen/ether.h>
- 31808 #include <net/gen/eth_io.h>
- 31809 #include "assert.h"
- 31810 INIT_ASSERT
- 31811 #include "dp8390.h"
- 31812 #include "wdeth.h"
- 31813
- 31814 #if ENABLE_NETWORKING
- 31815
- 31816 #if !__minix_vmd
- 31817 #define debug 0
- 31818 #endif
- 31819
- 31820 #define WET_ETHERNET 0x01 /* Ethernet transceiver */
- 31821 #define WET_STARLAN 0x02 /* Starlan transceiver */
- 31822 #define WET_INTERF_CHIP 0x04 /* has a WD83C583 interface chip */
- 31823 #define WET_BRD_16BIT 0x08 /* 16 bit board */
- 31824 #define WET_SLT_16BIT 0x10 /* 16 bit slot */
- 31825 #define WET_790 0x20 /* '790 chip */
- 31826
- 31827 static int we_int_table[8]= { 9, 3, 5, 7, 10, 11, 15, 4 };
- 31828 static int we_790int_table[8]= { 0, 9, 3, 5, 7, 10, 11, 15 };
- 31829
- 31830 _PROTOTYPE( static void we_init, (dpeth_t *dep) );
- 31831 _PROTOTYPE( static void we_stop, (dpeth_t *dep) );
- 31832 _PROTOTYPE( static int we_aliasing, (dpeth_t *dep) );
- 31833 _PROTOTYPE( static int we_interface_chip, (dpeth_t *dep) );
- 31834 _PROTOTYPE( static int we_16bitboard, (dpeth_t *dep) );
- 31835 _PROTOTYPE( static int we_16bitslot, (dpeth_t *dep) );
- 31836 _PROTOTYPE( static int we_ultra, (dpeth_t *dep) );
- 31837
- 31838 /*===========================================================================*
- 31839 * wdeth_probe *
- 31840 *===========================================================================*/
- 31841 int wdeth_probe(dep)
- 31842 dpeth_t *dep;
- 31843 {
- 31844 int sum;
- 31845
- 31846 if (dep->de_linmem == 0)
- 31847 return 0; /* No shared memory, so no WD board */
- 31848
- 31849 sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) +
- 31850 inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) +
- 31851 inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) +
- 31852 inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM);
- 31853 if ((sum & 0xFF) != 0xFF)
- 31854 return 0; /* No ethernet board at this address */
- 31855
- 31856 dep->de_initf= we_init;
- 31857 dep->de_stopf= we_stop;
- 31858 dep->de_prog_IO= 0;
- 31859 return 1;
- 31860 }
- 31863 /*===========================================================================*
- 31864 * we_init *
- 31865 *===========================================================================*/
- 31866 static void we_init(dep)
- 31867 dpeth_t *dep;
- 31868 {
- 31869 int i, int_indx, int_nr;
- 31870 int tlb, rambit, revision;
- 31871 int icr, irr, hwr, b, gcr;
- 31872 int we_type;
- 31873 int sendq_nr;
- 31874
- 31875 assert(dep->de_mode == DEM_ENABLED);
- 31876 assert(!(dep->de_flags & DEF_ENABLED));
- 31877
- 31878 dep->de_address.ea_addr[0] = inb_we(dep, EPL_EA0);
- 31879 dep->de_address.ea_addr[1] = inb_we(dep, EPL_EA1);
- 31880 dep->de_address.ea_addr[2] = inb_we(dep, EPL_EA2);
- 31881 dep->de_address.ea_addr[3] = inb_we(dep, EPL_EA3);
- 31882 dep->de_address.ea_addr[4] = inb_we(dep, EPL_EA4);
- 31883 dep->de_address.ea_addr[5] = inb_we(dep, EPL_EA5);
- 31884
- 31885 dep->de_dp8390_port= dep->de_base_port + EPL_DP8390;
- 31886
- 31887 dep->de_16bit= 0;
- 31888
- 31889 we_type= 0;
- 31890 we_type |= WET_ETHERNET; /* assume ethernet */
- 31891 if (we_ultra(dep))
- 31892 we_type |= WET_790;
- 31893 if (!we_aliasing(dep))
- 31894 {
- 31895 if (we_interface_chip(dep))
- 31896 we_type |= WET_INTERF_CHIP;
- 31897 if (we_16bitboard(dep))
- 31898 {
- 31899 we_type |= WET_BRD_16BIT;
- 31900 if (we_16bitslot(dep))
- 31901 we_type |= WET_SLT_16BIT;
- 31902 }
- 31903 }
- 31904 if (we_type & WET_SLT_16BIT)
- 31905 dep->de_16bit= 1;
- 31906
- 31907 /* look at the on board ram size. */
- 31908 tlb= inb_we(dep, EPL_TLB);
- 31909 revision= tlb & E_TLB_REV;
- 31910 rambit= tlb & E_TLB_RAM;
- 31911
- 31912 if (revision < 2)
- 31913 {
- 31914 dep->de_ramsize= 0x2000; /* 8K */
- 31915 if (we_type & WET_BRD_16BIT)
- 31916 dep->de_ramsize= 0x4000; /* 16K */
- 31917 else if ((we_type & WET_INTERF_CHIP) &&
- 31918 inb_we(dep, EPL_ICR) & E_ICR_MEMBIT)
- 31919 {
- 31920 dep->de_ramsize= 0x8000; /* 32K */
- 31921 }
- 31922 }
- 31923 else
- 31924 {
- 31925 if (we_type & WET_BRD_16BIT)
- 31926 {
- 31927 /* 32K or 16K */
- 31928 dep->de_ramsize= rambit ? 0x8000 : 0x4000;
- 31929 }
- 31930 else
- 31931 {
- 31932 /* 32K or 8K */
- 31933 dep->de_ramsize= rambit ? 0x8000 : 0x2000;
- 31934 }
- 31935 }
- 31936
- 31937 if (we_type & WET_790)
- 31938 {
- 31939 outb_we(dep, EPL_MSR, E_MSR_RESET);
- 31940 if ((we_type & (WET_BRD_16BIT|WET_SLT_16BIT)) ==
- 31941 (WET_BRD_16BIT|WET_SLT_16BIT))
- 31942 {
- 31943 outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E);
- 31944 }
- 31945 }
- 31946 else if (we_type & WET_BRD_16BIT)
- 31947 {
- 31948 if (we_type & WET_SLT_16BIT)
- 31949 {
- 31950 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
- 31951 E_LAAR_LAN16E | E_LAAR_MEM16E);
- 31952 }
- 31953 else
- 31954 {
- 31955 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
- 31956 E_LAAR_LAN16E);
- 31957 }
- 31958 }
- 31959
- 31960 if (we_type & WET_790)
- 31961 {
- 31962 outb_we(dep, EPL_MSR, E_MSR_MENABLE);
- 31963 hwr= inb_we(dep, EPL_790_HWR);
- 31964 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
- 31965 b= inb_we(dep, EPL_790_B);
- 31966 outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) |
- 31967 ((dep->de_linmem >> 11) & 0x40) | (b & 0xb0));
- 31968 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
- 31969 }
- 31970 else
- 31971 {
- 31972 outb_we(dep, EPL_MSR, E_MSR_RESET);
- 31973 outb_we(dep, EPL_MSR, E_MSR_MENABLE |
- 31974 ((dep->de_linmem >> 13) & E_MSR_MEMADDR));
- 31975 }
- 31976
- 31977 if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790))
- 31978 {
- 31979 icr= inb_we(dep, EPL_ICR);
- 31980 irr= inb_we(dep, EPL_IRR);
- 31981 int_indx= (icr & E_ICR_IR2) |
- 31982 ((irr & (E_IRR_IR0|E_IRR_IR1)) >> 5);
- 31983 int_nr= we_int_table[int_indx];
- 31984 #if DEBUG
- 31985 { printf("wdeth.c: encoded irq= %dn", int_nr); }
- 31986 #endif
- 31987 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
- 31988
- 31989 outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
- 31990 }
- 31991 if (we_type & WET_790)
- 31992 {
- 31993 hwr= inb_we(dep, EPL_790_HWR);
- 31994 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
- 31995
- 31996 gcr= inb_we(dep, EPL_790_GCR);
- 31997
- 31998 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
- 31999
- 32000 int_indx= ((gcr & E_790_GCR_IR2) >> 4) |
- 32001 ((gcr & (E_790_GCR_IR1|E_790_GCR_IR0)) >> 2);
- 32002 int_nr= we_790int_table[int_indx];
- 32003 #if DEBUG
- 32004 { printf("wdeth.c: encoded irq= %dn", int_nr); }
- 32005 #endif
- 32006 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
- 32007
- 32008 icr= inb_we(dep, EPL_790_ICR);
- 32009 outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL);
- 32010 }
- 32011
- 32012 /* Strip the "default flag." */
- 32013 dep->de_irq &= ~DEI_DEFAULT;
- 32014
- 32015 if (!debug)
- 32016 {
- 32017 printf("wdeth: WD80%d3 at %X:%d:%lXn",
- 32018 we_type & WET_BRD_16BIT ? 1 : 0,
- 32019 dep->de_base_port, dep->de_irq, dep->de_linmem);
- 32020 }
- 32021 else
- 32022 {
- 32023 printf("wdeth: Western Digital %s%s card %s%s",
- 32024 we_type & WET_BRD_16BIT ? "16-bit " : "",
- 32025 we_type & WET_ETHERNET ? "Ethernet" :
- 32026 we_type & WET_STARLAN ? "Starlan" : "Network",
- 32027 we_type & WET_INTERF_CHIP ? "with an interface chip " : "",
- 32028 we_type & WET_SLT_16BIT ? "in a 16-bit slot " : "");
- 32029 printf(
- 32030 "at I/O address 0x%X, memory address 0x%lX, memory size 0x%X, irq %dn",
- 32031 dep->de_base_port, dep->de_linmem, dep->de_ramsize,
- 32032 dep->de_irq);
- 32033 }
- 32034
- 32035 dep->de_offset_page= 0; /* Shared memory starts at 0 */
- 32036
- 32037 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
- 32038 sendq_nr= dep->de_ramsize / 0x2000;
- 32039 if (sendq_nr < 1)
- 32040 sendq_nr= 1;
- 32041 else if (sendq_nr > SENDQ_NR)
- 32042 sendq_nr= SENDQ_NR;
- 32043 dep->de_sendq_nr= sendq_nr;
- 32044 for (i= 0; i<sendq_nr; i++)
- 32045 dep->de_sendq[i].sq_sendpage= i*SENDQ_PAGES;
- 32046
- 32047 dep->de_startpage= i*SENDQ_PAGES;
- 32048 dep->de_stoppage= dep->de_ramsize / DP_PAGESIZE;
- 32049 }
- 32052 /*===========================================================================*
- 32053 * we_stop *
- 32054 *===========================================================================*/
- 32055 static void we_stop(dep)
- 32056 dpeth_t *dep;
- 32057 {
- 32058 if (dep->de_16bit)
- 32059 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
- 32060 outb_we(dep, EPL_MSR, E_MSR_RESET);
- 32061 outb_we(dep, EPL_MSR, 0);
- 32062 }
- 32065 /*===========================================================================*
- 32066 * we_aliasing *
- 32067 *===========================================================================*/
- 32068 static int we_aliasing(dep)
- 32069 dpeth_t *dep;
- 32070 {
- 32071 /* Determine whether wd8003 hardware performs register aliasing. This implies
- 32072 * an old WD8003E board. */
- 32073
- 32074 if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1))
- 32075 return 0;
- 32076 if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2))
- 32077 return 0;
- 32078 if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3))
- 32079 return 0;
- 32080 if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4))
- 32081 return 0;
- 32082 if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM))
- 32083 return 0;
- 32084 return 1;
- 32085 }
- 32088 /*===========================================================================*
- 32089 * we_interface_chip *
- 32090 *===========================================================================*/
- 32091 static int we_interface_chip(dep)
- 32092 dpeth_t *dep;
- 32093 {
- 32094 /* Determine if the board has an interface chip. */
- 32095
- 32096 outb_we(dep, EPL_GP2, 0x35);
- 32097 if (inb_we(dep, EPL_GP2) != 0x35)
- 32098 return 0;
- 32099 outb_we(dep, EPL_GP2, 0x3A);
- 32100 if (inb_we(dep, EPL_GP2) != 0x3A)
- 32101 return 0;
- 32102 return 1;
- 32103 }
- 32106 /*===========================================================================*
- 32107 * we_16bitboard *
- 32108 *===========================================================================*/
- 32109 static int we_16bitboard(dep)
- 32110 dpeth_t *dep;
- 32111 {
- 32112 /* Determine whether the board is capable of doing 16 bit memory moves.
- 32113 * If the 16 bit enable bit is unchangable by software we'll assume an
- 32114 * 8 bit board.
- 32115 */
- 32116 int icr;
- 32117 u8_t tlb;
- 32118
- 32119 icr= inb_we(dep, EPL_ICR);
- 32120
- 32121 outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT);
- 32122 if (inb_we(dep, EPL_ICR) == icr)
- 32123 {
- 32124 tlb= inb_we(dep, EPL_TLB);
- 32125 #if DEBUG
- 32126 printf("wdeth: tlb= 0x%xn", tlb);
- 32127 #endif
- 32128 return tlb == E_TLB_EB || tlb == E_TLB_E ||
- 32129 tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216C;
- 32130 }
- 32131 outb_we(dep, EPL_ICR, icr);
- 32132 return 1;
- 32133 }
- 32136 /*===========================================================================*
- 32137 * we_16bitslot *
- 32138 *===========================================================================*/
- 32139 static int we_16bitslot(dep)
- 32140 dpeth_t *dep;
- 32141 {
- 32142 /* Determine if the 16 bit board in plugged into a 16 bit slot. */
- 32143 return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT);
- 32144 }
- 32147 /*===========================================================================*
- 32148 * we_ultra *
- 32149 *===========================================================================*/
- 32150 static int we_ultra(dep)
- 32151 dpeth_t *dep;
- 32152 {
- 32153 /* Determine if we has an '790 chip. */
- 32154 u8_t tlb;
- 32155
- 32156 tlb= inb_we(dep, EPL_TLB);
- 32157 return tlb == E_TLB_SMC8216C;
- 32158 }
- 32160 #endif /* ENABLE_NETWORKING */
- 32161
- 32162 /*
- 32163 * $PchHeader: /mount/hd2/minix/sys/kernel/ibm/RCS/wdeth.c,v 1.4 1995/01/12 22:03:57 philip Exp $
- 32164 */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/wini.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 32200 /* wini.c - choose a winchester driver. Author: Kees J. Bot
- 32201 * 28 May 1994
- 32202 * Several different winchester drivers may be compiled
- 32203 * into the kernel, but only one may run. That one is chosen here using
- 32204 * the boot variable 'hd'.
- 32205 */
- 32206
- 32207 #include "kernel.h"
- 32208 #include "driver.h"
- 32209
- 32210 #if ENABLE_WINI
- 32211
- 32212 /* Map driver name to task function. */
- 32213 struct hdmap {
- 32214 char *name;
- 32215 task_t *task;
- 32216 } hdmap[] = {
- 32217
- 32218 #if ENABLE_AT_WINI
- 32219 { "at", at_winchester_task },
- 32220 #endif
- 32221
- 32222 #if ENABLE_BIOS_WINI
- 32223 { "bios", bios_winchester_task },
- 32224 #endif
- 32225
- 32226 #if ENABLE_ESDI_WINI
- 32227 { "esdi", esdi_winchester_task },
- 32228 #endif
- 32229
- 32230 #if ENABLE_XT_WINI
- 32231 { "xt", xt_winchester_task },
- 32232 #endif
- 32233
- 32234 };
- 32235
- 32236
- 32237 /*===========================================================================*
- 32238 * winchester_task *
- 32239 *===========================================================================*/
- 32240 PUBLIC void winchester_task()
- 32241 {
- 32242 /* Call the default or selected winchester task. */
- 32243 char *hd;
- 32244 struct hdmap *map;
- 32245
- 32246 hd = k_getenv("hd");
- 32247
- 32248 for (map = hdmap; map < hdmap + sizeof(hdmap)/sizeof(hdmap[0]); map++) {
- 32249 if (hd == NULL || strcmp(hd, map->name) == 0) {
- 32250 /* Run the selected winchester task. */
- 32251 (*map->task)();
- 32252 }
- 32253 }
- 32254 panic("no hd driver", NO_NUM);
- 32255 }
- 32256 #endif /* ENABLE_WINI */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/xt_wini.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 32300 /* This file contains the device dependent part of a driver for the WD
- 32301 * winchester controller from Western Digital (WX-2 and related controllers).
- 32302 * It was written by Adri Koppes.
- 32303 *
- 32304 * The file contains one entry point:
- 32305 *
- 32306 * xt_winchester_task: main entry when system is brought up
- 32307 *
- 32308 *
- 32309 * Changes:
- 32310 * 10 Apr 1987 by Gary Oliver: use with the Western Digital WX-2.
- 32311 * ? by Harry McGavran: robust operation on turbo clones.
- 32312 * ? by Mike Mitchell: WX-2 auto configure operation.
- 32313 * 2 May 1992 by Kees J. Bot: device dependent/independent split.
- 32314 */
- 32315
- 32316 #include "kernel.h"
- 32317 #include "driver.h"
- 32318 #include "drvlib.h"
- 32319
- 32320 #if ENABLE_XT_WINI
- 32321
- 32322 /* If the DMA buffer is large enough then use it always. */
- 32323 #define USE_BUF (DMA_BUF_SIZE > BLOCK_SIZE)
- 32324
- 32325 /* I/O Ports used by winchester disk task. */
- 32326 #define WIN_DATA 0x320 /* winchester disk controller data register */
- 32327 #define WIN_STATUS 0x321 /* winchester disk controller status register */
- 32328 #define WST_REQ 0x001 /* Request bit */
- 32329 #define WST_INPUT 0x002 /* Set if controller is writing to cpu */
- 32330 #define WST_BUS 0x004 /* Command/status bit */
- 32331 #define WST_BUSY 0x008 /* Busy */
- 32332 #define WST_DRQ 0x010 /* DMA request */
- 32333 #define WST_IRQ 0x020 /* Interrupt request */
- 32334 #define WIN_SELECT 0x322 /* winchester disk controller select port */
- 32335 #define WIN_DMA 0x323 /* winchester disk controller dma register */
- 32336 #define DMA_ADDR 0x006 /* port for low 16 bits of DMA address */
- 32337 #define DMA_TOP 0x082 /* port for top 4 bits of 20-bit DMA addr */
- 32338 #define DMA_COUNT 0x007 /* port for DMA count (count = bytes - 1) */
- 32339 #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flop-flop */
- 32340 #define DMA_MODE 0x00B /* DMA mode port */
- 32341 #define DMA_INIT 0x00A /* DMA init port */
- 32342
- 32343 /* Winchester disk controller command bytes. */
- 32344 #define WIN_RECALIBRATE 0x01 /* command for the drive to recalibrate */
- 32345 #define WIN_SENSE 0x03 /* command for the controller to get its status */
- 32346 #define WIN_READ 0x08 /* command for the drive to read */
- 32347 #define WIN_WRITE 0x0a /* command for the drive to write */
- 32348 #define WIN_SPECIFY 0x0C /* command for the controller to accept params */
- 32349 #define WIN_ECC_READ 0x0D /* command for the controller to read ecc length */
- 32350
- 32351 #define DMA_INT 3 /* Command with dma and interrupt */
- 32352 #define INT 2 /* Command with interrupt, no dma */
- 32353 #define NO_DMA_INT 0 /* Command without dma and interrupt */
- 32354
- 32355 /* DMA channel commands. */
- 32356 #define DMA_READ 0x47 /* DMA read opcode */
- 32357 #define DMA_WRITE 0x4B /* DMA write opcode */
- 32358
- 32359 /* Parameters for the disk drive. */
- 32360 #ifndef NR_SECTORS
- 32361 /* For RLL drives NR_SECTORS has to be defined in the makefile or in config.h.
- 32362 * There is some hope of getting it from the parameter table for these drives,
- 32363 * and then this driver should use wn_sectors like at_wini.c.
- 32364 * Unfortunately it is not standard in XT parameter tables.
- 32365 */
- 32366 #define NR_SECTORS 17 /* number of sectors per track */
- 32367 #endif
- 32368
- 32369 /* Error codes */
- 32370 #define ERR (-1) /* general error */
- 32371 #define ERR_BAD_SECTOR (-2) /* block marked bad detected */
- 32372
- 32373 /* Miscellaneous. */
- 32374 #define MAX_DRIVES 2 /* this driver support two drives (hd0 - hd9) */
- 32375 #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */
- 32376 #define MAX_RESULTS 4 /* max number of bytes controller returns */
- 32377 #define NR_DEVICES (MAX_DRIVES * DEV_PER_DRIVE)
- 32378 #define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
- 32379 #define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
- 32380 #define MAX_WIN_RETRY 32000 /* max # times to try to output to WIN */
- 32381 #if AUTO_BIOS
- 32382 #define AUTO_PARAM 0x1AD /* drive parameter table starts here in sect 0 */
- 32383 #define AUTO_ENABLE 0x10 /* auto bios enabled bit from status reg */
- 32384 /* some start up parameters in order to extract the drive parameter table */
- 32385 /* from the winchester. these should not need changed. */
- 32386 #define AUTO_CYLS 306 /* default number of cylinders */
- 32387 #define AUTO_HEADS 4 /* default number of heads */
- 32388 #define AUTO_RWC 307 /* default reduced write cylinder */
- 32389 #define AUTO_WPC 307 /* default write precomp cylinder */
- 32390 #define AUTO_ECC 11 /* default ecc burst */
- 32391 #define AUTO_CTRL 5 /* default winchester stepping speed byte */
- 32392 #endif
- 32393
- 32394 /* Variables. */
- 32395 PRIVATE struct wini { /* main drive struct, one entry per drive */
- 32396 unsigned wn_cylinders; /* number of cylinders */
- 32397 unsigned wn_heads; /* number of heads */
- 32398 unsigned wn_reduced_wr; /* first cylinder with reduced write current */
- 32399 unsigned wn_precomp; /* first cylinder with write precompensation */
- 32400 unsigned wn_max_ecc; /* maximum ECC burst length */
- 32401 unsigned wn_ctlbyte; /* control byte for COMMANDS (10-Apr-87 GO) */
- 32402 unsigned wn_open_ct; /* in-use count */
- 32403 struct device wn_part[DEV_PER_DRIVE]; /* primary partitions: hd[0-4] */
- 32404 struct device wn_subpart[SUB_PER_DRIVE]; /* subpartitions: hd[1-4][a-d] */
- 32405 } wini[MAX_DRIVES], *w_wn;
- 32406
- 32407 PRIVATE struct trans {
- 32408 struct iorequest_s *tr_iop; /* belongs to this I/O request */
- 32409 unsigned long tr_block; /* first sector to transfer */
- 32410 unsigned tr_count; /* byte count */
- 32411 phys_bytes tr_phys; /* user physical address */
- 32412 phys_bytes tr_dma; /* DMA physical address */
- 32413 } wtrans[NR_IOREQS];
- 32414
- 32415 PRIVATE int w_need_reset = FALSE; /* set when controller must be reset */
- 32416 PRIVATE int nr_drives; /* Number of drives */
- 32417 PRIVATE int w_switches; /* Drive type switches */
- 32418 PRIVATE struct trans *w_tp; /* to add transfer requests */
- 32419 PRIVATE unsigned w_count; /* number of bytes to transfer */
- 32420 PRIVATE unsigned long w_nextblock; /* next block on disk to transfer */
- 32421 PRIVATE int w_opcode; /* DEV_READ or DEV_WRITE */
- 32422 PRIVATE int w_drive; /* selected drive */
- 32423 PRIVATE struct device *w_dv; /* device's base and size */
- 32424 PRIVATE char w_results[MAX_RESULTS];/* the controller can give lots of output */
- 32425
- 32426
- 32427 FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
- 32428 FORWARD _PROTOTYPE( char *w_name, (void) );
- 32429 FORWARD _PROTOTYPE( int w_schedule, (int proc_nr, struct iorequest_s *iop) );
- 32430 FORWARD _PROTOTYPE( int w_finish, (void) );
- 32431 FORWARD _PROTOTYPE( void w_dma_setup, (struct trans *tp, unsigned count) );
- 32432 FORWARD _PROTOTYPE( int w_transfer, (struct trans *tp, unsigned count) );
- 32433 FORWARD _PROTOTYPE( int win_results, (void) );
- 32434 FORWARD _PROTOTYPE( void win_out, (int val) );
- 32435 FORWARD _PROTOTYPE( int w_reset, (void) );
- 32436 FORWARD _PROTOTYPE( int w_handler, (int irq) );
- 32437 FORWARD _PROTOTYPE( int win_specify, (int drive) );
- 32438 FORWARD _PROTOTYPE( int check_init, (void) );
- 32439 FORWARD _PROTOTYPE( int read_ecc, (void) );
- 32440 FORWARD _PROTOTYPE( int hd_wait, (int bits) );
- 32441 FORWARD _PROTOTYPE( int com_out, (int mode, u8_t *command) );
- 32442 FORWARD _PROTOTYPE( void init_params, (void) );
- 32443 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
- 32444 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
- 32445 FORWARD _PROTOTYPE( void w_init, (void) );
- 32446 FORWARD _PROTOTYPE( void copy_param, (char *src, struct wini *dest) );
- 32447 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
- 32448
- 32449
- 32450 /* Entry points to this driver. */
- 32451 PRIVATE struct driver w_dtab = {
- 32452 w_name, /* current device's name */
- 32453 w_do_open, /* open or mount request, initialize device */
- 32454 w_do_close, /* release device */
- 32455 do_diocntl, /* get or set a partition's geometry */
- 32456 w_prepare, /* prepare for I/O on a given minor device */
- 32457 w_schedule, /* precompute cylinder, head, sector, etc. */
- 32458 w_finish, /* do the I/O */
- 32459 nop_cleanup, /* no cleanup needed */
- 32460 w_geometry /* tell the geometry of the disk */
- 32461 };
- 32462
- 32463
- 32464 /*===========================================================================*
- 32465 * xt_winchester_task *
- 32466 *===========================================================================*/
- 32467 PUBLIC void xt_winchester_task()
- 32468 {
- 32469 init_params();
- 32470
- 32471 put_irq_handler(XT_WINI_IRQ, w_handler);
- 32472 enable_irq(XT_WINI_IRQ); /* ready for winchester interrupts */
- 32473
- 32474 driver_task(&w_dtab);
- 32475 }
- 32478 /*===========================================================================*
- 32479 * w_prepare *
- 32480 *===========================================================================*/
- 32481 PRIVATE struct device *w_prepare(device)
- 32482 int device;
- 32483 {
- 32484 /* Prepare for I/O on a device. */
- 32485
- 32486 /* Nothing to transfer as yet. */
- 32487 w_count = 0;
- 32488
- 32489 if (device < NR_DEVICES) { /* hd0, hd1, ... */
- 32490 w_drive = device / DEV_PER_DRIVE; /* save drive number */
- 32491 w_wn = &wini[w_drive];
- 32492 w_dv = &w_wn->wn_part[device % DEV_PER_DRIVE];
- 32493 } else
- 32494 if ((unsigned) (device -= MINOR_hd1a) < NR_SUBDEVS) { /* hd1a, hd1b, ... */
- 32495 w_drive = device / SUB_PER_DRIVE;
- 32496 w_wn = &wini[w_drive];
- 32497 w_dv = &w_wn->wn_subpart[device % SUB_PER_DRIVE];
- 32498 } else {
- 32499 return(NIL_DEV);
- 32500 }
- 32501 return(w_drive < nr_drives ? w_dv : NIL_DEV);
- 32502 }
- 32505 /*===========================================================================*
- 32506 * w_name *
- 32507 *===========================================================================*/
- 32508 PRIVATE char *w_name()
- 32509 {
- 32510 /* Return a name for the current device. */
- 32511 static char name[] = "xt-hd5";
- 32512
- 32513 name[5] = '0' + w_drive * DEV_PER_DRIVE;
- 32514 return name;
- 32515 }
- 32518 /*===========================================================================*
- 32519 * w_schedule *
- 32520 *===========================================================================*/
- 32521 PRIVATE int w_schedule(proc_nr, iop)
- 32522 int proc_nr; /* process doing the request */
- 32523 struct iorequest_s *iop; /* pointer to read or write request */
- 32524 {
- 32525 /* Gather I/O requests on consecutive blocks so they may be read/written
- 32526 * in one command if using a buffer. Check and gather all the requests
- 32527 * and try to finish them as fast as possible if unbuffered.
- 32528 */
- 32529 int r, opcode;
- 32530 unsigned long pos;
- 32531 unsigned nbytes, count, dma_count;
- 32532 unsigned long block;
- 32533 phys_bytes user_phys, dma_phys;
- 32534
- 32535 /* This many bytes to read/write */
- 32536 nbytes = iop->io_nbytes;
- 32537 if ((nbytes & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
- 32538
- 32539 /* From/to this position on the device */
- 32540 pos = iop->io_position;
- 32541 if ((pos & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
- 32542
- 32543 /* To/from this user address */
- 32544 user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
- 32545 if (user_phys == 0) return(iop->io_nbytes = EINVAL);
- 32546
- 32547 /* Read or write? */
- 32548 opcode = iop->io_request & ~OPTIONAL_IO;
- 32549
- 32550 /* Which block on disk and how close to EOF? */
- 32551 if (pos >= w_dv->dv_size) return(OK); /* At EOF */
- 32552 if (pos + nbytes > w_dv->dv_size) nbytes = w_dv->dv_size - pos;
- 32553 block = (w_dv->dv_base + pos) >> SECTOR_SHIFT;
- 32554
- 32555 if (USE_BUF && w_count > 0 && block != w_nextblock) {
- 32556 /* This new request can't be chained to the job being built */
- 32557 if ((r = w_finish()) != OK) return(r);
- 32558 }
- 32559
- 32560 /* The next consecutive block */
- 32561 if (USE_BUF) w_nextblock = block + (nbytes >> SECTOR_SHIFT);
- 32562
- 32563 /* While there are "unscheduled" bytes in the request: */
- 32564 do {
- 32565 count = nbytes;
- 32566
- 32567 if (USE_BUF) {
- 32568 if (w_count == DMA_BUF_SIZE) {
- 32569 /* Can't transfer more than the buffer allows. */
- 32570 if ((r = w_finish()) != OK) return(r);
- 32571 }
- 32572
- 32573 if (w_count + count > DMA_BUF_SIZE)
- 32574 count = DMA_BUF_SIZE - w_count;
- 32575 } else {
- 32576 if (w_tp == wtrans + NR_IOREQS) {
- 32577 /* All transfer slots in use. */
- 32578 if ((r = w_finish()) != OK) return(r);
- 32579 }
- 32580 }
- 32581
- 32582 if (w_count == 0) {
- 32583 /* The first request in a row, initialize. */
- 32584 w_opcode = opcode;
- 32585 w_tp = wtrans;
- 32586 }
- 32587
- 32588 if (USE_BUF) {
- 32589 dma_phys = tmp_phys + w_count;
- 32590 } else {
- 32591 /* Memory chunk to DMA. */
- 32592 dma_phys = user_phys;
- 32593 dma_count = dma_bytes_left(dma_phys);
- 32594
- 32595 if (dma_count < count) {
- 32596 /* Nearing a 64K boundary. */
- 32597 if (dma_count >= SECTOR_SIZE) {
- 32598 /* Can read a few sectors before hitting the
- 32599 * boundary.
- 32600 */
- 32601 count = dma_count & ~SECTOR_MASK;
- 32602 } else {
- 32603 /* Must use the special buffer for this. */
- 32604 count = SECTOR_SIZE;
- 32605 dma_phys = tmp_phys;
- 32606 }
- 32607 }
- 32608 }
- 32609
- 32610 /* Store I/O parameters */
- 32611 w_tp->tr_iop = iop;
- 32612 w_tp->tr_block = block;
- 32613 w_tp->tr_count = count;
- 32614 w_tp->tr_phys = user_phys;
- 32615 w_tp->tr_dma = dma_phys;
- 32616
- 32617 /* Update counters */
- 32618 w_tp++;
- 32619 w_count += count;
- 32620 block += count >> SECTOR_SHIFT;
- 32621 user_phys += count;
- 32622 nbytes -= count;
- 32623 } while (nbytes > 0);
- 32624
- 32625 return(OK);
- 32626 }
- 32629 /*===========================================================================*
- 32630 * w_finish *
- 32631 *===========================================================================*/
- 32632 PRIVATE int w_finish()
- 32633 {
- 32634 /* Carry out the I/O requests gathered in wtrans[]. */
- 32635
- 32636 struct trans *tp = wtrans, *tp2;
- 32637 unsigned count;
- 32638 int r, errors = 0, many = USE_BUF;
- 32639
- 32640 if (w_count == 0) return(OK); /* Spurious finish. */
- 32641
- 32642 do {
- 32643 if (w_opcode == DEV_WRITE) {
- 32644 tp2 = tp;
- 32645 count = 0;
- 32646 do {
- 32647 if (USE_BUF || tp2->tr_dma == tmp_phys) {
- 32648 phys_copy(tp2->tr_phys, tp2->tr_dma,
- 32649 (phys_bytes) tp2->tr_count);
- 32650 }
- 32651 count += tp2->tr_count;
- 32652 tp2++;
- 32653 } while (many && count < w_count);
- 32654 } else {
- 32655 count = many ? w_count : tp->tr_count;
- 32656 }
- 32657
- 32658 /* First check to see if a reset is needed. */
- 32659 if (w_need_reset) w_reset();
- 32660
- 32661 /* Now set up the DMA chip. */
- 32662 w_dma_setup(tp, count);
- 32663
- 32664 /* Perform the transfer. */
- 32665 r = w_transfer(tp, count);
- 32666
- 32667 if (r != OK) {
- 32668 /* An error occurred, try again block by block unless */
- 32669 if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS)
- 32670 return(tp->tr_iop->io_nbytes = EIO);
- 32671
- 32672 /* Reset if halfway, but bail out if optional I/O. */
- 32673 if (errors == MAX_ERRORS / 2) {
- 32674 w_need_reset = TRUE;
- 32675 if (tp->tr_iop->io_request & OPTIONAL_IO)
- 32676 return(tp->tr_iop->io_nbytes = EIO);
- 32677 }
- 32678 many = 0;
- 32679 continue;
- 32680 }
- 32681 errors = 0;
- 32682
- 32683 w_count -= count;
- 32684
- 32685 do {
- 32686 if (w_opcode == DEV_READ) {
- 32687 if (USE_BUF || tp->tr_dma == tmp_phys) {
- 32688 phys_copy(tp->tr_dma, tp->tr_phys,
- 32689 (phys_bytes) tp->tr_count);
- 32690 }
- 32691 }
- 32692 tp->tr_iop->io_nbytes -= tp->tr_count;
- 32693 count -= tp->tr_count;
- 32694 tp++;
- 32695 } while (count > 0);
- 32696 } while (w_count > 0);
- 32697
- 32698 return(OK);
- 32699 }
- 32702 /*==========================================================================*
- 32703 * w_dma_setup *
- 32704 *==========================================================================*/
- 32705 PRIVATE void w_dma_setup(tp, count)
- 32706 struct trans *tp; /* pointer to the transfer struct */
- 32707 unsigned count; /* bytes to transfer */
- 32708 {
- 32709 /* The IBM PC can perform DMA operations by using the DMA chip. To use it,
- 32710 * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
- 32711 * to by read from or written to, the byte count minus 1, and a read or write
- 32712 * opcode. This routine sets up the DMA chip. Note that the chip is not
- 32713 * capable of doing a DMA across a 64K boundary (e.g., you can't read a
- 32714 * 512-byte block starting at physical address 65520).
- 32715 */
- 32716
- 32717 /* Set up the DMA registers. */
- 32718 out_byte(DMA_FLIPFLOP, 0); /* write anything to reset it */
- 32719 out_byte(DMA_MODE, w_opcode == DEV_WRITE ? DMA_WRITE : DMA_READ);
- 32720 out_byte(DMA_ADDR, (int) tp->tr_dma >> 0);
- 32721 out_byte(DMA_ADDR, (int) tp->tr_dma >> 8);
- 32722 out_byte(DMA_TOP, (int) (tp->tr_dma >> 16));
- 32723 out_byte(DMA_COUNT, (count - 1) >> 0);
- 32724 out_byte(DMA_COUNT, (count - 1) >> 8);
- 32725 }
- 32728 /*=========================================================================*
- 32729 * w_transfer *
- 32730 *=========================================================================*/
- 32731 PRIVATE int w_transfer(tp, count)
- 32732 struct trans *tp; /* pointer to the transfer struct */
- 32733 unsigned count; /* transferring count bytes */
- 32734 {
- 32735 /* Read or write count bytes starting with tp->tr_block. */
- 32736
- 32737 unsigned cylinder, sector, head, secspcyl = w_wn->wn_heads * NR_SECTORS;
- 32738 u8_t command[6];
- 32739 message mess;
- 32740
- 32741 cylinder = tp->tr_block / secspcyl;
- 32742 head = (tp->tr_block % secspcyl) / NR_SECTORS;
- 32743 sector = tp->tr_block % NR_SECTORS;
- 32744
- 32745 /* The command is issued by outputting 6 bytes to the controller chip. */
- 32746 command[0] = w_opcode == DEV_WRITE ? WIN_WRITE : WIN_READ;
- 32747 command[1] = head | (w_drive << 5);
- 32748 command[2] = ((cylinder & 0x0300) >> 2) | sector;
- 32749 command[3] = cylinder & 0xFF;
- 32750 command[4] = count >> SECTOR_SHIFT;
- 32751 command[5] = w_wn->wn_ctlbyte;
- 32752
- 32753 if (com_out(DMA_INT, command) != OK)
- 32754 return(ERR);
- 32755
- 32756 out_byte(DMA_INIT, 3); /* initialize DMA */
- 32757
- 32758 /* Block, waiting for disk interrupt. */
- 32759 receive(HARDWARE, &mess);
- 32760
- 32761 /* Get controller status and check for errors. */
- 32762 if (win_results() == OK)
- 32763 return(OK);
- 32764 if ((w_results[0] & 63) == 24)
- 32765 read_ecc();
- 32766 else
- 32767 w_need_reset = TRUE;
- 32768 return(ERR);
- 32769 }
- 32772 /*==========================================================================*
- 32773 * win_results *
- 32774 *==========================================================================*/
- 32775 PRIVATE int win_results()
- 32776 {
- 32777 /* Extract results from the controller after an operation. */
- 32778
- 32779 int i, status;
- 32780 u8_t command[6];
- 32781
- 32782 status = in_byte(WIN_DATA);
- 32783 out_byte(WIN_DMA, 0);
- 32784 if (!(status & 2)) /* Test "error" bit */
- 32785 return(OK);
- 32786 command[0] = WIN_SENSE;
- 32787 command[1] = w_drive << 5;
- 32788 if (com_out(NO_DMA_INT, command) != OK)
- 32789 return(ERR);
- 32790
- 32791 /* Loop, extracting bytes from WIN */
- 32792 for (i = 0; i < MAX_RESULTS; i++) {
- 32793 if (hd_wait(WST_REQ) != OK)
- 32794 return(ERR);
- 32795 status = in_byte(WIN_DATA);
- 32796 w_results[i] = status & BYTE;
- 32797 }
- 32798 if (hd_wait(WST_REQ) != OK) /* Missing from */
- 32799 return (ERR); /* Original. 11-Apr-87 G.O. */
- 32800
- 32801 status = in_byte(WIN_DATA); /* Read "error" flag */
- 32802
- 32803 if (((status & 2) != 0) || (w_results[0] & 0x3F)) {
- 32804 return(ERR);
- 32805 } else
- 32806 return(OK);
- 32807 }
- 32810 /*===========================================================================*
- 32811 * win_out *
- 32812 *===========================================================================*/
- 32813 PRIVATE void win_out(val)
- 32814 int val; /* write this byte to winchester disk controller */
- 32815 {
- 32816 /* Output a byte to the controller. This is not entirely trivial, since you
- 32817 * can only write to it when it is listening, and it decides when to listen.
- 32818 * If the controller refuses to listen, the WIN chip is given a hard reset.
- 32819 */
- 32820 int r;
- 32821
- 32822 if (w_need_reset) return; /* if controller is not listening, return */
- 32823
- 32824 do {
- 32825 r = in_byte(WIN_STATUS);
- 32826 } while((r & (WST_REQ | WST_BUSY)) == WST_BUSY);
- 32827
- 32828 out_byte(WIN_DATA, val);
- 32829 }
- 32832 /*===========================================================================*
- 32833 * w_reset *
- 32834 *===========================================================================*/
- 32835 PRIVATE int w_reset()
- 32836 {
- 32837 /* Issue a reset to the controller. This is done after any catastrophe,
- 32838 * like the controller refusing to respond.
- 32839 */
- 32840
- 32841 int r, i, drive;
- 32842 u8_t command[6];
- 32843 message mess;
- 32844
- 32845 /* Strobe reset bit low. */
- 32846 out_byte(WIN_STATUS, 0);
- 32847
- 32848 milli_delay(5); /* Wait for a while */
- 32849
- 32850 out_byte(WIN_SELECT, 0); /* Issue select pulse */
- 32851 for (i = 0; i < MAX_WIN_RETRY; i++) {
- 32852 r = in_byte(WIN_STATUS);
- 32853 if (r & (WST_DRQ | WST_IRQ))
- 32854 return(ERR);
- 32855
- 32856 if ((r & (WST_BUSY | WST_BUS | WST_REQ)) ==
- 32857 (WST_BUSY | WST_BUS | WST_REQ))
- 32858 break;
- 32859 }
- 32860
- 32861 if (i == MAX_WIN_RETRY) {
- 32862 printf("%s: reset failed, status = %xn", w_name(), r);
- 32863 return(ERR);
- 32864 }
- 32865
- 32866 /* Reset succeeded. Tell WIN drive parameters. */
- 32867 w_need_reset = FALSE;
- 32868
- 32869 for (drive = 0; drive < nr_drives; drive++) {
- 32870 if (win_specify(drive) != OK)
- 32871 return (ERR);
- 32872
- 32873 command[0] = WIN_RECALIBRATE;
- 32874 command[1] = drive << 5;
- 32875 command[5] = wini[drive].wn_ctlbyte;
- 32876
- 32877 if (com_out(INT, command) != OK)
- 32878 return(ERR);
- 32879
- 32880 receive(HARDWARE, &mess);
- 32881
- 32882 if (win_results() != OK) {
- 32883 /* No actual drive present? */
- 32884 nr_drives = drive;
- 32885 }
- 32886 }
- 32887 return(nr_drives > 0 ? OK : ERR);
- 32888 }
- 32891 /*==========================================================================*
- 32892 * w_handler *
- 32893 *==========================================================================*/
- 32894 PRIVATE int w_handler(irq)
- 32895 int irq;
- 32896 {
- 32897 /* Disk interrupt, send message to winchester task and reenable interrupts. */
- 32898
- 32899 int r, i;
- 32900
- 32901 out_byte(DMA_INIT, 0x07); /* Disable int from DMA */
- 32902
- 32903 for (i = 0; i < MAX_WIN_RETRY; ++i) {
- 32904 r = in_byte(WIN_STATUS);
- 32905 if (r & WST_IRQ)
- 32906 break; /* Exit if end of int */
- 32907 }
- 32908
- 32909 interrupt(WINCHESTER);
- 32910 return 1;
- 32911 }
- 32914 /*============================================================================*
- 32915 * win_specify *
- 32916 *============================================================================*/
- 32917 PRIVATE int win_specify(drive)
- 32918 int drive;
- 32919 {
- 32920 struct wini *wn = &wini[drive];
- 32921 u8_t command[6];
- 32922
- 32923 command[0] = WIN_SPECIFY; /* Specify some parameters */
- 32924 command[1] = drive << 5; /* Drive number */
- 32925
- 32926 if (com_out(NO_DMA_INT, command) != OK) /* Output command block */
- 32927 return(ERR);
- 32928
- 32929 /* No. of cylinders (high byte) */
- 32930 win_out(wn->wn_cylinders >> 8);
- 32931
- 32932 /* No. of cylinders (low byte) */
- 32933 win_out(wn->wn_cylinders);
- 32934
- 32935 /* No. of heads */
- 32936 win_out(wn->wn_heads);
- 32937
- 32938 /* Start reduced write (high byte) */
- 32939 win_out(wn->wn_reduced_wr >> 8);
- 32940
- 32941 /* Start reduced write (low byte) */
- 32942 win_out(wn->wn_reduced_wr);
- 32943
- 32944 /* Start write precompensation (high byte) */
- 32945 win_out(wn->wn_precomp >> 8);
- 32946
- 32947 /* Start write precompensation (low byte) */
- 32948 win_out(wn->wn_precomp);
- 32949
- 32950 /* Ecc burst length */
- 32951 win_out(wn->wn_max_ecc);
- 32952
- 32953 if (check_init() != OK) { /* See if controller accepted parameters */
- 32954 w_need_reset = TRUE;
- 32955 return(ERR);
- 32956 } else
- 32957 return(OK);
- 32958 }
- 32961 /*============================================================================*
- 32962 * check_init *
- 32963 *============================================================================*/
- 32964 PRIVATE int check_init()
- 32965 {
- 32966 /* Routine to check if controller accepted the parameters */
- 32967 int r, s;
- 32968
- 32969 if (hd_wait(WST_REQ | WST_INPUT) == OK) {
- 32970 r = in_byte(WIN_DATA);
- 32971
- 32972 do {
- 32973 s = in_byte(WIN_STATUS);
- 32974 } while(s & WST_BUSY); /* Loop while still busy */
- 32975
- 32976 if (r & 2) /* Test error bit */
- 32977 return(ERR);
- 32978 else
- 32979 return(OK);
- 32980 } else
- 32981 return (ERR); /* Missing from original: 11-Apr-87 G.O. */
- 32982 }
- 32985 /*============================================================================*
- 32986 * read_ecc *
- 32987 *============================================================================*/
- 32988 PRIVATE int read_ecc()
- 32989 {
- 32990 /* Read the ecc burst-length and let the controller correct the data */
- 32991
- 32992 int r;
- 32993 u8_t command[6];
- 32994
- 32995 command[0] = WIN_ECC_READ;
- 32996 if (com_out(NO_DMA_INT, command) == OK && hd_wait(WST_REQ) == OK) {
- 32997 r = in_byte(WIN_DATA);
- 32998 if (hd_wait(WST_REQ) == OK) {
- 32999 r = in_byte(WIN_DATA);
- 33000 if (r & 1)
- 33001 w_need_reset = TRUE;
- 33002 }
- 33003 }
- 33004 return(ERR);
- 33005 }
- 33008 /*============================================================================*
- 33009 * hd_wait *
- 33010 *============================================================================*/
- 33011 PRIVATE int hd_wait(bits)
- 33012 int bits;
- 33013 {
- 33014 /* Wait until the controller is ready to receive a command or send status */
- 33015
- 33016 int r, i = 0;
- 33017
- 33018 do {
- 33019 r = in_byte(WIN_STATUS) & bits;
- 33020 } while ((i++ < MAX_WIN_RETRY) && r != bits); /* Wait for ALL bits */
- 33021
- 33022 if (i >= MAX_WIN_RETRY) {
- 33023 w_need_reset = TRUE;
- 33024 return(ERR);
- 33025 } else
- 33026 return(OK);
- 33027 }
- 33030 /*============================================================================*
- 33031 * com_out *
- 33032 *============================================================================*/
- 33033 PRIVATE int com_out(mode, commandp)
- 33034 int mode;
- 33035 u8_t *commandp;
- 33036 {
- 33037 /* Output the command block to the winchester controller and return status */
- 33038
- 33039 int i, r;
- 33040
- 33041 out_byte(WIN_DMA, mode);
- 33042 out_byte(WIN_SELECT, mode);
- 33043 for (i = 0; i < MAX_WIN_RETRY; i++) {
- 33044 r = in_byte(WIN_STATUS);
- 33045 if (r & WST_BUSY)
- 33046 break;
- 33047 }
- 33048
- 33049 if (i == MAX_WIN_RETRY) {
- 33050 w_need_reset = TRUE;
- 33051 return(ERR);
- 33052 }
- 33053
- 33054
- 33055 for (i = 0; i < 6; i++) {
- 33056 if (hd_wait(WST_REQ) != OK)
- 33057 break; /* No data request pending */
- 33058
- 33059 r = in_byte(WIN_STATUS);
- 33060
- 33061 if ((r & (WST_BUSY | WST_BUS | WST_INPUT)) !=
- 33062 (WST_BUSY | WST_BUS))
- 33063 break;
- 33064
- 33065 out_byte(WIN_DATA, commandp[i]);
- 33066 }
- 33067
- 33068 if (i != 6)
- 33069 return(ERR);
- 33070 else
- 33071 return(OK);
- 33072 }
- 33075 /*==========================================================================*
- 33076 * init_params *
- 33077 *==========================================================================*/
- 33078 PRIVATE void init_params()
- 33079 {
- 33080 /* This routine is called at startup to initialize the number of drives and
- 33081 * the controller.
- 33082 */
- 33083 u16_t parv[2];
- 33084 unsigned int drive;
- 33085 int dtype;
- 33086 phys_bytes address, buf_phys;
- 33087 char buf[16];
- 33088
- 33089 /* Get the number of drives from the bios */
- 33090 buf_phys = vir2phys(buf);
- 33091 phys_copy(0x475L, buf_phys, 1L);
- 33092 nr_drives = buf[0] & 0xFF;
- 33093 if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
- 33094
- 33095 /* Read the switches from the controller */
- 33096 w_switches = in_byte(WIN_SELECT);
- 33097
- 33098 #if AUTO_BIOS
- 33099 /* If no auto configuration or not enabled then go to the ROM. */
- 33100 if (!(w_switches & AUTO_ENABLE)) {
- 33101 #endif
- 33102 for (drive = 0; drive < nr_drives; drive++) {
- 33103 /* Calculate the drive type */
- 33104 dtype = (w_switches >> (2 * drive)) & 03;
- 33105
- 33106 /* Copy the BIOS parameter vector */
- 33107 phys_copy(WINI_0_PARM_VEC * 4L, vir2phys(parv), 4L);
- 33108
- 33109 /* Calculate the parameters' address and copy them to buf */
- 33110 address = hclick_to_physb(parv[1]) + parv[0] + 16 * dtype;
- 33111 phys_copy(address, buf_phys, 16L);
- 33112
- 33113 /* Copy the parameters to the structure of the drive. */
- 33114 copy_param(buf, &wini[drive]);
- 33115 }
- 33116 #if AUTO_BIOS
- 33117 }
- 33118 #endif
- 33119 }
- 33122 /*============================================================================*
- 33123 * w_do_open *
- 33124 *============================================================================*/
- 33125 PRIVATE int w_do_open(dp, m_ptr)
- 33126 struct driver *dp;
- 33127 message *m_ptr;
- 33128 {
- 33129 /* Device open: Initialize the controller and read the partition table. */
- 33130
- 33131 static int init_done = FALSE;
- 33132
- 33133 if (!init_done) { w_init(); init_done = TRUE; }
- 33134
- 33135 if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
- 33136
- 33137 if (w_wn->wn_open_ct++ == 0) {
- 33138 /* Partition the disk. */
- 33139 partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY);
- 33140 }
- 33141 return(OK);
- 33142 }
- 33145 /*============================================================================*
- 33146 * w_do_close *
- 33147 *============================================================================*/
- 33148 PRIVATE int w_do_close(dp, m_ptr)
- 33149 struct driver *dp;
- 33150 message *m_ptr;
- 33151 {
- 33152 /* Device close: Release a device. */
- 33153
- 33154 if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
- 33155 w_wn->wn_open_ct--;
- 33156 return(OK);
- 33157 }
- 33160 /*==========================================================================*
- 33161 * w_init *
- 33162 *==========================================================================*/
- 33163 PRIVATE void w_init()
- 33164 {
- 33165 /* Initialize the controller. */
- 33166
- 33167 int drive;
- 33168 struct wini *wn;
- 33169 #if AUTO_BIOS
- 33170 message mess;
- 33171
- 33172 for (drive = 0; drive < nr_drives; drive++) {
- 33173 /* Get the drive parameters from sector zero of the drive if the
- 33174 * autoconfig mode of the controller has been selected.
- 33175 */
- 33176 if (w_switches & AUTO_ENABLE) {
- 33177 /* Set up some phony parameters so that we can read the
- 33178 * first sector from the winchester. All drives will have
- 33179 * one cylinder and one head but set up initially to the
- 33180 * mini scribe drives from IBM.
- 33181 */
- 33182 wn = &wini[drive];
- 33183 wn->wn_cylinders = AUTO_CYLS;
- 33184 wn->wn_heads = AUTO_HEADS;
- 33185 wn->wn_reduced_wr = AUTO_RWC;
- 33186 wn->wn_precomp = AUTO_WPC;
- 33187 wn->wn_max_ecc = AUTO_ECC;
- 33188 wn->wn_ctlbyte = AUTO_CTRL;
- 33189 wn->wn_part[0].dv_size = SECTOR_SIZE;
- 33190 }
- 33191 }
- 33192
- 33193 /* Initialize controller to read parameters from the drives. */
- 33194 if (nr_drives > 0 && w_reset() != OK) nr_drives = 0;
- 33195
- 33196 for (drive = 0; drive < nr_drives; drive++) {
- 33197 if (w_switches & AUTO_ENABLE) {
- 33198 /* read the first sector from the drive */
- 33199 mess.DEVICE = drive * DEV_PER_DRIVE;
- 33200 mess.POSITION = 0L;
- 33201 mess.COUNT = SECTOR_SIZE;
- 33202 mess.ADDRESS = (char *) tmp_buf;
- 33203 mess.PROC_NR = WINCHESTER;
- 33204 mess.m_type = DEV_READ;
- 33205 if (do_rdwt(&w_dtab, &mess) != SECTOR_SIZE) {
- 33206 printf("%s: can't read parametersn", w_name());
- 33207 nr_drives = drive;
- 33208 break;
- 33209 }
- 33210
- 33211 /* save the parameter tables for later use */
- 33212 copy_param(&tmp_buf[AUTO_PARAM], &wini[drive]);
- 33213 }
- 33214 }
- 33215 #endif
- 33216
- 33217 if (nr_drives > 0 && w_reset() != OK) nr_drives = 0;
- 33218
- 33219 /* Set the size of each disk. */
- 33220 for (drive = 0; drive < nr_drives; drive++) {
- 33221 (void) w_prepare(drive * DEV_PER_DRIVE);
- 33222 wn = w_wn;
- 33223 wn->wn_part[0].dv_size = ((unsigned long) wn->wn_cylinders *
- 33224 wn->wn_heads * NR_SECTORS) << SECTOR_SHIFT;
- 33225 printf("%s: %d cylinders, %d heads, %d sectors per trackn",
- 33226 w_name(), wn->wn_cylinders, wn->wn_heads, NR_SECTORS);
- 33227 }
- 33228 }
- 33231 /*==========================================================================*
- 33232 * copy_param *
- 33233 *==========================================================================*/
- 33234 PRIVATE void copy_param(src, dest)
- 33235 char *src;
- 33236 struct wini *dest;
- 33237 {
- 33238 /* This routine copies the parameters from src to dest. */
- 33239
- 33240 dest->wn_cylinders = bp_cylinders(src);
- 33241 dest->wn_heads = bp_heads(src);
- 33242 dest->wn_reduced_wr = bp_reduced_wr(src);
- 33243 dest->wn_precomp = bp_precomp(src);
- 33244 dest->wn_max_ecc = bp_max_ecc(src);
- 33245 dest->wn_ctlbyte = bp_ctlbyte(src);
- 33246 }
- 33249 /*============================================================================*
- 33250 * w_geometry *
- 33251 *============================================================================*/
- 33252 PRIVATE void w_geometry(entry)
- 33253 struct partition *entry;
- 33254 {
- 33255 entry->cylinders = w_wn->wn_cylinders;
- 33256 entry->heads = w_wn->wn_heads;
- 33257 entry->sectors = NR_SECTORS;
- 33258 }
- 33259 #endif /* ENABLE_XT_WINI */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/klib.s
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 33300 #
- 33301 ! Chooses between the 8086 and 386 versions of the low level kernel code.
- 33302
- 33303 #include <minix/config.h>
- 33304 #if _WORD_SIZE == 2
- 33305 #include "klib88.s"
- 33306 #else
- 33307 #include "klib386.s"
- 33308 #endif
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/klib386.s
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 33400 #
- 33401 ! sections
- 33402
- 33403 .sect .text; .sect .rom; .sect .data; .sect .bss
- 33404
- 33405 #include <minix/config.h>
- 33406 #include <minix/const.h>
- 33407 #include "const.h"
- 33408 #include "sconst.h"
- 33409 #include "protect.h"
- 33410
- 33411 ! This file contains a number of assembly code utility routines needed by the
- 33412 ! kernel. They are:
- 33413
- 33414 .define _monitor ! exit Minix and return to the monitor
- 33415 .define _check_mem ! check a block of memory, return the valid size
- 33416 .define _cp_mess ! copies messages from source to destination
- 33417 .define _exit ! dummy for library routines
- 33418 .define __exit ! dummy for library routines
- 33419 .define ___exit ! dummy for library routines
- 33420 .define ___main ! dummy for GCC
- 33421 .define _in_byte ! read a byte from a port and return it
- 33422 .define _in_word ! read a word from a port and return it
- 33423 .define _out_byte ! write a byte to a port
- 33424 .define _out_word ! write a word to a port
- 33425 .define _port_read ! transfer data from (disk controller) port to memory
- 33426 .define _port_read_byte ! likewise byte by byte
- 33427 .define _port_write ! transfer data from memory to (disk controller) port
- 33428 .define _port_write_byte ! likewise byte by byte
- 33429 .define _lock ! disable interrupts
- 33430 .define _unlock ! enable interrupts
- 33431 .define _enable_irq ! enable an irq at the 8259 controller
- 33432 .define _disable_irq ! disable an irq
- 33433 .define _phys_copy ! copy data from anywhere to anywhere in memory
- 33434 .define _mem_rdw ! copy one word from [segment:offset]
- 33435 .define _reset ! reset the system
- 33436 .define _mem_vid_copy ! copy data to video ram
- 33437 .define _vid_vid_copy ! move data in video ram
- 33438 .define _level0 ! call a function at level 0
- 33439
- 33440 ! The routines only guarantee to preserve the registers the C compiler
- 33441 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
- 33442 ! direction bit in the flags).
- 33443
- 33444 ! imported variables
- 33445
- 33446 .sect .bss
- 33447 .extern _mon_return, _mon_sp
- 33448 .extern _irq_use
- 33449 .extern _blank_color
- 33450 .extern _ext_memsize
- 33451 .extern _gdt
- 33452 .extern _low_memsize
- 33453 .extern _sizes
- 33454 .extern _vid_seg
- 33455 .extern _vid_size
- 33456 .extern _vid_mask
- 33457 .extern _level0_func
- 33458
- 33459 .sect .text
- 33460 !*===========================================================================*
- 33461 !* monitor *
- 33462 !*===========================================================================*
- 33463 ! PUBLIC void monitor();
- 33464 ! Return to the monitor.
- 33465
- 33466 _monitor:
- 33467 mov eax, (_reboot_code) ! address of new parameters
- 33468 mov esp, (_mon_sp) ! restore monitor stack pointer
- 33469 o16 mov dx, SS_SELECTOR ! monitor data segment
- 33470 mov ds, dx
- 33471 mov es, dx
- 33472 mov fs, dx
- 33473 mov gs, dx
- 33474 mov ss, dx
- 33475 pop edi
- 33476 pop esi
- 33477 pop ebp
- 33478 o16 retf ! return to the monitor
- 33479
- 33480
- 33481 #if ENABLE_BIOS_WINI
- 33482 !*===========================================================================*
- 33483 !* bios13 *
- 33484 !*===========================================================================*
- 33485 ! PUBLIC void bios13();
- 33486 .define _bios13
- 33487 _bios13:
- 33488 cmpb (_mon_return), 0 ! is the monitor there?
- 33489 jnz 0f
- 33490 movb (_Ax+1), 0x01 ! "invalid command"
- 33491 ret
- 33492 0: push ebp ! save C registers
- 33493 push esi
- 33494 push edi
- 33495 push ebx
- 33496 pushf ! save flags
- 33497 cli ! no interruptions
- 33498
- 33499 inb INT2_CTLMASK
- 33500 movb ah, al
- 33501 inb INT_CTLMASK
- 33502 push eax ! save interrupt masks
- 33503 mov eax, (_irq_use) ! map of in-use IRQs
- 33504 and eax, ~[1<<CLOCK_IRQ] ! there is a special clock handler
- 33505 outb INT_CTLMASK ! enable all unused IRQs and vv.
- 33506 movb al, ah
- 33507 outb INT2_CTLMASK
- 33508
- 33509 mov eax, cr0
- 33510 push eax ! save machine status word
- 33511
- 33512 mov eax, SS_SELECTOR ! monitor data segment
- 33513 mov ss, ax
- 33514 xchg esp, (_mon_sp) ! switch stacks
- 33515 o16 push (_Es) ! parameters used in bios 13 call
- 33516 o16 push (_Dx)
- 33517 o16 push (_Cx)
- 33518 o16 push (_Bx)
- 33519 o16 push (_Ax)
- 33520 mov ds, ax ! remaining data selectors
- 33521 mov es, ax
- 33522 mov fs, ax
- 33523 mov gs, ax
- 33524 push cs
- 33525 push return ! kernel return address and selector
- 33526 o16 jmpf 16+2*4+5*2+2*4(esp) ! make the call
- 33527 return:
- 33528 o16 pop (_Ax)
- 33529 o16 pop (_Bx)
- 33530 o16 pop (_Cx)
- 33531 o16 pop (_Dx)
- 33532 o16 pop (_Es)
- 33533 lgdt (_gdt+GDT_SELECTOR) ! reload global descriptor table
- 33534 jmpf CS_SELECTOR:csinit ! restore everything
- 33535 csinit: mov eax, DS_SELECTOR
- 33536 mov ds, ax
- 33537 mov es, ax
- 33538 mov fs, ax
- 33539 mov gs, ax
- 33540 mov ss, ax
- 33541 xchg esp, (_mon_sp) ! unswitch stacks
- 33542 lidt (_gdt+IDT_SELECTOR) ! reload interrupt descriptor table
- 33543 andb (_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02 ! clear TSS busy bit
- 33544 mov ax, TSS_SELECTOR
- 33545 ltr ax ! set TSS register
- 33546
- 33547 pop eax
- 33548 mov cr0, eax ! restore machine status word
- 33549
- 33550 pop eax
- 33551 outb INT_CTLMASK ! restore interrupt masks
- 33552 movb al, ah
- 33553 outb INT2_CTLMASK
- 33554
- 33555 popf ! restore flags
- 33556 pop ebx ! restore C registers
- 33557 pop edi
- 33558 pop esi
- 33559 pop ebp
- 33560 ret
- 33561
- 33562 .sect .bss
- 33563 .define _Ax, _Bx, _Cx, _Dx, _Es ! 8086 register variables
- 33564 .comm _Ax, 4
- 33565 .comm _Bx, 4
- 33566 .comm _Cx, 4
- 33567 .comm _Dx, 4
- 33568 .comm _Es, 4
- 33569 .sect .text
- 33570 #endif /* ENABLE_BIOS_WINI */
- 33571
- 33572
- 33573 !*===========================================================================*
- 33574 !* check_mem *
- 33575 !*===========================================================================*
- 33576 ! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
- 33577 ! Check a block of memory, return the amount valid.
- 33578 ! Only every 16th byte is checked.
- 33579 ! An initial size of 0 means everything.
- 33580 ! This really should do some alias checks.
- 33581
- 33582 CM_DENSITY = 16
- 33583 CM_LOG_DENSITY = 4
- 33584 TEST1PATTERN = 0x55 ! memory test pattern 1
- 33585 TEST2PATTERN = 0xAA ! memory test pattern 2
- 33586
- 33587 CHKM_ARGS = 4 + 4 + 4 ! 4 + 4
- 33588 ! ds ebx eip base size
- 33589
- 33590 _check_mem:
- 33591 push ebx
- 33592 push ds
- 33593 o16 mov ax, FLAT_DS_SELECTOR
- 33594 mov ds, ax
- 33595 mov eax, CHKM_ARGS(esp)
- 33596 mov ebx, eax
- 33597 mov ecx, CHKM_ARGS+4(esp)
- 33598 shr ecx, CM_LOG_DENSITY
- 33599 cm_loop:
- 33600 movb dl, TEST1PATTERN
- 33601 xchgb dl, (eax) ! write test pattern, remember original
- 33602 xchgb dl, (eax) ! restore original, read test pattern
- 33603 cmpb dl, TEST1PATTERN ! must agree if good real memory
- 33604 jnz cm_exit ! if different, memory is unusable
- 33605 movb dl, TEST2PATTERN
- 33606 xchgb dl, (eax)
- 33607 xchgb dl, (eax)
- 33608 add eax, CM_DENSITY
- 33609 cmpb dl, TEST2PATTERN
- 33610 loopz cm_loop
- 33611 cm_exit:
- 33612 sub eax, ebx
- 33613 pop ds
- 33614 pop ebx
- 33615 ret
- 33616
- 33617
- 33618 !*===========================================================================*
- 33619 !* cp_mess *
- 33620 !*===========================================================================*
- 33621 ! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
- 33622 ! phys_clicks dst_clicks, vir_bytes dst_offset);
- 33623 ! This routine makes a fast copy of a message from anywhere in the address
- 33624 ! space to anywhere else. It also copies the source address provided as a
- 33625 ! parameter to the call into the first word of the destination message.
- 33626 !
- 33627 ! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
- 33628 ! correctly. Changing the definition of message in the type file and not
- 33629 ! changing it here will lead to total disaster.
- 33630
- 33631 CM_ARGS = 4 + 4 + 4 + 4 + 4 ! 4 + 4 + 4 + 4 + 4
- 33632 ! es ds edi esi eip proc scl sof dcl dof
- 33633
- 33634 .align 16
- 33635 _cp_mess:
- 33636 cld
- 33637 push esi
- 33638 push edi
- 33639 push ds
- 33640 push es
- 33641
- 33642 mov eax, FLAT_DS_SELECTOR
- 33643 mov ds, ax
- 33644 mov es, ax
- 33645
- 33646 mov esi, CM_ARGS+4(esp) ! src clicks
- 33647 shl esi, CLICK_SHIFT
- 33648 add esi, CM_ARGS+4+4(esp) ! src offset
- 33649 mov edi, CM_ARGS+4+4+4(esp) ! dst clicks
- 33650 shl edi, CLICK_SHIFT
- 33651 add edi, CM_ARGS+4+4+4+4(esp) ! dst offset
- 33652
- 33653 mov eax, CM_ARGS(esp) ! process number of sender
- 33654 stos ! copy number of sender to dest message
- 33655 add esi, 4 ! do not copy first word
- 33656 mov ecx, Msize - 1 ! remember, first word does not count
- 33657 rep
- 33658 movs ! copy the message
- 33659
- 33660 pop es
- 33661 pop ds
- 33662 pop edi
- 33663 pop esi
- 33664 ret ! that is all folks!
- 33665
- 33666
- 33667 !*===========================================================================*
- 33668 !* exit *
- 33669 !*===========================================================================*
- 33670 ! PUBLIC void exit();
- 33671 ! Some library routines use exit, so provide a dummy version.
- 33672 ! Actual calls to exit cannot occur in the kernel.
- 33673 ! GNU CC likes to call ___main from main() for nonobvious reasons.
- 33674
- 33675 _exit:
- 33676 __exit:
- 33677 ___exit:
- 33678 sti
- 33679 jmp ___exit
- 33680
- 33681 ___main:
- 33682 ret
- 33683
- 33684
- 33685 !*===========================================================================*
- 33686 !* in_byte *
- 33687 !*===========================================================================*
- 33688 ! PUBLIC unsigned in_byte(port_t port);
- 33689 ! Read an (unsigned) byte from the i/o port port and return it.
- 33690
- 33691 .align 16
- 33692 _in_byte:
- 33693 mov edx, 4(esp) ! port
- 33694 sub eax, eax
- 33695 inb dx ! read 1 byte
- 33696 ret
- 33697
- 33698
- 33699 !*===========================================================================*
- 33700 !* in_word *
- 33701 !*===========================================================================*
- 33702 ! PUBLIC unsigned in_word(port_t port);
- 33703 ! Read an (unsigned) word from the i/o port port and return it.
- 33704
- 33705 .align 16
- 33706 _in_word:
- 33707 mov edx, 4(esp) ! port
- 33708 sub eax, eax
- 33709 o16 in dx ! read 1 word
- 33710 ret
- 33711
- 33712
- 33713 !*===========================================================================*
- 33714 !* out_byte *
- 33715 !*===========================================================================*
- 33716 ! PUBLIC void out_byte(port_t port, u8_t value);
- 33717 ! Write value (cast to a byte) to the I/O port port.
- 33718
- 33719 .align 16
- 33720 _out_byte:
- 33721 mov edx, 4(esp) ! port
- 33722 movb al, 4+4(esp) ! value
- 33723 outb dx ! output 1 byte
- 33724 ret
- 33725
- 33726
- 33727 !*===========================================================================*
- 33728 !* out_word *
- 33729 !*===========================================================================*
- 33730 ! PUBLIC void out_word(Port_t port, U16_t value);
- 33731 ! Write value (cast to a word) to the I/O port port.
- 33732
- 33733 .align 16
- 33734 _out_word:
- 33735 mov edx, 4(esp) ! port
- 33736 mov eax, 4+4(esp) ! value
- 33737 o16 out dx ! output 1 word
- 33738 ret
- 33739
- 33740
- 33741 !*===========================================================================*
- 33742 !* port_read *
- 33743 !*===========================================================================*
- 33744 ! PUBLIC void port_read(port_t port, phys_bytes destination, unsigned bytcount);
- 33745 ! Transfer data from (hard disk controller) port to memory.
- 33746
- 33747 PR_ARGS = 4 + 4 + 4 ! 4 + 4 + 4
- 33748 ! es edi eip port dst len
- 33749
- 33750 .align 16
- 33751 _port_read:
- 33752 cld
- 33753 push edi
- 33754 push es
- 33755 mov ecx, FLAT_DS_SELECTOR
- 33756 mov es, cx
- 33757 mov edx, PR_ARGS(esp) ! port to read from
- 33758 mov edi, PR_ARGS+4(esp) ! destination addr
- 33759 mov ecx, PR_ARGS+4+4(esp) ! byte count
- 33760 shr ecx, 1 ! word count
- 33761 rep ! (hardware cannot handle dwords)
- 33762 o16 ins ! read everything
- 33763 pop es
- 33764 pop edi
- 33765 ret
- 33766
- 33767
- 33768 !*===========================================================================*
- 33769 !* port_read_byte *
- 33770 !*===========================================================================*
- 33771 ! PUBLIC void port_read_byte(port_t port, phys_bytes destination,
- 33772 ! unsigned bytcount);
- 33773 ! Transfer data from port to memory.
- 33774
- 33775 PR_ARGS_B = 4 + 4 + 4 ! 4 + 4 + 4
- 33776 ! es edi eip port dst len
- 33777
- 33778 _port_read_byte:
- 33779 cld
- 33780 push edi
- 33781 push es
- 33782 mov ecx, FLAT_DS_SELECTOR
- 33783 mov es, cx
- 33784 mov edx, PR_ARGS_B(esp)
- 33785 mov edi, PR_ARGS_B+4(esp)
- 33786 mov ecx, PR_ARGS_B+4+4(esp)
- 33787 rep
- 33788 insb
- 33789 pop es
- 33790 pop edi
- 33791 ret
- 33792
- 33793
- 33794 !*===========================================================================*
- 33795 !* port_write *
- 33796 !*===========================================================================*
- 33797 ! PUBLIC void port_write(port_t port, phys_bytes source, unsigned bytcount);
- 33798 ! Transfer data from memory to (hard disk controller) port.
- 33799
- 33800 PW_ARGS = 4 + 4 + 4 ! 4 + 4 + 4
- 33801 ! es edi eip port src len
- 33802
- 33803 .align 16
- 33804 _port_write:
- 33805 cld
- 33806 push esi
- 33807 push ds
- 33808 mov ecx, FLAT_DS_SELECTOR
- 33809 mov ds, cx
- 33810 mov edx, PW_ARGS(esp) ! port to write to
- 33811 mov esi, PW_ARGS+4(esp) ! source addr
- 33812 mov ecx, PW_ARGS+4+4(esp) ! byte count
- 33813 shr ecx, 1 ! word count
- 33814 rep ! (hardware cannot handle dwords)
- 33815 o16 outs ! write everything
- 33816 pop ds
- 33817 pop esi
- 33818 ret
- 33819
- 33820
- 33821 !*===========================================================================*
- 33822 !* port_write_byte *
- 33823 !*===========================================================================*
- 33824 ! PUBLIC void port_write_byte(port_t port, phys_bytes source,
- 33825 ! unsigned bytcount);
- 33826 ! Transfer data from memory to port.
- 33827
- 33828 PW_ARGS_B = 4 + 4 + 4 ! 4 + 4 + 4
- 33829 ! es edi eip port src len
- 33830
- 33831 _port_write_byte:
- 33832 cld
- 33833 push esi
- 33834 push ds
- 33835 mov ecx, FLAT_DS_SELECTOR
- 33836 mov ds, cx
- 33837 mov edx, PW_ARGS_B(esp)
- 33838 mov esi, PW_ARGS_B+4(esp)
- 33839 mov ecx, PW_ARGS_B+4+4(esp)
- 33840 rep
- 33841 outsb
- 33842 pop ds
- 33843 pop esi
- 33844 ret
- 33845
- 33846
- 33847 !*===========================================================================*
- 33848 !* lock *
- 33849 !*===========================================================================*
- 33850 ! PUBLIC void lock();
- 33851 ! Disable CPU interrupts.
- 33852
- 33853 .align 16
- 33854 _lock:
- 33855 cli ! disable interrupts
- 33856 ret
- 33857
- 33858
- 33859 !*===========================================================================*
- 33860 !* unlock *
- 33861 !*===========================================================================*
- 33862 ! PUBLIC void unlock();
- 33863 ! Enable CPU interrupts.
- 33864
- 33865 .align 16
- 33866 _unlock:
- 33867 sti
- 33868 ret
- 33869
- 33870
- 33871 !*==========================================================================*
- 33872 !* enable_irq *
- 33873 !*==========================================================================*/
- 33874 ! PUBLIC void enable_irq(unsigned irq)
- 33875 ! Enable an interrupt request line by clearing an 8259 bit.
- 33876 ! Equivalent code for irq < 8:
- 33877 ! out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) & ~(1 << irq));
- 33878
- 33879 .align 16
- 33880 _enable_irq:
- 33881 mov ecx, 4(esp) ! irq
- 33882 pushf
- 33883 cli
- 33884 movb ah, ~1
- 33885 rolb ah, cl ! ah = ~(1 << (irq % 8))
- 33886 cmpb cl, 8
- 33887 jae enable_8 ! enable irq >= 8 at the slave 8259
- 33888 enable_0:
- 33889 inb INT_CTLMASK
- 33890 andb al, ah
- 33891 outb INT_CTLMASK ! clear bit at master 8259
- 33892 popf
- 33893 ret
- 33894 .align 4
- 33895 enable_8:
- 33896 inb INT2_CTLMASK
- 33897 andb al, ah
- 33898 outb INT2_CTLMASK ! clear bit at slave 8259
- 33899 popf
- 33900 ret
- 33901
- 33902
- 33903 !*==========================================================================*
- 33904 !* disable_irq *
- 33905 !*==========================================================================*/
- 33906 ! PUBLIC int disable_irq(unsigned irq)
- 33907 ! Disable an interrupt request line by setting an 8259 bit.
- 33908 ! Equivalent code for irq < 8:
- 33909 ! out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) | (1 << irq));
- 33910 ! Returns true iff the interrupt was not already disabled.
- 33911
- 33912 .align 16
- 33913 _disable_irq:
- 33914 mov ecx, 4(esp) ! irq
- 33915 pushf
- 33916 cli
- 33917 movb ah, 1
- 33918 rolb ah, cl ! ah = (1 << (irq % 8))
- 33919 cmpb cl, 8
- 33920 jae disable_8 ! disable irq >= 8 at the slave 8259
- 33921 disable_0:
- 33922 inb INT_CTLMASK
- 33923 testb al, ah
- 33924 jnz dis_already ! already disabled?
- 33925 orb al, ah
- 33926 outb INT_CTLMASK ! set bit at master 8259
- 33927 popf
- 33928 mov eax, 1 ! disabled by this function
- 33929 ret
- 33930 disable_8:
- 33931 inb INT2_CTLMASK
- 33932 testb al, ah
- 33933 jnz dis_already ! already disabled?
- 33934 orb al, ah
- 33935 outb INT2_CTLMASK ! set bit at slave 8259
- 33936 popf
- 33937 mov eax, 1 ! disabled by this function
- 33938 ret
- 33939 dis_already:
- 33940 popf
- 33941 xor eax, eax ! already disabled
- 33942 ret
- 33943
- 33944
- 33945 !*===========================================================================*
- 33946 !* phys_copy *
- 33947 !*===========================================================================*
- 33948 ! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
- 33949 ! phys_bytes bytecount);
- 33950 ! Copy a block of physical memory.
- 33951
- 33952 PC_ARGS = 4 + 4 + 4 + 4 ! 4 + 4 + 4
- 33953 ! es edi esi eip src dst len
- 33954
- 33955 .align 16
- 33956 _phys_copy:
- 33957 cld
- 33958 push esi
- 33959 push edi
- 33960 push es
- 33961
- 33962 mov eax, FLAT_DS_SELECTOR
- 33963 mov es, ax
- 33964
- 33965 mov esi, PC_ARGS(esp)
- 33966 mov edi, PC_ARGS+4(esp)
- 33967 mov eax, PC_ARGS+4+4(esp)
- 33968
- 33969 cmp eax, 10 ! avoid align overhead for small counts
- 33970 jb pc_small
- 33971 mov ecx, esi ! align source, hope target is too
- 33972 neg ecx
- 33973 and ecx, 3 ! count for alignment
- 33974 sub eax, ecx
- 33975 rep
- 33976 eseg movsb
- 33977 mov ecx, eax
- 33978 shr ecx, 2 ! count of dwords
- 33979 rep
- 33980 eseg movs
- 33981 and eax, 3
- 33982 pc_small:
- 33983 xchg ecx, eax ! remainder
- 33984 rep
- 33985 eseg movsb
- 33986
- 33987 pop es
- 33988 pop edi
- 33989 pop esi
- 33990 ret
- 33991
- 33992
- 33993 !*===========================================================================*
- 33994 !* mem_rdw *
- 33995 !*===========================================================================*
- 33996 ! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
- 33997 ! Load and return word at far pointer segment:offset.
- 33998
- 33999 .align 16
- 34000 _mem_rdw:
- 34001 mov cx, ds
- 34002 mov ds, 4(esp) ! segment
- 34003 mov eax, 4+4(esp) ! offset
- 34004 movzx eax, (eax) ! word to return
- 34005 mov ds, cx
- 34006 ret
- 34007
- 34008
- 34009 !*===========================================================================*
- 34010 !* reset *
- 34011 !*===========================================================================*
- 34012 ! PUBLIC void reset();
- 34013 ! Reset the system by loading IDT with offset 0 and interrupting.
- 34014
- 34015 _reset:
- 34016 lidt (idt_zero)
- 34017 int 3 ! anything goes, the 386 will not like it
- 34018 .sect .data
- 34019 idt_zero: .data4 0, 0
- 34020 .sect .text
- 34021
- 34022
- 34023 !*===========================================================================*
- 34024 !* mem_vid_copy *
- 34025 !*===========================================================================*
- 34026 ! PUBLIC void mem_vid_copy(u16 *src, unsigned dst, unsigned count);
- 34027 !
- 34028 ! Copy count characters from kernel memory to video memory. Src, dst and
- 34029 ! count are character (word) based video offsets and counts. If src is null
- 34030 ! then screen memory is blanked by filling it with blank_color.
- 34031
- 34032 MVC_ARGS = 4 + 4 + 4 + 4 ! 4 + 4 + 4
- 34033 ! es edi esi eip src dst ct
- 34034
- 34035 _mem_vid_copy:
- 34036 push esi
- 34037 push edi
- 34038 push es
- 34039 mov esi, MVC_ARGS(esp) ! source
- 34040 mov edi, MVC_ARGS+4(esp) ! destination
- 34041 mov edx, MVC_ARGS+4+4(esp) ! count
- 34042 mov es, (_vid_seg) ! destination is video segment
- 34043 cld ! make sure direction is up
- 34044 mvc_loop:
- 34045 and edi, (_vid_mask) ! wrap address
- 34046 mov ecx, edx ! one chunk to copy
- 34047 mov eax, (_vid_size)
- 34048 sub eax, edi
- 34049 cmp ecx, eax
- 34050 jbe 0f
- 34051 mov ecx, eax ! ecx = min(ecx, vid_size - edi)
- 34052 0: sub edx, ecx ! count -= ecx
- 34053 shl edi, 1 ! byte address
- 34054 test esi, esi ! source == 0 means blank the screen
- 34055 jz mvc_blank
- 34056 mvc_copy:
- 34057 rep ! copy words to video memory
- 34058 o16 movs
- 34059 jmp mvc_test
- 34060 mvc_blank:
- 34061 mov eax, (_blank_color) ! ax = blanking character
- 34062 rep
- 34063 o16 stos ! copy blanks to video memory
- 34064 !jmp mvc_test
- 34065 mvc_test:
- 34066 shr edi, 1 ! word addresses
- 34067 test edx, edx
- 34068 jnz mvc_loop
- 34069 mvc_done:
- 34070 pop es
- 34071 pop edi
- 34072 pop esi
- 34073 ret
- 34074
- 34075
- 34076 !*===========================================================================*
- 34077 !* vid_vid_copy *
- 34078 !*===========================================================================*
- 34079 ! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
- 34080 !
- 34081 ! Copy count characters from video memory to video memory. Handle overlap.
- 34082 ! Used for scrolling, line or character insertion and deletion. Src, dst
- 34083 ! and count are character (word) based video offsets and counts.
- 34084
- 34085 VVC_ARGS = 4 + 4 + 4 + 4 ! 4 + 4 + 4
- 34086 ! es edi esi eip src dst ct
- 34087
- 34088 _vid_vid_copy:
- 34089 push esi
- 34090 push edi
- 34091 push es
- 34092 mov esi, VVC_ARGS(esp) ! source
- 34093 mov edi, VVC_ARGS+4(esp) ! destination
- 34094 mov edx, VVC_ARGS+4+4(esp) ! count
- 34095 mov es, (_vid_seg) ! use video segment
- 34096 cmp esi, edi ! copy up or down?
- 34097 jb vvc_down
- 34098 vvc_up:
- 34099 cld ! direction is up
- 34100 vvc_uploop:
- 34101 and esi, (_vid_mask) ! wrap addresses
- 34102 and edi, (_vid_mask)
- 34103 mov ecx, edx ! one chunk to copy
- 34104 mov eax, (_vid_size)
- 34105 sub eax, esi
- 34106 cmp ecx, eax
- 34107 jbe 0f
- 34108 mov ecx, eax ! ecx = min(ecx, vid_size - esi)
- 34109 0: mov eax, (_vid_size)
- 34110 sub eax, edi
- 34111 cmp ecx, eax
- 34112 jbe 0f
- 34113 mov ecx, eax ! ecx = min(ecx, vid_size - edi)
- 34114 0: sub edx, ecx ! count -= ecx
- 34115 shl esi, 1
- 34116 shl edi, 1 ! byte addresses
- 34117 rep
- 34118 eseg o16 movs ! copy video words
- 34119 shr esi, 1
- 34120 shr edi, 1 ! word addresses
- 34121 test edx, edx
- 34122 jnz vvc_uploop ! again?
- 34123 jmp vvc_done
- 34124 vvc_down:
- 34125 std ! direction is down
- 34126 lea esi, -1(esi)(edx*1) ! start copying at the top
- 34127 lea edi, -1(edi)(edx*1)
- 34128 vvc_downloop:
- 34129 and esi, (_vid_mask) ! wrap addresses
- 34130 and edi, (_vid_mask)
- 34131 mov ecx, edx ! one chunk to copy
- 34132 lea eax, 1(esi)
- 34133 cmp ecx, eax
- 34134 jbe 0f
- 34135 mov ecx, eax ! ecx = min(ecx, esi + 1)
- 34136 0: lea eax, 1(edi)
- 34137 cmp ecx, eax
- 34138 jbe 0f
- 34139 mov ecx, eax ! ecx = min(ecx, edi + 1)
- 34140 0: sub edx, ecx ! count -= ecx
- 34141 shl esi, 1
- 34142 shl edi, 1 ! byte addresses
- 34143 rep
- 34144 eseg o16 movs ! copy video words
- 34145 shr esi, 1
- 34146 shr edi, 1 ! word addresses
- 34147 test edx, edx
- 34148 jnz vvc_downloop ! again?
- 34149 cld ! C compiler expect up
- 34150 !jmp vvc_done
- 34151 vvc_done:
- 34152 pop es
- 34153 pop edi
- 34154 pop esi
- 34155 ret
- 34156
- 34157
- 34158 !*===========================================================================*
- 34159 !* level0 *
- 34160 !*===========================================================================*
- 34161 ! PUBLIC void level0(void (*func)(void))
- 34162 ! Call a function at permission level 0. This allows kernel tasks to do
- 34163 ! things that are only possible at the most privileged CPU level.
- 34164 !
- 34165 _level0:
- 34166 mov eax, 4(esp)
- 34167 mov (_level0_func), eax
- 34168 int LEVEL0_VECTOR
- 34169 ret
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/klib88.s
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 34200 #
- 34201 #include <minix/config.h>
- 34202 #include <minix/const.h>
- 34203 #include "const.h"
- 34204 #include "sconst.h"
- 34205 #include "protect.h"
- 34206
- 34207 ! This file contains a number of assembly code utility routines needed by the
- 34208 ! kernel. They are:
- 34209
- 34210 .define _monitor ! exit Minix and return to the monitor
- 34211 .define real2prot ! switch from real to protected mode
- 34212 .define prot2real ! switch from protected to real mode
- 34213 .define _check_mem ! check a block of memory, return the valid size
- 34214 .define _cp_mess ! copies messages from source to destination
- 34215 .define _exit ! dummy for library routines
- 34216 .define __exit ! dummy for library routines
- 34217 .define ___exit ! dummy for library routines
- 34218 .define .fat, .trp ! dummies for library routines
- 34219 .define _in_byte ! read a byte from a port and return it
- 34220 .define _in_word ! read a word from a port and return it
- 34221 .define _out_byte ! write a byte to a port
- 34222 .define _out_word ! write a word to a port
- 34223 .define _port_read ! transfer data from (disk controller) port to memory
- 34224 .define _port_read_byte ! likewise byte by byte
- 34225 .define _port_write ! transfer data from memory to (disk controller) port
- 34226 .define _port_write_byte ! likewise byte by byte
- 34227 .define _lock ! disable interrupts
- 34228 .define _unlock ! enable interrupts
- 34229 .define _enable_irq ! enable an irq at the 8259 controller
- 34230 .define _disable_irq ! disable an irq
- 34231 .define _phys_copy ! copy data from anywhere to anywhere in memory
- 34232 .define _mem_rdw ! copy one word from [segment:offset]
- 34233 .define _reset ! reset the system
- 34234 .define _mem_vid_copy ! copy data to video ram
- 34235 .define _vid_vid_copy ! move data in video ram
- 34236 .define _level0 ! call a function at level 0
- 34237 .define klib_init_prot ! initialize klib functions for protected mode
- 34238
- 34239 ! The routines only guarantee to preserve the registers the C compiler
- 34240 ! expects to be preserved (si, di, bp, sp, segment registers, and direction
- 34241 ! bit in the flags), though some of the older ones preserve bx, cx and dx.
- 34242
- 34243 #define DS_286_OFFSET DS_286_INDEX*DESC_SIZE
- 34244 #define ES_286_OFFSET ES_286_INDEX*DESC_SIZE
- 34245 # define EM_XFER_FUNC 0x87
- 34246 #define JMP_OPCODE 0xE9 /* opcode used for patching */
- 34247 #define OFF_MASK 0x000F /* offset mask for phys_b -> hclick:offset */
- 34248 #define HCHIGH_MASK 0x0F /* h/w click mask for low byte of hi word */
- 34249 #define HCLOW_MASK 0xF0 /* h/w click mask for low byte of low word */
- 34250
- 34251 ! Imported functions
- 34252
- 34253 .extern p_restart
- 34254 .extern p_save
- 34255 .extern _restart
- 34256 .extern save
- 34257
- 34258 ! Exported variables
- 34259
- 34260 .extern kernel_cs
- 34261
- 34262 ! Imported variables
- 34263
- 34264 .extern kernel_ds
- 34265 .extern _irq_use
- 34266 .extern _blank_color
- 34267 .extern _gdt
- 34268 .extern _protected_mode
- 34269 .extern _vid_seg
- 34270 .extern _vid_size
- 34271 .extern _vid_mask
- 34272 .extern _level0_func
- 34273
- 34274 .text
- 34275 !*===========================================================================*
- 34276 !* monitor *
- 34277 !*===========================================================================*
- 34278 ! PUBLIC void monitor();
- 34279 ! Return to the monitor.
- 34280
- 34281 _monitor:
- 34282 call prot2real ! switch to real mode
- 34283 mov ax, _reboot_code+0 ! address of new parameters
- 34284 mov dx, _reboot_code+2
- 34285 mov sp, _mon_sp ! restore monitor stack pointer
- 34286 mov bx, _mon_ss ! monitor data segment
- 34287 mov ds, bx
- 34288 mov es, bx
- 34289 mov ss, bx
- 34290 pop di
- 34291 pop si
- 34292 pop bp
- 34293 retf ! return to the monitor
- 34294
- 34295
- 34296 #if ENABLE_BIOS_WINI
- 34297 !*===========================================================================*
- 34298 !* bios13 *
- 34299 !*===========================================================================*
- 34300 ! PUBLIC void bios13();
- 34301 .define _bios13
- 34302 _bios13: ! make a BIOS 0x13 call for disk I/O
- 34303 push si
- 34304 push di ! save C variable registers
- 34305 pushf ! save flags
- 34306
- 34307 call int13 ! make the actual call
- 34308
- 34309 popf ! restore flags
- 34310 pop di ! restore C registers
- 34311 pop si
- 34312 ret
- 34313
- 34314 ! Make a BIOS 0x13 call from protected mode
- 34315 p_bios13:
- 34316 push bp
- 34317 push si
- 34318 push di ! save C variable registers
- 34319 pushf ! save flags
- 34320 cli ! no interruptions
- 34321 inb INT2_CTLMASK
- 34322 movb ah, al
- 34323 inb INT_CTLMASK
- 34324 push ax ! save interrupt masks
- 34325 mov ax, _irq_use ! map of in-use IRQs
- 34326 and ax, #~[1<<CLOCK_IRQ] ! there is a special clock handler
- 34327 outb INT_CTLMASK ! enable all unused IRQs and vv.
- 34328 movb al, ah
- 34329 outb INT2_CTLMASK
- 34330
- 34331 smsw ax
- 34332 push ax ! save machine status word
- 34333 call prot2real ! switch to real mode
- 34334
- 34335 call int13 ! make the actual call
- 34336
- 34337 call real2prot ! back to protected mode
- 34338 pop ax
- 34339 lmsw ax ! restore msw
- 34340
- 34341 pop ax ! restore interrupt masks
- 34342 outb INT_CTLMASK
- 34343 movb al, ah
- 34344 outb INT2_CTLMASK
- 34345 popf ! restore flags
- 34346 pop di
- 34347 pop si
- 34348 pop bp ! restore C variable registers
- 34349 ret
- 34350
- 34351 int13:
- 34352 mov ax, _Ax ! load parameters
- 34353 mov bx, _Bx
- 34354 mov cx, _Cx
- 34355 mov dx, _Dx
- 34356 mov es, _Es
- 34357 sti ! enable interrupts
- 34358 int 0x13 ! make the BIOS call
- 34359 cli ! disable interrupts
- 34360 mov _Ax, ax ! save results
- 34361 mov _Bx, bx
- 34362 mov _Cx, cx
- 34363 mov _Dx, dx
- 34364 mov _Es, es
- 34365 mov ax, ds
- 34366 mov es, ax ! restore es
- 34367 ret
- 34368
- 34369 .bss
- 34370 .define _Ax, _Bx, _Cx, _Dx, _Es ! 8086 register variables
- 34371 .comm _Ax, 2
- 34372 .comm _Bx, 2
- 34373 .comm _Cx, 2
- 34374 .comm _Dx, 2
- 34375 .comm _Es, 2
- 34376 .text
- 34377 #endif /* ENABLE_BIOS_WINI */
- 34378
- 34379
- 34380 !*===========================================================================*
- 34381 !* real2prot *
- 34382 !*===========================================================================*
- 34383 ! Switch from real to protected mode.
- 34384 real2prot:
- 34385 lgdt _gdt+GDT_SELECTOR ! set global descriptor table
- 34386 smsw ax
- 34387 mov msw, ax ! save real mode msw
- 34388 orb al, #0x01 ! set PE (protection enable) bit
- 34389 lmsw ax ! set msw, enabling protected mode
- 34390
- 34391 jmpf csinit, CS_SELECTOR ! set code segment selector
- 34392 csinit:
- 34393 mov ax, #DS_SELECTOR ! set data selectors
- 34394 mov ds, ax
- 34395 mov es, ax
- 34396 mov ss, ax
- 34397 lidt _gdt+IDT_SELECTOR ! set interrupt vectors
- 34398 andb _gdt+TSS_SELECTOR+DESC_ACCESS, #~0x02 ! clear TSS busy bit
- 34399 mov ax, #TSS_SELECTOR
- 34400 ltr ax ! set TSS register
- 34401
- 34402 movb ah, #0xDF
- 34403 jmp gate_A20 ! enable the A20 address line
- 34404
- 34405
- 34406 !*===========================================================================*
- 34407 !* prot2real *
- 34408 !*===========================================================================*
- 34409 ! Switch from protected to real mode.
- 34410 prot2real:
- 34411 mov save_sp, sp ! save stack pointer
- 34412 cmp _processor, #386 ! is this a 386?
- 34413 jae p2r386
- 34414 p2r286:
- 34415 mov _gdt+ES_286_OFFSET+DESC_BASE, #0x0400
- 34416 movb _gdt+ES_286_OFFSET+DESC_BASE_MIDDLE, #0x00
- 34417 mov ax, #ES_286_SELECTOR
- 34418 mov es, ax ! BIOS data segment
- 34419 eseg mov 0x0067, #real ! set return from shutdown address
- 34420 cseg mov ax, kernel_cs
- 34421 eseg mov 0x0069, ax
- 34422 movb al, #0x8F
- 34423 outb 0x70 ! select CMOS byte 0x0F (disable NMI)
- 34424 jmp .+2
- 34425 movb al, #0x0A
- 34426 outb 0x71 ! set shutdown code to 0x0A "jump far"
- 34427 jmp p_reset ! cause a processor shutdown
- 34428 p2r386:
- 34429 lidt idt_vectors ! real mode interrupt vectors
- 34430 push _gdt+CS_SELECTOR+0
- 34431 push _gdt+DS_SELECTOR+0 ! save CS and DS limits
- 34432 mov _gdt+CS_SELECTOR+0, #0xFFFF
- 34433 mov _gdt+DS_SELECTOR+0, #0xFFFF ! set 64k limits
- 34434 jmpf cs64k, CS_SELECTOR ! reload selectors
- 34435 cs64k: mov ax, #DS_SELECTOR
- 34436 mov ds, ax
- 34437 mov es, ax
- 34438 mov ss, ax
- 34439 pop _gdt+DS_SELECTOR+0
- 34440 pop _gdt+CS_SELECTOR+0 ! restore CS and DS limits
- 34441 .data1 0x0F,0x20,0xC0 ! mov eax, cr0
- 34442 mov ax, msw ! restore real mode (16 bits) msw
- 34443 .data1 0x0F,0x22,0xC0 ! mov cr0, eax
- 34444 .data1 0xEA ! jmpf real, "kernel_cs"
- 34445 .data2 real
- 34446 kernel_cs:
- 34447 .data2 0
- 34448 real:
- 34449 cseg mov ax, kernel_ds ! reload data segment registers
- 34450 mov ds, ax
- 34451 mov es, ax
- 34452 mov ss, ax
- 34453 mov sp, save_sp ! restore stack
- 34454
- 34455 movb ah, #0xDD
- 34456 !jmp gate_A20 ! disable the A20 address line
- 34457
- 34458 ! Enable (ah = 0xDF) or disable (ah = 0xDD) the A20 address line.
- 34459 gate_A20:
- 34460 call kb_wait
- 34461 movb al, #0xD1 ! Tell keyboard that a command is coming
- 34462 outb 0x64
- 34463 call kb_wait
- 34464 movb al, ah ! Enable or disable code
- 34465 outb 0x60
- 34466 call kb_wait
- 34467 mov ax, #25 ! 25 microsec delay for slow keyboard chip
- 34468 0: out 0xED ! Write to an unused port (1us)
- 34469 dec ax
- 34470 jne 0b
- 34471 ret
- 34472 kb_wait:
- 34473 inb 0x64
- 34474 testb al, #0x02 ! Keyboard input buffer full?
- 34475 jnz kb_wait ! If so, wait
- 34476 ret
- 34477
- 34478
- 34479 !*===========================================================================*
- 34480 !* check_mem *
- 34481 !*===========================================================================*
- 34482 ! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
- 34483 ! Check a block of memory, return the amount valid.
- 34484 ! Only every 16th byte is checked.
- 34485 ! This only works in protected mode.
- 34486 ! An initial size of 0 means everything.
- 34487 ! This really should do some alias checks.
- 34488
- 34489 PCM_DENSITY = 256 ! resolution of check
- 34490 ! the shift logic depends on this being 256
- 34491 TEST1PATTERN = 0x55 ! memory test pattern 1
- 34492 TEST2PATTERN = 0xAA ! memory test pattern 2
- 34493
- 34494 _check_mem:
- 34495 pop bx
- 34496 pop _gdt+DS_286_OFFSET+DESC_BASE
- 34497 pop ax ! pop base into base of source descriptor
- 34498 movb _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
- 34499 pop cx ! byte count in dx:cx
- 34500 pop dx
- 34501 sub sp,#4+4
- 34502 push bx
- 34503 push ds
- 34504
- 34505 sub ax,ax ! prepare for early exit
- 34506 test dx,#0xFF00
- 34507 jnz cm_1exit ! cannot handle bases above 16M
- 34508 movb cl,ch ! divide size by 256 and discard high byte
- 34509 movb ch,dl
- 34510 push cx ! save divided size
- 34511 sub bx,bx ! test bytes at bases of segments
- 34512 cm_loop:
- 34513 mov ax,#DS_286_SELECTOR
- 34514 mov ds,ax
- 34515 movb dl,#TEST1PATTERN
- 34516 xchgb dl,(bx) ! write test pattern, remember original value
- 34517 xchgb dl,(bx) ! restore original value, read test pattern
- 34518 cmpb dl,#TEST1PATTERN ! must agree if good real memory
- 34519 jnz cm_exit ! if different, memory is unusable
- 34520 movb dl,#TEST2PATTERN
- 34521 xchgb dl,(bx)
- 34522 xchgb dl,(bx)
- 34523 cmpb dl,#TEST2PATTERN
- 34524 jnz cm_exit
- 34525 ! next segment, test for wraparound at 16M
- 34526 ! assuming es == old ds
- 34527 eseg add _gdt+DS_286_OFFSET+DESC_BASE,#PCM_DENSITY
- 34528 eseg adcb _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,#0
- 34529 loopnz cm_loop
- 34530
- 34531 cm_exit:
- 34532 pop ax
- 34533 sub ax,cx ! verified size in multiples of PCM_DENSITY
- 34534 cm_1exit:
- 34535 movb dl,ah ! convert to phys_bytes in dx:ax
- 34536 subb dh,dh
- 34537 movb ah,al
- 34538 movb al,dh
- 34539 pop ds
- 34540 ret
- 34541
- 34542
- 34543 !*===========================================================================*
- 34544 !* cp_mess *
- 34545 !*===========================================================================*
- 34546 ! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
- 34547 ! phys_clicks dst_clicks, vir_bytes dst_offset);
- 34548 ! This routine makes a fast copy of a message from anywhere in the address
- 34549 ! space to anywhere else. It also copies the source address provided as a
- 34550 ! parameter to the call into the first word of the destination message.
- 34551 !
- 34552 ! Note that the message size, "Msize" is in WORDS (not bytes) and must be set
- 34553 ! correctly. Changing the definition of message in the type file and not
- 34554 ! changing it here will lead to total disaster.
- 34555
- 34556 _cp_mess:
- 34557 cld
- 34558 push es ! save es
- 34559 push ds ! save ds
- 34560 mov bx,sp ! index off bx because machine cannot use sp
- 34561 push si ! save si
- 34562 push di ! save di
- 34563
- 34564 mov ax,12(bx) ! destination click
- 34565 #if HCLICK_SHIFT > CLICK_SHIFT
- 34566 #error /* Small click sizes are not supported (right shift will lose bits). */
- 34567 #endif
- 34568 #if HCLICK_SHIFT < CLICK_SHIFT
- 34569 movb cl,#CLICK_SHIFT-HCLICK_SHIFT
- 34570 shl ax,cl ! destination segment
- 34571 #endif
- 34572 mov es,ax
- 34573 mov di,14(bx) ! offset of destination message
- 34574
- 34575 ! Be careful not to destroy ds before we are finished with the bx pointer.
- 34576 ! We are using bx and not the more natural bp to save pushing bp.
- 34577
- 34578 mov ax,6(bx) ! process number of sender
- 34579 mov si,10(bx) ! offset of source message
- 34580 mov bx,8(bx) ! source click (finished with bx as a pointer)
- 34581 #if HCLICK_SHIFT < CLICK_SHIFT