COMPLETE.TXT
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:2565k
源码类别:

操作系统开发

开发平台:

C/C++

  1. 31402         flgs |= 0000100;
  2. 31403
  3. 31404   /* RAW        - if not ICANON and not ISIG */
  4. 31405   if (!(tp->tty_termios.c_lflag & (ICANON|ISIG)))
  5. 31406         flgs |= 0000040;
  6. 31407
  7. 31408   /* CRMOD      - if ICRNL */
  8. 31409   if (tp->tty_termios.c_iflag & ICRNL)
  9. 31410         flgs |= 0000020;
  10. 31411
  11. 31412   /* ECHO       - if ECHO */
  12. 31413   if (tp->tty_termios.c_lflag & ECHO)
  13. 31414         flgs |= 0000010;
  14. 31415
  15. 31416   /* CBREAK     - if not ICANON and ISIG */
  16. 31417   if ((tp->tty_termios.c_lflag & (ICANON|ISIG)) == ISIG)
  17. 31418         flgs |= 0000002;
  18. 31419
  19. 31420   sg->sg_flags = flgs;
  20. 31421   return(OK);
  21. 31422 }
  22. 31425 /*===========================================================================*
  23. 31426  *                              compat_getc                                  *
  24. 31427  *===========================================================================*/
  25. 31428 PRIVATE int compat_getc(tp, tc)
  26. 31429 tty_t *tp;
  27. 31430 struct tchars *tc;
  28. 31431 {
  29. 31432 /* Translate an old TIOCGETC to the termios equivalent. */
  30. 31433
  31. 31434   tc->t_intrc = tp->tty_termios.c_cc[VINTR];
  32. 31435   tc->t_quitc = tp->tty_termios.c_cc[VQUIT];
  33. 31436   tc->t_startc = tp->tty_termios.c_cc[VSTART];
  34. 31437   tc->t_stopc = tp->tty_termios.c_cc[VSTOP];
  35. 31438   tc->t_brkc = tp->tty_termios.c_cc[VEOL];
  36. 31439   tc->t_eofc = tp->tty_termios.c_cc[VEOF];
  37. 31440   return(OK);
  38. 31441 }
  39. 31444 /*===========================================================================*
  40. 31445  *                              compat_setp                                  *
  41. 31446  *===========================================================================*/
  42. 31447 PRIVATE int compat_setp(tp, sg)
  43. 31448 tty_t *tp;
  44. 31449 struct sgttyb *sg;
  45. 31450 {
  46. 31451 /* Translate an old TIOCSETP to the termios equivalent. */
  47. 31452   struct termios termios;
  48. 31453   int flags;
  49. 31454
  50. 31455   termios = tp->tty_termios;
  51. 31456
  52. 31457   termios.c_cc[VERASE] = sg->sg_erase;
  53. 31458   termios.c_cc[VKILL] = sg->sg_kill;
  54. 31459   cfsetispeed(&termios, sgspd2tspd(sg->sg_ispeed & BYTE));
  55. 31460   cfsetospeed(&termios, sgspd2tspd(sg->sg_ospeed & BYTE));
  56. 31461   flags = sg->sg_flags;
  57. 31462
  58. 31463   /* Input flags */
  59. 31464
  60. 31465   /* BRKINT     - not changed */
  61. 31466   /* ICRNL      - set if CRMOD is set and not RAW */
  62. 31467   /*              (CRMOD also controls output) */
  63. 31468   termios.c_iflag &= ~ICRNL;
  64. 31469   if ((flags & 0000020) && !(flags & 0000040))
  65. 31470         termios.c_iflag |= ICRNL;
  66. 31471
  67. 31472   /* IGNBRK     - not changed */
  68. 31473   /* IGNCR      - forced off (ignoring cr's is not supported) */
  69. 31474   termios.c_iflag &= ~IGNCR;
  70. 31475
  71. 31476   /* IGNPAR     - not changed */
  72. 31477   /* INLCR      - forced off (mapping nl's to cr's is not supported) */
  73. 31478   termios.c_iflag &= ~INLCR;
  74. 31479
  75. 31480   /* INPCK      - not changed */
  76. 31481   /* ISTRIP     - not changed */
  77. 31482   /* IXOFF      - not changed */
  78. 31483   /* IXON       - forced on if not RAW */
  79. 31484   termios.c_iflag &= ~IXON;
  80. 31485   if (!(flags & 0000040))
  81. 31486         termios.c_iflag |= IXON;
  82. 31487
  83. 31488   /* PARMRK     - not changed */
  84. 31489
  85. 31490   /* Output flags */
  86. 31491
  87. 31492   /* OPOST      - forced on if not RAW */
  88. 31493   termios.c_oflag &= ~OPOST;
  89. 31494   if (!(flags & 0000040))
  90. 31495         termios.c_oflag |= OPOST;
  91. 31496
  92. 31497   /* ONLCR      - forced on if CRMOD */
  93. 31498   termios.c_oflag &= ~ONLCR;
  94. 31499   if (flags & 0000020)
  95. 31500         termios.c_oflag |= ONLCR;
  96. 31501
  97. 31502   /* XTABS      - forced on if XTABS */
  98. 31503   termios.c_oflag &= ~XTABS;
  99. 31504   if (flags & 0006000)
  100. 31505         termios.c_oflag |= XTABS;
  101. 31506
  102. 31507   /* CLOCAL     - not changed */
  103. 31508   /* CREAD      - forced on (receiver is always enabled) */
  104. 31509   termios.c_cflag |= CREAD;
  105. 31510
  106. 31511   /* CSIZE      - CS5-CS8 correspond directly to BITS5-BITS8 */
  107. 31512   termios.c_cflag = (termios.c_cflag & ~CSIZE) | ((flags & 0001400) >> (8-2));
  108. 31513
  109. 31514   /* CSTOPB     - not changed */
  110. 31515   /* HUPCL      - not changed */
  111. 31516   /* PARENB     - set if EVENP or ODDP is set */
  112. 31517   termios.c_cflag &= ~PARENB;
  113. 31518   if (flags & (0000200|0000100))
  114. 31519         termios.c_cflag |= PARENB;
  115. 31520
  116. 31521   /* PARODD     - set if ODDP is set */
  117. 31522   termios.c_cflag &= ~PARODD;
  118. 31523   if (flags & 0000100)
  119. 31524         termios.c_cflag |= PARODD;
  120. 31525
  121. 31526   /* Local flags */
  122. 31527
  123. 31528   /* ECHO               - set if ECHO is set */
  124. 31529   termios.c_lflag &= ~ECHO;
  125. 31530   if (flags & 0000010)
  126. 31531         termios.c_lflag |= ECHO;
  127. 31532
  128. 31533   /* ECHOE      - not changed */
  129. 31534   /* ECHOK      - not changed */
  130. 31535   /* ECHONL     - not changed */
  131. 31536   /* ICANON     - set if neither CBREAK nor RAW */
  132. 31537   termios.c_lflag &= ~ICANON;
  133. 31538   if (!(flags & (0000002|0000040)))
  134. 31539         termios.c_lflag |= ICANON;
  135. 31540
  136. 31541   /* IEXTEN     - set if not RAW */
  137. 31542   /* ISIG       - set if not RAW */
  138. 31543   termios.c_lflag &= ~(IEXTEN|ISIG);
  139. 31544   if (!(flags & 0000040))
  140. 31545         termios.c_lflag |= (IEXTEN|ISIG);
  141. 31546
  142. 31547   /* NOFLSH     - not changed */
  143. 31548   /* TOSTOP     - not changed */
  144. 31549
  145. 31550   tp->tty_termios = termios;
  146. 31551   setattr(tp);
  147. 31552   return(OK);
  148. 31553 }
  149. 31556 /*===========================================================================*
  150. 31557  *                              compat_setc                                  *
  151. 31558  *===========================================================================*/
  152. 31559 PRIVATE int compat_setc(tp, tc)
  153. 31560 tty_t *tp;
  154. 31561 struct tchars *tc;
  155. 31562 {
  156. 31563 /* Translate an old TIOCSETC to the termios equivalent. */
  157. 31564   struct termios termios;
  158. 31565
  159. 31566   termios = tp->tty_termios;
  160. 31567
  161. 31568   termios.c_cc[VINTR] = tc->t_intrc;
  162. 31569   termios.c_cc[VQUIT] = tc->t_quitc;
  163. 31570   termios.c_cc[VSTART] = tc->t_startc;
  164. 31571   termios.c_cc[VSTOP] = tc->t_stopc;
  165. 31572   termios.c_cc[VEOL] = tc->t_brkc;
  166. 31573   termios.c_cc[VEOF] = tc->t_eofc;
  167. 31574
  168. 31575   tp->tty_termios = termios;
  169. 31576   setattr(tp);
  170. 31577   return(OK);
  171. 31578 }
  172. 31581 /* Table of termios line speed to sgtty line speed translations.   All termios
  173. 31582  * speeds are present even if sgtty didn't know about them.  (Now it does.)
  174. 31583  */
  175. 31584 PRIVATE struct s2s {
  176. 31585   speed_t       tspd;
  177. 31586   u8_t          sgspd;
  178. 31587 } ts2sgs[] = {
  179. 31588   { B0,           0 },
  180. 31589   { B50,         50 },
  181. 31590   { B75,         75 },
  182. 31591   { B110,         1 },
  183. 31592   { B134,       134 },
  184. 31593   { B200,         2 },
  185. 31594   { B300,         3 },
  186. 31595   { B600,         6 },
  187. 31596   { B1200,       12 },
  188. 31597   { B1800,       18 },
  189. 31598   { B2400,       24 },
  190. 31599   { B4800,       48 },
  191. 31600   { B9600,       96 },
  192. 31601   { B19200,     192 },
  193. 31602   { B38400,     195 },
  194. 31603   { B57600,     194 },
  195. 31604   { B115200,    193 },
  196. 31605 };
  197. 31606
  198. 31607 /*===========================================================================*
  199. 31608  *                              tspd2sgspd                                   *
  200. 31609  *===========================================================================*/
  201. 31610 PRIVATE int tspd2sgspd(tspd)
  202. 31611 speed_t tspd;
  203. 31612 {
  204. 31613 /* Translate a termios speed to sgtty speed. */
  205. 31614   struct s2s *s;
  206. 31615
  207. 31616   for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
  208. 31617         if (s->tspd == tspd) return(s->sgspd);
  209. 31618   }
  210. 31619   return 96;
  211. 31620 }
  212. 31623 /*===========================================================================*
  213. 31624  *                              sgspd2tspd                                   *
  214. 31625  *===========================================================================*/
  215. 31626 PRIVATE speed_t sgspd2tspd(sgspd)
  216. 31627 int sgspd;
  217. 31628 {
  218. 31629 /* Translate a sgtty speed to termios speed. */
  219. 31630   struct s2s *s;
  220. 31631
  221. 31632   for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
  222. 31633         if (s->sgspd == sgspd) return(s->tspd);
  223. 31634   }
  224. 31635   return B9600;
  225. 31636 }
  226. 31639 #if ENABLE_BINCOMPAT
  227. 31640 /*===========================================================================*
  228. 31641  *                              do_ioctl_compat                              *
  229. 31642  *===========================================================================*/
  230. 31643 PRIVATE void do_ioctl_compat(tp, m_ptr)
  231. 31644 tty_t *tp;
  232. 31645 message *m_ptr;
  233. 31646 {
  234. 31647 /* Handle the old sgtty ioctl's that packed the sgtty or tchars struct into
  235. 31648  * the Minix message.  Efficient then, troublesome now.
  236. 31649  */
  237. 31650   int minor, proc, func, result, r;
  238. 31651   long flags, erki, spek;
  239. 31652   u8_t erase, kill, intr, quit, xon, xoff, brk, eof, ispeed, ospeed;
  240. 31653   struct sgttyb sg;
  241. 31654   struct tchars tc;
  242. 31655   message reply_mess;
  243. 31656
  244. 31657   minor = m_ptr->TTY_LINE;
  245. 31658   proc = m_ptr->PROC_NR;
  246. 31659   func = m_ptr->REQUEST;
  247. 31660   spek = m_ptr->m2_l1;
  248. 31661   flags = m_ptr->m2_l2;
  249. 31662
  250. 31663   switch(func)
  251. 31664   {
  252. 31665     case (('t'<<8) | 8):        /* TIOCGETP */
  253. 31666         r = compat_getp(tp, &sg);
  254. 31667         erase = sg.sg_erase;
  255. 31668         kill = sg.sg_kill;
  256. 31669         ispeed = sg.sg_ispeed;
  257. 31670         ospeed = sg.sg_ospeed;
  258. 31671         flags = sg.sg_flags;
  259. 31672         erki = ((long)ospeed<<24) | ((long)ispeed<<16) | ((long)erase<<8) |kill;
  260. 31673         break;
  261. 31674     case (('t'<<8) | 18):       /* TIOCGETC */
  262. 31675         r = compat_getc(tp, &tc);
  263. 31676         intr = tc.t_intrc;
  264. 31677         quit = tc.t_quitc;
  265. 31678         xon = tc.t_startc;
  266. 31679         xoff = tc.t_stopc;
  267. 31680         brk = tc.t_brkc;
  268. 31681         eof = tc.t_eofc;
  269. 31682         erki = ((long)intr<<24) | ((long)quit<<16) | ((long)xon<<8) | xoff;
  270. 31683         flags = (eof << 8) | brk;
  271. 31684         break;
  272. 31685     case (('t'<<8) | 17):       /* TIOCSETC */
  273. 31686         tc.t_stopc = (spek >> 0) & 0xFF;
  274. 31687         tc.t_startc = (spek >> 8) & 0xFF;
  275. 31688         tc.t_quitc = (spek >> 16) & 0xFF;
  276. 31689         tc.t_intrc = (spek >> 24) & 0xFF;
  277. 31690         tc.t_brkc = (flags >> 0) & 0xFF;
  278. 31691         tc.t_eofc = (flags >> 8) & 0xFF;
  279. 31692         r = compat_setc(tp, &tc);
  280. 31693         break;
  281. 31694     case (('t'<<8) | 9):        /* TIOCSETP */
  282. 31695         sg.sg_erase = (spek >> 8) & 0xFF;
  283. 31696         sg.sg_kill = (spek >> 0) & 0xFF;
  284. 31697         sg.sg_ispeed = (spek >> 16) & 0xFF;
  285. 31698         sg.sg_ospeed = (spek >> 24) & 0xFF;
  286. 31699         sg.sg_flags = flags;
  287. 31700         r = compat_setp(tp, &sg);
  288. 31701         break;
  289. 31702     default:
  290. 31703         r = ENOTTY;
  291. 31704   }
  292. 31705   reply_mess.m_type = TASK_REPLY;
  293. 31706   reply_mess.REP_PROC_NR = m_ptr->PROC_NR;
  294. 31707   reply_mess.REP_STATUS = r;
  295. 31708   reply_mess.m2_l1 = erki;
  296. 31709   reply_mess.m2_l2 = flags;
  297. 31710   send(m_ptr->m_source, &reply_mess);
  298. 31711 }
  299. 31712 #endif /* ENABLE_BINCOMPAT */
  300. 31713 #endif /* ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT */
  301. 31714
  302. 31715
  303. 31716
  304. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  305. src/kernel/wdeth.c    
  306. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  307. 31800 /*
  308. 31801 wdeth.c
  309. 31802
  310. 31803 Created:        March 14, 1994 by Philip Homburg
  311. 31804 */
  312. 31805
  313. 31806 #include "kernel.h"
  314. 31807 #include <net/gen/ether.h>
  315. 31808 #include <net/gen/eth_io.h>
  316. 31809 #include "assert.h"
  317. 31810 INIT_ASSERT
  318. 31811 #include "dp8390.h"
  319. 31812 #include "wdeth.h"
  320. 31813
  321. 31814 #if ENABLE_NETWORKING
  322. 31815
  323. 31816 #if !__minix_vmd
  324. 31817 #define debug           0
  325. 31818 #endif
  326. 31819
  327. 31820 #define WET_ETHERNET    0x01            /* Ethernet transceiver */
  328. 31821 #define WET_STARLAN     0x02            /* Starlan transceiver */
  329. 31822 #define WET_INTERF_CHIP 0x04            /* has a WD83C583 interface chip */
  330. 31823 #define WET_BRD_16BIT   0x08            /* 16 bit board */
  331. 31824 #define WET_SLT_16BIT   0x10            /* 16 bit slot */
  332. 31825 #define WET_790         0x20            /* '790 chip */
  333. 31826
  334. 31827 static int we_int_table[8]= { 9, 3, 5, 7, 10, 11, 15, 4 };
  335. 31828 static int we_790int_table[8]= { 0, 9, 3, 5, 7, 10, 11, 15 };
  336. 31829
  337. 31830 _PROTOTYPE( static void we_init, (dpeth_t *dep)                         );
  338. 31831 _PROTOTYPE( static void we_stop, (dpeth_t *dep)                         );
  339. 31832 _PROTOTYPE( static int we_aliasing, (dpeth_t *dep)                      );
  340. 31833 _PROTOTYPE( static int we_interface_chip, (dpeth_t *dep)                );
  341. 31834 _PROTOTYPE( static int we_16bitboard, (dpeth_t *dep)                    );
  342. 31835 _PROTOTYPE( static int we_16bitslot, (dpeth_t *dep)                     );
  343. 31836 _PROTOTYPE( static int we_ultra, (dpeth_t *dep)                         );
  344. 31837
  345. 31838 /*===========================================================================*
  346. 31839  *                              wdeth_probe                                  *
  347. 31840  *===========================================================================*/
  348. 31841 int wdeth_probe(dep)
  349. 31842 dpeth_t *dep;
  350. 31843 {
  351. 31844         int sum;
  352. 31845
  353. 31846         if (dep->de_linmem == 0)
  354. 31847                 return 0;       /* No shared memory, so no WD board */
  355. 31848
  356. 31849         sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) +
  357. 31850                 inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) +
  358. 31851                 inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) +
  359. 31852                 inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM);
  360. 31853         if ((sum & 0xFF) != 0xFF)
  361. 31854                 return 0;       /* No ethernet board at this address */
  362. 31855
  363. 31856         dep->de_initf= we_init;
  364. 31857         dep->de_stopf= we_stop;
  365. 31858         dep->de_prog_IO= 0;
  366. 31859         return 1;
  367. 31860 }
  368. 31863 /*===========================================================================*
  369. 31864  *                              we_init                                      *
  370. 31865  *===========================================================================*/
  371. 31866 static void we_init(dep)
  372. 31867 dpeth_t *dep;
  373. 31868 {
  374. 31869         int i, int_indx, int_nr;
  375. 31870         int tlb, rambit, revision;
  376. 31871         int icr, irr, hwr, b, gcr;
  377. 31872         int we_type;
  378. 31873         int sendq_nr;
  379. 31874
  380. 31875         assert(dep->de_mode == DEM_ENABLED);
  381. 31876         assert(!(dep->de_flags & DEF_ENABLED));
  382. 31877
  383. 31878         dep->de_address.ea_addr[0] = inb_we(dep, EPL_EA0);
  384. 31879         dep->de_address.ea_addr[1] = inb_we(dep, EPL_EA1);
  385. 31880         dep->de_address.ea_addr[2] = inb_we(dep, EPL_EA2);
  386. 31881         dep->de_address.ea_addr[3] = inb_we(dep, EPL_EA3);
  387. 31882         dep->de_address.ea_addr[4] = inb_we(dep, EPL_EA4);
  388. 31883         dep->de_address.ea_addr[5] = inb_we(dep, EPL_EA5);
  389. 31884
  390. 31885         dep->de_dp8390_port= dep->de_base_port + EPL_DP8390;
  391. 31886
  392. 31887         dep->de_16bit= 0;
  393. 31888
  394. 31889         we_type= 0;
  395. 31890         we_type |= WET_ETHERNET;        /* assume ethernet */
  396. 31891         if (we_ultra(dep))
  397. 31892                 we_type |= WET_790;
  398. 31893         if (!we_aliasing(dep))
  399. 31894         {
  400. 31895                 if (we_interface_chip(dep))
  401. 31896                         we_type |= WET_INTERF_CHIP;
  402. 31897                 if (we_16bitboard(dep))
  403. 31898                 {
  404. 31899                         we_type |= WET_BRD_16BIT;
  405. 31900                         if (we_16bitslot(dep))
  406. 31901                                 we_type |= WET_SLT_16BIT;
  407. 31902                 }
  408. 31903         }
  409. 31904         if (we_type & WET_SLT_16BIT)
  410. 31905                 dep->de_16bit= 1;
  411. 31906
  412. 31907         /* look at the on board ram size. */
  413. 31908         tlb= inb_we(dep, EPL_TLB);
  414. 31909         revision= tlb & E_TLB_REV;
  415. 31910         rambit= tlb & E_TLB_RAM;
  416. 31911
  417. 31912         if (revision < 2)
  418. 31913         {
  419. 31914                 dep->de_ramsize= 0x2000;                        /* 8K */
  420. 31915                 if (we_type & WET_BRD_16BIT)
  421. 31916                         dep->de_ramsize= 0x4000;                /* 16K */
  422. 31917                 else if ((we_type & WET_INTERF_CHIP) &&
  423. 31918                         inb_we(dep, EPL_ICR) & E_ICR_MEMBIT)
  424. 31919                 {
  425. 31920                         dep->de_ramsize= 0x8000;                /* 32K */
  426. 31921                 }
  427. 31922         }
  428. 31923         else
  429. 31924         {
  430. 31925                 if (we_type & WET_BRD_16BIT)
  431. 31926                 {
  432. 31927                         /* 32K or 16K */
  433. 31928                         dep->de_ramsize= rambit ? 0x8000 : 0x4000;
  434. 31929                 }
  435. 31930                 else
  436. 31931                 {
  437. 31932                         /* 32K or 8K */
  438. 31933                         dep->de_ramsize= rambit ? 0x8000 : 0x2000;
  439. 31934                 }
  440. 31935         }
  441. 31936
  442. 31937         if (we_type & WET_790)
  443. 31938         {
  444. 31939                 outb_we(dep, EPL_MSR, E_MSR_RESET);
  445. 31940                 if ((we_type & (WET_BRD_16BIT|WET_SLT_16BIT)) ==
  446. 31941                         (WET_BRD_16BIT|WET_SLT_16BIT))
  447. 31942                 {
  448. 31943                         outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E);
  449. 31944                 }
  450. 31945         }
  451. 31946         else if (we_type & WET_BRD_16BIT)
  452. 31947         {
  453. 31948                 if (we_type & WET_SLT_16BIT)
  454. 31949                 {
  455. 31950                         outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
  456. 31951                                 E_LAAR_LAN16E | E_LAAR_MEM16E);
  457. 31952                 }
  458. 31953                 else
  459. 31954                 {
  460. 31955                         outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT |
  461. 31956                                 E_LAAR_LAN16E);
  462. 31957                 }
  463. 31958         }
  464. 31959
  465. 31960         if (we_type & WET_790)
  466. 31961         {
  467. 31962                 outb_we(dep, EPL_MSR, E_MSR_MENABLE);
  468. 31963                 hwr= inb_we(dep, EPL_790_HWR);
  469. 31964                 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
  470. 31965                 b= inb_we(dep, EPL_790_B);
  471. 31966                 outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) |
  472. 31967                         ((dep->de_linmem >> 11) & 0x40) | (b & 0xb0));
  473. 31968                 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
  474. 31969         }
  475. 31970         else
  476. 31971         {
  477. 31972                 outb_we(dep, EPL_MSR, E_MSR_RESET);
  478. 31973                 outb_we(dep, EPL_MSR, E_MSR_MENABLE |
  479. 31974                         ((dep->de_linmem >> 13) & E_MSR_MEMADDR));
  480. 31975         }
  481. 31976
  482. 31977         if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790))
  483. 31978         {
  484. 31979                 icr= inb_we(dep, EPL_ICR);
  485. 31980                 irr= inb_we(dep, EPL_IRR);
  486. 31981                 int_indx= (icr & E_ICR_IR2) |
  487. 31982                         ((irr & (E_IRR_IR0|E_IRR_IR1)) >> 5);
  488. 31983                 int_nr= we_int_table[int_indx];
  489. 31984 #if DEBUG
  490. 31985  { printf("wdeth.c: encoded irq= %dn", int_nr); }
  491. 31986 #endif
  492. 31987                 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
  493. 31988
  494. 31989                 outb_we(dep, EPL_IRR, irr | E_IRR_IEN);
  495. 31990         }
  496. 31991         if (we_type & WET_790)
  497. 31992         {
  498. 31993                 hwr= inb_we(dep, EPL_790_HWR);
  499. 31994                 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH);
  500. 31995
  501. 31996                 gcr= inb_we(dep, EPL_790_GCR);
  502. 31997
  503. 31998                 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH);
  504. 31999
  505. 32000                 int_indx= ((gcr & E_790_GCR_IR2) >> 4) |
  506. 32001                         ((gcr & (E_790_GCR_IR1|E_790_GCR_IR0)) >> 2);
  507. 32002                 int_nr= we_790int_table[int_indx];
  508. 32003 #if DEBUG
  509. 32004  { printf("wdeth.c: encoded irq= %dn", int_nr); }
  510. 32005 #endif
  511. 32006                 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr;
  512. 32007
  513. 32008                 icr= inb_we(dep, EPL_790_ICR);
  514. 32009                 outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL);
  515. 32010         }
  516. 32011
  517. 32012         /* Strip the "default flag." */
  518. 32013         dep->de_irq &= ~DEI_DEFAULT;
  519. 32014
  520. 32015         if (!debug)
  521. 32016         {
  522. 32017                 printf("wdeth: WD80%d3 at %X:%d:%lXn",
  523. 32018                         we_type & WET_BRD_16BIT ? 1 : 0,
  524. 32019                         dep->de_base_port, dep->de_irq, dep->de_linmem);
  525. 32020         }
  526. 32021         else
  527. 32022         {
  528. 32023                 printf("wdeth: Western Digital %s%s card %s%s", 
  529. 32024                         we_type & WET_BRD_16BIT ? "16-bit " : "", 
  530. 32025                         we_type & WET_ETHERNET ? "Ethernet" : 
  531. 32026                         we_type & WET_STARLAN ? "Starlan" : "Network",
  532. 32027                         we_type & WET_INTERF_CHIP ? "with an interface chip " : "",
  533. 32028                         we_type & WET_SLT_16BIT ? "in a 16-bit slot " : "");
  534. 32029                 printf(
  535. 32030         "at I/O address 0x%X, memory address 0x%lX, memory size 0x%X, irq %dn",
  536. 32031                         dep->de_base_port, dep->de_linmem, dep->de_ramsize,
  537. 32032                         dep->de_irq);
  538. 32033         }
  539. 32034
  540. 32035         dep->de_offset_page= 0;         /* Shared memory starts at 0 */
  541. 32036
  542. 32037         /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
  543. 32038         sendq_nr= dep->de_ramsize / 0x2000;
  544. 32039         if (sendq_nr < 1)
  545. 32040                 sendq_nr= 1;
  546. 32041         else if (sendq_nr > SENDQ_NR)
  547. 32042                 sendq_nr= SENDQ_NR;
  548. 32043         dep->de_sendq_nr= sendq_nr;
  549. 32044         for (i= 0; i<sendq_nr; i++)
  550. 32045                 dep->de_sendq[i].sq_sendpage= i*SENDQ_PAGES;    
  551. 32046
  552. 32047         dep->de_startpage= i*SENDQ_PAGES;
  553. 32048         dep->de_stoppage= dep->de_ramsize / DP_PAGESIZE;
  554. 32049 }
  555. 32052 /*===========================================================================*
  556. 32053  *                              we_stop                                      *
  557. 32054  *===========================================================================*/
  558. 32055 static void we_stop(dep)
  559. 32056 dpeth_t *dep;
  560. 32057 {
  561. 32058         if (dep->de_16bit)
  562. 32059                 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
  563. 32060         outb_we(dep, EPL_MSR, E_MSR_RESET);
  564. 32061         outb_we(dep, EPL_MSR, 0);
  565. 32062 }
  566. 32065 /*===========================================================================*
  567. 32066  *                              we_aliasing                                  *
  568. 32067  *===========================================================================*/
  569. 32068 static int we_aliasing(dep)
  570. 32069 dpeth_t *dep;
  571. 32070 {
  572. 32071 /* Determine whether wd8003 hardware performs register aliasing. This implies 
  573. 32072  * an old WD8003E board. */
  574. 32073
  575. 32074         if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1))
  576. 32075                 return 0;
  577. 32076         if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2))
  578. 32077                 return 0;
  579. 32078         if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3))
  580. 32079                 return 0;
  581. 32080         if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4))
  582. 32081                 return 0;
  583. 32082         if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM))
  584. 32083                 return 0;
  585. 32084         return 1;
  586. 32085 }
  587. 32088 /*===========================================================================*
  588. 32089  *                              we_interface_chip                            *
  589. 32090  *===========================================================================*/
  590. 32091 static int we_interface_chip(dep)
  591. 32092 dpeth_t *dep;
  592. 32093 {
  593. 32094 /* Determine if the board has an interface chip. */
  594. 32095
  595. 32096         outb_we(dep, EPL_GP2, 0x35);
  596. 32097         if (inb_we(dep, EPL_GP2) != 0x35)
  597. 32098                 return 0;
  598. 32099         outb_we(dep, EPL_GP2, 0x3A);
  599. 32100         if (inb_we(dep, EPL_GP2) != 0x3A)
  600. 32101                 return 0;
  601. 32102         return 1;
  602. 32103 }
  603. 32106 /*===========================================================================*
  604. 32107  *                              we_16bitboard                                *
  605. 32108  *===========================================================================*/
  606. 32109 static int we_16bitboard(dep)
  607. 32110 dpeth_t *dep;
  608. 32111 {
  609. 32112 /* Determine whether the board is capable of doing 16 bit memory moves.
  610. 32113  * If the 16 bit enable bit is unchangable by software we'll assume an 
  611. 32114  * 8 bit board.
  612. 32115  */
  613. 32116         int icr;
  614. 32117         u8_t tlb;
  615. 32118
  616. 32119         icr= inb_we(dep, EPL_ICR);
  617. 32120
  618. 32121         outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT);
  619. 32122         if (inb_we(dep, EPL_ICR) == icr)
  620. 32123         {
  621. 32124                 tlb= inb_we(dep, EPL_TLB);
  622. 32125 #if DEBUG
  623. 32126                 printf("wdeth: tlb= 0x%xn", tlb);
  624. 32127 #endif
  625. 32128                 return tlb == E_TLB_EB || tlb == E_TLB_E ||
  626. 32129                         tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216C;
  627. 32130         }
  628. 32131         outb_we(dep, EPL_ICR, icr);
  629. 32132         return 1;
  630. 32133 }
  631. 32136 /*===========================================================================*
  632. 32137  *                              we_16bitslot                                 *
  633. 32138  *===========================================================================*/
  634. 32139 static int we_16bitslot(dep)
  635. 32140 dpeth_t *dep;
  636. 32141 {
  637. 32142 /* Determine if the 16 bit board in plugged into a 16 bit slot.  */
  638. 32143         return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT);
  639. 32144 }
  640. 32147 /*===========================================================================*
  641. 32148  *                              we_ultra                                     *
  642. 32149  *===========================================================================*/
  643. 32150 static int we_ultra(dep)
  644. 32151 dpeth_t *dep;
  645. 32152 {
  646. 32153 /* Determine if we has an '790 chip.  */
  647. 32154         u8_t tlb;
  648. 32155
  649. 32156         tlb= inb_we(dep, EPL_TLB);
  650. 32157         return tlb == E_TLB_SMC8216C;
  651. 32158 }
  652. 32160 #endif /* ENABLE_NETWORKING */
  653. 32161
  654. 32162 /*
  655. 32163  * $PchHeader: /mount/hd2/minix/sys/kernel/ibm/RCS/wdeth.c,v 1.4 1995/01/12 22:03:57 philip Exp $
  656. 32164  */
  657. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  658. src/kernel/wini.c    
  659. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  660. 32200 /*      wini.c - choose a winchester driver.            Author: Kees J. Bot
  661. 32201  *                                                              28 May 1994
  662. 32202  * Several different winchester drivers may be compiled
  663. 32203  * into the kernel, but only one may run.  That one is chosen here using
  664. 32204  * the boot variable 'hd'.
  665. 32205  */
  666. 32206
  667. 32207 #include "kernel.h"
  668. 32208 #include "driver.h"
  669. 32209
  670. 32210 #if ENABLE_WINI
  671. 32211
  672. 32212 /* Map driver name to task function. */
  673. 32213 struct hdmap {
  674. 32214   char          *name;
  675. 32215   task_t        *task;
  676. 32216 } hdmap[] = {
  677. 32217
  678. 32218 #if ENABLE_AT_WINI
  679. 32219   { "at",       at_winchester_task      },
  680. 32220 #endif
  681. 32221
  682. 32222 #if ENABLE_BIOS_WINI
  683. 32223   { "bios",     bios_winchester_task    },
  684. 32224 #endif
  685. 32225
  686. 32226 #if ENABLE_ESDI_WINI
  687. 32227   { "esdi",     esdi_winchester_task    },
  688. 32228 #endif
  689. 32229
  690. 32230 #if ENABLE_XT_WINI
  691. 32231   { "xt",       xt_winchester_task      },
  692. 32232 #endif
  693. 32233
  694. 32234 };
  695. 32235
  696. 32236
  697. 32237 /*===========================================================================*
  698. 32238  *                              winchester_task                              *
  699. 32239  *===========================================================================*/
  700. 32240 PUBLIC void winchester_task()
  701. 32241 {
  702. 32242   /* Call the default or selected winchester task. */
  703. 32243   char *hd;
  704. 32244   struct hdmap *map;
  705. 32245
  706. 32246   hd = k_getenv("hd");
  707. 32247
  708. 32248   for (map = hdmap; map < hdmap + sizeof(hdmap)/sizeof(hdmap[0]); map++) {
  709. 32249         if (hd == NULL || strcmp(hd, map->name) == 0) {
  710. 32250                 /* Run the selected winchester task. */
  711. 32251                 (*map->task)();
  712. 32252         }
  713. 32253   }
  714. 32254   panic("no hd driver", NO_NUM);
  715. 32255 }
  716. 32256 #endif /* ENABLE_WINI */
  717. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  718. src/kernel/xt_wini.c    
  719. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  720. 32300 /* This file contains the device dependent part of a driver for the WD
  721. 32301  * winchester controller from Western Digital (WX-2 and related controllers).
  722. 32302  * It was written by Adri Koppes.
  723. 32303  *
  724. 32304  * The file contains one entry point:
  725. 32305  *
  726. 32306  *       xt_winchester_task:    main entry when system is brought up
  727. 32307  *
  728. 32308  *
  729. 32309  * Changes:
  730. 32310  *      10 Apr 1987 by Gary Oliver: use with the Western Digital WX-2.
  731. 32311  *                ? by Harry McGavran: robust operation on turbo clones.
  732. 32312  *                ? by Mike Mitchell: WX-2 auto configure operation.
  733. 32313  *       2 May 1992 by Kees J. Bot: device dependent/independent split.
  734. 32314  */
  735. 32315
  736. 32316 #include "kernel.h"
  737. 32317 #include "driver.h"
  738. 32318 #include "drvlib.h"
  739. 32319
  740. 32320 #if ENABLE_XT_WINI
  741. 32321
  742. 32322 /* If the DMA buffer is large enough then use it always. */
  743. 32323 #define USE_BUF         (DMA_BUF_SIZE > BLOCK_SIZE)
  744. 32324
  745. 32325 /* I/O Ports used by winchester disk task. */
  746. 32326 #define WIN_DATA       0x320    /* winchester disk controller data register */
  747. 32327 #define WIN_STATUS     0x321    /* winchester disk controller status register */
  748. 32328 #define WST_REQ        0x001    /* Request bit */
  749. 32329 #define WST_INPUT      0x002    /* Set if controller is writing to cpu */
  750. 32330 #define WST_BUS        0x004    /* Command/status bit */
  751. 32331 #define WST_BUSY       0x008    /* Busy */
  752. 32332 #define WST_DRQ        0x010    /* DMA request */
  753. 32333 #define WST_IRQ        0x020    /* Interrupt request */
  754. 32334 #define WIN_SELECT     0x322    /* winchester disk controller select port */
  755. 32335 #define WIN_DMA        0x323    /* winchester disk controller dma register */
  756. 32336 #define DMA_ADDR       0x006    /* port for low 16 bits of DMA address */
  757. 32337 #define DMA_TOP        0x082    /* port for top 4 bits of 20-bit DMA addr */
  758. 32338 #define DMA_COUNT      0x007    /* port for DMA count (count =  bytes - 1) */
  759. 32339 #define DMA_FLIPFLOP   0x00C    /* DMA byte pointer flop-flop */
  760. 32340 #define DMA_MODE       0x00B    /* DMA mode port */
  761. 32341 #define DMA_INIT       0x00A    /* DMA init port */
  762. 32342
  763. 32343 /* Winchester disk controller command bytes. */
  764. 32344 #define WIN_RECALIBRATE 0x01    /* command for the drive to recalibrate */
  765. 32345 #define WIN_SENSE       0x03    /* command for the controller to get its status */
  766. 32346 #define WIN_READ        0x08    /* command for the drive to read */
  767. 32347 #define WIN_WRITE       0x0a    /* command for the drive to write */
  768. 32348 #define WIN_SPECIFY     0x0C    /* command for the controller to accept params  */
  769. 32349 #define WIN_ECC_READ    0x0D    /* command for the controller to read ecc length */
  770. 32350
  771. 32351 #define DMA_INT            3    /* Command with dma and interrupt */
  772. 32352 #define INT                2    /* Command with interrupt, no dma */
  773. 32353 #define NO_DMA_INT         0    /* Command without dma and interrupt */
  774. 32354
  775. 32355 /* DMA channel commands. */
  776. 32356 #define DMA_READ        0x47    /* DMA read opcode */
  777. 32357 #define DMA_WRITE       0x4B    /* DMA write opcode */
  778. 32358
  779. 32359 /* Parameters for the disk drive. */
  780. 32360 #ifndef NR_SECTORS
  781. 32361 /* For RLL drives NR_SECTORS has to be defined in the makefile or in config.h.
  782. 32362  * There is some hope of getting it from the parameter table for these drives,
  783. 32363  * and then this driver should use wn_sectors like at_wini.c.
  784. 32364  * Unfortunately it is not standard in XT parameter tables.
  785. 32365  */
  786. 32366 #define NR_SECTORS        17    /* number of sectors per track */
  787. 32367 #endif
  788. 32368
  789. 32369 /* Error codes */
  790. 32370 #define ERR              (-1)   /* general error */
  791. 32371 #define ERR_BAD_SECTOR   (-2)   /* block marked bad detected */
  792. 32372
  793. 32373 /* Miscellaneous. */
  794. 32374 #define MAX_DRIVES         2    /* this driver support two drives (hd0 - hd9) */
  795. 32375 #define MAX_ERRORS         4    /* how often to try rd/wt before quitting */
  796. 32376 #define MAX_RESULTS        4    /* max number of bytes controller returns */
  797. 32377 #define NR_DEVICES      (MAX_DRIVES * DEV_PER_DRIVE)
  798. 32378 #define SUB_PER_DRIVE   (NR_PARTITIONS * NR_PARTITIONS)
  799. 32379 #define NR_SUBDEVS      (MAX_DRIVES * SUB_PER_DRIVE)
  800. 32380 #define MAX_WIN_RETRY  32000    /* max # times to try to output to WIN */
  801. 32381 #if AUTO_BIOS
  802. 32382 #define AUTO_PARAM     0x1AD    /* drive parameter table starts here in sect 0  */
  803. 32383 #define AUTO_ENABLE     0x10    /* auto bios enabled bit from status reg */
  804. 32384 /* some start up parameters in order to extract the drive parameter table */
  805. 32385 /* from the winchester. these should not need changed. */
  806. 32386 #define AUTO_CYLS        306    /* default number of cylinders */
  807. 32387 #define AUTO_HEADS         4    /* default number of heads */
  808. 32388 #define AUTO_RWC         307    /* default reduced write cylinder */
  809. 32389 #define AUTO_WPC         307    /* default write precomp cylinder */
  810. 32390 #define AUTO_ECC          11    /* default ecc burst */
  811. 32391 #define AUTO_CTRL          5    /* default winchester stepping speed byte */
  812. 32392 #endif
  813. 32393
  814. 32394 /* Variables. */
  815. 32395 PRIVATE struct wini {           /* main drive struct, one entry per drive */
  816. 32396   unsigned wn_cylinders;        /* number of cylinders */
  817. 32397   unsigned wn_heads;            /* number of heads */
  818. 32398   unsigned wn_reduced_wr;       /* first cylinder with reduced write current */
  819. 32399   unsigned wn_precomp;          /* first cylinder with write precompensation */
  820. 32400   unsigned wn_max_ecc;          /* maximum ECC burst length */
  821. 32401   unsigned wn_ctlbyte;          /* control byte for COMMANDS (10-Apr-87 GO) */
  822. 32402   unsigned wn_open_ct;          /* in-use count */
  823. 32403   struct device wn_part[DEV_PER_DRIVE];    /* primary partitions: hd[0-4] */
  824. 32404   struct device wn_subpart[SUB_PER_DRIVE]; /* subpartitions: hd[1-4][a-d] */
  825. 32405 } wini[MAX_DRIVES], *w_wn;
  826. 32406
  827. 32407 PRIVATE struct trans {
  828. 32408   struct iorequest_s *tr_iop;   /* belongs to this I/O request */
  829. 32409   unsigned long tr_block;       /* first sector to transfer */
  830. 32410   unsigned tr_count;            /* byte count */
  831. 32411   phys_bytes tr_phys;           /* user physical address */
  832. 32412   phys_bytes tr_dma;            /* DMA physical address */
  833. 32413 } wtrans[NR_IOREQS];
  834. 32414
  835. 32415 PRIVATE int w_need_reset = FALSE;       /* set when controller must be reset */
  836. 32416 PRIVATE int nr_drives;                  /* Number of drives */
  837. 32417 PRIVATE int w_switches;                 /* Drive type switches */
  838. 32418 PRIVATE struct trans *w_tp;             /* to add transfer requests */
  839. 32419 PRIVATE unsigned w_count;               /* number of bytes to transfer */
  840. 32420 PRIVATE unsigned long w_nextblock;      /* next block on disk to transfer */
  841. 32421 PRIVATE int w_opcode;                   /* DEV_READ or DEV_WRITE */
  842. 32422 PRIVATE int w_drive;                    /* selected drive */
  843. 32423 PRIVATE struct device *w_dv;            /* device's base and size */
  844. 32424 PRIVATE char w_results[MAX_RESULTS];/* the controller can give lots of output */
  845. 32425
  846. 32426
  847. 32427 FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
  848. 32428 FORWARD _PROTOTYPE( char *w_name, (void) );
  849. 32429 FORWARD _PROTOTYPE( int w_schedule, (int proc_nr, struct iorequest_s *iop) );
  850. 32430 FORWARD _PROTOTYPE( int w_finish, (void) );
  851. 32431 FORWARD _PROTOTYPE( void w_dma_setup, (struct trans *tp, unsigned count) );
  852. 32432 FORWARD _PROTOTYPE( int w_transfer, (struct trans *tp, unsigned count) );
  853. 32433 FORWARD _PROTOTYPE( int win_results, (void) );
  854. 32434 FORWARD _PROTOTYPE( void win_out, (int val) );
  855. 32435 FORWARD _PROTOTYPE( int w_reset, (void) );
  856. 32436 FORWARD _PROTOTYPE( int w_handler, (int irq) );
  857. 32437 FORWARD _PROTOTYPE( int win_specify, (int drive) );
  858. 32438 FORWARD _PROTOTYPE( int check_init, (void) );
  859. 32439 FORWARD _PROTOTYPE( int read_ecc, (void) );
  860. 32440 FORWARD _PROTOTYPE( int hd_wait, (int bits) );
  861. 32441 FORWARD _PROTOTYPE( int com_out, (int mode, u8_t *command) );
  862. 32442 FORWARD _PROTOTYPE( void init_params, (void) );
  863. 32443 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
  864. 32444 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
  865. 32445 FORWARD _PROTOTYPE( void w_init, (void) );
  866. 32446 FORWARD _PROTOTYPE( void copy_param, (char *src, struct wini *dest) );
  867. 32447 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
  868. 32448
  869. 32449
  870. 32450 /* Entry points to this driver. */
  871. 32451 PRIVATE struct driver w_dtab = {
  872. 32452   w_name,       /* current device's name */
  873. 32453   w_do_open,    /* open or mount request, initialize device */
  874. 32454   w_do_close,   /* release device */
  875. 32455   do_diocntl,   /* get or set a partition's geometry */
  876. 32456   w_prepare,    /* prepare for I/O on a given minor device */
  877. 32457   w_schedule,   /* precompute cylinder, head, sector, etc. */
  878. 32458   w_finish,     /* do the I/O */
  879. 32459   nop_cleanup,  /* no cleanup needed */
  880. 32460   w_geometry    /* tell the geometry of the disk */
  881. 32461 };
  882. 32462
  883. 32463
  884. 32464 /*===========================================================================*
  885. 32465  *                              xt_winchester_task                           *
  886. 32466  *===========================================================================*/
  887. 32467 PUBLIC void xt_winchester_task()
  888. 32468 {
  889. 32469   init_params();
  890. 32470
  891. 32471   put_irq_handler(XT_WINI_IRQ, w_handler);
  892. 32472   enable_irq(XT_WINI_IRQ);      /* ready for winchester interrupts */
  893. 32473
  894. 32474   driver_task(&w_dtab);
  895. 32475 }
  896. 32478 /*===========================================================================*
  897. 32479  *                              w_prepare                                    *
  898. 32480  *===========================================================================*/
  899. 32481 PRIVATE struct device *w_prepare(device)
  900. 32482 int device;
  901. 32483 {
  902. 32484 /* Prepare for I/O on a device. */
  903. 32485
  904. 32486   /* Nothing to transfer as yet. */
  905. 32487   w_count = 0;
  906. 32488
  907. 32489   if (device < NR_DEVICES) {                    /* hd0, hd1, ... */
  908. 32490         w_drive = device / DEV_PER_DRIVE;       /* save drive number */
  909. 32491         w_wn = &wini[w_drive];
  910. 32492         w_dv = &w_wn->wn_part[device % DEV_PER_DRIVE];
  911. 32493   } else
  912. 32494   if ((unsigned) (device -= MINOR_hd1a) < NR_SUBDEVS) { /* hd1a, hd1b, ... */
  913. 32495         w_drive = device / SUB_PER_DRIVE;
  914. 32496         w_wn = &wini[w_drive];
  915. 32497         w_dv = &w_wn->wn_subpart[device % SUB_PER_DRIVE];
  916. 32498   } else {
  917. 32499         return(NIL_DEV);
  918. 32500   }
  919. 32501   return(w_drive < nr_drives ? w_dv : NIL_DEV);
  920. 32502 }
  921. 32505 /*===========================================================================*
  922. 32506  *                              w_name                                       *
  923. 32507  *===========================================================================*/
  924. 32508 PRIVATE char *w_name()
  925. 32509 {
  926. 32510 /* Return a name for the current device. */
  927. 32511   static char name[] = "xt-hd5";
  928. 32512
  929. 32513   name[5] = '0' + w_drive * DEV_PER_DRIVE;
  930. 32514   return name;
  931. 32515 }
  932. 32518 /*===========================================================================*
  933. 32519  *                              w_schedule                                   *
  934. 32520  *===========================================================================*/
  935. 32521 PRIVATE int w_schedule(proc_nr, iop)
  936. 32522 int proc_nr;                    /* process doing the request */
  937. 32523 struct iorequest_s *iop;        /* pointer to read or write request */
  938. 32524 {
  939. 32525 /* Gather I/O requests on consecutive blocks so they may be read/written
  940. 32526  * in one command if using a buffer.  Check and gather all the requests
  941. 32527  * and try to finish them as fast as possible if unbuffered.
  942. 32528  */
  943. 32529   int r, opcode;
  944. 32530   unsigned long pos;
  945. 32531   unsigned nbytes, count, dma_count;
  946. 32532   unsigned long block;
  947. 32533   phys_bytes user_phys, dma_phys;
  948. 32534
  949. 32535   /* This many bytes to read/write */
  950. 32536   nbytes = iop->io_nbytes;
  951. 32537   if ((nbytes & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  952. 32538
  953. 32539   /* From/to this position on the device */
  954. 32540   pos = iop->io_position;
  955. 32541   if ((pos & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  956. 32542
  957. 32543   /* To/from this user address */
  958. 32544   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
  959. 32545   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  960. 32546
  961. 32547   /* Read or write? */
  962. 32548   opcode = iop->io_request & ~OPTIONAL_IO;
  963. 32549
  964. 32550   /* Which block on disk and how close to EOF? */
  965. 32551   if (pos >= w_dv->dv_size) return(OK);         /* At EOF */
  966. 32552   if (pos + nbytes > w_dv->dv_size) nbytes = w_dv->dv_size - pos;
  967. 32553   block = (w_dv->dv_base + pos) >> SECTOR_SHIFT;
  968. 32554
  969. 32555   if (USE_BUF && w_count > 0 && block != w_nextblock) {
  970. 32556         /* This new request can't be chained to the job being built */
  971. 32557         if ((r = w_finish()) != OK) return(r);
  972. 32558   }
  973. 32559
  974. 32560   /* The next consecutive block */
  975. 32561   if (USE_BUF) w_nextblock = block + (nbytes >> SECTOR_SHIFT);
  976. 32562
  977. 32563   /* While there are "unscheduled" bytes in the request: */
  978. 32564   do {
  979. 32565         count = nbytes;
  980. 32566
  981. 32567         if (USE_BUF) {
  982. 32568                 if (w_count == DMA_BUF_SIZE) {
  983. 32569                         /* Can't transfer more than the buffer allows. */
  984. 32570                         if ((r = w_finish()) != OK) return(r);
  985. 32571                 }
  986. 32572
  987. 32573                 if (w_count + count > DMA_BUF_SIZE)
  988. 32574                         count = DMA_BUF_SIZE - w_count;
  989. 32575         } else {
  990. 32576                 if (w_tp == wtrans + NR_IOREQS) {
  991. 32577                         /* All transfer slots in use. */
  992. 32578                         if ((r = w_finish()) != OK) return(r);
  993. 32579                 }
  994. 32580         }
  995. 32581
  996. 32582         if (w_count == 0) {
  997. 32583                 /* The first request in a row, initialize. */
  998. 32584                 w_opcode = opcode;
  999. 32585                 w_tp = wtrans;
  1000. 32586         }
  1001. 32587
  1002. 32588         if (USE_BUF) {
  1003. 32589                 dma_phys = tmp_phys + w_count;
  1004. 32590         } else {
  1005. 32591                 /* Memory chunk to DMA. */
  1006. 32592                 dma_phys = user_phys;
  1007. 32593                 dma_count = dma_bytes_left(dma_phys);
  1008. 32594
  1009. 32595                 if (dma_count < count) {
  1010. 32596                         /* Nearing a 64K boundary. */
  1011. 32597                         if (dma_count >= SECTOR_SIZE) {
  1012. 32598                                 /* Can read a few sectors before hitting the
  1013. 32599                                  * boundary.
  1014. 32600                                  */
  1015. 32601                                 count = dma_count & ~SECTOR_MASK;
  1016. 32602                         } else {
  1017. 32603                                 /* Must use the special buffer for this. */
  1018. 32604                                 count = SECTOR_SIZE;
  1019. 32605                                 dma_phys = tmp_phys;
  1020. 32606                         }
  1021. 32607                 }
  1022. 32608         }
  1023. 32609
  1024. 32610         /* Store I/O parameters */
  1025. 32611         w_tp->tr_iop = iop;
  1026. 32612         w_tp->tr_block = block;
  1027. 32613         w_tp->tr_count = count;
  1028. 32614         w_tp->tr_phys = user_phys;
  1029. 32615         w_tp->tr_dma = dma_phys;
  1030. 32616
  1031. 32617         /* Update counters */
  1032. 32618         w_tp++;
  1033. 32619         w_count += count;
  1034. 32620         block += count >> SECTOR_SHIFT;
  1035. 32621         user_phys += count;
  1036. 32622         nbytes -= count;
  1037. 32623   } while (nbytes > 0);
  1038. 32624
  1039. 32625   return(OK);
  1040. 32626 }
  1041. 32629 /*===========================================================================*
  1042. 32630  *                              w_finish                                     *
  1043. 32631  *===========================================================================*/
  1044. 32632 PRIVATE int w_finish()
  1045. 32633 {
  1046. 32634 /* Carry out the I/O requests gathered in wtrans[]. */
  1047. 32635
  1048. 32636   struct trans *tp = wtrans, *tp2;
  1049. 32637   unsigned count;
  1050. 32638   int r, errors = 0, many = USE_BUF;
  1051. 32639
  1052. 32640   if (w_count == 0) return(OK); /* Spurious finish. */
  1053. 32641
  1054. 32642   do {
  1055. 32643         if (w_opcode == DEV_WRITE) {
  1056. 32644                 tp2 = tp;
  1057. 32645                 count = 0;
  1058. 32646                 do {
  1059. 32647                         if (USE_BUF || tp2->tr_dma == tmp_phys) {
  1060. 32648                                 phys_copy(tp2->tr_phys, tp2->tr_dma,
  1061. 32649                                                 (phys_bytes) tp2->tr_count);
  1062. 32650                         }
  1063. 32651                         count += tp2->tr_count;
  1064. 32652                         tp2++;
  1065. 32653                 } while (many && count < w_count);
  1066. 32654         } else {
  1067. 32655                 count = many ? w_count : tp->tr_count;
  1068. 32656         }
  1069. 32657
  1070. 32658         /* First check to see if a reset is needed. */
  1071. 32659         if (w_need_reset) w_reset();
  1072. 32660
  1073. 32661         /* Now set up the DMA chip. */
  1074. 32662         w_dma_setup(tp, count);
  1075. 32663
  1076. 32664         /* Perform the transfer. */
  1077. 32665         r = w_transfer(tp, count);
  1078. 32666
  1079. 32667         if (r != OK) {
  1080. 32668                 /* An error occurred, try again block by block unless */
  1081. 32669                 if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS)
  1082. 32670                         return(tp->tr_iop->io_nbytes = EIO);
  1083. 32671
  1084. 32672                 /* Reset if halfway, but bail out if optional I/O. */
  1085. 32673                 if (errors == MAX_ERRORS / 2) {
  1086. 32674                         w_need_reset = TRUE;
  1087. 32675                         if (tp->tr_iop->io_request & OPTIONAL_IO)
  1088. 32676                                 return(tp->tr_iop->io_nbytes = EIO);
  1089. 32677                 }
  1090. 32678                 many = 0;
  1091. 32679                 continue;
  1092. 32680         }
  1093. 32681         errors = 0;
  1094. 32682
  1095. 32683         w_count -= count;
  1096. 32684
  1097. 32685         do {
  1098. 32686                 if (w_opcode == DEV_READ) {
  1099. 32687                         if (USE_BUF || tp->tr_dma == tmp_phys) {
  1100. 32688                                 phys_copy(tp->tr_dma, tp->tr_phys,
  1101. 32689                                                 (phys_bytes) tp->tr_count);
  1102. 32690                         }
  1103. 32691                 }
  1104. 32692                 tp->tr_iop->io_nbytes -= tp->tr_count;
  1105. 32693                 count -= tp->tr_count;
  1106. 32694                 tp++;
  1107. 32695         } while (count > 0);
  1108. 32696   } while (w_count > 0);
  1109. 32697
  1110. 32698   return(OK);
  1111. 32699 }
  1112. 32702 /*==========================================================================*
  1113. 32703  *                              w_dma_setup                                 *
  1114. 32704  *==========================================================================*/
  1115. 32705 PRIVATE void w_dma_setup(tp, count)
  1116. 32706 struct trans *tp;               /* pointer to the transfer struct */
  1117. 32707 unsigned count;                 /* bytes to transfer */
  1118. 32708 {
  1119. 32709 /* The IBM PC can perform DMA operations by using the DMA chip.  To use it,
  1120. 32710  * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
  1121. 32711  * to by read from or written to, the byte count minus 1, and a read or write
  1122. 32712  * opcode.  This routine sets up the DMA chip.  Note that the chip is not
  1123. 32713  * capable of doing a DMA across a 64K boundary (e.g., you can't read a
  1124. 32714  * 512-byte block starting at physical address 65520).
  1125. 32715  */
  1126. 32716
  1127. 32717   /* Set up the DMA registers. */
  1128. 32718   out_byte(DMA_FLIPFLOP, 0);            /* write anything to reset it */
  1129. 32719   out_byte(DMA_MODE, w_opcode == DEV_WRITE ? DMA_WRITE : DMA_READ);
  1130. 32720   out_byte(DMA_ADDR, (int) tp->tr_dma >>  0);
  1131. 32721   out_byte(DMA_ADDR, (int) tp->tr_dma >>  8);
  1132. 32722   out_byte(DMA_TOP, (int) (tp->tr_dma >> 16));
  1133. 32723   out_byte(DMA_COUNT, (count - 1) >> 0);
  1134. 32724   out_byte(DMA_COUNT, (count - 1) >> 8);
  1135. 32725 }
  1136. 32728 /*=========================================================================*
  1137. 32729  *                              w_transfer                                 *
  1138. 32730  *=========================================================================*/
  1139. 32731 PRIVATE int w_transfer(tp, count)
  1140. 32732 struct trans *tp;               /* pointer to the transfer struct */
  1141. 32733 unsigned count;                 /* transferring count bytes */
  1142. 32734 {
  1143. 32735 /* Read or write count bytes starting with tp->tr_block. */
  1144. 32736
  1145. 32737   unsigned cylinder, sector, head, secspcyl = w_wn->wn_heads * NR_SECTORS;
  1146. 32738   u8_t command[6];
  1147. 32739   message mess;
  1148. 32740
  1149. 32741   cylinder = tp->tr_block / secspcyl;
  1150. 32742   head = (tp->tr_block % secspcyl) / NR_SECTORS;
  1151. 32743   sector = tp->tr_block % NR_SECTORS;
  1152. 32744
  1153. 32745   /* The command is issued by outputting 6 bytes to the controller chip. */
  1154. 32746   command[0] = w_opcode == DEV_WRITE ? WIN_WRITE : WIN_READ;
  1155. 32747   command[1] = head | (w_drive << 5);
  1156. 32748   command[2] = ((cylinder & 0x0300) >> 2) | sector;
  1157. 32749   command[3] = cylinder & 0xFF;
  1158. 32750   command[4] = count >> SECTOR_SHIFT;
  1159. 32751   command[5] = w_wn->wn_ctlbyte;
  1160. 32752
  1161. 32753   if (com_out(DMA_INT, command) != OK)
  1162. 32754         return(ERR);
  1163. 32755
  1164. 32756   out_byte(DMA_INIT, 3);        /* initialize DMA */
  1165. 32757
  1166. 32758   /* Block, waiting for disk interrupt. */
  1167. 32759   receive(HARDWARE, &mess);
  1168. 32760
  1169. 32761   /* Get controller status and check for errors. */
  1170. 32762   if (win_results() == OK)
  1171. 32763         return(OK);
  1172. 32764   if ((w_results[0] & 63) == 24)
  1173. 32765         read_ecc();
  1174. 32766   else
  1175. 32767         w_need_reset = TRUE;
  1176. 32768   return(ERR);
  1177. 32769 }
  1178. 32772 /*==========================================================================*
  1179. 32773  *                              win_results                                 *
  1180. 32774  *==========================================================================*/
  1181. 32775 PRIVATE int win_results()
  1182. 32776 {
  1183. 32777 /* Extract results from the controller after an operation. */
  1184. 32778
  1185. 32779   int i, status;
  1186. 32780   u8_t command[6];
  1187. 32781
  1188. 32782   status = in_byte(WIN_DATA);
  1189. 32783   out_byte(WIN_DMA, 0);
  1190. 32784   if (!(status & 2))            /* Test "error" bit */
  1191. 32785         return(OK);
  1192. 32786   command[0] = WIN_SENSE;
  1193. 32787   command[1] = w_drive << 5;
  1194. 32788   if (com_out(NO_DMA_INT, command) != OK)
  1195. 32789         return(ERR);
  1196. 32790
  1197. 32791   /* Loop, extracting bytes from WIN */
  1198. 32792   for (i = 0; i < MAX_RESULTS; i++) {
  1199. 32793         if (hd_wait(WST_REQ) != OK)
  1200. 32794                 return(ERR);
  1201. 32795         status = in_byte(WIN_DATA);
  1202. 32796         w_results[i] = status & BYTE;
  1203. 32797   }
  1204. 32798   if (hd_wait(WST_REQ) != OK)   /* Missing from                 */
  1205. 32799          return (ERR);          /* Original.  11-Apr-87 G.O.    */
  1206. 32800
  1207. 32801   status = in_byte(WIN_DATA);    /* Read "error" flag */
  1208. 32802
  1209. 32803   if (((status & 2) != 0) || (w_results[0] & 0x3F)) {
  1210. 32804         return(ERR);
  1211. 32805   } else
  1212. 32806         return(OK);
  1213. 32807 }
  1214. 32810 /*===========================================================================*
  1215. 32811  *                              win_out                                      *
  1216. 32812  *===========================================================================*/
  1217. 32813 PRIVATE void win_out(val)
  1218. 32814 int val;                /* write this byte to winchester disk controller */
  1219. 32815 {
  1220. 32816 /* Output a byte to the controller.  This is not entirely trivial, since you
  1221. 32817  * can only write to it when it is listening, and it decides when to listen.
  1222. 32818  * If the controller refuses to listen, the WIN chip is given a hard reset.
  1223. 32819  */
  1224. 32820   int r;
  1225. 32821
  1226. 32822   if (w_need_reset) return;     /* if controller is not listening, return */
  1227. 32823
  1228. 32824   do {
  1229. 32825         r = in_byte(WIN_STATUS);
  1230. 32826   } while((r & (WST_REQ | WST_BUSY)) == WST_BUSY);
  1231. 32827
  1232. 32828   out_byte(WIN_DATA, val);
  1233. 32829 }
  1234. 32832 /*===========================================================================*
  1235. 32833  *                              w_reset                                      *
  1236. 32834  *===========================================================================*/
  1237. 32835 PRIVATE int w_reset()
  1238. 32836 {
  1239. 32837 /* Issue a reset to the controller.  This is done after any catastrophe,
  1240. 32838  * like the controller refusing to respond.
  1241. 32839  */
  1242. 32840
  1243. 32841   int r, i, drive;
  1244. 32842   u8_t command[6];
  1245. 32843   message mess;
  1246. 32844
  1247. 32845   /* Strobe reset bit low. */
  1248. 32846   out_byte(WIN_STATUS, 0);
  1249. 32847
  1250. 32848   milli_delay(5);       /* Wait for a while */
  1251. 32849
  1252. 32850   out_byte(WIN_SELECT, 0);      /* Issue select pulse */
  1253. 32851   for (i = 0; i < MAX_WIN_RETRY; i++) {
  1254. 32852         r = in_byte(WIN_STATUS);
  1255. 32853         if (r & (WST_DRQ | WST_IRQ))
  1256. 32854                 return(ERR);
  1257. 32855
  1258. 32856         if ((r & (WST_BUSY | WST_BUS | WST_REQ)) ==
  1259. 32857                 (WST_BUSY | WST_BUS | WST_REQ))
  1260. 32858                 break;
  1261. 32859   }
  1262. 32860
  1263. 32861   if (i == MAX_WIN_RETRY) {
  1264. 32862         printf("%s: reset failed, status = %xn", w_name(), r);
  1265. 32863         return(ERR);
  1266. 32864   }
  1267. 32865
  1268. 32866   /* Reset succeeded.  Tell WIN drive parameters. */
  1269. 32867   w_need_reset = FALSE;
  1270. 32868
  1271. 32869   for (drive = 0; drive < nr_drives; drive++) {
  1272. 32870         if (win_specify(drive) != OK)
  1273. 32871                 return (ERR);
  1274. 32872
  1275. 32873         command[0] = WIN_RECALIBRATE;
  1276. 32874         command[1] = drive << 5;
  1277. 32875         command[5] = wini[drive].wn_ctlbyte;
  1278. 32876
  1279. 32877         if (com_out(INT, command) != OK)
  1280. 32878                 return(ERR);
  1281. 32879
  1282. 32880         receive(HARDWARE, &mess);
  1283. 32881
  1284. 32882         if (win_results() != OK) {
  1285. 32883                 /* No actual drive present? */
  1286. 32884                 nr_drives = drive;
  1287. 32885         }
  1288. 32886   }
  1289. 32887   return(nr_drives > 0 ? OK : ERR);
  1290. 32888 }
  1291. 32891 /*==========================================================================*
  1292. 32892  *                              w_handler                                   *
  1293. 32893  *==========================================================================*/
  1294. 32894 PRIVATE int w_handler(irq)
  1295. 32895 int irq;
  1296. 32896 {
  1297. 32897 /* Disk interrupt, send message to winchester task and reenable interrupts. */
  1298. 32898
  1299. 32899   int r, i;
  1300. 32900
  1301. 32901   out_byte(DMA_INIT, 0x07);     /* Disable int from DMA */
  1302. 32902
  1303. 32903   for (i = 0; i < MAX_WIN_RETRY; ++i) {
  1304. 32904         r = in_byte(WIN_STATUS);
  1305. 32905         if (r & WST_IRQ)
  1306. 32906                 break;          /* Exit if end of int */
  1307. 32907   }
  1308. 32908
  1309. 32909   interrupt(WINCHESTER);
  1310. 32910   return 1;
  1311. 32911 }
  1312. 32914 /*============================================================================*
  1313. 32915  *                              win_specify                                   *
  1314. 32916  *============================================================================*/
  1315. 32917 PRIVATE int win_specify(drive)
  1316. 32918 int drive;
  1317. 32919 {
  1318. 32920   struct wini *wn = &wini[drive];
  1319. 32921   u8_t command[6];
  1320. 32922
  1321. 32923   command[0] = WIN_SPECIFY;             /* Specify some parameters */
  1322. 32924   command[1] = drive << 5;              /* Drive number */
  1323. 32925
  1324. 32926   if (com_out(NO_DMA_INT, command) != OK)       /* Output command block */
  1325. 32927         return(ERR);
  1326. 32928
  1327. 32929         /* No. of cylinders (high byte) */
  1328. 32930   win_out(wn->wn_cylinders >> 8);
  1329. 32931
  1330. 32932         /* No. of cylinders (low byte) */
  1331. 32933   win_out(wn->wn_cylinders);
  1332. 32934
  1333. 32935         /* No. of heads */
  1334. 32936   win_out(wn->wn_heads);
  1335. 32937
  1336. 32938         /* Start reduced write (high byte) */
  1337. 32939   win_out(wn->wn_reduced_wr >> 8);
  1338. 32940
  1339. 32941         /* Start reduced write (low byte) */
  1340. 32942   win_out(wn->wn_reduced_wr);
  1341. 32943
  1342. 32944         /* Start write precompensation (high byte) */
  1343. 32945   win_out(wn->wn_precomp >> 8);
  1344. 32946
  1345. 32947         /* Start write precompensation (low byte) */
  1346. 32948   win_out(wn->wn_precomp);
  1347. 32949
  1348. 32950         /* Ecc burst length */
  1349. 32951   win_out(wn->wn_max_ecc);
  1350. 32952
  1351. 32953   if (check_init() != OK) {  /* See if controller accepted parameters */
  1352. 32954         w_need_reset = TRUE;
  1353. 32955         return(ERR);
  1354. 32956   } else
  1355. 32957         return(OK);
  1356. 32958 }
  1357. 32961 /*============================================================================*
  1358. 32962  *                              check_init                                    *
  1359. 32963  *============================================================================*/
  1360. 32964 PRIVATE int check_init()
  1361. 32965 {
  1362. 32966 /* Routine to check if controller accepted the parameters */
  1363. 32967   int r, s;
  1364. 32968
  1365. 32969   if (hd_wait(WST_REQ | WST_INPUT) == OK) {
  1366. 32970         r = in_byte(WIN_DATA);
  1367. 32971
  1368. 32972         do {
  1369. 32973                 s = in_byte(WIN_STATUS);
  1370. 32974         } while(s & WST_BUSY);          /* Loop while still busy */
  1371. 32975
  1372. 32976         if (r & 2)              /* Test error bit */
  1373. 32977                 return(ERR);
  1374. 32978         else
  1375. 32979                 return(OK);
  1376. 32980   } else
  1377. 32981         return (ERR);   /* Missing from original: 11-Apr-87 G.O. */
  1378. 32982 }
  1379. 32985 /*============================================================================*
  1380. 32986  *                              read_ecc                                      *
  1381. 32987  *============================================================================*/
  1382. 32988 PRIVATE int read_ecc()
  1383. 32989 {
  1384. 32990 /* Read the ecc burst-length and let the controller correct the data */
  1385. 32991
  1386. 32992   int r;
  1387. 32993   u8_t command[6];
  1388. 32994
  1389. 32995   command[0] = WIN_ECC_READ;
  1390. 32996   if (com_out(NO_DMA_INT, command) == OK && hd_wait(WST_REQ) == OK) {
  1391. 32997         r = in_byte(WIN_DATA);
  1392. 32998         if (hd_wait(WST_REQ) == OK) {
  1393. 32999                 r = in_byte(WIN_DATA);
  1394. 33000                 if (r & 1)
  1395. 33001                         w_need_reset = TRUE;
  1396. 33002         }
  1397. 33003   }
  1398. 33004   return(ERR);
  1399. 33005 }
  1400. 33008 /*============================================================================*
  1401. 33009  *                              hd_wait                                       *
  1402. 33010  *============================================================================*/
  1403. 33011 PRIVATE int hd_wait(bits)
  1404. 33012 int bits;
  1405. 33013 {
  1406. 33014 /* Wait until the controller is ready to receive a command or send status */
  1407. 33015
  1408. 33016   int r, i = 0;
  1409. 33017
  1410. 33018   do {
  1411. 33019         r = in_byte(WIN_STATUS) & bits;
  1412. 33020   } while ((i++ < MAX_WIN_RETRY) && r != bits);         /* Wait for ALL bits */
  1413. 33021
  1414. 33022   if (i >= MAX_WIN_RETRY) {
  1415. 33023         w_need_reset = TRUE;
  1416. 33024         return(ERR);
  1417. 33025   } else
  1418. 33026         return(OK);
  1419. 33027 }
  1420. 33030 /*============================================================================*
  1421. 33031  *                              com_out                                       *
  1422. 33032  *============================================================================*/
  1423. 33033 PRIVATE int com_out(mode, commandp)
  1424. 33034 int mode;
  1425. 33035 u8_t *commandp;
  1426. 33036 {
  1427. 33037 /* Output the command block to the winchester controller and return status */
  1428. 33038
  1429. 33039   int i, r;
  1430. 33040
  1431. 33041   out_byte(WIN_DMA, mode);
  1432. 33042   out_byte(WIN_SELECT, mode);
  1433. 33043   for (i = 0; i < MAX_WIN_RETRY; i++) {
  1434. 33044         r = in_byte(WIN_STATUS);
  1435. 33045         if (r & WST_BUSY)
  1436. 33046                 break;
  1437. 33047   }
  1438. 33048
  1439. 33049   if (i == MAX_WIN_RETRY) {
  1440. 33050         w_need_reset = TRUE;
  1441. 33051         return(ERR);
  1442. 33052   }
  1443. 33053
  1444. 33054
  1445. 33055   for (i = 0; i < 6; i++) {
  1446. 33056         if (hd_wait(WST_REQ) != OK)
  1447. 33057                 break;          /* No data request pending */
  1448. 33058
  1449. 33059         r = in_byte(WIN_STATUS);
  1450. 33060
  1451. 33061         if ((r & (WST_BUSY | WST_BUS | WST_INPUT)) !=
  1452. 33062                 (WST_BUSY | WST_BUS))
  1453. 33063                 break;
  1454. 33064
  1455. 33065         out_byte(WIN_DATA, commandp[i]);
  1456. 33066   }
  1457. 33067
  1458. 33068   if (i != 6)
  1459. 33069         return(ERR);
  1460. 33070   else
  1461. 33071         return(OK);
  1462. 33072 }
  1463. 33075 /*==========================================================================*
  1464. 33076  *                              init_params                                 *
  1465. 33077  *==========================================================================*/
  1466. 33078 PRIVATE void init_params()
  1467. 33079 {
  1468. 33080 /* This routine is called at startup to initialize the number of drives and
  1469. 33081  * the controller.
  1470. 33082  */
  1471. 33083   u16_t parv[2];
  1472. 33084   unsigned int drive;
  1473. 33085   int dtype;
  1474. 33086   phys_bytes address, buf_phys;
  1475. 33087   char buf[16];
  1476. 33088
  1477. 33089   /* Get the number of drives from the bios */
  1478. 33090   buf_phys = vir2phys(buf);
  1479. 33091   phys_copy(0x475L, buf_phys, 1L);
  1480. 33092   nr_drives = buf[0] & 0xFF;
  1481. 33093   if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
  1482. 33094
  1483. 33095   /* Read the switches from the controller */
  1484. 33096   w_switches = in_byte(WIN_SELECT);
  1485. 33097
  1486. 33098 #if AUTO_BIOS
  1487. 33099   /* If no auto configuration or not enabled then go to the ROM. */
  1488. 33100   if (!(w_switches & AUTO_ENABLE)) {
  1489. 33101 #endif
  1490. 33102         for (drive = 0; drive < nr_drives; drive++) {
  1491. 33103                 /* Calculate the drive type */
  1492. 33104                 dtype = (w_switches >> (2 * drive)) & 03;
  1493. 33105
  1494. 33106                 /* Copy the BIOS parameter vector */
  1495. 33107                 phys_copy(WINI_0_PARM_VEC * 4L, vir2phys(parv), 4L);
  1496. 33108
  1497. 33109                 /* Calculate the parameters' address and copy them to buf */
  1498. 33110                 address = hclick_to_physb(parv[1]) + parv[0] + 16 * dtype;
  1499. 33111                 phys_copy(address, buf_phys, 16L);
  1500. 33112
  1501. 33113                 /* Copy the parameters to the structure of the drive. */
  1502. 33114                 copy_param(buf, &wini[drive]);
  1503. 33115         }
  1504. 33116 #if AUTO_BIOS
  1505. 33117   }
  1506. 33118 #endif
  1507. 33119 }
  1508. 33122 /*============================================================================*
  1509. 33123  *                              w_do_open                                     *
  1510. 33124  *============================================================================*/
  1511. 33125 PRIVATE int w_do_open(dp, m_ptr)
  1512. 33126 struct driver *dp;
  1513. 33127 message *m_ptr;
  1514. 33128 {
  1515. 33129 /* Device open: Initialize the controller and read the partition table. */
  1516. 33130
  1517. 33131   static int init_done = FALSE;
  1518. 33132
  1519. 33133   if (!init_done) { w_init(); init_done = TRUE; }
  1520. 33134
  1521. 33135   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1522. 33136
  1523. 33137   if (w_wn->wn_open_ct++ == 0) {
  1524. 33138         /* Partition the disk. */
  1525. 33139         partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY);
  1526. 33140   }
  1527. 33141   return(OK);
  1528. 33142 }
  1529. 33145 /*============================================================================*
  1530. 33146  *                              w_do_close                                    *
  1531. 33147  *============================================================================*/
  1532. 33148 PRIVATE int w_do_close(dp, m_ptr)
  1533. 33149 struct driver *dp;
  1534. 33150 message *m_ptr;
  1535. 33151 {
  1536. 33152 /* Device close: Release a device. */
  1537. 33153
  1538. 33154   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1539. 33155   w_wn->wn_open_ct--;
  1540. 33156   return(OK);
  1541. 33157 }
  1542. 33160 /*==========================================================================*
  1543. 33161  *                              w_init                                      *
  1544. 33162  *==========================================================================*/
  1545. 33163 PRIVATE void w_init()
  1546. 33164 {
  1547. 33165   /* Initialize the controller. */
  1548. 33166
  1549. 33167   int drive;
  1550. 33168   struct wini *wn;
  1551. 33169 #if AUTO_BIOS
  1552. 33170   message mess;
  1553. 33171
  1554. 33172   for (drive = 0; drive < nr_drives; drive++) {
  1555. 33173         /* Get the drive parameters from sector zero of the drive if the
  1556. 33174          * autoconfig mode of the controller has been selected.
  1557. 33175          */
  1558. 33176         if (w_switches & AUTO_ENABLE) {
  1559. 33177                 /* Set up some phony parameters so that we can read the
  1560. 33178                  * first sector from the winchester.  All drives will have
  1561. 33179                  * one cylinder and one head but set up initially to the
  1562. 33180                  * mini scribe drives from IBM.
  1563. 33181                  */
  1564. 33182                 wn = &wini[drive];
  1565. 33183                 wn->wn_cylinders = AUTO_CYLS;
  1566. 33184                 wn->wn_heads = AUTO_HEADS;
  1567. 33185                 wn->wn_reduced_wr = AUTO_RWC;
  1568. 33186                 wn->wn_precomp = AUTO_WPC;
  1569. 33187                 wn->wn_max_ecc = AUTO_ECC;
  1570. 33188                 wn->wn_ctlbyte = AUTO_CTRL;
  1571. 33189                 wn->wn_part[0].dv_size = SECTOR_SIZE;
  1572. 33190         }
  1573. 33191   }
  1574. 33192
  1575. 33193   /* Initialize controller to read parameters from the drives. */
  1576. 33194   if (nr_drives > 0 && w_reset() != OK) nr_drives = 0;
  1577. 33195
  1578. 33196   for (drive = 0; drive < nr_drives; drive++) {
  1579. 33197         if (w_switches & AUTO_ENABLE) {
  1580. 33198                 /* read the first sector from the drive */
  1581. 33199                 mess.DEVICE = drive * DEV_PER_DRIVE;
  1582. 33200                 mess.POSITION = 0L;
  1583. 33201                 mess.COUNT = SECTOR_SIZE;
  1584. 33202                 mess.ADDRESS = (char *) tmp_buf;
  1585. 33203                 mess.PROC_NR = WINCHESTER;
  1586. 33204                 mess.m_type = DEV_READ;
  1587. 33205                 if (do_rdwt(&w_dtab, &mess) != SECTOR_SIZE) {
  1588. 33206                         printf("%s: can't read parametersn", w_name());
  1589. 33207                         nr_drives = drive;
  1590. 33208                         break;
  1591. 33209                 }
  1592. 33210
  1593. 33211                 /* save the parameter tables for later use */
  1594. 33212                 copy_param(&tmp_buf[AUTO_PARAM], &wini[drive]);
  1595. 33213         }
  1596. 33214   }
  1597. 33215 #endif
  1598. 33216
  1599. 33217   if (nr_drives > 0 && w_reset() != OK) nr_drives = 0;
  1600. 33218
  1601. 33219   /* Set the size of each disk. */
  1602. 33220   for (drive = 0; drive < nr_drives; drive++) {
  1603. 33221         (void) w_prepare(drive * DEV_PER_DRIVE);
  1604. 33222         wn = w_wn;
  1605. 33223         wn->wn_part[0].dv_size = ((unsigned long) wn->wn_cylinders *
  1606. 33224                                 wn->wn_heads * NR_SECTORS) << SECTOR_SHIFT;
  1607. 33225         printf("%s: %d cylinders, %d heads, %d sectors per trackn",
  1608. 33226                 w_name(), wn->wn_cylinders, wn->wn_heads, NR_SECTORS);
  1609. 33227   }
  1610. 33228 }
  1611. 33231 /*==========================================================================*
  1612. 33232  *                              copy_param                                  *
  1613. 33233  *==========================================================================*/
  1614. 33234 PRIVATE void copy_param(src, dest)
  1615. 33235 char *src;
  1616. 33236 struct wini *dest;
  1617. 33237 {
  1618. 33238 /* This routine copies the parameters from src to dest.  */
  1619. 33239
  1620. 33240   dest->wn_cylinders = bp_cylinders(src);
  1621. 33241   dest->wn_heads = bp_heads(src);
  1622. 33242   dest->wn_reduced_wr = bp_reduced_wr(src);
  1623. 33243   dest->wn_precomp = bp_precomp(src);
  1624. 33244   dest->wn_max_ecc = bp_max_ecc(src);
  1625. 33245   dest->wn_ctlbyte = bp_ctlbyte(src);
  1626. 33246 }
  1627. 33249 /*============================================================================*
  1628. 33250  *                              w_geometry                                    *
  1629. 33251  *============================================================================*/
  1630. 33252 PRIVATE void w_geometry(entry)
  1631. 33253 struct partition *entry;
  1632. 33254 {
  1633. 33255   entry->cylinders = w_wn->wn_cylinders;
  1634. 33256   entry->heads = w_wn->wn_heads;
  1635. 33257   entry->sectors = NR_SECTORS;
  1636. 33258 }
  1637. 33259 #endif /* ENABLE_XT_WINI */
  1638. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1639. src/kernel/klib.s    
  1640. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1641. 33300 #
  1642. 33301 ! Chooses between the 8086 and 386 versions of the low level kernel code.
  1643. 33302
  1644. 33303 #include <minix/config.h>
  1645. 33304 #if _WORD_SIZE == 2
  1646. 33305 #include "klib88.s"
  1647. 33306 #else
  1648. 33307 #include "klib386.s"
  1649. 33308 #endif
  1650. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1651. src/kernel/klib386.s    
  1652. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1653. 33400 #
  1654. 33401 ! sections
  1655. 33402
  1656. 33403 .sect .text; .sect .rom; .sect .data; .sect .bss
  1657. 33404
  1658. 33405 #include <minix/config.h>
  1659. 33406 #include <minix/const.h>
  1660. 33407 #include "const.h"
  1661. 33408 #include "sconst.h"
  1662. 33409 #include "protect.h"
  1663. 33410
  1664. 33411 ! This file contains a number of assembly code utility routines needed by the
  1665. 33412 ! kernel.  They are:
  1666. 33413
  1667. 33414 .define _monitor        ! exit Minix and return to the monitor
  1668. 33415 .define _check_mem      ! check a block of memory, return the valid size
  1669. 33416 .define _cp_mess        ! copies messages from source to destination
  1670. 33417 .define _exit           ! dummy for library routines
  1671. 33418 .define __exit          ! dummy for library routines
  1672. 33419 .define ___exit         ! dummy for library routines
  1673. 33420 .define ___main         ! dummy for GCC
  1674. 33421 .define _in_byte        ! read a byte from a port and return it
  1675. 33422 .define _in_word        ! read a word from a port and return it
  1676. 33423 .define _out_byte       ! write a byte to a port
  1677. 33424 .define _out_word       ! write a word to a port
  1678. 33425 .define _port_read      ! transfer data from (disk controller) port to memory
  1679. 33426 .define _port_read_byte ! likewise byte by byte
  1680. 33427 .define _port_write     ! transfer data from memory to (disk controller) port
  1681. 33428 .define _port_write_byte ! likewise byte by byte
  1682. 33429 .define _lock           ! disable interrupts
  1683. 33430 .define _unlock         ! enable interrupts
  1684. 33431 .define _enable_irq     ! enable an irq at the 8259 controller
  1685. 33432 .define _disable_irq    ! disable an irq
  1686. 33433 .define _phys_copy      ! copy data from anywhere to anywhere in memory
  1687. 33434 .define _mem_rdw        ! copy one word from [segment:offset]
  1688. 33435 .define _reset          ! reset the system
  1689. 33436 .define _mem_vid_copy   ! copy data to video ram
  1690. 33437 .define _vid_vid_copy   ! move data in video ram
  1691. 33438 .define _level0         ! call a function at level 0
  1692. 33439
  1693. 33440 ! The routines only guarantee to preserve the registers the C compiler
  1694. 33441 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
  1695. 33442 ! direction bit in the flags).
  1696. 33443
  1697. 33444 ! imported variables
  1698. 33445
  1699. 33446 .sect .bss
  1700. 33447 .extern _mon_return, _mon_sp
  1701. 33448 .extern _irq_use
  1702. 33449 .extern _blank_color
  1703. 33450 .extern _ext_memsize
  1704. 33451 .extern _gdt
  1705. 33452 .extern _low_memsize
  1706. 33453 .extern _sizes
  1707. 33454 .extern _vid_seg
  1708. 33455 .extern _vid_size
  1709. 33456 .extern _vid_mask
  1710. 33457 .extern _level0_func
  1711. 33458
  1712. 33459 .sect .text
  1713. 33460 !*===========================================================================*
  1714. 33461 !*                              monitor                                      *
  1715. 33462 !*===========================================================================*
  1716. 33463 ! PUBLIC void monitor();
  1717. 33464 ! Return to the monitor.
  1718. 33465
  1719. 33466 _monitor:
  1720. 33467         mov     eax, (_reboot_code)     ! address of new parameters
  1721. 33468         mov     esp, (_mon_sp)          ! restore monitor stack pointer
  1722. 33469     o16 mov     dx, SS_SELECTOR         ! monitor data segment
  1723. 33470         mov     ds, dx
  1724. 33471         mov     es, dx
  1725. 33472         mov     fs, dx
  1726. 33473         mov     gs, dx
  1727. 33474         mov     ss, dx
  1728. 33475         pop     edi
  1729. 33476         pop     esi
  1730. 33477         pop     ebp
  1731. 33478     o16 retf                            ! return to the monitor
  1732. 33479
  1733. 33480
  1734. 33481 #if ENABLE_BIOS_WINI
  1735. 33482 !*===========================================================================*
  1736. 33483 !*                              bios13                                       *
  1737. 33484 !*===========================================================================*
  1738. 33485 ! PUBLIC void bios13();
  1739. 33486 .define _bios13
  1740. 33487 _bios13:
  1741. 33488         cmpb    (_mon_return), 0        ! is the monitor there?
  1742. 33489         jnz     0f
  1743. 33490         movb    (_Ax+1), 0x01           ! "invalid command"
  1744. 33491         ret
  1745. 33492 0:      push    ebp                     ! save C registers
  1746. 33493         push    esi
  1747. 33494         push    edi
  1748. 33495         push    ebx
  1749. 33496         pushf                           ! save flags
  1750. 33497         cli                             ! no interruptions
  1751. 33498
  1752. 33499         inb     INT2_CTLMASK
  1753. 33500         movb    ah, al
  1754. 33501         inb     INT_CTLMASK
  1755. 33502         push    eax                     ! save interrupt masks
  1756. 33503         mov     eax, (_irq_use)         ! map of in-use IRQs
  1757. 33504         and     eax, ~[1<<CLOCK_IRQ]    ! there is a special clock handler
  1758. 33505         outb    INT_CTLMASK             ! enable all unused IRQs and vv.
  1759. 33506         movb    al, ah
  1760. 33507         outb    INT2_CTLMASK
  1761. 33508
  1762. 33509         mov     eax, cr0
  1763. 33510         push    eax                     ! save machine status word
  1764. 33511
  1765. 33512         mov     eax, SS_SELECTOR        ! monitor data segment
  1766. 33513         mov     ss, ax
  1767. 33514         xchg    esp, (_mon_sp)          ! switch stacks
  1768. 33515     o16 push    (_Es)                   ! parameters used in bios 13 call
  1769. 33516     o16 push    (_Dx)
  1770. 33517     o16 push    (_Cx)
  1771. 33518     o16 push    (_Bx)
  1772. 33519     o16 push    (_Ax)
  1773. 33520         mov     ds, ax                  ! remaining data selectors
  1774. 33521         mov     es, ax
  1775. 33522         mov     fs, ax
  1776. 33523         mov     gs, ax
  1777. 33524         push    cs
  1778. 33525         push    return                  ! kernel return address and selector
  1779. 33526     o16 jmpf    16+2*4+5*2+2*4(esp)     ! make the call
  1780. 33527 return:
  1781. 33528     o16 pop     (_Ax)
  1782. 33529     o16 pop     (_Bx)
  1783. 33530     o16 pop     (_Cx)
  1784. 33531     o16 pop     (_Dx)
  1785. 33532     o16 pop     (_Es)
  1786. 33533         lgdt    (_gdt+GDT_SELECTOR)     ! reload global descriptor table
  1787. 33534         jmpf    CS_SELECTOR:csinit      ! restore everything
  1788. 33535 csinit: mov     eax, DS_SELECTOR
  1789. 33536         mov     ds, ax
  1790. 33537         mov     es, ax
  1791. 33538         mov     fs, ax
  1792. 33539         mov     gs, ax
  1793. 33540         mov     ss, ax
  1794. 33541         xchg    esp, (_mon_sp)          ! unswitch stacks
  1795. 33542         lidt    (_gdt+IDT_SELECTOR)     ! reload interrupt descriptor table
  1796. 33543         andb    (_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02  ! clear TSS busy bit
  1797. 33544         mov     ax, TSS_SELECTOR
  1798. 33545         ltr     ax                      ! set TSS register
  1799. 33546
  1800. 33547         pop     eax
  1801. 33548         mov     cr0, eax                ! restore machine status word
  1802. 33549
  1803. 33550         pop     eax
  1804. 33551         outb    INT_CTLMASK             ! restore interrupt masks
  1805. 33552         movb    al, ah
  1806. 33553         outb    INT2_CTLMASK
  1807. 33554
  1808. 33555         popf                            ! restore flags
  1809. 33556         pop     ebx                     ! restore C registers
  1810. 33557         pop     edi
  1811. 33558         pop     esi
  1812. 33559         pop     ebp
  1813. 33560         ret
  1814. 33561
  1815. 33562 .sect .bss
  1816. 33563 .define _Ax, _Bx, _Cx, _Dx, _Es         ! 8086 register variables
  1817. 33564 .comm   _Ax, 4
  1818. 33565 .comm   _Bx, 4
  1819. 33566 .comm   _Cx, 4
  1820. 33567 .comm   _Dx, 4
  1821. 33568 .comm   _Es, 4
  1822. 33569 .sect .text
  1823. 33570 #endif /* ENABLE_BIOS_WINI */
  1824. 33571
  1825. 33572
  1826. 33573 !*===========================================================================*
  1827. 33574 !*                              check_mem                                    *
  1828. 33575 !*===========================================================================*
  1829. 33576 ! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
  1830. 33577 ! Check a block of memory, return the amount valid.
  1831. 33578 ! Only every 16th byte is checked.
  1832. 33579 ! An initial size of 0 means everything.
  1833. 33580 ! This really should do some alias checks.
  1834. 33581
  1835. 33582 CM_DENSITY      =       16
  1836. 33583 CM_LOG_DENSITY  =       4
  1837. 33584 TEST1PATTERN    =       0x55            ! memory test pattern 1
  1838. 33585 TEST2PATTERN    =       0xAA            ! memory test pattern 2
  1839. 33586
  1840. 33587 CHKM_ARGS       =       4 + 4 + 4       ! 4 + 4
  1841. 33588 !                       ds ebx eip      base size
  1842. 33589
  1843. 33590 _check_mem:
  1844. 33591         push    ebx
  1845. 33592         push    ds
  1846. 33593     o16 mov     ax, FLAT_DS_SELECTOR
  1847. 33594         mov     ds, ax
  1848. 33595         mov     eax, CHKM_ARGS(esp)
  1849. 33596         mov     ebx, eax
  1850. 33597         mov     ecx, CHKM_ARGS+4(esp)
  1851. 33598         shr     ecx, CM_LOG_DENSITY
  1852. 33599 cm_loop:
  1853. 33600         movb    dl, TEST1PATTERN
  1854. 33601         xchgb   dl, (eax)               ! write test pattern, remember original
  1855. 33602         xchgb   dl, (eax)               ! restore original, read test pattern
  1856. 33603         cmpb    dl, TEST1PATTERN        ! must agree if good real memory
  1857. 33604         jnz     cm_exit                 ! if different, memory is unusable
  1858. 33605         movb    dl, TEST2PATTERN
  1859. 33606         xchgb   dl, (eax)
  1860. 33607         xchgb   dl, (eax)
  1861. 33608         add     eax, CM_DENSITY
  1862. 33609         cmpb    dl, TEST2PATTERN
  1863. 33610         loopz   cm_loop
  1864. 33611 cm_exit:
  1865. 33612         sub     eax, ebx
  1866. 33613         pop     ds
  1867. 33614         pop     ebx
  1868. 33615         ret
  1869. 33616
  1870. 33617
  1871. 33618 !*===========================================================================*
  1872. 33619 !*                              cp_mess                                      *
  1873. 33620 !*===========================================================================*
  1874. 33621 ! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
  1875. 33622 !                     phys_clicks dst_clicks, vir_bytes dst_offset);
  1876. 33623 ! This routine makes a fast copy of a message from anywhere in the address
  1877. 33624 ! space to anywhere else.  It also copies the source address provided as a
  1878. 33625 ! parameter to the call into the first word of the destination message.
  1879. 33626 !
  1880. 33627 ! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
  1881. 33628 ! correctly.  Changing the definition of message in the type file and not
  1882. 33629 ! changing it here will lead to total disaster.
  1883. 33630
  1884. 33631 CM_ARGS =       4 + 4 + 4 + 4 + 4       ! 4 + 4 + 4 + 4 + 4
  1885. 33632 !               es  ds edi esi eip      proc scl sof dcl dof
  1886. 33633
  1887. 33634         .align  16
  1888. 33635 _cp_mess:
  1889. 33636         cld
  1890. 33637         push    esi
  1891. 33638         push    edi
  1892. 33639         push    ds
  1893. 33640         push    es
  1894. 33641
  1895. 33642         mov     eax, FLAT_DS_SELECTOR
  1896. 33643         mov     ds, ax
  1897. 33644         mov     es, ax
  1898. 33645
  1899. 33646         mov     esi, CM_ARGS+4(esp)             ! src clicks
  1900. 33647         shl     esi, CLICK_SHIFT
  1901. 33648         add     esi, CM_ARGS+4+4(esp)           ! src offset
  1902. 33649         mov     edi, CM_ARGS+4+4+4(esp)         ! dst clicks
  1903. 33650         shl     edi, CLICK_SHIFT
  1904. 33651         add     edi, CM_ARGS+4+4+4+4(esp)       ! dst offset
  1905. 33652
  1906. 33653         mov     eax, CM_ARGS(esp)       ! process number of sender
  1907. 33654         stos                            ! copy number of sender to dest message
  1908. 33655         add     esi, 4                  ! do not copy first word
  1909. 33656         mov     ecx, Msize - 1          ! remember, first word does not count
  1910. 33657         rep
  1911. 33658         movs                            ! copy the message
  1912. 33659
  1913. 33660         pop     es
  1914. 33661         pop     ds
  1915. 33662         pop     edi
  1916. 33663         pop     esi
  1917. 33664         ret                             ! that is all folks!
  1918. 33665
  1919. 33666
  1920. 33667 !*===========================================================================*
  1921. 33668 !*                              exit                                         *
  1922. 33669 !*===========================================================================*
  1923. 33670 ! PUBLIC void exit();
  1924. 33671 ! Some library routines use exit, so provide a dummy version.
  1925. 33672 ! Actual calls to exit cannot occur in the kernel.
  1926. 33673 ! GNU CC likes to call ___main from main() for nonobvious reasons.
  1927. 33674
  1928. 33675 _exit:
  1929. 33676 __exit:
  1930. 33677 ___exit:
  1931. 33678         sti
  1932. 33679         jmp     ___exit
  1933. 33680
  1934. 33681 ___main:
  1935. 33682         ret
  1936. 33683
  1937. 33684
  1938. 33685 !*===========================================================================*
  1939. 33686 !*                              in_byte                                      *
  1940. 33687 !*===========================================================================*
  1941. 33688 ! PUBLIC unsigned in_byte(port_t port);
  1942. 33689 ! Read an (unsigned) byte from the i/o port  port  and return it.
  1943. 33690
  1944. 33691         .align  16
  1945. 33692 _in_byte:
  1946. 33693         mov     edx, 4(esp)             ! port
  1947. 33694         sub     eax, eax
  1948. 33695         inb     dx                      ! read 1 byte
  1949. 33696         ret
  1950. 33697
  1951. 33698
  1952. 33699 !*===========================================================================*
  1953. 33700 !*                              in_word                                      *
  1954. 33701 !*===========================================================================*
  1955. 33702 ! PUBLIC unsigned in_word(port_t port);
  1956. 33703 ! Read an (unsigned) word from the i/o port  port  and return it.
  1957. 33704
  1958. 33705         .align  16
  1959. 33706 _in_word:
  1960. 33707         mov     edx, 4(esp)             ! port
  1961. 33708         sub     eax, eax
  1962. 33709     o16 in      dx                      ! read 1 word
  1963. 33710         ret
  1964. 33711
  1965. 33712
  1966. 33713 !*===========================================================================*
  1967. 33714 !*                              out_byte                                     *
  1968. 33715 !*===========================================================================*
  1969. 33716 ! PUBLIC void out_byte(port_t port, u8_t value);
  1970. 33717 ! Write  value  (cast to a byte)  to the I/O port  port.
  1971. 33718
  1972. 33719         .align  16
  1973. 33720 _out_byte:
  1974. 33721         mov     edx, 4(esp)             ! port
  1975. 33722         movb    al, 4+4(esp)            ! value
  1976. 33723         outb    dx                      ! output 1 byte
  1977. 33724         ret
  1978. 33725
  1979. 33726
  1980. 33727 !*===========================================================================*
  1981. 33728 !*                              out_word                                     *
  1982. 33729 !*===========================================================================*
  1983. 33730 ! PUBLIC void out_word(Port_t port, U16_t value);
  1984. 33731 ! Write  value  (cast to a word)  to the I/O port  port.
  1985. 33732
  1986. 33733         .align  16
  1987. 33734 _out_word:
  1988. 33735         mov     edx, 4(esp)             ! port
  1989. 33736         mov     eax, 4+4(esp)           ! value
  1990. 33737     o16 out     dx                      ! output 1 word
  1991. 33738         ret
  1992. 33739
  1993. 33740
  1994. 33741 !*===========================================================================*
  1995. 33742 !*                              port_read                                    *
  1996. 33743 !*===========================================================================*
  1997. 33744 ! PUBLIC void port_read(port_t port, phys_bytes destination, unsigned bytcount);
  1998. 33745 ! Transfer data from (hard disk controller) port to memory.
  1999. 33746
  2000. 33747 PR_ARGS =       4 + 4 + 4               ! 4 + 4 + 4
  2001. 33748 !               es edi eip              port dst len
  2002. 33749
  2003. 33750         .align  16
  2004. 33751 _port_read:
  2005. 33752         cld
  2006. 33753         push    edi
  2007. 33754         push    es
  2008. 33755         mov     ecx, FLAT_DS_SELECTOR
  2009. 33756         mov     es, cx
  2010. 33757         mov     edx, PR_ARGS(esp)       ! port to read from
  2011. 33758         mov     edi, PR_ARGS+4(esp)     ! destination addr
  2012. 33759         mov     ecx, PR_ARGS+4+4(esp)   ! byte count
  2013. 33760         shr     ecx, 1                  ! word count
  2014. 33761         rep                             ! (hardware cannot handle dwords)
  2015. 33762     o16 ins                             ! read everything
  2016. 33763         pop     es
  2017. 33764         pop     edi
  2018. 33765         ret
  2019. 33766
  2020. 33767
  2021. 33768 !*===========================================================================*
  2022. 33769 !*                              port_read_byte                               *
  2023. 33770 !*===========================================================================*
  2024. 33771 ! PUBLIC void port_read_byte(port_t port, phys_bytes destination,
  2025. 33772 !                                               unsigned bytcount);
  2026. 33773 ! Transfer data from port to memory.
  2027. 33774
  2028. 33775 PR_ARGS_B =     4 + 4 + 4               ! 4 + 4 + 4
  2029. 33776 !               es edi eip              port dst len
  2030. 33777
  2031. 33778 _port_read_byte:
  2032. 33779         cld
  2033. 33780         push    edi
  2034. 33781         push    es
  2035. 33782         mov     ecx, FLAT_DS_SELECTOR
  2036. 33783         mov     es, cx
  2037. 33784         mov     edx, PR_ARGS_B(esp)
  2038. 33785         mov     edi, PR_ARGS_B+4(esp)
  2039. 33786         mov     ecx, PR_ARGS_B+4+4(esp)
  2040. 33787         rep
  2041. 33788         insb
  2042. 33789         pop     es
  2043. 33790         pop     edi
  2044. 33791         ret
  2045. 33792
  2046. 33793
  2047. 33794 !*===========================================================================*
  2048. 33795 !*                              port_write                                   *
  2049. 33796 !*===========================================================================*
  2050. 33797 ! PUBLIC void port_write(port_t port, phys_bytes source, unsigned bytcount);
  2051. 33798 ! Transfer data from memory to (hard disk controller) port.
  2052. 33799
  2053. 33800 PW_ARGS =       4 + 4 + 4               ! 4 + 4 + 4
  2054. 33801 !               es edi eip              port src len
  2055. 33802
  2056. 33803         .align  16
  2057. 33804 _port_write:
  2058. 33805         cld
  2059. 33806         push    esi
  2060. 33807         push    ds
  2061. 33808         mov     ecx, FLAT_DS_SELECTOR
  2062. 33809         mov     ds, cx
  2063. 33810         mov     edx, PW_ARGS(esp)       ! port to write to
  2064. 33811         mov     esi, PW_ARGS+4(esp)     ! source addr
  2065. 33812         mov     ecx, PW_ARGS+4+4(esp)   ! byte count
  2066. 33813         shr     ecx, 1                  ! word count
  2067. 33814         rep                             ! (hardware cannot handle dwords)
  2068. 33815     o16 outs                            ! write everything
  2069. 33816         pop     ds
  2070. 33817         pop     esi
  2071. 33818         ret
  2072. 33819
  2073. 33820
  2074. 33821 !*===========================================================================*
  2075. 33822 !*                              port_write_byte                              *
  2076. 33823 !*===========================================================================*
  2077. 33824 ! PUBLIC void port_write_byte(port_t port, phys_bytes source,
  2078. 33825 !                                               unsigned bytcount);
  2079. 33826 ! Transfer data from memory to port.
  2080. 33827
  2081. 33828 PW_ARGS_B =     4 + 4 + 4               ! 4 + 4 + 4
  2082. 33829 !               es edi eip              port src len
  2083. 33830
  2084. 33831 _port_write_byte:
  2085. 33832         cld
  2086. 33833         push    esi
  2087. 33834         push    ds
  2088. 33835         mov     ecx, FLAT_DS_SELECTOR
  2089. 33836         mov     ds, cx
  2090. 33837         mov     edx, PW_ARGS_B(esp)
  2091. 33838         mov     esi, PW_ARGS_B+4(esp)
  2092. 33839         mov     ecx, PW_ARGS_B+4+4(esp)
  2093. 33840         rep
  2094. 33841         outsb
  2095. 33842         pop     ds
  2096. 33843         pop     esi
  2097. 33844         ret
  2098. 33845
  2099. 33846
  2100. 33847 !*===========================================================================*
  2101. 33848 !*                              lock                                         *
  2102. 33849 !*===========================================================================*
  2103. 33850 ! PUBLIC void lock();
  2104. 33851 ! Disable CPU interrupts.
  2105. 33852
  2106. 33853         .align  16
  2107. 33854 _lock:
  2108. 33855         cli                             ! disable interrupts
  2109. 33856         ret
  2110. 33857
  2111. 33858
  2112. 33859 !*===========================================================================*
  2113. 33860 !*                              unlock                                       *
  2114. 33861 !*===========================================================================*
  2115. 33862 ! PUBLIC void unlock();
  2116. 33863 ! Enable CPU interrupts.
  2117. 33864
  2118. 33865         .align  16
  2119. 33866 _unlock:
  2120. 33867         sti
  2121. 33868         ret
  2122. 33869
  2123. 33870
  2124. 33871 !*==========================================================================*
  2125. 33872 !*                              enable_irq                                  *
  2126. 33873 !*==========================================================================*/
  2127. 33874 ! PUBLIC void enable_irq(unsigned irq)
  2128. 33875 ! Enable an interrupt request line by clearing an 8259 bit.
  2129. 33876 ! Equivalent code for irq < 8:
  2130. 33877 !       out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) & ~(1 << irq));
  2131. 33878
  2132. 33879         .align  16
  2133. 33880 _enable_irq:
  2134. 33881         mov     ecx, 4(esp)             ! irq
  2135. 33882         pushf
  2136. 33883         cli
  2137. 33884         movb    ah, ~1
  2138. 33885         rolb    ah, cl                  ! ah = ~(1 << (irq % 8))
  2139. 33886         cmpb    cl, 8
  2140. 33887         jae     enable_8                ! enable irq >= 8 at the slave 8259
  2141. 33888 enable_0:
  2142. 33889         inb     INT_CTLMASK
  2143. 33890         andb    al, ah
  2144. 33891         outb    INT_CTLMASK             ! clear bit at master 8259
  2145. 33892         popf
  2146. 33893         ret
  2147. 33894         .align  4
  2148. 33895 enable_8:
  2149. 33896         inb     INT2_CTLMASK
  2150. 33897         andb    al, ah
  2151. 33898         outb    INT2_CTLMASK            ! clear bit at slave 8259
  2152. 33899         popf
  2153. 33900         ret
  2154. 33901
  2155. 33902
  2156. 33903 !*==========================================================================*
  2157. 33904 !*                              disable_irq                                 *
  2158. 33905 !*==========================================================================*/
  2159. 33906 ! PUBLIC int disable_irq(unsigned irq)
  2160. 33907 ! Disable an interrupt request line by setting an 8259 bit.
  2161. 33908 ! Equivalent code for irq < 8:
  2162. 33909 !       out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) | (1 << irq));
  2163. 33910 ! Returns true iff the interrupt was not already disabled.
  2164. 33911
  2165. 33912         .align  16
  2166. 33913 _disable_irq:
  2167. 33914         mov     ecx, 4(esp)             ! irq
  2168. 33915         pushf
  2169. 33916         cli
  2170. 33917         movb    ah, 1
  2171. 33918         rolb    ah, cl                  ! ah = (1 << (irq % 8))
  2172. 33919         cmpb    cl, 8
  2173. 33920         jae     disable_8               ! disable irq >= 8 at the slave 8259
  2174. 33921 disable_0:
  2175. 33922         inb     INT_CTLMASK
  2176. 33923         testb   al, ah
  2177. 33924         jnz     dis_already             ! already disabled?
  2178. 33925         orb     al, ah
  2179. 33926         outb    INT_CTLMASK             ! set bit at master 8259
  2180. 33927         popf
  2181. 33928         mov     eax, 1                  ! disabled by this function
  2182. 33929         ret
  2183. 33930 disable_8:
  2184. 33931         inb     INT2_CTLMASK
  2185. 33932         testb   al, ah
  2186. 33933         jnz     dis_already             ! already disabled?
  2187. 33934         orb     al, ah
  2188. 33935         outb    INT2_CTLMASK            ! set bit at slave 8259
  2189. 33936         popf
  2190. 33937         mov     eax, 1                  ! disabled by this function
  2191. 33938         ret
  2192. 33939 dis_already:
  2193. 33940         popf
  2194. 33941         xor     eax, eax                ! already disabled
  2195. 33942         ret
  2196. 33943
  2197. 33944
  2198. 33945 !*===========================================================================*
  2199. 33946 !*                              phys_copy                                    *
  2200. 33947 !*===========================================================================*
  2201. 33948 ! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
  2202. 33949 !                       phys_bytes bytecount);
  2203. 33950 ! Copy a block of physical memory.
  2204. 33951
  2205. 33952 PC_ARGS =       4 + 4 + 4 + 4   ! 4 + 4 + 4
  2206. 33953 !               es edi esi eip   src dst len
  2207. 33954
  2208. 33955         .align  16
  2209. 33956 _phys_copy:
  2210. 33957         cld
  2211. 33958         push    esi
  2212. 33959         push    edi
  2213. 33960         push    es
  2214. 33961
  2215. 33962         mov     eax, FLAT_DS_SELECTOR
  2216. 33963         mov     es, ax
  2217. 33964
  2218. 33965         mov     esi, PC_ARGS(esp)
  2219. 33966         mov     edi, PC_ARGS+4(esp)
  2220. 33967         mov     eax, PC_ARGS+4+4(esp)
  2221. 33968
  2222. 33969         cmp     eax, 10                 ! avoid align overhead for small counts
  2223. 33970         jb      pc_small
  2224. 33971         mov     ecx, esi                ! align source, hope target is too
  2225. 33972         neg     ecx
  2226. 33973         and     ecx, 3                  ! count for alignment
  2227. 33974         sub     eax, ecx
  2228. 33975         rep
  2229. 33976    eseg movsb
  2230. 33977         mov     ecx, eax
  2231. 33978         shr     ecx, 2                  ! count of dwords
  2232. 33979         rep
  2233. 33980    eseg movs
  2234. 33981         and     eax, 3
  2235. 33982 pc_small:
  2236. 33983         xchg    ecx, eax                ! remainder
  2237. 33984         rep
  2238. 33985    eseg movsb
  2239. 33986
  2240. 33987         pop     es
  2241. 33988         pop     edi
  2242. 33989         pop     esi
  2243. 33990         ret
  2244. 33991
  2245. 33992
  2246. 33993 !*===========================================================================*
  2247. 33994 !*                              mem_rdw                                      *
  2248. 33995 !*===========================================================================*
  2249. 33996 ! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
  2250. 33997 ! Load and return word at far pointer segment:offset.
  2251. 33998
  2252. 33999         .align  16
  2253. 34000 _mem_rdw:
  2254. 34001         mov     cx, ds
  2255. 34002         mov     ds, 4(esp)              ! segment
  2256. 34003         mov     eax, 4+4(esp)           ! offset
  2257. 34004         movzx   eax, (eax)              ! word to return
  2258. 34005         mov     ds, cx
  2259. 34006         ret
  2260. 34007
  2261. 34008
  2262. 34009 !*===========================================================================*
  2263. 34010 !*                              reset                                        *
  2264. 34011 !*===========================================================================*
  2265. 34012 ! PUBLIC void reset();
  2266. 34013 ! Reset the system by loading IDT with offset 0 and interrupting.
  2267. 34014
  2268. 34015 _reset:
  2269. 34016         lidt    (idt_zero)
  2270. 34017         int     3               ! anything goes, the 386 will not like it
  2271. 34018 .sect .data
  2272. 34019 idt_zero:       .data4  0, 0
  2273. 34020 .sect .text
  2274. 34021
  2275. 34022
  2276. 34023 !*===========================================================================*
  2277. 34024 !*                              mem_vid_copy                                 *
  2278. 34025 !*===========================================================================*
  2279. 34026 ! PUBLIC void mem_vid_copy(u16 *src, unsigned dst, unsigned count);
  2280. 34027 !
  2281. 34028 ! Copy count characters from kernel memory to video memory.  Src, dst and
  2282. 34029 ! count are character (word) based video offsets and counts.  If src is null
  2283. 34030 ! then screen memory is blanked by filling it with blank_color.
  2284. 34031
  2285. 34032 MVC_ARGS        =       4 + 4 + 4 + 4   ! 4 + 4 + 4
  2286. 34033 !                       es edi esi eip   src dst ct
  2287. 34034
  2288. 34035 _mem_vid_copy:
  2289. 34036         push    esi
  2290. 34037         push    edi
  2291. 34038         push    es
  2292. 34039         mov     esi, MVC_ARGS(esp)      ! source
  2293. 34040         mov     edi, MVC_ARGS+4(esp)    ! destination
  2294. 34041         mov     edx, MVC_ARGS+4+4(esp)  ! count
  2295. 34042         mov     es, (_vid_seg)          ! destination is video segment
  2296. 34043         cld                             ! make sure direction is up
  2297. 34044 mvc_loop:
  2298. 34045         and     edi, (_vid_mask)        ! wrap address
  2299. 34046         mov     ecx, edx                ! one chunk to copy
  2300. 34047         mov     eax, (_vid_size)
  2301. 34048         sub     eax, edi
  2302. 34049         cmp     ecx, eax
  2303. 34050         jbe     0f
  2304. 34051         mov     ecx, eax                ! ecx = min(ecx, vid_size - edi)
  2305. 34052 0:      sub     edx, ecx                ! count -= ecx
  2306. 34053         shl     edi, 1                  ! byte address
  2307. 34054         test    esi, esi                ! source == 0 means blank the screen
  2308. 34055         jz      mvc_blank
  2309. 34056 mvc_copy:
  2310. 34057         rep                             ! copy words to video memory
  2311. 34058     o16 movs
  2312. 34059         jmp     mvc_test
  2313. 34060 mvc_blank:
  2314. 34061         mov     eax, (_blank_color)     ! ax = blanking character
  2315. 34062         rep
  2316. 34063     o16 stos                            ! copy blanks to video memory
  2317. 34064         !jmp    mvc_test
  2318. 34065 mvc_test:
  2319. 34066         shr     edi, 1                  ! word addresses
  2320. 34067         test    edx, edx
  2321. 34068         jnz     mvc_loop
  2322. 34069 mvc_done:
  2323. 34070         pop     es
  2324. 34071         pop     edi
  2325. 34072         pop     esi
  2326. 34073         ret
  2327. 34074
  2328. 34075
  2329. 34076 !*===========================================================================*
  2330. 34077 !*                              vid_vid_copy                                 *
  2331. 34078 !*===========================================================================*
  2332. 34079 ! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
  2333. 34080 !
  2334. 34081 ! Copy count characters from video memory to video memory.  Handle overlap.
  2335. 34082 ! Used for scrolling, line or character insertion and deletion.  Src, dst
  2336. 34083 ! and count are character (word) based video offsets and counts.
  2337. 34084
  2338. 34085 VVC_ARGS        =       4 + 4 + 4 + 4   ! 4 + 4 + 4
  2339. 34086 !                       es edi esi eip   src dst ct
  2340. 34087
  2341. 34088 _vid_vid_copy:
  2342. 34089         push    esi
  2343. 34090         push    edi
  2344. 34091         push    es
  2345. 34092         mov     esi, VVC_ARGS(esp)      ! source
  2346. 34093         mov     edi, VVC_ARGS+4(esp)    ! destination
  2347. 34094         mov     edx, VVC_ARGS+4+4(esp)  ! count
  2348. 34095         mov     es, (_vid_seg)          ! use video segment
  2349. 34096         cmp     esi, edi                ! copy up or down?
  2350. 34097         jb      vvc_down
  2351. 34098 vvc_up:
  2352. 34099         cld                             ! direction is up
  2353. 34100 vvc_uploop:
  2354. 34101         and     esi, (_vid_mask)        ! wrap addresses
  2355. 34102         and     edi, (_vid_mask)
  2356. 34103         mov     ecx, edx                ! one chunk to copy
  2357. 34104         mov     eax, (_vid_size)
  2358. 34105         sub     eax, esi
  2359. 34106         cmp     ecx, eax
  2360. 34107         jbe     0f
  2361. 34108         mov     ecx, eax                ! ecx = min(ecx, vid_size - esi)
  2362. 34109 0:      mov     eax, (_vid_size)
  2363. 34110         sub     eax, edi
  2364. 34111         cmp     ecx, eax
  2365. 34112         jbe     0f
  2366. 34113         mov     ecx, eax                ! ecx = min(ecx, vid_size - edi)
  2367. 34114 0:      sub     edx, ecx                ! count -= ecx
  2368. 34115         shl     esi, 1
  2369. 34116         shl     edi, 1                  ! byte addresses
  2370. 34117         rep
  2371. 34118 eseg o16 movs                           ! copy video words
  2372. 34119         shr     esi, 1
  2373. 34120         shr     edi, 1                  ! word addresses
  2374. 34121         test    edx, edx
  2375. 34122         jnz     vvc_uploop              ! again?
  2376. 34123         jmp     vvc_done
  2377. 34124 vvc_down:
  2378. 34125         std                             ! direction is down
  2379. 34126         lea     esi, -1(esi)(edx*1)     ! start copying at the top
  2380. 34127         lea     edi, -1(edi)(edx*1)
  2381. 34128 vvc_downloop:
  2382. 34129         and     esi, (_vid_mask)        ! wrap addresses
  2383. 34130         and     edi, (_vid_mask)
  2384. 34131         mov     ecx, edx                ! one chunk to copy
  2385. 34132         lea     eax, 1(esi)
  2386. 34133         cmp     ecx, eax
  2387. 34134         jbe     0f
  2388. 34135         mov     ecx, eax                ! ecx = min(ecx, esi + 1)
  2389. 34136 0:      lea     eax, 1(edi)
  2390. 34137         cmp     ecx, eax
  2391. 34138         jbe     0f
  2392. 34139         mov     ecx, eax                ! ecx = min(ecx, edi + 1)
  2393. 34140 0:      sub     edx, ecx                ! count -= ecx
  2394. 34141         shl     esi, 1
  2395. 34142         shl     edi, 1                  ! byte addresses
  2396. 34143         rep
  2397. 34144 eseg o16 movs                           ! copy video words
  2398. 34145         shr     esi, 1
  2399. 34146         shr     edi, 1                  ! word addresses
  2400. 34147         test    edx, edx
  2401. 34148         jnz     vvc_downloop            ! again?
  2402. 34149         cld                             ! C compiler expect up
  2403. 34150         !jmp    vvc_done
  2404. 34151 vvc_done:
  2405. 34152         pop     es
  2406. 34153         pop     edi
  2407. 34154         pop     esi
  2408. 34155         ret
  2409. 34156
  2410. 34157
  2411. 34158 !*===========================================================================*
  2412. 34159 !*                            level0                                         *
  2413. 34160 !*===========================================================================*
  2414. 34161 ! PUBLIC void level0(void (*func)(void))
  2415. 34162 ! Call a function at permission level 0.  This allows kernel tasks to do
  2416. 34163 ! things that are only possible at the most privileged CPU level.
  2417. 34164 !
  2418. 34165 _level0:
  2419. 34166         mov     eax, 4(esp)
  2420. 34167         mov     (_level0_func), eax
  2421. 34168         int     LEVEL0_VECTOR
  2422. 34169         ret
  2423. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2424. src/kernel/klib88.s    
  2425. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2426. 34200 #
  2427. 34201 #include <minix/config.h>
  2428. 34202 #include <minix/const.h>
  2429. 34203 #include "const.h"
  2430. 34204 #include "sconst.h"
  2431. 34205 #include "protect.h"
  2432. 34206
  2433. 34207 ! This file contains a number of assembly code utility routines needed by the
  2434. 34208 ! kernel.  They are:
  2435. 34209
  2436. 34210 .define _monitor        ! exit Minix and return to the monitor
  2437. 34211 .define real2prot       ! switch from real to protected mode
  2438. 34212 .define prot2real       ! switch from protected to real mode
  2439. 34213 .define _check_mem      ! check a block of memory, return the valid size
  2440. 34214 .define _cp_mess        ! copies messages from source to destination
  2441. 34215 .define _exit           ! dummy for library routines
  2442. 34216 .define __exit          ! dummy for library routines
  2443. 34217 .define ___exit         ! dummy for library routines
  2444. 34218 .define .fat, .trp      ! dummies for library routines
  2445. 34219 .define _in_byte        ! read a byte from a port and return it
  2446. 34220 .define _in_word        ! read a word from a port and return it
  2447. 34221 .define _out_byte       ! write a byte to a port
  2448. 34222 .define _out_word       ! write a word to a port
  2449. 34223 .define _port_read      ! transfer data from (disk controller) port to memory
  2450. 34224 .define _port_read_byte ! likewise byte by byte
  2451. 34225 .define _port_write     ! transfer data from memory to (disk controller) port
  2452. 34226 .define _port_write_byte ! likewise byte by byte
  2453. 34227 .define _lock           ! disable interrupts
  2454. 34228 .define _unlock         ! enable interrupts
  2455. 34229 .define _enable_irq     ! enable an irq at the 8259 controller
  2456. 34230 .define _disable_irq    ! disable an irq
  2457. 34231 .define _phys_copy      ! copy data from anywhere to anywhere in memory
  2458. 34232 .define _mem_rdw        ! copy one word from [segment:offset]
  2459. 34233 .define _reset          ! reset the system
  2460. 34234 .define _mem_vid_copy   ! copy data to video ram
  2461. 34235 .define _vid_vid_copy   ! move data in video ram
  2462. 34236 .define _level0         ! call a function at level 0
  2463. 34237 .define klib_init_prot  ! initialize klib functions for protected mode
  2464. 34238
  2465. 34239 ! The routines only guarantee to preserve the registers the C compiler
  2466. 34240 ! expects to be preserved (si, di, bp, sp, segment registers, and direction
  2467. 34241 ! bit in the flags), though some of the older ones preserve bx, cx and dx.
  2468. 34242
  2469. 34243 #define DS_286_OFFSET   DS_286_INDEX*DESC_SIZE
  2470. 34244 #define ES_286_OFFSET   ES_286_INDEX*DESC_SIZE
  2471. 34245 #       define EM_XFER_FUNC     0x87
  2472. 34246 #define JMP_OPCODE      0xE9    /* opcode used for patching */
  2473. 34247 #define OFF_MASK        0x000F  /* offset mask for phys_b -> hclick:offset */
  2474. 34248 #define HCHIGH_MASK     0x0F    /* h/w click mask for low byte of hi word */
  2475. 34249 #define HCLOW_MASK      0xF0    /* h/w click mask for low byte of low word */
  2476. 34250
  2477. 34251 ! Imported functions
  2478. 34252
  2479. 34253 .extern p_restart
  2480. 34254 .extern p_save
  2481. 34255 .extern _restart
  2482. 34256 .extern save
  2483. 34257
  2484. 34258 ! Exported variables
  2485. 34259
  2486. 34260 .extern kernel_cs
  2487. 34261
  2488. 34262 ! Imported variables
  2489. 34263
  2490. 34264 .extern kernel_ds
  2491. 34265 .extern _irq_use
  2492. 34266 .extern _blank_color
  2493. 34267 .extern _gdt
  2494. 34268 .extern _protected_mode
  2495. 34269 .extern _vid_seg
  2496. 34270 .extern _vid_size
  2497. 34271 .extern _vid_mask
  2498. 34272 .extern _level0_func
  2499. 34273
  2500. 34274         .text
  2501. 34275 !*===========================================================================*
  2502. 34276 !*                              monitor                                      *
  2503. 34277 !*===========================================================================*
  2504. 34278 ! PUBLIC void monitor();
  2505. 34279 ! Return to the monitor.
  2506. 34280
  2507. 34281 _monitor:
  2508. 34282         call    prot2real               ! switch to real mode
  2509. 34283         mov     ax, _reboot_code+0      ! address of new parameters
  2510. 34284         mov     dx, _reboot_code+2
  2511. 34285         mov     sp, _mon_sp             ! restore monitor stack pointer
  2512. 34286         mov     bx, _mon_ss             ! monitor data segment
  2513. 34287         mov     ds, bx
  2514. 34288         mov     es, bx
  2515. 34289         mov     ss, bx
  2516. 34290         pop     di
  2517. 34291         pop     si
  2518. 34292         pop     bp
  2519. 34293         retf                            ! return to the monitor
  2520. 34294
  2521. 34295
  2522. 34296 #if ENABLE_BIOS_WINI
  2523. 34297 !*===========================================================================*
  2524. 34298 !*                              bios13                                       *
  2525. 34299 !*===========================================================================*
  2526. 34300 ! PUBLIC void bios13();
  2527. 34301 .define _bios13
  2528. 34302 _bios13:                        ! make a BIOS 0x13 call for disk I/O
  2529. 34303         push    si
  2530. 34304         push    di              ! save C variable registers
  2531. 34305         pushf                   ! save flags
  2532. 34306
  2533. 34307         call    int13           ! make the actual call
  2534. 34308
  2535. 34309         popf                    ! restore flags
  2536. 34310         pop     di              ! restore C registers
  2537. 34311         pop     si
  2538. 34312         ret
  2539. 34313
  2540. 34314 ! Make a BIOS 0x13 call from protected mode
  2541. 34315 p_bios13:
  2542. 34316         push    bp
  2543. 34317         push    si
  2544. 34318         push    di                      ! save C variable registers
  2545. 34319         pushf                           ! save flags
  2546. 34320         cli                             ! no interruptions
  2547. 34321         inb     INT2_CTLMASK
  2548. 34322         movb    ah, al
  2549. 34323         inb     INT_CTLMASK
  2550. 34324         push    ax                      ! save interrupt masks
  2551. 34325         mov     ax, _irq_use            ! map of in-use IRQs
  2552. 34326         and     ax, #~[1<<CLOCK_IRQ]    ! there is a special clock handler
  2553. 34327         outb    INT_CTLMASK             ! enable all unused IRQs and vv.
  2554. 34328         movb    al, ah
  2555. 34329         outb    INT2_CTLMASK
  2556. 34330
  2557. 34331         smsw    ax
  2558. 34332         push    ax                      ! save machine status word
  2559. 34333         call    prot2real               ! switch to real mode
  2560. 34334
  2561. 34335         call    int13                   ! make the actual call
  2562. 34336
  2563. 34337         call    real2prot               ! back to protected mode
  2564. 34338         pop     ax
  2565. 34339         lmsw    ax                      ! restore msw
  2566. 34340
  2567. 34341         pop     ax                      ! restore interrupt masks
  2568. 34342         outb    INT_CTLMASK
  2569. 34343         movb    al, ah
  2570. 34344         outb    INT2_CTLMASK
  2571. 34345         popf                            ! restore flags
  2572. 34346         pop     di
  2573. 34347         pop     si
  2574. 34348         pop     bp                      ! restore C variable registers
  2575. 34349         ret
  2576. 34350
  2577. 34351 int13:
  2578. 34352         mov     ax, _Ax         ! load parameters
  2579. 34353         mov     bx, _Bx
  2580. 34354         mov     cx, _Cx
  2581. 34355         mov     dx, _Dx
  2582. 34356         mov     es, _Es
  2583. 34357         sti                     ! enable interrupts
  2584. 34358         int     0x13            ! make the BIOS call
  2585. 34359         cli                     ! disable interrupts
  2586. 34360         mov     _Ax, ax         ! save results
  2587. 34361         mov     _Bx, bx
  2588. 34362         mov     _Cx, cx
  2589. 34363         mov     _Dx, dx
  2590. 34364         mov     _Es, es
  2591. 34365         mov     ax, ds
  2592. 34366         mov     es, ax          ! restore es
  2593. 34367         ret
  2594. 34368
  2595. 34369 .bss
  2596. 34370 .define _Ax, _Bx, _Cx, _Dx, _Es         ! 8086 register variables
  2597. 34371 .comm   _Ax, 2
  2598. 34372 .comm   _Bx, 2
  2599. 34373 .comm   _Cx, 2
  2600. 34374 .comm   _Dx, 2
  2601. 34375 .comm   _Es, 2
  2602. 34376 .text
  2603. 34377 #endif /* ENABLE_BIOS_WINI */
  2604. 34378
  2605. 34379
  2606. 34380 !*===========================================================================*
  2607. 34381 !*                              real2prot                                    *
  2608. 34382 !*===========================================================================*
  2609. 34383 ! Switch from real to protected mode.
  2610. 34384 real2prot:
  2611. 34385         lgdt    _gdt+GDT_SELECTOR       ! set global descriptor table
  2612. 34386         smsw    ax
  2613. 34387         mov     msw, ax                 ! save real mode msw
  2614. 34388         orb     al, #0x01               ! set PE (protection enable) bit
  2615. 34389         lmsw    ax                      ! set msw, enabling protected mode
  2616. 34390
  2617. 34391         jmpf    csinit, CS_SELECTOR     ! set code segment selector
  2618. 34392 csinit:
  2619. 34393         mov     ax, #DS_SELECTOR        ! set data selectors
  2620. 34394         mov     ds, ax
  2621. 34395         mov     es, ax
  2622. 34396         mov     ss, ax
  2623. 34397         lidt    _gdt+IDT_SELECTOR       ! set interrupt vectors
  2624. 34398         andb    _gdt+TSS_SELECTOR+DESC_ACCESS, #~0x02  ! clear TSS busy bit
  2625. 34399         mov     ax, #TSS_SELECTOR
  2626. 34400         ltr     ax                      ! set TSS register
  2627. 34401
  2628. 34402         movb    ah, #0xDF
  2629. 34403         jmp     gate_A20                ! enable the A20 address line
  2630. 34404
  2631. 34405
  2632. 34406 !*===========================================================================*
  2633. 34407 !*                              prot2real                                    *
  2634. 34408 !*===========================================================================*
  2635. 34409 ! Switch from protected to real mode.
  2636. 34410 prot2real:
  2637. 34411         mov     save_sp, sp             ! save stack pointer
  2638. 34412         cmp     _processor, #386        ! is this a 386?
  2639. 34413         jae     p2r386
  2640. 34414 p2r286:
  2641. 34415         mov     _gdt+ES_286_OFFSET+DESC_BASE, #0x0400
  2642. 34416         movb    _gdt+ES_286_OFFSET+DESC_BASE_MIDDLE, #0x00
  2643. 34417         mov     ax, #ES_286_SELECTOR
  2644. 34418         mov     es, ax                  ! BIOS data segment
  2645. 34419   eseg  mov     0x0067, #real           ! set return from shutdown address
  2646. 34420   cseg  mov     ax, kernel_cs
  2647. 34421   eseg  mov     0x0069, ax
  2648. 34422         movb    al, #0x8F
  2649. 34423         outb    0x70                    ! select CMOS byte 0x0F (disable NMI)
  2650. 34424         jmp     .+2
  2651. 34425         movb    al, #0x0A
  2652. 34426         outb    0x71                    ! set shutdown code to 0x0A "jump far"
  2653. 34427         jmp     p_reset                 ! cause a processor shutdown
  2654. 34428 p2r386:
  2655. 34429         lidt    idt_vectors             ! real mode interrupt vectors
  2656. 34430         push    _gdt+CS_SELECTOR+0
  2657. 34431         push    _gdt+DS_SELECTOR+0      ! save CS and DS limits
  2658. 34432         mov     _gdt+CS_SELECTOR+0, #0xFFFF
  2659. 34433         mov     _gdt+DS_SELECTOR+0, #0xFFFF ! set 64k limits
  2660. 34434         jmpf    cs64k, CS_SELECTOR      ! reload selectors
  2661. 34435 cs64k:  mov     ax, #DS_SELECTOR
  2662. 34436         mov     ds, ax
  2663. 34437         mov     es, ax
  2664. 34438         mov     ss, ax
  2665. 34439         pop     _gdt+DS_SELECTOR+0
  2666. 34440         pop     _gdt+CS_SELECTOR+0      ! restore CS and DS limits
  2667. 34441         .data1  0x0F,0x20,0xC0          ! mov   eax, cr0
  2668. 34442         mov     ax, msw                 ! restore real mode (16 bits) msw
  2669. 34443         .data1  0x0F,0x22,0xC0          ! mov   cr0, eax
  2670. 34444         .data1  0xEA                    ! jmpf real, "kernel_cs"
  2671. 34445         .data2  real
  2672. 34446 kernel_cs:
  2673. 34447         .data2  0
  2674. 34448 real:
  2675. 34449   cseg  mov     ax, kernel_ds           ! reload data segment registers
  2676. 34450         mov     ds, ax
  2677. 34451         mov     es, ax
  2678. 34452         mov     ss, ax
  2679. 34453         mov     sp, save_sp             ! restore stack
  2680. 34454
  2681. 34455         movb    ah, #0xDD
  2682. 34456         !jmp    gate_A20                ! disable the A20 address line
  2683. 34457
  2684. 34458 ! Enable (ah = 0xDF) or disable (ah = 0xDD) the A20 address line.
  2685. 34459 gate_A20:
  2686. 34460         call    kb_wait
  2687. 34461         movb    al, #0xD1       ! Tell keyboard that a command is coming
  2688. 34462         outb    0x64
  2689. 34463         call    kb_wait
  2690. 34464         movb    al, ah          ! Enable or disable code
  2691. 34465         outb    0x60
  2692. 34466         call    kb_wait
  2693. 34467         mov     ax, #25         ! 25 microsec delay for slow keyboard chip
  2694. 34468 0:      out     0xED            ! Write to an unused port (1us)
  2695. 34469         dec     ax
  2696. 34470         jne     0b
  2697. 34471         ret
  2698. 34472 kb_wait:
  2699. 34473         inb     0x64
  2700. 34474         testb   al, #0x02       ! Keyboard input buffer full?
  2701. 34475         jnz     kb_wait         ! If so, wait
  2702. 34476         ret
  2703. 34477
  2704. 34478
  2705. 34479 !*===========================================================================*
  2706. 34480 !*                              check_mem                                    *
  2707. 34481 !*===========================================================================*
  2708. 34482 ! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
  2709. 34483 ! Check a block of memory, return the amount valid.
  2710. 34484 ! Only every 16th byte is checked.
  2711. 34485 ! This only works in protected mode.
  2712. 34486 ! An initial size of 0 means everything.
  2713. 34487 ! This really should do some alias checks.
  2714. 34488
  2715. 34489 PCM_DENSITY     =       256     ! resolution of check
  2716. 34490                                 ! the shift logic depends on this being 256
  2717. 34491 TEST1PATTERN    =       0x55    ! memory test pattern 1
  2718. 34492 TEST2PATTERN    =       0xAA    ! memory test pattern 2
  2719. 34493
  2720. 34494 _check_mem:
  2721. 34495         pop     bx
  2722. 34496         pop     _gdt+DS_286_OFFSET+DESC_BASE
  2723. 34497         pop     ax              ! pop base into base of source descriptor
  2724. 34498         movb    _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
  2725. 34499         pop     cx              ! byte count in dx:cx
  2726. 34500         pop     dx
  2727. 34501         sub     sp,#4+4
  2728. 34502         push    bx
  2729. 34503         push    ds
  2730. 34504
  2731. 34505         sub     ax,ax           ! prepare for early exit
  2732. 34506         test    dx,#0xFF00
  2733. 34507         jnz     cm_1exit        ! cannot handle bases above 16M
  2734. 34508         movb    cl,ch           ! divide size by 256 and discard high byte
  2735. 34509         movb    ch,dl
  2736. 34510         push    cx              ! save divided size
  2737. 34511         sub     bx,bx           ! test bytes at bases of segments
  2738. 34512 cm_loop:
  2739. 34513         mov     ax,#DS_286_SELECTOR
  2740. 34514         mov     ds,ax
  2741. 34515         movb    dl,#TEST1PATTERN
  2742. 34516         xchgb   dl,(bx)         ! write test pattern, remember original value
  2743. 34517         xchgb   dl,(bx)         ! restore original value, read test pattern
  2744. 34518         cmpb    dl,#TEST1PATTERN        ! must agree if good real memory
  2745. 34519         jnz     cm_exit         ! if different, memory is unusable
  2746. 34520         movb    dl,#TEST2PATTERN
  2747. 34521         xchgb   dl,(bx)
  2748. 34522         xchgb   dl,(bx)
  2749. 34523         cmpb    dl,#TEST2PATTERN
  2750. 34524         jnz     cm_exit
  2751. 34525                                 ! next segment, test for wraparound at 16M
  2752. 34526                                 ! assuming es == old ds
  2753. 34527   eseg  add     _gdt+DS_286_OFFSET+DESC_BASE,#PCM_DENSITY
  2754. 34528   eseg  adcb    _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,#0
  2755. 34529         loopnz  cm_loop
  2756. 34530
  2757. 34531 cm_exit:
  2758. 34532         pop     ax
  2759. 34533         sub     ax,cx           ! verified size in multiples of PCM_DENSITY
  2760. 34534 cm_1exit:
  2761. 34535         movb    dl,ah           ! convert to phys_bytes in dx:ax
  2762. 34536         subb    dh,dh
  2763. 34537         movb    ah,al
  2764. 34538         movb    al,dh
  2765. 34539         pop     ds
  2766. 34540         ret
  2767. 34541
  2768. 34542
  2769. 34543 !*===========================================================================*
  2770. 34544 !*                              cp_mess                                      *
  2771. 34545 !*===========================================================================*
  2772. 34546 ! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
  2773. 34547 !                     phys_clicks dst_clicks, vir_bytes dst_offset);
  2774. 34548 ! This routine makes a fast copy of a message from anywhere in the address
  2775. 34549 ! space to anywhere else.  It also copies the source address provided as a
  2776. 34550 ! parameter to the call into the first word of the destination message.
  2777. 34551 !
  2778. 34552 ! Note that the message size, "Msize" is in WORDS (not bytes) and must be set
  2779. 34553 ! correctly.  Changing the definition of message in the type file and not
  2780. 34554 ! changing it here will lead to total disaster.
  2781. 34555
  2782. 34556 _cp_mess:
  2783. 34557         cld
  2784. 34558         push es                 ! save es
  2785. 34559         push ds                 ! save ds
  2786. 34560         mov bx,sp               ! index off bx because machine cannot use sp
  2787. 34561         push si                 ! save si
  2788. 34562         push di                 ! save di
  2789. 34563
  2790. 34564         mov     ax,12(bx)       ! destination click
  2791. 34565 #if HCLICK_SHIFT > CLICK_SHIFT
  2792. 34566 #error /* Small click sizes are not supported (right shift will lose bits). */
  2793. 34567 #endif
  2794. 34568 #if HCLICK_SHIFT < CLICK_SHIFT
  2795. 34569         movb    cl,#CLICK_SHIFT-HCLICK_SHIFT
  2796. 34570         shl     ax,cl           ! destination segment
  2797. 34571 #endif
  2798. 34572         mov     es,ax
  2799. 34573         mov     di,14(bx)       ! offset of destination message
  2800. 34574
  2801. 34575 ! Be careful not to destroy ds before we are finished with the bx pointer.
  2802. 34576 ! We are using bx and not the more natural bp to save pushing bp.
  2803. 34577
  2804. 34578         mov     ax,6(bx)        ! process number of sender
  2805. 34579         mov     si,10(bx)       ! offset of source message
  2806. 34580         mov     bx,8(bx)        ! source click (finished with bx as a pointer)
  2807. 34581 #if HCLICK_SHIFT < CLICK_SHIFT