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

操作系统开发

开发平台:

C/C++

  1. 18751   message mess;
  2. 18752
  3. 18753   mess.DEVICE = device;
  4. 18754   mess.POSITION = offset << SECTOR_SHIFT;
  5. 18755   mess.COUNT = SECTOR_SIZE;
  6. 18756   mess.ADDRESS = (char *) tmp_buf;
  7. 18757   mess.PROC_NR = proc_number(proc_ptr);
  8. 18758   mess.m_type = DEV_READ;
  9. 18759
  10. 18760   if (do_rdwt(dp, &mess) != SECTOR_SIZE) {
  11. 18761         printf("%s: can't read partition tablen", (*dp->dr_name)());
  12. 18762         return 0;
  13. 18763   }
  14. 18764   if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) {
  15. 18765         /* Invalid partition table. */
  16. 18766         return 0;
  17. 18767   }
  18. 18768   memcpy(table, (tmp_buf + PART_TABLE_OFF), NR_PARTITIONS * sizeof(table[0]));
  19. 18769   return 1;
  20. 18770 }
  21. 18773 /*===========================================================================*
  22. 18774  *                              sort                                         *
  23. 18775  *===========================================================================*/
  24. 18776 PRIVATE void sort(table)
  25. 18777 struct part_entry *table;
  26. 18778 {
  27. 18779 /* Sort a partition table. */
  28. 18780   struct part_entry *pe, tmp;
  29. 18781   int n = NR_PARTITIONS;
  30. 18782
  31. 18783   do {
  32. 18784         for (pe = table; pe < table + NR_PARTITIONS-1; pe++) {
  33. 18785                 if (pe[0].sysind == NO_PART
  34. 18786                         || (pe[0].lowsec > pe[1].lowsec
  35. 18787                                         && pe[1].sysind != NO_PART)) {
  36. 18788                         tmp = pe[0]; pe[0] = pe[1]; pe[1] = tmp;
  37. 18789                 }
  38. 18790         }
  39. 18791   } while (--n > 0);
  40. 18792 }
  41. .Op 247 src/kernel/esdi_wini.c
  42. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  43. src/kernel/esdi_wini.c    
  44. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  45. 18800 /*     device dependent part of a hard disk driver for ibm ps/2 esdi adapter
  46. 18801  *
  47. 18802  *     written by doug burks, based on other minix wini drivers.
  48. 18803  *     some additions by art roberts
  49. 18804  *
  50. 18805  *     references:
  51. 18806  *        ibm personal system/2 hardware technical reference  (1988)
  52. 18807  *        ibm 60/120mb fixed disk drive technical reference  (1988)
  53. 18808  *
  54. 18809  *     caveats:
  55. 18810  *       * this driver has been reported to work on ibm ps/2 models 50 and
  56. 18811  *         70 with ibm's 60/120mb hard disks.
  57. 18812  *       * for a true esdi adapter, changes will have to be made, but this
  58. 18813  *         certainly serves as a good start.
  59. 18814  *       * no timeouts are implemented, so this driver could hang under
  60. 18815  *         adverse conditions.
  61. 18816  *       * the error processing has not been tested.  my disk works too well.
  62. 18817  *
  63. 18818  * The file contains one entry point:
  64. 18819  *
  65. 18820  *   esdi_winchester_task:      main entry when system is brought up
  66. 18821  *
  67. 18822  *
  68. 18823  * Changes:
  69. 18824  *       3 May 1992 by Kees J. Bot: device dependent/independent split.
  70. 18825  */
  71. 18826 #include "kernel.h"
  72. 18827 #include "driver.h"
  73. 18828 #include "drvlib.h"
  74. 18829
  75. 18830 #if ENABLE_ESDI_WINI
  76. 18831
  77. 18832 /* If the DMA buffer is large enough then use it always. */
  78. 18833 #define USE_BUF         (DMA_BUF_SIZE > BLOCK_SIZE)
  79. 18834
  80. 18835
  81. 18836 /*****  esdi i/o adapter ports  */
  82. 18837
  83. 18838 #define  CMD_REG   0x3510       /* command interface register            */
  84. 18839 #define  STAT_REG  0x3510       /* status interface register             */
  85. 18840 #define  BCTL_REG  0x3512       /* basic control register                */
  86. 18841 #define  BST_REG   0x3512       /* basic status register                 */
  87. 18842 #define  ATT_REG   0x3513       /* attention register                    */
  88. 18843 #define  INT_REG   0x3513       /* interrupt status register             */
  89. 18844
  90. 18845
  91. 18846 /*****  basic status register bits  */
  92. 18847
  93. 18848 #define  DMA_ENA   0x80         /* DMA enabled?                          */
  94. 18849 #define  INT_PND   0x40         /* interrupt pending?                    */
  95. 18850 #define  CMD_PRG   0x20         /* command in progress?                  */
  96. 18851 #define  BUSY      0x10         /* is adapter busy?                      */
  97. 18852 #define  STR_FUL   0x08         /* status interface register set?        */
  98. 18853 #define  CMD_FUL   0x04         /* command interface register full?      */
  99. 18854 #define  XFR_REQ   0x02         /* data transfer operation ready?        */
  100. .Ep 248 src/kernel/esdi_wini.c
  101. 18855 #define  INT_SET   0x01         /* adapter sending interrupt?            */
  102. 18856
  103. 18857
  104. 18858 /*****  attention register commands  */
  105. 18859
  106. 18860 #define  ATT_CMD   0x01         /* command request                       */
  107. 18861 #define  ATT_EOI   0x02         /* end of interrupt processing           */
  108. 18862 #define  ATT_ABT   0x03         /* abort the current command             */
  109. 18863 #define  ATT_RST   0xE4         /* reset the esdi adapter                */
  110. 18864
  111. 18865
  112. 18866 /*****  dma register addresses  */
  113. 18867
  114. 18868 #define  DMA_EXTCMD  0x18       /* extended function register            */
  115. 18869 #define  DMA_EXEC    0x1A       /* extended function execute             */
  116. 18870
  117. 18871
  118. 18872 /*****  miscellaneous  */
  119. 18873
  120. 18874 #define  ERR            (-1)    /* general error code                    */
  121. 18875 #define  ERR_BAD_SECTOR (-2)    /* block marked bad detected             */
  122. 18876 #define  MAX_ERRORS     4       /* maximum number of read/write retries  */
  123. 18877 #define  MAX_DRIVES     2       /* maximum number of physical drives     */
  124. 18878 #define  NR_DEVICES     (MAX_DRIVES*DEV_PER_DRIVE)
  125. 18879                                 /* Maximum number of logical devices     */
  126. 18880 #define  SUB_PER_DRIVE  (NR_PARTITIONS * NR_PARTITIONS)
  127. 18881 #define  NR_SUBDEVS     (MAX_DRIVES * SUB_PER_DRIVE)
  128. 18882
  129. 18883 #define  SYS_PORTA      0x92    /* system control port a                 */
  130. 18884 #define  LIGHT_ON       0xC0    /* fixed-disk activity light reg. mask   */
  131. 18885
  132. 18886
  133. 18887 /*****  variables  */
  134. 18888
  135. 18889 PRIVATE struct wini {           /* disk/partition information            */
  136. 18890   unsigned open_ct;                     /* in-use count                  */
  137. 18891   struct device part[DEV_PER_DRIVE];    /* primary partitions: hd[0-4]   */
  138. 18892   struct device subpart[SUB_PER_DRIVE]; /* subpartitions: hd[1-4][a-d] */
  139. 18893 } wini[MAX_DRIVES], *w_wn;
  140. 18894
  141. 18895 PRIVATE struct trans {
  142. 18896   struct iorequest_s *iop;      /* belongs to this I/O request           */
  143. 18897   unsigned long block;          /* first sector to transfer              */
  144. 18898   unsigned count;               /* byte count                            */
  145. 18899   phys_bytes phys;              /* user physical address                 */
  146. 18900   phys_bytes dma;               /* DMA physical address                  */
  147. 18901 } wtrans[NR_IOREQS];
  148. 18902
  149. 18903 PRIVATE int nr_drives;          /* actual number of physical disk drive  */
  150. 18904 PRIVATE int command[4];         /* controller command buffer             */
  151. 18905 PRIVATE unsigned int status_block[9];   /* status block output from a command */
  152. 18906 PRIVATE int dma_channel;        /* fixed disk dma channel number         */
  153. 18907 PRIVATE struct trans *w_tp;     /* to add transfer requests              */
  154. 18908 PRIVATE unsigned w_count;       /* number of bytes to transfer           */
  155. 18909 PRIVATE unsigned long w_nextblock;      /* next block on disk to transfer */
  156. 18910 PRIVATE int w_opcode;           /* DEV_READ or DEV_WRITE                 */
  157. 18911 PRIVATE int w_drive;            /* selected drive                        */
  158. 18912 PRIVATE int w_istat;            /* interrupt status of last command      */
  159. 18913 PRIVATE struct device *w_dv;    /* device's base and size                */
  160. 18914
  161. .Op 249 src/kernel/esdi_wini.c
  162. 18915
  163. 18916 /*****  functions  */
  164. 18917
  165. 18918 FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
  166. 18919 FORWARD _PROTOTYPE( char *w_name, (void) );
  167. 18920 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
  168. 18921 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
  169. 18922 FORWARD _PROTOTYPE( void w_init, (void) );
  170. 18923 FORWARD _PROTOTYPE( int w_command, (int device, int cmd, int num_words) );
  171. 18924 FORWARD _PROTOTYPE( int w_schedule, (int proc_nr, struct iorequest_s *iop) );
  172. 18925 FORWARD _PROTOTYPE( int w_finish, (void) );
  173. 18926 FORWARD _PROTOTYPE( int w_transfer, (struct trans *tp, unsigned count) );
  174. 18927 FORWARD _PROTOTYPE( int w_att_write, (int value) );
  175. 18928 FORWARD _PROTOTYPE( void w_interrupt, (int dma) );
  176. 18929 FORWARD _PROTOTYPE( int w_handler, (int irq) );
  177. 18930 FORWARD _PROTOTYPE( void w_dma_setup, (struct trans *tp, unsigned count) );
  178. 18931 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry));
  179. 18932
  180. 18933
  181. 18934 /* Entry points to this driver. */
  182. 18935 PRIVATE struct driver w_dtab = {
  183. 18936   w_name,       /* current device's name */
  184. 18937   w_do_open,    /* open or mount request, initialize device */
  185. 18938   w_do_close,   /* release device */
  186. 18939   do_diocntl,   /* get or set a partition's geometry */
  187. 18940   w_prepare,    /* prepare for I/O on a given minor device */
  188. 18941   w_schedule,   /* precompute cylinder, head, sector, etc. */
  189. 18942   w_finish,     /* do the I/O */
  190. 18943   nop_cleanup,  /* no cleanup needed */
  191. 18944   w_geometry    /* tell the geometry of the disk */
  192. 18945 };
  193. 18946
  194. 18947
  195. 18948 /*===========================================================================*
  196. 18949  *                              esdi_winchester_task                         *
  197. 18950  *===========================================================================*/
  198. 18951 PUBLIC void esdi_winchester_task()
  199. 18952 {
  200. 18953   driver_task(&w_dtab);
  201. 18954 }
  202. 18957 /*===========================================================================*
  203. 18958  *                              w_prepare                                    *
  204. 18959  *===========================================================================*/
  205. 18960 PRIVATE struct device *w_prepare(device)
  206. 18961 int device;
  207. 18962 {
  208. 18963 /* Prepare for I/O on a device. */
  209. 18964
  210. 18965   /* Nothing to transfer as yet. */
  211. 18966   w_count = 0;
  212. 18967
  213. 18968   if (device < NR_DEVICES) {                    /* hd0, hd1, ... */
  214. 18969         w_drive = device / DEV_PER_DRIVE;       /* save drive number */
  215. 18970         w_wn = &wini[w_drive];
  216. 18971         w_dv = &w_wn->part[device % DEV_PER_DRIVE];
  217. 18972   } else
  218. 18973   if ((unsigned) (device -= MINOR_hd1a) < NR_SUBDEVS) { /* hd1a, hd1b, ... */
  219. 18974         w_drive = device / SUB_PER_DRIVE;
  220. .Ep 250 src/kernel/esdi_wini.c
  221. 18975         w_wn = &wini[w_drive];
  222. 18976         w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
  223. 18977   } else {
  224. 18978         return(NIL_DEV);
  225. 18979   }
  226. 18980   return(w_drive < nr_drives ? w_dv : NIL_DEV);
  227. 18981 }
  228. 18984 /*===========================================================================*
  229. 18985  *                              w_name                                       *
  230. 18986  *===========================================================================*/
  231. 18987 PRIVATE char *w_name()
  232. 18988 {
  233. 18989 /* Return a name for the current device. */
  234. 18990   static char name[] = "esdi-hd5";
  235. 18991
  236. 18992   name[7] = '0' + w_drive * DEV_PER_DRIVE;
  237. 18993   return name;
  238. 18994 }
  239. 18997 /*============================================================================*
  240. 18998  *                              w_do_open                                     *
  241. 18999  *============================================================================*/
  242. 19000 PRIVATE int w_do_open(dp, m_ptr)
  243. 19001 struct driver *dp;
  244. 19002 message *m_ptr;
  245. 19003 {
  246. 19004 /* Device open: Initialize the controller and read the partition table. */
  247. 19005
  248. 19006   static int init_done = FALSE;
  249. 19007
  250. 19008   if (!init_done) { w_init(); init_done = TRUE; }
  251. 19009
  252. 19010   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  253. 19011
  254. 19012   if (w_wn->open_ct++ == 0) {
  255. 19013         /* partition the disk */
  256. 19014         partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY);
  257. 19015   }
  258. 19016   return(OK);
  259. 19017 }
  260. 19020 /*============================================================================*
  261. 19021  *                              w_do_close                                    *
  262. 19022  *============================================================================*/
  263. 19023 PRIVATE int w_do_close(dp, m_ptr)
  264. 19024 struct driver *dp;
  265. 19025 message *m_ptr;
  266. 19026 {
  267. 19027 /* Device close: Release a device. */
  268. 19028
  269. 19029   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  270. 19030   w_wn->open_ct--;
  271. 19031   return(OK);
  272. 19032 }
  273. .Op 251 src/kernel/esdi_wini.c
  274. 19035 /*============================================================================*
  275. 19036  *                              w_init                                        *
  276. 19037  *============================================================================*/
  277. 19038 PRIVATE void w_init()
  278. 19039 {
  279. 19040 /*     initializes everything needed to run the hard disk
  280. 19041  *
  281. 19042  *     the following items are initialized:
  282. 19043  *       -- hard disk attributes stored in bios
  283. 19044  *       -- dma transfer channel, read from system register
  284. 19045  *       -- dma transfer and interrupts [disabled]
  285. 19046  *
  286. 19047  *     the hard disk adapter is initialized when the ibm ps/2 is turned on,
  287. 19048  *     using the programmable option select registers.  thus the only
  288. 19049  *     additional initialization is making sure the dma transfer and interrupts
  289. 19050  *     are disabled.  other initialization problems could be checked for, such
  290. 19051  *     as an operation underway.  the paranoid could add a check for adapter
  291. 19052  *     activity and abort the operations.  the truly paranoid can reset the
  292. 19053  *     adapter.  until such worries are proven, why bother?
  293. 19054  */
  294. 19055   unsigned int drive;           /* hard disk drive number                */
  295. 19056   unsigned long size;           /* hard disk size                        */
  296. 19057
  297. 19058   /* get the number of drives from the bios */
  298. 19059   phys_copy(0x475L, tmp_phys, 1L);
  299. 19060   nr_drives = tmp_buf[0];
  300. 19061   if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
  301. 19062
  302. 19063   put_irq_handler(AT_WINI_IRQ, w_handler);
  303. 19064   enable_irq(AT_WINI_IRQ);      /* ready for winchester interrupts */
  304. 19065
  305. 19066   for (drive = 0; drive < nr_drives; ++drive) {
  306. 19067         (void) w_prepare(drive * DEV_PER_DRIVE);
  307. 19068         if (w_command(drive, 0x0609, 6) != OK) {
  308. 19069                 printf("%s: unable to get parametersn", w_name());
  309. 19070                 nr_drives = drive;
  310. 19071                 break;
  311. 19072         }
  312. 19073         /* size of the drive */
  313. 19074         size =  ((unsigned long) status_block[2] <<  0) |
  314. 19075                 ((unsigned long) status_block[3] << 16);
  315. 19076         if (drive == 0) {
  316. 19077                 if (w_command(7, 0x060A, 5) != OK) {
  317. 19078                         printf("%s: unable to get dma channeln", w_name());
  318. 19079                         nr_drives = 0;
  319. 19080                         return;
  320. 19081                 }
  321. 19082                 dma_channel = (status_block[2] & 0x3C00) >> 10;
  322. 19083         }
  323. 19084         printf("%s: %lu sectorsn", w_name(), size);
  324. 19085         w_wn->part[0].dv_size = size << SECTOR_SHIFT;
  325. 19086   }
  326. 19087 }
  327. 19090 /*===========================================================================*
  328. 19091  *                          w_command                                        *
  329. 19092  *===========================================================================*/
  330. 19093 PRIVATE int w_command(device, cmd, num_words)
  331. 19094 int device;                     /* i device to operate on                */
  332. .Ep 252 src/kernel/esdi_wini.c
  333. 19095                                 /*   1-2   physical disk drive number    */
  334. 19096                                 /*   7     hard disk controller          */
  335. 19097 int cmd;                        /* i command to execute                  */
  336. 19098 int num_words;                  /* i expected size of status block       */
  337. 19099 {
  338. 19100 /*     executes a command for a particular device
  339. 19101  *
  340. 19102  *     the operation is conducted as follows:
  341. 19103  *       -- create the command block
  342. 19104  *       -- initialize for command reading by the controller
  343. 19105  *       -- write the command block to the controller, making sure the
  344. 19106  *          controller has digested the previous command word, before shoving
  345. 19107  *          the next down its throat
  346. 19108  *       -- wait for an interrupt
  347. 19109  *       -- read expected number of words of command status information
  348. 19110  *       -- return the command status block
  349. 19111  *
  350. 19112  *     reading and writing registers is accompanied by enabling and disabling
  351. 19113  *     interrupts to ensure that the status register contents still apply when
  352. 19114  *     the desired register is read/written.
  353. 19115  */
  354. 19116   register int ki;              /* -- scratch --                         */
  355. 19117   int status;                   /* disk adapter status register value    */
  356. 19118
  357. 19119   device <<= 5;                 /* adjust device for our use             */
  358. 19120   command[0] = cmd | device;    /* build command block                   */
  359. 19121   command[1] = 0;
  360. 19122
  361. 19123   w_att_write(device | ATT_CMD);
  362. 19124
  363. 19125   for (ki = 0; ki < 2; ++ki) {
  364. 19126         out_word(CMD_REG, command[ki]);
  365. 19127         unlock();
  366. 19128         while (TRUE) {
  367. 19129                 lock();
  368. 19130                 status = in_byte(BST_REG);
  369. 19131                 if (!(status & CMD_FUL)) break;
  370. 19132                 unlock();
  371. 19133         }
  372. 19134   }
  373. 19135   unlock();
  374. 19136
  375. 19137   w_interrupt(0);
  376. 19138   if (w_istat != (device | 0x01)) {
  377. 19139         w_att_write(device | ATT_ABT);
  378. 19140         w_interrupt(0);
  379. 19141         return(ERR);
  380. 19142   }
  381. 19143   for (ki = 0; ki < num_words; ++ki) {
  382. 19144         while (TRUE) {
  383. 19145                 lock();
  384. 19146                 status = in_byte(BST_REG);
  385. 19147                 if (status & STR_FUL) break;
  386. 19148                 unlock();
  387. 19149         }
  388. 19150         status_block[ki] = in_word(STAT_REG);
  389. 19151         unlock();
  390. 19152   }
  391. 19153   w_att_write(device | ATT_EOI);
  392. 19154
  393. .Op 253 src/kernel/esdi_wini.c
  394. 19155   return(OK);
  395. 19156 }
  396. 19159 /*===========================================================================*
  397. 19160  *                              w_schedule                                   *
  398. 19161  *===========================================================================*/
  399. 19162 PRIVATE int w_schedule(proc_nr, iop)
  400. 19163 int proc_nr;                    /* process doing the request */
  401. 19164 struct iorequest_s *iop;        /* pointer to read or write request */
  402. 19165 {
  403. 19166 /* Gather I/O requests on consecutive blocks so they may be read/written
  404. 19167  * in one command if using a buffer.  Check and gather all the requests
  405. 19168  * and try to finish them as fast as possible if unbuffered.
  406. 19169  */
  407. 19170   int r, opcode;
  408. 19171   unsigned long pos;
  409. 19172   unsigned nbytes, count;
  410. 19173   unsigned long block;
  411. 19174   phys_bytes user_phys, dma_phys;
  412. 19175
  413. 19176   /* This many bytes to read/write */
  414. 19177   nbytes = iop->io_nbytes;
  415. 19178   if ((nbytes & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  416. 19179
  417. 19180   /* From/to this position on the device */
  418. 19181   pos = iop->io_position;
  419. 19182   if ((pos & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  420. 19183
  421. 19184   /* To/from this user address */
  422. 19185   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
  423. 19186   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  424. 19187
  425. 19188   /* Read or write? */
  426. 19189   opcode = iop->io_request & ~OPTIONAL_IO;
  427. 19190
  428. 19191   /* Which block on disk and how close to EOF? */
  429. 19192   if (pos >= w_dv->dv_size) return(OK);         /* At EOF */
  430. 19193   if (pos + nbytes > w_dv->dv_size) nbytes = w_dv->dv_size - pos;
  431. 19194   block = (w_dv->dv_base + pos) >> SECTOR_SHIFT;
  432. 19195
  433. 19196   if (USE_BUF && w_count > 0 && block != w_nextblock) {
  434. 19197         /* This new request can't be chained to the job being built */
  435. 19198         if ((r = w_finish()) != OK) return(r);
  436. 19199   }
  437. 19200
  438. 19201   /* The next consecutive block */
  439. 19202   if (USE_BUF) w_nextblock = block + (nbytes >> SECTOR_SHIFT);
  440. 19203
  441. 19204   /* While there are "unscheduled" bytes in the request: */
  442. 19205   do {
  443. 19206         count = nbytes;
  444. 19207
  445. 19208         if (USE_BUF) {
  446. 19209                 if (w_count == DMA_BUF_SIZE) {
  447. 19210                         /* Can't transfer more than the buffer allows. */
  448. 19211                         if ((r = w_finish()) != OK) return(r);
  449. 19212                 }
  450. 19213
  451. 19214                 if (w_count + count > DMA_BUF_SIZE)
  452. .Ep 254 src/kernel/esdi_wini.c
  453. 19215                         count = DMA_BUF_SIZE - w_count;
  454. 19216         } else {
  455. 19217                 if (w_tp == wtrans + NR_IOREQS) {
  456. 19218                         /* All transfer slots in use. */
  457. 19219                         if ((r = w_finish()) != OK) return(r);
  458. 19220                 }
  459. 19221         }
  460. 19222
  461. 19223         if (w_count == 0) {
  462. 19224                 /* The first request in a row, initialize. */
  463. 19225                 w_opcode = opcode;
  464. 19226                 w_tp = wtrans;
  465. 19227         }
  466. 19228
  467. 19229         if (USE_BUF) {
  468. 19230                 dma_phys = tmp_phys + w_count;
  469. 19231         } else {
  470. 19232                 /* Note: No 64K boundary problem, the better PS/2's have a
  471. 19233                  * working DMA chip.
  472. 19234                  */
  473. 19235                 dma_phys = user_phys;
  474. 19236         }
  475. 19237
  476. 19238         /* Store I/O parameters */
  477. 19239         w_tp->iop = iop;
  478. 19240         w_tp->block = block;
  479. 19241         w_tp->count = count;
  480. 19242         w_tp->phys = user_phys;
  481. 19243         w_tp->dma = dma_phys;
  482. 19244
  483. 19245         /* Update counters */
  484. 19246         w_tp++;
  485. 19247         w_count += count;
  486. 19248         block += count >> SECTOR_SHIFT;
  487. 19249         user_phys += count;
  488. 19250         nbytes -= count;
  489. 19251   } while (nbytes > 0);
  490. 19252
  491. 19253   return(OK);
  492. 19254 }
  493. 19257 /*===========================================================================*
  494. 19258  *                              w_finish                                     *
  495. 19259  *===========================================================================*/
  496. 19260 PRIVATE int w_finish()
  497. 19261 {
  498. 19262 /*     carries out the I/O requests gathered in wtrans[]
  499. 19263  *
  500. 19264  *     fills the disk information structure for one block at a time or many
  501. 19265  *     in a row before calling 'w_transfer' to do the dirty work.  while
  502. 19266  *     unsuccessful operations are re-tried, this may be superfluous, since
  503. 19267  *     the controller does the same on its own.  turns on the fixed disk
  504. 19268  *     activity light, while busy.  computers need blinking lights, right?
  505. 19269  */
  506. 19270
  507. 19271   struct trans *tp = wtrans, *tp2;
  508. 19272   unsigned count;
  509. 19273   int r, errors = 0, many = USE_BUF;
  510. 19274
  511. .Op 255 src/kernel/esdi_wini.c
  512. 19275   if (w_count == 0) return(OK); /* Spurious finish. */
  513. 19276
  514. 19277   do {
  515. 19278         if (w_opcode == DEV_WRITE) {
  516. 19279                 tp2 = tp;
  517. 19280                 count = 0;
  518. 19281                 do {
  519. 19282                         if (USE_BUF || tp2->dma == tmp_phys) {
  520. 19283                                 phys_copy(tp2->phys, tp2->dma,
  521. 19284                                                 (phys_bytes) tp2->count);
  522. 19285                         }
  523. 19286                         count += tp2->count;
  524. 19287                         tp2++;
  525. 19288                 } while (many && count < w_count);
  526. 19289         } else {
  527. 19290                 count = many ? w_count : tp->count;
  528. 19291         }
  529. 19292
  530. 19293         /* Turn on the disk activity light. */
  531. 19294         out_byte(SYS_PORTA, in_byte(SYS_PORTA) | LIGHT_ON);
  532. 19295
  533. 19296         /* Perform the transfer. */
  534. 19297         r = w_transfer(tp, count);
  535. 19298
  536. 19299         /* Turn off the disk activity light. */
  537. 19300         out_byte(SYS_PORTA, in_byte(SYS_PORTA) & ~LIGHT_ON);
  538. 19301
  539. 19302         if (r != OK) {
  540. 19303                 /* An error occurred, try again block by block unless */
  541. 19304                 if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS)
  542. 19305                         return(tp->iop->io_nbytes = EIO);
  543. 19306
  544. 19307                 many = 0;
  545. 19308                 continue;
  546. 19309         }
  547. 19310         errors = 0;
  548. 19311
  549. 19312         w_count -= count;
  550. 19313
  551. 19314         do {
  552. 19315                 if (w_opcode == DEV_READ) {
  553. 19316                         if (USE_BUF || tp->dma == tmp_phys) {
  554. 19317                                 phys_copy(tp->dma, tp->phys,
  555. 19318                                                 (phys_bytes) tp->count);
  556. 19319                         }
  557. 19320                 }
  558. 19321                 tp->iop->io_nbytes -= tp->count;
  559. 19322                 count -= tp->count;
  560. 19323                 tp++;
  561. 19324         } while (count > 0);
  562. 19325   } while (w_count > 0);
  563. 19326
  564. 19327   return(OK);
  565. 19328 }
  566. 19331 /*===========================================================================*
  567. 19332  *                              w_transfer                                   *
  568. 19333  *===========================================================================*/
  569. 19334 PRIVATE int w_transfer(tp, count)
  570. .Ep 256 src/kernel/esdi_wini.c
  571. 19335 struct trans *tp;               /* pointer to the transfer struct */
  572. 19336 unsigned int count;             /* bytes to transfer */
  573. 19337 {
  574. 19338 /*     reads/writes a single block of data from/to the hard disk
  575. 19339  *
  576. 19340  *     the read/write operation performs the following steps:
  577. 19341  *       -- create the command block
  578. 19342  *       -- initialize the command reading by the controller
  579. 19343  *       -- write the command block to the controller, making sure the
  580. 19344  *            controller has digested the previous command word, before
  581. 19345  *            shoving the next down its throat.
  582. 19346  *       -- wait for an interrupt, which must return a 'data transfer ready'
  583. 19347  *            status.  abort the command if it doesn't.
  584. 19348  *       -- set up and start up the direct memory transfer
  585. 19349  *       -- wait for an interrupt, signalling the end of the transfer
  586. 19350  */
  587. 19351   int device;                   /* device mask for the command register  */
  588. 19352   int ki;                       /* -- scratch --                         */
  589. 19353   int status;                   /* basic status register value           */
  590. 19354
  591. 19355   device = w_drive << 5;
  592. 19356   command[0] = (w_opcode == DEV_WRITE ? 0x4602 : 0x4601) | device;
  593. 19357   command[1] = count >> SECTOR_SHIFT;
  594. 19358   command[2] = (int) (tp->block & 0xFFFF);
  595. 19359   command[3] = (int) (tp->block >> 16);
  596. 19360
  597. 19361   w_att_write(device | ATT_CMD);
  598. 19362
  599. 19363   for (ki = 0; ki < 4; ++ki) {
  600. 19364         out_word(CMD_REG, command[ki]);
  601. 19365         unlock();
  602. 19366         while (TRUE) {
  603. 19367                 lock();
  604. 19368                 status = in_byte(BST_REG);
  605. 19369                 if (!(status & CMD_FUL)) break;
  606. 19370                 unlock();
  607. 19371         }
  608. 19372   }
  609. 19373   unlock();
  610. 19374
  611. 19375   w_interrupt(0);
  612. 19376   if (w_istat != (device | 0x0B)) {
  613. 19377         w_att_write(device | ATT_ABT);
  614. 19378         w_interrupt(0);
  615. 19379         return(ERR);
  616. 19380   }
  617. 19381   w_dma_setup(tp, count);
  618. 19382
  619. 19383   w_interrupt(1);
  620. 19384
  621. 19385   w_att_write(device | ATT_EOI);
  622. 19386
  623. 19387   if ((w_istat & 0x0F) > 8) return(ERR);
  624. 19388   return(OK);
  625. 19389 }
  626. 19393 /*==========================================================================*
  627. 19394  *                            w_att_write                                   *
  628. .Op 257 src/kernel/esdi_wini.c
  629. 19395  *==========================================================================*/
  630. 19396 PRIVATE int w_att_write(value)
  631. 19397 register int value;
  632. 19398 {
  633. 19399 /*     writes a command to the esdi attention register
  634. 19400  *
  635. 19401  *     waits for the controller to finish its business before sending the
  636. 19402  *     command to the controller.  note that the interrupts must be off to read
  637. 19403  *     the basic status register and, if the controller is ready, must not be
  638. 19404  *     turned back on until the attention register command is sent.
  639. 19405  */
  640. 19406   int status;                   /* basic status register value           */
  641. 19407
  642. 19408   while (TRUE) {
  643. 19409         lock();
  644. 19410         status = in_byte(BST_REG);
  645. 19411         if (!(status & (INT_PND | BUSY))) break;
  646. 19412         unlock();
  647. 19413   }
  648. 19414   out_byte(ATT_REG, value);
  649. 19415   unlock();
  650. 19416
  651. 19417   return(OK);
  652. 19418 }
  653. 19422 /*===========================================================================*
  654. 19423  *                          w_interrupt                                      *
  655. 19424  *===========================================================================*/
  656. 19425 PRIVATE void w_interrupt(dma)
  657. 19426 int dma;                        /* i dma transfer is underway            */
  658. 19427 {
  659. 19428 /*     waits for an interrupt from the hard disk controller
  660. 19429  *
  661. 19430  *     enable interrupts on the hard disk and interrupt controllers (and dma if
  662. 19431  *     necessary).  wait for an interrupt.  when received, return the interrupt
  663. 19432  *     status register value.
  664. 19433  *
  665. 19434  *     an interrupt can be detected either from the basic status register or
  666. 19435  *     through a system interrupt handler.  the handler is used for all
  667. 19436  *     interrupts, due to the expected long times to process reads and writes
  668. 19437  *     and to avoid busy waits.
  669. 19438  */
  670. 19439   message dummy;                /* -- scratch --                         */
  671. 19440
  672. 19441   out_byte(BCTL_REG, dma ? 0x03 : 0x01);
  673. 19442
  674. 19443   receive(HARDWARE, &dummy);
  675. 19444
  676. 19445   out_byte(BCTL_REG, 0);
  677. 19446   if (dma) out_byte(DMA_EXTCMD, 0x90 + dma_channel);
  678. 19447 }
  679. 19451 /*==========================================================================*
  680. 19452  *                              w_handler                                   *
  681. 19453  *==========================================================================*/
  682. 19454 PRIVATE int w_handler(irq)
  683. .Ep 258 src/kernel/esdi_wini.c
  684. 19455 int irq;
  685. 19456 {
  686. 19457 /* Disk interrupt, send message to winchester task and reenable interrupts. */
  687. 19458
  688. 19459   w_istat = in_byte(INT_REG);
  689. 19460   interrupt(WINCHESTER);
  690. 19461   return 1;
  691. 19462 }
  692. 19466 /*==========================================================================*
  693. 19467  *                      w_dma_setup                                         *
  694. 19468  *==========================================================================*/
  695. 19469 PRIVATE void w_dma_setup(tp, count)
  696. 19470 struct trans *tp;
  697. 19471 unsigned int count;
  698. 19472 {
  699. 19473 /*     programs the dma controller to move data to and from the hard disk.
  700. 19474  *
  701. 19475  *     uses the extended mode operation of the ibm ps/2 interrupt controller
  702. 19476  *     chip, rather than the intel 8237 (pc/at) compatible mode.
  703. 19477  */
  704. 19478
  705. 19479   lock();
  706. 19480   out_byte(DMA_EXTCMD, 0x90 + dma_channel);
  707. 19481   /* Disable access to dma channel 5     */
  708. 19482   out_byte(DMA_EXTCMD, 0x20 + dma_channel);
  709. 19483   /* Clear the address byte pointer      */
  710. 19484   out_byte(DMA_EXEC, (int)  tp->dma >>  0);     /* address bits 0..7   */
  711. 19485   out_byte(DMA_EXEC, (int)  tp->dma >>  8);     /* address bits 8..15  */
  712. 19486   out_byte(DMA_EXEC, (int) (tp->dma >> 16));    /* address bits 16..19 */
  713. 19487   out_byte(DMA_EXTCMD, 0x40 + dma_channel);
  714. 19488   /* Clear the count byte pointer        */
  715. 19489   out_byte(DMA_EXEC, (count - 1) >> 0);         /* count bits 0..7     */
  716. 19490   out_byte(DMA_EXEC, (count - 1) >> 8);         /* count bits 8..15    */
  717. 19491   out_byte(DMA_EXTCMD, 0x70 + dma_channel);
  718. 19492   /* Set the transfer mode               */
  719. 19493   out_byte(DMA_EXEC, w_opcode == DEV_WRITE ? 0x44 : 0x4C);
  720. 19494   out_byte(DMA_EXTCMD, 0xA0 + dma_channel);
  721. 19495   /* Enable access to dma channel 5      */
  722. 19496   unlock();
  723. 19497 }
  724. 19500 /*============================================================================*
  725. 19501  *                              w_geometry                                    *
  726. 19502  *============================================================================*/
  727. 19503 PRIVATE void w_geometry(entry)
  728. 19504 struct partition *entry;
  729. 19505 {
  730. 19506   entry->cylinders = (w_wn->part[0].dv_size >> SECTOR_SHIFT) / (64 * 32);
  731. 19507   entry->heads = 64;
  732. 19508   entry->sectors = 32;
  733. 19509 }
  734. 19510 #endif /* ENABLE_ESDI_WINI */
  735. .Op 259 src/kernel/exception.c
  736. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  737. src/kernel/exception.c    
  738. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  739. 19600 /* This file contains a simple exception handler.  Exceptions in user
  740. 19601  * processes are converted to signals.  Exceptions in the kernel, MM and
  741. 19602  * FS cause a panic.
  742. 19603  */
  743. 19604
  744. 19605 #include "kernel.h"
  745. 19606 #include <signal.h>
  746. 19607 #include "proc.h"
  747. 19608
  748. 19609 /*==========================================================================*
  749. 19610  *                              exception                                   *
  750. 19611  *==========================================================================*/
  751. 19612 PUBLIC void exception(vec_nr)
  752. 19613 unsigned vec_nr;
  753. 19614 {
  754. 19615 /* An exception or unexpected interrupt has occurred. */
  755. 19616
  756. 19617   struct ex_s {
  757. 19618         char *msg;
  758. 19619         int signum;
  759. 19620         int minprocessor;
  760. 19621   };
  761. 19622   static struct ex_s ex_data[] = {
  762. 19623         "Divide error", SIGFPE, 86,
  763. 19624         "Debug exception", SIGTRAP, 86,
  764. 19625         "Nonmaskable interrupt", SIGBUS, 86,
  765. 19626         "Breakpoint", SIGEMT, 86,
  766. 19627         "Overflow", SIGFPE, 86,
  767. 19628         "Bounds check", SIGFPE, 186,
  768. 19629         "Invalid opcode", SIGILL, 186,
  769. 19630         "Coprocessor not available", SIGFPE, 186,
  770. 19631         "Double fault", SIGBUS, 286,
  771. 19632         "Copressor segment overrun", SIGSEGV, 286,
  772. 19633         "Invalid TSS", SIGSEGV, 286,
  773. 19634         "Segment not present", SIGSEGV, 286,
  774. 19635         "Stack exception", SIGSEGV, 286,        /* STACK_FAULT already used */
  775. 19636         "General protection", SIGSEGV, 286,
  776. 19637         "Page fault", SIGSEGV, 386,             /* not close */
  777. 19638         NIL_PTR, SIGILL, 0,                     /* probably software trap */
  778. 19639         "Coprocessor error", SIGFPE, 386,
  779. 19640   };
  780. 19641   register struct ex_s *ep;
  781. 19642   struct proc *saved_proc;
  782. 19643
  783. 19644   saved_proc= proc_ptr; /* Save proc_ptr, because it may be changed by debug 
  784. 19645                          * statements.
  785. 19646                          */
  786. 19647
  787. 19648   ep = &ex_data[vec_nr];
  788. 19649
  789. 19650   if (vec_nr == 2) {            /* spurious NMI on some machines */
  790. 19651         printf("got spurious NMIn");
  791. 19652         return;
  792. 19653   }
  793. 19654
  794. .Ep 260 src/kernel/exception.c
  795. 19655   if (k_reenter == 0 && isuserp(saved_proc)) {
  796. 19656         unlock();               /* this is protected like sys_call() */
  797. 19657         cause_sig(proc_number(saved_proc), ep->signum);
  798. 19658         return;
  799. 19659   }
  800. 19660
  801. 19661   /* This is not supposed to happen. */
  802. 19662   if (ep->msg == NIL_PTR || processor < ep->minprocessor)
  803. 19663         printf("nIntel-reserved exception %dn", vec_nr);
  804. 19664   else
  805. 19665         printf("n%sn", ep->msg);
  806. 19666   printf("process number %d, pc = 0x%04x:0x%08xn",
  807. 19667         proc_number(saved_proc),
  808. 19668         (unsigned) saved_proc->p_reg.cs,
  809. 19669         (unsigned) saved_proc->p_reg.pc);
  810. 19670   panic("exception in system code", NO_NUM);
  811. 19671 }
  812. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  813. src/kernel/floppy.c    
  814. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  815. 19700 /* This file contains the device dependent part of the driver for the Floppy
  816. 19701  * Disk Controller (FDC) using the NEC PD765 chip.
  817. 19702  *
  818. 19703  * The file contains one entry point:
  819. 19704  *
  820. 19705  *   floppy_task:       main entry when system is brought up
  821. 19706  *   floppy_stop:       stop all activity
  822. 19707  *
  823. 19708  *  Changes:
  824. 19709  *      27 Oct. 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
  825. 19710  *      28 Nov. 1986 by Peter Kay: better resetting for 386
  826. 19711  *      06 Jan. 1988 by Al Crew: allow 1.44 MB diskettes
  827. 19712  *              1989 by Bruce Evans: I/O vector to keep up with 1-1 interleave
  828. 19713  *      13 May  1991 by Don Chapman: renovated the errors loop.
  829. 19714  *              1991 by Bruce Evans: len[] / motors / reset / step rate / ...
  830. 19715  *      14 Feb  1992 by Andy Tanenbaum: check drive density on opens only
  831. 19716  *      27 Mar  1992 by Kees J. Bot: last details on density checking
  832. 19717  *      04 Apr  1992 by Kees J. Bot: device dependent/independent split
  833. 19718  */
  834. 19719
  835. 19720 #include "kernel.h"
  836. 19721 #include "driver.h"
  837. 19722 #include "drvlib.h"
  838. 19723 #include <ibm/diskparm.h>
  839. 19724
  840. 19725 /* I/O Ports used by floppy disk task. */
  841. 19726 #define DOR            0x3F2    /* motor drive control bits */
  842. 19727 #define FDC_STATUS     0x3F4    /* floppy disk controller status register */
  843. 19728 #define FDC_DATA       0x3F5    /* floppy disk controller data register */
  844. 19729 #define FDC_RATE       0x3F7    /* transfer rate register */
  845. 19730 #define DMA_ADDR       0x004    /* port for low 16 bits of DMA address */
  846. 19731 #define DMA_TOP        0x081    /* port for top 4 bits of 20-bit DMA addr */
  847. 19732 #define DMA_COUNT      0x005    /* port for DMA count (count =  bytes - 1) */
  848. 19733 #define DMA_FLIPFLOP   0x00C    /* DMA byte pointer flip-flop */
  849. 19734 #define DMA_MODE       0x00B    /* DMA mode port */
  850. .Op 261 src/kernel/floppy.c
  851. 19735 #define DMA_INIT       0x00A    /* DMA init port */
  852. 19736 #define DMA_RESET_VAL   0x06
  853. 19737
  854. 19738 /* Status registers returned as result of operation. */
  855. 19739 #define ST0             0x00    /* status register 0 */
  856. 19740 #define ST1             0x01    /* status register 1 */
  857. 19741 #define ST2             0x02    /* status register 2 */
  858. 19742 #define ST3             0x00    /* status register 3 (return by DRIVE_SENSE) */
  859. 19743 #define ST_CYL          0x03    /* slot where controller reports cylinder */
  860. 19744 #define ST_HEAD         0x04    /* slot where controller reports head */
  861. 19745 #define ST_SEC          0x05    /* slot where controller reports sector */
  862. 19746 #define ST_PCN          0x01    /* slot where controller reports present cyl */
  863. 19747
  864. 19748 /* Fields within the I/O ports. */
  865. 19749 /* Main status register. */
  866. 19750 #define CTL_BUSY        0x10    /* bit is set when read or write in progress */
  867. 19751 #define DIRECTION       0x40    /* bit is set when reading data reg is valid */
  868. 19752 #define MASTER          0x80    /* bit is set when data reg can be accessed */
  869. 19753
  870. 19754 /* Digital output port (DOR). */
  871. 19755 #define MOTOR_SHIFT        4    /* high 4 bits control the motors in DOR */
  872. 19756 #define ENABLE_INT      0x0C    /* used for setting DOR port */
  873. 19757
  874. 19758 /* ST0. */
  875. 19759 #define ST0_BITS        0xF8    /* check top 5 bits of seek status */
  876. 19760 #define TRANS_ST0       0x00    /* top 5 bits of ST0 for READ/WRITE */
  877. 19761 #define SEEK_ST0        0x20    /* top 5 bits of ST0 for SEEK */
  878. 19762
  879. 19763 /* ST1. */
  880. 19764 #define BAD_SECTOR      0x05    /* if these bits are set in ST1, recalibrate */
  881. 19765 #define WRITE_PROTECT   0x02    /* bit is set if diskette is write protected */
  882. 19766
  883. 19767 /* ST2. */
  884. 19768 #define BAD_CYL         0x1F    /* if any of these bits are set, recalibrate */
  885. 19769
  886. 19770 /* ST3 (not used). */
  887. 19771 #define ST3_FAULT       0x80    /* if this bit is set, drive is sick */
  888. 19772 #define ST3_WR_PROTECT  0x40    /* set when diskette is write protected */
  889. 19773 #define ST3_READY       0x20    /* set when drive is ready */
  890. 19774
  891. 19775 /* Floppy disk controller command bytes. */
  892. 19776 #define FDC_SEEK        0x0F    /* command the drive to seek */
  893. 19777 #define FDC_READ        0xE6    /* command the drive to read */
  894. 19778 #define FDC_WRITE       0xC5    /* command the drive to write */
  895. 19779 #define FDC_SENSE       0x08    /* command the controller to tell its status */
  896. 19780 #define FDC_RECALIBRATE 0x07    /* command the drive to go to cyl 0 */
  897. 19781 #define FDC_SPECIFY     0x03    /* command the drive to accept params */
  898. 19782 #define FDC_READ_ID     0x4A    /* command the drive to read sector identity */
  899. 19783 #define FDC_FORMAT      0x4D    /* command the drive to format a track */
  900. 19784
  901. 19785 /* DMA channel commands. */
  902. 19786 #define DMA_READ        0x46    /* DMA read opcode */
  903. 19787 #define DMA_WRITE       0x4A    /* DMA write opcode */
  904. 19788
  905. 19789 /* Parameters for the disk drive. */
  906. 19790 #define HC_SIZE         2880    /* # sectors on largest legal disk (1.44MB) */
  907. 19791 #define NR_HEADS        0x02    /* two heads (i.e., two tracks/cylinder) */
  908. 19792 #define MAX_SECTORS       18    /* largest # sectors per track */
  909. 19793 #define DTL             0xFF    /* determines data length (sector size) */
  910. 19794 #define SPEC2           0x02    /* second parameter to SPECIFY */
  911. .Ep 262 src/kernel/floppy.c
  912. 19795 #define MOTOR_OFF       3*HZ    /* how long to wait before stopping motor */
  913. 19796 #define WAKEUP          2*HZ    /* timeout on I/O, FDC won't quit. */
  914. 19797
  915. 19798 /* Error codes */
  916. 19799 #define ERR_SEEK         (-1)   /* bad seek */
  917. 19800 #define ERR_TRANSFER     (-2)   /* bad transfer */
  918. 19801 #define ERR_STATUS       (-3)   /* something wrong when getting status */
  919. 19802 #define ERR_READ_ID      (-4)   /* bad read id */
  920. 19803 #define ERR_RECALIBRATE  (-5)   /* recalibrate didn't work properly */
  921. 19804 #define ERR_DRIVE        (-6)   /* something wrong with a drive */
  922. 19805 #define ERR_WR_PROTECT   (-7)   /* diskette is write protected */
  923. 19806 #define ERR_TIMEOUT      (-8)   /* interrupt timeout */
  924. 19807
  925. 19808 /* No retries on some errors. */
  926. 19809 #define err_no_retry(err)       ((err) <= ERR_WR_PROTECT)
  927. 19810
  928. 19811 /* Encoding of drive type in minor device number. */
  929. 19812 #define DEV_TYPE_BITS   0x7C    /* drive type + 1, if nonzero */
  930. 19813 #define DEV_TYPE_SHIFT     2    /* right shift to normalize type bits */
  931. 19814 #define FORMAT_DEV_BIT  0x80    /* bit in minor to turn write into format */
  932. 19815
  933. 19816 /* Miscellaneous. */
  934. 19817 #define MAX_ERRORS         6    /* how often to try rd/wt before quitting */
  935. 19818 #define MAX_RESULTS        7    /* max number of bytes controller returns */
  936. 19819 #define NR_DRIVES          2    /* maximum number of drives */
  937. 19820 #define DIVISOR          128    /* used for sector size encoding */
  938. 19821 #define SECTOR_SIZE_CODE   2    /* code to say "512" to the controller */
  939. 19822 #define TIMEOUT          500    /* milliseconds waiting for FDC */
  940. 19823 #define NT                 7    /* number of diskette/drive combinations */
  941. 19824 #define UNCALIBRATED       0    /* drive needs to be calibrated at next use */
  942. 19825 #define CALIBRATED         1    /* no calibration needed */
  943. 19826 #define BASE_SECTOR        1    /* sectors are numbered starting at 1 */
  944. 19827 #define NO_SECTOR          0    /* current sector unknown */
  945. 19828 #define NO_CYL           (-1)   /* current cylinder unknown, must seek */
  946. 19829 #define NO_DENS          100    /* current media unknown */
  947. 19830 #define BSY_IDLE           0    /* busy doing nothing */
  948. 19831 #define BSY_IO             1    /* doing I/O */
  949. 19832 #define BSY_WAKEN          2    /* got a wakeup call */
  950. 19833
  951. 19834 /* Variables. */
  952. 19835 PRIVATE struct floppy {         /* main drive struct, one entry per drive */
  953. 19836   int fl_curcyl;                /* current cylinder */
  954. 19837   int fl_hardcyl;               /* hardware cylinder, as opposed to: */
  955. 19838   int fl_cylinder;              /* cylinder number addressed */
  956. 19839   int fl_sector;                /* sector addressed */
  957. 19840   int fl_head;                  /* head number addressed */
  958. 19841   char fl_calibration;          /* CALIBRATED or UNCALIBRATED */
  959. 19842   char fl_density;              /* NO_DENS = ?, 0 = 360K; 1 = 360K/1.2M; etc.*/
  960. 19843   char fl_class;                /* bitmap for possible densities */
  961. 19844   struct device fl_geom;        /* Geometry of the drive */
  962. 19845   struct device fl_part[NR_PARTITIONS];  /* partition's base & size */
  963. 19846 } floppy[NR_DRIVES], *f_fp;
  964. 19847
  965. 19848 /* Gather transfer data for each sector. */
  966. 19849 PRIVATE struct trans {          /* precomputed transfer params */
  967. 19850   unsigned tr_count;            /* byte count */
  968. 19851   struct iorequest_s *tr_iop;   /* belongs to this I/O request */
  969. 19852   phys_bytes tr_phys;           /* user physical address */
  970. 19853   phys_bytes tr_dma;            /* DMA physical address */
  971. 19854 } ftrans[MAX_SECTORS];
  972. .Op 263 src/kernel/floppy.c
  973. 19855
  974. 19856 PRIVATE unsigned f_count;       /* this many bytes to transfer */
  975. 19857 PRIVATE unsigned f_nexttrack;   /* don't do blocks above this */
  976. 19858 PRIVATE int motor_status;       /* bitmap of current motor status */
  977. 19859 PRIVATE int motor_goal;         /* bitmap of desired motor status */
  978. 19860 PRIVATE int need_reset;         /* set to 1 when controller must be reset */
  979. 19861 PRIVATE int d;                  /* diskette/drive combination */
  980. 19862 PRIVATE int f_drive;            /* selected drive */
  981. 19863 PRIVATE int f_device;           /* selected minor device */
  982. 19864 PRIVATE int f_opcode;           /* DEV_READ or DEV_WRITE */
  983. 19865 PRIVATE int f_sectors;          /* sectors per track of the floppy */
  984. 19866 PRIVATE int f_must;             /* must do part of the next track? */
  985. 19867 PRIVATE int f_busy;             /* BSY_IDLE, BSY_IO, BSY_WAKEN */
  986. 19868 PRIVATE int current_spec1;      /* latest spec1 sent to the controller */
  987. 19869 PRIVATE struct device *f_dv;    /* device's base and size */
  988. 19870 PRIVATE struct disk_parameter_s fmt_param; /* parameters for format */
  989. 19871 PRIVATE char f_results[MAX_RESULTS];/* the controller can give lots of output */
  990. 19872
  991. 19873
  992. 19874 /* Seven combinations of diskette/drive are supported.
  993. 19875  *
  994. 19876  * # Drive  diskette  Sectors  Tracks  Rotation Data-rate  Comment
  995. 19877  * 0  360K    360K      9       40     300 RPM  250 kbps   Standard PC DSDD
  996. 19878  * 1  1.2M    1.2M     15       80     360 RPM  500 kbps   AT disk in AT drive
  997. 19879  * 2  720K    360K      9       40     300 RPM  250 kbps   Quad density PC
  998. 19880  * 3  720K    720K      9       80     300 RPM  250 kbps   Toshiba, et al.
  999. 19881  * 4  1.2M    360K      9       40     360 RPM  300 kbps   PC disk in AT drive
  1000. 19882  * 5  1.2M    720K      9       80     360 RPM  300 kbps   Toshiba in AT drive
  1001. 19883  * 6  1.44M   1.44M    18       80     300 RPM  500 kbps   PS/2, et al.
  1002. 19884  *
  1003. 19885  * In addition, 720K diskettes can be read in 1.44MB drives, but that does
  1004. 19886  * not need a different set of parameters.  This combination uses
  1005. 19887  *
  1006. 19888  * X  1.44M   720K      9       80     300 RPM  250 kbps   PS/2, et al.
  1007. 19889  */
  1008. 19890 PRIVATE char gap[NT] =
  1009. 19891         {0x2A, 0x1B, 0x2A, 0x2A, 0x23, 0x23, 0x1B}; /* gap size */
  1010. 19892 PRIVATE char rate[NT] =
  1011. 19893         {0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x00}; /* 2=250,1=300,0=500 kbps*/
  1012. 19894 PRIVATE char nr_sectors[NT] =
  1013. 19895         {9,    15,   9,    9,    9,    9,    18};   /* sectors/track */
  1014. 19896 PRIVATE int nr_blocks[NT] =
  1015. 19897         {720,  2400, 720,  1440, 720,  1440, 2880}; /* sectors/diskette*/
  1016. 19898 PRIVATE char steps_per_cyl[NT] =
  1017. 19899         {1,    1,    2,    1,    2,    1,     1};   /* 2 = dbl step */
  1018. 19900 PRIVATE char mtr_setup[NT] =
  1019. 19901         {1*HZ/4,3*HZ/4,1*HZ/4,4*HZ/4,3*HZ/4,3*HZ/4,4*HZ/4}; /* in ticks */
  1020. 19902 PRIVATE char spec1[NT] =
  1021. 19903         {0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF}; /* step rate, etc. */
  1022. 19904 PRIVATE char test_sector[NT] =
  1023. 19905         {4*9,  14,   2*9,  4*9,  2*9,  4*9,  17};   /* to recognize it */
  1024. 19906
  1025. 19907 #define b(d)    (1 << (d))      /* bit for density d. */
  1026. 19908
  1027. 19909 /* The following table is used with the test_sector array to recognize a
  1028. 19910  * drive/floppy combination.  The sector to test has been determined by
  1029. 19911  * looking at the differences in gap size, sectors/track, and double stepping.
  1030. 19912  * This means that types 0 and 3 can't be told apart, only the motor start
  1031. 19913  * time differs.  If a read test succeeds then the drive is limited to the
  1032. 19914  * set of densities it can support to avoid unnecessary tests in the future.
  1033. .Ep 264 src/kernel/floppy.c
  1034. 19915  */
  1035. 19916
  1036. 19917 PRIVATE struct test_order {
  1037. 19918         char    t_density;      /* floppy/drive type */
  1038. 19919         char    t_class;        /* limit drive to this class of densities */
  1039. 19920 } test_order[NT-1] = {
  1040. 19921         { 6,  b(3) | b(6) },            /* 1.44M  {720K, 1.44M} */
  1041. 19922         { 1,  b(1) | b(4) | b(5) },     /* 1.2M   {1.2M, 360K, 720K} */
  1042. 19923         { 3,  b(2) | b(3) | b(6) },     /* 720K   {360K, 720K, 1.44M} */
  1043. 19924         { 4,  b(1) | b(4) | b(5) },     /* 360K   {1.2M, 360K, 720K} */
  1044. 19925         { 5,  b(1) | b(4) | b(5) },     /* 720K   {1.2M, 360K, 720K} */
  1045. 19926         { 2,  b(2) | b(3) },            /* 360K   {360K, 720K} */
  1046. 19927         /* Note that type 0 is missing, type 3 can read/write it too (alas). */
  1047. 19928 };
  1048. 19929
  1049. 19930 FORWARD _PROTOTYPE( struct device *f_prepare, (int device) );
  1050. 19931 FORWARD _PROTOTYPE( char *f_name, (void) );
  1051. 19932 FORWARD _PROTOTYPE( void f_cleanup, (void) );
  1052. 19933 FORWARD _PROTOTYPE( int f_schedule, (int proc_nr, struct iorequest_s *iop) );
  1053. 19934 FORWARD _PROTOTYPE( int f_finish, (void) );
  1054. 19935 FORWARD _PROTOTYPE( void defuse, (void) );
  1055. 19936 FORWARD _PROTOTYPE( void dma_setup, (struct trans *tp) );
  1056. 19937 FORWARD _PROTOTYPE( void start_motor, (void) );
  1057. 19938 FORWARD _PROTOTYPE( void stop_motor, (void) );
  1058. 19939 FORWARD _PROTOTYPE( int seek, (struct floppy *fp) );
  1059. 19940 FORWARD _PROTOTYPE( int f_transfer, (struct floppy *fp, struct trans *tp) );
  1060. 19941 FORWARD _PROTOTYPE( int fdc_results, (void) );
  1061. 19942 FORWARD _PROTOTYPE( int f_handler, (int irq) );
  1062. 19943 FORWARD _PROTOTYPE( void fdc_out, (int val) );
  1063. 19944 FORWARD _PROTOTYPE( int recalibrate, (struct floppy *fp) );
  1064. 19945 FORWARD _PROTOTYPE( void f_reset, (void) );
  1065. 19946 FORWARD _PROTOTYPE( void send_mess, (void) );
  1066. 19947 FORWARD _PROTOTYPE( int f_intr_wait, (void) );
  1067. 19948 FORWARD _PROTOTYPE( void f_timeout, (void) );
  1068. 19949 FORWARD _PROTOTYPE( int read_id, (struct floppy *fp) );
  1069. 19950 FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr) );
  1070. 19951 FORWARD _PROTOTYPE( int test_read, (int density) );
  1071. 19952 FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry));
  1072. 19953
  1073. 19954
  1074. 19955 /* Entry points to this driver. */
  1075. 19956 PRIVATE struct driver f_dtab = {
  1076. 19957   f_name,       /* current device's name */
  1077. 19958   f_do_open,    /* open or mount request, sense type of diskette */
  1078. 19959   do_nop,       /* nothing on a close */
  1079. 19960   do_diocntl,   /* get or set a partitions geometry */
  1080. 19961   f_prepare,    /* prepare for I/O on a given minor device */
  1081. 19962   f_schedule,   /* precompute cylinder, head, sector, etc. */
  1082. 19963   f_finish,     /* do the I/O */
  1083. 19964   f_cleanup,    /* cleanup before sending reply to user process */
  1084. 19965   f_geometry    /* tell the geometry of the diskette */
  1085. 19966 };
  1086. 19967
  1087. 19968
  1088. 19969 /*===========================================================================*
  1089. 19970  *                              floppy_task                                  *
  1090. 19971  *===========================================================================*/
  1091. 19972 PUBLIC void floppy_task()
  1092. 19973 {
  1093. 19974 /* Initialize the floppy structure. */
  1094. .Op 265 src/kernel/floppy.c
  1095. 19975
  1096. 19976   struct floppy *fp;
  1097. 19977
  1098. 19978   for (fp = &floppy[0]; fp < &floppy[NR_DRIVES]; fp++) {
  1099. 19979         fp->fl_curcyl = NO_CYL;
  1100. 19980         fp->fl_density = NO_DENS;
  1101. 19981         fp->fl_class = ~0;
  1102. 19982   }
  1103. 19983
  1104. 19984   put_irq_handler(FLOPPY_IRQ, f_handler);
  1105. 19985   enable_irq(FLOPPY_IRQ);               /* ready for floppy interrupts */
  1106. 19986
  1107. 19987   driver_task(&f_dtab);
  1108. 19988 }
  1109. 19991 /*===========================================================================*
  1110. 19992  *                              f_prepare                                    *
  1111. 19993  *===========================================================================*/
  1112. 19994 PRIVATE struct device *f_prepare(device)
  1113. 19995 int device;
  1114. 19996 {
  1115. 19997 /* Prepare for I/O on a device. */
  1116. 19998
  1117. 19999   /* Leftover jobs after an I/O error must be removed */
  1118. 20000   if (f_count > 0) defuse();
  1119. 20001
  1120. 20002   f_device = device;
  1121. 20003   f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
  1122. 20004   if (f_drive < 0 || f_drive >= NR_DRIVES) return(NIL_DEV);
  1123. 20005
  1124. 20006   f_fp = &floppy[f_drive];
  1125. 20007   f_dv = &f_fp->fl_geom;
  1126. 20008   d = f_fp->fl_density;
  1127. 20009   f_sectors = nr_sectors[d];
  1128. 20010
  1129. 20011   f_must = TRUE;        /* the first transfers must be done */
  1130. 20012
  1131. 20013   /* A partition? */
  1132. 20014   if ((device &= DEV_TYPE_BITS) >= MINOR_fd0a)
  1133. 20015         f_dv = &f_fp->fl_part[(device - MINOR_fd0a) >> DEV_TYPE_SHIFT];
  1134. 20016
  1135. 20017   return f_dv;
  1136. 20018 }
  1137. 20021 /*===========================================================================*
  1138. 20022  *                              f_name                                       *
  1139. 20023  *===========================================================================*/
  1140. 20024 PRIVATE char *f_name()
  1141. 20025 {
  1142. 20026 /* Return a name for the current device. */
  1143. 20027   static char name[] = "fd3";
  1144. 20028
  1145. 20029   name[2] = '0' + f_drive;
  1146. 20030   return name;
  1147. 20031 }
  1148. 20034 /*===========================================================================*
  1149. .Ep 266 src/kernel/floppy.c
  1150. 20035  *                              f_cleanup                                    *
  1151. 20036  *===========================================================================*/
  1152. 20037 PRIVATE void f_cleanup()
  1153. 20038 {
  1154. 20039   /* Start watchdog timer to turn all motors off in a few seconds.
  1155. 20040    * There is a race here.  An old watchdog might bite before the
  1156. 20041    * new delay is installed, and turn of the motors prematurely.
  1157. 20042    * This cannot be solved simply by resetting motor_goal after
  1158. 20043    * sending the message, because the new watchdog might bite
  1159. 20044    * before motor_goal is reset.  Then the motors would stay on
  1160. 20045    * until after the next floppy access.  This could be fixed with
  1161. 20046    * extra code (call the clock task twice in some cases).  Or
  1162. 20047    * stop_motor() could be replaced by send_mess(), and send a
  1163. 20048    * STOP_MOTOR message to be accepted by the clock task.  This
  1164. 20049    * would be slower but have the advantage that this comment could
  1165. 20050    * be deleted!
  1166. 20051    *
  1167. 20052    * Since it is not likely and not serious for an old watchdog to
  1168. 20053    * bite, accept that possibility for now.  A full solution to the
  1169. 20054    * motor madness requires a lots of extra work anyway, such as
  1170. 20055    * a separate timer for each motor, and smaller delays for motors
  1171. 20056    * that have just been turned off or start faster than the spec.
  1172. 20057    * (is there a motor-ready bit?).
  1173. 20058    */
  1174. 20059   motor_goal = 0;
  1175. 20060   clock_mess(MOTOR_OFF, stop_motor);
  1176. 20061 }
  1177. 20064 /*===========================================================================*
  1178. 20065  *                              f_schedule                                   *
  1179. 20066  *===========================================================================*/
  1180. 20067 PRIVATE int f_schedule(proc_nr, iop)
  1181. 20068 int proc_nr;                    /* process doing the request */
  1182. 20069 struct iorequest_s *iop;        /* pointer to read or write request */
  1183. 20070 {
  1184. 20071   int r, opcode, spanning;
  1185. 20072   unsigned long pos;
  1186. 20073   unsigned block;       /* Seen any 32M floppies lately? */
  1187. 20074   unsigned nbytes, count, dma_count;
  1188. 20075   phys_bytes user_phys, dma_phys;
  1189. 20076   struct trans *tp, *tp0;
  1190. 20077
  1191. 20078   /* Ignore any alarm to turn motor off, now there is work to do. */
  1192. 20079   motor_goal = motor_status;
  1193. 20080
  1194. 20081   /* This many bytes to read/write */
  1195. 20082   nbytes = iop->io_nbytes;
  1196. 20083   if ((nbytes & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  1197. 20084
  1198. 20085   /* From/to this position on disk */
  1199. 20086   pos = iop->io_position;
  1200. 20087   if ((pos & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  1201. 20088
  1202. 20089   /* To/from this user address */
  1203. 20090   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
  1204. 20091   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  1205. 20092
  1206. 20093   /* Read, write or format? */
  1207. 20094   opcode = iop->io_request & ~OPTIONAL_IO;
  1208. .Op 267 src/kernel/floppy.c
  1209. 20095   if (f_device & FORMAT_DEV_BIT) {
  1210. 20096         if (opcode != DEV_WRITE) return(iop->io_nbytes = EIO);
  1211. 20097         if (nbytes != BLOCK_SIZE) return(iop->io_nbytes = EINVAL);
  1212. 20098
  1213. 20099         phys_copy(user_phys + SECTOR_SIZE, vir2phys(&fmt_param),
  1214. 20100                                                 (phys_bytes) sizeof fmt_param);
  1215. 20101
  1216. 20102         /* Check that the number of sectors in the data is reasonable, to
  1217. 20103          * avoid division by 0.  Leave checking of other data to the FDC.
  1218. 20104          */
  1219. 20105         if (fmt_param.sectors_per_cylinder == 0)
  1220. 20106                 return(iop->io_nbytes = EIO);
  1221. 20107
  1222. 20108         /* Only the first sector of the parameters now needed. */
  1223. 20109         iop->io_nbytes = nbytes = SECTOR_SIZE;
  1224. 20110   }
  1225. 20111
  1226. 20112   /* Which block on disk and how close to EOF? */
  1227. 20113   if (pos >= f_dv->dv_size) return(OK);         /* At EOF */
  1228. 20114   if (pos + nbytes > f_dv->dv_size) nbytes = f_dv->dv_size - pos;
  1229. 20115   block = (f_dv->dv_base + pos) >> SECTOR_SHIFT;
  1230. 20116
  1231. 20117   spanning = FALSE;     /* set if the block spans a track */
  1232. 20118
  1233. 20119   /* While there are "unscheduled" bytes in the request: */
  1234. 20120   do {
  1235. 20121         count = nbytes;
  1236. 20122
  1237. 20123         if (f_count > 0 && block >= f_nexttrack) {
  1238. 20124                 /* The new job leaves the track, finish all gathered jobs */
  1239. 20125                 if ((r = f_finish()) != OK) return(r);
  1240. 20126                 f_must = spanning;
  1241. 20127         }
  1242. 20128
  1243. 20129         if (f_count == 0) {
  1244. 20130                 /* This is the first job, compute cylinder and head */
  1245. 20131                 f_opcode = opcode;
  1246. 20132                 f_fp->fl_cylinder = block / (NR_HEADS * f_sectors);
  1247. 20133                 f_fp->fl_hardcyl = f_fp->fl_cylinder * steps_per_cyl[d];
  1248. 20134                 f_fp->fl_head = (block % (NR_HEADS * f_sectors)) / f_sectors;
  1249. 20135
  1250. 20136                 /* See where the next track starts, one is trouble enough */
  1251. 20137                 f_nexttrack = (f_fp->fl_cylinder * NR_HEADS
  1252. 20138                                         + f_fp->fl_head + 1) * f_sectors;
  1253. 20139         }
  1254. 20140
  1255. 20141         /* Don't do track spanning I/O. */
  1256. 20142         if (block + (count >> SECTOR_SHIFT) > f_nexttrack)
  1257. 20143                 count = (f_nexttrack - block) << SECTOR_SHIFT;
  1258. 20144
  1259. 20145         /* Memory chunk to DMA. */
  1260. 20146         dma_phys = user_phys;
  1261. 20147         dma_count = dma_bytes_left(dma_phys);
  1262. 20148
  1263. 20149 #if _WORD_SIZE > 2
  1264. 20150         /* The DMA chip uses a 24 bit address, so don't DMA above 16MB. */
  1265. 20151         if (dma_phys >= 0x1000000) dma_count = 0;
  1266. 20152 #endif
  1267. 20153         if (dma_count < count) {
  1268. 20154                 /* Nearing a 64K boundary. */
  1269. .Ep 268 src/kernel/floppy.c
  1270. 20155                 if (dma_count >= SECTOR_SIZE) {
  1271. 20156                         /* Can read a few sectors before hitting the
  1272. 20157                          * boundary.
  1273. 20158                          */
  1274. 20159                         count = dma_count & ~SECTOR_MASK;
  1275. 20160                 } else {
  1276. 20161                         /* Must use the special buffer for this. */
  1277. 20162                         count = SECTOR_SIZE;
  1278. 20163                         dma_phys = tmp_phys;
  1279. 20164                 }
  1280. 20165         }
  1281. 20166
  1282. 20167         /* Store the I/O parameters in the ftrans slots for the sectors to
  1283. 20168          * read.  The first slot specifies all sectors, the ones following
  1284. 20169          * it each specify one sector less.  This allows I/O to be started
  1285. 20170          * in the middle of a block.
  1286. 20171          */
  1287. 20172         tp = tp0 = &ftrans[block % f_sectors];
  1288. 20173
  1289. 20174         block += count >> SECTOR_SHIFT;
  1290. 20175         nbytes -= count;
  1291. 20176         f_count += count;
  1292. 20177         if (!(iop->io_request & OPTIONAL_IO)) f_must = TRUE;
  1293. 20178
  1294. 20179         do {
  1295. 20180                 tp->tr_count = count;
  1296. 20181                 tp->tr_iop = iop;
  1297. 20182                 tp->tr_phys = user_phys;
  1298. 20183                 tp->tr_dma = dma_phys;
  1299. 20184                 tp++;
  1300. 20185
  1301. 20186                 user_phys += SECTOR_SIZE;
  1302. 20187                 dma_phys += SECTOR_SIZE;
  1303. 20188                 count -= SECTOR_SIZE;
  1304. 20189         } while (count > 0);
  1305. 20190
  1306. 20191         spanning = TRUE;        /* the rest of the block may span a track */
  1307. 20192   } while (nbytes > 0);
  1308. 20193
  1309. 20194   return(OK);
  1310. 20195 }
  1311. 20198 /*===========================================================================*
  1312. 20199  *                              f_finish                                     *
  1313. 20200  *===========================================================================*/
  1314. 20201 PRIVATE int f_finish()
  1315. 20202 {
  1316. 20203 /* Carry out the I/O requests gathered in ftrans[].  */
  1317. 20204
  1318. 20205   struct floppy *fp = f_fp;
  1319. 20206   struct trans *tp;
  1320. 20207   int r, errors;
  1321. 20208
  1322. 20209   if (f_count == 0) return(OK); /* Spurious finish. */
  1323. 20210
  1324. 20211   /* If all the requests are optional then don't read from the next track.
  1325. 20212    * (There may be enough buffers to read the next track, but doing so is
  1326. 20213    * unwise.  It's no good to be greedy on a slow device.)
  1327. 20214    */
  1328. .Op 269 src/kernel/floppy.c
  1329. 20215   if (!f_must) {
  1330. 20216         defuse();
  1331. 20217         return(EAGAIN);
  1332. 20218   }
  1333. 20219
  1334. 20220   /* See if motor is running; if not, turn it on and wait */
  1335. 20221   start_motor();
  1336. 20222
  1337. 20223   /* Let read_id find out the next sector to read/write if it pays to do so.
  1338. 20224    * Note that no read_id is done while formatting if there is one format
  1339. 20225    * request per track as there should be.
  1340. 20226    */
  1341. 20227   fp->fl_sector = f_count >= (6 * SECTOR_SIZE) ? 0 : BASE_SECTOR;
  1342. 20228
  1343. 20229   do {
  1344. 20230         /* This loop allows a failed operation to be repeated. */
  1345. 20231         errors = 0;
  1346. 20232         for (;;) {
  1347. 20233                 /* First check to see if a reset is needed. */
  1348. 20234                 if (need_reset) f_reset();
  1349. 20235
  1350. 20236                 /* Set the stepping rate */
  1351. 20237                 if (current_spec1 != spec1[d]) {
  1352. 20238                         fdc_out(FDC_SPECIFY);
  1353. 20239                         current_spec1 = spec1[d];
  1354. 20240                         fdc_out(current_spec1);
  1355. 20241                         fdc_out(SPEC2);
  1356. 20242                 }
  1357. 20243
  1358. 20244                 /* Set the data rate */
  1359. 20245                 if (pc_at) out_byte(FDC_RATE, rate[d]);
  1360. 20246
  1361. 20247                 /* If we are going to a new cylinder, perform a seek. */
  1362. 20248                 r = seek(fp);
  1363. 20249
  1364. 20250                 if (fp->fl_sector == NO_SECTOR) {
  1365. 20251                         /* Don't retry read_id too often, we need tp soon */
  1366. 20252                         if (errors > 0) fp->fl_sector = BASE_SECTOR;
  1367. 20253
  1368. 20254                         /* Find out what the current sector is */
  1369. 20255                         if (r == OK) r = read_id(fp);
  1370. 20256                 }
  1371. 20257
  1372. 20258                 /* Look for the next job in ftrans[] */
  1373. 20259                 if (fp->fl_sector != NO_SECTOR) {
  1374. 20260                         for (;;) {
  1375. 20261                                 if (fp->fl_sector >= BASE_SECTOR + f_sectors)
  1376. 20262                                         fp->fl_sector = BASE_SECTOR;
  1377. 20263
  1378. 20264                                 tp = &ftrans[fp->fl_sector - BASE_SECTOR];
  1379. 20265                                 if (tp->tr_count > 0) break;
  1380. 20266                                 fp->fl_sector++;
  1381. 20267                         }
  1382. 20268                         /* Do not transfer more than f_count bytes. */
  1383. 20269                         if (tp->tr_count > f_count) tp->tr_count = f_count;
  1384. 20270                 }
  1385. 20271
  1386. 20272                 if (r == OK && tp->tr_dma == tmp_phys
  1387. 20273                                                 && f_opcode == DEV_WRITE) {
  1388. 20274                         /* Copy the bad user buffer to the DMA buffer. */
  1389. .Ep 270 src/kernel/floppy.c
  1390. 20275                         phys_copy(tp->tr_phys, tp->tr_dma,
  1391. 20276                                                 (phys_bytes) tp->tr_count);
  1392. 20277                 }
  1393. 20278
  1394. 20279                 /* Set up the DMA chip and perform the transfer. */
  1395. 20280                 if (r == OK) {
  1396. 20281                         dma_setup(tp);
  1397. 20282                         r = f_transfer(fp, tp);
  1398. 20283                 }
  1399. 20284
  1400. 20285                 if (r == OK && tp->tr_dma == tmp_phys
  1401. 20286                                                 && f_opcode == DEV_READ) {
  1402. 20287                         /* Copy the DMA buffer to the bad user buffer. */
  1403. 20288                         phys_copy(tp->tr_dma, tp->tr_phys,
  1404. 20289                                                 (phys_bytes) tp->tr_count);
  1405. 20290                 }
  1406. 20291
  1407. 20292                 if (r == OK) break;     /* if successful, exit loop */
  1408. 20293
  1409. 20294                 /* Don't retry if write protected or too many errors. */
  1410. 20295                 if (err_no_retry(r) || ++errors == MAX_ERRORS) {
  1411. 20296                         if (fp->fl_sector != 0) tp->tr_iop->io_nbytes = EIO;
  1412. 20297                         return(EIO);
  1413. 20298                 }
  1414. 20299
  1415. 20300                 /* Recalibrate if halfway, but bail out if optional I/O. */
  1416. 20301                 if (errors == MAX_ERRORS / 2) {
  1417. 20302                         fp->fl_calibration = UNCALIBRATED;
  1418. 20303                         if (tp->tr_iop->io_request & OPTIONAL_IO)
  1419. 20304                                 return(tp->tr_iop->io_nbytes = EIO);
  1420. 20305                 }
  1421. 20306         }
  1422. 20307         f_count -= tp->tr_count;
  1423. 20308         tp->tr_iop->io_nbytes -= tp->tr_count;
  1424. 20309   } while (f_count > 0);
  1425. 20310
  1426. 20311   /* Defuse the leftover partial jobs. */
  1427. 20312   defuse();
  1428. 20313
  1429. 20314   return(OK);
  1430. 20315 }
  1431. 20318 /*===========================================================================*
  1432. 20319  *                              defuse                                       *
  1433. 20320  *===========================================================================*/
  1434. 20321 PRIVATE void defuse()
  1435. 20322 {
  1436. 20323 /* Invalidate leftover requests in the transfer array. */
  1437. 20324
  1438. 20325   struct trans *tp;
  1439. 20326
  1440. 20327   for (tp = ftrans; tp < ftrans + MAX_SECTORS; tp++) tp->tr_count = 0;
  1441. 20328   f_count = 0;
  1442. 20329 }
  1443. 20332 /*===========================================================================*
  1444. 20333  *                              dma_setup                                    *
  1445. 20334  *===========================================================================*/
  1446. .Op 271 src/kernel/floppy.c
  1447. 20335 PRIVATE void dma_setup(tp)
  1448. 20336 struct trans *tp;               /* pointer to the transfer struct */
  1449. 20337 {
  1450. 20338 /* The IBM PC can perform DMA operations by using the DMA chip.  To use it,
  1451. 20339  * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
  1452. 20340  * to be read from or written to, the byte count minus 1, and a read or write
  1453. 20341  * opcode.  This routine sets up the DMA chip.  Note that the chip is not
  1454. 20342  * capable of doing a DMA across a 64K boundary (e.g., you can't read a
  1455. 20343  * 512-byte block starting at physical address 65520).
  1456. 20344  */
  1457. 20345
  1458. 20346   /* Set up the DMA registers.  (The comment on the reset is a bit strong,
  1459. 20347    * it probably only resets the floppy channel.)
  1460. 20348    */
  1461. 20349   out_byte(DMA_INIT, DMA_RESET_VAL);    /* reset the dma controller */
  1462. 20350   out_byte(DMA_FLIPFLOP, 0);            /* write anything to reset it */
  1463. 20351   out_byte(DMA_MODE, f_opcode == DEV_WRITE ? DMA_WRITE : DMA_READ);
  1464. 20352   out_byte(DMA_ADDR, (int) tp->tr_dma >>  0);
  1465. 20353   out_byte(DMA_ADDR, (int) tp->tr_dma >>  8);
  1466. 20354   out_byte(DMA_TOP, (int) (tp->tr_dma >> 16));
  1467. 20355   out_byte(DMA_COUNT, (tp->tr_count - 1) >> 0);
  1468. 20356   out_byte(DMA_COUNT, (tp->tr_count - 1) >> 8);
  1469. 20357   out_byte(DMA_INIT, 2);        /* some sort of enable */
  1470. 20358 }
  1471. 20361 /*===========================================================================*
  1472. 20362  *                              start_motor                                  *
  1473. 20363  *===========================================================================*/
  1474. 20364 PRIVATE void start_motor()
  1475. 20365 {
  1476. 20366 /* Control of the floppy disk motors is a big pain.  If a motor is off, you
  1477. 20367  * have to turn it on first, which takes 1/2 second.  You can't leave it on
  1478. 20368  * all the time, since that would wear out the diskette.  However, if you turn
  1479. 20369  * the motor off after each operation, the system performance will be awful.
  1480. 20370  * The compromise used here is to leave it on for a few seconds after each
  1481. 20371  * operation.  If a new operation is started in that interval, it need not be
  1482. 20372  * turned on again.  If no new operation is started, a timer goes off and the
  1483. 20373  * motor is turned off.  I/O port DOR has bits to control each of 4 drives.
  1484. 20374  * The timer cannot go off while we are changing with the bits, since the
  1485. 20375  * clock task cannot run while another (this) task is active, so there is no
  1486. 20376  * need to lock().
  1487. 20377  */
  1488. 20378
  1489. 20379   int motor_bit, running;
  1490. 20380   message mess;
  1491. 20381
  1492. 20382   motor_bit = 1 << f_drive;             /* bit mask for this drive */
  1493. 20383   running = motor_status & motor_bit;   /* nonzero if this motor is running */
  1494. 20384   motor_goal = motor_status | motor_bit;/* want this drive running too */
  1495. 20385
  1496. 20386   out_byte(DOR, (motor_goal << MOTOR_SHIFT) | ENABLE_INT | f_drive);
  1497. 20387   motor_status = motor_goal;
  1498. 20388
  1499. 20389   /* If the motor was already running, we don't have to wait for it. */
  1500. 20390   if (running) return;                  /* motor was already running */
  1501. 20391   clock_mess(mtr_setup[d], send_mess);  /* motor was not running */
  1502. 20392   receive(CLOCK, &mess);                /* wait for clock interrupt */
  1503. 20393 }
  1504. .Ep 272 src/kernel/floppy.c
  1505. 20396 /*===========================================================================*
  1506. 20397  *                              stop_motor                                   *
  1507. 20398  *===========================================================================*/
  1508. 20399 PRIVATE void stop_motor()
  1509. 20400 {
  1510. 20401 /* This routine is called by the clock interrupt after several seconds have
  1511. 20402  * elapsed with no floppy disk activity.  It checks to see if any drives are
  1512. 20403  * supposed to be turned off, and if so, turns them off.
  1513. 20404  */
  1514. 20405
  1515. 20406   if (motor_goal != motor_status) {
  1516. 20407         out_byte(DOR, (motor_goal << MOTOR_SHIFT) | ENABLE_INT);
  1517. 20408         motor_status = motor_goal;
  1518. 20409   }
  1519. 20410 }
  1520. 20413 /*===========================================================================*
  1521. 20414  *                              floppy_stop                                  *
  1522. 20415  *===========================================================================*/
  1523. 20416 PUBLIC void floppy_stop()
  1524. 20417 {
  1525. 20418 /* Stop all activity. */
  1526. 20419
  1527. 20420   motor_goal = 0;
  1528. 20421   stop_motor();
  1529. 20422 }
  1530. 20425 /*===========================================================================*
  1531. 20426  *                              seek                                         *
  1532. 20427  *===========================================================================*/
  1533. 20428 PRIVATE int seek(fp)
  1534. 20429 struct floppy *fp;              /* pointer to the drive struct */
  1535. 20430 {
  1536. 20431 /* Issue a SEEK command on the indicated drive unless the arm is already
  1537. 20432  * positioned on the correct cylinder.
  1538. 20433  */
  1539. 20434
  1540. 20435   int r;
  1541. 20436   message mess;
  1542. 20437
  1543. 20438   /* Are we already on the correct cylinder? */
  1544. 20439   if (fp->fl_calibration == UNCALIBRATED)
  1545. 20440         if (recalibrate(fp) != OK) return(ERR_SEEK);
  1546. 20441   if (fp->fl_curcyl == fp->fl_hardcyl) return(OK);
  1547. 20442
  1548. 20443   /* No.  Wrong cylinder.  Issue a SEEK and wait for interrupt. */
  1549. 20444   fdc_out(FDC_SEEK);
  1550. 20445   fdc_out((fp->fl_head << 2) | f_drive);
  1551. 20446   fdc_out(fp->fl_hardcyl);
  1552. 20447   if (need_reset) return(ERR_SEEK);     /* if controller is sick, abort seek */
  1553. 20448   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
  1554. 20449
  1555. 20450   /* Interrupt has been received.  Check drive status. */
  1556. 20451   fdc_out(FDC_SENSE);           /* probe FDC to make it return status */
  1557. 20452   r = fdc_results();            /* get controller status bytes */
  1558. 20453   if (r != OK || (f_results[ST0] & ST0_BITS) != SEEK_ST0
  1559. 20454                                 || f_results[ST1] != fp->fl_hardcyl) {
  1560. .Op 273 src/kernel/floppy.c
  1561. 20455         /* seek failed, may need a recalibrate */
  1562. 20456         return(ERR_SEEK);
  1563. 20457   }
  1564. 20458   /* give head time to settle on a format, no retrying here! */
  1565. 20459   if (f_device & FORMAT_DEV_BIT) {
  1566. 20460         clock_mess(2, send_mess);
  1567. 20461         receive(CLOCK, &mess);
  1568. 20462   }
  1569. 20463   fp->fl_curcyl = fp->fl_hardcyl;
  1570. 20464   return(OK);
  1571. 20465 }
  1572. 20468 /*===========================================================================*
  1573. 20469  *                              f_transfer                                   *
  1574. 20470  *===========================================================================*/
  1575. 20471 PRIVATE int f_transfer(fp, tp)
  1576. 20472 struct floppy *fp;              /* pointer to the drive struct */
  1577. 20473 struct trans *tp;               /* pointer to the transfer struct */
  1578. 20474 {
  1579. 20475 /* The drive is now on the proper cylinder.  Read, write or format 1 block. */
  1580. 20476
  1581. 20477   int r, s;
  1582. 20478
  1583. 20479   /* Never attempt a transfer if the drive is uncalibrated or motor is off. */
  1584. 20480   if (fp->fl_calibration == UNCALIBRATED) return(ERR_TRANSFER);
  1585. 20481   if ((motor_status & (1 << f_drive)) == 0) return(ERR_TRANSFER);
  1586. 20482
  1587. 20483   /* The command is issued by outputting several bytes to the controller chip.
  1588. 20484    */
  1589. 20485   if (f_device & FORMAT_DEV_BIT) {
  1590. 20486         fdc_out(FDC_FORMAT);
  1591. 20487         fdc_out((fp->fl_head << 2) | f_drive);
  1592. 20488         fdc_out(fmt_param.sector_size_code);
  1593. 20489         fdc_out(fmt_param.sectors_per_cylinder);
  1594. 20490         fdc_out(fmt_param.gap_length_for_format);
  1595. 20491         fdc_out(fmt_param.fill_byte_for_format);
  1596. 20492   } else {
  1597. 20493         fdc_out(f_opcode == DEV_WRITE ? FDC_WRITE : FDC_READ);
  1598. 20494         fdc_out((fp->fl_head << 2) | f_drive);
  1599. 20495         fdc_out(fp->fl_cylinder);
  1600. 20496         fdc_out(fp->fl_head);
  1601. 20497         fdc_out(fp->fl_sector);
  1602. 20498         fdc_out(SECTOR_SIZE_CODE);
  1603. 20499         fdc_out(f_sectors);
  1604. 20500         fdc_out(gap[d]);        /* sector gap */
  1605. 20501         fdc_out(DTL);           /* data length */
  1606. 20502   }
  1607. 20503
  1608. 20504   /* Block, waiting for disk interrupt. */
  1609. 20505   if (need_reset) return(ERR_TRANSFER); /* if controller is sick, abort op */
  1610. 20506
  1611. 20507   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
  1612. 20508
  1613. 20509   /* Get controller status and check for errors. */
  1614. 20510   r = fdc_results();
  1615. 20511   if (r != OK) return(r);
  1616. 20512
  1617. 20513   if (f_results[ST1] & WRITE_PROTECT) {
  1618. 20514         printf("%s: diskette is write protected.n", f_name());
  1619. .Ep 274 src/kernel/floppy.c
  1620. 20515         return(ERR_WR_PROTECT);
  1621. 20516   }
  1622. 20517
  1623. 20518   if ((f_results[ST0] & ST0_BITS) != TRANS_ST0) return(ERR_TRANSFER);
  1624. 20519   if (f_results[ST1] | f_results[ST2]) return(ERR_TRANSFER);
  1625. 20520
  1626. 20521   if (f_device & FORMAT_DEV_BIT) return(OK);
  1627. 20522
  1628. 20523   /* Compare actual numbers of sectors transferred with expected number. */
  1629. 20524   s =  (f_results[ST_CYL] - fp->fl_cylinder) * NR_HEADS * f_sectors;
  1630. 20525   s += (f_results[ST_HEAD] - fp->fl_head) * f_sectors;
  1631. 20526   s += (f_results[ST_SEC] - fp->fl_sector);
  1632. 20527   if ((s << SECTOR_SHIFT) != tp->tr_count) return(ERR_TRANSFER);
  1633. 20528
  1634. 20529   /* This sector is next for I/O: */
  1635. 20530   fp->fl_sector = f_results[ST_SEC];
  1636. 20531   return(OK);
  1637. 20532 }
  1638. 20535 /*==========================================================================*
  1639. 20536  *                              fdc_results                                 *
  1640. 20537  *==========================================================================*/
  1641. 20538 PRIVATE int fdc_results()
  1642. 20539 {
  1643. 20540 /* Extract results from the controller after an operation, then allow floppy
  1644. 20541  * interrupts again.
  1645. 20542  */
  1646. 20543
  1647. 20544   int result_nr, status;
  1648. 20545   struct milli_state ms;
  1649. 20546
  1650. 20547   /* Extract bytes from FDC until it says it has no more.  The loop is
  1651. 20548    * really an outer loop on result_nr and an inner loop on status.
  1652. 20549    */
  1653. 20550   result_nr = 0;
  1654. 20551   milli_start(&ms);
  1655. 20552   do {
  1656. 20553         /* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
  1657. 20554          * bit must be set instead of clear, but the CTL_BUSY bit destroys
  1658. 20555          * the perfection of the mirror.
  1659. 20556          */
  1660. 20557         status = in_byte(FDC_STATUS) & (MASTER | DIRECTION | CTL_BUSY);
  1661. 20558         if (status == (MASTER | DIRECTION | CTL_BUSY)) {
  1662. 20559                 if (result_nr >= MAX_RESULTS) break;    /* too many results */
  1663. 20560                 f_results[result_nr++] = in_byte(FDC_DATA);
  1664. 20561                 continue;
  1665. 20562         }
  1666. 20563         if (status == MASTER) { /* all read */
  1667. 20564                 enable_irq(FLOPPY_IRQ);
  1668. 20565                 return(OK);     /* only good exit */
  1669. 20566         }
  1670. 20567   } while (milli_elapsed(&ms) < TIMEOUT);
  1671. 20568   need_reset = TRUE;            /* controller chip must be reset */
  1672. 20569   enable_irq(FLOPPY_IRQ);
  1673. 20570   return(ERR_STATUS);
  1674. 20571 }
  1675. 20574 /*==========================================================================*
  1676. .Op 275 src/kernel/floppy.c
  1677. 20575  *                              f_handler                                   *
  1678. 20576  *==========================================================================*/
  1679. 20577 PRIVATE int f_handler(irq)
  1680. 20578 int irq;
  1681. 20579 {
  1682. 20580 /* FDC interrupt, send message to floppy task. */
  1683. 20581
  1684. 20582   interrupt(FLOPPY);
  1685. 20583   return 0;
  1686. 20584 }
  1687. 20587 /*===========================================================================*
  1688. 20588  *                              fdc_out                                      *
  1689. 20589  *===========================================================================*/
  1690. 20590 PRIVATE void fdc_out(val)
  1691. 20591 int val;                /* write this byte to floppy disk controller */
  1692. 20592 {
  1693. 20593 /* Output a byte to the controller.  This is not entirely trivial, since you
  1694. 20594  * can only write to it when it is listening, and it decides when to listen.
  1695. 20595  * If the controller refuses to listen, the FDC chip is given a hard reset.
  1696. 20596  */
  1697. 20597
  1698. 20598   struct milli_state ms;
  1699. 20599
  1700. 20600   if (need_reset) return;       /* if controller is not listening, return */
  1701. 20601
  1702. 20602   /* It may take several tries to get the FDC to accept a command. */
  1703. 20603   milli_start(&ms);
  1704. 20604   while ((in_byte(FDC_STATUS) & (MASTER | DIRECTION)) != (MASTER | 0)) {
  1705. 20605         if (milli_elapsed(&ms) >= TIMEOUT) {
  1706. 20606                 /* Controller is not listening.  Hit it over the head. */
  1707. 20607                 need_reset = TRUE;
  1708. 20608                 return;
  1709. 20609         }
  1710. 20610   }
  1711. 20611   out_byte(FDC_DATA, val);
  1712. 20612 }
  1713. 20615 /*===========================================================================*
  1714. 20616  *                              recalibrate                                  *
  1715. 20617  *===========================================================================*/
  1716. 20618 PRIVATE int recalibrate(fp)
  1717. 20619 struct floppy *fp;      /* pointer tot he drive struct */
  1718. 20620 {
  1719. 20621 /* The floppy disk controller has no way of determining its absolute arm
  1720. 20622  * position (cylinder).  Instead, it steps the arm a cylinder at a time and
  1721. 20623  * keeps track of where it thinks it is (in software).  However, after a
  1722. 20624  * SEEK, the hardware reads information from the diskette telling where the
  1723. 20625  * arm actually is.  If the arm is in the wrong place, a recalibration is done,
  1724. 20626  * which forces the arm to cylinder 0.  This way the controller can get back
  1725. 20627  * into sync with reality.
  1726. 20628  */
  1727. 20629
  1728. 20630   int r;
  1729. 20631
  1730. 20632   /* Issue the RECALIBRATE command and wait for the interrupt. */
  1731. 20633   start_motor();                /* can't recalibrate with motor off */
  1732. 20634   fdc_out(FDC_RECALIBRATE);     /* tell drive to recalibrate itself */
  1733. .Ep 276 src/kernel/floppy.c
  1734. 20635   fdc_out(f_drive);             /* specify drive */
  1735. 20636   if (need_reset) return(ERR_SEEK);     /* don't wait if controller is sick */
  1736. 20637   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
  1737. 20638
  1738. 20639   /* Determine if the recalibration succeeded. */
  1739. 20640   fdc_out(FDC_SENSE);           /* issue SENSE command to request results */
  1740. 20641   r = fdc_results();            /* get results of the FDC_RECALIBRATE command*/
  1741. 20642   fp->fl_curcyl = NO_CYL;       /* force a SEEK next time */
  1742. 20643   if (r != OK ||                /* controller would not respond */
  1743. 20644      (f_results[ST0] & ST0_BITS) != SEEK_ST0 || f_results[ST_PCN] != 0) {
  1744. 20645         /* Recalibration failed.  FDC must be reset. */
  1745. 20646         need_reset = TRUE;
  1746. 20647         return(ERR_RECALIBRATE);
  1747. 20648   } else {
  1748. 20649         /* Recalibration succeeded. */
  1749. 20650         fp->fl_calibration = CALIBRATED;
  1750. 20651         return(OK);
  1751. 20652   }
  1752. 20653 }
  1753. 20656 /*===========================================================================*
  1754. 20657  *                              f_reset                                      *
  1755. 20658  *===========================================================================*/
  1756. 20659 PRIVATE void f_reset()
  1757. 20660 {
  1758. 20661 /* Issue a reset to the controller.  This is done after any catastrophe,
  1759. 20662  * like the controller refusing to respond.
  1760. 20663  */
  1761. 20664
  1762. 20665   int i;
  1763. 20666   message mess;
  1764. 20667
  1765. 20668   /* Disable interrupts and strobe reset bit low. */
  1766. 20669   need_reset = FALSE;
  1767. 20670
  1768. 20671   /* It is not clear why the next lock is needed.  Writing 0 to DOR causes
  1769. 20672    * interrupt, while the PC documentation says turning bit 8 off disables
  1770. 20673    * interrupts.  Without the lock:
  1771. 20674    *   1) the interrupt handler sets the floppy mask bit in the 8259.
  1772. 20675    *   2) writing ENABLE_INT to DOR causes the FDC to assert the interrupt
  1773. 20676    *      line again, but the mask stops the cpu being interrupted.
  1774. 20677    *   3) the sense interrupt clears the interrupt (not clear which one).
  1775. 20678    * and for some reason the reset does not work.
  1776. 20679    */
  1777. 20680   lock();
  1778. 20681   motor_status = 0;
  1779. 20682   motor_goal = 0;
  1780. 20683   out_byte(DOR, 0);             /* strobe reset bit low */
  1781. 20684   out_byte(DOR, ENABLE_INT);    /* strobe it high again */
  1782. 20685   unlock();
  1783. 20686   receive(HARDWARE, &mess);     /* collect the RESET interrupt */
  1784. 20687
  1785. 20688   /* The controller supports 4 drives and returns a result for each of them.
  1786. 20689    * Collect all the results now.  The old version only collected the first
  1787. 20690    * result.  This happens to work for 2 drives, but it doesn't work for 3
  1788. 20691    * or more drives, at least with only drives 0 and 2 actually connected
  1789. 20692    * (the controller generates an extra interrupt for the middle drive when
  1790. 20693    * drive 2 is accessed and the driver panics).
  1791. 20694    *
  1792. .Op 277 src/kernel/floppy.c
  1793. 20695    * It would be better to keep collecting results until there are no more.
  1794. 20696    * For this, fdc_results needs to return the number of results (instead
  1795. 20697    * of OK) when it succeeds.
  1796. 20698    */
  1797. 20699   for (i = 0; i < 4; i++) {
  1798. 20700         fdc_out(FDC_SENSE);     /* probe FDC to make it return status */
  1799. 20701         (void) fdc_results();   /* flush controller */
  1800. 20702   }
  1801. 20703   for (i = 0; i < NR_DRIVES; i++)       /* clear each drive */
  1802. 20704         floppy[i].fl_calibration = UNCALIBRATED;
  1803. 20705
  1804. 20706   /* The current timing parameters must be specified again. */
  1805. 20707   current_spec1 = 0;
  1806. 20708 }
  1807. 20711 /*===========================================================================*
  1808. 20712  *                              send_mess                                    *
  1809. 20713  *===========================================================================*/
  1810. 20714 PRIVATE void send_mess()
  1811. 20715 {
  1812. 20716 /* This routine is called when the clock task has timed out on motor startup.*/
  1813. 20717
  1814. 20718   message mess;
  1815. 20719
  1816. 20720   send(FLOPPY, &mess);
  1817. 20721 }
  1818. 20724 /*===========================================================================*
  1819. 20725  *                              f_intr_wait                                  *
  1820. 20726  *===========================================================================*/
  1821. 20727 PRIVATE int f_intr_wait()
  1822. 20728 {
  1823. 20729 /* Wait for an interrupt, but not forever.  The FDC may have all the time of
  1824. 20730  * the world, but we humans do not.
  1825. 20731  */
  1826. 20732   message mess;
  1827. 20733
  1828. 20734   f_busy = BSY_IO;
  1829. 20735   clock_mess(WAKEUP, f_timeout);
  1830. 20736   receive(HARDWARE, &mess);
  1831. 20737
  1832. 20738   if (f_busy == BSY_WAKEN) {
  1833. 20739         /* No interrupt from the FDC, this means that there is probably no
  1834. 20740          * floppy in the drive.  Get the FDC down to earth and return error.
  1835. 20741          */
  1836. 20742         f_reset();
  1837. 20743         return(ERR_TIMEOUT);
  1838. 20744   }
  1839. 20745   f_busy = BSY_IDLE;
  1840. 20746   return(OK);
  1841. 20747 }
  1842. 20750 /*===========================================================================*
  1843. 20751  *                              f_timeout                                    *
  1844. 20752  *===========================================================================*/
  1845. 20753 PRIVATE void f_timeout()
  1846. 20754 {
  1847. .Ep 278 src/kernel/floppy.c
  1848. 20755 /* When it takes too long for the FDC to get an interrupt (no floppy in the
  1849. 20756  * drive), this routine is called.  It sets a flag and fakes a hardware
  1850. 20757  * interrupt.
  1851. 20758  */
  1852. 20759   if (f_busy == BSY_IO) {
  1853. 20760         f_busy = BSY_WAKEN;
  1854. 20761         interrupt(FLOPPY);
  1855. 20762   }
  1856. 20763 }
  1857. 20766 /*==========================================================================*
  1858. 20767  *                              read_id                                     *
  1859. 20768  *==========================================================================*/
  1860. 20769 PRIVATE int read_id(fp)
  1861. 20770 struct floppy *fp;      /* pointer to the drive struct */
  1862. 20771 {
  1863. 20772 /* Determine current cylinder and sector. */
  1864. 20773
  1865. 20774   int result;
  1866. 20775
  1867. 20776   /* Never attempt a read id if the drive is uncalibrated or motor is off. */
  1868. 20777   if (fp->fl_calibration == UNCALIBRATED) return(ERR_READ_ID);
  1869. 20778   if ((motor_status & (1 << f_drive)) == 0) return(ERR_READ_ID);
  1870. 20779
  1871. 20780   /* The command is issued by outputting 2 bytes to the controller chip. */
  1872. 20781   fdc_out(FDC_READ_ID);         /* issue the read id command */
  1873. 20782   fdc_out( (f_fp->fl_head << 2) | f_drive);
  1874. 20783
  1875. 20784   /* Block, waiting for disk interrupt. */
  1876. 20785   if (need_reset) return(ERR_READ_ID);  /* if controller is sick, abort op */
  1877. 20786
  1878. 20787   if (f_intr_wait() != OK) return(ERR_TIMEOUT);
  1879. 20788
  1880. 20789   /* Get controller status and check for errors. */
  1881. 20790   result = fdc_results();
  1882. 20791   if (result != OK) return(result);
  1883. 20792
  1884. 20793   if ((f_results[ST0] & ST0_BITS) != TRANS_ST0) return(ERR_READ_ID);
  1885. 20794   if (f_results[ST1] | f_results[ST2]) return(ERR_READ_ID);
  1886. 20795
  1887. 20796   /* The next sector is next for I/O: */
  1888. 20797   f_fp->fl_sector = f_results[ST_SEC] + 1;
  1889. 20798   return(OK);
  1890. 20799 }
  1891. 20802 /*==========================================================================*
  1892. 20803  *                              f_do_open                                   *
  1893. 20804  *==========================================================================*/
  1894. 20805 PRIVATE int f_do_open(dp, m_ptr)
  1895. 20806 struct driver *dp;
  1896. 20807 message *m_ptr;                 /* pointer to open message */
  1897. 20808 {
  1898. 20809 /* Handle an open on a floppy.  Determine diskette type if need be. */
  1899. 20810
  1900. 20811   int dtype;
  1901. 20812   struct test_order *top;
  1902. 20813
  1903. 20814   /* Decode the message parameters. */
  1904. .Op 279 src/kernel/floppy.c
  1905. 20815   if (f_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1906. 20816
  1907. 20817   dtype = f_device & DEV_TYPE_BITS;     /* get density from minor dev */
  1908. 20818   if (dtype >= MINOR_fd0a) dtype = 0;
  1909. 20819   if (dtype != 0) {
  1910. 20820         /* All types except 0 indicate a specific drive/medium combination.*/
  1911. 20821         dtype = (dtype >> DEV_TYPE_SHIFT) - 1;
  1912. 20822         if (dtype >= NT) return(ENXIO);
  1913. 20823         f_fp->fl_density = dtype;
  1914. 20824         f_fp->fl_geom.dv_size = (long) nr_blocks[dtype] << SECTOR_SHIFT;
  1915. 20825         return(OK);
  1916. 20826   }
  1917. 20827   if (f_device & FORMAT_DEV_BIT) return(EIO);   /* Can't format /dev/fdx */
  1918. 20828
  1919. 20829   /* No need to test if the motor is still running. */
  1920. 20830   if (motor_status & (1 << f_drive)) return(OK);
  1921. 20831
  1922. 20832   /* The device opened is /dev/fdx.  Experimentally determine drive/medium.
  1923. 20833    * First check fl_density.  If it is not NO_DENS, the drive has been used
  1924. 20834    * before and the value of fl_density tells what was found last time. Try
  1925. 20835    * that first.
  1926. 20836    */
  1927. 20837   if (f_fp->fl_density != NO_DENS && test_read(f_fp->fl_density) == OK)
  1928. 20838         return(OK);
  1929. 20839
  1930. 20840   /* Either drive type is unknown or a different diskette is now present.
  1931. 20841    * Use test_order to try them one by one.
  1932. 20842    */
  1933. 20843   for (top = &test_order[0]; top < &test_order[NT-1]; top++) {
  1934. 20844         dtype = top->t_density;
  1935. 20845
  1936. 20846         /* Skip densities that have been proven to be impossible */
  1937. 20847         if (!(f_fp->fl_class & (1 << dtype))) continue;
  1938. 20848
  1939. 20849         if (test_read(dtype) == OK) {
  1940. 20850                 /* The test succeeded, use this knowledge to limit the
  1941. 20851                  * drive class to match the density just read.
  1942. 20852                  */
  1943. 20853                 f_fp->fl_class &= top->t_class;
  1944. 20854                 return(OK);
  1945. 20855         }
  1946. 20856         /* Test failed, wrong density or did it time out? */
  1947. 20857         if (f_busy == BSY_WAKEN) break;
  1948. 20858   }
  1949. 20859   f_fp->fl_density = NO_DENS;
  1950. 20860   return(EIO);                  /* nothing worked */
  1951. 20861 }
  1952. 20864 /*==========================================================================*
  1953. 20865  *                              test_read                                   *
  1954. 20866  *==========================================================================*/
  1955. 20867 PRIVATE int test_read(density)
  1956. 20868 int density;
  1957. 20869 {
  1958. 20870 /* Try to read the highest numbered sector on cylinder 2.  Not all floppy
  1959. 20871  * types have as many sectors per track, and trying cylinder 2 finds the
  1960. 20872  * ones that need double stepping.
  1961. 20873  */
  1962. 20874
  1963. .Ep 280 src/kernel/floppy.c
  1964. 20875   message m;
  1965. 20876   int r, device;
  1966. 20877
  1967. 20878   f_fp->fl_density = density;
  1968. 20879   device = ((density + 1) << DEV_TYPE_SHIFT) + f_drive;
  1969. 20880   f_fp->fl_geom.dv_size = (long) nr_blocks[density] << SECTOR_SHIFT;
  1970. 20881   m.m_type = DEV_READ;
  1971. 20882   m.DEVICE = device;
  1972. 20883   m.PROC_NR = FLOPPY;
  1973. 20884   m.COUNT = SECTOR_SIZE;
  1974. 20885   m.POSITION = (long) test_sector[density] * SECTOR_SIZE;
  1975. 20886   m.ADDRESS = (char *) tmp_buf;
  1976. 20887   r = do_rdwt(&f_dtab, &m);
  1977. 20888   if (r != SECTOR_SIZE) return(EIO);
  1978. 20889
  1979. 20890   partition(&f_dtab, f_drive, P_FLOPPY);
  1980. 20891   return(OK);
  1981. 20892 }
  1982. 20895 /*============================================================================*
  1983. 20896  *                              f_geometry                                    *
  1984. 20897  *============================================================================*/
  1985. 20898 PRIVATE void f_geometry(entry)
  1986. 20899 struct partition *entry;
  1987. 20900 {
  1988. 20901   entry->cylinders = nr_blocks[d] / (NR_HEADS * f_sectors);
  1989. 20902   entry->heads = NR_HEADS;
  1990. 20903   entry->sectors = f_sectors;
  1991. 20904 }
  1992. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1993. src/kernel/i8259.c    
  1994. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1995. 21000 /* This file contains routines for initializing the 8259 interrupt controller:
  1996. 21001  *      get_irq_handler: address of handler for a given interrupt
  1997. 21002  *      put_irq_handler: register an interrupt handler
  1998. 21003  *      intr_init:      initialize the interrupt controller(s)
  1999. 21004  */
  2000. 21005
  2001. 21006 #include "kernel.h"
  2002. 21007
  2003. 21008 #define ICW1_AT         0x11    /* edge triggered, cascade, need ICW4 */
  2004. 21009 #define ICW1_PC         0x13    /* edge triggered, no cascade, need ICW4 */
  2005. 21010 #define ICW1_PS         0x19    /* level triggered, cascade, need ICW4 */
  2006. 21011 #define ICW4_AT         0x01    /* not SFNM, not buffered, normal EOI, 8086 */
  2007. 21012 #define ICW4_PC         0x09    /* not SFNM, buffered, normal EOI, 8086 */
  2008. 21013
  2009. 21014 FORWARD _PROTOTYPE( int spurious_irq, (int irq) );
  2010. 21015
  2011. 21016 #if _WORD_SIZE == 2
  2012. 21017 typedef _PROTOTYPE( void (*vecaddr_t), (void) );
  2013. 21018
  2014. 21019 FORWARD _PROTOTYPE( void set_vec, (int vec_nr, vecaddr_t addr) );
  2015. .Op 281 src/kernel/i8259.c
  2016. 21020
  2017. 21021 PRIVATE vecaddr_t int_vec[] = {
  2018. 21022   int00, int01, int02, int03, int04, int05, int06, int07,
  2019. 21023 };
  2020. 21024
  2021. 21025 PRIVATE vecaddr_t irq_vec[] = {
  2022. 21026   hwint00, hwint01, hwint02, hwint03, hwint04, hwint05, hwint06, hwint07,
  2023. 21027   hwint08, hwint09, hwint10, hwint11, hwint12, hwint13, hwint14, hwint15,
  2024. 21028 };
  2025. 21029 #else
  2026. 21030 #define set_vec(nr, addr)       ((void)0)
  2027. 21031 #endif
  2028. 21032
  2029. 21033
  2030. 21034 /*==========================================================================*
  2031. 21035  *                              intr_init                                   *
  2032. 21036  *==========================================================================*/
  2033. 21037 PUBLIC void intr_init(mine)
  2034. 21038 int mine;
  2035. 21039 {
  2036. 21040 /* Initialize the 8259s, finishing with all interrupts disabled.  This is
  2037. 21041  * only done in protected mode, in real mode we don't touch the 8259s, but
  2038. 21042  * use the BIOS locations instead.  The flag "mine" is set if the 8259s are
  2039. 21043  * to be programmed for Minix, or to be reset to what the BIOS expects.
  2040. 21044  */
  2041. 21045
  2042. 21046   int i;
  2043. 21047
  2044. 21048   lock();
  2045. 21049   if (protected_mode) {
  2046. 21050         /* The AT and newer PS/2 have two interrupt controllers, one master,
  2047. 21051          * one slaved at IRQ 2.  (We don't have to deal with the PC that
  2048. 21052          * has just one controller, because it must run in real mode.)
  2049. 21053          */
  2050. 21054         out_byte(INT_CTL, ps_mca ? ICW1_PS : ICW1_AT);
  2051. 21055         out_byte(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
  2052. 21056                                                         /* ICW2 for master */
  2053. 21057         out_byte(INT_CTLMASK, (1 << CASCADE_IRQ));      /* ICW3 tells slaves */
  2054. 21058         out_byte(INT_CTLMASK, ICW4_AT);
  2055. 21059         out_byte(INT_CTLMASK, ~(1 << CASCADE_IRQ));     /* IRQ 0-7 mask */
  2056. 21060         out_byte(INT2_CTL, ps_mca ? ICW1_PS : ICW1_AT);
  2057. 21061         out_byte(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
  2058. 21062                                                         /* ICW2 for slave */
  2059. 21063         out_byte(INT2_CTLMASK, CASCADE_IRQ);            /* ICW3 is slave nr */
  2060. 21064         out_byte(INT2_CTLMASK, ICW4_AT);
  2061. 21065         out_byte(INT2_CTLMASK, ~0);                     /* IRQ 8-15 mask */
  2062. 21066   } else {
  2063. 21067         /* Use the BIOS interrupt vectors in real mode.  We only reprogram the
  2064. 21068          * exceptions here, the interrupt vectors are reprogrammed on demand.
  2065. 21069          * SYS_VECTOR is the Minix system call for message passing.
  2066. 21070          */
  2067. 21071         for (i = 0; i < 8; i++) set_vec(i, int_vec[i]);
  2068. 21072         set_vec(SYS_VECTOR, s_call);
  2069. 21073   }
  2070. 21074
  2071. 21075   /* Initialize the table of interrupt handlers. */
  2072. 21076   for (i = 0; i < NR_IRQ_VECTORS; i++) irq_table[i] = spurious_irq;
  2073. 21077 }
  2074. 21079 /*=========================================================================*
  2075. .Ep 282 src/kernel/i8259.c
  2076. 21080  *                              spurious_irq                               *
  2077. 21081  *=========================================================================*/
  2078. 21082 PRIVATE int spurious_irq(irq)
  2079. 21083 int irq;
  2080. 21084 {
  2081. 21085 /* Default interrupt handler.  It complains a lot. */
  2082. 21086
  2083. 21087   if (irq < 0 || irq >= NR_IRQ_VECTORS)
  2084. 21088         panic("invalid call to spurious_irq", irq);
  2085. 21089
  2086. 21090   printf("spurious irq %dn", irq);
  2087. 21091
  2088. 21092   return 1;     /* Reenable interrupt */
  2089. 21093 }
  2090. 21095 /*=========================================================================*
  2091. 21096  *                              put_irq_handler                            *
  2092. 21097  *=========================================================================*/
  2093. 21098 PUBLIC void put_irq_handler(irq, handler)
  2094. 21099 int irq;
  2095. 21100 irq_handler_t handler;
  2096. 21101 {
  2097. 21102 /* Register an interrupt handler. */
  2098. 21103
  2099. 21104   if (irq < 0 || irq >= NR_IRQ_VECTORS)
  2100. 21105         panic("invalid call to put_irq_handler", irq);
  2101. 21106
  2102. 21107   if (irq_table[irq] == handler)
  2103. 21108         return;         /* extra initialization */
  2104. 21109
  2105. 21110   if (irq_table[irq] != spurious_irq)
  2106. 21111         panic("attempt to register second irq handler for irq", irq);
  2107. 21112
  2108. 21113   disable_irq(irq);
  2109. 21114   if (!protected_mode) set_vec(BIOS_VECTOR(irq), irq_vec[irq]);
  2110. 21115   irq_table[irq]= handler;
  2111. 21116   irq_use |= 1 << irq;
  2112. 21117 }
  2113. 21120 #if _WORD_SIZE == 2
  2114. 21121 /*===========================================================================*
  2115. 21122  *                                   set_vec                                 *
  2116. 21123  *===========================================================================*/
  2117. 21124 PRIVATE void set_vec(vec_nr, addr)
  2118. 21125 int vec_nr;                     /* which vector */
  2119. 21126 vecaddr_t addr;                 /* where to start */
  2120. 21127 {
  2121. 21128 /* Set up a real mode interrupt vector. */
  2122. 21129
  2123. 21130   u16_t vec[2];
  2124. 21131
  2125. 21132   /* Build the vector in the array 'vec'. */
  2126. 21133   vec[0] = (u16_t) addr;
  2127. 21134   vec[1] = (u16_t) physb_to_hclick(code_base);
  2128. 21135
  2129. 21136   /* Copy the vector into place. */
  2130. 21137   phys_copy(vir2phys(vec), vec_nr * 4L, 4L);
  2131. 21138 }
  2132. 21139 #endif /* _WORD_SIZE == 2 */
  2133. .Op 283 src/kernel/keyboard.c
  2134. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2135. src/kernel/keyboard.c    
  2136. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2137. 21200 /* Keyboard driver for PC's and AT's.
  2138. 21201  *
  2139. 21202  * Changed by Marcus Hampel     (04/02/1994)
  2140. 21203  *  - Loadable keymaps
  2141. 21204  */
  2142. 21205
  2143. 21206 #include "kernel.h"
  2144. 21207 #include <termios.h>
  2145. 21208 #include <signal.h>
  2146. 21209 #include <unistd.h>
  2147. 21210 #include <minix/callnr.h>
  2148. 21211 #include <minix/com.h>
  2149. 21212 #include <minix/keymap.h>
  2150. 21213 #include "tty.h"
  2151. 21214 #include "keymaps/us-std.src"
  2152. 21215
  2153. 21216 /* Standard and AT keyboard.  (PS/2 MCA implies AT throughout.) */
  2154. 21217 #define KEYBD           0x60    /* I/O port for keyboard data */
  2155. 21218
  2156. 21219 /* AT keyboard. */
  2157. 21220 #define KB_COMMAND      0x64    /* I/O port for commands on AT */
  2158. 21221 #define KB_GATE_A20     0x02    /* bit in output port to enable A20 line */
  2159. 21222 #define KB_PULSE_OUTPUT 0xF0    /* base for commands to pulse output port */
  2160. 21223 #define KB_RESET        0x01    /* bit in output port to reset CPU */
  2161. 21224 #define KB_STATUS       0x64    /* I/O port for status on AT */
  2162. 21225 #define KB_ACK          0xFA    /* keyboard ack response */
  2163. 21226 #define KB_BUSY         0x02    /* status bit set when KEYBD port ready */
  2164. 21227 #define LED_CODE        0xED    /* command to keyboard to set LEDs */
  2165. 21228 #define MAX_KB_ACK_RETRIES 0x1000       /* max #times to wait for kb ack */
  2166. 21229 #define MAX_KB_BUSY_RETRIES 0x1000      /* max #times to loop while kb busy */
  2167. 21230 #define KBIT            0x80    /* bit used to ack characters to keyboard */
  2168. 21231
  2169. 21232 /* Miscellaneous. */
  2170. 21233 #define ESC_SCAN           1    /* Reboot key when panicking */
  2171. 21234 #define SLASH_SCAN        53    /* to recognize numeric slash */
  2172. 21235 #define HOME_SCAN         71    /* first key on the numeric keypad */
  2173. 21236 #define DEL_SCAN          83    /* DEL for use in CTRL-ALT-DEL reboot */
  2174. 21237 #define CONSOLE            0    /* line number for console */
  2175. 21238 #define MEMCHECK_ADR   0x472    /* address to stop memory check after reboot */
  2176. 21239 #define MEMCHECK_MAG  0x1234    /* magic number to stop memory check */
  2177. 21240
  2178. 21241 #define kb_addr()       (&kb_lines[0])  /* there is only one keyboard */
  2179. 21242 #define KB_IN_BYTES       32    /* size of keyboard input buffer */
  2180. 21243
  2181. 21244 PRIVATE int alt1;               /* left alt key state */
  2182. 21245 PRIVATE int alt2;               /* right alt key state */
  2183. 21246 PRIVATE int capslock;           /* caps lock key state */
  2184. 21247 PRIVATE int esc;                /* escape scan code detected? */
  2185. 21248 PRIVATE int control;            /* control key state */
  2186. 21249 PRIVATE int caps_off;           /* 1 = normal position, 0 = depressed */
  2187. 21250 PRIVATE int numlock;            /* number lock key state */
  2188. 21251 PRIVATE int num_off;            /* 1 = normal position, 0 = depressed */
  2189. 21252 PRIVATE int slock;              /* scroll lock key state */
  2190. 21253 PRIVATE int slock_off;          /* 1 = normal position, 0 = depressed */
  2191. 21254 PRIVATE int shift;              /* shift key state */
  2192. .Ep 284 src/kernel/keyboard.c
  2193. 21255
  2194. 21256 PRIVATE char numpad_map[] =
  2195. 21257                 {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
  2196. 21258
  2197. 21259 /* Keyboard structure, 1 per console. */
  2198. 21260 struct kb_s {
  2199. 21261   char *ihead;                  /* next free spot in input buffer */
  2200. 21262   char *itail;                  /* scan code to return to TTY */
  2201. 21263   int icount;                   /* # codes in buffer */
  2202. 21264   char ibuf[KB_IN_BYTES];       /* input buffer */
  2203. 21265 };
  2204. 21266
  2205. 21267 PRIVATE struct kb_s kb_lines[NR_CONS];
  2206. 21268
  2207. 21269 FORWARD _PROTOTYPE( int kb_ack, (void) );
  2208. 21270 FORWARD _PROTOTYPE( int kb_wait, (void) );
  2209. 21271 FORWARD _PROTOTYPE( int func_key, (int scode) );
  2210. 21272 FORWARD _PROTOTYPE( int scan_keyboard, (void) );
  2211. 21273 FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
  2212. 21274 FORWARD _PROTOTYPE( void set_leds, (void) );
  2213. 21275 FORWARD _PROTOTYPE( int kbd_hw_int, (int irq) );
  2214. 21276 FORWARD _PROTOTYPE( void kb_read, (struct tty *tp) );
  2215. 21277 FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
  2216. 21278
  2217. 21279
  2218. 21280 /*===========================================================================*
  2219. 21281  *                              map_key0                                     *
  2220. 21282  *===========================================================================*/
  2221. 21283 /* Map a scan code to an ASCII code ignoring modifiers. */
  2222. 21284 #define map_key0(scode)  
  2223. 21285         ((unsigned) keymap[(scode) * MAP_COLS])
  2224. 21286
  2225. 21287
  2226. 21288 /*===========================================================================*
  2227. 21289  *                              map_key                                      *
  2228. 21290  *===========================================================================*/
  2229. 21291 PRIVATE unsigned map_key(scode)
  2230. 21292 int scode;
  2231. 21293 {
  2232. 21294 /* Map a scan code to an ASCII code. */
  2233. 21295
  2234. 21296   int caps, column;
  2235. 21297   u16_t *keyrow;
  2236. 21298
  2237. 21299   if (scode == SLASH_SCAN && esc) return '/';   /* don't map numeric slash */
  2238. 21300
  2239. 21301   keyrow = &keymap[scode * MAP_COLS];
  2240. 21302
  2241. 21303   caps = shift;
  2242. 21304   if (numlock && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
  2243. 21305   if (capslock && (keyrow[0] & HASCAPS)) caps = !caps;
  2244. 21306
  2245. 21307   if (alt1 || alt2) {
  2246. 21308         column = 2;
  2247. 21309         if (control || alt2) column = 3;        /* Ctrl + Alt1 == Alt2 */
  2248. 21310         if (caps) column = 4;
  2249. 21311   } else {
  2250. 21312         column = 0;
  2251. 21313         if (caps) column = 1;
  2252. 21314         if (control) column = 5;
  2253. .Op 285 src/kernel/keyboard.c
  2254. 21315   }
  2255. 21316   return keyrow[column] & ~HASCAPS;
  2256. 21317 }
  2257. 21320 /*===========================================================================*
  2258. 21321  *                              kbd_hw_int                                   *
  2259. 21322  *===========================================================================*/
  2260. 21323 PRIVATE int kbd_hw_int(irq)
  2261. 21324 int irq;
  2262. 21325 {
  2263. 21326 /* A keyboard interrupt has occurred.  Process it. */
  2264. 21327
  2265. 21328   int code;
  2266. 21329   unsigned km;
  2267. 21330   register struct kb_s *kb;
  2268. 21331
  2269. 21332   /* Fetch the character from the keyboard hardware and acknowledge it. */
  2270. 21333   code = scan_keyboard();
  2271. 21334
  2272. 21335   /* The IBM keyboard interrupts twice per key, once when depressed, once when
  2273. 21336    * released.  Filter out the latter, ignoring all but the shift-type keys.
  2274. 21337    * The shift-type keys 29, 42, 54, 56, 58, and 69 must be processed normally.
  2275. 21338    */
  2276. 21339
  2277. 21340   if (code & 0200) {
  2278. 21341         /* A key has been released (high bit is set). */
  2279. 21342         km = map_key0(code & 0177);
  2280. 21343         if (km != CTRL && km != SHIFT && km != ALT && km != CALOCK
  2281. 21344                         && km != NLOCK && km != SLOCK && km != EXTKEY)
  2282. 21345                 return 1;
  2283. 21346   }
  2284. 21347
  2285. 21348   /* Store the character in memory so the task can get at it later. */
  2286. 21349   kb = kb_addr();
  2287. 21350   if (kb->icount < KB_IN_BYTES) {
  2288. 21351         *kb->ihead++ = code;
  2289. 21352         if (kb->ihead == kb->ibuf + KB_IN_BYTES) kb->ihead = kb->ibuf;
  2290. 21353         kb->icount++;
  2291. 21354         tty_table[current].tty_events = 1;
  2292. 21355         force_timeout();
  2293. 21356   }
  2294. 21357   /* Else it doesn't fit - discard it. */
  2295. 21358   return 1;     /* Reenable keyboard interrupt */
  2296. 21359 }
  2297. 21362 /*==========================================================================*
  2298. 21363  *                              kb_read                                     *
  2299. 21364  *==========================================================================*/
  2300. 21365 PRIVATE void kb_read(tp)
  2301. 21366 tty_t *tp;
  2302. 21367 {
  2303. 21368 /* Process characters from the circular keyboard buffer. */
  2304. 21369
  2305. 21370   struct kb_s *kb;
  2306. 21371   char buf[3];
  2307. 21372   int scode;
  2308. 21373   unsigned ch;
  2309. 21374
  2310. .Ep 286 src/kernel/keyboard.c
  2311. 21375   kb = kb_addr();
  2312. 21376   tp = &tty_table[current];             /* always use the current console */
  2313. 21377
  2314. 21378   while (kb->icount > 0) {
  2315. 21379         scode = *kb->itail++;                   /* take one key scan code */
  2316. 21380         if (kb->itail == kb->ibuf + KB_IN_BYTES) kb->itail = kb->ibuf;
  2317. 21381         lock();
  2318. 21382         kb->icount--;
  2319. 21383         unlock();
  2320. 21384
  2321. 21385         /* Function keys are being used for debug dumps. */
  2322. 21386         if (func_key(scode)) continue;
  2323. 21387
  2324. 21388         /* Perform make/break processing. */
  2325. 21389         ch = make_break(scode);
  2326. 21390
  2327. 21391         if (ch <= 0xFF) {
  2328. 21392                 /* A normal character. */
  2329. 21393                 buf[0] = ch;
  2330. 21394                 (void) in_process(tp, buf, 1);
  2331. 21395         } else
  2332. 21396         if (HOME <= ch && ch <= INSRT) {
  2333. 21397                 /* An ASCII escape sequence generated by the numeric pad. */
  2334. 21398                 buf[0] = ESC;
  2335. 21399                 buf[1] = '[';
  2336. 21400                 buf[2] = numpad_map[ch - HOME];
  2337. 21401                 (void) in_process(tp, buf, 3);
  2338. 21402         } else
  2339. 21403         if (ch == ALEFT) {
  2340. 21404                 /* Choose lower numbered console as current console. */
  2341. 21405                 select_console(current - 1);
  2342. 21406         } else
  2343. 21407         if (ch == ARIGHT) {
  2344. 21408                 /* Choose higher numbered console as current console. */
  2345. 21409                 select_console(current + 1);
  2346. 21410         } else
  2347. 21411         if (AF1 <= ch && ch <= AF12) {
  2348. 21412                 /* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
  2349. 21413                 select_console(ch - AF1);
  2350. 21414         }
  2351. 21415   }
  2352. 21416 }
  2353. 21419 /*===========================================================================*
  2354. 21420  *                              make_break                                   *
  2355. 21421  *===========================================================================*/
  2356. 21422 PRIVATE unsigned make_break(scode)
  2357. 21423 int scode;                      /* scan code of key just struck or released */
  2358. 21424 {
  2359. 21425 /* This routine can handle keyboards that interrupt only on key depression,
  2360. 21426  * as well as keyboards that interrupt on key depression and key release.
  2361. 21427  * For efficiency, the interrupt routine filters out most key releases.
  2362. 21428  */
  2363. 21429   int ch, make;
  2364. 21430   static int CAD_count = 0;
  2365. 21431
  2366. 21432   /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
  2367. 21433    * be better done in keyboard() in case TTY is hung, except control and
  2368. 21434    * alt are set in the high level code.
  2369. .Op 287 src/kernel/keyboard.c
  2370. 21435    */
  2371. 21436   if (control && (alt1 || alt2) && scode == DEL_SCAN)
  2372. 21437   {
  2373. 21438         if (++CAD_count == 3) wreboot(RBT_HALT);
  2374. 21439         cause_sig(INIT_PROC_NR, SIGABRT);
  2375. 21440         return -1;
  2376. 21441   }
  2377. 21442
  2378. 21443   /* High-order bit set on key release. */
  2379. 21444   make = (scode & 0200 ? 0 : 1);        /* 0 = release, 1 = press */
  2380. 21445
  2381. 21446   ch = map_key(scode & 0177);           /* map to ASCII */
  2382. 21447
  2383. 21448   switch (ch) {
  2384. 21449         case CTRL:
  2385. 21450                 control = make;
  2386. 21451                 ch = -1;
  2387. 21452                 break;
  2388. 21453         case SHIFT:
  2389. 21454                 shift = make;
  2390. 21455                 ch = -1;
  2391. 21456                 break;
  2392. 21457         case ALT:
  2393. 21458                 if (make) {
  2394. 21459                         if (esc) alt2 = 1; else alt1 = 1;
  2395. 21460                 } else {
  2396. 21461                         alt1 = alt2 = 0;
  2397. 21462                 }
  2398. 21463                 ch = -1;
  2399. 21464                 break;
  2400. 21465         case CALOCK:
  2401. 21466                 if (make && caps_off) {
  2402. 21467                         capslock = 1 - capslock;
  2403. 21468                         set_leds();
  2404. 21469                 }
  2405. 21470                 caps_off = 1 - make;
  2406. 21471                 ch = -1;
  2407. 21472                 break;
  2408. 21473         case NLOCK:
  2409. 21474                 if (make && num_off) {
  2410. 21475                         numlock = 1 - numlock;
  2411. 21476                         set_leds();
  2412. 21477                 }
  2413. 21478                 num_off = 1 - make;
  2414. 21479                 ch = -1;
  2415. 21480                 break;
  2416. 21481         case SLOCK:
  2417. 21482                 if (make & slock_off) {
  2418. 21483                         slock = 1 - slock;
  2419. 21484                         set_leds();
  2420. 21485                 }
  2421. 21486                 slock_off = 1 - make;
  2422. 21487                 ch = -1;
  2423. 21488                 break;
  2424. 21489         case EXTKEY:
  2425. 21490                 esc = 1;
  2426. 21491                 return(-1);
  2427. 21492         default:
  2428. 21493                 if (!make) ch = -1;
  2429. 21494   }
  2430. .Ep 288 src/kernel/keyboard.c
  2431. 21495   esc = 0;
  2432. 21496   return(ch);
  2433. 21497 }
  2434. 21500 /*===========================================================================*
  2435. 21501  *                              set_leds                                     *
  2436. 21502  *===========================================================================*/
  2437. 21503 PRIVATE void set_leds()
  2438. 21504 {
  2439. 21505 /* Set the LEDs on the caps lock and num lock keys */
  2440. 21506
  2441. 21507   unsigned leds;
  2442. 21508
  2443. 21509   if (!pc_at) return;   /* PC/XT doesn't have LEDs */
  2444. 21510
  2445. 21511   /* encode LED bits */
  2446. 21512   leds = (slock << 0) | (numlock << 1) | (capslock << 2);
  2447. 21513
  2448. 21514   kb_wait();                    /* wait for buffer empty  */
  2449. 21515   out_byte(KEYBD, LED_CODE);    /* prepare keyboard to accept LED values */
  2450. 21516   kb_ack();                     /* wait for ack response  */
  2451. 21517
  2452. 21518   kb_wait();                    /* wait for buffer empty  */
  2453. 21519   out_byte(KEYBD, leds);        /* give keyboard LED values */
  2454. 21520   kb_ack();                     /* wait for ack response  */
  2455. 21521 }
  2456. 21524 /*==========================================================================*
  2457. 21525  *                              kb_wait                                     *
  2458. 21526  *==========================================================================*/
  2459. 21527 PRIVATE int kb_wait()
  2460. 21528 {
  2461. 21529 /* Wait until the controller is ready; return zero if this times out. */
  2462. 21530
  2463. 21531   int retries;
  2464. 21532
  2465. 21533   retries = MAX_KB_BUSY_RETRIES + 1;
  2466. 21534   while (--retries != 0 && in_byte(KB_STATUS) & KB_BUSY)
  2467. 21535         ;                       /* wait until not busy */
  2468. 21536   return(retries);              /* nonzero if ready */
  2469. 21537 }
  2470. 21540 /*==========================================================================*
  2471. 21541  *                              kb_ack                                      *
  2472. 21542  *==========================================================================*/
  2473. 21543 PRIVATE int kb_ack()
  2474. 21544 {
  2475. 21545 /* Wait until kbd acknowledges last command; return zero if this times out. */
  2476. 21546
  2477. 21547   int retries;
  2478. 21548
  2479. 21549   retries = MAX_KB_ACK_RETRIES + 1;
  2480. 21550   while (--retries != 0 && in_byte(KEYBD) != KB_ACK)
  2481. 21551         ;                       /* wait for ack */
  2482. 21552   return(retries);              /* nonzero if ack received */
  2483. 21553 }
  2484. .Op 289 src/kernel/keyboard.c
  2485. 21555 /*===========================================================================*
  2486. 21556  *                              kb_init                                      *
  2487. 21557  *===========================================================================*/
  2488. 21558 PUBLIC void kb_init(tp)
  2489. 21559 tty_t *tp;
  2490. 21560 {
  2491. 21561 /* Initialize the keyboard driver. */
  2492. 21562
  2493. 21563   register struct kb_s *kb;
  2494. 21564
  2495. 21565   /* Input function. */
  2496. 21566   tp->tty_devread = kb_read;
  2497. 21567
  2498. 21568   kb = kb_addr();
  2499. 21569
  2500. 21570   /* Set up input queue. */
  2501. 21571   kb->ihead = kb->itail = kb->ibuf;
  2502. 21572
  2503. 21573   /* Set initial values. */
  2504. 21574   caps_off = 1;
  2505. 21575   num_off = 1;
  2506. 21576   slock_off = 1;
  2507. 21577   esc = 0;
  2508. 21578
  2509. 21579   set_leds();                   /* turn off numlock led */
  2510. 21580
  2511. 21581   scan_keyboard();              /* stop lockup from leftover keystroke */
  2512. 21582
  2513. 21583   put_irq_handler(KEYBOARD_IRQ, kbd_hw_int);    /* set the interrupt handler */
  2514. 21584   enable_irq(KEYBOARD_IRQ);     /* safe now everything initialised! */
  2515. 21585 }
  2516. 21588 /*===========================================================================*
  2517. 21589  *                              kbd_loadmap                                  *
  2518. 21590  *===========================================================================*/
  2519. 21591 PUBLIC int kbd_loadmap(user_phys)
  2520. 21592 phys_bytes user_phys;
  2521. 21593 {
  2522. 21594 /* Load a new keymap. */
  2523. 21595
  2524. 21596   phys_copy(user_phys, vir2phys(keymap), (phys_bytes) sizeof(keymap));
  2525. 21597   return(OK);
  2526. 21598 }
  2527. 21601 /*===========================================================================*
  2528. 21602  *                              func_key                                     *
  2529. 21603  *===========================================================================*/
  2530. 21604 PRIVATE int func_key(scode)
  2531. 21605 int scode;                      /* scan code for a function key */
  2532. 21606 {
  2533. 21607 /* This procedure traps function keys for debugging and control purposes. */
  2534. 21608
  2535. 21609   unsigned code;
  2536. 21610
  2537. 21611   code = map_key0(scode);                       /* first ignore modifiers */
  2538. 21612   if (code < F1 || code > F12) return(FALSE);   /* not our job */
  2539. 21613
  2540. 21614   switch (map_key(scode)) {                     /* include modifiers */
  2541. .Ep 290 src/kernel/keyboard.c
  2542. 21615
  2543. 21616   case F1:      p_dmp(); break;         /* print process table */
  2544. 21617   case F2:      map_dmp(); break;       /* print memory map */
  2545. 21618   case F3:      toggle_scroll(); break; /* hardware vs. software scrolling */
  2546. 21619
  2547. 21620 #if ENABLE_NETWORKING
  2548. 21621   case F5:      dp_dump(); break;               /* network statistics */
  2549. 21622 #endif
  2550. 21623   case CF7:     sigchar(&tty_table[CONSOLE], SIGQUIT); break;
  2551. 21624   case CF8:     sigchar(&tty_table[CONSOLE], SIGINT); break;
  2552. 21625   case CF9:     sigchar(&tty_table[CONSOLE], SIGKILL); break;
  2553. 21626   default:      return(FALSE);
  2554. 21627   }
  2555. 21628   return(TRUE);
  2556. 21629 }
  2557. 21632 /*==========================================================================*
  2558. 21633  *                              scan_keyboard                               *
  2559. 21634  *==========================================================================*/
  2560. 21635 PRIVATE int scan_keyboard()
  2561. 21636 {
  2562. 21637 /* Fetch the character from the keyboard hardware and acknowledge it. */
  2563. 21638
  2564. 21639   int code;
  2565. 21640   int val;
  2566. 21641
  2567. 21642   code = in_byte(KEYBD);        /* get the scan code for the key struck */
  2568. 21643   val = in_byte(PORT_B);        /* strobe the keyboard to ack the char */
  2569. 21644   out_byte(PORT_B, val | KBIT); /* strobe the bit high */
  2570. 21645   out_byte(PORT_B, val);        /* now strobe it low */
  2571. 21646   return code;
  2572. 21647 }
  2573. 21650 /*==========================================================================*
  2574. 21651  *                              wreboot                                     *
  2575. 21652  *==========================================================================*/
  2576. 21653 PUBLIC void wreboot(how)
  2577. 21654 int how;                /* 0 = halt, 1 = reboot, 2 = panic!, ... */
  2578. 21655 {
  2579. 21656 /* Wait for keystrokes for printing debugging info and reboot. */
  2580. 21657
  2581. 21658   int quiet, code;
  2582. 21659   static u16_t magic = MEMCHECK_MAG;
  2583. 21660   struct tasktab *ttp;
  2584. 21661
  2585. 21662   /* Mask all interrupts. */
  2586. 21663   out_byte(INT_CTLMASK, ~0);
  2587. 21664
  2588. 21665   /* Tell several tasks to stop. */
  2589. 21666   cons_stop();
  2590. 21667 #if ENABLE_NETWORKING
  2591. 21668   dp8390_stop();
  2592. 21669 #endif
  2593. 21670   floppy_stop();
  2594. 21671   clock_stop();
  2595. 21672
  2596. 21673   if (how == RBT_HALT) {
  2597. 21674         printf("System Haltedn");
  2598. .Op 291 src/kernel/keyboard.c
  2599. 21675         if (!mon_return) how = RBT_PANIC;
  2600. 21676   }
  2601. 21677
  2602. 21678   if (how == RBT_PANIC) {
  2603. 21679         /* A panic! */
  2604. 21680         printf("Hit ESC to reboot, F-keys for debug dumpsn");
  2605. 21681
  2606. 21682         (void) scan_keyboard(); /* ack any old input */
  2607. 21683         quiet = scan_keyboard();/* quiescent value (0 on PC, last code on AT)*/
  2608. 21684         for (;;) {
  2609. 21685                 milli_delay(100);       /* pause for a decisecond */
  2610. 21686                 code = scan_keyboard();
  2611. 21687                 if (code != quiet) {
  2612. 21688                         /* A key has been pressed. */
  2613. 21689                         if (code == ESC_SCAN) break; /* reboot if ESC typed */
  2614. 21690                         (void) func_key(code);       /* process function key */
  2615. 21691                         quiet = scan_keyboard();
  2616. 21692                 }
  2617. 21693         }
  2618. 21694         how = RBT_REBOOT;
  2619. 21695   }
  2620. 21696
  2621. 21697   if (how == RBT_REBOOT) printf("Rebootingn");
  2622. 21698
  2623. 21699   if (mon_return && how != RBT_RESET) {
  2624. 21700         /* Reinitialize the interrupt controllers to the BIOS defaults. */
  2625. 21701         intr_init(0);
  2626. 21702         out_byte(INT_CTLMASK, 0);
  2627. 21703         out_byte(INT2_CTLMASK, 0);
  2628. 21704
  2629. 21705         /* Return to the boot monitor. */
  2630. 21706         if (how == RBT_HALT) {
  2631. 21707                 reboot_code = vir2phys("");
  2632. 21708         } else
  2633. 21709         if (how == RBT_REBOOT) {
  2634. 21710                 reboot_code = vir2phys("delay;boot");
  2635. 21711         }
  2636. 21712         level0(monitor);
  2637. 21713   }
  2638. 21714
  2639. 21715   /* Stop BIOS memory test. */
  2640. 21716   phys_copy(vir2phys(&magic), (phys_bytes) MEMCHECK_ADR,
  2641. 21717                                                 (phys_bytes) sizeof(magic));
  2642. 21718
  2643. 21719   if (protected_mode) {
  2644. 21720         /* Use the AT keyboard controller to reset the processor.
  2645. 21721          * The A20 line is kept enabled in case this code is ever
  2646. 21722          * run from extended memory, and because some machines
  2647. 21723          * appear to drive the fake A20 high instead of low just
  2648. 21724          * after reset, leading to an illegal opode trap.  This bug
  2649. 21725          * is more of a problem if the fake A20 is in use, as it
  2650. 21726          * would be if the keyboard reset were used for real mode.
  2651. 21727          */
  2652. 21728         kb_wait();
  2653. 21729         out_byte(KB_COMMAND,
  2654. 21730                  KB_PULSE_OUTPUT | (0x0F & ~(KB_GATE_A20 | KB_RESET)));
  2655. 21731         milli_delay(10);
  2656. 21732
  2657. 21733         /* If the nice method fails then do a reset.  In protected
  2658. 21734          * mode this means a processor shutdown.
  2659. .Ep 292 src/kernel/keyboard.c
  2660. 21735          */
  2661. 21736         printf("Hard reset...n");
  2662. 21737         milli_delay(250);
  2663. 21738   }
  2664. 21739   /* In real mode, jumping to the reset address is good enough. */
  2665. 21740   level0(reset);
  2666. 21741 }
  2667. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2668. src/kernel/main.c    
  2669. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2670. 21800 /* This file contains the main program of MINIX.  The routine main()
  2671. 21801  * initializes the system and starts the ball rolling by setting up the proc
  2672. 21802  * table, interrupt vectors, and scheduling each task to run to initialize
  2673. 21803  * itself.
  2674. 21804  *
  2675. 21805  * The entries into this file are:
  2676. 21806  *   main:              MINIX main program
  2677. 21807  *   panic:             abort MINIX due to a fatal error
  2678. 21808  */
  2679. 21809
  2680. 21810 #include "kernel.h"
  2681. 21811 #include <signal.h>
  2682. 21812 #include <unistd.h>
  2683. 21813 #include <minix/callnr.h>
  2684. 21814 #include <minix/com.h>
  2685. 21815 #include "proc.h"
  2686. 21816
  2687. 21817
  2688. 21818 /*===========================================================================*
  2689. 21819  *                                   main                                    *
  2690. 21820  *===========================================================================*/
  2691. 21821 PUBLIC void main()
  2692. 21822 {
  2693. 21823 /* Start the ball rolling. */
  2694. 21824
  2695. 21825   register struct proc *rp;
  2696. 21826   register int t;
  2697. 21827   int sizeindex;
  2698. 21828   phys_clicks text_base;
  2699. 21829   vir_clicks text_clicks;
  2700. 21830   vir_clicks data_clicks;
  2701. 21831   phys_bytes phys_b;
  2702. 21832   reg_t ktsb;                   /* kernel task stack base */
  2703. 21833   struct memory *memp;
  2704. 21834   struct tasktab *ttp;
  2705. 21835
  2706. 21836   /* Initialize the interrupt controller. */
  2707. 21837   intr_init(1);
  2708. 21838
  2709. 21839   /* Interpret memory sizes. */
  2710. 21840   mem_init();
  2711. 21841
  2712. 21842   /* Clear the process table.
  2713. 21843    * Set up mappings for proc_addr() and proc_number() macros.
  2714. 21844    */
  2715. .Op 293 src/kernel/main.c
  2716. 21845   for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
  2717. 21846         rp->p_flags = P_SLOT_FREE;
  2718. 21847         rp->p_nr = t;           /* proc number from ptr */
  2719. 21848         (pproc_addr + NR_TASKS)[t] = rp;        /* proc ptr from number */
  2720. 21849   }
  2721. 21850
  2722. 21851   /* Set up proc table entries for tasks and servers.  The stacks of the
  2723. 21852    * kernel tasks are initialized to an array in data space.  The stacks
  2724. 21853    * of the servers have been added to the data segment by the monitor, so
  2725. 21854    * the stack pointer is set to the end of the data segment.  All the
  2726. 21855    * processes are in low memory on the 8086.  On the 386 only the kernel
  2727. 21856    * is in low memory, the rest if loaded in extended memory.
  2728. 21857    */
  2729. 21858
  2730. 21859   /* Task stacks. */
  2731. 21860   ktsb = (reg_t) t_stack;
  2732. 21861
  2733. 21862   for (t = -NR_TASKS; t <= LOW_USER; ++t) {
  2734. 21863         rp = proc_addr(t);                      /* t's process slot */
  2735. 21864         ttp = &tasktab[t + NR_TASKS];           /* t's task attributes */
  2736. 21865         strcpy(rp->p_name, ttp->name);
  2737. 21866         if (t < 0) {
  2738. 21867                 if (ttp->stksize > 0) {
  2739. 21868                         rp->p_stguard = (reg_t *) ktsb;
  2740. 21869                         *rp->p_stguard = STACK_GUARD;
  2741. 21870                 }
  2742. 21871                 ktsb += ttp->stksize;
  2743. 21872                 rp->p_reg.sp = ktsb;
  2744. 21873                 text_base = code_base >> CLICK_SHIFT;
  2745. 21874                                         /* tasks are all in the kernel */
  2746. 21875                 sizeindex = 0;          /* and use the full kernel sizes */
  2747. 21876                 memp = &mem[0];         /* remove from this memory chunk */
  2748. 21877         } else {
  2749. 21878                 sizeindex = 2 * t + 2;  /* MM, FS, INIT have their own sizes */
  2750. 21879         }
  2751. 21880         rp->p_reg.pc = (reg_t) ttp->initial_pc;
  2752. 21881         rp->p_reg.psw = istaskp(rp) ? INIT_TASK_PSW : INIT_PSW;
  2753. 21882
  2754. 21883         text_clicks = sizes[sizeindex];
  2755. 21884         data_clicks = sizes[sizeindex + 1];
  2756. 21885         rp->p_map[T].mem_phys = text_base;
  2757. 21886         rp->p_map[T].mem_len  = text_clicks;
  2758. 21887         rp->p_map[D].mem_phys = text_base + text_clicks;
  2759. 21888         rp->p_map[D].mem_len  = data_clicks;
  2760. 21889         rp->p_map[S].mem_phys = text_base + text_clicks + data_clicks;
  2761. 21890         rp->p_map[S].mem_vir  = data_clicks;    /* empty - stack is in data */
  2762. 21891         text_base += text_clicks + data_clicks; /* ready for next, if server */
  2763. 21892         memp->size -= (text_base - memp->base);
  2764. 21893         memp->base = text_base;                 /* memory no longer free */
  2765. 21894
  2766. 21895         if (t >= 0) {
  2767. 21896                 /* Initialize the server stack pointer.  Take it down one word
  2768. 21897                  * to give crtso.s something to use as "argc".
  2769. 21898                  */
  2770. 21899                 rp->p_reg.sp = (rp->p_map[S].mem_vir +
  2771. 21900                                 rp->p_map[S].mem_len) << CLICK_SHIFT;
  2772. 21901                 rp->p_reg.sp -= sizeof(reg_t);
  2773. 21902         }
  2774. 21903
  2775. 21904 #if _WORD_SIZE == 4
  2776. .Ep 294 src/kernel/main.c
  2777. 21905         /* Servers are loaded in extended memory if in 386 mode. */
  2778. 21906         if (t < 0) {
  2779. 21907                 memp = &mem[1];
  2780. 21908                 text_base = 0x100000 >> CLICK_SHIFT;
  2781. 21909         }
  2782. 21910 #endif
  2783. 21911         if (!isidlehardware(t)) lock_ready(rp); /* IDLE, HARDWARE neveready */
  2784. 21912         rp->p_flags = 0;
  2785. 21913
  2786. 21914         alloc_segments(rp);
  2787. 21915   }
  2788. 21916
  2789. 21917   proc[NR_TASKS+INIT_PROC_NR].p_pid = 1;/* INIT of course has pid 1 */
  2790. 21918   bill_ptr = proc_addr(IDLE);           /* it has to point somewhere */
  2791. 21919   lock_pick_proc();
  2792. 21920
  2793. 21921   /* Now go to the assembly code to start running the current process. */
  2794. 21922   restart();
  2795. 21923 }
  2796. 21926 /*===========================================================================*
  2797. 21927  *                                   panic                                   *
  2798. 21928  *===========================================================================*/
  2799. 21929 PUBLIC void panic(s,n)
  2800. 21930 _CONST char *s;
  2801. 21931 int n;
  2802. 21932 {
  2803. 21933 /* The system has run aground of a fatal error.  Terminate execution.
  2804. 21934  * If the panic originated in MM or FS, the string will be empty and the
  2805. 21935  * file system already syncked.  If the panic originates in the kernel, we are
  2806. 21936  * kind of stuck.
  2807. 21937  */
  2808. 21938
  2809. 21939   if (*s != 0) {
  2810. 21940         printf("nKernel panic: %s",s);
  2811. 21941         if (n != NO_NUM) printf(" %d", n);
  2812. 21942         printf("n");
  2813. 21943   }
  2814. 21944   wreboot(RBT_PANIC);
  2815. 21945 }
  2816. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2817. src/kernel/mcd.c    
  2818. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2819. 22000 /* This file contains the driver for a Mitsumi cdrom controller.
  2820. 22001  *
  2821. 22002  * The file contains one entry point:
  2822. 22003  *
  2823. 22004  *   mcd_task:          main entry when system is brought up
  2824. 22005  *
  2825. 22006  *  Mar 30 1995                 Author: Michel R. Prevenier 
  2826. 22007  */
  2827. 22008
  2828. 22009
  2829. .Op 295 src/kernel/mcd.c