]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/ide/testcdej.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / ide / testcdej.c
1
2 #include <stdio.h>
3 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <malloc.h>
8 #include <ctype.h>
9 #include <fcntl.h>
10 #include <dos.h>
11
12 #include <hw/vga/vga.h>
13 #include <hw/pci/pci.h>
14 #include <hw/dos/dos.h>
15 #include <hw/8254/8254.h>               /* 8254 timer */
16 #include <hw/8259/8259.h>               /* 8259 PIC interrupts */
17 #include <hw/vga/vgagui.h>
18 #include <hw/vga/vgatty.h>
19 #include <hw/ide/idelib.h>
20
21 #include "testutil.h"
22 #include "testmbox.h"
23 #include "testcmui.h"
24 #include "testbusy.h"
25 #include "testpiot.h"
26 #include "testrvfy.h"
27 #include "testrdwr.h"
28 #include "testidnt.h"
29 #include "testcdej.h"
30 #include "test.h"
31
32 #include "testnop.h"
33 #include "testpwr.h"
34
35 void do_drive_atapi_eject_load(struct ide_controller *ide,unsigned char which,unsigned char atapi_eject_how) {
36         struct vga_msg_box vgabox;
37         uint8_t buf[12] = {0x1B/*EJECT*/,0x00,0x00,0x00, /* ATAPI EJECT (START/STOP UNIT) command */
38                 0x00,0x00,0x00,0x00,
39                 0x00,0x00,0x00,0x00};
40         /* NTS: buf[4] is filled in with how to start/stop the unit:
41          *   0x00 STOP (spin down)
42          *   0x01 START (spin up)
43          *   0x02 EJECT (eject CD, usually eject CD-ROM tray)
44          *   0x03 LOAD (load CD, close CD tray if drive is capable) */
45
46         if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0)
47                 return;
48         idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */
49         if (idelib_controller_atapi_prepare_packet_command(ide,/*xfer=to host no DMA*/0x04,/*byte count=*/0) < 0) /* fill out taskfile with command */
50                 return;
51         if (idelib_controller_apply_taskfile(ide,0xBE/*base_io+1-5&7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) /* also writes command */
52                 return;
53
54         /* NTS: Despite OSDev ATAPI advice, IRQ doesn't seem to fire at this stage, we must poll wait */
55         do_ide_controller_user_wait_busy_controller(ide);
56         do_ide_controller_user_wait_drive_ready(ide);
57         idelib_controller_update_atapi_state(ide);
58         if (!(ide->last_status&1)) { /* if no error, read result from count register */
59                 do_warn_if_atapi_not_in_command_state(ide); /* sector count register should signal we're in the command stage */
60
61                 buf[4] = atapi_eject_how; /* fill in byte 4 which tells ATAPI how to start/stop the unit */
62                 idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */
63                 idelib_controller_atapi_write_command(ide,buf,12); /* write 12-byte ATAPI command data */
64                 if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */
65                         do_ide_controller_user_wait_irq(ide,1);
66                         idelib_controller_ack_irq(ide); /* <- or else it won't fire again */
67                 }
68                 do_ide_controller_user_wait_busy_controller(ide);
69                 do_ide_controller_user_wait_drive_ready(ide);
70                 idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */
71                 common_ide_success_or_error_vga_msg_box(ide,&vgabox);
72                 wait_for_enter_or_escape();
73                 vga_msg_box_destroy(&vgabox);
74
75                 do_warn_if_atapi_not_in_complete_state(ide); /* sector count register should signal we're in the completed stage (command/data=1 input/output=1) */
76         }
77         else {
78                 common_ide_success_or_error_vga_msg_box(ide,&vgabox);
79                 wait_for_enter_or_escape();
80                 vga_msg_box_destroy(&vgabox);
81         }
82 }
83
84 static const char *drive_cdrom_startstop_strings[] = {
85         "Show IDE register taskfile",           /* 0 */
86         "Eject",
87         "Load",
88         "Start",
89         "Stop"
90 };
91
92 void do_drive_cdrom_startstop_test(struct ide_controller *ide,unsigned char which) {
93         struct menuboxbounds mbox;
94         char backredraw=1;
95         VGA_ALPHA_PTR vga;
96         unsigned int x,y;
97         int select=-1;
98         char redraw=1;
99         int c;
100
101         /* UI element vars */
102         menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1);
103         menuboxbounds_set_item_strings_arraylen(&mbox,drive_cdrom_startstop_strings);
104
105         /* most of the commands assume a ready controller. if it's stuck,
106          * we'd rather the user have a visual indication that it's stuck that way */
107         c = do_ide_controller_user_wait_busy_controller(ide);
108         if (c != 0) return;
109
110         /* select the drive we want */
111         idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS);
112
113         /* in case the IDE controller is busy for that time */
114         c = do_ide_controller_user_wait_busy_controller(ide);
115         if (c != 0) return;
116
117         /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */
118         c = do_ide_controller_drive_check_select(ide,which);
119         if (c < 0) return;
120
121         /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */
122         do_ide_controller_atapi_device_check_post_host_reset(ide);
123
124         /* wait for the drive to indicate readiness */
125         /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong
126          *      possibility that the device doesn't exist. This can happen for example if there
127          *      is a master attached but no slave. */
128         c = do_ide_controller_user_wait_drive_ready(ide);
129         if (c < 0) return;
130
131         /* for completeness, clear pending IRQ */
132         idelib_controller_ack_irq(ide);
133
134         while (1) {
135                 if (backredraw) {
136                         vga = vga_alpha_ram;
137                         backredraw = 0;
138                         redraw = 1;
139
140                         for (y=0;y < vga_height;y++) {
141                                 for (x=0;x < vga_width;x++) {
142                                         *vga++ = 0x1E00 + 177;
143                                 }
144                         }
145
146                         vga_moveto(0,0);
147
148                         vga_write_color(0x1F);
149                         vga_write("        IDE controller ");
150                         sprintf(tmp,"@%X",ide->base_io);
151                         vga_write(tmp);
152                         if (ide->alt_io != 0) {
153                                 sprintf(tmp," alt %X",ide->alt_io);
154                                 vga_write(tmp);
155                         }
156                         if (ide->irq >= 0) {
157                                 sprintf(tmp," IRQ %d",ide->irq);
158                                 vga_write(tmp);
159                         }
160                         vga_write(which ? " Slave" : " Master");
161                         vga_write(" << CD-ROM eject/load");
162                         while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' ');
163
164                         vga_write_color(0xC);
165                         vga_write("WARNING: This code talks directly to your hard disk controller.");
166                         while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' ');
167                         vga_write_color(0xC);
168                         vga_write("         If you value the data on your hard drive do not run this program.");
169                         while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' ');
170                 }
171
172                 if (redraw) {
173                         redraw = 0;
174
175                         vga_moveto(mbox.ofsx,mbox.ofsy - 2);
176                         vga_write_color((select == -1) ? 0x70 : 0x0F);
177                         vga_write("Back to IDE drive main menu");
178                         while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' ');
179
180                         menuboxbound_redraw(&mbox,select);
181                 }
182
183                 c = getch();
184                 if (c == 0) c = getch() << 8;
185
186                 if (c == 27) {
187                         break;
188                 }
189                 else if (c == 13) {
190                         if (select == -1)
191                                 break;
192
193                         switch (select) {
194                                 case 0: /* show IDE register taskfile */
195                                         do_common_show_ide_taskfile(ide,which);
196                                         redraw = backredraw = 1;
197                                         break;
198                                 case 1: /*Eject*/
199                                 case 2: /*Load*/
200                                 case 3: /*Start*/
201                                 case 4: /*Stop*/ {
202                                         static const unsigned char cmd[4] = {2/*eject*/,3/*load*/,1/*start*/,0/*stop*/};
203                                         do_drive_atapi_eject_load(ide,which,cmd[select-1]);
204                                         } break;
205                         };
206                 }
207                 else if (c == 0x4800) {
208                         if (--select < -1)
209                                 select = mbox.item_max;
210
211                         redraw = 1;
212                 }
213                 else if (c == 0x4B00) { /* left */
214                         redraw = 1;
215                 }
216                 else if (c == 0x4D00) { /* right */
217                         redraw = 1;
218                 }
219                 else if (c == 0x5000) {
220                         if (++select > mbox.item_max)
221                                 select = -1;
222
223                         redraw = 1;
224                 }
225         }
226 }
227