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

操作系统开发

开发平台:

WINDOWS

  1. 22010 #include "kernel.h"
  2. 22011 #include "driver.h"
  3. 22012 #include "drvlib.h"
  4. 22013 #include <minix/cdrom.h>
  5. 22014 #include <sys/ioctl.h>
  6. 22015
  7. 22016 #if ENABLE_MITSUMI_CDROM
  8. 22017
  9. 22018 #define MCD_DEBUG               0       /* debug level */
  10. 22019
  11. 22020 /* Default IRQ. */
  12. 22021 #define MCD_IRQ                 10
  13. 22022
  14. 22023 /* Default I/O ports (offset from base address */
  15. 22024 #define MCD_IO_BASE_ADDRESS     0x300   
  16. 22025 #define MCD_DATA_PORT           (mcd_io_base+0)
  17. 22026 #define MCD_FLAG_PORT           (mcd_io_base+1)
  18. 22027 #define MCD_CONTROL_PORT        (mcd_io_base+2)
  19. 22028
  20. 22029
  21. 22030 /* Miscellaneous constants. */
  22. 22031 #define MCD_SKIP                150     /* Skip first 150 blocks on cdrom */
  23. 22032 #define MCD_BLOCK_SIZE          2048    /* Block size in cooked mode */
  24. 22033 #define MCD_BLOCK_SHIFT         11      /* for division */
  25. 22034 #define MCD_BLOCK_MASK          2047    /* and remainder */
  26. 22035 #define BYTES_PER_SECTOR        2048    /* Nr. of bytes in a sector */
  27. 22036 #define SECTORS_PER_SECOND      75      /* Nr. of sectors in a second */
  28. 22037 #define SECONDS_PER_MINUTE      60      /* You never know, things change :-) */ 
  29. 22038 #define MCD_RETRIES             2       /* Number of retries for a command */
  30. 22039 #define REPLY_DELAY             5000    /* Count to wait for a reply */
  31. 22040 #define MAX_TRACKS              104     /* Maximum nr. of tracks */
  32. 22041 #define LEAD_OUT                0xAA    /* Lead out track is always 0xAA */
  33. 22042 #define SUB_PER_DRIVE   (NR_PARTITIONS * NR_PARTITIONS)
  34. 22043
  35. 22044
  36. 22045 /* Drive commands */
  37. 22046 #define MCD_GET_VOL_INFO        0x10    /* Read volume information */
  38. 22047 #define MCD_GET_Q_CHANNEL       0x20    /* Read q-channel information */
  39. 22048 #define MCD_GET_STATUS          0x40    /* Read status of drive */
  40. 22049 #define MCD_SET_MODE            0x50    /* Set transmission mode */
  41. 22050 #define MCD_RESET               0x60    /* Reset controller */
  42. 22051 #define MCD_STOP_AUDIO          0x70    /* Stop audio playing */
  43. 22052 #define MCD_SET_DRIVE_MODE      0xA0    /* Set drive mode */
  44. 22053 #define MCD_READ_FROM_TO        0xC0    /* Read from .. to .. */
  45. 22054 #define MCD_GET_VERSION         0xDC    /* Get version number */
  46. 22055 #define MCD_STOP                0xF0    /* Stop everything */
  47. 22056 #define MCD_EJECT               0xF6    /* Eject cd */
  48. 22057 #define MCD_PICKLE              0x04    /* Needed for newer drive models */
  49. 22058
  50. 22059
  51. 22060 /* Command bits for MCD_SET_MODE command */
  52. 22061 #define MCD_MUTE_DATA           0x01    /* 1 = Don't play back data as audio */
  53. 22062 #define MCD_GET_TOC             0x04    /* 0 = Get toc on next GET_Q_CHANNEL */
  54. 22063 #define MCD_ECC_MODE            0x20    /* 0 = Use secondary ecc */
  55. 22064 #define MCD_DATALENGTH          0x40    /* 0 = Read user data only */
  56. 22065 #define MCD_COOKED              (MCD_MUTE_DATA)
  57. 22066 #define MCD_TOC                 (MCD_MUTE_DATA | MCD_GET_TOC)   
  58. 22067
  59. 22068
  60. 22069 /* Status bits */
  61. .Ep 296 src/kernel/mcd.c
  62. 22070 #define MCD_CMD_ERROR           0x01    /* Command error */
  63. 22071 #define MCD_AUDIO_BUSY          0x02    /* Audio disk is playing */
  64. 22072 #define MCD_READ_ERROR          0x04    /* Read error */
  65. 22073 #define MCD_AUDIO_DISK          0x08    /* Audio disk is in */
  66. 22074 #define MCD_SPINNING            0x10    /* Motor is spinning */
  67. 22075 #define MCD_DISK_CHANGED        0x20    /* Disk has been removed or changed */
  68. 22076 #define MCD_DISK_IN             0x40    /* Disk is in */
  69. 22077 #define MCD_DOOR_OPEN           0x80    /* Door is open */
  70. 22078
  71. 22079 /* Flag bits */
  72. 22080 #define MCD_DATA_AVAILABLE      0x02    /* Data available */
  73. 22081 #define MCD_BUSY                0x04    /* Drive is busy */
  74. 22082
  75. 22083 /* Function prototypes */
  76. 22084 FORWARD _PROTOTYPE ( int mcd_init, (void));
  77. 22085 FORWARD _PROTOTYPE ( int c_handler, (int irq));
  78. 22086 FORWARD _PROTOTYPE ( int mcd_play_mss, (struct cd_play_mss));
  79. 22087 FORWARD _PROTOTYPE ( int mcd_play_tracks, (struct cd_play_track tracks));
  80. 22088 FORWARD _PROTOTYPE ( int mcd_stop, (void));
  81. 22089 FORWARD _PROTOTYPE ( int mcd_eject, (void));
  82. 22090 FORWARD _PROTOTYPE ( int mcd_pause, (void));
  83. 22091 FORWARD _PROTOTYPE ( int mcd_resume, (void));
  84. 22092 FORWARD _PROTOTYPE ( u8_t bin2bcd, (u8_t b));
  85. 22093 FORWARD _PROTOTYPE ( void bcd2bin, (u8_t *bcd));
  86. 22094 FORWARD _PROTOTYPE ( long mss2block, (u8_t *mss));
  87. 22095 FORWARD _PROTOTYPE ( void block2mss, (long block, u8_t *mss));
  88. 22096 FORWARD _PROTOTYPE ( int mcd_get_reply, (u8_t *reply, int delay));
  89. 22097 FORWARD _PROTOTYPE ( int mcd_get_status, (int f));
  90. 22098 FORWARD _PROTOTYPE ( int mcd_ready, (int delay));
  91. 22099 FORWARD _PROTOTYPE ( int mcd_data_ready, (int delay));
  92. 22100 FORWARD _PROTOTYPE ( int mcd_set_mode, (int mode));
  93. 22101 FORWARD _PROTOTYPE ( int mcd_send_command, (int command));
  94. 22102 FORWARD _PROTOTYPE ( int mcd_get_disk_info, (void));
  95. 22103 FORWARD _PROTOTYPE ( int mcd_read_q_channel, (struct cd_toc_entry *qc));
  96. 22104 FORWARD _PROTOTYPE ( int mcd_read_toc, (void));
  97. 22105 FORWARD _PROTOTYPE ( int ioctl_read_toc, (message *m_ptr));
  98. 22106 FORWARD _PROTOTYPE ( int ioctl_disk_info, (message *m_ptr));
  99. 22107 FORWARD _PROTOTYPE ( int ioctl_read_sub, (message *m_ptr));
  100. 22108 FORWARD _PROTOTYPE ( int ioctl_disk_info, (message *m_ptr));
  101. 22109 FORWARD _PROTOTYPE ( int ioctl_play_mss, (message *m_ptr));
  102. 22110 FORWARD _PROTOTYPE ( int ioctl_play_ti, (message *m_ptr));
  103. 22111 FORWARD _PROTOTYPE ( int mcd_open, (struct driver *dp, message *m_ptr));
  104. 22112 FORWARD _PROTOTYPE ( int mcd_close, (struct driver *dp, message *m_ptr));
  105. 22113 FORWARD _PROTOTYPE ( int mcd_ioctl, (struct driver *dp, message *m_ptr));
  106. 22114 FORWARD _PROTOTYPE ( char *mcd_name, (void));
  107. 22115 FORWARD _PROTOTYPE ( struct device *mcd_prepare, (int dev));
  108. 22116 FORWARD _PROTOTYPE ( int mcd_schedule, (int proc_nr, struct iorequest_s *iop));
  109. 22117 FORWARD _PROTOTYPE ( int mcd_finish, (void));
  110. 22118 FORWARD _PROTOTYPE ( void mcd_geometry, (struct partition *entry));
  111. 22119
  112. 22120
  113. 22121 /* Flags displaying current status of cdrom, used with the McdStatus variable */
  114. 22122 #define TOC_UPTODATE   0x001     /* Table of contents is up to date */
  115. 22123 #define INFO_UPTODATE  0x002     /* Disk info is up to date */
  116. 22124 #define DISK_CHANGED   0x004     /* Disk has changed */
  117. 22125 #define AUDIO_PLAYING  0x008     /* Cdrom is playing audio */
  118. 22126 #define AUDIO_PAUSED   0x010     /* Cdrom is paused (only audio) */
  119. 22127 #define AUDIO_DISK     0x020     /* Disk contains audio */
  120. 22128 #define DISK_ERROR     0x040     /* An error occured */
  121. 22129 #define NO_DISK        0x080     /* No disk in device */
  122. .Op 297 src/kernel/mcd.c
  123. 22130
  124. 22131 /* Entry points to this driver. */
  125. 22132 PRIVATE struct driver mcd_dtab = 
  126. 22133 {
  127. 22134 #if __minix_vmd
  128. 22135   NULL,         /* No private request buffer */
  129. 22136 #endif
  130. 22137   mcd_name,     /* Current device's name */
  131. 22138   mcd_open,     /* Open request read table of contents */
  132. 22139   mcd_close,    /* Release device */
  133. 22140   mcd_ioctl,    /* Do cdrom ioctls */
  134. 22141   mcd_prepare,  /* Prepare for I/O */
  135. 22142   mcd_schedule, /* Precompute blocks */
  136. 22143   mcd_finish,   /* Do the I/O */
  137. 22144   nop_cleanup,  /* No cleanup to do */
  138. 22145   mcd_geometry  /* Tell geometry */
  139. 22146 };
  140. 22147
  141. 22148
  142. 22149 PRIVATE struct trans 
  143. 22150 {
  144. 22151   struct iorequest_s *tr_iop;   /* Belongs to this I/O request */
  145. 22152   unsigned long tr_pos;         /* Byte position to transfer from */
  146. 22153   int tr_count;                 /* Byte count */
  147. 22154   phys_bytes tr_phys;           /* User physical address */
  148. 22155 } mcd_trans[NR_IOREQS];
  149. 22156
  150. 22157
  151. 22158 /* Globals */
  152. 22159 #if __minix_vmd
  153. 22160 PRIVATE int mcd_tasknr = ANY;
  154. 22161 #endif
  155. 22162 PRIVATE int mcd_avail;                  /* Set if Mitsumi device exists */
  156. 22163 PRIVATE int mcd_irq;                    /* Interrupt request line */
  157. 22164 PRIVATE int mcd_io_base;                /* I/O base register */
  158. 22165 PRIVATE struct device *mcd_dv;          /* Active partition */
  159. 22166 PRIVATE struct trans *mcd_tp;           /* Pointer to add transfer requests */
  160. 22167 PRIVATE unsigned mcd_count;             /* Number of bytes to transfer */
  161. 22168 PRIVATE unsigned long mcd_nextpos;      /* Next consecutive position on disk */
  162. 22169 PRIVATE struct device mcd_part[DEV_PER_DRIVE];
  163. 22170                                         /* Primary partitions: cd[0-4] */
  164. 22171 PRIVATE struct device mcd_subpart[SUB_PER_DRIVE];
  165. 22172                                         /* Subpartitions: cd[1-4][a-d] */
  166. 22173 PRIVATE int mcd_open_ct;                /* in-use count */
  167. 22174 PRIVATE int McdStatus = NO_DISK;        /* A new (or no) disk is inserted */ 
  168. 22175 PRIVATE struct cd_play_mss PlayMss;     /* Keep track of where we are if we
  169. 22176                                            pause, used by resume */ 
  170. 22177 PRIVATE struct cd_disk_info DiskInfo;   /* Contains toc header */  
  171. 22178 PRIVATE struct cd_toc_entry Toc[MAX_TRACKS];  /* Buffer for toc */
  172. 22179
  173. 22180
  174. 22181
  175. 22182 /*=========================================================================*
  176. 22183  *                              mcd_task                                   *
  177. 22184  *=========================================================================*/
  178. 22185 PUBLIC void mcd_task()
  179. 22186 {
  180. 22187   long v;
  181. 22188   static char var[] = "MCD";
  182. 22189   static char fmt[] = "x:d";
  183. .Ep 298 src/kernel/mcd.c
  184. 22190
  185. 22191 #if __minix_vmd
  186. 22192   mcd_tasknr = proc_number(proc_ptr);
  187. 22193 #endif
  188. 22194
  189. 22195   /* Configure I/O base and IRQ. */
  190. 22196   v = MCD_IO_BASE_ADDRESS;
  191. 22197   (void) env_parse(var, fmt, 0, &v, 0x000L, 0x3FFL);
  192. 22198   mcd_io_base = v;
  193. 22199
  194. 22200   v = MCD_IRQ;
  195. 22201   (void) env_parse(var, fmt, 0, &v, 0L, (long) NR_IRQ_VECTORS - 1);
  196. 22202   mcd_irq = v;
  197. 22203
  198. 22204   driver_task(&mcd_dtab);       /* Start driver task for cdrom */
  199. 22205 }
  200. 22208 /*=========================================================================*
  201. 22209  *                              mcd_open                                   *    
  202. 22210  *=========================================================================*/
  203. 22211 PRIVATE int mcd_open(dp, m_ptr)
  204. 22212 struct driver *dp;      /* pointer to this drive */
  205. 22213 message *m_ptr;         /* OPEN */
  206. 22214 {
  207. 22215   int i, status;
  208. 22216
  209. 22217   if (!mcd_avail && mcd_init() != OK) return EIO;
  210. 22218
  211. 22219   if (mcd_prepare(m_ptr->DEVICE) == NIL_DEV) return ENXIO;
  212. 22220
  213. 22221   /* A CD-ROM is read-only by definition. */
  214. 22222   if (m_ptr->COUNT & W_BIT) return EACCES;
  215. 22223
  216. 22224   if (mcd_open_ct == 0)
  217. 22225   {
  218. 22226     i = 20;
  219. 22227     for (;;) {
  220. 22228       if (mcd_get_status(1) == -1) return EIO;   /* set McdStatus flags */
  221. 22229       if (!(McdStatus & NO_DISK)) break;
  222. 22230       if (--i == 0) return EIO;
  223. 22231       milli_delay(100);
  224. 22232     }
  225. 22233
  226. 22234     /* Try to read the table of contents of the CD currently inserted */
  227. 22235     if ((status = mcd_read_toc()) != OK)  
  228. 22236       return status;
  229. 22237
  230. 22238     mcd_open_ct++;
  231. 22239
  232. 22240     /* fill in size of device (= nr. of bytes on the disk) */
  233. 22241     mcd_part[0].dv_base = 0;
  234. 22242     mcd_part[0].dv_size = 
  235. 22243      ((((unsigned long)DiskInfo.disk_length_mss[MINUTES] * SECONDS_PER_MINUTE
  236. 22244       + (unsigned long)DiskInfo.disk_length_mss[SECONDS]) * SECTORS_PER_SECOND)
  237. 22245       + (unsigned long)DiskInfo.disk_length_mss[SECTOR]) * BYTES_PER_SECTOR; 
  238. 22246
  239. 22247 #if MCD_DEBUG >= 1
  240. 22248     printf("cd size: %lun", mcd_part[0].dv_size);
  241. 22249 #endif
  242. .Op 299 src/kernel/mcd.c
  243. 22250
  244. 22251     /* Partition the disk. */
  245. 22252     partition(&mcd_dtab, 0, P_PRIMARY);
  246. 22253   }
  247. 22254   return OK;
  248. 22255 }
  249. 22258 /*=========================================================================*
  250. 22259  *                              mcd_close                                  *    
  251. 22260  *=========================================================================*/
  252. 22261 PRIVATE int mcd_close(dp, m_ptr)
  253. 22262 struct driver *dp;      /* pointer to this drive */
  254. 22263 message *m_ptr;         /* CLOSE */
  255. 22264 {
  256. 22265   /* One less reference to the device */
  257. 22266
  258. 22267   mcd_open_ct--;
  259. 22268   return OK;
  260. 22269 }
  261. 22272 /*=========================================================================*
  262. 22273  *                              mcd_name                                   *    
  263. 22274  *=========================================================================*/
  264. 22275 PRIVATE char *mcd_name()
  265. 22276 {
  266. 22277   /* Return a name for the device */
  267. 22278
  268. 22279   return "cd0";
  269. 22280 }
  270. 22283 /*=========================================================================*
  271. 22284  *                              mcd_ioctl                                  *    
  272. 22285  *=========================================================================*/
  273. 22286 PRIVATE int mcd_ioctl(dp, m_ptr)
  274. 22287 struct driver *dp;      /* pointer to the drive */
  275. 22288 message *m_ptr;         /* contains ioctl command */
  276. 22289 {
  277. 22290   /* Perform the ioctl request */
  278. 22291
  279. 22292   int status;
  280. 22293
  281. 22294   if (mcd_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  282. 22295
  283. 22296   mcd_get_status(1);    /* Update the status flags */
  284. 22297   if ((McdStatus & NO_DISK) && m_ptr->REQUEST != CDIOEJECT)
  285. 22298     return EIO;
  286. 22299
  287. 22300   switch(m_ptr->REQUEST)
  288. 22301   {
  289. 22302     case CDIOPLAYMSS:     status = ioctl_play_mss(m_ptr);break;
  290. 22303     case CDIOPLAYTI:      status = ioctl_play_ti(m_ptr);break;
  291. 22304     case CDIOREADTOCHDR:  status = ioctl_disk_info(m_ptr);break;
  292. 22305     case CDIOREADTOC:     status = ioctl_read_toc(m_ptr);break;
  293. 22306     case CDIOREADSUBCH:   status = ioctl_read_sub(m_ptr);break;
  294. 22307     case CDIOSTOP:        status = mcd_stop();break;
  295. 22308     case CDIOPAUSE:       status = mcd_pause();break;
  296. 22309     case CDIORESUME:      status = mcd_resume();break;
  297. .Ep 300 src/kernel/mcd.c
  298. 22310     case CDIOEJECT:       status = mcd_eject();break;
  299. 22311     default:              status = do_diocntl(dp, m_ptr);
  300. 22312   }
  301. 22313   return status;
  302. 22314 }
  303. 22317 /*=========================================================================*
  304. 22318  *                              mcd_get_reply                              *    
  305. 22319  *=========================================================================*/
  306. 22320 PRIVATE int mcd_get_reply(reply, delay)
  307. 22321 u8_t *reply;            /* variable to put reply in */
  308. 22322 int delay;              /* count to wait for the reply */
  309. 22323 {
  310. 22324   /* Get a reply from the drive */
  311. 22325
  312. 22326   if (mcd_ready(delay) != OK) return EIO;           /* wait for drive to 
  313. 22327                                                        become available */
  314. 22328   *reply = in_byte(MCD_DATA_PORT);      /* get the reply */
  315. 22329   return OK;
  316. 22330 }
  317. 22333 /*=========================================================================*
  318. 22334  *                              mcd_ready                                  *    
  319. 22335  *=========================================================================*/
  320. 22336 PRIVATE int mcd_ready(delay)
  321. 22337 int delay;   /* count to wait for drive to become available again */
  322. 22338 {
  323. 22339   /* Wait for drive to become available */
  324. 22340
  325. 22341   struct milli_state ms;
  326. 22342
  327. 22343   milli_start(&ms);
  328. 22344   do
  329. 22345   {
  330. 22346     if (!(in_byte(MCD_FLAG_PORT) & MCD_BUSY)) return OK; /* OK, drive ready */
  331. 22347   } while(milli_elapsed(&ms) < delay);
  332. 22348
  333. 22349   return EIO; /* Timeout */
  334. 22350 }
  335. 22353 /*=========================================================================*
  336. 22354  *                              mcd_data_ready                             *    
  337. 22355  *=========================================================================*/
  338. 22356 PRIVATE int mcd_data_ready(delay)
  339. 22357 int delay;      /* count to wait for the data */
  340. 22358 {
  341. 22359   /* Wait for the drive to get the data */
  342. 22360
  343. 22361   struct milli_state ms;
  344. 22362
  345. 22363   milli_start(&ms);
  346. 22364   do
  347. 22365   {
  348. 22366     if (!(in_byte(MCD_FLAG_PORT) & 2)) return OK; /* OK, data is there */
  349. 22367   } while(milli_elapsed(&ms) < delay);
  350. 22368
  351. 22369   return EIO;  /* Timeout */
  352. .Op 301 src/kernel/mcd.c
  353. 22370 }
  354. 22373 /*=========================================================================*
  355. 22374  *                              mcd_get_status                             *    
  356. 22375  *=========================================================================*/
  357. 22376 PRIVATE int mcd_get_status(f)
  358. 22377 int f;          /* flag */
  359. 22378 {
  360. 22379   /* Return status info from the drive and update the global McdStatus */
  361. 22380
  362. 22381   u8_t status;
  363. 22382
  364. 22383   /* If f = 1, we first send a get_status command, otherwise we just get
  365. 22384      the status info from the drive */ 
  366. 22385
  367. 22386   if (f) out_byte(MCD_DATA_PORT, MCD_GET_STATUS);        /* Try to get status */
  368. 22387   if (mcd_get_reply(&status,REPLY_DELAY) != OK) return -1; 
  369. 22388
  370. 22389   McdStatus &= ~(NO_DISK | DISK_CHANGED | DISK_ERROR);
  371. 22390
  372. 22391   /* Fill in the McdStatus variable */
  373. 22392   if (status & MCD_DOOR_OPEN ||
  374. 22393      !(status & MCD_DISK_IN))         McdStatus = NO_DISK;  
  375. 22394   else if (status & MCD_DISK_CHANGED) McdStatus = DISK_CHANGED; 
  376. 22395   else if (status & MCD_READ_ERROR ||
  377. 22396            status & MCD_CMD_ERROR)    McdStatus = DISK_ERROR; 
  378. 22397   else 
  379. 22398   {
  380. 22399     if (status & MCD_AUDIO_DISK) 
  381. 22400     {
  382. 22401       McdStatus |= AUDIO_DISK;
  383. 22402       if (!(status & MCD_AUDIO_BUSY)) McdStatus &= ~(AUDIO_PLAYING); 
  384. 22403       else McdStatus |= AUDIO_PLAYING;
  385. 22404     }
  386. 22405   }
  387. 22406 #if MCD_DEBUG >= 3
  388. 22407   printf("mcd_get_status(%d) = %02x, McdStatus = %02xn",
  389. 22408         f, status, McdStatus);
  390. 22409 #endif
  391. 22410   return status;        /* Return status */
  392. 22411 }
  393. 22414 /*=========================================================================*
  394. 22415  *                              mcd_set_mode                               *    
  395. 22416  *=========================================================================*/
  396. 22417 PRIVATE int mcd_set_mode(mode)
  397. 22418 int mode; /* new drive mode */
  398. 22419 {
  399. 22420   /* Set drive mode */
  400. 22421
  401. 22422   int i;
  402. 22423
  403. 22424   for (i = 0; i < MCD_RETRIES; i++)
  404. 22425   {
  405. 22426     out_byte(MCD_DATA_PORT, MCD_SET_MODE); /* Send set mode command */
  406. 22427     out_byte(MCD_DATA_PORT, mode);         /* Send which mode */
  407. 22428     if (mcd_get_status(0) != -1 &&
  408. 22429          !(McdStatus & DISK_ERROR)) break; 
  409. .Ep 302 src/kernel/mcd.c
  410. 22430   }
  411. 22431   if (i == MCD_RETRIES) return EIO;        /* Operation failed */
  412. 22432
  413. 22433   return OK; /* Operation succeeded */
  414. 22434 }
  415. 22437 /*=========================================================================*
  416. 22438  *                              mcd_send_command                           *    
  417. 22439  *=========================================================================*/
  418. 22440 PRIVATE int mcd_send_command(command)
  419. 22441 int command;    /* command to send */
  420. 22442 {
  421. 22443   int i;
  422. 22444
  423. 22445   for (i = 0; i < MCD_RETRIES; i++)
  424. 22446   {
  425. 22447     out_byte(MCD_DATA_PORT, command);      /* send command */
  426. 22448     if (mcd_get_status(0) != -1 && 
  427. 22449          !(McdStatus & DISK_ERROR)) break; 
  428. 22450   }
  429. 22451   if (i == MCD_RETRIES) return EIO;        /* operation failed */
  430. 22452
  431. 22453   return OK;
  432. 22454 }
  433. 22457 /*=========================================================================*
  434. 22458  *                              mcd_init                                   *    
  435. 22459  *=========================================================================*/
  436. 22460 PRIVATE int mcd_init()
  437. 22461 {
  438. 22462   /* Initialize the drive and get the version bytes, this is done only
  439. 22463      once when the system gets up. We can't use mcd_ready because
  440. 22464      the clock task is not available yet.
  441. 22465    */
  442. 22466
  443. 22467   u8_t version[3];
  444. 22468   int i;
  445. 22469   u32_t n;
  446. 22470   struct milli_state ms;
  447. 22471
  448. 22472   /* Reset the flag port and remove all pending data, if we do
  449. 22473    * not do this properly the drive won't cooperate.
  450. 22474    */
  451. 22475   out_byte(MCD_FLAG_PORT, 0x00);        
  452. 22476   for (n = 0; n < 1000000; n++)
  453. 22477     (void) in_byte(MCD_FLAG_PORT);
  454. 22478
  455. 22479   /* Now see if the drive will report its status */
  456. 22480   if (mcd_get_status(1) == -1)
  457. 22481   {
  458. 22482     /* Too bad, drive will not listen */
  459. 22483     printf("%s: init failed, no Mitsumi cdrom presentn", mcd_name());
  460. 22484     return -1; 
  461. 22485   }
  462. 22486
  463. 22487   /* Find out drive version */
  464. 22488   out_byte(MCD_DATA_PORT, MCD_GET_VERSION);
  465. 22489   milli_start(&ms);
  466. .Op 303 src/kernel/mcd.c
  467. 22490   for (i = 0; i < 3; i++)
  468. 22491   {
  469. 22492     while (in_byte(MCD_FLAG_PORT) & MCD_BUSY)
  470. 22493     {
  471. 22494       if (milli_elapsed(&ms) >= 1000) 
  472. 22495       {
  473. 22496         printf("%s: can't get version of Mitsumi cdromn", mcd_name());
  474. 22497         return -1;
  475. 22498       }
  476. 22499     }
  477. 22500     version[i] = in_byte(MCD_DATA_PORT);
  478. 22501   }
  479. 22502  
  480. 22503   if (version[1] == 'D')
  481. 22504     printf("%s: Mitsumi FX001D CD-ROMn", mcd_name());
  482. 22505   else 
  483. 22506     printf("%s: Mitsumi CD-ROM version %02x%02x%02xn", mcd_name(), 
  484. 22507             version[0], version[1], version[2]);
  485. 22508
  486. 22509   /* Newer drive models need this */
  487. 22510   if (version[1] >= 4) out_byte(MCD_CONTROL_PORT, MCD_PICKLE);
  488. 22511
  489. 22512   /* Register interrupt vector and enable interrupt 
  490. 22513    * currently the interrupt is not used because
  491. 22514    * the controller isn't set up to do dma.  XXX
  492. 22515    */
  493. 22516   put_irq_handler(mcd_irq, c_handler);
  494. 22517   enable_irq(mcd_irq);
  495. 22518
  496. 22519   mcd_avail = 1;
  497. 22520   return OK;
  498. 22521 }
  499. 22524 /*=========================================================================*
  500. 22525  *                              c_handler                                  *    
  501. 22526  *=========================================================================*/
  502. 22527 PRIVATE int c_handler(irq)
  503. 22528 int irq;        /* irq number */
  504. 22529 {
  505. 22530   /* The interrupt handler, I never got an interrupt but its here just
  506. 22531    * in case...
  507. 22532    */
  508. 22533
  509. 22534   /* Send interrupt message to cdrom task */
  510. 22535 #if XXX
  511. 22536 #if __minix_vmd
  512. 22537   interrupt(mcd_tasknr);
  513. 22538 #else
  514. 22539   interrupt(CDROM);
  515. 22540 #endif
  516. 22541 #endif
  517. 22542
  518. 22543   return 1;
  519. 22544 }
  520. 22547 /*=========================================================================*
  521. 22548  *                              mcd_play_mss                               *    
  522. 22549  *=========================================================================*/
  523. .Ep 304 src/kernel/mcd.c
  524. 22550 PRIVATE int mcd_play_mss(mss)
  525. 22551 struct cd_play_mss mss;  /* from where to play minute:second.sector */
  526. 22552 {
  527. 22553   /* Command the drive to start playing at min:sec.sector */
  528. 22554
  529. 22555   int i;
  530. 22556
  531. 22557 #if MCD_DEBUG >= 1
  532. 22558   printf("Play_mss: begin: %02d:%02d.%02d  end: %02d:%02d.%02dn",
  533. 22559           mss.begin_mss[MINUTES], mss.begin_mss[SECONDS],
  534. 22560           mss.begin_mss[SECTOR], mss.end_mss[MINUTES], 
  535. 22561           mss.end_mss[SECONDS], mss.end_mss[SECTOR]); 
  536. 22562 #endif
  537. 22563
  538. 22564   for (i=0; i < MCD_RETRIES; i++)     /* Try it more than once */
  539. 22565   {
  540. 22566     lock();        /* No interrupts when we issue this command */
  541. 22567
  542. 22568     /* Send command with paramters to drive */
  543. 22569     out_byte(MCD_DATA_PORT, MCD_READ_FROM_TO);
  544. 22570     out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[MINUTES]));
  545. 22571     out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[SECONDS]));
  546. 22572     out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[SECTOR]));
  547. 22573     out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[MINUTES]));
  548. 22574     out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[SECONDS]));
  549. 22575     out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[SECTOR]));
  550. 22576
  551. 22577     unlock();      /* Enable interrupts again */
  552. 22578
  553. 22579     mcd_get_status(0);                    /* See if all went well */
  554. 22580     if (McdStatus & AUDIO_PLAYING) break; /* Ok, we're playing */
  555. 22581   }
  556. 22582
  557. 22583   if (i == MCD_RETRIES) return EIO;       /* Command failed */
  558. 22584
  559. 22585   /* keep in mind where we going in case of a future resume */
  560. 22586   PlayMss.end_mss[MINUTES] = mss.end_mss[MINUTES];
  561. 22587   PlayMss.end_mss[SECONDS] = mss.end_mss[SECONDS];
  562. 22588   PlayMss.end_mss[SECTOR] = mss.end_mss[SECTOR];
  563. 22589
  564. 22590   McdStatus &= ~(AUDIO_PAUSED);
  565. 22591
  566. 22592   return(OK);
  567. 22593 }
  568. 22596 /*=========================================================================*
  569. 22597  *                              mcd_play_tracks                            *    
  570. 22598  *=========================================================================*/
  571. 22599 PRIVATE int mcd_play_tracks(tracks)
  572. 22600 struct cd_play_track tracks;     /* which tracks to play */
  573. 22601 {
  574. 22602   /* Command the drive to play tracks */
  575. 22603   
  576. 22604   int i, err;
  577. 22605   struct cd_play_mss mss;
  578. 22606
  579. 22607 #if MCD_DEBUG >= 1
  580. 22608   printf("Play tracks: begin: %02d end: %02dn",
  581. 22609            tracks.begin_track, tracks.end_track);
  582. .Op 305 src/kernel/mcd.c
  583. 22610 #endif
  584. 22611
  585. 22612   /* First read the table of contents */
  586. 22613   if ((err = mcd_read_toc()) != OK) return err; 
  587. 22614  
  588. 22615   /* Check if parameters are valid */
  589. 22616   if (tracks.begin_track < DiskInfo.first_track ||
  590. 22617       tracks.end_track > DiskInfo.last_track ||
  591. 22618       tracks.begin_track > tracks.end_track)
  592. 22619     return EINVAL;
  593. 22620
  594. 22621
  595. 22622   /* Convert the track numbers to min:sec.sector */
  596. 22623   for (i=0; i<3; i++)
  597. 22624   {
  598. 22625     mss.begin_mss[i] = Toc[tracks.begin_track].position_mss[i]; 
  599. 22626     mss.end_mss[i] = Toc[tracks.end_track+1].position_mss[i]; 
  600. 22627   }
  601. 22628
  602. 22629   return(mcd_play_mss(mss));     /* Start playing */
  603. 22630 }
  604. 22633 /*=========================================================================*
  605. 22634  *                              mcd_get_disk_info                          *    
  606. 22635  *=========================================================================*/
  607. 22636 PRIVATE int mcd_get_disk_info()
  608. 22637 {
  609. 22638   /* Get disk info */
  610. 22639
  611. 22640   int i, err;
  612. 22641
  613. 22642   if (McdStatus & INFO_UPTODATE) return OK; /* No need to read info again */
  614. 22643
  615. 22644   /* Issue the get volume info command */
  616. 22645   if ((err = mcd_send_command(MCD_GET_VOL_INFO)) != OK) return err;
  617. 22646
  618. 22647   /* Fill global DiskInfo */
  619. 22648   for (i=0; i < sizeof(DiskInfo); i++) 
  620. 22649   {
  621. 22650     if ((err = mcd_get_reply((u8_t *)(&DiskInfo) + i, REPLY_DELAY)) !=OK)
  622. 22651       return err;
  623. 22652     bcd2bin((u8_t *)(&DiskInfo) + i);  
  624. 22653   }
  625. 22654
  626. 22655 #if MCD_DEBUG >= 1
  627. 22656   printf("Mitsumi disk info: first: %d last: %d first %02d:%02d.%02d length: %02d:%02d.%02dn",
  628. 22657       DiskInfo.first_track,
  629. 22658       DiskInfo.last_track,
  630. 22659       DiskInfo.first_track_mss[MINUTES],
  631. 22660       DiskInfo.first_track_mss[SECONDS],
  632. 22661       DiskInfo.first_track_mss[SECTOR],
  633. 22662       DiskInfo.disk_length_mss[MINUTES],        
  634. 22663       DiskInfo.disk_length_mss[SECONDS],        
  635. 22664       DiskInfo.disk_length_mss[SECTOR]);        
  636. 22665 #endif
  637. 22666
  638. 22667   /* Update global status info */
  639. 22668   McdStatus |= INFO_UPTODATE; /* toc header has been read */
  640. 22669   McdStatus &= ~TOC_UPTODATE; /* toc has not been read yet */
  641. .Ep 306 src/kernel/mcd.c
  642. 22670
  643. 22671   return OK;
  644. 22672 }
  645. 22676 /*=========================================================================*
  646. 22677  *                              mcd_read_q_channel                         *    
  647. 22678  *=========================================================================*/
  648. 22679 PRIVATE int mcd_read_q_channel(qc)
  649. 22680 struct cd_toc_entry *qc;  /* struct to return q-channel info in */
  650. 22681 {
  651. 22682   /* Read the qchannel info, if we we're already playing this returns
  652. 22683    * the relative position and the absolute position of where we are
  653. 22684    * in min:sec.sector. If we're not playing, this returns an entry
  654. 22685    * from the table of contents
  655. 22686    */
  656. 22687  
  657. 22688   int i, err; 
  658. 22689
  659. 22690   /* Issue the command */
  660. 22691   if ((err = mcd_send_command(MCD_GET_Q_CHANNEL)) != OK) return err;
  661. 22692
  662. 22693   /* Read the info */
  663. 22694   for (i=0; i < sizeof(struct cd_toc_entry); i++)
  664. 22695   {
  665. 22696     /* Return error on timeout */
  666. 22697     if ((err = mcd_get_reply((u8_t *)qc + i, REPLY_DELAY)) != OK) 
  667. 22698       return err;
  668. 22699
  669. 22700     bcd2bin((u8_t *)qc + i);  /* Convert value to binary */
  670. 22701   }
  671. 22702  
  672. 22703 #if MCD_DEBUG >= 2
  673. 22704   printf("qchannel info: ctl_addr: %d track: %d index: %d length %02d:%02d.%02d pos: %02d:%02d.%02dn",
  674. 22705       qc->control_address,
  675. 22706       qc->track_nr,
  676. 22707       qc->index_nr,
  677. 22708       qc->track_time_mss[MINUTES],      
  678. 22709       qc->track_time_mss[SECONDS],      
  679. 22710       qc->track_time_mss[SECTOR],
  680. 22711       qc->position_mss[MINUTES],        
  681. 22712       qc->position_mss[SECONDS],        
  682. 22713       qc->position_mss[SECTOR]);
  683. 22714 #endif
  684. 22715
  685. 22716   return OK;  /* All done */
  686. 22717 }
  687. 22720 /*=========================================================================*
  688. 22721  *                              mcd_read_toc                               *    
  689. 22722  *=========================================================================*/
  690. 22723 PRIVATE int mcd_read_toc()
  691. 22724 {
  692. 22725   /* Read the table of contents (TOC) */
  693. 22726
  694. 22727   struct cd_toc_entry q_info;
  695. 22728   int current_track, current_index;
  696. 22729   int err,i;
  697. .Op 307 src/kernel/mcd.c
  698. 22730
  699. 22731
  700. 22732   if (McdStatus & TOC_UPTODATE) return OK; /* No need to read toc again */
  701. 22733         
  702. 22734   /* Clear toc table */
  703. 22735   for (i = 0; i < MAX_TRACKS; i++) Toc[i].index_nr = 0;                 
  704. 22736
  705. 22737   /* Read disk info */
  706. 22738   if ((err = mcd_get_disk_info()) != OK) return err;
  707. 22739
  708. 22740   /* Calculate track to start with */ 
  709. 22741   current_track = DiskInfo.last_track - DiskInfo.first_track + 1;
  710. 22742
  711. 22743   /* Set read toc mode */
  712. 22744   if ((err = mcd_set_mode(MCD_TOC)) != OK) return err;
  713. 22745
  714. 22746   /* Read the complete TOC, on every read-q-channel command we get a random
  715. 22747    * TOC entry depending on how far we are in the q-channel, collect entries
  716. 22748    * as long as we don't have the complete TOC. There's a limit of 600 here,
  717. 22749    * if we don't have the complete TOC after 600 reads we quit with an error
  718. 22750    */
  719. 22751   for (i = 0; (i < 600 && current_track > 0); i++)
  720. 22752   {
  721. 22753     /* Try to read a TOC entry */
  722. 22754     if ((err = mcd_read_q_channel(&q_info)) != OK) break;       
  723. 22755
  724. 22756     /* Is this a valid track number and didn't we have it yet ? */
  725. 22757     current_index = q_info.index_nr;    
  726. 22758     if (current_index >= DiskInfo.first_track &&
  727. 22759         current_index <= DiskInfo.last_track &&
  728. 22760         q_info.track_nr == 0)
  729. 22761     {
  730. 22762       /* Copy entry into toc table */
  731. 22763       if (Toc[current_index].index_nr == 0)
  732. 22764       {
  733. 22765         Toc[current_index].control_address = q_info.control_address;
  734. 22766         Toc[current_index].track_nr = current_index;
  735. 22767         Toc[current_index].index_nr = 1;
  736. 22768         Toc[current_index].track_time_mss[MINUTES] = q_info.track_time_mss[MINUTES];
  737. 22769         Toc[current_index].track_time_mss[SECONDS] = q_info.track_time_mss[SECONDS];
  738. 22770         Toc[current_index].track_time_mss[SECTOR] = q_info.track_time_mss[SECTOR];
  739. 22771         Toc[current_index].position_mss[MINUTES] = q_info.position_mss[MINUTES];
  740. 22772         Toc[current_index].position_mss[SECONDS] = q_info.position_mss[SECONDS];
  741. 22773         Toc[current_index].position_mss[SECTOR] = q_info.position_mss[SECTOR];
  742. 22774         current_track--;
  743. 22775       }
  744. 22776     }
  745. 22777   }
  746. 22778   if (err) return err;   /* Do we have all toc entries? */
  747. 22779
  748. 22780   /* Fill in lead out */
  749. 22781   current_index = DiskInfo.last_track + 1;
  750. 22782   Toc[current_index].control_address = 
  751. 22783                                   Toc[current_index-1].control_address;
  752. 22784   Toc[current_index].track_nr = 0;
  753. 22785   Toc[current_index].index_nr = LEAD_OUT;
  754. 22786   Toc[current_index].position_mss[MINUTES] = DiskInfo.disk_length_mss[MINUTES];
  755. 22787   Toc[current_index].position_mss[SECONDS] = DiskInfo.disk_length_mss[SECONDS];
  756. 22788   Toc[current_index].position_mss[SECTOR] = DiskInfo.disk_length_mss[SECTOR];
  757. 22789
  758. .Ep 308 src/kernel/mcd.c
  759. 22790   /* Return to cooked mode */
  760. 22791   if ((err = mcd_set_mode(MCD_COOKED)) != OK) return err; 
  761. 22792
  762. 22793   /* Update global status */
  763. 22794   McdStatus |= TOC_UPTODATE;
  764. 22795
  765. 22796 #if MCD_DEBUG >= 1
  766. 22797   for (i = DiskInfo.first_track; i <= current_index; i++)
  767. 22798   {
  768. 22799     printf("Mitsumi toc %d: trk %d  index %d  time %02d:%02d.%02d  pos: %02d:%02d.%02dn",
  769. 22800         i,
  770. 22801         Toc[i].track_nr,
  771. 22802         Toc[i].index_nr,
  772. 22803         Toc[i].track_time_mss[MINUTES],
  773. 22804         Toc[i].track_time_mss[SECONDS],
  774. 22805         Toc[i].track_time_mss[SECTOR],
  775. 22806         Toc[i].position_mss[MINUTES],
  776. 22807         Toc[i].position_mss[SECONDS],
  777. 22808         Toc[i].position_mss[SECTOR]);
  778. 22809   }
  779. 22810 #endif
  780. 22811
  781. 22812   return OK;
  782. 22813 }
  783. 22816 /*=========================================================================*
  784. 22817  *                              mcd_stop                                   *    
  785. 22818  *=========================================================================*/
  786. 22819 PRIVATE int mcd_stop()
  787. 22820 {
  788. 22821   int err;
  789. 22822
  790. 22823   if ((err = mcd_send_command(MCD_STOP)) != OK ) return err;
  791. 22824
  792. 22825   McdStatus &= ~(AUDIO_PAUSED);
  793. 22826
  794. 22827   return OK;
  795. 22828 } 
  796. 22829
  797. 22830
  798. 22831 /*=========================================================================*
  799. 22832  *                              mcd_eject                                  *    
  800. 22833  *=========================================================================*/
  801. 22834 PRIVATE int mcd_eject()
  802. 22835 {
  803. 22836   int err;
  804. 22837
  805. 22838   if ((err = mcd_send_command(MCD_EJECT)) != OK) return err;
  806. 22839   return OK;
  807. 22840 } 
  808. 22841
  809. 22842
  810. 22843 /*=========================================================================*
  811. 22844  *                              mcd_pause                                  *    
  812. 22845  *=========================================================================*/
  813. 22846 PRIVATE int mcd_pause()
  814. 22847 {
  815. 22848   int err;
  816. 22849   struct cd_toc_entry qc;
  817. .Op 309 src/kernel/mcd.c
  818. 22850
  819. 22851   /* We can only pause when we are playing audio */
  820. 22852   if (!(McdStatus & AUDIO_PLAYING)) return EINVAL;
  821. 22853
  822. 22854   /* Look where we are */
  823. 22855   if ((err = mcd_read_q_channel(&qc)) != OK) return err;
  824. 22856
  825. 22857   /* Stop playing */
  826. 22858   if ((err = mcd_send_command(MCD_STOP_AUDIO)) != OK) return err;
  827. 22859
  828. 22860   /* Keep in mind were we have to start again */
  829. 22861   PlayMss.begin_mss[MINUTES] = qc.position_mss[MINUTES];
  830. 22862   PlayMss.begin_mss[SECONDS] = qc.position_mss[SECONDS];
  831. 22863   PlayMss.begin_mss[SECTOR] = qc.position_mss[SECTOR];
  832. 22864
  833. 22865   /* Update McdStatus */
  834. 22866   McdStatus |= AUDIO_PAUSED;
  835. 22867
  836. 22868 #if MCD_DEBUG >= 1
  837. 22869   printf("Mcd_paused at: %02d:%02d.%02dn",
  838. 22870       PlayMss.begin_mss[MINUTES],
  839. 22871       PlayMss.begin_mss[SECONDS],
  840. 22872       PlayMss.begin_mss[SECTOR]);
  841. 22873 #endif
  842. 22874
  843. 22875   return OK;
  844. 22876 } 
  845. 22877
  846. 22878
  847. 22879 /*=========================================================================*
  848. 22880  *                              mcd_resume                                 *    
  849. 22881  *=========================================================================*/
  850. 22882 PRIVATE int mcd_resume()
  851. 22883 {
  852. 22884   int err;
  853. 22885
  854. 22886   /* we can only resume if we are in a pause state */
  855. 22887   if (!(McdStatus & AUDIO_PAUSED)) return EINVAL;
  856. 22888
  857. 22889   /* start playing where we left off */
  858. 22890   if ((err = mcd_play_mss(PlayMss)) != OK) return err;
  859. 22891
  860. 22892   McdStatus &= ~(AUDIO_PAUSED);
  861. 22893
  862. 22894 #if MCD_DEBUG >= 1
  863. 22895   printf("Mcd resumed at: %02d:%02d.%02dn",
  864. 22896       PlayMss.begin_mss[MINUTES],
  865. 22897       PlayMss.begin_mss[SECONDS],
  866. 22898       PlayMss.begin_mss[SECTOR]);
  867. 22899 #endif
  868. 22900
  869. 22901   return OK;
  870. 22902 } 
  871. 22903
  872. 22904
  873. 22905 /*=========================================================================*
  874. 22906  *                              ioctl_read_sub                             *    
  875. 22907  *=========================================================================*/
  876. 22908 PRIVATE int ioctl_read_sub(m_ptr)
  877. 22909 message *m_ptr;
  878. .Ep 310 src/kernel/mcd.c
  879. 22910 {
  880. 22911   phys_bytes user_phys;
  881. 22912   struct cd_toc_entry sub;
  882. 22913   int err;
  883. 22914
  884. 22915   /* We can only read a sub channel when we are playing audio */
  885. 22916   if (!(McdStatus & AUDIO_PLAYING)) return EINVAL; 
  886. 22917
  887. 22918   /* Read the sub channel */
  888. 22919   if ((err = mcd_read_q_channel(&sub)) != OK) return err;
  889. 22920
  890. 22921   /* Copy info to user */
  891. 22922   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(sub));
  892. 22923   if (user_phys == 0) return(EFAULT);
  893. 22924   phys_copy(vir2phys(&sub), user_phys, (phys_bytes) sizeof(sub));
  894. 22925
  895. 22926   return OK;
  896. 22927 }  
  897. 22928
  898. 22929
  899. 22930
  900. 22931 /*=========================================================================*
  901. 22932  *                              ioctl_read_toc                             *    
  902. 22933  *=========================================================================*/
  903. 22934 PRIVATE int ioctl_read_toc(m_ptr)
  904. 22935 message *m_ptr;
  905. 22936 {
  906. 22937   phys_bytes user_phys;
  907. 22938   int err, toc_size;
  908. 22939
  909. 22940   /* Try to read the table of contents */
  910. 22941   if ((err = mcd_read_toc()) != OK) return err;
  911. 22942
  912. 22943   /* Get size of toc */
  913. 22944   toc_size = (DiskInfo.last_track + 1) * sizeof(struct cd_toc_entry);
  914. 22945
  915. 22946   /* Copy to user */
  916. 22947   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, toc_size);
  917. 22948   if (user_phys == 0) return(EFAULT);
  918. 22949   phys_copy(vir2phys(&Toc), user_phys, (phys_bytes) toc_size);
  919. 22950
  920. 22951   return OK;
  921. 22952 }  
  922. 22953
  923. 22954
  924. 22955 /*=========================================================================*
  925. 22956  *                              ioctl_disk_info                            *    
  926. 22957  *=========================================================================*/
  927. 22958 PRIVATE int ioctl_disk_info(m_ptr)
  928. 22959 message *m_ptr;
  929. 22960 {
  930. 22961   phys_bytes user_phys;
  931. 22962   int err;
  932. 22963
  933. 22964   /* Try to read the toc header */
  934. 22965   if ((err = mcd_get_disk_info()) != OK) return err;
  935. 22966
  936. 22967   /* Copy info to user */
  937. 22968   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(DiskInfo));
  938. 22969   if (user_phys == 0) return(EFAULT);
  939. .Op 311 src/kernel/mcd.c
  940. 22970   phys_copy(vir2phys(&DiskInfo), user_phys, (phys_bytes) sizeof(DiskInfo));
  941. 22971
  942. 22972   return OK;
  943. 22973 }
  944. 22976 /*=========================================================================*
  945. 22977  *                              ioctl_play_mss                             *    
  946. 22978  *=========================================================================*/
  947. 22979 PRIVATE int ioctl_play_mss(m_ptr)
  948. 22980 message *m_ptr;
  949. 22981 {
  950. 22982   phys_bytes user_phys;
  951. 22983   struct cd_play_mss mss;
  952. 22984
  953. 22985   /* Get user data */
  954. 22986   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(mss));
  955. 22987   if (user_phys == 0) return(EFAULT);
  956. 22988   phys_copy(user_phys, vir2phys(&mss), (phys_bytes) sizeof(mss));
  957. 22989
  958. 22990   /* Try to play */
  959. 22991   return mcd_play_mss(mss);
  960. 22992 }
  961. 22995 /*=========================================================================*
  962. 22996  *                              ioctl_play_ti                              *    
  963. 22997  *=========================================================================*/
  964. 22998 PRIVATE int ioctl_play_ti(m_ptr)
  965. 22999 message *m_ptr;
  966. 23000 {
  967. 23001   phys_bytes user_phys;
  968. 23002   struct cd_play_track tracks;
  969. 23003
  970. 23004   /* Get user data */
  971. 23005   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(tracks));
  972. 23006   if (user_phys == 0) return(EFAULT);
  973. 23007   phys_copy(user_phys, vir2phys(&tracks), (phys_bytes) sizeof(tracks));
  974. 23008
  975. 23009   /* Try to play */
  976. 23010   return mcd_play_tracks(tracks);
  977. 23011 }
  978. 23014 /*===========================================================================*
  979. 23015  *                              mcd_prepare                                  *
  980. 23016  *===========================================================================*/
  981. 23017 PRIVATE struct device *mcd_prepare(device)
  982. 23018 int device;
  983. 23019 {
  984. 23020   /* Nothing to transfer as yet. */
  985. 23021   mcd_count = 0;
  986. 23022
  987. 23023   /* Select partition. */
  988. 23024   if (device < DEV_PER_DRIVE) {                 /* cd0, cd1, ... */
  989. 23025     mcd_dv = &mcd_part[device];
  990. 23026   } else
  991. 23027   if ((unsigned) (device -= MINOR_hd1a) < SUB_PER_DRIVE) { /* cd1a, cd1b, ... */
  992. 23028     mcd_dv = &mcd_subpart[device];
  993. 23029   } else {
  994. .Ep 312 src/kernel/mcd.c
  995. 23030     return NIL_DEV;
  996. 23031   }
  997. 23032
  998. 23033   return mcd_dv;
  999. 23034 }
  1000. 23037 /*===========================================================================*
  1001. 23038  *                              mcd_schedule                                 *
  1002. 23039  *===========================================================================*/
  1003. 23040 PRIVATE int mcd_schedule(proc_nr, iop)
  1004. 23041 int proc_nr;                    /* process doing the request */
  1005. 23042 struct iorequest_s *iop;        /* pointer to read or write request */
  1006. 23043 {
  1007. 23044 /* Gather I/O requests on consecutive blocks so they may be read/written
  1008. 23045  * in one controller command.  (There is enough time to compute the next
  1009. 23046  * consecutive request while an unwanted block passes by.)
  1010. 23047  */
  1011. 23048   int r, opcode;
  1012. 23049   unsigned long pos;
  1013. 23050   unsigned nbytes;
  1014. 23051   phys_bytes user_phys;
  1015. 23052
  1016. 23053   /* This many bytes to read */
  1017. 23054   nbytes = iop->io_nbytes;
  1018. 23055
  1019. 23056   /* From/to this position on the device */
  1020. 23057   pos = iop->io_position;
  1021. 23058
  1022. 23059   /* To/from this user address */
  1023. 23060   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
  1024. 23061   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  1025. 23062
  1026. 23063   /* Read or write? */
  1027. 23064   opcode = iop->io_request & ~OPTIONAL_IO;
  1028. 23065
  1029. 23066   /* Only read permitted on cdrom */
  1030. 23067   if (opcode != DEV_READ) return EIO;
  1031. 23068
  1032. 23069   /* What position on disk and how close to EOF? */
  1033. 23070   if (pos >= mcd_dv->dv_size) return(OK);       /* At EOF */
  1034. 23071   if (pos + nbytes > mcd_dv->dv_size) nbytes = mcd_dv->dv_size - pos;
  1035. 23072   pos += mcd_dv->dv_base;
  1036. 23073
  1037. 23074   if (mcd_count > 0 && pos != mcd_nextpos) {
  1038. 23075         /* This new request can't be chained to the job being built */
  1039. 23076         if ((r = mcd_finish()) != OK) return(r);
  1040. 23077   }
  1041. 23078
  1042. 23079   /* Next consecutive position. */
  1043. 23080   mcd_nextpos = pos + nbytes;
  1044. 23081
  1045. 23082   if (mcd_count == 0) 
  1046. 23083   {
  1047. 23084     /* The first request in a row, initialize. */
  1048. 23085     mcd_tp = mcd_trans;
  1049. 23086   }
  1050. 23087
  1051. 23088   /* Store I/O parameters */
  1052. 23089   mcd_tp->tr_iop = iop;
  1053. .Op 313 src/kernel/mcd.c
  1054. 23090   mcd_tp->tr_pos = pos;
  1055. 23091   mcd_tp->tr_count = nbytes;
  1056. 23092   mcd_tp->tr_phys = user_phys;
  1057. 23093
  1058. 23094   /* Update counters */
  1059. 23095   mcd_tp++;
  1060. 23096   mcd_count += nbytes;
  1061. 23097   return(OK);
  1062. 23098 }
  1063. 23101 /*===========================================================================*
  1064. 23102  *                              mcd_finish                                   *
  1065. 23103  *===========================================================================*/
  1066. 23104 PRIVATE int mcd_finish()
  1067. 23105 {
  1068. 23106 /* Carry out the I/O requests gathered in mcd_trans[]. */
  1069. 23107
  1070. 23108   struct trans *tp = mcd_trans;
  1071. 23109   int err, errors;
  1072. 23110   u8_t mss[3];
  1073. 23111   unsigned long pos;
  1074. 23112   unsigned count, n;
  1075. 23113
  1076. 23114   if (mcd_count == 0) return(OK);       /* we're already done */
  1077. 23115
  1078. 23116   /* Update status */
  1079. 23117   mcd_get_status(1);
  1080. 23118   if (McdStatus & (AUDIO_DISK | NO_DISK))
  1081. 23119     return(tp->tr_iop->io_nbytes = EIO);
  1082. 23120                                                           
  1083. 23121   /* Set cooked mode */
  1084. 23122   if ((err = mcd_set_mode(MCD_COOKED)) != OK)
  1085. 23123     return(tp->tr_iop->io_nbytes = err);
  1086. 23124
  1087. 23125   while (mcd_count > 0)
  1088. 23126   {
  1089. 23127     /* Position on the CD rounded down to the CD block size */
  1090. 23128     pos = tp->tr_pos & ~MCD_BLOCK_MASK;
  1091. 23129
  1092. 23130     /* Byte count rounded up. */
  1093. 23131     count = (pos - tp->tr_pos) + mcd_count;
  1094. 23132     count = (count + MCD_BLOCK_SIZE - 1) & ~MCD_BLOCK_MASK;
  1095. 23133
  1096. 23134     /* XXX transfer size limits? */
  1097. 23135     if (count > MCD_BLOCK_SIZE) count = MCD_BLOCK_SIZE;
  1098. 23136
  1099. 23137     /* Compute disk position in min:sec:sector */
  1100. 23138     block2mss(pos >> MCD_BLOCK_SHIFT, mss);
  1101. 23139
  1102. 23140     /* Now try to read a block */
  1103. 23141     errors = 0;
  1104. 23142     while (errors < MCD_RETRIES) 
  1105. 23143     {
  1106. 23144       lock();
  1107. 23145       out_byte(MCD_DATA_PORT, MCD_READ_FROM_TO);
  1108. 23146       out_byte(MCD_DATA_PORT, bin2bcd(mss[MINUTES])); 
  1109. 23147       out_byte(MCD_DATA_PORT, bin2bcd(mss[SECONDS])); 
  1110. 23148       out_byte(MCD_DATA_PORT, bin2bcd(mss[SECTOR])); 
  1111. 23149       out_byte(MCD_DATA_PORT, 0); 
  1112. .Ep 314 src/kernel/mcd.c
  1113. 23150       out_byte(MCD_DATA_PORT, 0); 
  1114. 23151       out_byte(MCD_DATA_PORT, 1);       /* XXX count in mss form? */
  1115. 23152       unlock();
  1116. 23153
  1117. 23154       /* Wait for data */
  1118. 23155       if (mcd_data_ready(REPLY_DELAY) == OK) break;
  1119. 23156       printf("Mcd: data time outn");
  1120. 23157       errors++;
  1121. 23158     }
  1122. 23159     if (errors == MCD_RETRIES) return(tp->tr_iop->io_nbytes = EIO);
  1123. 23160
  1124. 23161     /* Prepare reading data. */
  1125. 23162     out_byte(MCD_CONTROL_PORT, 0x04);
  1126. 23163
  1127. 23164     while (pos < tp->tr_pos)
  1128. 23165     {
  1129. 23166       /* Discard bytes before the position we are really interested in. */
  1130. 23167       n = tp->tr_pos - pos;
  1131. 23168       if (n > DMA_BUF_SIZE) n = DMA_BUF_SIZE;
  1132. 23169       port_read_byte(MCD_DATA_PORT, tmp_phys, n);
  1133. 23170 #if XXX
  1134. 23171 printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %un",
  1135. 23172 count, n, 0, 0, 0, mcd_count);
  1136. 23173 #endif
  1137. 23174       pos += n;
  1138. 23175       count -= n;
  1139. 23176     }
  1140. 23177
  1141. 23178     while (mcd_count > 0 && count > 0)
  1142. 23179     {
  1143. 23180       /* Transfer bytes into the user buffers. */
  1144. 23181       n = tp->tr_count;
  1145. 23182       if (n > count) n = count;
  1146. 23183       port_read_byte(MCD_DATA_PORT, tp->tr_phys, n);
  1147. 23184 #if XXX
  1148. 23185 printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %un",
  1149. 23186 count, n, tp->tr_pos, tp->tr_iop->io_nbytes, tp->tr_count, mcd_count);
  1150. 23187 #endif
  1151. 23188       tp->tr_phys += n;
  1152. 23189       tp->tr_pos += n;
  1153. 23190       tp->tr_iop->io_nbytes -= n;
  1154. 23191       if ((tp->tr_count -= n) == 0) tp++;
  1155. 23192       count -= n;
  1156. 23193       mcd_count -= n;
  1157. 23194     }
  1158. 23195
  1159. 23196     while (count > 0)
  1160. 23197     {
  1161. 23198       /* Discard excess bytes. */
  1162. 23199       n = count;
  1163. 23200       if (n > DMA_BUF_SIZE) n = DMA_BUF_SIZE;
  1164. 23201       port_read_byte(MCD_DATA_PORT, tmp_phys, n);
  1165. 23202 #if XXX
  1166. 23203 printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %un",
  1167. 23204 count, n, 0, 0, 0, mcd_count);
  1168. 23205 #endif
  1169. 23206       count -= n;
  1170. 23207     }
  1171. 23208
  1172. 23209     /* Finish reading data. */
  1173. .Op 315 src/kernel/mcd.c
  1174. 23210     out_byte(MCD_CONTROL_PORT, 0x0c);
  1175. 23211 #if 0 /*XXX*/
  1176. 23212     mcd_get_status(1);
  1177. 23213     if (!(McdStatus & DISK_ERROR)) done = 1; /* OK, no errors */
  1178. 23214 #endif
  1179. 23215   }
  1180. 23216  
  1181. 23217   return OK; 
  1182. 23218 }
  1183. 23221 /*============================================================================*
  1184. 23222  *                              mcd_geometry                                  *
  1185. 23223  *============================================================================*/
  1186. 23224 PRIVATE void mcd_geometry(entry)
  1187. 23225 struct partition *entry;                
  1188. 23226 {
  1189. 23227 /* The geometry of a cdrom doesn't look like the geometry of a regular disk,
  1190. 23228  * so we invent a geometry to keep external programs happy.
  1191. 23229  */ 
  1192. 23230   entry->cylinders = (mcd_part[0].dv_size >> SECTOR_SHIFT) / (64 * 32);
  1193. 23231   entry->heads = 64;
  1194. 23232   entry->sectors = 32;
  1195. 23233 }
  1196. 23236 /*============================================================================*
  1197. 23237  *                              misc functions                                *
  1198. 23238  *============================================================================*/
  1199. 23239 PRIVATE u8_t bin2bcd(u8_t b)
  1200. 23240 {
  1201. 23241   /* Convert a number to binary-coded-decimal */
  1202. 23242   int u,t;
  1203. 23243
  1204. 23244   u = b%10;
  1205. 23245   t = b/10;
  1206. 23246   return (u8_t)(u | (t << 4));
  1207. 23247 }
  1208. 23250 PRIVATE void bcd2bin(u8_t *bcd)
  1209. 23251 {
  1210. 23252   /* Convert binary-coded-decimal to binary :-) */
  1211. 23253
  1212. 23254   *bcd = (*bcd >> 4) * 10 + (*bcd & 0xf);
  1213. 23255 }
  1214. 23258 PRIVATE void block2mss(block, mss)
  1215. 23259 long block;
  1216. 23260 u8_t *mss;
  1217. 23261 {
  1218. 23262   /* Compute disk position of a block in min:sec:sector */
  1219. 23263
  1220. 23264   block += MCD_SKIP;
  1221. 23265   mss[MINUTES] = block/(SECONDS_PER_MINUTE * SECTORS_PER_SECOND);
  1222. 23266   block %= (SECONDS_PER_MINUTE * SECTORS_PER_SECOND);
  1223. 23267   mss[SECONDS] = block/(SECTORS_PER_SECOND);
  1224. 23268   mss[SECTOR] = block%(SECTORS_PER_SECOND);
  1225. 23269 }
  1226. .Ep 316 src/kernel/mcd.c
  1227. 23272 PRIVATE long mss2block(u8_t *mss)
  1228. 23273 {
  1229. 23274   /* Compute block number belonging to 
  1230. 23275    * disk position min:sec:sector 
  1231. 23276    */
  1232. 23277
  1233. 23278   return ((((unsigned long) mss[MINUTES] * SECONDS_PER_MINUTE
  1234. 23279         + (unsigned long) mss[SECONDS]) * SECTORS_PER_SECOND)
  1235. 23280         + (unsigned long) mss[SECTOR]) - MCD_SKIP;
  1236. 23281 }
  1237. 23282 #endif /* ENABLE_MITSUMI_CDROM */
  1238. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1239. src/kernel/memory.c    
  1240. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1241. 23300 /* This file contains the device dependent part of the drivers for the
  1242. 23301  * following special files:
  1243. 23302  *     /dev/null        - null device (data sink)
  1244. 23303  *     /dev/mem         - absolute memory
  1245. 23304  *     /dev/kmem        - kernel virtual memory
  1246. 23305  *     /dev/ram         - RAM disk
  1247. 23306  *
  1248. 23307  * The file contains one entry point:
  1249. 23308  *
  1250. 23309  *   mem_task:  main entry when system is brought up
  1251. 23310  *
  1252. 23311  *  Changes:
  1253. 23312  *      20 Apr  1992 by Kees J. Bot: device dependent/independent split
  1254. 23313  */
  1255. 23314
  1256. 23315 #include "kernel.h"
  1257. 23316 #include "driver.h"
  1258. 23317 #include <sys/ioctl.h>
  1259. 23318
  1260. 23319 #define NR_RAMS            4    /* number of RAM-type devices */
  1261. 23320
  1262. 23321 PRIVATE struct device m_geom[NR_RAMS];  /* Base and size of each RAM disk */
  1263. 23322 PRIVATE int m_device;           /* current device */
  1264. 23323
  1265. 23324 FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
  1266. 23325 FORWARD _PROTOTYPE( int m_schedule, (int proc_nr, struct iorequest_s *iop) );
  1267. 23326 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
  1268. 23327 FORWARD _PROTOTYPE( void m_init, (void) );
  1269. 23328 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
  1270. 23329 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
  1271. 23330
  1272. 23331
  1273. 23332 /* Entry points to this driver. */
  1274. 23333 PRIVATE struct driver m_dtab = {
  1275. 23334   no_name,      /* current device's name */
  1276. 23335   m_do_open,    /* open or mount */
  1277. 23336   do_nop,       /* nothing on a close */
  1278. 23337   m_ioctl,      /* specify ram disk geometry */
  1279. 23338   m_prepare,    /* prepare for I/O on a given minor device */
  1280. 23339   m_schedule,   /* do the I/O */
  1281. .Op 317 src/kernel/memory.c
  1282. 23340   nop_finish,   /* schedule does the work, no need to be smart */
  1283. 23341   nop_cleanup,  /* nothing's dirty */
  1284. 23342   m_geometry,   /* memory device "geometry" */
  1285. 23343 };
  1286. 23344
  1287. 23345
  1288. 23346 /*===========================================================================*
  1289. 23347  *                              mem_task                                     *
  1290. 23348  *===========================================================================*/
  1291. 23349 PUBLIC void mem_task()
  1292. 23350 {
  1293. 23351   m_init();
  1294. 23352   driver_task(&m_dtab);
  1295. 23353 }
  1296. 23356 /*===========================================================================*
  1297. 23357  *                              m_prepare                                    *
  1298. 23358  *===========================================================================*/
  1299. 23359 PRIVATE struct device *m_prepare(device)
  1300. 23360 int device;
  1301. 23361 {
  1302. 23362 /* Prepare for I/O on a device. */
  1303. 23363
  1304. 23364   if (device < 0 || device >= NR_RAMS) return(NIL_DEV);
  1305. 23365   m_device = device;
  1306. 23366
  1307. 23367   return(&m_geom[device]);
  1308. 23368 }
  1309. 23371 /*===========================================================================*
  1310. 23372  *                              m_schedule                                   *
  1311. 23373  *===========================================================================*/
  1312. 23374 PRIVATE int m_schedule(proc_nr, iop)
  1313. 23375 int proc_nr;                    /* process doing the request */
  1314. 23376 struct iorequest_s *iop;        /* pointer to read or write request */
  1315. 23377 {
  1316. 23378 /* Read or write /dev/null, /dev/mem, /dev/kmem, or /dev/ram. */
  1317. 23379
  1318. 23380   int device, count, opcode;
  1319. 23381   phys_bytes mem_phys, user_phys;
  1320. 23382   struct device *dv;
  1321. 23383
  1322. 23384   /* Type of request */
  1323. 23385   opcode = iop->io_request & ~OPTIONAL_IO;
  1324. 23386
  1325. 23387   /* Get minor device number and check for /dev/null. */
  1326. 23388   device = m_device;
  1327. 23389   dv = &m_geom[device];
  1328. 23390
  1329. 23391   /* Determine address where data is to go or to come from. */
  1330. 23392   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf,
  1331. 23393                                                 (vir_bytes) iop->io_nbytes);
  1332. 23394   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  1333. 23395
  1334. 23396   if (device == NULL_DEV) {
  1335. 23397         /* /dev/null: Black hole. */
  1336. 23398         if (opcode == DEV_WRITE) iop->io_nbytes = 0;
  1337. 23399         count = 0;
  1338. .Ep 318 src/kernel/memory.c
  1339. 23400   } else {
  1340. 23401         /* /dev/mem, /dev/kmem, or /dev/ram: Check for EOF */
  1341. 23402         if (iop->io_position >= dv->dv_size) return(OK);
  1342. 23403         count = iop->io_nbytes;
  1343. 23404         if (iop->io_position + count > dv->dv_size)
  1344. 23405                 count = dv->dv_size - iop->io_position;
  1345. 23406   }
  1346. 23407
  1347. 23408   /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram */
  1348. 23409   mem_phys = dv->dv_base + iop->io_position;
  1349. 23410
  1350. 23411   /* Book the number of bytes to be transferred in advance. */
  1351. 23412   iop->io_nbytes -= count;
  1352. 23413
  1353. 23414   if (count == 0) return(OK);
  1354. 23415
  1355. 23416   /* Copy the data. */
  1356. 23417   if (opcode == DEV_READ)
  1357. 23418         phys_copy(mem_phys, user_phys, (phys_bytes) count);
  1358. 23419   else
  1359. 23420         phys_copy(user_phys, mem_phys, (phys_bytes) count);
  1360. 23421
  1361. 23422   return(OK);
  1362. 23423 }
  1363. 23426 /*============================================================================*
  1364. 23427  *                              m_do_open                                     *
  1365. 23428  *============================================================================*/
  1366. 23429 PRIVATE int m_do_open(dp, m_ptr)
  1367. 23430 struct driver *dp;
  1368. 23431 message *m_ptr;
  1369. 23432 {
  1370. 23433 /* Check device number on open.  Give I/O privileges to a process opening
  1371. 23434  * /dev/mem or /dev/kmem.
  1372. 23435  */
  1373. 23436
  1374. 23437   if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1375. 23438
  1376. 23439 #if (CHIP == INTEL)
  1377. 23440   if (m_device == MEM_DEV || m_device == KMEM_DEV)
  1378. 23441         enable_iop(proc_addr(m_ptr->PROC_NR));
  1379. 23442 #endif
  1380. 23443
  1381. 23444   return(OK);
  1382. 23445 }
  1383. 23448 /*===========================================================================*
  1384. 23449  *                              m_init                                       *
  1385. 23450  *===========================================================================*/
  1386. 23451 PRIVATE void m_init()
  1387. 23452 {
  1388. 23453   /* Initialize this task. */
  1389. 23454   extern int _end;
  1390. 23455
  1391. 23456   m_geom[KMEM_DEV].dv_base = vir2phys(0);
  1392. 23457   m_geom[KMEM_DEV].dv_size = vir2phys(&_end);
  1393. 23458
  1394. 23459 #if (CHIP == INTEL)
  1395. .Op 319 src/kernel/memory.c
  1396. 23460   if (!protected_mode) {
  1397. 23461         m_geom[MEM_DEV].dv_size =   0x100000;   /* 1M for 8086 systems */
  1398. 23462   } else {
  1399. 23463 #if _WORD_SIZE == 2
  1400. 23464         m_geom[MEM_DEV].dv_size =  0x1000000;   /* 16M for 286 systems */
  1401. 23465 #else
  1402. 23466         m_geom[MEM_DEV].dv_size = 0xFFFFFFFF;   /* 4G-1 for 386 systems */
  1403. 23467 #endif
  1404. 23468   }
  1405. 23469 #else /* !(CHIP == INTEL) */
  1406. 23470 #if (CHIP == M68000)
  1407. 23471   m_geom[MEM_DEV].dv_size = MEM_BYTES;
  1408. 23472 #else /* !(CHIP == M68000) */
  1409. 23473 #error /* memory limit not set up */
  1410. 23474 #endif /* !(CHIP == M68000) */
  1411. 23475 #endif /* !(CHIP == INTEL) */
  1412. 23476 }
  1413. 23479 /*===========================================================================*
  1414. 23480  *                              m_ioctl                                      *
  1415. 23481  *===========================================================================*/
  1416. 23482 PRIVATE int m_ioctl(dp, m_ptr)
  1417. 23483 struct driver *dp;
  1418. 23484 message *m_ptr;                 /* pointer to read or write message */
  1419. 23485 {
  1420. 23486 /* Set parameters for one of the RAM disks. */
  1421. 23487
  1422. 23488   unsigned long bytesize;
  1423. 23489   unsigned base, size;
  1424. 23490   struct memory *memp;
  1425. 23491   static struct psinfo psinfo = { NR_TASKS, NR_PROCS, (vir_bytes) proc, 0, 0 };
  1426. 23492   phys_bytes psinfo_phys;
  1427. 23493
  1428. 23494   switch (m_ptr->REQUEST) {
  1429. 23495   case MIOCRAMSIZE:
  1430. 23496         /* FS sets the RAM disk size. */
  1431. 23497         if (m_ptr->PROC_NR != FS_PROC_NR) return(EPERM);
  1432. 23498
  1433. 23499         bytesize = m_ptr->POSITION * BLOCK_SIZE;
  1434. 23500         size = (bytesize + CLICK_SHIFT-1) >> CLICK_SHIFT;
  1435. 23501
  1436. 23502         /* Find a memory chunk big enough for the RAM disk. */
  1437. 23503         memp= &mem[NR_MEMS];
  1438. 23504         while ((--memp)->size < size) {
  1439. 23505                 if (memp == mem) panic("RAM disk is too big", NO_NUM);
  1440. 23506         }
  1441. 23507         base = memp->base;
  1442. 23508         memp->base += size;
  1443. 23509         memp->size -= size;
  1444. 23510
  1445. 23511         m_geom[RAM_DEV].dv_base = (unsigned long) base << CLICK_SHIFT;
  1446. 23512         m_geom[RAM_DEV].dv_size = bytesize;
  1447. 23513         break;
  1448. 23514   case MIOCSPSINFO:
  1449. 23515         /* MM or FS set the address of their process table. */
  1450. 23516         if (m_ptr->PROC_NR == MM_PROC_NR) {
  1451. 23517                 psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
  1452. 23518         } else
  1453. 23519         if (m_ptr->PROC_NR == FS_PROC_NR) {
  1454. .Ep 320 src/kernel/memory.c
  1455. 23520                 psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
  1456. 23521         } else {
  1457. 23522                 return(EPERM);
  1458. 23523         }
  1459. 23524         break;
  1460. 23525   case MIOCGPSINFO:
  1461. 23526         /* The ps program wants the process table addresses. */
  1462. 23527         psinfo_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
  1463. 23528                                                         sizeof(psinfo));
  1464. 23529         if (psinfo_phys == 0) return(EFAULT);
  1465. 23530         phys_copy(vir2phys(&psinfo), psinfo_phys, (phys_bytes) sizeof(psinfo));
  1466. 23531         break;
  1467. 23532   default:
  1468. 23533         return(do_diocntl(&m_dtab, m_ptr));
  1469. 23534   }
  1470. 23535   return(OK);
  1471. 23536 }
  1472. 23539 /*============================================================================*
  1473. 23540  *                              m_geometry                                    *
  1474. 23541  *============================================================================*/
  1475. 23542 PRIVATE void m_geometry(entry)
  1476. 23543 struct partition *entry;
  1477. 23544 {
  1478. 23545   /* Memory devices don't have a geometry, but the outside world insists. */
  1479. 23546   entry->cylinders = (m_geom[m_device].dv_size >> SECTOR_SHIFT) / (64 * 32);
  1480. 23547   entry->heads = 64;
  1481. 23548   entry->sectors = 32;
  1482. 23549 }
  1483. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1484. src/kernel/misc.c    
  1485. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1486. 23600 /* This file contains a collection of miscellaneous procedures:
  1487. 23601  *      mem_init:       initialize memory tables.  Some memory is reported
  1488. 23602  *                      by the BIOS, some is guesstimated and checked later
  1489. 23603  *      env_parse       parse environment variable.
  1490. 23604  *      bad_assertion   for debugging
  1491. 23605  *      bad_compare     for debugging
  1492. 23606  */
  1493. 23607
  1494. 23608 #include "kernel.h"
  1495. 23609 #include "assert.h"
  1496. 23610 #include <stdlib.h>
  1497. 23611 #include <minix/com.h>
  1498. 23612
  1499. 23613 #if (CHIP == INTEL)
  1500. 23614
  1501. 23615 #define EM_BASE     0x100000L   /* base of extended memory on AT's */
  1502. 23616 #define SHADOW_BASE 0xFA0000L   /* base of RAM shadowing ROM on some AT's */
  1503. 23617 #define SHADOW_MAX  0x060000L   /* maximum usable shadow memory (16M limit) */
  1504. 23618
  1505. 23619 /*=========================================================================*
  1506. .Op 321 src/kernel/misc.c
  1507. 23620  *                              mem_init                                   *
  1508. 23621  *=========================================================================*/
  1509. 23622 PUBLIC void mem_init()
  1510. 23623 {
  1511. 23624 /* Initialize the memory size tables.  This is complicated by fragmentation
  1512. 23625  * and different access strategies for protected mode.  There must be a
  1513. 23626  * chunk at 0 big enough to hold Minix proper.  For 286 and 386 processors,
  1514. 23627  * there can be extended memory (memory above 1MB).  This usually starts at
  1515. 23628  * 1MB, but there may be another chunk just below 16MB, reserved under DOS
  1516. 23629  * for shadowing ROM, but available to Minix if the hardware can be re-mapped.
  1517. 23630  * In protected mode, extended memory is accessible assuming CLICK_SIZE is
  1518. 23631  * large enough, and is treated as ordinary memory.
  1519. 23632  */
  1520. 23633
  1521. 23634   u32_t ext_clicks;
  1522. 23635   phys_clicks max_clicks;
  1523. 23636
  1524. 23637   /* Get the size of ordinary memory from the BIOS. */
  1525. 23638   mem[0].size = k_to_click(low_memsize);        /* base = 0 */
  1526. 23639
  1527. 23640   if (pc_at && protected_mode) {
  1528. 23641         /* Get the size of extended memory from the BIOS.  This is special
  1529. 23642          * except in protected mode, but protected mode is now normal.
  1530. 23643          * Note that no more than 16M can be addressed in 286 mode, so make
  1531. 23644          * sure that the highest memory address fits in a short when counted
  1532. 23645          * in clicks.
  1533. 23646          */
  1534. 23647         ext_clicks = k_to_click((u32_t) ext_memsize);
  1535. 23648         max_clicks = USHRT_MAX - (EM_BASE >> CLICK_SHIFT);
  1536. 23649         mem[1].size = MIN(ext_clicks, max_clicks);
  1537. 23650         mem[1].base = EM_BASE >> CLICK_SHIFT;
  1538. 23651
  1539. 23652         if (ext_memsize <= (unsigned) ((SHADOW_BASE - EM_BASE) / 1024)
  1540. 23653                         && check_mem(SHADOW_BASE, SHADOW_MAX) == SHADOW_MAX) {
  1541. 23654                 /* Shadow ROM memory. */
  1542. 23655                 mem[2].size = SHADOW_MAX >> CLICK_SHIFT;
  1543. 23656                 mem[2].base = SHADOW_BASE >> CLICK_SHIFT;
  1544. 23657         }
  1545. 23658   }
  1546. 23659
  1547. 23660   /* Total system memory. */
  1548. 23661   tot_mem_size = mem[0].size + mem[1].size + mem[2].size;
  1549. 23662 }
  1550. 23663 #endif /* (CHIP == INTEL) */
  1551. 23664
  1552. 23665 /*=========================================================================*
  1553. 23666  *                              env_parse                                  *
  1554. 23667  *=========================================================================*/
  1555. 23668 PUBLIC int env_parse(env, fmt, field, param, min, max)
  1556. 23669 char *env;              /* environment variable to inspect */
  1557. 23670 char *fmt;              /* template to parse it with */
  1558. 23671 int field;              /* field number of value to return */
  1559. 23672 long *param;            /* address of parameter to get */
  1560. 23673 long min, max;          /* minimum and maximum values for the parameter */
  1561. 23674 {
  1562. 23675 /* Parse an environment variable setting, something like "DPETH0=300:3".
  1563. 23676  * Panic if the parsing fails.  Return EP_UNSET if the environment variable
  1564. 23677  * is not set, EP_OFF if it is set to "off", EP_ON if set to "on" or a
  1565. 23678  * field is left blank, or EP_SET if a field is given (return value through
  1566. 23679  * *param).  Commas and colons may be used in the environment and format
  1567. .Ep 322 src/kernel/misc.c
  1568. 23680  * string, fields in the environment string may be empty, and punctuation
  1569. 23681  * may be missing to skip fields.  The format string contains characters
  1570. 23682  * 'd', 'o', 'x' and 'c' to indicate that 10, 8, 16, or 0 is used as the
  1571. 23683  * last argument to strtol.
  1572. 23684  */
  1573. 23685
  1574. 23686   char *val, *end;
  1575. 23687   long newpar;
  1576. 23688   int i = 0, radix, r;
  1577. 23689
  1578. 23690   if ((val = k_getenv(env)) == NIL_PTR) return(EP_UNSET);
  1579. 23691   if (strcmp(val, "off") == 0) return(EP_OFF);
  1580. 23692   if (strcmp(val, "on") == 0) return(EP_ON);
  1581. 23693
  1582. 23694   r = EP_ON;
  1583. 23695   for (;;) {
  1584. 23696         while (*val == ' ') val++;
  1585. 23697
  1586. 23698         if (*val == 0) return(r);       /* the proper exit point */
  1587. 23699
  1588. 23700         if (*fmt == 0) break;           /* too many values */
  1589. 23701
  1590. 23702         if (*val == ',' || *val == ':') {
  1591. 23703                 /* Time to go to the next field. */
  1592. 23704                 if (*fmt == ',' || *fmt == ':') i++;
  1593. 23705                 if (*fmt++ == *val) val++;
  1594. 23706         } else {
  1595. 23707                 /* Environment contains a value, get it. */
  1596. 23708                 switch (*fmt) {
  1597. 23709                 case 'd':       radix =   10;   break;
  1598. 23710                 case 'o':       radix =  010;   break;
  1599. 23711                 case 'x':       radix = 0x10;   break;
  1600. 23712                 case 'c':       radix =    0;   break;
  1601. 23713                 default:        goto badenv;
  1602. 23714                 }
  1603. 23715                 newpar = strtol(val, &end, radix);
  1604. 23716
  1605. 23717                 if (end == val) break;  /* not a number */
  1606. 23718                 val = end;
  1607. 23719
  1608. 23720                 if (i == field) {
  1609. 23721                         /* The field requested. */
  1610. 23722                         if (newpar < min || newpar > max) break;
  1611. 23723                         *param = newpar;
  1612. 23724                         r = EP_SET;
  1613. 23725                 }
  1614. 23726         }
  1615. 23727   }
  1616. 23728 badenv:
  1617. 23729   printf("Bad environment setting: '%s = %s'n", env, k_getenv(env));
  1618. 23730   panic("", NO_NUM);
  1619. 23731   /*NOTREACHED*/
  1620. 23732 }
  1621. 23734 #if DEBUG
  1622. 23735 /*=========================================================================*
  1623. 23736  *                              bad_assertion                              *
  1624. 23737  *=========================================================================*/
  1625. 23738 PUBLIC void bad_assertion(file, line, what)
  1626. 23739 char *file;
  1627. .Op 323 src/kernel/misc.c
  1628. 23740 int line;
  1629. 23741 char *what;
  1630. 23742 {
  1631. 23743   printf("panic at %s(%d): assertion "%s" failedn", file, line, what);
  1632. 23744   panic(NULL, NO_NUM);
  1633. 23745 }
  1634. 23747 /*=========================================================================*
  1635. 23748  *                              bad_compare                                *
  1636. 23749  *=========================================================================*/
  1637. 23750 PUBLIC void bad_compare(file, line, lhs, what, rhs)
  1638. 23751 char *file;
  1639. 23752 int line;
  1640. 23753 int lhs;
  1641. 23754 char *what;
  1642. 23755 int rhs;
  1643. 23756 {
  1644. 23757   printf("panic at %s(%d): compare (%d) %s (%d) failedn",
  1645. 23758         file, line, lhs, what, rhs);
  1646. 23759   panic(NULL, NO_NUM);
  1647. 23760 }
  1648. 23761 #endif /* DEBUG */
  1649. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1650. src/kernel/ne2000.c    
  1651. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1652. 23800 /*
  1653. 23801 ne2000.c
  1654. 23802
  1655. 23803 Driver for the ne2000 ethernet cards. This file contains only the ne2000
  1656. 23804 specific code, the rest is in dp8390.c
  1657. 23805
  1658. 23806 Created:        March 15, 1994 by Philip Homburg <philip@cs.vu.nl>
  1659. 23807 */
  1660. 23808
  1661. 23809 #include "kernel.h"
  1662. 23810 #include <net/gen/ether.h>
  1663. 23811 #include <net/gen/eth_io.h>
  1664. 23812 #include "dp8390.h"
  1665. 23813 #include "ne2000.h"
  1666. 23814
  1667. 23815 #if ENABLE_NETWORKING
  1668. 23816
  1669. 23817 #if !__minix_vmd
  1670. 23818 #define debug           0
  1671. 23819 #endif
  1672. 23820
  1673. 23821 #define N 100
  1674. 23822
  1675. 23823 _PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)  );
  1676. 23824
  1677. 23825 u8_t    pat0[]= { 0x00, 0x00, 0x00, 0x00 };
  1678. 23826 u8_t    pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
  1679. 23827 u8_t    pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
  1680. 23828 u8_t    pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
  1681. 23829
  1682. .Ep 324 src/kernel/ne2000.c
  1683. 23830 _PROTOTYPE( static int test_8, (dpeth_t *dep, int pos, u8_t *pat)       );
  1684. 23831 _PROTOTYPE( static int test_16, (dpeth_t *dep, int pos, u8_t *pat)      );
  1685. 23832 _PROTOTYPE( static void ne_init, (dpeth_t *dep)                         );
  1686. 23833 _PROTOTYPE( static void ne_stop, (dpeth_t *dep)                         );
  1687. 23834
  1688. 23835 /*===========================================================================*
  1689. 23836  *                              ne_probe                                     *
  1690. 23837  *===========================================================================*/
  1691. 23838 int ne_probe(dep)
  1692. 23839 dpeth_t *dep;
  1693. 23840 {
  1694. 23841         int byte;
  1695. 23842         int i;
  1696. 23843         int loc1, loc2;
  1697. 23844         testf_t f;
  1698. 23845
  1699. 23846         dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
  1700. 23847
  1701. 23848         /* We probe for an ne1000 or an ne2000 by testing whether the
  1702. 23849          * on board is reachable through the dp8390. Note that the
  1703. 23850          * ne1000 is an 8bit card and has a memory region distict from
  1704. 23851          * the 16bit ne2000
  1705. 23852          */
  1706. 23853
  1707. 23854         for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
  1708. 23855         {
  1709. 23856                 /* Reset the ethernet card */
  1710. 23857                 byte= inb_ne(dep, NE_RESET);
  1711. 23858                 milli_delay(2);
  1712. 23859                 outb_ne(dep, NE_RESET, byte);
  1713. 23860                 milli_delay(2);
  1714. 23861
  1715. 23862                 /* Reset the dp8390 */
  1716. 23863                 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
  1717. 23864                 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
  1718. 23865                         ; /* Do nothing */
  1719. 23866
  1720. 23867                 /* Check if the dp8390 is really there */
  1721. 23868                 if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
  1722. 23869                         (CR_STP|CR_DM_ABORT))
  1723. 23870                 {
  1724. 23871                         return 0;
  1725. 23872                 }
  1726. 23873
  1727. 23874                 /* Put it in loop-back mode */
  1728. 23875                 outb_reg0(dep, DP_RCR, RCR_MON);
  1729. 23876                 outb_reg0(dep, DP_TCR, TCR_NORMAL);
  1730. 23877                 if (dep->de_16bit)
  1731. 23878                 {
  1732. 23879                         outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
  1733. 23880                                 DCR_BMS);
  1734. 23881                 }
  1735. 23882                 else
  1736. 23883                 {
  1737. 23884                         outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
  1738. 23885                                 DCR_BMS);
  1739. 23886                 }
  1740. 23887
  1741. 23888                 if (dep->de_16bit)
  1742. 23889                 {
  1743. .Op 325 src/kernel/ne2000.c
  1744. 23890                         loc1= NE2000_START;
  1745. 23891                         loc2= NE2000_START + NE2000_SIZE - 4;
  1746. 23892                         f= test_16;
  1747. 23893                 }
  1748. 23894                 else
  1749. 23895                 {
  1750. 23896                         loc1= NE1000_START;
  1751. 23897                         loc2= NE1000_START + NE1000_SIZE - 4;
  1752. 23898                         f= test_8;
  1753. 23899                 }
  1754. 23900                 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
  1755. 23901                         f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
  1756. 23902                         f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
  1757. 23903                         f(dep, loc2, pat2) && f(dep, loc2, pat3))
  1758. 23904                 {
  1759. 23905                         /* We don't need a memory segment */
  1760. 23906                         dep->de_linmem= 0;
  1761. 23907                         dep->de_initf= ne_init;
  1762. 23908                         dep->de_stopf= ne_stop;
  1763. 23909                         dep->de_prog_IO= 1;
  1764. 23910                         return 1;
  1765. 23911                 }
  1766. 23912         }
  1767. 23913         return 0;
  1768. 23914 }
  1769. 23917 /*===========================================================================*
  1770. 23918  *                              test_8                                       *
  1771. 23919  *===========================================================================*/
  1772. 23920 static int test_8(dep, pos, pat)
  1773. 23921 dpeth_t *dep;
  1774. 23922 int pos;
  1775. 23923 u8_t *pat;
  1776. 23924 {
  1777. 23925         u8_t buf[4];
  1778. 23926         int i;
  1779. 23927         int r;
  1780. 23928
  1781. 23929         outb_reg0(dep, DP_ISR, 0xFF);
  1782. 23930
  1783. 23931         /* Setup a transfer to put the pattern. */
  1784. 23932         outb_reg0(dep, DP_RBCR0, 4);
  1785. 23933         outb_reg0(dep, DP_RBCR1, 0);
  1786. 23934         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  1787. 23935         outb_reg0(dep, DP_RSAR1, pos >> 8);
  1788. 23936         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
  1789. 23937
  1790. 23938         for (i= 0; i<4; i++)
  1791. 23939                 outb_ne(dep, NE_DATA, pat[i]);
  1792. 23940
  1793. 23941         for (i= 0; i<N; i++)
  1794. 23942         {
  1795. 23943                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
  1796. 23944                         break;
  1797. 23945         }
  1798. 23946         if (i == N)
  1799. 23947         {
  1800. 23948                 printf("ne2000, test_8: remote dma failed to completen");
  1801. 23949                 return 0;
  1802. .Ep 326 src/kernel/ne2000.c
  1803. 23950         }
  1804. 23951
  1805. 23952         outb_reg0(dep, DP_RBCR0, 4);
  1806. 23953         outb_reg0(dep, DP_RBCR1, 0);
  1807. 23954         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  1808. 23955         outb_reg0(dep, DP_RSAR1, pos >> 8);
  1809. 23956         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  1810. 23957
  1811. 23958         for (i= 0; i<4; i++)
  1812. 23959                 buf[i]= inb_ne(dep, NE_DATA);
  1813. 23960
  1814. 23961         r= (memcmp(buf, pat, 4) == 0);
  1815. 23962         return r;
  1816. 23963 }
  1817. 23966 /*===========================================================================*
  1818. 23967  *                              test_16                                      *
  1819. 23968  *===========================================================================*/
  1820. 23969 static int test_16(dep, pos, pat)
  1821. 23970 dpeth_t *dep;
  1822. 23971 int pos;
  1823. 23972 u8_t *pat;
  1824. 23973 {
  1825. 23974         u8_t buf[4];
  1826. 23975         int i;
  1827. 23976         int r;
  1828. 23977
  1829. 23978         outb_reg0(dep, DP_ISR, 0xFF);
  1830. 23979
  1831. 23980         /* Setup a transfer to put the pattern. */
  1832. 23981         outb_reg0(dep, DP_RBCR0, 4);
  1833. 23982         outb_reg0(dep, DP_RBCR1, 0);
  1834. 23983         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  1835. 23984         outb_reg0(dep, DP_RSAR1, pos >> 8);
  1836. 23985         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
  1837. 23986
  1838. 23987         for (i= 0; i<4; i += 2)
  1839. 23988         {
  1840. 23989                 outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
  1841. 23990         }
  1842. 23991
  1843. 23992         for (i= 0; i<N; i++)
  1844. 23993         {
  1845. 23994                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
  1846. 23995                         break;
  1847. 23996         }
  1848. 23997         if (i == N)
  1849. 23998         {
  1850. 23999                 printf("ne2000, test_16: remote dma failed to completen");
  1851. 24000                 return 0;
  1852. 24001         }
  1853. 24002
  1854. 24003         outb_reg0(dep, DP_RBCR0, 4);
  1855. 24004         outb_reg0(dep, DP_RBCR1, 0);
  1856. 24005         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  1857. 24006         outb_reg0(dep, DP_RSAR1, pos >> 8);
  1858. 24007         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  1859. 24008
  1860. 24009         for (i= 0; i<4; i += 2)
  1861. .Op 327 src/kernel/ne2000.c
  1862. 24010         {
  1863. 24011                 *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
  1864. 24012         }
  1865. 24013
  1866. 24014         r= (memcmp(buf, pat, 4) == 0);
  1867. 24015         return r;
  1868. 24016 }
  1869. 24019 /*===========================================================================*
  1870. 24020  *                              ne_init                                      *
  1871. 24021  *===========================================================================*/
  1872. 24022 static void ne_init(dep)
  1873. 24023 dpeth_t *dep;
  1874. 24024 {
  1875. 24025         int i;
  1876. 24026         int word, sendq_nr;
  1877. 24027
  1878. 24028         /* Setup a transfer to get the ethernet address. */
  1879. 24029         if (dep->de_16bit)
  1880. 24030                 outb_reg0(dep, DP_RBCR0, 6*2);
  1881. 24031         else
  1882. 24032                 outb_reg0(dep, DP_RBCR0, 6);
  1883. 24033         outb_reg0(dep, DP_RBCR1, 0);
  1884. 24034         outb_reg0(dep, DP_RSAR0, 0);
  1885. 24035         outb_reg0(dep, DP_RSAR1, 0);
  1886. 24036         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  1887. 24037
  1888. 24038         for (i= 0; i<6; i++)
  1889. 24039         {
  1890. 24040                 if (dep->de_16bit)
  1891. 24041                 {
  1892. 24042                         word= inw_ne(dep, NE_DATA);
  1893. 24043                         dep->de_address.ea_addr[i]= word;
  1894. 24044                 }
  1895. 24045                 else
  1896. 24046                 {
  1897. 24047                         dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
  1898. 24048                 }
  1899. 24049         }
  1900. 24050         dep->de_data_port= dep->de_base_port + NE_DATA;
  1901. 24051         if (dep->de_16bit)
  1902. 24052         {
  1903. 24053                 dep->de_ramsize= NE2000_SIZE;
  1904. 24054                 dep->de_offset_page= NE2000_START / DP_PAGESIZE;
  1905. 24055         }
  1906. 24056         else
  1907. 24057         {
  1908. 24058                 dep->de_ramsize= NE1000_SIZE;
  1909. 24059                 dep->de_offset_page= NE1000_START / DP_PAGESIZE;
  1910. 24060         }
  1911. 24061
  1912. 24062         /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
  1913. 24063         sendq_nr= dep->de_ramsize / 0x2000;
  1914. 24064         if (sendq_nr < 1)
  1915. 24065                 sendq_nr= 1;
  1916. 24066         else if (sendq_nr > SENDQ_NR)
  1917. 24067                 sendq_nr= SENDQ_NR;
  1918. 24068         dep->de_sendq_nr= sendq_nr;
  1919. 24069         for (i= 0; i<sendq_nr; i++)
  1920. .Ep 328 src/kernel/ne2000.c
  1921. 24070         {
  1922. 24071                 dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
  1923. 24072                         i*SENDQ_PAGES;  
  1924. 24073         }
  1925. 24074
  1926. 24075         dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
  1927. 24076         dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
  1928. 24077
  1929. 24078         /* Can't override the default IRQ. */
  1930. 24079         dep->de_irq &= ~DEI_DEFAULT;
  1931. 24080
  1932. 24081         if (!debug)
  1933. 24082         {
  1934. 24083                 printf("ne2000: NE%d000 at %X:%dn",
  1935. 24084                         dep->de_16bit ? 2 : 1,
  1936. 24085                         dep->de_base_port, dep->de_irq);
  1937. 24086         }
  1938. 24087         else
  1939. 24088         {
  1940. 24089                 printf("ne2000: Novell %s ethernet card ", 
  1941. 24090                         dep->de_16bit ? "16-bit (ne2000)" : "8-bit (ne1000)");
  1942. 24091                 printf("at I/O address 0x%X, memory size 0x%X, irq %dn",
  1943. 24092                         dep->de_base_port, dep->de_ramsize, dep->de_irq);
  1944. 24093         }
  1945. 24094 }
  1946. 24097 /*===========================================================================*
  1947. 24098  *                              ne_stop                                      *
  1948. 24099  *===========================================================================*/
  1949. 24100 static void ne_stop(dep)
  1950. 24101 dpeth_t *dep;
  1951. 24102 {
  1952. 24103         int byte;
  1953. 24104
  1954. 24105         /* Reset the ethernet card */
  1955. 24106         byte= inb_ne(dep, NE_RESET);
  1956. 24107         milli_delay(2);
  1957. 24108         outb_ne(dep, NE_RESET, byte);
  1958. 24109 }
  1959. 24111 #endif /* ENABLE_NETWORKING */
  1960. 24112
  1961. 24113 /*
  1962. 24114  * $PchHeader: /mount/hd2/minix/sys/kernel/ibm/RCS/ne2000.c,v 1.2 1995/01/12 21:48:53 philip Exp $
  1963. 24115  */
  1964. .Op 329 src/kernel/printer.c
  1965. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1966. src/kernel/printer.c    
  1967. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1968. 24200 /* This file contains the printer driver. It is a fairly simple driver,
  1969. 24201  * supporting only one printer.  Characters that are written to the driver
  1970. 24202  * are written to the printer without any changes at all.
  1971. 24203  *
  1972. 24204  * The valid messages and their parameters are:
  1973. 24205  *
  1974. 24206  *   HARD_INT:     interrupt handler has finished current chunk of output
  1975. 24207  *   DEV_WRITE:    a process wants to write on a terminal
  1976. 24208  *   CANCEL:       terminate a previous incomplete system call immediately
  1977. 24209  *
  1978. 24210  *    m_type      TTY_LINE   PROC_NR    COUNT    ADDRESS
  1979. 24211  * -------------------------------------------------------
  1980. 24212  * | HARD_INT    |         |         |         |         |
  1981. 24213  * |-------------+---------+---------+---------+---------|
  1982. 24214  * | DEV_WRITE   |minor dev| proc nr |  count  | buf ptr |
  1983. 24215  * |-------------+---------+---------+---------+---------|
  1984. 24216  * | CANCEL      |minor dev| proc nr |         |         |
  1985. 24217  * -------------------------------------------------------
  1986. 24218  * 
  1987. 24219  * Note: since only 1 printer is supported, minor dev is not used at present.
  1988. 24220  */
  1989. 24221
  1990. 24222 #include "kernel.h"
  1991. 24223 #include <minix/callnr.h>
  1992. 24224 #include <minix/com.h>
  1993. 24225 #include "proc.h"
  1994. 24226
  1995. 24227 /* Control bits (in port_base + 2).  "+" means positive logic and "-" means
  1996. 24228  * negative logic.  Most of the signals are negative logic on the pins but
  1997. 24229  * many are converted to positive logic in the ports.  Some manuals are
  1998. 24230  * misleading because they only document the pin logic.
  1999. 24231  *
  2000. 24232  *      +0x01   Pin 1   -Strobe
  2001. 24233  *      +0x02   Pin 14  -Auto Feed
  2002. 24234  *      -0x04   Pin 16  -Initialize Printer
  2003. 24235  *      +0x08   Pin 17  -Select Printer
  2004. 24236  *      +0x10   IRQ7 Enable
  2005. 24237  *
  2006. 24238  * Auto Feed and Select Printer are always enabled. Strobe is enabled briefly
  2007. 24239  * when characters are output.  Initialize Printer is enabled briefly when
  2008. 24240  * the task is started.  IRQ7 is enabled when the first character is output
  2009. 24241  * and left enabled until output is completed (or later after certain
  2010. 24242  * abnormal completions).
  2011. 24243  */
  2012. 24244 #define ASSERT_STROBE   0x1D    /* strobe a character to the interface */
  2013. 24245 #define NEGATE_STROBE   0x1C    /* enable interrupt on interface */
  2014. 24246 #define SELECT          0x0C    /* select printer bit */
  2015. 24247 #define INIT_PRINTER    0x08    /* init printer bits */
  2016. 24248
  2017. 24249 /* Status bits (in port_base + 2).
  2018. 24250  *
  2019. 24251  *      -0x08   Pin 15  -Error
  2020. 24252  *      +0x10   Pin 13  +Select Status
  2021. 24253  *      +0x20   Pin 12  +Out of Paper
  2022. 24254  *      -0x40   Pin 10  -Acknowledge
  2023. .Ep 330 src/kernel/printer.c
  2024. 24255  *      -0x80   Pin 11  +Busy
  2025. 24256  */
  2026. 24257 #define BUSY_STATUS     0x10    /* printer gives this status when busy */
  2027. 24258 #define NO_PAPER        0x20    /* status bit saying that paper is out */
  2028. 24259 #define NORMAL_STATUS   0x90    /* printer gives this status when idle */
  2029. 24260 #define ON_LINE         0x10    /* status bit saying that printer is online */
  2030. 24261 #define STATUS_MASK     0xB0    /* mask to filter out status bits */ 
  2031. 24262
  2032. 24263 /* Centronics interface timing that must be met by software (in microsec).
  2033. 24264  *
  2034. 24265  * Strobe length:       0.5u to 100u (not sure about the upper limit).
  2035. 24266  * Data set up:         0.5u before strobe.
  2036. 24267  * Data hold:                   0.5u after strobe.
  2037. 24268  * Init pulse length:      over 200u (not sure).
  2038. 24269  *
  2039. 24270  * The strobe length is about 50u with the code here and function calls for
  2040. 24271  * out_byte() - not much to spare.  The 0.5u minimums may be violated if
  2041. 24272  * out_byte() is generated in-line on a fast machine.  Some printer boards
  2042. 24273  * are slower than 0.5u anyway.
  2043. 24274  */
  2044. 24275
  2045. 24276 PRIVATE int caller;             /* process to tell when printing done (FS) */
  2046. 24277 PRIVATE int done_status;        /* status of last output completion */
  2047. 24278 PRIVATE int oleft;              /* bytes of output left in obuf */
  2048. 24279 PRIVATE char obuf[128];         /* output buffer */
  2049. 24280 PRIVATE int opending;           /* nonzero while expected printing not done */
  2050. 24281 PRIVATE char *optr;             /* ptr to next char in obuf to print */
  2051. 24282 PRIVATE int orig_count;         /* original byte count */
  2052. 24283 PRIVATE int port_base;          /* I/O port for printer */
  2053. 24284 PRIVATE int proc_nr;            /* user requesting the printing */
  2054. 24285 PRIVATE int user_left;          /* bytes of output left in user buf */
  2055. 24286 PRIVATE vir_bytes user_vir;     /* address of remainder of user buf */
  2056. 24287 PRIVATE int writing;            /* nonzero while write is in progress */
  2057. 24288
  2058. 24289 FORWARD _PROTOTYPE( void do_cancel, (message *m_ptr) );
  2059. 24290 FORWARD _PROTOTYPE( void do_done, (void) );
  2060. 24291 FORWARD _PROTOTYPE( void do_write, (message *m_ptr) );
  2061. 24292 FORWARD _PROTOTYPE( void pr_start, (void) );
  2062. 24293 FORWARD _PROTOTYPE( void print_init, (void) );
  2063. 24294 FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process,
  2064. 24295                 int status) );
  2065. 24296 FORWARD _PROTOTYPE( int pr_handler, (int irq) );
  2066. 24297
  2067. 24298 /*===========================================================================*
  2068. 24299  *                              printer_task                                 *
  2069. 24300  *===========================================================================*/
  2070. 24301 PUBLIC void printer_task()
  2071. 24302 {
  2072. 24303 /* Main routine of the printer task. */
  2073. 24304
  2074. 24305   message pr_mess;              /* buffer for all incoming messages */
  2075. 24306
  2076. 24307   print_init();                 /* initialize */
  2077. 24308
  2078. 24309   while (TRUE) {
  2079. 24310         receive(ANY, &pr_mess);
  2080. 24311         switch(pr_mess.m_type) {
  2081. 24312             case DEV_OPEN:
  2082. 24313             case DEV_CLOSE:
  2083. 24314                 reply(TASK_REPLY, pr_mess.m_source, pr_mess.PROC_NR, OK);
  2084. .Op 331 src/kernel/printer.c
  2085. 24315                 break;
  2086. 24316             case DEV_WRITE:     do_write(&pr_mess);     break;
  2087. 24317             case CANCEL   :     do_cancel(&pr_mess);    break;
  2088. 24318             case HARD_INT :     do_done();              break;
  2089. 24319             default:
  2090. 24320                 reply(TASK_REPLY, pr_mess.m_source, pr_mess.PROC_NR, EINVAL);
  2091. 24321         }
  2092. 24322   }
  2093. 24323 }
  2094. 24326 /*===========================================================================*
  2095. 24327  *                              do_write                                     *
  2096. 24328  *===========================================================================*/
  2097. 24329 PRIVATE void do_write(m_ptr)
  2098. 24330 register message *m_ptr;        /* pointer to the newly arrived message */
  2099. 24331 {
  2100. 24332 /* The printer is used by sending DEV_WRITE messages to it. Process one. */
  2101. 24333
  2102. 24334   register int r;
  2103. 24335
  2104. 24336   /* Reject command if last write is not finished, count not positive, or
  2105. 24337    * user address bad.
  2106. 24338    */
  2107. 24339   if (writing) {
  2108. 24340         r = EIO;
  2109. 24341   } else
  2110. 24342   if (m_ptr->COUNT <= 0) {
  2111. 24343         r = EINVAL;
  2112. 24344   } else
  2113. 24345   if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
  2114. 24346         r = EFAULT;
  2115. 24347   } else {
  2116. 24348         /* Save information needed later. */
  2117. 24349         caller = m_ptr->m_source;
  2118. 24350         proc_nr = m_ptr->PROC_NR;
  2119. 24351         user_left = m_ptr->COUNT;
  2120. 24352         orig_count = m_ptr->COUNT;
  2121. 24353         user_vir = (vir_bytes) m_ptr->ADDRESS;
  2122. 24354         pr_start();
  2123. 24355         writing = TRUE;
  2124. 24356         r = SUSPEND;
  2125. 24357   }
  2126. 24358
  2127. 24359   /* Reply to FS, no matter what happened. */
  2128. 24360   reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
  2129. 24361 }
  2130. 24364 /*===========================================================================*
  2131. 24365  *                              do_done                                      *
  2132. 24366  *===========================================================================*/
  2133. 24367 PRIVATE void do_done()
  2134. 24368 {
  2135. 24369 /* Previous chunk of printing is finished.  Continue if OK and more.
  2136. 24370  * Otherwise, reply to caller (FS).
  2137. 24371  */
  2138. 24372
  2139. 24373   register int status;
  2140. 24374
  2141. .Ep 332 src/kernel/printer.c
  2142. 24375   if (!writing) return;         /* interrupt while canceling */
  2143. 24376   if (done_status != OK) {
  2144. 24377         /* Printer error. */
  2145. 24378         status = EIO;
  2146. 24379         if ((done_status & ON_LINE) == 0) {
  2147. 24380                 printf("Printer is not on linen");
  2148. 24381         } else
  2149. 24382         if (done_status & NO_PAPER) {
  2150. 24383                 status = EAGAIN;        /* out of paper */
  2151. 24384         } else {
  2152. 24385                 printf("Printer error, status is 0x%02Xn", done_status);
  2153. 24386         }
  2154. 24387         if (status == EAGAIN && user_left < orig_count) {
  2155. 24388                 /* Some characters have been printed, tell how many. */
  2156. 24389                 status = orig_count - user_left;
  2157. 24390         }
  2158. 24391         oleft = 0;              /* cancel output by interrupt handler */
  2159. 24392   } else if (user_left != 0) {
  2160. 24393         pr_start();
  2161. 24394         return;
  2162. 24395   } else {
  2163. 24396         status = orig_count;
  2164. 24397   }
  2165. 24398   reply(REVIVE, caller, proc_nr, status);
  2166. 24399   writing = FALSE;
  2167. 24400 }
  2168. 24403 /*===========================================================================*
  2169. 24404  *                              do_cancel                                    *
  2170. 24405  *===========================================================================*/
  2171. 24406 PRIVATE void do_cancel(m_ptr)
  2172. 24407 register message *m_ptr;        /* pointer to the newly arrived message */
  2173. 24408 {
  2174. 24409 /* Cancel a print request that has already started.  Usually this means that
  2175. 24410  * the process doing the printing has been killed by a signal.  It is not
  2176. 24411  * clear if there are race conditions.  Try not to cancel the wrong process,
  2177. 24412  * but rely on FS to handle the EINTR reply and de-suspension properly.
  2178. 24413  */
  2179. 24414
  2180. 24415   if (writing && m_ptr->PROC_NR == proc_nr) {
  2181. 24416         oleft = 0;              /* cancel output by interrupt handler */
  2182. 24417         writing = FALSE;
  2183. 24418   }
  2184. 24419   reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINTR);
  2185. 24420 }
  2186. 24423 /*===========================================================================*
  2187. 24424  *                              reply                                        *
  2188. 24425  *===========================================================================*/
  2189. 24426 PRIVATE void reply(code, replyee, process, status)
  2190. 24427 int code;                       /* TASK_REPLY or REVIVE */
  2191. 24428 int replyee;                    /* destination for message (normally FS) */
  2192. 24429 int process;                    /* which user requested the printing */
  2193. 24430 int status;                     /* number of  chars printed or error code */
  2194. 24431 {
  2195. 24432 /* Send a reply telling FS that printing has started or stopped. */
  2196. 24433
  2197. 24434   message pr_mess;
  2198. .Op 333 src/kernel/printer.c
  2199. 24435
  2200. 24436   pr_mess.m_type = code;        /* TASK_REPLY or REVIVE */
  2201. 24437   pr_mess.REP_STATUS = status;  /* count or EIO */
  2202. 24438   pr_mess.REP_PROC_NR = process;        /* which user does this pertain to */
  2203. 24439   send(replyee, &pr_mess);      /* send the message */
  2204. 24440 }
  2205. 24443 /*===========================================================================*
  2206. 24444  *                              print_init                                   *
  2207. 24445  *===========================================================================*/
  2208. 24446 PRIVATE void print_init()
  2209. 24447 {
  2210. 24448 /* Set global variables.  Get the port base for the first printer from the
  2211. 24449  * BIOS and initialize the printer.
  2212. 24450  */
  2213. 24451
  2214. 24452   phys_copy(0x408L, vir2phys(&port_base), 2L);
  2215. 24453   out_byte(port_base + 2, INIT_PRINTER);
  2216. 24454   milli_delay(2);               /* easily satisfies Centronics minimum */
  2217. 24455   out_byte(port_base + 2, SELECT);
  2218. 24456   put_irq_handler(PRINTER_IRQ, pr_handler);
  2219. 24457   enable_irq(PRINTER_IRQ);              /* ready for printer interrupts */
  2220. 24458 }
  2221. 24461 /*==========================================================================*
  2222. 24462  *                              pr_start                                    *
  2223. 24463  *==========================================================================*/
  2224. 24464 PRIVATE void pr_start()
  2225. 24465 {
  2226. 24466 /* Start next chunk of printer output. */
  2227. 24467
  2228. 24468   register int chunk;
  2229. 24469   phys_bytes user_phys;
  2230. 24470
  2231. 24471   if ( (chunk = user_left) > sizeof obuf) chunk = sizeof obuf;
  2232. 24472   user_phys = proc_vir2phys(proc_addr(proc_nr), user_vir);
  2233. 24473   phys_copy(user_phys, vir2phys(obuf), (phys_bytes) chunk);
  2234. 24474   optr = obuf;
  2235. 24475   opending = TRUE;
  2236. 24476   oleft = chunk;                /* now interrupt handler is enabled */
  2237. 24477 }
  2238. 24480 /*===========================================================================*
  2239. 24481  *                              pr_handler                                   *
  2240. 24482  *===========================================================================*/
  2241. 24483 PRIVATE int pr_handler(irq)
  2242. 24484 int irq;
  2243. 24485 {
  2244. 24486 /* This is the interrupt handler.  When a character has been printed, an
  2245. 24487  * interrupt occurs, and the assembly code routine trapped to calls
  2246. 24488  * pr_handler().
  2247. 24489  *
  2248. 24490  * One problem is that the 8259A controller generates spurious interrupts to
  2249. 24491  * IRQ7 when it gets confused by mistimed interrupts on any line.  (IRQ7 for
  2250. 24492  * the first controller happens to be the printer IRQ.)  Such an interrupt is
  2251. 24493  * ignored as a side-affect of the method of checking the busy status.  This
  2252. 24494  * is harmless for the printer task but probably fatal to the task that missed
  2253. .Ep 334 src/kernel/printer.c
  2254. 24495  * the interrupt.  It may be possible to recover by doing more work here.
  2255. 24496  */
  2256. 24497
  2257. 24498   register int status;
  2258. 24499
  2259. 24500   if (oleft == 0) {
  2260. 24501         /* Nothing more to print.  Turn off printer interrupts in case they
  2261. 24502          * are level-sensitive as on the PS/2.  This should be safe even
  2262. 24503          * when the printer is busy with a previous character, because the
  2263. 24504          * interrupt status does not affect the printer.
  2264. 24505          */
  2265. 24506         out_byte(port_base + 2, SELECT);
  2266. 24507         return 1;
  2267. 24508   }
  2268. 24509
  2269. 24510   do {
  2270. 24511         /* Loop to handle fast (buffered) printers.  It is important that
  2271. 24512          * processor interrupts are not disabled here, just printer interrupts.
  2272. 24513          */
  2273. 24514         status = in_byte(port_base + 1);
  2274. 24515         if ((status & STATUS_MASK) == BUSY_STATUS) {
  2275. 24516                 /* Still busy with last output.  This normally happens
  2276. 24517                  * immediately after doing output to an unbuffered or slow
  2277. 24518                  * printer.  It may happen after a call from pr_start or
  2278. 24519                  * pr_restart, since they are not synchronized with printer
  2279. 24520                  * interrupts.  It may happen after a spurious interrupt.
  2280. 24521                  */
  2281. 24522                 return 1;
  2282. 24523         }
  2283. 24524         if ((status & STATUS_MASK) == NORMAL_STATUS) {
  2284. 24525                 /* Everything is all right.  Output another character. */
  2285. 24526                 out_byte(port_base, *optr++);   /* output character */
  2286. 24527                 lock();         /* ensure strobe is not too long */
  2287. 24528                 out_byte(port_base + 2, ASSERT_STROBE);
  2288. 24529                 out_byte(port_base + 2, NEGATE_STROBE);
  2289. 24530                 unlock();
  2290. 24531                 opending = FALSE;       /* show interrupt is working */
  2291. 24532
  2292. 24533                 user_vir++;
  2293. 24534                 user_left--;
  2294. 24535         } else {
  2295. 24536                 /* Error.  This would be better ignored (treat as busy). */
  2296. 24537                 done_status = status;
  2297. 24538                 interrupt(PRINTER);
  2298. 24539                 return 1;
  2299. 24540         }
  2300. 24541   }
  2301. 24542   while (--oleft != 0);
  2302. 24543
  2303. 24544   /* Finished printing chunk OK. */
  2304. 24545   done_status = OK;
  2305. 24546   interrupt(PRINTER);
  2306. 24547   return 1;     /* Reenable printer interrupt */
  2307. 24548 }
  2308. 24551 /*==========================================================================*
  2309. 24552  *                              pr_restart                                  *
  2310. 24553  *==========================================================================*/
  2311. 24554 PUBLIC void pr_restart()
  2312. .Op 335 src/kernel/printer.c
  2313. 24555 {
  2314. 24556 /* Check if printer is hung up, and if so, restart it.
  2315. 24557  * Disable_irq() returns true if the irq could be disabled, so that
  2316. 24558  * pr_restart() is not reentered.
  2317. 24559  */
  2318. 24560
  2319. 24561   if (oleft != 0) {
  2320. 24562         if (opending && disable_irq(PRINTER_IRQ)) {
  2321. 24563                 (void) pr_handler(PRINTER_IRQ);
  2322. 24564
  2323. 24565                 /* ready for printer interrupts again */
  2324. 24566                 enable_irq(PRINTER_IRQ);
  2325. 24567         }
  2326. 24568         opending = TRUE;        /* expect some printing before next call */
  2327. 24569   }
  2328. 24570 }
  2329. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2330. src/kernel/proc.c    
  2331. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2332. 24600 /* This file contains essentially all of the process and message handling.
  2333. 24601  * It has two main entry points from the outside:
  2334. 24602  *
  2335. 24603  *   sys_call:   called when a process or task does SEND, RECEIVE or SENDREC
  2336. 24604  *   interrupt: called by interrupt routines to send a message to task
  2337. 24605  *
  2338. 24606  * It also has several minor entry points:
  2339. 24607  *
  2340. 24608  *   lock_ready:      put a process on one of the ready queues so it can be run
  2341. 24609  *   lock_unready:    remove a process from the ready queues
  2342. 24610  *   lock_sched:      a process has run too long; schedule another one
  2343. 24611  *   lock_mini_send:  send a message (used by interrupt signals, etc.)
  2344. 24612  *   lock_pick_proc:  pick a process to run (used by system initialization)
  2345. 24613  *   unhold:          repeat all held-up interrupts
  2346. 24614  */
  2347. 24615
  2348. 24616 #include "kernel.h"
  2349. 24617 #include <minix/callnr.h>
  2350. 24618 #include <minix/com.h>
  2351. 24619 #include "proc.h"
  2352. 24620
  2353. 24621 PRIVATE unsigned char switching;        /* nonzero to inhibit interrupt() */
  2354. 24622
  2355. 24623 FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dest,
  2356. 24624                 message *m_ptr) );
  2357. 24625 FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
  2358. 24626                 message *m_ptr) );
  2359. 24627 FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
  2360. 24628 FORWARD _PROTOTYPE( void sched, (void) );
  2361. 24629 FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
  2362. 24630 FORWARD _PROTOTYPE( void pick_proc, (void) );
  2363. 24631
  2364. 24632 #if (CHIP == M68000)
  2365. 24633 FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
  2366. 24634                 struct proc *dst_p, message *dst_m) );
  2367. .Ep 336 src/kernel/proc.c
  2368. 24635 #endif
  2369. 24636
  2370. 24637 #if (CHIP == INTEL)
  2371. 24638 #define CopyMess(s,sp,sm,dp,dm) 
  2372. 24639         cp_mess(s, (sp)->p_map[D].mem_phys, (vir_bytes)sm, (dp)->p_map[D].mem_phys, (vir_bytes)dm)
  2373. 24640 #endif
  2374. 24641
  2375. 24642 #if (CHIP == M68000)
  2376. 24643 #define CopyMess(s,sp,sm,dp,dm) 
  2377. 24644         cp_mess(s,sp,sm,dp,dm)
  2378. 24645 #endif
  2379. 24646
  2380. 24647 /*===========================================================================*
  2381. 24648  *                              interrupt                                    * 
  2382. 24649  *===========================================================================*/
  2383. 24650 PUBLIC void interrupt(task)
  2384. 24651 int task;                       /* number of task to be started */
  2385. 24652 {
  2386. 24653 /* An interrupt has occurred.  Schedule the task that handles it. */
  2387. 24654
  2388. 24655   register struct proc *rp;     /* pointer to task's proc entry */
  2389. 24656
  2390. 24657   rp = proc_addr(task);
  2391. 24658
  2392. 24659   /* If this call would compete with other process-switching functions, put
  2393. 24660    * it on the 'held' queue to be flushed at the next non-competing restart().
  2394. 24661    * The competing conditions are:
  2395. 24662    * (1) k_reenter == (typeof k_reenter) -1:
  2396. 24663    *     Call from the task level, typically from an output interrupt
  2397. 24664    *     routine.  An interrupt handler might reenter interrupt().  Rare,
  2398. 24665    *     so not worth special treatment.
  2399. 24666    * (2) k_reenter > 0:
  2400. 24667    *     Call from a nested interrupt handler.  A previous interrupt handler
  2401. 24668    *     might be inside interrupt() or sys_call().
  2402. 24669    * (3) switching != 0:
  2403. 24670    *     Some process-switching function other than interrupt() is being
  2404. 24671    *     called from the task level, typically sched() from CLOCK.  An
  2405. 24672    *     interrupt handler might call interrupt and pass the k_reenter test.
  2406. 24673    */
  2407. 24674   if (k_reenter != 0 || switching) {
  2408. 24675         lock();
  2409. 24676         if (!rp->p_int_held) {
  2410. 24677                 rp->p_int_held = TRUE;
  2411. 24678                 if (held_head != NIL_PROC)
  2412. 24679                         held_tail->p_nextheld = rp;
  2413. 24680                 else
  2414. 24681                         held_head = rp;
  2415. 24682                 held_tail = rp;
  2416. 24683                 rp->p_nextheld = NIL_PROC;
  2417. 24684         }
  2418. 24685         unlock();
  2419. 24686         return;
  2420. 24687   }
  2421. 24688
  2422. 24689   /* If task is not waiting for an interrupt, record the blockage. */
  2423. 24690   if ( (rp->p_flags & (RECEIVING | SENDING)) != RECEIVING ||
  2424. 24691       !isrxhardware(rp->p_getfrom)) {
  2425. 24692         rp->p_int_blocked = TRUE;
  2426. 24693         return;
  2427. 24694   }
  2428. .Op 337 src/kernel/proc.c
  2429. 24695
  2430. 24696   /* Destination is waiting for an interrupt.
  2431. 24697    * Send it a message with source HARDWARE and type HARD_INT.
  2432. 24698    * No more information can be reliably provided since interrupt messages
  2433. 24699    * are not queued.
  2434. 24700    */
  2435. 24701   rp->p_messbuf->m_source = HARDWARE;
  2436. 24702   rp->p_messbuf->m_type = HARD_INT;
  2437. 24703   rp->p_flags &= ~RECEIVING;
  2438. 24704   rp->p_int_blocked = FALSE;
  2439. 24705
  2440. 24706    /* Make rp ready and run it unless a task is already running.  This is
  2441. 24707     * ready(rp) in-line for speed.
  2442. 24708     */
  2443. 24709   if (rdy_head[TASK_Q] != NIL_PROC)
  2444. 24710         rdy_tail[TASK_Q]->p_nextready = rp;
  2445. 24711   else
  2446. 24712         proc_ptr = rdy_head[TASK_Q] = rp;
  2447. 24713   rdy_tail[TASK_Q] = rp;
  2448. 24714   rp->p_nextready = NIL_PROC;
  2449. 24715 }
  2450. 24717 /*===========================================================================*
  2451. 24718  *                              sys_call                                     * 
  2452. 24719  *===========================================================================*/
  2453. 24720 PUBLIC int sys_call(function, src_dest, m_ptr)
  2454. 24721 int function;                   /* SEND, RECEIVE, or BOTH */
  2455. 24722 int src_dest;                   /* source to receive from or dest to send to */
  2456. 24723 message *m_ptr;                 /* pointer to message */
  2457. 24724 {
  2458. 24725 /* The only system calls that exist in MINIX are sending and receiving
  2459. 24726  * messages.  These are done by trapping to the kernel with an INT instruction.
  2460. 24727  * The trap is caught and sys_call() is called to send or receive a message
  2461. 24728  * (or both). The caller is always given by proc_ptr.
  2462. 24729  */
  2463. 24730
  2464. 24731   register struct proc *rp;
  2465. 24732   int n;
  2466. 24733
  2467. 24734   /* Check for bad system call parameters. */
  2468. 24735   if (!isoksrc_dest(src_dest)) return(E_BAD_SRC);
  2469. 24736   rp = proc_ptr;
  2470. 24737
  2471. 24738   if (isuserp(rp) && function != BOTH) return(E_NO_PERM);
  2472. 24739   
  2473. 24740   /* The parameters are ok. Do the call. */
  2474. 24741   if (function & SEND) {
  2475. 24742         /* Function = SEND or BOTH. */
  2476. 24743         n = mini_send(rp, src_dest, m_ptr);
  2477. 24744         if (function == SEND || n != OK)
  2478. 24745                 return(n);      /* done, or SEND failed */
  2479. 24746   }
  2480. 24747
  2481. 24748   /* Function = RECEIVE or BOTH.
  2482. 24749    * We have checked user calls are BOTH, and trust 'function' otherwise.
  2483. 24750    */
  2484. 24751   return(mini_rec(rp, src_dest, m_ptr));
  2485. 24752 }
  2486. 24754 /*===========================================================================*
  2487. .Ep 338 src/kernel/proc.c
  2488. 24755  *                              mini_send                                    * 
  2489. 24756  *===========================================================================*/
  2490. 24757 PRIVATE int mini_send(caller_ptr, dest, m_ptr)
  2491. 24758 register struct proc *caller_ptr;       /* who is trying to send a message? */
  2492. 24759 int dest;                       /* to whom is message being sent? */
  2493. 24760 message *m_ptr;                 /* pointer to message buffer */
  2494. 24761 {
  2495. 24762 /* Send a message from 'caller_ptr' to 'dest'. If 'dest' is blocked waiting
  2496. 24763  * for this message, copy the message to it and unblock 'dest'. If 'dest' is
  2497. 24764  * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
  2498. 24765  */
  2499. 24766
  2500. 24767   register struct proc *dest_ptr, *next_ptr;
  2501. 24768   vir_bytes vb;                 /* message buffer pointer as vir_bytes */
  2502. 24769   vir_clicks vlo, vhi;          /* virtual clicks containing message to send */
  2503. 24770
  2504. 24771   /* User processes are only allowed to send to FS and MM.  Check for this. */
  2505. 24772   if (isuserp(caller_ptr) && !issysentn(dest)) return(E_BAD_DEST);
  2506. 24773   dest_ptr = proc_addr(dest);   /* pointer to destination's proc entry */
  2507. 24774   if (dest_ptr->p_flags & P_SLOT_FREE) return(E_BAD_DEST);      /* dead dest */
  2508. 24775
  2509. 24776 #if ALLOW_GAP_MESSAGES
  2510. 24777   /* This check allows a message to be anywhere in data or stack or gap. 
  2511. 24778    * It will have to be made more elaborate later for machines which
  2512. 24779    * don't have the gap mapped.
  2513. 24780    */
  2514. 24781   vb = (vir_bytes) m_ptr;
  2515. 24782   vlo = vb >> CLICK_SHIFT;      /* vir click for bottom of message */
  2516. 24783   vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT;    /* vir click for top of msg */
  2517. 24784   if (vlo < caller_ptr->p_map[D].mem_vir || vlo > vhi ||
  2518. 24785       vhi >= caller_ptr->p_map[S].mem_vir + caller_ptr->p_map[S].mem_len)
  2519. 24786         return(EFAULT); 
  2520. 24787 #else
  2521. 24788   /* Check for messages wrapping around top of memory or outside data seg. */
  2522. 24789   vb = (vir_bytes) m_ptr;
  2523. 24790   vlo = vb >> CLICK_SHIFT;      /* vir click for bottom of message */
  2524. 24791   vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT;    /* vir click for top of msg */
  2525. 24792   if (vhi < vlo ||
  2526. 24793       vhi - caller_ptr->p_map[D].mem_vir >= caller_ptr->p_map[D].mem_len)
  2527. 24794         return(EFAULT);
  2528. 24795 #endif
  2529. 24796
  2530. 24797   /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
  2531. 24798   if (dest_ptr->p_flags & SENDING) {
  2532. 24799         next_ptr = proc_addr(dest_ptr->p_sendto);
  2533. 24800         while (TRUE) {
  2534. 24801                 if (next_ptr == caller_ptr) return(ELOCKED);
  2535. 24802                 if (next_ptr->p_flags & SENDING)
  2536. 24803                         next_ptr = proc_addr(next_ptr->p_sendto);
  2537. 24804                 else
  2538. 24805                         break;
  2539. 24806         }
  2540. 24807   }
  2541. 24808
  2542. 24809   /* Check to see if 'dest' is blocked waiting for this message. */
  2543. 24810   if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
  2544. 24811        (dest_ptr->p_getfrom == ANY ||
  2545. 24812         dest_ptr->p_getfrom == proc_number(caller_ptr))) {
  2546. 24813         /* Destination is indeed waiting for this message. */
  2547. 24814         CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
  2548. .Op 339 src/kernel/proc.c
  2549. 24815                  dest_ptr->p_messbuf);
  2550. 24816         dest_ptr->p_flags &= ~RECEIVING;        /* deblock destination */
  2551. 24817         if (dest_ptr->p_flags == 0) ready(dest_ptr);
  2552. 24818   } else {
  2553. 24819         /* Destination is not waiting.  Block and queue caller. */
  2554. 24820         caller_ptr->p_messbuf = m_ptr;
  2555. 24821         if (caller_ptr->p_flags == 0) unready(caller_ptr);
  2556. 24822         caller_ptr->p_flags |= SENDING;
  2557. 24823         caller_ptr->p_sendto= dest;
  2558. 24824
  2559. 24825         /* Process is now blocked.  Put in on the destination's queue. */
  2560. 24826         if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
  2561. 24827                 dest_ptr->p_callerq = caller_ptr;
  2562. 24828         else {
  2563. 24829                 while (next_ptr->p_sendlink != NIL_PROC)
  2564. 24830                         next_ptr = next_ptr->p_sendlink;
  2565. 24831                 next_ptr->p_sendlink = caller_ptr;
  2566. 24832         }
  2567. 24833         caller_ptr->p_sendlink = NIL_PROC;
  2568. 24834   }
  2569. 24835   return(OK);
  2570. 24836 }
  2571. 24838 /*===========================================================================*
  2572. 24839  *                              mini_rec                                     * 
  2573. 24840  *===========================================================================*/
  2574. 24841 PRIVATE int mini_rec(caller_ptr, src, m_ptr)
  2575. 24842 register struct proc *caller_ptr;       /* process trying to get message */
  2576. 24843 int src;                        /* which message source is wanted (or ANY) */
  2577. 24844 message *m_ptr;                 /* pointer to message buffer */
  2578. 24845 {
  2579. 24846 /* A process or task wants to get a message.  If one is already queued,
  2580. 24847  * acquire it and deblock the sender.  If no message from the desired source
  2581. 24848  * is available, block the caller.  No need to check parameters for validity.
  2582. 24849  * Users calls are always sendrec(), and mini_send() has checked already.  
  2583. 24850  * Calls from the tasks, MM, and FS are trusted.
  2584. 24851  */
  2585. 24852
  2586. 24853   register struct proc *sender_ptr;
  2587. 24854   register struct proc *previous_ptr;
  2588. 24855
  2589. 24856   /* Check to see if a message from desired source is already available. */
  2590. 24857   if (!(caller_ptr->p_flags & SENDING)) {
  2591. 24858         /* Check caller queue. */
  2592. 24859     for (sender_ptr = caller_ptr->p_callerq; sender_ptr != NIL_PROC;
  2593. 24860          previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) {
  2594. 24861         if (src == ANY || src == proc_number(sender_ptr)) {
  2595. 24862                 /* An acceptable message has been found. */
  2596. 24863                 CopyMess(proc_number(sender_ptr), sender_ptr,
  2597. 24864                          sender_ptr->p_messbuf, caller_ptr, m_ptr);
  2598. 24865                 if (sender_ptr == caller_ptr->p_callerq)
  2599. 24866                         caller_ptr->p_callerq = sender_ptr->p_sendlink;
  2600. 24867                 else
  2601. 24868                         previous_ptr->p_sendlink = sender_ptr->p_sendlink;
  2602. 24869                 if ((sender_ptr->p_flags &= ~SENDING) == 0)
  2603. 24870                         ready(sender_ptr);      /* deblock sender */
  2604. 24871                 return(OK);
  2605. 24872         }
  2606. 24873     }
  2607. 24874
  2608. .Ep 340 src/kernel/proc.c
  2609. 24875     /* Check for blocked interrupt. */
  2610. 24876     if (caller_ptr->p_int_blocked && isrxhardware(src)) {
  2611. 24877         m_ptr->m_source = HARDWARE;
  2612. 24878         m_ptr->m_type = HARD_INT;
  2613. 24879         caller_ptr->p_int_blocked = FALSE;
  2614. 24880         return(OK);
  2615. 24881     }
  2616. 24882   }
  2617. 24883
  2618. 24884   /* No suitable message is available.  Block the process trying to receive. */
  2619. 24885   caller_ptr->p_getfrom = src;
  2620. 24886   caller_ptr->p_messbuf = m_ptr;
  2621. 24887   if (caller_ptr->p_flags == 0) unready(caller_ptr);
  2622. 24888   caller_ptr->p_flags |= RECEIVING;
  2623. 24889
  2624. 24890   /* If MM has just blocked and there are kernel signals pending, now is the
  2625. 24891    * time to tell MM about them, since it will be able to accept the message.
  2626. 24892    */
  2627. 24893   if (sig_procs > 0 && proc_number(caller_ptr) == MM_PROC_NR && src == ANY)
  2628. 24894         inform();
  2629. 24895   return(OK);
  2630. 24896 }
  2631. 24898 /*===========================================================================*
  2632. 24899  *                              pick_proc                                    * 
  2633. 24900  *===========================================================================*/
  2634. 24901 PRIVATE void pick_proc()
  2635. 24902 {
  2636. 24903 /* Decide who to run now.  A new process is selected by setting 'proc_ptr'.
  2637. 24904  * When a fresh user (or idle) process is selected, record it in 'bill_ptr',
  2638. 24905  * so the clock task can tell who to bill for system time.
  2639. 24906  */
  2640. 24907
  2641. 24908   register struct proc *rp;     /* process to run */
  2642. 24909
  2643. 24910   if ( (rp = rdy_head[TASK_Q]) != NIL_PROC) {
  2644. 24911         proc_ptr = rp;
  2645. 24912         return;
  2646. 24913   }
  2647. 24914   if ( (rp = rdy_head[SERVER_Q]) != NIL_PROC) {
  2648. 24915         proc_ptr = rp;
  2649. 24916         return;
  2650. 24917   }
  2651. 24918   if ( (rp = rdy_head[USER_Q]) != NIL_PROC) {
  2652. 24919         proc_ptr = rp;
  2653. 24920         bill_ptr = rp;
  2654. 24921         return;
  2655. 24922   }
  2656. 24923   /* No one is ready.  Run the idle task.  The idle task might be made an
  2657. 24924    * always-ready user task to avoid this special case.
  2658. 24925    */
  2659. 24926   bill_ptr = proc_ptr = proc_addr(IDLE);
  2660. 24927 }
  2661. 24929 /*===========================================================================*
  2662. 24930  *                              ready                                        * 
  2663. 24931  *===========================================================================*/
  2664. 24932 PRIVATE void ready(rp)
  2665. 24933 register struct proc *rp;       /* this process is now runnable */
  2666. 24934 {
  2667. .Op 341 src/kernel/proc.c
  2668. 24935 /* Add 'rp' to the end of one of the queues of runnable processes. Three
  2669. 24936  * queues are maintained:
  2670. 24937  *   TASK_Q   - (highest priority) for runnable tasks
  2671. 24938  *   SERVER_Q - (middle priority) for MM and FS only
  2672. 24939  *   USER_Q   - (lowest priority) for user processes
  2673. 24940  */
  2674. 24941
  2675. 24942   if (istaskp(rp)) {
  2676. 24943         if (rdy_head[TASK_Q] != NIL_PROC)
  2677. 24944                 /* Add to tail of nonempty queue. */
  2678. 24945                 rdy_tail[TASK_Q]->p_nextready = rp;
  2679. 24946         else {
  2680. 24947                 proc_ptr =              /* run fresh task next */
  2681. 24948                 rdy_head[TASK_Q] = rp;  /* add to empty queue */
  2682. 24949         }
  2683. 24950         rdy_tail[TASK_Q] = rp;
  2684. 24951         rp->p_nextready = NIL_PROC;     /* new entry has no successor */
  2685. 24952         return;
  2686. 24953   }
  2687. 24954   if (!isuserp(rp)) {           /* others are similar */
  2688. 24955         if (rdy_head[SERVER_Q] != NIL_PROC)
  2689. 24956                 rdy_tail[SERVER_Q]->p_nextready = rp;
  2690. 24957         else
  2691. 24958                 rdy_head[SERVER_Q] = rp;
  2692. 24959         rdy_tail[SERVER_Q] = rp;
  2693. 24960         rp->p_nextready = NIL_PROC;
  2694. 24961         return;
  2695. 24962   }
  2696. 24963 #if (SHADOWING == 1)
  2697. 24964   if (isshadowp(rp)) {          /* others are similar */
  2698. 24965         if (rdy_head[SHADOW_Q] != NIL_PROC)
  2699. 24966                 rdy_tail[SHADOW_Q]->p_nextready = rp;
  2700. 24967         else
  2701. 24968                 rdy_head[SHADOW_Q] = rp;
  2702. 24969         rdy_tail[SHADOW_Q] = rp;
  2703. 24970         rp->p_nextready = NIL_PROC;
  2704. 24971         return;
  2705. 24972   }
  2706. 24973 #endif
  2707. 24974   if (rdy_head[USER_Q] == NIL_PROC)
  2708. 24975         rdy_tail[USER_Q] = rp;
  2709. 24976   rp->p_nextready = rdy_head[USER_Q];
  2710. 24977   rdy_head[USER_Q] = rp;
  2711. 24978 /*
  2712. 24979   if (rdy_head[USER_Q] != NIL_PROC)
  2713. 24980         rdy_tail[USER_Q]->p_nextready = rp;
  2714. 24981   else
  2715. 24982         rdy_head[USER_Q] = rp;
  2716. 24983   rdy_tail[USER_Q] = rp;
  2717. 24984   rp->p_nextready = NIL_PROC;
  2718. 24985 */
  2719. 24986 }
  2720. 24988 /*===========================================================================*
  2721. 24989  *                              unready                                      * 
  2722. 24990  *===========================================================================*/
  2723. 24991 PRIVATE void unready(rp)
  2724. 24992 register struct proc *rp;       /* this process is no longer runnable */
  2725. 24993 {
  2726. 24994 /* A process has blocked. */
  2727. .Ep 342 src/kernel/proc.c
  2728. 24995
  2729. 24996   register struct proc *xp;
  2730. 24997   register struct proc **qtail;  /* TASK_Q, SERVER_Q, or USER_Q rdy_tail */
  2731. 24998
  2732. 24999   if (istaskp(rp)) {
  2733. 25000         /* task stack still ok? */
  2734. 25001         if (*rp->p_stguard != STACK_GUARD)
  2735. 25002                 panic("stack overrun by task", proc_number(rp));
  2736. 25003
  2737. 25004         if ( (xp = rdy_head[TASK_Q]) == NIL_PROC) return;
  2738. 25005         if (xp == rp) {
  2739. 25006                 /* Remove head of queue */
  2740. 25007                 rdy_head[TASK_Q] = xp->p_nextready;
  2741. 25008                 if (rp == proc_ptr) pick_proc();
  2742. 25009                 return;
  2743. 25010         }
  2744. 25011         qtail = &rdy_tail[TASK_Q];
  2745. 25012   }
  2746. 25013   else if (!isuserp(rp)) {
  2747. 25014         if ( (xp = rdy_head[SERVER_Q]) == NIL_PROC) return;
  2748. 25015         if (xp == rp) {
  2749. 25016                 rdy_head[SERVER_Q] = xp->p_nextready;
  2750. 25017 #if (CHIP == M68000)
  2751. 25018                 if (rp == proc_ptr)
  2752. 25019 #endif
  2753. 25020                 pick_proc();
  2754. 25021                 return;
  2755. 25022         }
  2756. 25023         qtail = &rdy_tail[SERVER_Q];
  2757. 25024   } else
  2758. 25025 #if (SHADOWING == 1)
  2759. 25026   if (isshadowp(rp)) {
  2760. 25027         if ( (xp = rdy_head[SHADOW_Q]) == NIL_PROC) return;
  2761. 25028         if (xp == rp) {
  2762. 25029                 rdy_head[SHADOW_Q] = xp->p_nextready;
  2763. 25030                 if (rp == proc_ptr)
  2764. 25031                         pick_proc();
  2765. 25032                 return;
  2766. 25033         }
  2767. 25034         qtail = &rdy_tail[SHADOW_Q];
  2768. 25035   } else
  2769. 25036 #endif
  2770. 25037   {
  2771. 25038         if ( (xp = rdy_head[USER_Q]) == NIL_PROC) return;
  2772. 25039         if (xp == rp) {
  2773. 25040                 rdy_head[USER_Q] = xp->p_nextready;
  2774. 25041 #if (CHIP == M68000)
  2775. 25042                 if (rp == proc_ptr)
  2776. 25043 #endif
  2777. 25044                 pick_proc();
  2778. 25045                 return;
  2779. 25046         }
  2780. 25047         qtail = &rdy_tail[USER_Q];
  2781. 25048   }
  2782. 25049
  2783. 25050   /* Search body of queue.  A process can be made unready even if it is
  2784. 25051    * not running by being sent a signal that kills it.
  2785. 25052    */
  2786. 25053   while (xp->p_nextready != rp)
  2787. 25054         if ( (xp = xp->p_nextready) == NIL_PROC) return;
  2788. .Op 343 src/kernel/proc.c
  2789. 25055   xp->p_nextready = xp->p_nextready->p_nextready;
  2790. 25056   if (*qtail == rp) *qtail = xp;
  2791. 25057 }
  2792. 25059 /*===========================================================================*
  2793. 25060  *                              sched                                        * 
  2794. 25061  *===========================================================================*/
  2795. 25062 PRIVATE void sched()
  2796. 25063 {
  2797. 25064 /* The current process has run too long.  If another low priority (user)
  2798. 25065  * process is runnable, put the current process on the end of the user queue,
  2799. 25066  * possibly promoting another user to head of the queue.
  2800. 25067  */
  2801. 25068
  2802. 25069   if (rdy_head[USER_Q] == NIL_PROC) return;
  2803. 25070
  2804. 25071   /* One or more user processes queued. */
  2805. 25072   rdy_tail[USER_Q]->p_nextready = rdy_head[USER_Q];
  2806. 25073   rdy_tail[USER_Q] = rdy_head[USER_Q];
  2807. 25074   rdy_head[USER_Q] = rdy_head[USER_Q]->p_nextready;
  2808. 25075   rdy_tail[USER_Q]->p_nextready = NIL_PROC;
  2809. 25076   pick_proc();
  2810. 25077 }
  2811. 25079 /*==========================================================================*
  2812. 25080  *                              lock_mini_send                              *
  2813. 25081  *==========================================================================*/
  2814. 25082 PUBLIC int lock_mini_send(caller_ptr, dest, m_ptr)
  2815. 25083 struct proc *caller_ptr;        /* who is trying to send a message? */
  2816. 25084 int dest;                       /* to whom is message being sent? */
  2817. 25085 message *m_ptr;                 /* pointer to message buffer */
  2818. 25086 {
  2819. 25087 /* Safe gateway to mini_send() for tasks. */
  2820. 25088
  2821. 25089   int result;
  2822. 25090
  2823. 25091   switching = TRUE;
  2824. 25092   result = mini_send(caller_ptr, dest, m_ptr);
  2825. 25093   switching = FALSE;
  2826. 25094   return(result);
  2827. 25095 }
  2828. 25097 /*==========================================================================*
  2829. 25098  *                              lock_pick_proc                              *
  2830. 25099  *==========================================================================*/
  2831. 25100 PUBLIC void lock_pick_proc()
  2832. 25101 {
  2833. 25102 /* Safe gateway to pick_proc() for tasks. */
  2834. 25103
  2835. 25104   switching = TRUE;
  2836. 25105   pick_proc();
  2837. 25106   switching = FALSE;
  2838. 25107 }