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

操作系统开发

开发平台:

C/C++

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