Image Map Image Map
Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Read Back on 8253 PIT Chip

  1. #1

    Default Read Back on 8253 PIT Chip

    I'm playing with the PIT and am reading that the Read Back command (e.g. "get status") is only supported on the 8254. This gave me a few questions that I haven't found an answer to:

    1. What range of computers would you say this affects? I know the PC and XT had the 8253 but it seems the IBM PS/2 had something like it that isn't an 8254.

    2. What happens when you try to use the read back command on the 8253?

    3. Based on #2; is this a way to determine whether a computer has 8253 or 8254 or ... ?

    4. Are there any methods to detect (in software) whether the computer has an 8253 or 8254 chip?
    Last edited by neilobremski; December 9th, 2016 at 03:09 PM. Reason: Removed mistypes

  2. #2
    Join Date
    Jan 2007
    Location
    Pacific Northwest, USA
    Posts
    22,805
    Blog Entries
    20

    Default

    1. Just the early PC and XT compatibles. By the time the 5170 was introduced the 8254 (HMOS) was mainstream.

    2. Technically, it's undefined, but probably results in no operation.

    3 and 4. I suspect that a READ STATUS command and checking for the mode being what was used to initialize the counter might serve to make the distinction.

  3. #3

    Default

    Quote Originally Posted by neilobremski View Post
    I'm playing with the PIT and am reading that the Read Back command (e.g. "get status") is only supported on the 8254.
    Stepping back a bit here, what are you trying to achieve? Do you really need to read back the status, or just the current counter value (for timing purposes)? If you just need to read the count, that works fine on an 8253 - write a mode control byte with 0 in bits 4 and 5 (latch count command) and then read two bytes from the counter port. If you really do want to read back the command status I'd be interested to know what you're planning to do with it.

  4. #4

    Default

    Quote Originally Posted by reenigne View Post
    Stepping back a bit here, what are you trying to achieve? Do you really need to read back the status, or just the current counter value (for timing purposes)?
    Well, one of my first thoughts after learning how to configure the PIT was: how do I restore this to the configuration it was in when my program began? This led me to the blossoming of questions that started this thread. One thing I realized after Chuck's response was that even if I can set the mode based on the output of the Read Back Command, the divisor is not included in that status.

    Most times the divisor is at 0 (maximum 16-bit unsigned + 1 = 65,536) when the program starts to give the 18.2 per second default. Then in the OSDev Wiki I read: "The PIT has only 16 bits that are used as frequency divider, which can represent the values from 0 to 65535. Since the frequency can't be divided by 0 in a sane way, many implementations use 0 to represent the value 65536." Are there implementations where 0 is NOT 65,536 (e.g. and is simply ignored since a zero divisor is not possible)?

    And to add yet another question: is it possible to detect the current divisor accurately of timer 0? If I installed something on INT 08H then I could "listen" for a range of counter values and make a guess, but is really dirty. Any other ideas?

  5. #5

    Default

    Quote Originally Posted by neilobremski View Post
    Well, one of my first thoughts after learning how to configure the PIT was: how do I restore this to the configuration it was in when my program began?
    I don't think this is something that DOS programs normally do. Normally if a program reprograms PIT channel 0, it'll restore it by setting it to mode 3, binary, divisor 0. Not always, though - I seem to remember a mouse driver that increased it to approximately triple its normal rate. I had a music player program that used IRQ0 for timing, and the tempo was much faster when the mouse driver was loaded!

    Channel 2 was even worse - basically nothing ever restores it even to the usual mode (everything just turns off the speaker and leaves it at the last value used). The title screen music of the game "Bruce Lee" (in at least one version) doesn't reprogram the channel 2 mode, so the music sounds very different depending on which mode PIT channel 2 was left in! Basically this is just one of those weird quirks about using DOS - programs just don't always leave the hardware in same state they found it in.

    Quote Originally Posted by neilobremski View Post
    Are there implementations where 0 is NOT 65,536 (e.g. and is simply ignored since a zero divisor is not possible)?
    I don't believe so. If there were, they would be broken by any programs which leave PIT channel 0 with divisor 0 (which is basically every program that uses the PIT).

    Quote Originally Posted by neilobremski View Post
    And to add yet another question: is it possible to detect the current divisor accurately of timer 0? If I installed something on INT 08H then I could "listen" for a range of counter values and make a guess, but is really dirty. Any other ideas?
    Immediately after an INT 8 has occurred, the counter value should be very close to the maximum value. The amount by which it is different depends on several factors, all of which can be corrected for if you really care:
    1) The time the CPU takes to finish executing the currently-executing instruction (if it's not in a HLT state).
    2) The possibility that interrupts are disabled at the point where the PIT counter reaches 0.
    3) The time the CPU takes to actually process the interrupt at get to the point in the code at which the counter is read (should be the same for a known and unknown counter value).
    4) The possibility that one or several DRAM refresh DMAs occur in this critical period.
    5) The fact that the counter counts down twice as fast in mode 3 as in mode 2.

  6. #6

    Default

    Thanks reenigne, I really appreciate the insights.

    A lot of DOS programs certainly weren't very courteous to subsequent ones. And of course the boot time was so fast (even with the RAM check) that a mere CTRL+ALT+DEL solved most problems! I like understanding how this could be done even if no one ever uses the program I write that does it. It matters enough to me to find the answer despite the question's insignificance, otherwise I relate to Columbo's "Ah, yeah, but there's just one more thing that bothers me..."

    I like the idea about checking the count immediately after the interrupt is fired. What I could add to that is that if it is near to the upper limits, within a small threshold, then the program would decide that the maximum (18.2 FPS) was probably in use. Anything else and it could try to restore it to that divisor. I will have to remember about mode 3's counter speed.

    Uh, sir, just one more thing ...

    The default timer 0 drives the computer's tick count which in turn is used to keep the date and time updated; am I remembering that correctly? It occurred to me that all of the references I've read so far mention this and that it is possible but there's very few examples doing it. It seems to fall into the "restart fixes everything" bucket. One could either update the tick count manually in an INT 8 handler (by trying to call the old handler at 18.2 per second) or attempt to correct the tick count and clock discrepancy at the end of the program. Are there any articles or examples of either of these working successfully?

  7. #7
    Join Date
    Jan 2007
    Location
    Pacific Northwest, USA
    Posts
    22,805
    Blog Entries
    20

    Default

    There were a few programs, TSRs mostly where the 18.2 msec resolution wasn't fine enough, so the approach was to reduce the max count/interrupt frequency and post-scale it with software. That is, one could get a resolution in the millisecond range by reducing the max count by a factor of 32 and hooking INT 8 to keep an internal, private counter that bypassed the usual INT 8 tasks 31 out of 32 times. (i.e. post-scale the interrupt).

    Since few programs use counter 0 directly, but rather refer to the "tick count", this works perfectly. Of course, there's a small penalty in performance.

  8. #8

    Default

    Quote Originally Posted by neilobremski View Post
    The default timer 0 drives the computer's tick count which in turn is used to keep the date and time updated; am I remembering that correctly?
    Yes, that's correct.

    Quote Originally Posted by neilobremski View Post
    It occurred to me that all of the references I've read so far mention this and that it is possible but there's very few examples doing it. It seems to fall into the "restart fixes everything" bucket. One could either update the tick count manually in an INT 8 handler (by trying to call the old handler at 18.2 per second)
    I think that most programs that reprogram the PIT do actually do this, if they're making any effort at all to play nice with other software on the machine. People do tend to complain if playing a game causes the clock to be wrong! It's pretty easy to do - just maintain a 16-bit counter and add the divisor value to it on each interrupt. When it overflows ("jc" in assembler, "count+divisor <= count" in C) then jump to the saved previous interrupt vector, otherwise EOI and IRET. Of course, this has the wrong effect if the previous vector is expecting to be called more often than 18.2 times per second (i.e. if you have a TSR loaded that increases the PIT rate but maintains the clock correctly) but it works for 99% of cases.

    Quote Originally Posted by neilobremski View Post
    or attempt to correct the tick count and clock discrepancy at the end of the program. Are there any articles or examples of either of these working successfully?
    I'm not aware of any popular software that does this, but I have written code to do it for some of my own programs. It's a bit more fiddly but does mean that you can take over the machine completely for the duration of your program without upsetting the clock. As before, maintain a counter and add the divisor to it each interrupt. Use a 32-bit counter if the program will always take less than an hour to run, or a 48-bit counter if it might run for longer. At the end of the program, the top 16/32 bits of this counter will be the number of 18.2Hz ticks that have elapsed. There are a couple of different ways that you can go from here. One is just to repeatedly call the previous vector for each "should have elapsed" tick. This is easy and plays nicely with any loaded TSRs but could mean a significant delay on exit if your program runs for a long time on a slow machine. The other way is more complicated - look at how the BIOS implementation of the interrupt 8 vector updates the clock and update it yourself, doing some maths to directly figure out the new time rather than updating it one tick at a time. That doesn't help if you've got a TSR loaded which keeps track of the time separately from the BIOS, but again it takes care of 99% of cases.

    Apart from keeping track of the time of day, another function of the BIOS interrupt 8 vector is to turn off the floppy drive motors if no disk accesses have been done for a few seconds. If you're planning on not calling the BIOS interrupt 8 vector for a while, you should probably make sure the floppy motors are switched off first to save wear on motors, heads and floppy media (as well as reduce noise). The original version of Digger did this by directly accessing the floppy drive port. A more portable way might be to call the BIOS interrupt 8 handler a few seconds' worth of times and adjust your tick counter appropriately (or simply wait long enough to be sure it's off).

  9. #9
    Join Date
    Aug 2006
    Location
    Chicagoland, Illinois, USA
    Posts
    3,954
    Blog Entries
    1

    Default

    Quote Originally Posted by reenigne View Post
    I'm not aware of any popular software that does this
    Access did this for their RealSound games (Mean Streets, Crime Wave, Martian Memorandum, Echelon, World Class Leader Board, Links, possibly others). The PWM playback code didn't call the old int08 for obvious reasons, but kept track of how much the clock got behind with every digitized sound played, and they adjusted the DOS clock accordingly on program exit. I also recall another game (can't remember the name) that restored the DOS clock on exit by reading the time directly out of the CMOS RTC (ports 70h/71h) and setting the DOS time with the data.
    Offering a bounty for:
    - Music Construction Set, IBM Music Feature edition (has red sticker on front stating IBM Music Feature)

  10. #10

    Default

    I recently came across this quote on MSDN in the remarks for the Beep() function:

    A long time ago, all PC computers shared a common 8254 programable interval timer chip for the generation of primitive sounds. The Beep function was written specifically to emit a beep on that piece of hardware.
    ...
    Since then, sound cards have become standard equipment on almost all PC computers. As sound cards became more common, manufacturers began to remove the old timer chip from computers. The chips were also excluded from the design of server computers. The result is that Beep did not work on all computers without the chip. This was okay because most developers had moved on to calling the MessageBeep function that uses whatever is the default sound device instead of the 8254 chip.
    Has the ol' 8253/8254 been removed in recent times? I had the notion that it was still present beneath or beside all the newer hardware.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •