COMPLETE.T
资源名称:os_source.zip [点击查看]
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:2535k
源码类别:
操作系统开发
开发平台:
C/C++
- 22010 #include "kernel.h"
- 22011 #include "driver.h"
- 22012 #include "drvlib.h"
- 22013 #include <minix/cdrom.h>
- 22014 #include <sys/ioctl.h>
- 22015
- 22016 #if ENABLE_MITSUMI_CDROM
- 22017
- 22018 #define MCD_DEBUG 0 /* debug level */
- 22019
- 22020 /* Default IRQ. */
- 22021 #define MCD_IRQ 10
- 22022
- 22023 /* Default I/O ports (offset from base address */
- 22024 #define MCD_IO_BASE_ADDRESS 0x300
- 22025 #define MCD_DATA_PORT (mcd_io_base+0)
- 22026 #define MCD_FLAG_PORT (mcd_io_base+1)
- 22027 #define MCD_CONTROL_PORT (mcd_io_base+2)
- 22028
- 22029
- 22030 /* Miscellaneous constants. */
- 22031 #define MCD_SKIP 150 /* Skip first 150 blocks on cdrom */
- 22032 #define MCD_BLOCK_SIZE 2048 /* Block size in cooked mode */
- 22033 #define MCD_BLOCK_SHIFT 11 /* for division */
- 22034 #define MCD_BLOCK_MASK 2047 /* and remainder */
- 22035 #define BYTES_PER_SECTOR 2048 /* Nr. of bytes in a sector */
- 22036 #define SECTORS_PER_SECOND 75 /* Nr. of sectors in a second */
- 22037 #define SECONDS_PER_MINUTE 60 /* You never know, things change :-) */
- 22038 #define MCD_RETRIES 2 /* Number of retries for a command */
- 22039 #define REPLY_DELAY 5000 /* Count to wait for a reply */
- 22040 #define MAX_TRACKS 104 /* Maximum nr. of tracks */
- 22041 #define LEAD_OUT 0xAA /* Lead out track is always 0xAA */
- 22042 #define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
- 22043
- 22044
- 22045 /* Drive commands */
- 22046 #define MCD_GET_VOL_INFO 0x10 /* Read volume information */
- 22047 #define MCD_GET_Q_CHANNEL 0x20 /* Read q-channel information */
- 22048 #define MCD_GET_STATUS 0x40 /* Read status of drive */
- 22049 #define MCD_SET_MODE 0x50 /* Set transmission mode */
- 22050 #define MCD_RESET 0x60 /* Reset controller */
- 22051 #define MCD_STOP_AUDIO 0x70 /* Stop audio playing */
- 22052 #define MCD_SET_DRIVE_MODE 0xA0 /* Set drive mode */
- 22053 #define MCD_READ_FROM_TO 0xC0 /* Read from .. to .. */
- 22054 #define MCD_GET_VERSION 0xDC /* Get version number */
- 22055 #define MCD_STOP 0xF0 /* Stop everything */
- 22056 #define MCD_EJECT 0xF6 /* Eject cd */
- 22057 #define MCD_PICKLE 0x04 /* Needed for newer drive models */
- 22058
- 22059
- 22060 /* Command bits for MCD_SET_MODE command */
- 22061 #define MCD_MUTE_DATA 0x01 /* 1 = Don't play back data as audio */
- 22062 #define MCD_GET_TOC 0x04 /* 0 = Get toc on next GET_Q_CHANNEL */
- 22063 #define MCD_ECC_MODE 0x20 /* 0 = Use secondary ecc */
- 22064 #define MCD_DATALENGTH 0x40 /* 0 = Read user data only */
- 22065 #define MCD_COOKED (MCD_MUTE_DATA)
- 22066 #define MCD_TOC (MCD_MUTE_DATA | MCD_GET_TOC)
- 22067
- 22068
- 22069 /* Status bits */
- .Ep 296 src/kernel/mcd.c
- 22070 #define MCD_CMD_ERROR 0x01 /* Command error */
- 22071 #define MCD_AUDIO_BUSY 0x02 /* Audio disk is playing */
- 22072 #define MCD_READ_ERROR 0x04 /* Read error */
- 22073 #define MCD_AUDIO_DISK 0x08 /* Audio disk is in */
- 22074 #define MCD_SPINNING 0x10 /* Motor is spinning */
- 22075 #define MCD_DISK_CHANGED 0x20 /* Disk has been removed or changed */
- 22076 #define MCD_DISK_IN 0x40 /* Disk is in */
- 22077 #define MCD_DOOR_OPEN 0x80 /* Door is open */
- 22078
- 22079 /* Flag bits */
- 22080 #define MCD_DATA_AVAILABLE 0x02 /* Data available */
- 22081 #define MCD_BUSY 0x04 /* Drive is busy */
- 22082
- 22083 /* Function prototypes */
- 22084 FORWARD _PROTOTYPE ( int mcd_init, (void));
- 22085 FORWARD _PROTOTYPE ( int c_handler, (int irq));
- 22086 FORWARD _PROTOTYPE ( int mcd_play_mss, (struct cd_play_mss));
- 22087 FORWARD _PROTOTYPE ( int mcd_play_tracks, (struct cd_play_track tracks));
- 22088 FORWARD _PROTOTYPE ( int mcd_stop, (void));
- 22089 FORWARD _PROTOTYPE ( int mcd_eject, (void));
- 22090 FORWARD _PROTOTYPE ( int mcd_pause, (void));
- 22091 FORWARD _PROTOTYPE ( int mcd_resume, (void));
- 22092 FORWARD _PROTOTYPE ( u8_t bin2bcd, (u8_t b));
- 22093 FORWARD _PROTOTYPE ( void bcd2bin, (u8_t *bcd));
- 22094 FORWARD _PROTOTYPE ( long mss2block, (u8_t *mss));
- 22095 FORWARD _PROTOTYPE ( void block2mss, (long block, u8_t *mss));
- 22096 FORWARD _PROTOTYPE ( int mcd_get_reply, (u8_t *reply, int delay));
- 22097 FORWARD _PROTOTYPE ( int mcd_get_status, (int f));
- 22098 FORWARD _PROTOTYPE ( int mcd_ready, (int delay));
- 22099 FORWARD _PROTOTYPE ( int mcd_data_ready, (int delay));
- 22100 FORWARD _PROTOTYPE ( int mcd_set_mode, (int mode));
- 22101 FORWARD _PROTOTYPE ( int mcd_send_command, (int command));
- 22102 FORWARD _PROTOTYPE ( int mcd_get_disk_info, (void));
- 22103 FORWARD _PROTOTYPE ( int mcd_read_q_channel, (struct cd_toc_entry *qc));
- 22104 FORWARD _PROTOTYPE ( int mcd_read_toc, (void));
- 22105 FORWARD _PROTOTYPE ( int ioctl_read_toc, (message *m_ptr));
- 22106 FORWARD _PROTOTYPE ( int ioctl_disk_info, (message *m_ptr));
- 22107 FORWARD _PROTOTYPE ( int ioctl_read_sub, (message *m_ptr));
- 22108 FORWARD _PROTOTYPE ( int ioctl_disk_info, (message *m_ptr));
- 22109 FORWARD _PROTOTYPE ( int ioctl_play_mss, (message *m_ptr));
- 22110 FORWARD _PROTOTYPE ( int ioctl_play_ti, (message *m_ptr));
- 22111 FORWARD _PROTOTYPE ( int mcd_open, (struct driver *dp, message *m_ptr));
- 22112 FORWARD _PROTOTYPE ( int mcd_close, (struct driver *dp, message *m_ptr));
- 22113 FORWARD _PROTOTYPE ( int mcd_ioctl, (struct driver *dp, message *m_ptr));
- 22114 FORWARD _PROTOTYPE ( char *mcd_name, (void));
- 22115 FORWARD _PROTOTYPE ( struct device *mcd_prepare, (int dev));
- 22116 FORWARD _PROTOTYPE ( int mcd_schedule, (int proc_nr, struct iorequest_s *iop));
- 22117 FORWARD _PROTOTYPE ( int mcd_finish, (void));
- 22118 FORWARD _PROTOTYPE ( void mcd_geometry, (struct partition *entry));
- 22119
- 22120
- 22121 /* Flags displaying current status of cdrom, used with the McdStatus variable */
- 22122 #define TOC_UPTODATE 0x001 /* Table of contents is up to date */
- 22123 #define INFO_UPTODATE 0x002 /* Disk info is up to date */
- 22124 #define DISK_CHANGED 0x004 /* Disk has changed */
- 22125 #define AUDIO_PLAYING 0x008 /* Cdrom is playing audio */
- 22126 #define AUDIO_PAUSED 0x010 /* Cdrom is paused (only audio) */
- 22127 #define AUDIO_DISK 0x020 /* Disk contains audio */
- 22128 #define DISK_ERROR 0x040 /* An error occured */
- 22129 #define NO_DISK 0x080 /* No disk in device */
- .Op 297 src/kernel/mcd.c
- 22130
- 22131 /* Entry points to this driver. */
- 22132 PRIVATE struct driver mcd_dtab =
- 22133 {
- 22134 #if __minix_vmd
- 22135 NULL, /* No private request buffer */
- 22136 #endif
- 22137 mcd_name, /* Current device's name */
- 22138 mcd_open, /* Open request read table of contents */
- 22139 mcd_close, /* Release device */
- 22140 mcd_ioctl, /* Do cdrom ioctls */
- 22141 mcd_prepare, /* Prepare for I/O */
- 22142 mcd_schedule, /* Precompute blocks */
- 22143 mcd_finish, /* Do the I/O */
- 22144 nop_cleanup, /* No cleanup to do */
- 22145 mcd_geometry /* Tell geometry */
- 22146 };
- 22147
- 22148
- 22149 PRIVATE struct trans
- 22150 {
- 22151 struct iorequest_s *tr_iop; /* Belongs to this I/O request */
- 22152 unsigned long tr_pos; /* Byte position to transfer from */
- 22153 int tr_count; /* Byte count */
- 22154 phys_bytes tr_phys; /* User physical address */
- 22155 } mcd_trans[NR_IOREQS];
- 22156
- 22157
- 22158 /* Globals */
- 22159 #if __minix_vmd
- 22160 PRIVATE int mcd_tasknr = ANY;
- 22161 #endif
- 22162 PRIVATE int mcd_avail; /* Set if Mitsumi device exists */
- 22163 PRIVATE int mcd_irq; /* Interrupt request line */
- 22164 PRIVATE int mcd_io_base; /* I/O base register */
- 22165 PRIVATE struct device *mcd_dv; /* Active partition */
- 22166 PRIVATE struct trans *mcd_tp; /* Pointer to add transfer requests */
- 22167 PRIVATE unsigned mcd_count; /* Number of bytes to transfer */
- 22168 PRIVATE unsigned long mcd_nextpos; /* Next consecutive position on disk */
- 22169 PRIVATE struct device mcd_part[DEV_PER_DRIVE];
- 22170 /* Primary partitions: cd[0-4] */
- 22171 PRIVATE struct device mcd_subpart[SUB_PER_DRIVE];
- 22172 /* Subpartitions: cd[1-4][a-d] */
- 22173 PRIVATE int mcd_open_ct; /* in-use count */
- 22174 PRIVATE int McdStatus = NO_DISK; /* A new (or no) disk is inserted */
- 22175 PRIVATE struct cd_play_mss PlayMss; /* Keep track of where we are if we
- 22176 pause, used by resume */
- 22177 PRIVATE struct cd_disk_info DiskInfo; /* Contains toc header */
- 22178 PRIVATE struct cd_toc_entry Toc[MAX_TRACKS]; /* Buffer for toc */
- 22179
- 22180
- 22181
- 22182 /*=========================================================================*
- 22183 * mcd_task *
- 22184 *=========================================================================*/
- 22185 PUBLIC void mcd_task()
- 22186 {
- 22187 long v;
- 22188 static char var[] = "MCD";
- 22189 static char fmt[] = "x:d";
- .Ep 298 src/kernel/mcd.c
- 22190
- 22191 #if __minix_vmd
- 22192 mcd_tasknr = proc_number(proc_ptr);
- 22193 #endif
- 22194
- 22195 /* Configure I/O base and IRQ. */
- 22196 v = MCD_IO_BASE_ADDRESS;
- 22197 (void) env_parse(var, fmt, 0, &v, 0x000L, 0x3FFL);
- 22198 mcd_io_base = v;
- 22199
- 22200 v = MCD_IRQ;
- 22201 (void) env_parse(var, fmt, 0, &v, 0L, (long) NR_IRQ_VECTORS - 1);
- 22202 mcd_irq = v;
- 22203
- 22204 driver_task(&mcd_dtab); /* Start driver task for cdrom */
- 22205 }
- 22208 /*=========================================================================*
- 22209 * mcd_open *
- 22210 *=========================================================================*/
- 22211 PRIVATE int mcd_open(dp, m_ptr)
- 22212 struct driver *dp; /* pointer to this drive */
- 22213 message *m_ptr; /* OPEN */
- 22214 {
- 22215 int i, status;
- 22216
- 22217 if (!mcd_avail && mcd_init() != OK) return EIO;
- 22218
- 22219 if (mcd_prepare(m_ptr->DEVICE) == NIL_DEV) return ENXIO;
- 22220
- 22221 /* A CD-ROM is read-only by definition. */
- 22222 if (m_ptr->COUNT & W_BIT) return EACCES;
- 22223
- 22224 if (mcd_open_ct == 0)
- 22225 {
- 22226 i = 20;
- 22227 for (;;) {
- 22228 if (mcd_get_status(1) == -1) return EIO; /* set McdStatus flags */
- 22229 if (!(McdStatus & NO_DISK)) break;
- 22230 if (--i == 0) return EIO;
- 22231 milli_delay(100);
- 22232 }
- 22233
- 22234 /* Try to read the table of contents of the CD currently inserted */
- 22235 if ((status = mcd_read_toc()) != OK)
- 22236 return status;
- 22237
- 22238 mcd_open_ct++;
- 22239
- 22240 /* fill in size of device (= nr. of bytes on the disk) */
- 22241 mcd_part[0].dv_base = 0;
- 22242 mcd_part[0].dv_size =
- 22243 ((((unsigned long)DiskInfo.disk_length_mss[MINUTES] * SECONDS_PER_MINUTE
- 22244 + (unsigned long)DiskInfo.disk_length_mss[SECONDS]) * SECTORS_PER_SECOND)
- 22245 + (unsigned long)DiskInfo.disk_length_mss[SECTOR]) * BYTES_PER_SECTOR;
- 22246
- 22247 #if MCD_DEBUG >= 1
- 22248 printf("cd size: %lun", mcd_part[0].dv_size);
- 22249 #endif
- .Op 299 src/kernel/mcd.c
- 22250
- 22251 /* Partition the disk. */
- 22252 partition(&mcd_dtab, 0, P_PRIMARY);
- 22253 }
- 22254 return OK;
- 22255 }
- 22258 /*=========================================================================*
- 22259 * mcd_close *
- 22260 *=========================================================================*/
- 22261 PRIVATE int mcd_close(dp, m_ptr)
- 22262 struct driver *dp; /* pointer to this drive */
- 22263 message *m_ptr; /* CLOSE */
- 22264 {
- 22265 /* One less reference to the device */
- 22266
- 22267 mcd_open_ct--;
- 22268 return OK;
- 22269 }
- 22272 /*=========================================================================*
- 22273 * mcd_name *
- 22274 *=========================================================================*/
- 22275 PRIVATE char *mcd_name()
- 22276 {
- 22277 /* Return a name for the device */
- 22278
- 22279 return "cd0";
- 22280 }
- 22283 /*=========================================================================*
- 22284 * mcd_ioctl *
- 22285 *=========================================================================*/
- 22286 PRIVATE int mcd_ioctl(dp, m_ptr)
- 22287 struct driver *dp; /* pointer to the drive */
- 22288 message *m_ptr; /* contains ioctl command */
- 22289 {
- 22290 /* Perform the ioctl request */
- 22291
- 22292 int status;
- 22293
- 22294 if (mcd_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
- 22295
- 22296 mcd_get_status(1); /* Update the status flags */
- 22297 if ((McdStatus & NO_DISK) && m_ptr->REQUEST != CDIOEJECT)
- 22298 return EIO;
- 22299
- 22300 switch(m_ptr->REQUEST)
- 22301 {
- 22302 case CDIOPLAYMSS: status = ioctl_play_mss(m_ptr);break;
- 22303 case CDIOPLAYTI: status = ioctl_play_ti(m_ptr);break;
- 22304 case CDIOREADTOCHDR: status = ioctl_disk_info(m_ptr);break;
- 22305 case CDIOREADTOC: status = ioctl_read_toc(m_ptr);break;
- 22306 case CDIOREADSUBCH: status = ioctl_read_sub(m_ptr);break;
- 22307 case CDIOSTOP: status = mcd_stop();break;
- 22308 case CDIOPAUSE: status = mcd_pause();break;
- 22309 case CDIORESUME: status = mcd_resume();break;
- .Ep 300 src/kernel/mcd.c
- 22310 case CDIOEJECT: status = mcd_eject();break;
- 22311 default: status = do_diocntl(dp, m_ptr);
- 22312 }
- 22313 return status;
- 22314 }
- 22317 /*=========================================================================*
- 22318 * mcd_get_reply *
- 22319 *=========================================================================*/
- 22320 PRIVATE int mcd_get_reply(reply, delay)
- 22321 u8_t *reply; /* variable to put reply in */
- 22322 int delay; /* count to wait for the reply */
- 22323 {
- 22324 /* Get a reply from the drive */
- 22325
- 22326 if (mcd_ready(delay) != OK) return EIO; /* wait for drive to
- 22327 become available */
- 22328 *reply = in_byte(MCD_DATA_PORT); /* get the reply */
- 22329 return OK;
- 22330 }
- 22333 /*=========================================================================*
- 22334 * mcd_ready *
- 22335 *=========================================================================*/
- 22336 PRIVATE int mcd_ready(delay)
- 22337 int delay; /* count to wait for drive to become available again */
- 22338 {
- 22339 /* Wait for drive to become available */
- 22340
- 22341 struct milli_state ms;
- 22342
- 22343 milli_start(&ms);
- 22344 do
- 22345 {
- 22346 if (!(in_byte(MCD_FLAG_PORT) & MCD_BUSY)) return OK; /* OK, drive ready */
- 22347 } while(milli_elapsed(&ms) < delay);
- 22348
- 22349 return EIO; /* Timeout */
- 22350 }
- 22353 /*=========================================================================*
- 22354 * mcd_data_ready *
- 22355 *=========================================================================*/
- 22356 PRIVATE int mcd_data_ready(delay)
- 22357 int delay; /* count to wait for the data */
- 22358 {
- 22359 /* Wait for the drive to get the data */
- 22360
- 22361 struct milli_state ms;
- 22362
- 22363 milli_start(&ms);
- 22364 do
- 22365 {
- 22366 if (!(in_byte(MCD_FLAG_PORT) & 2)) return OK; /* OK, data is there */
- 22367 } while(milli_elapsed(&ms) < delay);
- 22368
- 22369 return EIO; /* Timeout */
- .Op 301 src/kernel/mcd.c
- 22370 }
- 22373 /*=========================================================================*
- 22374 * mcd_get_status *
- 22375 *=========================================================================*/
- 22376 PRIVATE int mcd_get_status(f)
- 22377 int f; /* flag */
- 22378 {
- 22379 /* Return status info from the drive and update the global McdStatus */
- 22380
- 22381 u8_t status;
- 22382
- 22383 /* If f = 1, we first send a get_status command, otherwise we just get
- 22384 the status info from the drive */
- 22385
- 22386 if (f) out_byte(MCD_DATA_PORT, MCD_GET_STATUS); /* Try to get status */
- 22387 if (mcd_get_reply(&status,REPLY_DELAY) != OK) return -1;
- 22388
- 22389 McdStatus &= ~(NO_DISK | DISK_CHANGED | DISK_ERROR);
- 22390
- 22391 /* Fill in the McdStatus variable */
- 22392 if (status & MCD_DOOR_OPEN ||
- 22393 !(status & MCD_DISK_IN)) McdStatus = NO_DISK;
- 22394 else if (status & MCD_DISK_CHANGED) McdStatus = DISK_CHANGED;
- 22395 else if (status & MCD_READ_ERROR ||
- 22396 status & MCD_CMD_ERROR) McdStatus = DISK_ERROR;
- 22397 else
- 22398 {
- 22399 if (status & MCD_AUDIO_DISK)
- 22400 {
- 22401 McdStatus |= AUDIO_DISK;
- 22402 if (!(status & MCD_AUDIO_BUSY)) McdStatus &= ~(AUDIO_PLAYING);
- 22403 else McdStatus |= AUDIO_PLAYING;
- 22404 }
- 22405 }
- 22406 #if MCD_DEBUG >= 3
- 22407 printf("mcd_get_status(%d) = %02x, McdStatus = %02xn",
- 22408 f, status, McdStatus);
- 22409 #endif
- 22410 return status; /* Return status */
- 22411 }
- 22414 /*=========================================================================*
- 22415 * mcd_set_mode *
- 22416 *=========================================================================*/
- 22417 PRIVATE int mcd_set_mode(mode)
- 22418 int mode; /* new drive mode */
- 22419 {
- 22420 /* Set drive mode */
- 22421
- 22422 int i;
- 22423
- 22424 for (i = 0; i < MCD_RETRIES; i++)
- 22425 {
- 22426 out_byte(MCD_DATA_PORT, MCD_SET_MODE); /* Send set mode command */
- 22427 out_byte(MCD_DATA_PORT, mode); /* Send which mode */
- 22428 if (mcd_get_status(0) != -1 &&
- 22429 !(McdStatus & DISK_ERROR)) break;
- .Ep 302 src/kernel/mcd.c
- 22430 }
- 22431 if (i == MCD_RETRIES) return EIO; /* Operation failed */
- 22432
- 22433 return OK; /* Operation succeeded */
- 22434 }
- 22437 /*=========================================================================*
- 22438 * mcd_send_command *
- 22439 *=========================================================================*/
- 22440 PRIVATE int mcd_send_command(command)
- 22441 int command; /* command to send */
- 22442 {
- 22443 int i;
- 22444
- 22445 for (i = 0; i < MCD_RETRIES; i++)
- 22446 {
- 22447 out_byte(MCD_DATA_PORT, command); /* send command */
- 22448 if (mcd_get_status(0) != -1 &&
- 22449 !(McdStatus & DISK_ERROR)) break;
- 22450 }
- 22451 if (i == MCD_RETRIES) return EIO; /* operation failed */
- 22452
- 22453 return OK;
- 22454 }
- 22457 /*=========================================================================*
- 22458 * mcd_init *
- 22459 *=========================================================================*/
- 22460 PRIVATE int mcd_init()
- 22461 {
- 22462 /* Initialize the drive and get the version bytes, this is done only
- 22463 once when the system gets up. We can't use mcd_ready because
- 22464 the clock task is not available yet.
- 22465 */
- 22466
- 22467 u8_t version[3];
- 22468 int i;
- 22469 u32_t n;
- 22470 struct milli_state ms;
- 22471
- 22472 /* Reset the flag port and remove all pending data, if we do
- 22473 * not do this properly the drive won't cooperate.
- 22474 */
- 22475 out_byte(MCD_FLAG_PORT, 0x00);
- 22476 for (n = 0; n < 1000000; n++)
- 22477 (void) in_byte(MCD_FLAG_PORT);
- 22478
- 22479 /* Now see if the drive will report its status */
- 22480 if (mcd_get_status(1) == -1)
- 22481 {
- 22482 /* Too bad, drive will not listen */
- 22483 printf("%s: init failed, no Mitsumi cdrom presentn", mcd_name());
- 22484 return -1;
- 22485 }
- 22486
- 22487 /* Find out drive version */
- 22488 out_byte(MCD_DATA_PORT, MCD_GET_VERSION);
- 22489 milli_start(&ms);
- .Op 303 src/kernel/mcd.c
- 22490 for (i = 0; i < 3; i++)
- 22491 {
- 22492 while (in_byte(MCD_FLAG_PORT) & MCD_BUSY)
- 22493 {
- 22494 if (milli_elapsed(&ms) >= 1000)
- 22495 {
- 22496 printf("%s: can't get version of Mitsumi cdromn", mcd_name());
- 22497 return -1;
- 22498 }
- 22499 }
- 22500 version[i] = in_byte(MCD_DATA_PORT);
- 22501 }
- 22502
- 22503 if (version[1] == 'D')
- 22504 printf("%s: Mitsumi FX001D CD-ROMn", mcd_name());
- 22505 else
- 22506 printf("%s: Mitsumi CD-ROM version %02x%02x%02xn", mcd_name(),
- 22507 version[0], version[1], version[2]);
- 22508
- 22509 /* Newer drive models need this */
- 22510 if (version[1] >= 4) out_byte(MCD_CONTROL_PORT, MCD_PICKLE);
- 22511
- 22512 /* Register interrupt vector and enable interrupt
- 22513 * currently the interrupt is not used because
- 22514 * the controller isn't set up to do dma. XXX
- 22515 */
- 22516 put_irq_handler(mcd_irq, c_handler);
- 22517 enable_irq(mcd_irq);
- 22518
- 22519 mcd_avail = 1;
- 22520 return OK;
- 22521 }
- 22524 /*=========================================================================*
- 22525 * c_handler *
- 22526 *=========================================================================*/
- 22527 PRIVATE int c_handler(irq)
- 22528 int irq; /* irq number */
- 22529 {
- 22530 /* The interrupt handler, I never got an interrupt but its here just
- 22531 * in case...
- 22532 */
- 22533
- 22534 /* Send interrupt message to cdrom task */
- 22535 #if XXX
- 22536 #if __minix_vmd
- 22537 interrupt(mcd_tasknr);
- 22538 #else
- 22539 interrupt(CDROM);
- 22540 #endif
- 22541 #endif
- 22542
- 22543 return 1;
- 22544 }
- 22547 /*=========================================================================*
- 22548 * mcd_play_mss *
- 22549 *=========================================================================*/
- .Ep 304 src/kernel/mcd.c
- 22550 PRIVATE int mcd_play_mss(mss)
- 22551 struct cd_play_mss mss; /* from where to play minute:second.sector */
- 22552 {
- 22553 /* Command the drive to start playing at min:sec.sector */
- 22554
- 22555 int i;
- 22556
- 22557 #if MCD_DEBUG >= 1
- 22558 printf("Play_mss: begin: %02d:%02d.%02d end: %02d:%02d.%02dn",
- 22559 mss.begin_mss[MINUTES], mss.begin_mss[SECONDS],
- 22560 mss.begin_mss[SECTOR], mss.end_mss[MINUTES],
- 22561 mss.end_mss[SECONDS], mss.end_mss[SECTOR]);
- 22562 #endif
- 22563
- 22564 for (i=0; i < MCD_RETRIES; i++) /* Try it more than once */
- 22565 {
- 22566 lock(); /* No interrupts when we issue this command */
- 22567
- 22568 /* Send command with paramters to drive */
- 22569 out_byte(MCD_DATA_PORT, MCD_READ_FROM_TO);
- 22570 out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[MINUTES]));
- 22571 out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[SECONDS]));
- 22572 out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[SECTOR]));
- 22573 out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[MINUTES]));
- 22574 out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[SECONDS]));
- 22575 out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[SECTOR]));
- 22576
- 22577 unlock(); /* Enable interrupts again */
- 22578
- 22579 mcd_get_status(0); /* See if all went well */
- 22580 if (McdStatus & AUDIO_PLAYING) break; /* Ok, we're playing */
- 22581 }
- 22582
- 22583 if (i == MCD_RETRIES) return EIO; /* Command failed */
- 22584
- 22585 /* keep in mind where we going in case of a future resume */
- 22586 PlayMss.end_mss[MINUTES] = mss.end_mss[MINUTES];
- 22587 PlayMss.end_mss[SECONDS] = mss.end_mss[SECONDS];
- 22588 PlayMss.end_mss[SECTOR] = mss.end_mss[SECTOR];
- 22589
- 22590 McdStatus &= ~(AUDIO_PAUSED);
- 22591
- 22592 return(OK);
- 22593 }
- 22596 /*=========================================================================*
- 22597 * mcd_play_tracks *
- 22598 *=========================================================================*/
- 22599 PRIVATE int mcd_play_tracks(tracks)
- 22600 struct cd_play_track tracks; /* which tracks to play */
- 22601 {
- 22602 /* Command the drive to play tracks */
- 22603
- 22604 int i, err;
- 22605 struct cd_play_mss mss;
- 22606
- 22607 #if MCD_DEBUG >= 1
- 22608 printf("Play tracks: begin: %02d end: %02dn",
- 22609 tracks.begin_track, tracks.end_track);
- .Op 305 src/kernel/mcd.c
- 22610 #endif
- 22611
- 22612 /* First read the table of contents */
- 22613 if ((err = mcd_read_toc()) != OK) return err;
- 22614
- 22615 /* Check if parameters are valid */
- 22616 if (tracks.begin_track < DiskInfo.first_track ||
- 22617 tracks.end_track > DiskInfo.last_track ||
- 22618 tracks.begin_track > tracks.end_track)
- 22619 return EINVAL;
- 22620
- 22621
- 22622 /* Convert the track numbers to min:sec.sector */
- 22623 for (i=0; i<3; i++)
- 22624 {
- 22625 mss.begin_mss[i] = Toc[tracks.begin_track].position_mss[i];
- 22626 mss.end_mss[i] = Toc[tracks.end_track+1].position_mss[i];
- 22627 }
- 22628
- 22629 return(mcd_play_mss(mss)); /* Start playing */
- 22630 }
- 22633 /*=========================================================================*
- 22634 * mcd_get_disk_info *
- 22635 *=========================================================================*/
- 22636 PRIVATE int mcd_get_disk_info()
- 22637 {
- 22638 /* Get disk info */
- 22639
- 22640 int i, err;
- 22641
- 22642 if (McdStatus & INFO_UPTODATE) return OK; /* No need to read info again */
- 22643
- 22644 /* Issue the get volume info command */
- 22645 if ((err = mcd_send_command(MCD_GET_VOL_INFO)) != OK) return err;
- 22646
- 22647 /* Fill global DiskInfo */
- 22648 for (i=0; i < sizeof(DiskInfo); i++)
- 22649 {
- 22650 if ((err = mcd_get_reply((u8_t *)(&DiskInfo) + i, REPLY_DELAY)) !=OK)
- 22651 return err;
- 22652 bcd2bin((u8_t *)(&DiskInfo) + i);
- 22653 }
- 22654
- 22655 #if MCD_DEBUG >= 1
- 22656 printf("Mitsumi disk info: first: %d last: %d first %02d:%02d.%02d length: %02d:%02d.%02dn",
- 22657 DiskInfo.first_track,
- 22658 DiskInfo.last_track,
- 22659 DiskInfo.first_track_mss[MINUTES],
- 22660 DiskInfo.first_track_mss[SECONDS],
- 22661 DiskInfo.first_track_mss[SECTOR],
- 22662 DiskInfo.disk_length_mss[MINUTES],
- 22663 DiskInfo.disk_length_mss[SECONDS],
- 22664 DiskInfo.disk_length_mss[SECTOR]);
- 22665 #endif
- 22666
- 22667 /* Update global status info */
- 22668 McdStatus |= INFO_UPTODATE; /* toc header has been read */
- 22669 McdStatus &= ~TOC_UPTODATE; /* toc has not been read yet */
- .Ep 306 src/kernel/mcd.c
- 22670
- 22671 return OK;
- 22672 }
- 22676 /*=========================================================================*
- 22677 * mcd_read_q_channel *
- 22678 *=========================================================================*/
- 22679 PRIVATE int mcd_read_q_channel(qc)
- 22680 struct cd_toc_entry *qc; /* struct to return q-channel info in */
- 22681 {
- 22682 /* Read the qchannel info, if we we're already playing this returns
- 22683 * the relative position and the absolute position of where we are
- 22684 * in min:sec.sector. If we're not playing, this returns an entry
- 22685 * from the table of contents
- 22686 */
- 22687
- 22688 int i, err;
- 22689
- 22690 /* Issue the command */
- 22691 if ((err = mcd_send_command(MCD_GET_Q_CHANNEL)) != OK) return err;
- 22692
- 22693 /* Read the info */
- 22694 for (i=0; i < sizeof(struct cd_toc_entry); i++)
- 22695 {
- 22696 /* Return error on timeout */
- 22697 if ((err = mcd_get_reply((u8_t *)qc + i, REPLY_DELAY)) != OK)
- 22698 return err;
- 22699
- 22700 bcd2bin((u8_t *)qc + i); /* Convert value to binary */
- 22701 }
- 22702
- 22703 #if MCD_DEBUG >= 2
- 22704 printf("qchannel info: ctl_addr: %d track: %d index: %d length %02d:%02d.%02d pos: %02d:%02d.%02dn",
- 22705 qc->control_address,
- 22706 qc->track_nr,
- 22707 qc->index_nr,
- 22708 qc->track_time_mss[MINUTES],
- 22709 qc->track_time_mss[SECONDS],
- 22710 qc->track_time_mss[SECTOR],
- 22711 qc->position_mss[MINUTES],
- 22712 qc->position_mss[SECONDS],
- 22713 qc->position_mss[SECTOR]);
- 22714 #endif
- 22715
- 22716 return OK; /* All done */
- 22717 }
- 22720 /*=========================================================================*
- 22721 * mcd_read_toc *
- 22722 *=========================================================================*/
- 22723 PRIVATE int mcd_read_toc()
- 22724 {
- 22725 /* Read the table of contents (TOC) */
- 22726
- 22727 struct cd_toc_entry q_info;
- 22728 int current_track, current_index;
- 22729 int err,i;
- .Op 307 src/kernel/mcd.c
- 22730
- 22731
- 22732 if (McdStatus & TOC_UPTODATE) return OK; /* No need to read toc again */
- 22733
- 22734 /* Clear toc table */
- 22735 for (i = 0; i < MAX_TRACKS; i++) Toc[i].index_nr = 0;
- 22736
- 22737 /* Read disk info */
- 22738 if ((err = mcd_get_disk_info()) != OK) return err;
- 22739
- 22740 /* Calculate track to start with */
- 22741 current_track = DiskInfo.last_track - DiskInfo.first_track + 1;
- 22742
- 22743 /* Set read toc mode */
- 22744 if ((err = mcd_set_mode(MCD_TOC)) != OK) return err;
- 22745
- 22746 /* Read the complete TOC, on every read-q-channel command we get a random
- 22747 * TOC entry depending on how far we are in the q-channel, collect entries
- 22748 * as long as we don't have the complete TOC. There's a limit of 600 here,
- 22749 * if we don't have the complete TOC after 600 reads we quit with an error
- 22750 */
- 22751 for (i = 0; (i < 600 && current_track > 0); i++)
- 22752 {
- 22753 /* Try to read a TOC entry */
- 22754 if ((err = mcd_read_q_channel(&q_info)) != OK) break;
- 22755
- 22756 /* Is this a valid track number and didn't we have it yet ? */
- 22757 current_index = q_info.index_nr;
- 22758 if (current_index >= DiskInfo.first_track &&
- 22759 current_index <= DiskInfo.last_track &&
- 22760 q_info.track_nr == 0)
- 22761 {
- 22762 /* Copy entry into toc table */
- 22763 if (Toc[current_index].index_nr == 0)
- 22764 {
- 22765 Toc[current_index].control_address = q_info.control_address;
- 22766 Toc[current_index].track_nr = current_index;
- 22767 Toc[current_index].index_nr = 1;
- 22768 Toc[current_index].track_time_mss[MINUTES] = q_info.track_time_mss[MINUTES];
- 22769 Toc[current_index].track_time_mss[SECONDS] = q_info.track_time_mss[SECONDS];
- 22770 Toc[current_index].track_time_mss[SECTOR] = q_info.track_time_mss[SECTOR];
- 22771 Toc[current_index].position_mss[MINUTES] = q_info.position_mss[MINUTES];
- 22772 Toc[current_index].position_mss[SECONDS] = q_info.position_mss[SECONDS];
- 22773 Toc[current_index].position_mss[SECTOR] = q_info.position_mss[SECTOR];
- 22774 current_track--;
- 22775 }
- 22776 }
- 22777 }
- 22778 if (err) return err; /* Do we have all toc entries? */
- 22779
- 22780 /* Fill in lead out */
- 22781 current_index = DiskInfo.last_track + 1;
- 22782 Toc[current_index].control_address =
- 22783 Toc[current_index-1].control_address;
- 22784 Toc[current_index].track_nr = 0;
- 22785 Toc[current_index].index_nr = LEAD_OUT;
- 22786 Toc[current_index].position_mss[MINUTES] = DiskInfo.disk_length_mss[MINUTES];
- 22787 Toc[current_index].position_mss[SECONDS] = DiskInfo.disk_length_mss[SECONDS];
- 22788 Toc[current_index].position_mss[SECTOR] = DiskInfo.disk_length_mss[SECTOR];
- 22789
- .Ep 308 src/kernel/mcd.c
- 22790 /* Return to cooked mode */
- 22791 if ((err = mcd_set_mode(MCD_COOKED)) != OK) return err;
- 22792
- 22793 /* Update global status */
- 22794 McdStatus |= TOC_UPTODATE;
- 22795
- 22796 #if MCD_DEBUG >= 1
- 22797 for (i = DiskInfo.first_track; i <= current_index; i++)
- 22798 {
- 22799 printf("Mitsumi toc %d: trk %d index %d time %02d:%02d.%02d pos: %02d:%02d.%02dn",
- 22800 i,
- 22801 Toc[i].track_nr,
- 22802 Toc[i].index_nr,
- 22803 Toc[i].track_time_mss[MINUTES],
- 22804 Toc[i].track_time_mss[SECONDS],
- 22805 Toc[i].track_time_mss[SECTOR],
- 22806 Toc[i].position_mss[MINUTES],
- 22807 Toc[i].position_mss[SECONDS],
- 22808 Toc[i].position_mss[SECTOR]);
- 22809 }
- 22810 #endif
- 22811
- 22812 return OK;
- 22813 }
- 22816 /*=========================================================================*
- 22817 * mcd_stop *
- 22818 *=========================================================================*/
- 22819 PRIVATE int mcd_stop()
- 22820 {
- 22821 int err;
- 22822
- 22823 if ((err = mcd_send_command(MCD_STOP)) != OK ) return err;
- 22824
- 22825 McdStatus &= ~(AUDIO_PAUSED);
- 22826
- 22827 return OK;
- 22828 }
- 22829
- 22830
- 22831 /*=========================================================================*
- 22832 * mcd_eject *
- 22833 *=========================================================================*/
- 22834 PRIVATE int mcd_eject()
- 22835 {
- 22836 int err;
- 22837
- 22838 if ((err = mcd_send_command(MCD_EJECT)) != OK) return err;
- 22839 return OK;
- 22840 }
- 22841
- 22842
- 22843 /*=========================================================================*
- 22844 * mcd_pause *
- 22845 *=========================================================================*/
- 22846 PRIVATE int mcd_pause()
- 22847 {
- 22848 int err;
- 22849 struct cd_toc_entry qc;
- .Op 309 src/kernel/mcd.c
- 22850
- 22851 /* We can only pause when we are playing audio */
- 22852 if (!(McdStatus & AUDIO_PLAYING)) return EINVAL;
- 22853
- 22854 /* Look where we are */
- 22855 if ((err = mcd_read_q_channel(&qc)) != OK) return err;
- 22856
- 22857 /* Stop playing */
- 22858 if ((err = mcd_send_command(MCD_STOP_AUDIO)) != OK) return err;
- 22859
- 22860 /* Keep in mind were we have to start again */
- 22861 PlayMss.begin_mss[MINUTES] = qc.position_mss[MINUTES];
- 22862 PlayMss.begin_mss[SECONDS] = qc.position_mss[SECONDS];
- 22863 PlayMss.begin_mss[SECTOR] = qc.position_mss[SECTOR];
- 22864
- 22865 /* Update McdStatus */
- 22866 McdStatus |= AUDIO_PAUSED;
- 22867
- 22868 #if MCD_DEBUG >= 1
- 22869 printf("Mcd_paused at: %02d:%02d.%02dn",
- 22870 PlayMss.begin_mss[MINUTES],
- 22871 PlayMss.begin_mss[SECONDS],
- 22872 PlayMss.begin_mss[SECTOR]);
- 22873 #endif
- 22874
- 22875 return OK;
- 22876 }
- 22877
- 22878
- 22879 /*=========================================================================*
- 22880 * mcd_resume *
- 22881 *=========================================================================*/
- 22882 PRIVATE int mcd_resume()
- 22883 {
- 22884 int err;
- 22885
- 22886 /* we can only resume if we are in a pause state */
- 22887 if (!(McdStatus & AUDIO_PAUSED)) return EINVAL;
- 22888
- 22889 /* start playing where we left off */
- 22890 if ((err = mcd_play_mss(PlayMss)) != OK) return err;
- 22891
- 22892 McdStatus &= ~(AUDIO_PAUSED);
- 22893
- 22894 #if MCD_DEBUG >= 1
- 22895 printf("Mcd resumed at: %02d:%02d.%02dn",
- 22896 PlayMss.begin_mss[MINUTES],
- 22897 PlayMss.begin_mss[SECONDS],
- 22898 PlayMss.begin_mss[SECTOR]);
- 22899 #endif
- 22900
- 22901 return OK;
- 22902 }
- 22903
- 22904
- 22905 /*=========================================================================*
- 22906 * ioctl_read_sub *
- 22907 *=========================================================================*/
- 22908 PRIVATE int ioctl_read_sub(m_ptr)
- 22909 message *m_ptr;
- .Ep 310 src/kernel/mcd.c
- 22910 {
- 22911 phys_bytes user_phys;
- 22912 struct cd_toc_entry sub;
- 22913 int err;
- 22914
- 22915 /* We can only read a sub channel when we are playing audio */
- 22916 if (!(McdStatus & AUDIO_PLAYING)) return EINVAL;
- 22917
- 22918 /* Read the sub channel */
- 22919 if ((err = mcd_read_q_channel(&sub)) != OK) return err;
- 22920
- 22921 /* Copy info to user */
- 22922 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(sub));
- 22923 if (user_phys == 0) return(EFAULT);
- 22924 phys_copy(vir2phys(&sub), user_phys, (phys_bytes) sizeof(sub));
- 22925
- 22926 return OK;
- 22927 }
- 22928
- 22929
- 22930
- 22931 /*=========================================================================*
- 22932 * ioctl_read_toc *
- 22933 *=========================================================================*/
- 22934 PRIVATE int ioctl_read_toc(m_ptr)
- 22935 message *m_ptr;
- 22936 {
- 22937 phys_bytes user_phys;
- 22938 int err, toc_size;
- 22939
- 22940 /* Try to read the table of contents */
- 22941 if ((err = mcd_read_toc()) != OK) return err;
- 22942
- 22943 /* Get size of toc */
- 22944 toc_size = (DiskInfo.last_track + 1) * sizeof(struct cd_toc_entry);
- 22945
- 22946 /* Copy to user */
- 22947 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, toc_size);
- 22948 if (user_phys == 0) return(EFAULT);
- 22949 phys_copy(vir2phys(&Toc), user_phys, (phys_bytes) toc_size);
- 22950
- 22951 return OK;
- 22952 }
- 22953
- 22954
- 22955 /*=========================================================================*
- 22956 * ioctl_disk_info *
- 22957 *=========================================================================*/
- 22958 PRIVATE int ioctl_disk_info(m_ptr)
- 22959 message *m_ptr;
- 22960 {
- 22961 phys_bytes user_phys;
- 22962 int err;
- 22963
- 22964 /* Try to read the toc header */
- 22965 if ((err = mcd_get_disk_info()) != OK) return err;
- 22966
- 22967 /* Copy info to user */
- 22968 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(DiskInfo));
- 22969 if (user_phys == 0) return(EFAULT);
- .Op 311 src/kernel/mcd.c
- 22970 phys_copy(vir2phys(&DiskInfo), user_phys, (phys_bytes) sizeof(DiskInfo));
- 22971
- 22972 return OK;
- 22973 }
- 22976 /*=========================================================================*
- 22977 * ioctl_play_mss *
- 22978 *=========================================================================*/
- 22979 PRIVATE int ioctl_play_mss(m_ptr)
- 22980 message *m_ptr;
- 22981 {
- 22982 phys_bytes user_phys;
- 22983 struct cd_play_mss mss;
- 22984
- 22985 /* Get user data */
- 22986 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(mss));
- 22987 if (user_phys == 0) return(EFAULT);
- 22988 phys_copy(user_phys, vir2phys(&mss), (phys_bytes) sizeof(mss));
- 22989
- 22990 /* Try to play */
- 22991 return mcd_play_mss(mss);
- 22992 }
- 22995 /*=========================================================================*
- 22996 * ioctl_play_ti *
- 22997 *=========================================================================*/
- 22998 PRIVATE int ioctl_play_ti(m_ptr)
- 22999 message *m_ptr;
- 23000 {
- 23001 phys_bytes user_phys;
- 23002 struct cd_play_track tracks;
- 23003
- 23004 /* Get user data */
- 23005 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(tracks));
- 23006 if (user_phys == 0) return(EFAULT);
- 23007 phys_copy(user_phys, vir2phys(&tracks), (phys_bytes) sizeof(tracks));
- 23008
- 23009 /* Try to play */
- 23010 return mcd_play_tracks(tracks);
- 23011 }
- 23014 /*===========================================================================*
- 23015 * mcd_prepare *
- 23016 *===========================================================================*/
- 23017 PRIVATE struct device *mcd_prepare(device)
- 23018 int device;
- 23019 {
- 23020 /* Nothing to transfer as yet. */
- 23021 mcd_count = 0;
- 23022
- 23023 /* Select partition. */
- 23024 if (device < DEV_PER_DRIVE) { /* cd0, cd1, ... */
- 23025 mcd_dv = &mcd_part[device];
- 23026 } else
- 23027 if ((unsigned) (device -= MINOR_hd1a) < SUB_PER_DRIVE) { /* cd1a, cd1b, ... */
- 23028 mcd_dv = &mcd_subpart[device];
- 23029 } else {
- .Ep 312 src/kernel/mcd.c
- 23030 return NIL_DEV;
- 23031 }
- 23032
- 23033 return mcd_dv;
- 23034 }
- 23037 /*===========================================================================*
- 23038 * mcd_schedule *
- 23039 *===========================================================================*/
- 23040 PRIVATE int mcd_schedule(proc_nr, iop)
- 23041 int proc_nr; /* process doing the request */
- 23042 struct iorequest_s *iop; /* pointer to read or write request */
- 23043 {
- 23044 /* Gather I/O requests on consecutive blocks so they may be read/written
- 23045 * in one controller command. (There is enough time to compute the next
- 23046 * consecutive request while an unwanted block passes by.)
- 23047 */
- 23048 int r, opcode;
- 23049 unsigned long pos;
- 23050 unsigned nbytes;
- 23051 phys_bytes user_phys;
- 23052
- 23053 /* This many bytes to read */
- 23054 nbytes = iop->io_nbytes;
- 23055
- 23056 /* From/to this position on the device */
- 23057 pos = iop->io_position;
- 23058
- 23059 /* To/from this user address */
- 23060 user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
- 23061 if (user_phys == 0) return(iop->io_nbytes = EINVAL);
- 23062
- 23063 /* Read or write? */
- 23064 opcode = iop->io_request & ~OPTIONAL_IO;
- 23065
- 23066 /* Only read permitted on cdrom */
- 23067 if (opcode != DEV_READ) return EIO;
- 23068
- 23069 /* What position on disk and how close to EOF? */
- 23070 if (pos >= mcd_dv->dv_size) return(OK); /* At EOF */
- 23071 if (pos + nbytes > mcd_dv->dv_size) nbytes = mcd_dv->dv_size - pos;
- 23072 pos += mcd_dv->dv_base;
- 23073
- 23074 if (mcd_count > 0 && pos != mcd_nextpos) {
- 23075 /* This new request can't be chained to the job being built */
- 23076 if ((r = mcd_finish()) != OK) return(r);
- 23077 }
- 23078
- 23079 /* Next consecutive position. */
- 23080 mcd_nextpos = pos + nbytes;
- 23081
- 23082 if (mcd_count == 0)
- 23083 {
- 23084 /* The first request in a row, initialize. */
- 23085 mcd_tp = mcd_trans;
- 23086 }
- 23087
- 23088 /* Store I/O parameters */
- 23089 mcd_tp->tr_iop = iop;
- .Op 313 src/kernel/mcd.c
- 23090 mcd_tp->tr_pos = pos;
- 23091 mcd_tp->tr_count = nbytes;
- 23092 mcd_tp->tr_phys = user_phys;
- 23093
- 23094 /* Update counters */
- 23095 mcd_tp++;
- 23096 mcd_count += nbytes;
- 23097 return(OK);
- 23098 }
- 23101 /*===========================================================================*
- 23102 * mcd_finish *
- 23103 *===========================================================================*/
- 23104 PRIVATE int mcd_finish()
- 23105 {
- 23106 /* Carry out the I/O requests gathered in mcd_trans[]. */
- 23107
- 23108 struct trans *tp = mcd_trans;
- 23109 int err, errors;
- 23110 u8_t mss[3];
- 23111 unsigned long pos;
- 23112 unsigned count, n;
- 23113
- 23114 if (mcd_count == 0) return(OK); /* we're already done */
- 23115
- 23116 /* Update status */
- 23117 mcd_get_status(1);
- 23118 if (McdStatus & (AUDIO_DISK | NO_DISK))
- 23119 return(tp->tr_iop->io_nbytes = EIO);
- 23120
- 23121 /* Set cooked mode */
- 23122 if ((err = mcd_set_mode(MCD_COOKED)) != OK)
- 23123 return(tp->tr_iop->io_nbytes = err);
- 23124
- 23125 while (mcd_count > 0)
- 23126 {
- 23127 /* Position on the CD rounded down to the CD block size */
- 23128 pos = tp->tr_pos & ~MCD_BLOCK_MASK;
- 23129
- 23130 /* Byte count rounded up. */
- 23131 count = (pos - tp->tr_pos) + mcd_count;
- 23132 count = (count + MCD_BLOCK_SIZE - 1) & ~MCD_BLOCK_MASK;
- 23133
- 23134 /* XXX transfer size limits? */
- 23135 if (count > MCD_BLOCK_SIZE) count = MCD_BLOCK_SIZE;
- 23136
- 23137 /* Compute disk position in min:sec:sector */
- 23138 block2mss(pos >> MCD_BLOCK_SHIFT, mss);
- 23139
- 23140 /* Now try to read a block */
- 23141 errors = 0;
- 23142 while (errors < MCD_RETRIES)
- 23143 {
- 23144 lock();
- 23145 out_byte(MCD_DATA_PORT, MCD_READ_FROM_TO);
- 23146 out_byte(MCD_DATA_PORT, bin2bcd(mss[MINUTES]));
- 23147 out_byte(MCD_DATA_PORT, bin2bcd(mss[SECONDS]));
- 23148 out_byte(MCD_DATA_PORT, bin2bcd(mss[SECTOR]));
- 23149 out_byte(MCD_DATA_PORT, 0);
- .Ep 314 src/kernel/mcd.c
- 23150 out_byte(MCD_DATA_PORT, 0);
- 23151 out_byte(MCD_DATA_PORT, 1); /* XXX count in mss form? */
- 23152 unlock();
- 23153
- 23154 /* Wait for data */
- 23155 if (mcd_data_ready(REPLY_DELAY) == OK) break;
- 23156 printf("Mcd: data time outn");
- 23157 errors++;
- 23158 }
- 23159 if (errors == MCD_RETRIES) return(tp->tr_iop->io_nbytes = EIO);
- 23160
- 23161 /* Prepare reading data. */
- 23162 out_byte(MCD_CONTROL_PORT, 0x04);
- 23163
- 23164 while (pos < tp->tr_pos)
- 23165 {
- 23166 /* Discard bytes before the position we are really interested in. */
- 23167 n = tp->tr_pos - pos;
- 23168 if (n > DMA_BUF_SIZE) n = DMA_BUF_SIZE;
- 23169 port_read_byte(MCD_DATA_PORT, tmp_phys, n);
- 23170 #if XXX
- 23171 printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %un",
- 23172 count, n, 0, 0, 0, mcd_count);
- 23173 #endif
- 23174 pos += n;
- 23175 count -= n;
- 23176 }
- 23177
- 23178 while (mcd_count > 0 && count > 0)
- 23179 {
- 23180 /* Transfer bytes into the user buffers. */
- 23181 n = tp->tr_count;
- 23182 if (n > count) n = count;
- 23183 port_read_byte(MCD_DATA_PORT, tp->tr_phys, n);
- 23184 #if XXX
- 23185 printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %un",
- 23186 count, n, tp->tr_pos, tp->tr_iop->io_nbytes, tp->tr_count, mcd_count);
- 23187 #endif
- 23188 tp->tr_phys += n;
- 23189 tp->tr_pos += n;
- 23190 tp->tr_iop->io_nbytes -= n;
- 23191 if ((tp->tr_count -= n) == 0) tp++;
- 23192 count -= n;
- 23193 mcd_count -= n;
- 23194 }
- 23195
- 23196 while (count > 0)
- 23197 {
- 23198 /* Discard excess bytes. */
- 23199 n = count;
- 23200 if (n > DMA_BUF_SIZE) n = DMA_BUF_SIZE;
- 23201 port_read_byte(MCD_DATA_PORT, tmp_phys, n);
- 23202 #if XXX
- 23203 printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %un",
- 23204 count, n, 0, 0, 0, mcd_count);
- 23205 #endif
- 23206 count -= n;
- 23207 }
- 23208
- 23209 /* Finish reading data. */
- .Op 315 src/kernel/mcd.c
- 23210 out_byte(MCD_CONTROL_PORT, 0x0c);
- 23211 #if 0 /*XXX*/
- 23212 mcd_get_status(1);
- 23213 if (!(McdStatus & DISK_ERROR)) done = 1; /* OK, no errors */
- 23214 #endif
- 23215 }
- 23216
- 23217 return OK;
- 23218 }
- 23221 /*============================================================================*
- 23222 * mcd_geometry *
- 23223 *============================================================================*/
- 23224 PRIVATE void mcd_geometry(entry)
- 23225 struct partition *entry;
- 23226 {
- 23227 /* The geometry of a cdrom doesn't look like the geometry of a regular disk,
- 23228 * so we invent a geometry to keep external programs happy.
- 23229 */
- 23230 entry->cylinders = (mcd_part[0].dv_size >> SECTOR_SHIFT) / (64 * 32);
- 23231 entry->heads = 64;
- 23232 entry->sectors = 32;
- 23233 }
- 23236 /*============================================================================*
- 23237 * misc functions *
- 23238 *============================================================================*/
- 23239 PRIVATE u8_t bin2bcd(u8_t b)
- 23240 {
- 23241 /* Convert a number to binary-coded-decimal */
- 23242 int u,t;
- 23243
- 23244 u = b%10;
- 23245 t = b/10;
- 23246 return (u8_t)(u | (t << 4));
- 23247 }
- 23250 PRIVATE void bcd2bin(u8_t *bcd)
- 23251 {
- 23252 /* Convert binary-coded-decimal to binary :-) */
- 23253
- 23254 *bcd = (*bcd >> 4) * 10 + (*bcd & 0xf);
- 23255 }
- 23258 PRIVATE void block2mss(block, mss)
- 23259 long block;
- 23260 u8_t *mss;
- 23261 {
- 23262 /* Compute disk position of a block in min:sec:sector */
- 23263
- 23264 block += MCD_SKIP;
- 23265 mss[MINUTES] = block/(SECONDS_PER_MINUTE * SECTORS_PER_SECOND);
- 23266 block %= (SECONDS_PER_MINUTE * SECTORS_PER_SECOND);
- 23267 mss[SECONDS] = block/(SECTORS_PER_SECOND);
- 23268 mss[SECTOR] = block%(SECTORS_PER_SECOND);
- 23269 }
- .Ep 316 src/kernel/mcd.c
- 23272 PRIVATE long mss2block(u8_t *mss)
- 23273 {
- 23274 /* Compute block number belonging to
- 23275 * disk position min:sec:sector
- 23276 */
- 23277
- 23278 return ((((unsigned long) mss[MINUTES] * SECONDS_PER_MINUTE
- 23279 + (unsigned long) mss[SECONDS]) * SECTORS_PER_SECOND)
- 23280 + (unsigned long) mss[SECTOR]) - MCD_SKIP;
- 23281 }
- 23282 #endif /* ENABLE_MITSUMI_CDROM */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/memory.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 23300 /* This file contains the device dependent part of the drivers for the
- 23301 * following special files:
- 23302 * /dev/null - null device (data sink)
- 23303 * /dev/mem - absolute memory
- 23304 * /dev/kmem - kernel virtual memory
- 23305 * /dev/ram - RAM disk
- 23306 *
- 23307 * The file contains one entry point:
- 23308 *
- 23309 * mem_task: main entry when system is brought up
- 23310 *
- 23311 * Changes:
- 23312 * 20 Apr 1992 by Kees J. Bot: device dependent/independent split
- 23313 */
- 23314
- 23315 #include "kernel.h"
- 23316 #include "driver.h"
- 23317 #include <sys/ioctl.h>
- 23318
- 23319 #define NR_RAMS 4 /* number of RAM-type devices */
- 23320
- 23321 PRIVATE struct device m_geom[NR_RAMS]; /* Base and size of each RAM disk */
- 23322 PRIVATE int m_device; /* current device */
- 23323
- 23324 FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
- 23325 FORWARD _PROTOTYPE( int m_schedule, (int proc_nr, struct iorequest_s *iop) );
- 23326 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
- 23327 FORWARD _PROTOTYPE( void m_init, (void) );
- 23328 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
- 23329 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
- 23330
- 23331
- 23332 /* Entry points to this driver. */
- 23333 PRIVATE struct driver m_dtab = {
- 23334 no_name, /* current device's name */
- 23335 m_do_open, /* open or mount */
- 23336 do_nop, /* nothing on a close */
- 23337 m_ioctl, /* specify ram disk geometry */
- 23338 m_prepare, /* prepare for I/O on a given minor device */
- 23339 m_schedule, /* do the I/O */
- .Op 317 src/kernel/memory.c
- 23340 nop_finish, /* schedule does the work, no need to be smart */
- 23341 nop_cleanup, /* nothing's dirty */
- 23342 m_geometry, /* memory device "geometry" */
- 23343 };
- 23344
- 23345
- 23346 /*===========================================================================*
- 23347 * mem_task *
- 23348 *===========================================================================*/
- 23349 PUBLIC void mem_task()
- 23350 {
- 23351 m_init();
- 23352 driver_task(&m_dtab);
- 23353 }
- 23356 /*===========================================================================*
- 23357 * m_prepare *
- 23358 *===========================================================================*/
- 23359 PRIVATE struct device *m_prepare(device)
- 23360 int device;
- 23361 {
- 23362 /* Prepare for I/O on a device. */
- 23363
- 23364 if (device < 0 || device >= NR_RAMS) return(NIL_DEV);
- 23365 m_device = device;
- 23366
- 23367 return(&m_geom[device]);
- 23368 }
- 23371 /*===========================================================================*
- 23372 * m_schedule *
- 23373 *===========================================================================*/
- 23374 PRIVATE int m_schedule(proc_nr, iop)
- 23375 int proc_nr; /* process doing the request */
- 23376 struct iorequest_s *iop; /* pointer to read or write request */
- 23377 {
- 23378 /* Read or write /dev/null, /dev/mem, /dev/kmem, or /dev/ram. */
- 23379
- 23380 int device, count, opcode;
- 23381 phys_bytes mem_phys, user_phys;
- 23382 struct device *dv;
- 23383
- 23384 /* Type of request */
- 23385 opcode = iop->io_request & ~OPTIONAL_IO;
- 23386
- 23387 /* Get minor device number and check for /dev/null. */
- 23388 device = m_device;
- 23389 dv = &m_geom[device];
- 23390
- 23391 /* Determine address where data is to go or to come from. */
- 23392 user_phys = numap(proc_nr, (vir_bytes) iop->io_buf,
- 23393 (vir_bytes) iop->io_nbytes);
- 23394 if (user_phys == 0) return(iop->io_nbytes = EINVAL);
- 23395
- 23396 if (device == NULL_DEV) {
- 23397 /* /dev/null: Black hole. */
- 23398 if (opcode == DEV_WRITE) iop->io_nbytes = 0;
- 23399 count = 0;
- .Ep 318 src/kernel/memory.c
- 23400 } else {
- 23401 /* /dev/mem, /dev/kmem, or /dev/ram: Check for EOF */
- 23402 if (iop->io_position >= dv->dv_size) return(OK);
- 23403 count = iop->io_nbytes;
- 23404 if (iop->io_position + count > dv->dv_size)
- 23405 count = dv->dv_size - iop->io_position;
- 23406 }
- 23407
- 23408 /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram */
- 23409 mem_phys = dv->dv_base + iop->io_position;
- 23410
- 23411 /* Book the number of bytes to be transferred in advance. */
- 23412 iop->io_nbytes -= count;
- 23413
- 23414 if (count == 0) return(OK);
- 23415
- 23416 /* Copy the data. */
- 23417 if (opcode == DEV_READ)
- 23418 phys_copy(mem_phys, user_phys, (phys_bytes) count);
- 23419 else
- 23420 phys_copy(user_phys, mem_phys, (phys_bytes) count);
- 23421
- 23422 return(OK);
- 23423 }
- 23426 /*============================================================================*
- 23427 * m_do_open *
- 23428 *============================================================================*/
- 23429 PRIVATE int m_do_open(dp, m_ptr)
- 23430 struct driver *dp;
- 23431 message *m_ptr;
- 23432 {
- 23433 /* Check device number on open. Give I/O privileges to a process opening
- 23434 * /dev/mem or /dev/kmem.
- 23435 */
- 23436
- 23437 if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
- 23438
- 23439 #if (CHIP == INTEL)
- 23440 if (m_device == MEM_DEV || m_device == KMEM_DEV)
- 23441 enable_iop(proc_addr(m_ptr->PROC_NR));
- 23442 #endif
- 23443
- 23444 return(OK);
- 23445 }
- 23448 /*===========================================================================*
- 23449 * m_init *
- 23450 *===========================================================================*/
- 23451 PRIVATE void m_init()
- 23452 {
- 23453 /* Initialize this task. */
- 23454 extern int _end;
- 23455
- 23456 m_geom[KMEM_DEV].dv_base = vir2phys(0);
- 23457 m_geom[KMEM_DEV].dv_size = vir2phys(&_end);
- 23458
- 23459 #if (CHIP == INTEL)
- .Op 319 src/kernel/memory.c
- 23460 if (!protected_mode) {
- 23461 m_geom[MEM_DEV].dv_size = 0x100000; /* 1M for 8086 systems */
- 23462 } else {
- 23463 #if _WORD_SIZE == 2
- 23464 m_geom[MEM_DEV].dv_size = 0x1000000; /* 16M for 286 systems */
- 23465 #else
- 23466 m_geom[MEM_DEV].dv_size = 0xFFFFFFFF; /* 4G-1 for 386 systems */
- 23467 #endif
- 23468 }
- 23469 #else /* !(CHIP == INTEL) */
- 23470 #if (CHIP == M68000)
- 23471 m_geom[MEM_DEV].dv_size = MEM_BYTES;
- 23472 #else /* !(CHIP == M68000) */
- 23473 #error /* memory limit not set up */
- 23474 #endif /* !(CHIP == M68000) */
- 23475 #endif /* !(CHIP == INTEL) */
- 23476 }
- 23479 /*===========================================================================*
- 23480 * m_ioctl *
- 23481 *===========================================================================*/
- 23482 PRIVATE int m_ioctl(dp, m_ptr)
- 23483 struct driver *dp;
- 23484 message *m_ptr; /* pointer to read or write message */
- 23485 {
- 23486 /* Set parameters for one of the RAM disks. */
- 23487
- 23488 unsigned long bytesize;
- 23489 unsigned base, size;
- 23490 struct memory *memp;
- 23491 static struct psinfo psinfo = { NR_TASKS, NR_PROCS, (vir_bytes) proc, 0, 0 };
- 23492 phys_bytes psinfo_phys;
- 23493
- 23494 switch (m_ptr->REQUEST) {
- 23495 case MIOCRAMSIZE:
- 23496 /* FS sets the RAM disk size. */
- 23497 if (m_ptr->PROC_NR != FS_PROC_NR) return(EPERM);
- 23498
- 23499 bytesize = m_ptr->POSITION * BLOCK_SIZE;
- 23500 size = (bytesize + CLICK_SHIFT-1) >> CLICK_SHIFT;
- 23501
- 23502 /* Find a memory chunk big enough for the RAM disk. */
- 23503 memp= &mem[NR_MEMS];
- 23504 while ((--memp)->size < size) {
- 23505 if (memp == mem) panic("RAM disk is too big", NO_NUM);
- 23506 }
- 23507 base = memp->base;
- 23508 memp->base += size;
- 23509 memp->size -= size;
- 23510
- 23511 m_geom[RAM_DEV].dv_base = (unsigned long) base << CLICK_SHIFT;
- 23512 m_geom[RAM_DEV].dv_size = bytesize;
- 23513 break;
- 23514 case MIOCSPSINFO:
- 23515 /* MM or FS set the address of their process table. */
- 23516 if (m_ptr->PROC_NR == MM_PROC_NR) {
- 23517 psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
- 23518 } else
- 23519 if (m_ptr->PROC_NR == FS_PROC_NR) {
- .Ep 320 src/kernel/memory.c
- 23520 psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
- 23521 } else {
- 23522 return(EPERM);
- 23523 }
- 23524 break;
- 23525 case MIOCGPSINFO:
- 23526 /* The ps program wants the process table addresses. */
- 23527 psinfo_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- 23528 sizeof(psinfo));
- 23529 if (psinfo_phys == 0) return(EFAULT);
- 23530 phys_copy(vir2phys(&psinfo), psinfo_phys, (phys_bytes) sizeof(psinfo));
- 23531 break;
- 23532 default:
- 23533 return(do_diocntl(&m_dtab, m_ptr));
- 23534 }
- 23535 return(OK);
- 23536 }
- 23539 /*============================================================================*
- 23540 * m_geometry *
- 23541 *============================================================================*/
- 23542 PRIVATE void m_geometry(entry)
- 23543 struct partition *entry;
- 23544 {
- 23545 /* Memory devices don't have a geometry, but the outside world insists. */
- 23546 entry->cylinders = (m_geom[m_device].dv_size >> SECTOR_SHIFT) / (64 * 32);
- 23547 entry->heads = 64;
- 23548 entry->sectors = 32;
- 23549 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/misc.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 23600 /* This file contains a collection of miscellaneous procedures:
- 23601 * mem_init: initialize memory tables. Some memory is reported
- 23602 * by the BIOS, some is guesstimated and checked later
- 23603 * env_parse parse environment variable.
- 23604 * bad_assertion for debugging
- 23605 * bad_compare for debugging
- 23606 */
- 23607
- 23608 #include "kernel.h"
- 23609 #include "assert.h"
- 23610 #include <stdlib.h>
- 23611 #include <minix/com.h>
- 23612
- 23613 #if (CHIP == INTEL)
- 23614
- 23615 #define EM_BASE 0x100000L /* base of extended memory on AT's */
- 23616 #define SHADOW_BASE 0xFA0000L /* base of RAM shadowing ROM on some AT's */
- 23617 #define SHADOW_MAX 0x060000L /* maximum usable shadow memory (16M limit) */
- 23618
- 23619 /*=========================================================================*
- .Op 321 src/kernel/misc.c
- 23620 * mem_init *
- 23621 *=========================================================================*/
- 23622 PUBLIC void mem_init()
- 23623 {
- 23624 /* Initialize the memory size tables. This is complicated by fragmentation
- 23625 * and different access strategies for protected mode. There must be a
- 23626 * chunk at 0 big enough to hold Minix proper. For 286 and 386 processors,
- 23627 * there can be extended memory (memory above 1MB). This usually starts at
- 23628 * 1MB, but there may be another chunk just below 16MB, reserved under DOS
- 23629 * for shadowing ROM, but available to Minix if the hardware can be re-mapped.
- 23630 * In protected mode, extended memory is accessible assuming CLICK_SIZE is
- 23631 * large enough, and is treated as ordinary memory.
- 23632 */
- 23633
- 23634 u32_t ext_clicks;
- 23635 phys_clicks max_clicks;
- 23636
- 23637 /* Get the size of ordinary memory from the BIOS. */
- 23638 mem[0].size = k_to_click(low_memsize); /* base = 0 */
- 23639
- 23640 if (pc_at && protected_mode) {
- 23641 /* Get the size of extended memory from the BIOS. This is special
- 23642 * except in protected mode, but protected mode is now normal.
- 23643 * Note that no more than 16M can be addressed in 286 mode, so make
- 23644 * sure that the highest memory address fits in a short when counted
- 23645 * in clicks.
- 23646 */
- 23647 ext_clicks = k_to_click((u32_t) ext_memsize);
- 23648 max_clicks = USHRT_MAX - (EM_BASE >> CLICK_SHIFT);
- 23649 mem[1].size = MIN(ext_clicks, max_clicks);
- 23650 mem[1].base = EM_BASE >> CLICK_SHIFT;
- 23651
- 23652 if (ext_memsize <= (unsigned) ((SHADOW_BASE - EM_BASE) / 1024)
- 23653 && check_mem(SHADOW_BASE, SHADOW_MAX) == SHADOW_MAX) {
- 23654 /* Shadow ROM memory. */
- 23655 mem[2].size = SHADOW_MAX >> CLICK_SHIFT;
- 23656 mem[2].base = SHADOW_BASE >> CLICK_SHIFT;
- 23657 }
- 23658 }
- 23659
- 23660 /* Total system memory. */
- 23661 tot_mem_size = mem[0].size + mem[1].size + mem[2].size;
- 23662 }
- 23663 #endif /* (CHIP == INTEL) */
- 23664
- 23665 /*=========================================================================*
- 23666 * env_parse *
- 23667 *=========================================================================*/
- 23668 PUBLIC int env_parse(env, fmt, field, param, min, max)
- 23669 char *env; /* environment variable to inspect */
- 23670 char *fmt; /* template to parse it with */
- 23671 int field; /* field number of value to return */
- 23672 long *param; /* address of parameter to get */
- 23673 long min, max; /* minimum and maximum values for the parameter */
- 23674 {
- 23675 /* Parse an environment variable setting, something like "DPETH0=300:3".
- 23676 * Panic if the parsing fails. Return EP_UNSET if the environment variable
- 23677 * is not set, EP_OFF if it is set to "off", EP_ON if set to "on" or a
- 23678 * field is left blank, or EP_SET if a field is given (return value through
- 23679 * *param). Commas and colons may be used in the environment and format
- .Ep 322 src/kernel/misc.c
- 23680 * string, fields in the environment string may be empty, and punctuation
- 23681 * may be missing to skip fields. The format string contains characters
- 23682 * 'd', 'o', 'x' and 'c' to indicate that 10, 8, 16, or 0 is used as the
- 23683 * last argument to strtol.
- 23684 */
- 23685
- 23686 char *val, *end;
- 23687 long newpar;
- 23688 int i = 0, radix, r;
- 23689
- 23690 if ((val = k_getenv(env)) == NIL_PTR) return(EP_UNSET);
- 23691 if (strcmp(val, "off") == 0) return(EP_OFF);
- 23692 if (strcmp(val, "on") == 0) return(EP_ON);
- 23693
- 23694 r = EP_ON;
- 23695 for (;;) {
- 23696 while (*val == ' ') val++;
- 23697
- 23698 if (*val == 0) return(r); /* the proper exit point */
- 23699
- 23700 if (*fmt == 0) break; /* too many values */
- 23701
- 23702 if (*val == ',' || *val == ':') {
- 23703 /* Time to go to the next field. */
- 23704 if (*fmt == ',' || *fmt == ':') i++;
- 23705 if (*fmt++ == *val) val++;
- 23706 } else {
- 23707 /* Environment contains a value, get it. */
- 23708 switch (*fmt) {
- 23709 case 'd': radix = 10; break;
- 23710 case 'o': radix = 010; break;
- 23711 case 'x': radix = 0x10; break;
- 23712 case 'c': radix = 0; break;
- 23713 default: goto badenv;
- 23714 }
- 23715 newpar = strtol(val, &end, radix);
- 23716
- 23717 if (end == val) break; /* not a number */
- 23718 val = end;
- 23719
- 23720 if (i == field) {
- 23721 /* The field requested. */
- 23722 if (newpar < min || newpar > max) break;
- 23723 *param = newpar;
- 23724 r = EP_SET;
- 23725 }
- 23726 }
- 23727 }
- 23728 badenv:
- 23729 printf("Bad environment setting: '%s = %s'n", env, k_getenv(env));
- 23730 panic("", NO_NUM);
- 23731 /*NOTREACHED*/
- 23732 }
- 23734 #if DEBUG
- 23735 /*=========================================================================*
- 23736 * bad_assertion *
- 23737 *=========================================================================*/
- 23738 PUBLIC void bad_assertion(file, line, what)
- 23739 char *file;
- .Op 323 src/kernel/misc.c
- 23740 int line;
- 23741 char *what;
- 23742 {
- 23743 printf("panic at %s(%d): assertion "%s" failedn", file, line, what);
- 23744 panic(NULL, NO_NUM);
- 23745 }
- 23747 /*=========================================================================*
- 23748 * bad_compare *
- 23749 *=========================================================================*/
- 23750 PUBLIC void bad_compare(file, line, lhs, what, rhs)
- 23751 char *file;
- 23752 int line;
- 23753 int lhs;
- 23754 char *what;
- 23755 int rhs;
- 23756 {
- 23757 printf("panic at %s(%d): compare (%d) %s (%d) failedn",
- 23758 file, line, lhs, what, rhs);
- 23759 panic(NULL, NO_NUM);
- 23760 }
- 23761 #endif /* DEBUG */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/ne2000.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 23800 /*
- 23801 ne2000.c
- 23802
- 23803 Driver for the ne2000 ethernet cards. This file contains only the ne2000
- 23804 specific code, the rest is in dp8390.c
- 23805
- 23806 Created: March 15, 1994 by Philip Homburg <philip@cs.vu.nl>
- 23807 */
- 23808
- 23809 #include "kernel.h"
- 23810 #include <net/gen/ether.h>
- 23811 #include <net/gen/eth_io.h>
- 23812 #include "dp8390.h"
- 23813 #include "ne2000.h"
- 23814
- 23815 #if ENABLE_NETWORKING
- 23816
- 23817 #if !__minix_vmd
- 23818 #define debug 0
- 23819 #endif
- 23820
- 23821 #define N 100
- 23822
- 23823 _PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat) );
- 23824
- 23825 u8_t pat0[]= { 0x00, 0x00, 0x00, 0x00 };
- 23826 u8_t pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
- 23827 u8_t pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
- 23828 u8_t pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
- 23829
- .Ep 324 src/kernel/ne2000.c
- 23830 _PROTOTYPE( static int test_8, (dpeth_t *dep, int pos, u8_t *pat) );
- 23831 _PROTOTYPE( static int test_16, (dpeth_t *dep, int pos, u8_t *pat) );
- 23832 _PROTOTYPE( static void ne_init, (dpeth_t *dep) );
- 23833 _PROTOTYPE( static void ne_stop, (dpeth_t *dep) );
- 23834
- 23835 /*===========================================================================*
- 23836 * ne_probe *
- 23837 *===========================================================================*/
- 23838 int ne_probe(dep)
- 23839 dpeth_t *dep;
- 23840 {
- 23841 int byte;
- 23842 int i;
- 23843 int loc1, loc2;
- 23844 testf_t f;
- 23845
- 23846 dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
- 23847
- 23848 /* We probe for an ne1000 or an ne2000 by testing whether the
- 23849 * on board is reachable through the dp8390. Note that the
- 23850 * ne1000 is an 8bit card and has a memory region distict from
- 23851 * the 16bit ne2000
- 23852 */
- 23853
- 23854 for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
- 23855 {
- 23856 /* Reset the ethernet card */
- 23857 byte= inb_ne(dep, NE_RESET);
- 23858 milli_delay(2);
- 23859 outb_ne(dep, NE_RESET, byte);
- 23860 milli_delay(2);
- 23861
- 23862 /* Reset the dp8390 */
- 23863 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
- 23864 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
- 23865 ; /* Do nothing */
- 23866
- 23867 /* Check if the dp8390 is really there */
- 23868 if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
- 23869 (CR_STP|CR_DM_ABORT))
- 23870 {
- 23871 return 0;
- 23872 }
- 23873
- 23874 /* Put it in loop-back mode */
- 23875 outb_reg0(dep, DP_RCR, RCR_MON);
- 23876 outb_reg0(dep, DP_TCR, TCR_NORMAL);
- 23877 if (dep->de_16bit)
- 23878 {
- 23879 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
- 23880 DCR_BMS);
- 23881 }
- 23882 else
- 23883 {
- 23884 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
- 23885 DCR_BMS);
- 23886 }
- 23887
- 23888 if (dep->de_16bit)
- 23889 {
- .Op 325 src/kernel/ne2000.c
- 23890 loc1= NE2000_START;
- 23891 loc2= NE2000_START + NE2000_SIZE - 4;
- 23892 f= test_16;
- 23893 }
- 23894 else
- 23895 {
- 23896 loc1= NE1000_START;
- 23897 loc2= NE1000_START + NE1000_SIZE - 4;
- 23898 f= test_8;
- 23899 }
- 23900 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
- 23901 f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
- 23902 f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
- 23903 f(dep, loc2, pat2) && f(dep, loc2, pat3))
- 23904 {
- 23905 /* We don't need a memory segment */
- 23906 dep->de_linmem= 0;
- 23907 dep->de_initf= ne_init;
- 23908 dep->de_stopf= ne_stop;
- 23909 dep->de_prog_IO= 1;
- 23910 return 1;
- 23911 }
- 23912 }
- 23913 return 0;
- 23914 }
- 23917 /*===========================================================================*
- 23918 * test_8 *
- 23919 *===========================================================================*/
- 23920 static int test_8(dep, pos, pat)
- 23921 dpeth_t *dep;
- 23922 int pos;
- 23923 u8_t *pat;
- 23924 {
- 23925 u8_t buf[4];
- 23926 int i;
- 23927 int r;
- 23928
- 23929 outb_reg0(dep, DP_ISR, 0xFF);
- 23930
- 23931 /* Setup a transfer to put the pattern. */
- 23932 outb_reg0(dep, DP_RBCR0, 4);
- 23933 outb_reg0(dep, DP_RBCR1, 0);
- 23934 outb_reg0(dep, DP_RSAR0, pos & 0xFF);
- 23935 outb_reg0(dep, DP_RSAR1, pos >> 8);
- 23936 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
- 23937
- 23938 for (i= 0; i<4; i++)
- 23939 outb_ne(dep, NE_DATA, pat[i]);
- 23940
- 23941 for (i= 0; i<N; i++)
- 23942 {
- 23943 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
- 23944 break;
- 23945 }
- 23946 if (i == N)
- 23947 {
- 23948 printf("ne2000, test_8: remote dma failed to completen");
- 23949 return 0;
- .Ep 326 src/kernel/ne2000.c
- 23950 }
- 23951
- 23952 outb_reg0(dep, DP_RBCR0, 4);
- 23953 outb_reg0(dep, DP_RBCR1, 0);
- 23954 outb_reg0(dep, DP_RSAR0, pos & 0xFF);
- 23955 outb_reg0(dep, DP_RSAR1, pos >> 8);
- 23956 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
- 23957
- 23958 for (i= 0; i<4; i++)
- 23959 buf[i]= inb_ne(dep, NE_DATA);
- 23960
- 23961 r= (memcmp(buf, pat, 4) == 0);
- 23962 return r;
- 23963 }
- 23966 /*===========================================================================*
- 23967 * test_16 *
- 23968 *===========================================================================*/
- 23969 static int test_16(dep, pos, pat)
- 23970 dpeth_t *dep;
- 23971 int pos;
- 23972 u8_t *pat;
- 23973 {
- 23974 u8_t buf[4];
- 23975 int i;
- 23976 int r;
- 23977
- 23978 outb_reg0(dep, DP_ISR, 0xFF);
- 23979
- 23980 /* Setup a transfer to put the pattern. */
- 23981 outb_reg0(dep, DP_RBCR0, 4);
- 23982 outb_reg0(dep, DP_RBCR1, 0);
- 23983 outb_reg0(dep, DP_RSAR0, pos & 0xFF);
- 23984 outb_reg0(dep, DP_RSAR1, pos >> 8);
- 23985 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
- 23986
- 23987 for (i= 0; i<4; i += 2)
- 23988 {
- 23989 outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
- 23990 }
- 23991
- 23992 for (i= 0; i<N; i++)
- 23993 {
- 23994 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
- 23995 break;
- 23996 }
- 23997 if (i == N)
- 23998 {
- 23999 printf("ne2000, test_16: remote dma failed to completen");
- 24000 return 0;
- 24001 }
- 24002
- 24003 outb_reg0(dep, DP_RBCR0, 4);
- 24004 outb_reg0(dep, DP_RBCR1, 0);
- 24005 outb_reg0(dep, DP_RSAR0, pos & 0xFF);
- 24006 outb_reg0(dep, DP_RSAR1, pos >> 8);
- 24007 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
- 24008
- 24009 for (i= 0; i<4; i += 2)
- .Op 327 src/kernel/ne2000.c
- 24010 {
- 24011 *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
- 24012 }
- 24013
- 24014 r= (memcmp(buf, pat, 4) == 0);
- 24015 return r;
- 24016 }
- 24019 /*===========================================================================*
- 24020 * ne_init *
- 24021 *===========================================================================*/
- 24022 static void ne_init(dep)
- 24023 dpeth_t *dep;
- 24024 {
- 24025 int i;
- 24026 int word, sendq_nr;
- 24027
- 24028 /* Setup a transfer to get the ethernet address. */
- 24029 if (dep->de_16bit)
- 24030 outb_reg0(dep, DP_RBCR0, 6*2);
- 24031 else
- 24032 outb_reg0(dep, DP_RBCR0, 6);
- 24033 outb_reg0(dep, DP_RBCR1, 0);
- 24034 outb_reg0(dep, DP_RSAR0, 0);
- 24035 outb_reg0(dep, DP_RSAR1, 0);
- 24036 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
- 24037
- 24038 for (i= 0; i<6; i++)
- 24039 {
- 24040 if (dep->de_16bit)
- 24041 {
- 24042 word= inw_ne(dep, NE_DATA);
- 24043 dep->de_address.ea_addr[i]= word;
- 24044 }
- 24045 else
- 24046 {
- 24047 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
- 24048 }
- 24049 }
- 24050 dep->de_data_port= dep->de_base_port + NE_DATA;
- 24051 if (dep->de_16bit)
- 24052 {
- 24053 dep->de_ramsize= NE2000_SIZE;
- 24054 dep->de_offset_page= NE2000_START / DP_PAGESIZE;
- 24055 }
- 24056 else
- 24057 {
- 24058 dep->de_ramsize= NE1000_SIZE;
- 24059 dep->de_offset_page= NE1000_START / DP_PAGESIZE;
- 24060 }
- 24061
- 24062 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
- 24063 sendq_nr= dep->de_ramsize / 0x2000;
- 24064 if (sendq_nr < 1)
- 24065 sendq_nr= 1;
- 24066 else if (sendq_nr > SENDQ_NR)
- 24067 sendq_nr= SENDQ_NR;
- 24068 dep->de_sendq_nr= sendq_nr;
- 24069 for (i= 0; i<sendq_nr; i++)
- .Ep 328 src/kernel/ne2000.c
- 24070 {
- 24071 dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
- 24072 i*SENDQ_PAGES;
- 24073 }
- 24074
- 24075 dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
- 24076 dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
- 24077
- 24078 /* Can't override the default IRQ. */
- 24079 dep->de_irq &= ~DEI_DEFAULT;
- 24080
- 24081 if (!debug)
- 24082 {
- 24083 printf("ne2000: NE%d000 at %X:%dn",
- 24084 dep->de_16bit ? 2 : 1,
- 24085 dep->de_base_port, dep->de_irq);
- 24086 }
- 24087 else
- 24088 {
- 24089 printf("ne2000: Novell %s ethernet card ",
- 24090 dep->de_16bit ? "16-bit (ne2000)" : "8-bit (ne1000)");
- 24091 printf("at I/O address 0x%X, memory size 0x%X, irq %dn",
- 24092 dep->de_base_port, dep->de_ramsize, dep->de_irq);
- 24093 }
- 24094 }
- 24097 /*===========================================================================*
- 24098 * ne_stop *
- 24099 *===========================================================================*/
- 24100 static void ne_stop(dep)
- 24101 dpeth_t *dep;
- 24102 {
- 24103 int byte;
- 24104
- 24105 /* Reset the ethernet card */
- 24106 byte= inb_ne(dep, NE_RESET);
- 24107 milli_delay(2);
- 24108 outb_ne(dep, NE_RESET, byte);
- 24109 }
- 24111 #endif /* ENABLE_NETWORKING */
- 24112
- 24113 /*
- 24114 * $PchHeader: /mount/hd2/minix/sys/kernel/ibm/RCS/ne2000.c,v 1.2 1995/01/12 21:48:53 philip Exp $
- 24115 */
- .Op 329 src/kernel/printer.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/printer.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 24200 /* This file contains the printer driver. It is a fairly simple driver,
- 24201 * supporting only one printer. Characters that are written to the driver
- 24202 * are written to the printer without any changes at all.
- 24203 *
- 24204 * The valid messages and their parameters are:
- 24205 *
- 24206 * HARD_INT: interrupt handler has finished current chunk of output
- 24207 * DEV_WRITE: a process wants to write on a terminal
- 24208 * CANCEL: terminate a previous incomplete system call immediately
- 24209 *
- 24210 * m_type TTY_LINE PROC_NR COUNT ADDRESS
- 24211 * -------------------------------------------------------
- 24212 * | HARD_INT | | | | |
- 24213 * |-------------+---------+---------+---------+---------|
- 24214 * | DEV_WRITE |minor dev| proc nr | count | buf ptr |
- 24215 * |-------------+---------+---------+---------+---------|
- 24216 * | CANCEL |minor dev| proc nr | | |
- 24217 * -------------------------------------------------------
- 24218 *
- 24219 * Note: since only 1 printer is supported, minor dev is not used at present.
- 24220 */
- 24221
- 24222 #include "kernel.h"
- 24223 #include <minix/callnr.h>
- 24224 #include <minix/com.h>
- 24225 #include "proc.h"
- 24226
- 24227 /* Control bits (in port_base + 2). "+" means positive logic and "-" means
- 24228 * negative logic. Most of the signals are negative logic on the pins but
- 24229 * many are converted to positive logic in the ports. Some manuals are
- 24230 * misleading because they only document the pin logic.
- 24231 *
- 24232 * +0x01 Pin 1 -Strobe
- 24233 * +0x02 Pin 14 -Auto Feed
- 24234 * -0x04 Pin 16 -Initialize Printer
- 24235 * +0x08 Pin 17 -Select Printer
- 24236 * +0x10 IRQ7 Enable
- 24237 *
- 24238 * Auto Feed and Select Printer are always enabled. Strobe is enabled briefly
- 24239 * when characters are output. Initialize Printer is enabled briefly when
- 24240 * the task is started. IRQ7 is enabled when the first character is output
- 24241 * and left enabled until output is completed (or later after certain
- 24242 * abnormal completions).
- 24243 */
- 24244 #define ASSERT_STROBE 0x1D /* strobe a character to the interface */
- 24245 #define NEGATE_STROBE 0x1C /* enable interrupt on interface */
- 24246 #define SELECT 0x0C /* select printer bit */
- 24247 #define INIT_PRINTER 0x08 /* init printer bits */
- 24248
- 24249 /* Status bits (in port_base + 2).
- 24250 *
- 24251 * -0x08 Pin 15 -Error
- 24252 * +0x10 Pin 13 +Select Status
- 24253 * +0x20 Pin 12 +Out of Paper
- 24254 * -0x40 Pin 10 -Acknowledge
- .Ep 330 src/kernel/printer.c
- 24255 * -0x80 Pin 11 +Busy
- 24256 */
- 24257 #define BUSY_STATUS 0x10 /* printer gives this status when busy */
- 24258 #define NO_PAPER 0x20 /* status bit saying that paper is out */
- 24259 #define NORMAL_STATUS 0x90 /* printer gives this status when idle */
- 24260 #define ON_LINE 0x10 /* status bit saying that printer is online */
- 24261 #define STATUS_MASK 0xB0 /* mask to filter out status bits */
- 24262
- 24263 /* Centronics interface timing that must be met by software (in microsec).
- 24264 *
- 24265 * Strobe length: 0.5u to 100u (not sure about the upper limit).
- 24266 * Data set up: 0.5u before strobe.
- 24267 * Data hold: 0.5u after strobe.
- 24268 * Init pulse length: over 200u (not sure).
- 24269 *
- 24270 * The strobe length is about 50u with the code here and function calls for
- 24271 * out_byte() - not much to spare. The 0.5u minimums may be violated if
- 24272 * out_byte() is generated in-line on a fast machine. Some printer boards
- 24273 * are slower than 0.5u anyway.
- 24274 */
- 24275
- 24276 PRIVATE int caller; /* process to tell when printing done (FS) */
- 24277 PRIVATE int done_status; /* status of last output completion */
- 24278 PRIVATE int oleft; /* bytes of output left in obuf */
- 24279 PRIVATE char obuf[128]; /* output buffer */
- 24280 PRIVATE int opending; /* nonzero while expected printing not done */
- 24281 PRIVATE char *optr; /* ptr to next char in obuf to print */
- 24282 PRIVATE int orig_count; /* original byte count */
- 24283 PRIVATE int port_base; /* I/O port for printer */
- 24284 PRIVATE int proc_nr; /* user requesting the printing */
- 24285 PRIVATE int user_left; /* bytes of output left in user buf */
- 24286 PRIVATE vir_bytes user_vir; /* address of remainder of user buf */
- 24287 PRIVATE int writing; /* nonzero while write is in progress */
- 24288
- 24289 FORWARD _PROTOTYPE( void do_cancel, (message *m_ptr) );
- 24290 FORWARD _PROTOTYPE( void do_done, (void) );
- 24291 FORWARD _PROTOTYPE( void do_write, (message *m_ptr) );
- 24292 FORWARD _PROTOTYPE( void pr_start, (void) );
- 24293 FORWARD _PROTOTYPE( void print_init, (void) );
- 24294 FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process,
- 24295 int status) );
- 24296 FORWARD _PROTOTYPE( int pr_handler, (int irq) );
- 24297
- 24298 /*===========================================================================*
- 24299 * printer_task *
- 24300 *===========================================================================*/
- 24301 PUBLIC void printer_task()
- 24302 {
- 24303 /* Main routine of the printer task. */
- 24304
- 24305 message pr_mess; /* buffer for all incoming messages */
- 24306
- 24307 print_init(); /* initialize */
- 24308
- 24309 while (TRUE) {
- 24310 receive(ANY, &pr_mess);
- 24311 switch(pr_mess.m_type) {
- 24312 case DEV_OPEN:
- 24313 case DEV_CLOSE:
- 24314 reply(TASK_REPLY, pr_mess.m_source, pr_mess.PROC_NR, OK);
- .Op 331 src/kernel/printer.c
- 24315 break;
- 24316 case DEV_WRITE: do_write(&pr_mess); break;
- 24317 case CANCEL : do_cancel(&pr_mess); break;
- 24318 case HARD_INT : do_done(); break;
- 24319 default:
- 24320 reply(TASK_REPLY, pr_mess.m_source, pr_mess.PROC_NR, EINVAL);
- 24321 }
- 24322 }
- 24323 }
- 24326 /*===========================================================================*
- 24327 * do_write *
- 24328 *===========================================================================*/
- 24329 PRIVATE void do_write(m_ptr)
- 24330 register message *m_ptr; /* pointer to the newly arrived message */
- 24331 {
- 24332 /* The printer is used by sending DEV_WRITE messages to it. Process one. */
- 24333
- 24334 register int r;
- 24335
- 24336 /* Reject command if last write is not finished, count not positive, or
- 24337 * user address bad.
- 24338 */
- 24339 if (writing) {
- 24340 r = EIO;
- 24341 } else
- 24342 if (m_ptr->COUNT <= 0) {
- 24343 r = EINVAL;
- 24344 } else
- 24345 if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
- 24346 r = EFAULT;
- 24347 } else {
- 24348 /* Save information needed later. */
- 24349 caller = m_ptr->m_source;
- 24350 proc_nr = m_ptr->PROC_NR;
- 24351 user_left = m_ptr->COUNT;
- 24352 orig_count = m_ptr->COUNT;
- 24353 user_vir = (vir_bytes) m_ptr->ADDRESS;
- 24354 pr_start();
- 24355 writing = TRUE;
- 24356 r = SUSPEND;
- 24357 }
- 24358
- 24359 /* Reply to FS, no matter what happened. */
- 24360 reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
- 24361 }
- 24364 /*===========================================================================*
- 24365 * do_done *
- 24366 *===========================================================================*/
- 24367 PRIVATE void do_done()
- 24368 {
- 24369 /* Previous chunk of printing is finished. Continue if OK and more.
- 24370 * Otherwise, reply to caller (FS).
- 24371 */
- 24372
- 24373 register int status;
- 24374
- .Ep 332 src/kernel/printer.c
- 24375 if (!writing) return; /* interrupt while canceling */
- 24376 if (done_status != OK) {
- 24377 /* Printer error. */
- 24378 status = EIO;
- 24379 if ((done_status & ON_LINE) == 0) {
- 24380 printf("Printer is not on linen");
- 24381 } else
- 24382 if (done_status & NO_PAPER) {
- 24383 status = EAGAIN; /* out of paper */
- 24384 } else {
- 24385 printf("Printer error, status is 0x%02Xn", done_status);
- 24386 }
- 24387 if (status == EAGAIN && user_left < orig_count) {
- 24388 /* Some characters have been printed, tell how many. */
- 24389 status = orig_count - user_left;
- 24390 }
- 24391 oleft = 0; /* cancel output by interrupt handler */
- 24392 } else if (user_left != 0) {
- 24393 pr_start();
- 24394 return;
- 24395 } else {
- 24396 status = orig_count;
- 24397 }
- 24398 reply(REVIVE, caller, proc_nr, status);
- 24399 writing = FALSE;
- 24400 }
- 24403 /*===========================================================================*
- 24404 * do_cancel *
- 24405 *===========================================================================*/
- 24406 PRIVATE void do_cancel(m_ptr)
- 24407 register message *m_ptr; /* pointer to the newly arrived message */
- 24408 {
- 24409 /* Cancel a print request that has already started. Usually this means that
- 24410 * the process doing the printing has been killed by a signal. It is not
- 24411 * clear if there are race conditions. Try not to cancel the wrong process,
- 24412 * but rely on FS to handle the EINTR reply and de-suspension properly.
- 24413 */
- 24414
- 24415 if (writing && m_ptr->PROC_NR == proc_nr) {
- 24416 oleft = 0; /* cancel output by interrupt handler */
- 24417 writing = FALSE;
- 24418 }
- 24419 reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINTR);
- 24420 }
- 24423 /*===========================================================================*
- 24424 * reply *
- 24425 *===========================================================================*/
- 24426 PRIVATE void reply(code, replyee, process, status)
- 24427 int code; /* TASK_REPLY or REVIVE */
- 24428 int replyee; /* destination for message (normally FS) */
- 24429 int process; /* which user requested the printing */
- 24430 int status; /* number of chars printed or error code */
- 24431 {
- 24432 /* Send a reply telling FS that printing has started or stopped. */
- 24433
- 24434 message pr_mess;
- .Op 333 src/kernel/printer.c
- 24435
- 24436 pr_mess.m_type = code; /* TASK_REPLY or REVIVE */
- 24437 pr_mess.REP_STATUS = status; /* count or EIO */
- 24438 pr_mess.REP_PROC_NR = process; /* which user does this pertain to */
- 24439 send(replyee, &pr_mess); /* send the message */
- 24440 }
- 24443 /*===========================================================================*
- 24444 * print_init *
- 24445 *===========================================================================*/
- 24446 PRIVATE void print_init()
- 24447 {
- 24448 /* Set global variables. Get the port base for the first printer from the
- 24449 * BIOS and initialize the printer.
- 24450 */
- 24451
- 24452 phys_copy(0x408L, vir2phys(&port_base), 2L);
- 24453 out_byte(port_base + 2, INIT_PRINTER);
- 24454 milli_delay(2); /* easily satisfies Centronics minimum */
- 24455 out_byte(port_base + 2, SELECT);
- 24456 put_irq_handler(PRINTER_IRQ, pr_handler);
- 24457 enable_irq(PRINTER_IRQ); /* ready for printer interrupts */
- 24458 }
- 24461 /*==========================================================================*
- 24462 * pr_start *
- 24463 *==========================================================================*/
- 24464 PRIVATE void pr_start()
- 24465 {
- 24466 /* Start next chunk of printer output. */
- 24467
- 24468 register int chunk;
- 24469 phys_bytes user_phys;
- 24470
- 24471 if ( (chunk = user_left) > sizeof obuf) chunk = sizeof obuf;
- 24472 user_phys = proc_vir2phys(proc_addr(proc_nr), user_vir);
- 24473 phys_copy(user_phys, vir2phys(obuf), (phys_bytes) chunk);
- 24474 optr = obuf;
- 24475 opending = TRUE;
- 24476 oleft = chunk; /* now interrupt handler is enabled */
- 24477 }
- 24480 /*===========================================================================*
- 24481 * pr_handler *
- 24482 *===========================================================================*/
- 24483 PRIVATE int pr_handler(irq)
- 24484 int irq;
- 24485 {
- 24486 /* This is the interrupt handler. When a character has been printed, an
- 24487 * interrupt occurs, and the assembly code routine trapped to calls
- 24488 * pr_handler().
- 24489 *
- 24490 * One problem is that the 8259A controller generates spurious interrupts to
- 24491 * IRQ7 when it gets confused by mistimed interrupts on any line. (IRQ7 for
- 24492 * the first controller happens to be the printer IRQ.) Such an interrupt is
- 24493 * ignored as a side-affect of the method of checking the busy status. This
- 24494 * is harmless for the printer task but probably fatal to the task that missed
- .Ep 334 src/kernel/printer.c
- 24495 * the interrupt. It may be possible to recover by doing more work here.
- 24496 */
- 24497
- 24498 register int status;
- 24499
- 24500 if (oleft == 0) {
- 24501 /* Nothing more to print. Turn off printer interrupts in case they
- 24502 * are level-sensitive as on the PS/2. This should be safe even
- 24503 * when the printer is busy with a previous character, because the
- 24504 * interrupt status does not affect the printer.
- 24505 */
- 24506 out_byte(port_base + 2, SELECT);
- 24507 return 1;
- 24508 }
- 24509
- 24510 do {
- 24511 /* Loop to handle fast (buffered) printers. It is important that
- 24512 * processor interrupts are not disabled here, just printer interrupts.
- 24513 */
- 24514 status = in_byte(port_base + 1);
- 24515 if ((status & STATUS_MASK) == BUSY_STATUS) {
- 24516 /* Still busy with last output. This normally happens
- 24517 * immediately after doing output to an unbuffered or slow
- 24518 * printer. It may happen after a call from pr_start or
- 24519 * pr_restart, since they are not synchronized with printer
- 24520 * interrupts. It may happen after a spurious interrupt.
- 24521 */
- 24522 return 1;
- 24523 }
- 24524 if ((status & STATUS_MASK) == NORMAL_STATUS) {
- 24525 /* Everything is all right. Output another character. */
- 24526 out_byte(port_base, *optr++); /* output character */
- 24527 lock(); /* ensure strobe is not too long */
- 24528 out_byte(port_base + 2, ASSERT_STROBE);
- 24529 out_byte(port_base + 2, NEGATE_STROBE);
- 24530 unlock();
- 24531 opending = FALSE; /* show interrupt is working */
- 24532
- 24533 user_vir++;
- 24534 user_left--;
- 24535 } else {
- 24536 /* Error. This would be better ignored (treat as busy). */
- 24537 done_status = status;
- 24538 interrupt(PRINTER);
- 24539 return 1;
- 24540 }
- 24541 }
- 24542 while (--oleft != 0);
- 24543
- 24544 /* Finished printing chunk OK. */
- 24545 done_status = OK;
- 24546 interrupt(PRINTER);
- 24547 return 1; /* Reenable printer interrupt */
- 24548 }
- 24551 /*==========================================================================*
- 24552 * pr_restart *
- 24553 *==========================================================================*/
- 24554 PUBLIC void pr_restart()
- .Op 335 src/kernel/printer.c
- 24555 {
- 24556 /* Check if printer is hung up, and if so, restart it.
- 24557 * Disable_irq() returns true if the irq could be disabled, so that
- 24558 * pr_restart() is not reentered.
- 24559 */
- 24560
- 24561 if (oleft != 0) {
- 24562 if (opending && disable_irq(PRINTER_IRQ)) {
- 24563 (void) pr_handler(PRINTER_IRQ);
- 24564
- 24565 /* ready for printer interrupts again */
- 24566 enable_irq(PRINTER_IRQ);
- 24567 }
- 24568 opending = TRUE; /* expect some printing before next call */
- 24569 }
- 24570 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/proc.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 24600 /* This file contains essentially all of the process and message handling.
- 24601 * It has two main entry points from the outside:
- 24602 *
- 24603 * sys_call: called when a process or task does SEND, RECEIVE or SENDREC
- 24604 * interrupt: called by interrupt routines to send a message to task
- 24605 *
- 24606 * It also has several minor entry points:
- 24607 *
- 24608 * lock_ready: put a process on one of the ready queues so it can be run
- 24609 * lock_unready: remove a process from the ready queues
- 24610 * lock_sched: a process has run too long; schedule another one
- 24611 * lock_mini_send: send a message (used by interrupt signals, etc.)
- 24612 * lock_pick_proc: pick a process to run (used by system initialization)
- 24613 * unhold: repeat all held-up interrupts
- 24614 */
- 24615
- 24616 #include "kernel.h"
- 24617 #include <minix/callnr.h>
- 24618 #include <minix/com.h>
- 24619 #include "proc.h"
- 24620
- 24621 PRIVATE unsigned char switching; /* nonzero to inhibit interrupt() */
- 24622
- 24623 FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dest,
- 24624 message *m_ptr) );
- 24625 FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
- 24626 message *m_ptr) );
- 24627 FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
- 24628 FORWARD _PROTOTYPE( void sched, (void) );
- 24629 FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
- 24630 FORWARD _PROTOTYPE( void pick_proc, (void) );
- 24631
- 24632 #if (CHIP == M68000)
- 24633 FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
- 24634 struct proc *dst_p, message *dst_m) );
- .Ep 336 src/kernel/proc.c
- 24635 #endif
- 24636
- 24637 #if (CHIP == INTEL)
- 24638 #define CopyMess(s,sp,sm,dp,dm)
- 24639 cp_mess(s, (sp)->p_map[D].mem_phys, (vir_bytes)sm, (dp)->p_map[D].mem_phys, (vir_bytes)dm)
- 24640 #endif
- 24641
- 24642 #if (CHIP == M68000)
- 24643 #define CopyMess(s,sp,sm,dp,dm)
- 24644 cp_mess(s,sp,sm,dp,dm)
- 24645 #endif
- 24646
- 24647 /*===========================================================================*
- 24648 * interrupt *
- 24649 *===========================================================================*/
- 24650 PUBLIC void interrupt(task)
- 24651 int task; /* number of task to be started */
- 24652 {
- 24653 /* An interrupt has occurred. Schedule the task that handles it. */
- 24654
- 24655 register struct proc *rp; /* pointer to task's proc entry */
- 24656
- 24657 rp = proc_addr(task);
- 24658
- 24659 /* If this call would compete with other process-switching functions, put
- 24660 * it on the 'held' queue to be flushed at the next non-competing restart().
- 24661 * The competing conditions are:
- 24662 * (1) k_reenter == (typeof k_reenter) -1:
- 24663 * Call from the task level, typically from an output interrupt
- 24664 * routine. An interrupt handler might reenter interrupt(). Rare,
- 24665 * so not worth special treatment.
- 24666 * (2) k_reenter > 0:
- 24667 * Call from a nested interrupt handler. A previous interrupt handler
- 24668 * might be inside interrupt() or sys_call().
- 24669 * (3) switching != 0:
- 24670 * Some process-switching function other than interrupt() is being
- 24671 * called from the task level, typically sched() from CLOCK. An
- 24672 * interrupt handler might call interrupt and pass the k_reenter test.
- 24673 */
- 24674 if (k_reenter != 0 || switching) {
- 24675 lock();
- 24676 if (!rp->p_int_held) {
- 24677 rp->p_int_held = TRUE;
- 24678 if (held_head != NIL_PROC)
- 24679 held_tail->p_nextheld = rp;
- 24680 else
- 24681 held_head = rp;
- 24682 held_tail = rp;
- 24683 rp->p_nextheld = NIL_PROC;
- 24684 }
- 24685 unlock();
- 24686 return;
- 24687 }
- 24688
- 24689 /* If task is not waiting for an interrupt, record the blockage. */
- 24690 if ( (rp->p_flags & (RECEIVING | SENDING)) != RECEIVING ||
- 24691 !isrxhardware(rp->p_getfrom)) {
- 24692 rp->p_int_blocked = TRUE;
- 24693 return;
- 24694 }
- .Op 337 src/kernel/proc.c
- 24695
- 24696 /* Destination is waiting for an interrupt.
- 24697 * Send it a message with source HARDWARE and type HARD_INT.
- 24698 * No more information can be reliably provided since interrupt messages
- 24699 * are not queued.
- 24700 */
- 24701 rp->p_messbuf->m_source = HARDWARE;
- 24702 rp->p_messbuf->m_type = HARD_INT;
- 24703 rp->p_flags &= ~RECEIVING;
- 24704 rp->p_int_blocked = FALSE;
- 24705
- 24706 /* Make rp ready and run it unless a task is already running. This is
- 24707 * ready(rp) in-line for speed.
- 24708 */
- 24709 if (rdy_head[TASK_Q] != NIL_PROC)
- 24710 rdy_tail[TASK_Q]->p_nextready = rp;
- 24711 else
- 24712 proc_ptr = rdy_head[TASK_Q] = rp;
- 24713 rdy_tail[TASK_Q] = rp;
- 24714 rp->p_nextready = NIL_PROC;
- 24715 }
- 24717 /*===========================================================================*
- 24718 * sys_call *
- 24719 *===========================================================================*/
- 24720 PUBLIC int sys_call(function, src_dest, m_ptr)
- 24721 int function; /* SEND, RECEIVE, or BOTH */
- 24722 int src_dest; /* source to receive from or dest to send to */
- 24723 message *m_ptr; /* pointer to message */
- 24724 {
- 24725 /* The only system calls that exist in MINIX are sending and receiving
- 24726 * messages. These are done by trapping to the kernel with an INT instruction.
- 24727 * The trap is caught and sys_call() is called to send or receive a message
- 24728 * (or both). The caller is always given by proc_ptr.
- 24729 */
- 24730
- 24731 register struct proc *rp;
- 24732 int n;
- 24733
- 24734 /* Check for bad system call parameters. */
- 24735 if (!isoksrc_dest(src_dest)) return(E_BAD_SRC);
- 24736 rp = proc_ptr;
- 24737
- 24738 if (isuserp(rp) && function != BOTH) return(E_NO_PERM);
- 24739
- 24740 /* The parameters are ok. Do the call. */
- 24741 if (function & SEND) {
- 24742 /* Function = SEND or BOTH. */
- 24743 n = mini_send(rp, src_dest, m_ptr);
- 24744 if (function == SEND || n != OK)
- 24745 return(n); /* done, or SEND failed */
- 24746 }
- 24747
- 24748 /* Function = RECEIVE or BOTH.
- 24749 * We have checked user calls are BOTH, and trust 'function' otherwise.
- 24750 */
- 24751 return(mini_rec(rp, src_dest, m_ptr));
- 24752 }
- 24754 /*===========================================================================*
- .Ep 338 src/kernel/proc.c
- 24755 * mini_send *
- 24756 *===========================================================================*/
- 24757 PRIVATE int mini_send(caller_ptr, dest, m_ptr)
- 24758 register struct proc *caller_ptr; /* who is trying to send a message? */
- 24759 int dest; /* to whom is message being sent? */
- 24760 message *m_ptr; /* pointer to message buffer */
- 24761 {
- 24762 /* Send a message from 'caller_ptr' to 'dest'. If 'dest' is blocked waiting
- 24763 * for this message, copy the message to it and unblock 'dest'. If 'dest' is
- 24764 * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
- 24765 */
- 24766
- 24767 register struct proc *dest_ptr, *next_ptr;
- 24768 vir_bytes vb; /* message buffer pointer as vir_bytes */
- 24769 vir_clicks vlo, vhi; /* virtual clicks containing message to send */
- 24770
- 24771 /* User processes are only allowed to send to FS and MM. Check for this. */
- 24772 if (isuserp(caller_ptr) && !issysentn(dest)) return(E_BAD_DEST);
- 24773 dest_ptr = proc_addr(dest); /* pointer to destination's proc entry */
- 24774 if (dest_ptr->p_flags & P_SLOT_FREE) return(E_BAD_DEST); /* dead dest */
- 24775
- 24776 #if ALLOW_GAP_MESSAGES
- 24777 /* This check allows a message to be anywhere in data or stack or gap.
- 24778 * It will have to be made more elaborate later for machines which
- 24779 * don't have the gap mapped.
- 24780 */
- 24781 vb = (vir_bytes) m_ptr;
- 24782 vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
- 24783 vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
- 24784 if (vlo < caller_ptr->p_map[D].mem_vir || vlo > vhi ||
- 24785 vhi >= caller_ptr->p_map[S].mem_vir + caller_ptr->p_map[S].mem_len)
- 24786 return(EFAULT);
- 24787 #else
- 24788 /* Check for messages wrapping around top of memory or outside data seg. */
- 24789 vb = (vir_bytes) m_ptr;
- 24790 vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
- 24791 vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
- 24792 if (vhi < vlo ||
- 24793 vhi - caller_ptr->p_map[D].mem_vir >= caller_ptr->p_map[D].mem_len)
- 24794 return(EFAULT);
- 24795 #endif
- 24796
- 24797 /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
- 24798 if (dest_ptr->p_flags & SENDING) {
- 24799 next_ptr = proc_addr(dest_ptr->p_sendto);
- 24800 while (TRUE) {
- 24801 if (next_ptr == caller_ptr) return(ELOCKED);
- 24802 if (next_ptr->p_flags & SENDING)
- 24803 next_ptr = proc_addr(next_ptr->p_sendto);
- 24804 else
- 24805 break;
- 24806 }
- 24807 }
- 24808
- 24809 /* Check to see if 'dest' is blocked waiting for this message. */
- 24810 if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
- 24811 (dest_ptr->p_getfrom == ANY ||
- 24812 dest_ptr->p_getfrom == proc_number(caller_ptr))) {
- 24813 /* Destination is indeed waiting for this message. */
- 24814 CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
- .Op 339 src/kernel/proc.c
- 24815 dest_ptr->p_messbuf);
- 24816 dest_ptr->p_flags &= ~RECEIVING; /* deblock destination */
- 24817 if (dest_ptr->p_flags == 0) ready(dest_ptr);
- 24818 } else {
- 24819 /* Destination is not waiting. Block and queue caller. */
- 24820 caller_ptr->p_messbuf = m_ptr;
- 24821 if (caller_ptr->p_flags == 0) unready(caller_ptr);
- 24822 caller_ptr->p_flags |= SENDING;
- 24823 caller_ptr->p_sendto= dest;
- 24824
- 24825 /* Process is now blocked. Put in on the destination's queue. */
- 24826 if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
- 24827 dest_ptr->p_callerq = caller_ptr;
- 24828 else {
- 24829 while (next_ptr->p_sendlink != NIL_PROC)
- 24830 next_ptr = next_ptr->p_sendlink;
- 24831 next_ptr->p_sendlink = caller_ptr;
- 24832 }
- 24833 caller_ptr->p_sendlink = NIL_PROC;
- 24834 }
- 24835 return(OK);
- 24836 }
- 24838 /*===========================================================================*
- 24839 * mini_rec *
- 24840 *===========================================================================*/
- 24841 PRIVATE int mini_rec(caller_ptr, src, m_ptr)
- 24842 register struct proc *caller_ptr; /* process trying to get message */
- 24843 int src; /* which message source is wanted (or ANY) */
- 24844 message *m_ptr; /* pointer to message buffer */
- 24845 {
- 24846 /* A process or task wants to get a message. If one is already queued,
- 24847 * acquire it and deblock the sender. If no message from the desired source
- 24848 * is available, block the caller. No need to check parameters for validity.
- 24849 * Users calls are always sendrec(), and mini_send() has checked already.
- 24850 * Calls from the tasks, MM, and FS are trusted.
- 24851 */
- 24852
- 24853 register struct proc *sender_ptr;
- 24854 register struct proc *previous_ptr;
- 24855
- 24856 /* Check to see if a message from desired source is already available. */
- 24857 if (!(caller_ptr->p_flags & SENDING)) {
- 24858 /* Check caller queue. */
- 24859 for (sender_ptr = caller_ptr->p_callerq; sender_ptr != NIL_PROC;
- 24860 previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) {
- 24861 if (src == ANY || src == proc_number(sender_ptr)) {
- 24862 /* An acceptable message has been found. */
- 24863 CopyMess(proc_number(sender_ptr), sender_ptr,
- 24864 sender_ptr->p_messbuf, caller_ptr, m_ptr);
- 24865 if (sender_ptr == caller_ptr->p_callerq)
- 24866 caller_ptr->p_callerq = sender_ptr->p_sendlink;
- 24867 else
- 24868 previous_ptr->p_sendlink = sender_ptr->p_sendlink;
- 24869 if ((sender_ptr->p_flags &= ~SENDING) == 0)
- 24870 ready(sender_ptr); /* deblock sender */
- 24871 return(OK);
- 24872 }
- 24873 }
- 24874
- .Ep 340 src/kernel/proc.c
- 24875 /* Check for blocked interrupt. */
- 24876 if (caller_ptr->p_int_blocked && isrxhardware(src)) {
- 24877 m_ptr->m_source = HARDWARE;
- 24878 m_ptr->m_type = HARD_INT;
- 24879 caller_ptr->p_int_blocked = FALSE;
- 24880 return(OK);
- 24881 }
- 24882 }
- 24883
- 24884 /* No suitable message is available. Block the process trying to receive. */
- 24885 caller_ptr->p_getfrom = src;
- 24886 caller_ptr->p_messbuf = m_ptr;
- 24887 if (caller_ptr->p_flags == 0) unready(caller_ptr);
- 24888 caller_ptr->p_flags |= RECEIVING;
- 24889
- 24890 /* If MM has just blocked and there are kernel signals pending, now is the
- 24891 * time to tell MM about them, since it will be able to accept the message.
- 24892 */
- 24893 if (sig_procs > 0 && proc_number(caller_ptr) == MM_PROC_NR && src == ANY)
- 24894 inform();
- 24895 return(OK);
- 24896 }
- 24898 /*===========================================================================*
- 24899 * pick_proc *
- 24900 *===========================================================================*/
- 24901 PRIVATE void pick_proc()
- 24902 {
- 24903 /* Decide who to run now. A new process is selected by setting 'proc_ptr'.
- 24904 * When a fresh user (or idle) process is selected, record it in 'bill_ptr',
- 24905 * so the clock task can tell who to bill for system time.
- 24906 */
- 24907
- 24908 register struct proc *rp; /* process to run */
- 24909
- 24910 if ( (rp = rdy_head[TASK_Q]) != NIL_PROC) {
- 24911 proc_ptr = rp;
- 24912 return;
- 24913 }
- 24914 if ( (rp = rdy_head[SERVER_Q]) != NIL_PROC) {
- 24915 proc_ptr = rp;
- 24916 return;
- 24917 }
- 24918 if ( (rp = rdy_head[USER_Q]) != NIL_PROC) {
- 24919 proc_ptr = rp;
- 24920 bill_ptr = rp;
- 24921 return;
- 24922 }
- 24923 /* No one is ready. Run the idle task. The idle task might be made an
- 24924 * always-ready user task to avoid this special case.
- 24925 */
- 24926 bill_ptr = proc_ptr = proc_addr(IDLE);
- 24927 }
- 24929 /*===========================================================================*
- 24930 * ready *
- 24931 *===========================================================================*/
- 24932 PRIVATE void ready(rp)
- 24933 register struct proc *rp; /* this process is now runnable */
- 24934 {
- .Op 341 src/kernel/proc.c
- 24935 /* Add 'rp' to the end of one of the queues of runnable processes. Three
- 24936 * queues are maintained:
- 24937 * TASK_Q - (highest priority) for runnable tasks
- 24938 * SERVER_Q - (middle priority) for MM and FS only
- 24939 * USER_Q - (lowest priority) for user processes
- 24940 */
- 24941
- 24942 if (istaskp(rp)) {
- 24943 if (rdy_head[TASK_Q] != NIL_PROC)
- 24944 /* Add to tail of nonempty queue. */
- 24945 rdy_tail[TASK_Q]->p_nextready = rp;
- 24946 else {
- 24947 proc_ptr = /* run fresh task next */
- 24948 rdy_head[TASK_Q] = rp; /* add to empty queue */
- 24949 }
- 24950 rdy_tail[TASK_Q] = rp;
- 24951 rp->p_nextready = NIL_PROC; /* new entry has no successor */
- 24952 return;
- 24953 }
- 24954 if (!isuserp(rp)) { /* others are similar */
- 24955 if (rdy_head[SERVER_Q] != NIL_PROC)
- 24956 rdy_tail[SERVER_Q]->p_nextready = rp;
- 24957 else
- 24958 rdy_head[SERVER_Q] = rp;
- 24959 rdy_tail[SERVER_Q] = rp;
- 24960 rp->p_nextready = NIL_PROC;
- 24961 return;
- 24962 }
- 24963 #if (SHADOWING == 1)
- 24964 if (isshadowp(rp)) { /* others are similar */
- 24965 if (rdy_head[SHADOW_Q] != NIL_PROC)
- 24966 rdy_tail[SHADOW_Q]->p_nextready = rp;
- 24967 else
- 24968 rdy_head[SHADOW_Q] = rp;
- 24969 rdy_tail[SHADOW_Q] = rp;
- 24970 rp->p_nextready = NIL_PROC;
- 24971 return;
- 24972 }
- 24973 #endif
- 24974 if (rdy_head[USER_Q] == NIL_PROC)
- 24975 rdy_tail[USER_Q] = rp;
- 24976 rp->p_nextready = rdy_head[USER_Q];
- 24977 rdy_head[USER_Q] = rp;
- 24978 /*
- 24979 if (rdy_head[USER_Q] != NIL_PROC)
- 24980 rdy_tail[USER_Q]->p_nextready = rp;
- 24981 else
- 24982 rdy_head[USER_Q] = rp;
- 24983 rdy_tail[USER_Q] = rp;
- 24984 rp->p_nextready = NIL_PROC;
- 24985 */
- 24986 }
- 24988 /*===========================================================================*
- 24989 * unready *
- 24990 *===========================================================================*/
- 24991 PRIVATE void unready(rp)
- 24992 register struct proc *rp; /* this process is no longer runnable */
- 24993 {
- 24994 /* A process has blocked. */
- .Ep 342 src/kernel/proc.c
- 24995
- 24996 register struct proc *xp;
- 24997 register struct proc **qtail; /* TASK_Q, SERVER_Q, or USER_Q rdy_tail */
- 24998
- 24999 if (istaskp(rp)) {
- 25000 /* task stack still ok? */
- 25001 if (*rp->p_stguard != STACK_GUARD)
- 25002 panic("stack overrun by task", proc_number(rp));
- 25003
- 25004 if ( (xp = rdy_head[TASK_Q]) == NIL_PROC) return;
- 25005 if (xp == rp) {
- 25006 /* Remove head of queue */
- 25007 rdy_head[TASK_Q] = xp->p_nextready;
- 25008 if (rp == proc_ptr) pick_proc();
- 25009 return;
- 25010 }
- 25011 qtail = &rdy_tail[TASK_Q];
- 25012 }
- 25013 else if (!isuserp(rp)) {
- 25014 if ( (xp = rdy_head[SERVER_Q]) == NIL_PROC) return;
- 25015 if (xp == rp) {
- 25016 rdy_head[SERVER_Q] = xp->p_nextready;
- 25017 #if (CHIP == M68000)
- 25018 if (rp == proc_ptr)
- 25019 #endif
- 25020 pick_proc();
- 25021 return;
- 25022 }
- 25023 qtail = &rdy_tail[SERVER_Q];
- 25024 } else
- 25025 #if (SHADOWING == 1)
- 25026 if (isshadowp(rp)) {
- 25027 if ( (xp = rdy_head[SHADOW_Q]) == NIL_PROC) return;
- 25028 if (xp == rp) {
- 25029 rdy_head[SHADOW_Q] = xp->p_nextready;
- 25030 if (rp == proc_ptr)
- 25031 pick_proc();
- 25032 return;
- 25033 }
- 25034 qtail = &rdy_tail[SHADOW_Q];
- 25035 } else
- 25036 #endif
- 25037 {
- 25038 if ( (xp = rdy_head[USER_Q]) == NIL_PROC) return;
- 25039 if (xp == rp) {
- 25040 rdy_head[USER_Q] = xp->p_nextready;
- 25041 #if (CHIP == M68000)
- 25042 if (rp == proc_ptr)
- 25043 #endif
- 25044 pick_proc();
- 25045 return;
- 25046 }
- 25047 qtail = &rdy_tail[USER_Q];
- 25048 }
- 25049
- 25050 /* Search body of queue. A process can be made unready even if it is
- 25051 * not running by being sent a signal that kills it.
- 25052 */
- 25053 while (xp->p_nextready != rp)
- 25054 if ( (xp = xp->p_nextready) == NIL_PROC) return;
- .Op 343 src/kernel/proc.c
- 25055 xp->p_nextready = xp->p_nextready->p_nextready;
- 25056 if (*qtail == rp) *qtail = xp;
- 25057 }
- 25059 /*===========================================================================*
- 25060 * sched *
- 25061 *===========================================================================*/
- 25062 PRIVATE void sched()
- 25063 {
- 25064 /* The current process has run too long. If another low priority (user)
- 25065 * process is runnable, put the current process on the end of the user queue,
- 25066 * possibly promoting another user to head of the queue.
- 25067 */
- 25068
- 25069 if (rdy_head[USER_Q] == NIL_PROC) return;
- 25070
- 25071 /* One or more user processes queued. */
- 25072 rdy_tail[USER_Q]->p_nextready = rdy_head[USER_Q];
- 25073 rdy_tail[USER_Q] = rdy_head[USER_Q];
- 25074 rdy_head[USER_Q] = rdy_head[USER_Q]->p_nextready;
- 25075 rdy_tail[USER_Q]->p_nextready = NIL_PROC;
- 25076 pick_proc();
- 25077 }
- 25079 /*==========================================================================*
- 25080 * lock_mini_send *
- 25081 *==========================================================================*/
- 25082 PUBLIC int lock_mini_send(caller_ptr, dest, m_ptr)
- 25083 struct proc *caller_ptr; /* who is trying to send a message? */
- 25084 int dest; /* to whom is message being sent? */
- 25085 message *m_ptr; /* pointer to message buffer */
- 25086 {
- 25087 /* Safe gateway to mini_send() for tasks. */
- 25088
- 25089 int result;
- 25090
- 25091 switching = TRUE;
- 25092 result = mini_send(caller_ptr, dest, m_ptr);
- 25093 switching = FALSE;
- 25094 return(result);
- 25095 }
- 25097 /*==========================================================================*
- 25098 * lock_pick_proc *
- 25099 *==========================================================================*/
- 25100 PUBLIC void lock_pick_proc()
- 25101 {
- 25102 /* Safe gateway to pick_proc() for tasks. */
- 25103
- 25104 switching = TRUE;
- 25105 pick_proc();
- 25106 switching = FALSE;
- 25107 }