OSDN Git Service

first commit
[winexe-harib/winexe-harib.git] / haribote / ata / ATAIOISA.C
1 //********************************************************************
2 // ATA LOW LEVEL I/O DRIVER -- ATAIOISA.C
3 //
4 // by Hale Landis (www.ata-atapi.com)
5 //
6 // There is no copyright and there are no restrictions on the use
7 // of this ATA Low Level I/O Driver code.  It is distributed to
8 // help other programmers understand how the ATA device interface
9 // works and it is distributed without any warranty.  Use this
10 // code at your own risk.
11 //
12 // This code is based on the ATA-2, ATA-3 and ATA-4 standards and
13 // on interviews with various ATA controller and drive designers.
14 //
15 // This code has been run on many ATA (IDE) drives and
16 // MFM/RLL controllers.  This code may be a little
17 // more picky about the status it sees at various times.  A real
18 // BIOS probably would not check the status as carefully.
19 //
20 // Compile with one of the Borland C or C++ compilers.
21 //
22 // This C source contains the ISA bus READ/WRITE DMA command
23 // processing for ATA and ATAPI.
24 //********************************************************************
25
26 #include <dos.h>
27
28 #include "ataio.h"
29
30 #define DEBUG_ISA 0x00  // not zero for debug
31                         // 0x01 trace the DMA channel mode
32
33 //***********************************************************
34 //
35 // Some notes about ISA bus DMA...
36 //
37 // ISA bus DMA uses an DMA controller built into an ISA bus
38 // motherboard.  This DMA controller has six DMA channels:  1, 2, 3,
39 // 5, 6 and 7. Channels 0 and 4 are reserved for other uses.
40 // Channels 1, 2 and 3 are 8-bit and channels 5, 6 and 7 are 16-bit.
41 // Since ATA DMA is always 16-bit only channels 5, 6 or 7 can be
42 // used here.
43 //
44 // An ISA bus DMA controller is unable to transfer data across a
45 // 128K boundary in physical memory.  This code is able to cross one
46 // 128K DMA boundary.  It could be enhanced to cross any number of
47 // boundaries but since a tradional ATA read/write command can not
48 // transfer more than 256 sectors or 128K bytes, there is little
49 // need for this code to handle more than one boundary crossing.
50 //
51 // Note that the ISA 16-bit DMA channels are restricted to
52 // transfering data on word boundaries and transfers of an even
53 // number of bytes.  This is because the host memory address and the
54 // transfer length byte count are both divided by 2. These word
55 // addresses and word counts are used by the DMA controller.
56 //
57 //***********************************************************
58
59 //***********************************************************
60 //
61 // isa bus dma channel configuration stuff,
62 // see dma_isa_config().
63 //
64 //***********************************************************
65
66 static int dmaChan = 0;          // dma channel number (5, 6 or 7)
67
68 static int dmaPageReg;           // page reg addr
69 static int dmaAddrReg;           // addr reg addr
70 static int dmaCntrReg;           // cntr reg addr
71
72 static int dmaChanSel;           // channel selection bits...
73                                  // also see modeByte below
74
75 #define DMA_SEL5 0x01            // values used in dmaChanSel
76 #define DMA_SEL6 0x02
77 #define DMA_SEL7 0x03
78
79 static int dmaTCbit;             // terminal count bit status
80
81 #define DMA_TC5 0x02             // values used in dmaTCbit
82 #define DMA_TC6 0x04
83 #define DMA_TC7 0x08
84
85 //***********************************************************
86 //
87 // isa bus dma channel configuration and control macros
88 //
89 //***********************************************************
90
91 #define DMA_MASK_ENABLE  0x00    // bits for enable/disable
92 #define DMA_MASK_DISABLE 0x04
93
94 #define enableChan()  outportb( 0xd4, DMA_MASK_ENABLE  | dmaChanSel )
95 #define disableChan() outportb( 0xd4, DMA_MASK_DISABLE | dmaChanSel )
96
97 #define clearFF() outportb( 0xd8, 0 )  // macro to reset flip-flop
98                                        // so we access the low byte
99                                        // of the address and word
100                                        // count registers
101
102 //***********************************************************
103 //
104 // dma channel programming stuff
105 //
106 //***********************************************************
107
108 static int doTwo;             // transfer crosses a physical boundary if != 0
109
110 static unsigned int page1;    // upper part of physical memory address
111                               // for 1st (or only) transfer
112 static unsigned int page2;    // upper part of physical memory address
113                               // for 2nd transfer
114
115 static unsigned long addr1;   // physical address for 1st (or only) transfer
116 static unsigned long addr2;   // physical address for 2nd transfer
117
118 static unsigned long count1;  // byte/word count for 1st (or only) transfer
119 static unsigned long count2;  // byte/word count for 2nd transfer
120
121 static int modeByte;          // mode byte for the dma channel...
122                               // also see dmaChanSel above
123
124 #define DMA_MODE_DEMAND 0x00  // modeByte bits for various dma modes
125 #define DMA_MODE_BLOCK  0x80
126 #define DMA_MODE_SINGLE 0x40
127
128 #define DMA_MODE_MEMR 0x08    // modeByte memory read or write
129 #define DMA_MODE_MEMW 0x04
130
131 //***********************************************************
132 //
133 // set_up_xfer() -- set up for 1 or 2 dma transfers -- either
134 //                  1 or 2 transfers are required per ata
135 //                  or atapi command.
136 //
137 //***********************************************************
138
139 static void set_up_xfer( int dir, long bc, unsigned int seg, unsigned int off );
140
141 static void set_up_xfer( int dir, long bc, unsigned int seg, unsigned int off )
142
143 {
144    unsigned long count;    // total byte/word count
145    unsigned long addr;     // absolute memory address
146
147    // determine number of bytes to be transferred
148
149    count = bc;
150
151    // convert transfer address from seg:off to a 20-bit absolute memory address
152
153    addr = (unsigned long) seg;
154    addr = addr << 4;
155    addr = addr + (unsigned long) off;
156
157    // determine first transfer address,
158    // determine first and second transfer counts.
159    // The absolute address bits a19 - a0 are used as follows:
160    // bits 7-4 of the page register are set to 0.
161    // a19 - a17 are placed into the page register bits 3-1.
162    // bit 0 of the page register is set to 0.
163    // a16-a1 are placed into the address register bits 15-0.
164    // a0 is discarded.
165    // assume that only one transfer is needed and determine the
166    // page, addr1, count1 and count2 values.
167    // the transfer count is converted from byte to word counts.
168
169    page1 = (int) ( ( addr & 0x000e0000L ) >> 16 );
170    page2 = page1 + 2;
171    addr1 = ( addr & 0x0001fffeL ) >> 1;
172    addr2 = 0;
173    count1 = count >> 1;
174    count2 = 0;
175
176    // if a dma boundary will be crossed, determine the
177    // first and second transfer counts.  again the
178    // transfer counts must be converted from byte to word counts.
179
180    doTwo = 0;
181    if ( ( ( addr + count - 1L ) & 0x000e0000L ) != ( addr & 0x000e0000L ) )
182    {
183       doTwo = 1;
184
185       // determine first and second transfer counts
186
187       count1 = ( ( addr & 0x000e0000L ) + 0x00020000L ) - addr;
188       count2 = count - count1;
189
190       // convert counts to word values
191
192       count1 = count1 >> 1;
193       count2 = count2 >> 1;
194    }
195
196    // get dma channel mode
197
198    modeByte = DMA_MODE_DEMAND;      // change this line for single word dma
199    modeByte = modeByte | ( dir ? DMA_MODE_MEMR : DMA_MODE_MEMW );
200    modeByte = modeByte | dmaChanSel;
201 }
202
203 //***********************************************************
204 //
205 // prog_dma_chan() -- config the dma channel we will use --
206 //                    we call this function to set each
207 //                    part of a dma transfer.
208 //
209 //***********************************************************
210
211 static void prog_dma_chan( unsigned int page, unsigned long addr,
212                            unsigned long count, int mode );
213
214 static void prog_dma_chan( unsigned int page, unsigned long addr,
215                            unsigned long count, int mode )
216
217 {
218
219    // disable interrupts
220
221    disable();
222
223    // disable the dma channel
224
225    trc_llt( 0, 0, TRC_LLT_DMA3 );
226    disableChan();
227
228    // reset channel status (required by some systems)
229
230    inportb( 0xd0 );
231
232    // set dma channel transfer address
233
234    clearFF();
235    outportb( dmaAddrReg, (int) ( addr & 0x000000ffL ) );
236    addr = addr >> 8;
237    outportb( dmaAddrReg, (int) ( addr & 0x000000ffL ) );
238
239    // set dma channel page
240
241    outportb( dmaPageReg, page );
242
243    // set dma channel word count
244
245    count -- ;
246    clearFF();
247    outportb( dmaCntrReg, (int) ( count & 0x000000ffL ) );
248    count = count >> 8;
249    outportb( dmaCntrReg, (int) ( count & 0x000000ffL ) );
250
251    // set dma channel mode
252
253    outportb( 0xd6, mode );
254
255    #if DEBUG_ISA & 0x01
256       trc_llt( 0, mode, TRC_LLT_DEBUG );  // for debugging
257    #endif
258
259    // enable the dma channel
260
261    trc_llt( 0, 0, TRC_LLT_DMA1 );
262    enableChan();
263
264    // enable interrupts
265
266    enable();
267 }
268
269 //***********************************************************
270 //
271 // chk_cmd_done() -- check for command completion
272 //
273 //***********************************************************
274
275 static int chk_cmd_done( void );
276
277 static int chk_cmd_done( void )
278
279 {
280    int status;
281
282    // check for interrupt or poll status
283
284    if ( int_use_intr_flag )
285    {
286       if ( int_intr_flag )                // interrupt?
287       {
288          trc_llt( 0, 0, TRC_LLT_INTRQ );
289          status = int_ata_status;         // get status
290          trc_llt( CB_STAT, status, TRC_LLT_INB );
291          return 1;                        // cmd done
292       }
293    }
294    else
295    {
296       status = pio_inbyte( CB_ASTAT );    // poll for not busy & DRQ/errors
297       if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == 0 )
298          return 1;                        // cmd done
299       if ( ( status & ( CB_STAT_BSY | CB_STAT_DF ) ) == CB_STAT_DF )
300          return 1;                        // cmd done
301       if ( ( status & ( CB_STAT_BSY | CB_STAT_ERR ) ) == CB_STAT_ERR )
302          return 1;                        // cmd done
303    }
304    return 0;                              // not done yet
305 }
306
307 //***********************************************************
308 //
309 // dma_isa_config() - configure/setup for Read/Write DMA
310 //
311 // The caller must call this function before attempting
312 // to use any ATA or ATAPI commands in ISA DMA mode.
313 //
314 //***********************************************************
315
316 int dma_isa_config( int chan )
317
318 {
319
320    // channel must be 0 (disable) or 5, 6 or 7.
321
322    switch ( chan )
323    {
324       case 0:
325          dmaChan = 0;            // disable ISA DMA
326          return 0;
327       case 5:                    // set up channel 5
328          dmaChan = 5;
329          dmaPageReg = 0x8b;
330          dmaAddrReg = 0xc4;
331          dmaCntrReg = 0xc6;
332          dmaChanSel = DMA_SEL5;
333          dmaTCbit   = DMA_TC5;
334          break;
335       case 6:                    // set up channel 6
336          dmaChan = 6;
337          dmaPageReg = 0x89;
338          dmaAddrReg = 0xc8;
339          dmaCntrReg = 0xca;
340          dmaChanSel = DMA_SEL6;
341          dmaTCbit   = DMA_TC6;
342          break;
343       case 7:                    // set up channel 7
344          dmaChan = 7;
345          dmaPageReg = 0x8a;
346          dmaAddrReg = 0xcc;
347          dmaCntrReg = 0xce;
348          dmaChanSel = DMA_SEL7;
349          dmaTCbit   = DMA_TC7;
350          break;
351       default:                   // not channel 5, 6 or 7
352          dmaChan = 0;               // disable ISA DMA
353          return 1;                  // return error
354    }
355
356    return 0;
357 }
358
359 //***********************************************************
360 //
361 // exec_isa_ata_cmd() - DMA in ISA Multiword for ATA R/W DMA
362 //
363 //***********************************************************
364
365 static int exec_isa_ata_cmd( int dev,
366                              unsigned int seg, unsigned int off,
367                              long numSect );
368
369 static int exec_isa_ata_cmd( int dev,
370                              unsigned int seg, unsigned int off,
371                              long numSect )
372
373 {
374    unsigned char status;
375    unsigned long lw1, lw2;
376
377    // mark start of a R/W DMA command in low level trace
378
379    trc_llt( 0, 0, TRC_LLT_S_RWD );
380
381    // Quit now if no dma channel set up.
382
383    if ( ! dmaChan )
384    {
385       reg_cmd_info.ec = 70;
386       trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
387       sub_trace_command();
388       trc_llt( 0, 0, TRC_LLT_E_RWD );
389       return 1;
390    }
391
392    // Quit now if 1) I/O buffer overrun possible
393    // or 2) DMA can't handle the transfer size.
394
395    if ( ( numSect > 256L ) || ( ( numSect * 512L ) > reg_buffer_size ) )
396    {
397       reg_cmd_info.ec = 61;
398       trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
399       sub_trace_command();
400       trc_llt( 0, 0, TRC_LLT_E_PID );
401       return 1;
402    }
403
404    // set up the dma transfer
405
406    set_up_xfer( ( reg_cmd_info.cmd == CMD_WRITE_DMA )
407                 ||
408                 ( reg_cmd_info.cmd == CMD_WRITE_DMA_EXT ),
409                 numSect * 512L, seg, off );
410
411    // Set command time out.
412
413    tmr_set_timeout();
414
415    // Select the drive - call the sub_select function.
416    // Quit now if this fails.
417
418    if ( sub_select( dev ) )
419    {
420       sub_trace_command();
421       trc_llt( 0, 0, TRC_LLT_E_RWD );
422       return 1;
423    }
424
425    // Set up all the registers except the command register.
426
427    sub_setup_command();
428
429    // For interrupt mode, install interrupt handler.
430
431    int_save_int_vect();
432
433    // program the dma channel for the first or only transfer.
434
435    prog_dma_chan( page1, addr1, count1, modeByte );
436
437    // Start the command by setting the Command register.  The drive
438    // should immediately set BUSY status.
439
440    pio_outbyte( CB_CMD, reg_cmd_info.cmd );
441
442    // Waste some time by reading the alternate status a few times.
443    // This gives the drive time to set BUSY in the status register on
444    // really fast systems.  If we don't do this, a slow drive on a fast
445    // system may not set BUSY fast enough and we would think it had
446    // completed the command when it really had not even started the
447    // command yet.
448
449    ATA_DELAY();
450
451    // Data transfer...
452    // If this transfer requires two dma transfers,
453    // wait for the first transfer to complete and
454    // then program the dma channel for the second transfer.
455
456    if ( ( reg_cmd_info.ec == 0 ) && doTwo )
457    {
458       // Data transfer...
459       // wait for dma chan to transfer first part by monitoring
460       // the dma channel's terminal count status bit
461       // -or-
462       // watch for command completion due to an error
463       // -or-
464       // time out if this takes too long.
465
466       trc_llt( 0, 0, TRC_LLT_DMA2 );
467       while ( 1 )
468       {
469          if ( inportb( 0xd0 ) & dmaTCbit )   // terminal count yet ?
470             break;                           // yes - ok!
471          if ( chk_cmd_done() )               // cmd done ?
472          {
473             reg_cmd_info.ec = 71;
474             trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
475             break;
476          }
477          if ( tmr_chk_timeout() )            // time out yet ?
478          {
479             trc_llt( 0, 0, TRC_LLT_TOUT );
480             reg_cmd_info.to = 1;
481             reg_cmd_info.ec = 72;
482             trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
483             break;
484          }
485       }
486
487       // if no error, set up 2nd transfer
488
489       if ( reg_cmd_info.ec == 0 )
490       {
491          // update bytes transferred count
492          reg_cmd_info.totalBytesXfer += count1 << 1;
493
494          // program dma channel to transfer the second part
495          prog_dma_chan( page2, addr2, count2, modeByte );
496          count1 = count2;
497       }
498    }
499
500    // End of command...
501    // if no error,
502    // wait for drive to signal command completion
503    // -or-
504    // time out if this takes to long.
505
506    if ( reg_cmd_info.ec == 0 )
507    {
508       if ( int_use_intr_flag )
509          trc_llt( 0, 0, TRC_LLT_WINT );
510       else
511          trc_llt( 0, 0, TRC_LLT_PNBSY );
512       while ( 1 )
513       {
514          if ( chk_cmd_done() )               // cmd done ?
515             break;                           // yes
516          if ( tmr_chk_timeout() )            // time out yet ?
517          {
518             trc_llt( 0, 0, TRC_LLT_TOUT );   // yes
519             reg_cmd_info.to = 1;
520             reg_cmd_info.ec = 73;
521             trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
522             break;
523          }
524       }
525    }
526
527    // End of command...
528    // disable the dma channel
529
530    trc_llt( 0, 0, TRC_LLT_DMA3 );
531    disableChan();
532
533    // End of command...
534    // If polling or error read the Status register,
535    // otherwise use the Status register value that was read
536    // by the interrupt handler.
537
538    if ( ( ! int_use_intr_flag ) || ( reg_cmd_info.ec ) )
539       status = pio_inbyte( CB_STAT );
540    else
541       status = int_ata_status;
542
543    // Final status check...
544    // if no error, check final status...
545    // Error if BUSY, DEVICE FAULT, DRQ or ERROR status now.
546
547    if ( reg_cmd_info.ec == 0 )
548    {
549       if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_DRQ | CB_STAT_ERR ) )
550       {
551          reg_cmd_info.ec = 74;
552          trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
553       }
554    }
555
556    // Final status check...
557    // if no error, check dma channel terminal count flag
558
559    if ( ( reg_cmd_info.ec == 0 )
560         &&
561         ( ( inportb( 0xd0 ) & dmaTCbit ) == 0 )
562       )
563    {
564       reg_cmd_info.ec = 71;
565       trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
566    }
567
568    // Final status check...
569    // update total bytes transferred
570
571    if ( reg_cmd_info.ec == 0 )
572       reg_cmd_info.totalBytesXfer += count1 << 1;
573    else
574    {
575       clearFF();
576       lw1 = inportb( dmaCntrReg );
577       lw2 = inportb( dmaCntrReg );
578       lw1 = ( ( lw2 << 8 ) | lw1 ) + 1;
579       lw1 = lw1 & 0x0000ffffL;
580       reg_cmd_info.totalBytesXfer += ( count1 - lw1 ) << 1;
581    }
582
583    // Done...
584    // Read the output registers and trace the command.
585
586    sub_trace_command();
587
588    // Done...
589    // For interrupt mode, remove interrupt handler.
590
591    int_restore_int_vect();
592
593    // Done...
594    // mark end of a R/W DMA command in low level trace
595
596    trc_llt( 0, 0, TRC_LLT_E_RWD );
597
598    // All done.  The return values of this function are described in
599    // ATAIO.H.
600
601    if ( reg_cmd_info.ec )
602       return 1;
603    return 0;
604 }
605
606 //***********************************************************
607 //
608 // dma_isa_chs() - DMA in ISA Multiword for ATA R/W DMA
609 //
610 //***********************************************************
611
612 int dma_isa_chs( int dev, int cmd,
613                      unsigned int fr, unsigned int sc,
614                      unsigned int cyl, unsigned int head, unsigned int sect,
615                      unsigned int seg, unsigned int off,
616                      long numSect )
617
618 {
619
620    // Setup current command information.
621
622    sub_zero_return_data();
623    reg_cmd_info.flg = TRC_FLAG_ATA;
624    reg_cmd_info.ct  = TRC_TYPE_ADMAI;
625    if ( ( cmd == CMD_WRITE_DMA ) || ( cmd == CMD_WRITE_DMA_EXT ) )
626       reg_cmd_info.ct  = TRC_TYPE_ADMAO;
627    reg_cmd_info.cmd = cmd;
628    reg_cmd_info.fr1 = fr;
629    reg_cmd_info.sc1 = sc;
630    reg_cmd_info.sn1 = sect;
631    reg_cmd_info.cl1 = cyl & 0x00ff;
632    reg_cmd_info.ch1 = ( cyl & 0xff00 ) >> 8;
633    reg_cmd_info.dh1 = ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) | ( head & 0x0f );
634    reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
635    reg_cmd_info.ns  = numSect;
636    reg_cmd_info.lbaSize = LBACHS;
637
638    // Execute the command.
639
640    return exec_isa_ata_cmd( dev, seg, off, numSect );
641 }
642
643 //***********************************************************
644 //
645 // dma_isa_lba28() - DMA in ISA Multiword for ATA R/W DMA
646 //
647 //***********************************************************
648
649 int dma_isa_lba28( int dev, int cmd,
650                        unsigned int fr, unsigned int sc,
651                        unsigned long lba,
652                        unsigned int seg, unsigned int off,
653                        long numSect )
654
655 {
656
657    // Setup current command information.
658
659    sub_zero_return_data();
660    reg_cmd_info.flg = TRC_FLAG_ATA;
661    reg_cmd_info.ct  = TRC_TYPE_ADMAI;
662    reg_cmd_info.cmd = cmd;
663    if ( ( cmd == CMD_WRITE_DMA ) || ( cmd == CMD_WRITE_DMA_EXT ) )
664       reg_cmd_info.ct  = TRC_TYPE_ADMAO;
665    reg_cmd_info.fr1 = fr;
666    reg_cmd_info.sc1 = sc;
667    reg_cmd_info.dh1 = CB_DH_LBA | (dev ? CB_DH_DEV1 : CB_DH_DEV0 );
668    reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
669    reg_cmd_info.ns  = numSect;
670    reg_cmd_info.lbaSize = LBA28;
671    reg_cmd_info.lbaHigh1 = 0L;
672    reg_cmd_info.lbaLow1 = lba;
673
674    // Execute the command.
675
676    return exec_isa_ata_cmd( dev, seg, off, numSect );
677 }
678
679 //***********************************************************
680 //
681 // dma_isa_lba48() - DMA in ISA Multiword for ATA R/W DMA
682 //
683 //***********************************************************
684
685 int dma_isa_lba48( int dev, int cmd,
686                        unsigned int fr, unsigned int sc,
687                        unsigned long lbahi, unsigned long lbalo,
688                        unsigned int seg, unsigned int off,
689                        long numSect )
690
691 {
692
693    // Setup current command information.
694
695    sub_zero_return_data();
696    reg_cmd_info.flg = TRC_FLAG_ATA;
697    reg_cmd_info.ct  = TRC_TYPE_ADMAI;
698    if ( ( cmd == CMD_WRITE_DMA ) || ( cmd == CMD_WRITE_DMA_EXT ) )
699       reg_cmd_info.ct  = TRC_TYPE_ADMAO;
700    reg_cmd_info.cmd = cmd;
701    reg_cmd_info.fr1 = fr;
702    reg_cmd_info.sc1 = sc;
703    reg_cmd_info.dh1 = CB_DH_LBA | (dev ? CB_DH_DEV1 : CB_DH_DEV0 );
704    reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
705    reg_cmd_info.ns  = numSect;
706    reg_cmd_info.lbaSize = LBA48;
707    reg_cmd_info.lbaHigh1 = lbahi;
708    reg_cmd_info.lbaLow1 = lbalo;
709
710    // Execute the command.
711
712    return exec_isa_ata_cmd( dev, seg, off, numSect );
713 }
714
715 //***********************************************************
716 //
717 // dma_isa_packet() - DMA in ISA Multiword for ATAPI Packet
718 //
719 //***********************************************************
720
721 int dma_isa_packet( int dev,
722                     unsigned int cpbc,
723                     unsigned int cpseg, unsigned int cpoff,
724                     int dir,
725                     long dpbc,
726                     unsigned int dpseg, unsigned int dpoff,
727                     unsigned long lba )
728
729 {
730    unsigned char status;
731    unsigned char reason;
732    unsigned char lowCyl;
733    unsigned char highCyl;
734    int ndx;
735    unsigned char far * cfp;
736    unsigned long lw1, lw2;
737
738    // mark start of isa dma PI cmd in low level trace
739
740    trc_llt( 0, 0, TRC_LLT_S_PID );
741
742    // Make sure the command packet size is either 12 or 16
743    // and save the command packet size and data.
744
745    cpbc = cpbc < 12 ? 12 : cpbc;
746    cpbc = cpbc > 12 ? 16 : cpbc;
747
748    // Setup current command information.
749
750    sub_zero_return_data();
751    reg_cmd_info.flg = TRC_FLAG_ATAPI;
752    reg_cmd_info.ct  = dir ? TRC_TYPE_PDMAO : TRC_TYPE_PDMAI;
753    reg_cmd_info.cmd = CMD_PACKET;
754    reg_cmd_info.fr1 = reg_atapi_reg_fr | 0x01;  // packet DMA mode !
755    reg_cmd_info.sc1 = reg_atapi_reg_sc;
756    reg_cmd_info.sn1 = reg_atapi_reg_sn;
757    reg_cmd_info.cl1 = 0;         // no Byte Count Limit in DMA !
758    reg_cmd_info.ch1 = 0;         // no Byte Count Limit in DMA !
759    reg_cmd_info.dh1 = dev ? CB_DH_DEV1 : CB_DH_DEV0;
760    reg_cmd_info.dc1 = int_use_intr_flag ? 0 : CB_DC_NIEN;
761    reg_cmd_info.lbaSize = LBA32;
762    reg_cmd_info.lbaLow1 = lba;
763    reg_cmd_info.lbaHigh1 = 0L;
764    reg_atapi_cp_size = cpbc;
765    cfp = MK_FP( cpseg, cpoff );
766    for ( ndx = 0; ndx < cpbc; ndx ++ )
767    {
768       reg_atapi_cp_data[ndx] = * cfp;
769       cfp ++ ;
770    }
771
772    // Zero the alternate ATAPI register data.
773
774    reg_atapi_reg_fr = 0;
775    reg_atapi_reg_sc = 0;
776    reg_atapi_reg_sn = 0;
777    reg_atapi_reg_dh = 0;
778
779    // Quit now if no dma channel set up
780
781    if ( ! dmaChan )
782    {
783       reg_cmd_info.ec = 70;
784       trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
785       sub_trace_command();
786       trc_llt( 0, 0, TRC_LLT_E_PID );
787       return 1;
788    }
789
790    // the data packet byte count must be even
791    // and must not be zero
792
793    if ( dpbc & 1L )
794       dpbc ++ ;
795    if ( dpbc < 2L )
796       dpbc = 2L;
797
798    // Quit now if 1) I/O buffer overrun possible
799    // or 2) DMA can't handle the transfer size.
800
801    if ( ( dpbc > 131072L ) || ( dpbc > reg_buffer_size ) )
802    {
803       reg_cmd_info.ec = 61;
804       trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
805       sub_trace_command();
806       trc_llt( 0, 0, TRC_LLT_E_PID );
807       return 1;
808    }
809
810    // set up the dma transfer(s)
811
812    set_up_xfer( dir, dpbc, dpseg, dpoff );
813
814    // Set command time out.
815
816    tmr_set_timeout();
817
818    // Select the drive - call the reg_select function.
819    // Quit now if this fails.
820
821    if ( sub_select( dev ) )
822    {
823       sub_trace_command();
824       trc_llt( 0, 0, TRC_LLT_E_PID );
825       return 1;
826    }
827
828    // Set up all the registers except the command register.
829
830    sub_setup_command();
831
832    // For interrupt mode, install interrupt handler.
833
834    int_save_int_vect();
835
836    // program the dma channel for the first or only transfer.
837
838    prog_dma_chan( page1, addr1, count1, modeByte );
839
840    // Start the command by setting the Command register.  The drive
841    // should immediately set BUSY status.
842
843    pio_outbyte( CB_CMD, CMD_PACKET );
844
845    // Waste some time by reading the alternate status a few times.
846    // This gives the drive time to set BUSY in the status register on
847    // really fast systems.  If we don't do this, a slow drive on a fast
848    // system may not set BUSY fast enough and we would think it had
849    // completed the command when it really had not even started the
850    // command yet.
851
852    ATA_DELAY();
853
854    // Command packet transfer...
855    // Check for protocol failures,
856    // the device should have BSY=1 or
857    // if BSY=0 then either DRQ=1 or CHK=1.
858
859    ATAPI_DELAY( dev );
860    status = pio_inbyte( CB_ASTAT );
861    if ( status & CB_STAT_BSY )
862    {
863       // BSY=1 is OK
864    }
865    else
866    {
867       if ( status & ( CB_STAT_DRQ | CB_STAT_ERR ) )
868       {
869          // BSY=0 and DRQ=1 is OK
870          // BSY=0 and ERR=1 is OK
871       }
872       else
873       {
874          reg_cmd_info.failbits |= FAILBIT0;  // not OK
875       }
876    }
877
878    // Command packet transfer...
879    // Poll Alternate Status for BSY=0.
880
881    trc_llt( 0, 0, TRC_LLT_PNBSY );
882    while ( 1 )
883    {
884       status = pio_inbyte( CB_ASTAT );       // poll for not busy
885       if ( ( status & CB_STAT_BSY ) == 0 )
886          break;
887       if ( tmr_chk_timeout() )               // time out yet ?
888       {
889          trc_llt( 0, 0, TRC_LLT_TOUT );      // yes
890          reg_cmd_info.to = 1;
891          reg_cmd_info.ec = 75;
892          trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
893          break;
894       }
895    }
896
897    // Command packet transfer...
898    // Check for protocol failures... no interrupt here please!
899    // Clear any interrupt the command packet transfer may have caused.
900
901    if ( int_intr_flag )    // extra interrupt(s) ?
902       reg_cmd_info.failbits |= FAILBIT1;
903    int_intr_flag = 0;
904
905    // Command packet transfer...
906    // If no error, transfer the command packet.
907
908    if ( reg_cmd_info.ec == 0 )
909    {
910
911       // Command packet transfer...
912       // Read the primary status register and the other ATAPI registers.
913
914       status = pio_inbyte( CB_STAT );
915       reason = pio_inbyte( CB_SC );
916       lowCyl = pio_inbyte( CB_CL );
917       highCyl = pio_inbyte( CB_CH );
918
919       // Command packet transfer...
920       // check status: must have BSY=0, DRQ=1 now
921
922       if (    ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) )
923            != CB_STAT_DRQ
924          )
925       {
926          reg_cmd_info.ec = 76;
927          trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
928       }
929       else
930       {
931          // Command packet transfer...
932          // Check for protocol failures...
933          // check: C/nD=1, IO=0.
934
935          if ( ( reason &  ( CB_SC_P_TAG | CB_SC_P_REL | CB_SC_P_IO ) )
936               || ( ! ( reason &  CB_SC_P_CD ) )
937             )
938             reg_cmd_info.failbits |= FAILBIT2;
939          if (    ( lowCyl != reg_cmd_info.cl1 )
940               || ( highCyl != reg_cmd_info.ch1 ) )
941             reg_cmd_info.failbits |= FAILBIT3;
942
943          // Command packet transfer...
944          // trace cdb byte 0,
945          // xfer the command packet (the cdb)
946
947          trc_llt( 0, * (unsigned char far *) MK_FP( cpseg, cpoff ), TRC_LLT_P_CMD );
948          pio_drq_block_out( CB_DATA, cpseg, cpoff, cpbc >> 1 );
949       }
950    }
951
952    // Data transfer...
953    // If this transfer requires two dma transfers,
954    // wait for the first transfer to complete and
955    // then program the dma channel for the second transfer.
956
957    if ( ( reg_cmd_info.ec == 0 ) && doTwo )
958    {
959       // Data transfer...
960       // wait for dma chan to transfer first part by monitoring
961       // the dma channel's terminal count status bit
962       // -or-
963       // watch for command completion due to an error
964       // -or-
965       // time out if this takes too long.
966
967       trc_llt( 0, 0, TRC_LLT_DMA2 );
968       while ( 1 )
969       {
970          if ( inportb( 0xd0 ) & dmaTCbit )   // terminal count yet ?
971             break;                           // yes - ok!
972          if ( chk_cmd_done() )               // cmd done ?
973          {
974             reg_cmd_info.ec = 71;
975             trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
976             break;
977          }
978          if ( tmr_chk_timeout() )            // time out yet ?
979          {
980             trc_llt( 0, 0, TRC_LLT_TOUT );
981             reg_cmd_info.to = 1;
982             reg_cmd_info.ec = 72;
983             trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
984             break;
985          }
986       }
987
988       // if no error, set up 2nd transfer
989
990       if ( reg_cmd_info.ec == 0 )
991       {
992          // update bytes transferred count
993          reg_cmd_info.totalBytesXfer += count1 << 1;
994
995          // program dma channel to transfer the second part
996          prog_dma_chan( page2, addr2, count2, modeByte );
997          count1 = count2;
998       }
999    }
1000
1001    // End of command...
1002    // if no error,
1003    // wait for drive to signal command completion
1004    // -or-
1005    // time out if this takes to long.
1006
1007    if ( reg_cmd_info.ec == 0 )
1008    {
1009       if ( int_use_intr_flag )
1010          trc_llt( 0, 0, TRC_LLT_WINT );
1011       else
1012          trc_llt( 0, 0, TRC_LLT_PNBSY );
1013       while ( 1 )
1014       {
1015          if ( chk_cmd_done() )               // cmd done ?
1016             break;                           // yes
1017          if ( tmr_chk_timeout() )            // time out yet ?
1018          {
1019             trc_llt( 0, 0, TRC_LLT_TOUT );   // yes
1020             reg_cmd_info.to = 1;
1021             reg_cmd_info.ec = 73;
1022             trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
1023             break;
1024          }
1025       }
1026    }
1027
1028    // End of command...
1029    // disable/stop the dma channel
1030
1031    trc_llt( 0, 0, TRC_LLT_DMA3 );
1032    disableChan();
1033
1034    // End of command...
1035    // If polling or error read the Status register,
1036    // otherwise use the Status register value that was read
1037    // by the interrupt handler.
1038
1039    if ( ( ! int_use_intr_flag ) || ( reg_cmd_info.ec ) )
1040       status = pio_inbyte( CB_STAT );
1041    else
1042       status = int_ata_status;
1043
1044    // Final status check...
1045    // if no error, check final status...
1046    // Error if BUSY, DEVICE FAULT, DRQ or ERROR status now.
1047
1048    if ( reg_cmd_info.ec == 0 )
1049    {
1050       if ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) )
1051       {
1052          reg_cmd_info.ec = 74;
1053          trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR );
1054       }
1055    }
1056
1057    // Final status check...
1058    // Check for protocol failures...
1059    // check: C/nD=1, IO=1.
1060
1061    reason = pio_inbyte( CB_SC );
1062    if ( ( reason & ( CB_SC_P_TAG | CB_SC_P_REL ) )
1063         || ( ! ( reason & CB_SC_P_IO ) )
1064         || ( ! ( reason & CB_SC_P_CD ) )
1065       )
1066       reg_cmd_info.failbits |= FAILBIT8;
1067
1068    // Final status check...
1069    // update total bytes transferred
1070
1071    clearFF();
1072    lw1 = inportb( dmaCntrReg );
1073    lw2 = inportb( dmaCntrReg );
1074    lw1 = ( ( lw2 << 8 ) | lw1 ) + 1;
1075    lw1 = lw1 & 0x0000ffffL;
1076    reg_cmd_info.totalBytesXfer += ( count1 - lw1 ) << 1;
1077
1078    // Done...
1079    // Read the output registers and trace the command.
1080
1081    sub_trace_command();
1082
1083    // Done...
1084    // For interrupt mode, remove interrupt handler.
1085
1086    int_restore_int_vect();
1087
1088    // Done...
1089    // mark end of isa dma PI cmd in low level trace
1090
1091    trc_llt( 0, 0, TRC_LLT_E_PID );
1092
1093    // All done.  The return values of this function are described in
1094    // ATAIO.H.
1095
1096    if ( reg_cmd_info.ec )
1097       return 1;
1098    return 0;
1099 }
1100
1101 // end ataioisa.c