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

操作系统开发

开发平台:

C/C++

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