…Show last 1040 lines
61 byte commandstatus; //Do we have a command?
62 struct
63 {
64 union
65 {
66 struct
67 {
68 byte noaddressmark : 1;
69 byte track0notfound : 1;
70 byte commandaborted : 1;
71 byte mediachangerequested : 1;
72 byte idmarknotfound : 1;
73 byte mediachanged : 1;
74 byte uncorrectabledata : 1;
75 byte badsector : 1;
76 };
77 byte data;
78 } ERRORREGISTER;
79 union
80 {
81 struct
82 {
83 byte error : 1; //An error has occurred when 1!
84 byte index : 1; //Set once per disk revolution.
85 byte correcteddata : 1; //Data has been corrected.
86 byte datarequestready : 1; //Ready to transfer a word or byte of data between the host and the drive.
87 byte driveseekcomplete : 1; //Drive heads are settled on a track.
88 byte drivewritefault : 1; //Write fault status.
89 byte driveready : 1; //Ready to accept a command?
90 byte busy : 1; //The drive has access to the Command Block Registers.
91 };
92 byte data;
93 } STATUSREGISTER;
94
95 struct
96 {
97 union
98 {
99 struct
100 {
101 byte sectornumber; //LBA bits 0-7!
102 byte cylinderhigh; //LBA bits 8-15!
103 byte cylinderlow; //LBA bits 16-23!
104 union
105 {
106 byte drivehead; //LBA 24-27!
107 struct
108 {
109 byte head : 4; //What head?
110 byte slavedrive : 1; //What drive?
111 byte always1_1 : 1;
112 byte LBAMode_2 : 1; //LBA mode?
113 byte always1_2 : 1;
114 };
115 struct
116 {
117 byte LBAhigh : 6; //High 6 bits!
118 byte LBAMode : 1; //LBA mode?
119 byte always1_3 : 1;
120 };
121 };
122 };
123 uint_32 LBA; //LBA address in LBA mode (28 bits value)!
124 };
125 byte features;
126 byte sectorcount;
127 } PARAMETERS;
128 word driveparams[0x100]; //All drive parameters for a drive!
129 uint_32 current_LBA_address; //Current LBA address!
130 } Drive[2]; //Two drives!
131
132 union
133 {
134 struct
135 {
136 byte unused : 1;
137 byte nIEN : 1; //Disable interrupts when set or not the drive selected!
138 byte SRST : 1; //Reset!
139 };
140 byte data;
141 } DriveControlRegister;
142 union
143 {
144 byte data;
145 } DriveAddressRegister;
146
147 byte activedrive; //What drive are we currently?
148 byte DMAPending; //DMA pending?
149 byte TC; //Terminal count occurred in DMA transfer?
150} ATA[2]; //Two channels of ATA drives!
151
152uint_32 ATA_CHS2LBA(byte channel, byte slave, word cylinder, byte head, byte sector)
153{
154 return ((cylinder*ATA[channel].Drive[slave].driveparams[55]) + head)*ATA[channel].Drive[slave].driveparams[56]; //Give the LBA value!
155}
156
157void ATA_LBA2CHS(byte channel, byte slave, uint_32 LBA, word *cylinder, byte *head, byte *sector)
158{
159 uint_32 temp;
160 temp = (ATA[channel].Drive[slave].driveparams[55] * ATA[channel].Drive[slave].driveparams[56]); //Sectors per cylinder!
161 *cylinder = (word)(LBA / temp); //Cylinder!
162 LBA -= temp; //Decrease LBA to get heads§ors!
163 temp = ATA[channel].Drive[slave].driveparams[56]; //SPT!
164 *head = (LBA / temp) & 0xF; //The head!
165 LBA -= temp; //Decrease LBA to get sectors!
166 *sector = (LBA & 0xFF); //The sector!
167}
168
169int ATA_Drives[2][2]; //All ATA mounted drives to disk conversion!
170byte ATA_DrivesReverse[4][2]; //All Drive to ATA mounted drives conversion!
171
172void ATA_IRQ(byte channel, byte slave)
173{
174 if (!ATA[channel].DriveControlRegister.nIEN) //Allow interrupts?
175 {
176 switch (channel)
177 {
178 case 0: //Primary channel?
179 doirq(ATA_PRIMARYIRQ); //Execute the IRQ!
180 break;
181 case 1:
182 doirq(ATA_PRIMARYIRQ); //Execute the IRQ!
183 break;
184 default: //Unknown channel?
185 break;
186 }
187 }
188}
189
190void ATA_removeIRQ(byte channel, byte slave)
191{
192 if (!ATA[channel].DriveControlRegister.nIEN) //Allow interrupts?
193 {
194 switch (channel)
195 {
196 case 0: //Primary channel?
197 removeirq(ATA_PRIMARYIRQ); //Execute the IRQ!
198 break;
199 case 1:
200 removeirq(ATA_PRIMARYIRQ); //Execute the IRQ!
201 break;
202 default: //Unknown channel?
203 break;
204 }
205 }
206}
207
208TicksHolder ATATicks;
209struct
210{
211 uint_64 ATA_tickstiming;
212 uint_64 ATA_tickstimeout; //How big a timeout are we talking about?
213 byte type; //Type of timer!
214} IRQtimer[4]; //IRQ timer!
215
216void updateATA() //ATA timing!
217{
218 uint_64 passed = getuspassed_k(&ATATicks); //Get us passed!
219 if (passed) //Anything passed?
220 {
221 getuspassed(&ATATicks); //Passed some time!
222 int i;
223 for (i = 0;i < 4;i++) //Process all timers!
224 {
225 if (IRQtimer[i].ATA_tickstimeout) //Ticking?
226 {
227 IRQtimer[i].ATA_tickstiming += passed; //We've passed some!
228 if (IRQtimer[i].ATA_tickstiming >= IRQtimer[i].ATA_tickstimeout) //Expired?
229 {
230 IRQtimer[i].ATA_tickstimeout = 0; //Finished!
231 ATA_IRQ(i & 2, i & 1); //Do an IRQ from the source!
232 byte drive = (i & 1); //Drive!
233 byte channel = ((i & 2) >> 1); //Channel!
234 }
235 }
236 }
237 }
238}
239
240uint_32 getPORTaddress(byte channel)
241{
242 switch (channel)
243 {
244 case 0: //First?
245 return (PCI_IDE.BAR[0] > 1) ? PCI_IDE.BAR[0] : 0x1F0; //Give the BAR!
246 break;
247 case 1: //Second?
248 return (PCI_IDE.BAR[2] > 1) ? PCI_IDE.BAR[2] : 0x170; //Give the BAR!
249 break;
250 default:
251 return ~0; //Error!
252 }
253}
254
255uint_32 getControlPORTaddress(byte channel)
256{
257 switch (channel)
258 {
259 case 0: //First?
260 return (PCI_IDE.BAR[1] > 1) ? PCI_IDE.BAR[1] : 0x3F6; //Give the BAR!
261 break;
262 case 1: //Second?
263 return (PCI_IDE.BAR[3] > 1) ? PCI_IDE.BAR[3] : 0x376; //Give the BAR!
264 break;
265 default:
266 return ~0; //Error!
267 }
268}
269
270word get_cylinders(uint_64 disk_size)
271{
272 return floor(disk_size / (63 * 16)); //How many cylinders!
273}
274
275word get_heads(uint_64 disk_size)
276{
277 return 16;
278}
279
280word get_SPT(uint_64 disk_size)
281{
282 return 63;
283}
284
285byte ATA_activeDrive(byte channel)
286{
287 return ATA[channel].activedrive; //Give the drive or 0xFF if invalid!
288}
289
290byte ATA_resultIN(byte channel)
291{
292 byte result;
293 switch (ATA[channel].command)
294 {
295 case 0xEC: //Identify?
296 result = ATA[channel].result[ATA[channel].resultpos++]; //Read the result byte!
297 if (ATA[channel].resultpos == ATA[channel].resultsize) //Fully read?
298 {
299 ATA[channel].commandstatus = 0; //Reset command!
300 }
301 return result; //Give the result byte!
302 break;
303 default: //Unknown?
304 break;
305 }
306 return 0; //Unknown data!
307}
308
309void ATA_increasesector(byte channel) //Increase the current sector to the next sector!
310{
311 ++ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address; //Increase the current sector!
312}
313
314void ATA_updatesector(byte channel) //Update the current sector!
315{
316 word cylinder;
317 byte head, sector;
318 if (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBAMode) //LBA mode?
319 {
320 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBA &= 0xFFFFFFF; //Clear the LBA part!
321 ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address &= 0xFFFFFFF; //Truncate the address to it's size!
322 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBA |= ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address; //Set the LBA part only!
323 }
324 else
325 {
326 uint_64 disk_size = ((ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[61] << 8) | ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[60]); //The size of the disk in sectors!
327 ATA_LBA2CHS(channel,ATA_activeDrive(channel),ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address, &cylinder, &head, §or); //Convert the current LBA address into a CHS value!
328 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh = ((cylinder >> 8) & 0xFF); //Cylinder high!
329 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow = (cylinder&0xFF); //Cylinder low!
330 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.head = head; //Head!
331 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectornumber = sector; //Sector number!
332 }
333}
334
335byte ATA_readsector(byte channel) //Read the current sector set up!
336{
337 uint_64 disk_size = ((ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[61] << 8) | ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[60]); //The size of the disk in sectors!
338 if (ATA[channel].commandstatus == 1) //We're reading already?
339 {
340 if (!--ATA[channel].datasize) //Finished?
341 {
342 ATA_updatesector(channel); //Update the current sector!
343 ATA[channel].commandstatus = 0; //We're back in command mode!
344 return 1; //We're finished!
345 }
346 }
347 if (ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address >= disk_size) //Past the end of the disk?
348 {
349 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.idmarknotfound = 1; //Not found!
350 ATA_updatesector(channel); //Update the current sector!
351 ATA[channel].commandstatus = 0xFF; //Error!
352 return 0; //Stop!
353 }
354
355 if (readdata(ATA_Drives[channel][ATA_activeDrive(channel)], &ATA[channel].data, (ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address << 9), 0x200)) //Read the data from disk?
356 {
357 ATA_increasesector(channel); //Increase the current sector!
358
359 ATA[channel].datablock = 0x200; //We're refreshing after this many bytes!
360 ATA[channel].datapos = 0; //Initialise our data position!
361 ATA[channel].commandstatus = 1; //Transferring data IN!
362 return 1; //Process the block!
363 }
364 else //Error reading?
365 {
366 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.idmarknotfound = 1; //Not found!
367 ATA_updatesector(channel); //Update the current sector!
368 ATA[channel].commandstatus = 0xFF; //Error!
369 return 0; //Stop!
370 }
371 return 1; //We're finished!
372}
373
374byte ATA_writesector(byte channel)
375{
376 uint_64 disk_size = ((ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[61] << 8) | ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[60]); //The size of the disk in sectors!
377 if (ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address >= disk_size) //Past the end of the disk?
378 {
379 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.idmarknotfound = 1; //Not found!
380 ATA_updatesector(channel); //Update the current sector!
381 ATA[channel].commandstatus = 0xFF; //Error!
382 return 1; //We're finished!
383 }
384
385 if (writedata(ATA_Drives[channel][ATA_activeDrive(channel)], &ATA[channel].data, (ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address << 9), 0x200)) //Write the data to the disk?
386 {
387 ATA_increasesector(channel); //Increase the current sector!
388
389 if (!--ATA[channel].datasize) //Finished?
390 {
391 ATA_updatesector(channel); //Update the current sector!
392 ATA[channel].commandstatus = 0; //We're back in command mode!
393 return 1; //We're finished!
394 }
395
396 //Process next sector!
397 ATA[channel].datablock = 0x200; //We're refreshing after this many bytes!
398 ATA[channel].datapos = 0; //Initialise our data position!
399 ATA[channel].commandstatus = 1; //Transferring data IN!
400 return 1; //Process the block!
401 }
402 else //Write failed?
403 {
404 if (drivereadonly(ATA_Drives[channel][ATA_activeDrive(channel)])) //R/O drive?
405 {
406 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.drivewritefault = 1; //Write fault!
407 }
408 else
409 {
410 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.uncorrectabledata = 1; //Not found!
411 }
412 ATA_updatesector(channel); //Update the current sector!
413 ATA[channel].commandstatus = 0xFF; //Error!
414 }
415 return 0; //Finished!
416}
417
418byte ATA_dataIN(byte channel) //Byte read from data!
419{
420 byte result;
421 switch (ATA[channel].command) //What command?
422 {
423 case 0x20:
424 case 0x21: //Read sectors?
425 result = ATA[channel].data[ATA[channel].datapos++]; //Read the data byte!
426 if (ATA[channel].datapos == ATA[channel].datablock) //Full block read?
427 {
428 if (ATA_readsector(channel)) //Next sector read?
429 {
430 ATA_IRQ(channel, ATA_activeDrive(channel)); //Give our requesting IRQ!
431 }
432 }
433 break;
434 default: //Unknown?
435 break;
436 }
437 return 0; //Unknown data!
438}
439
440void ATA_dataOUT(byte channel, byte data) //Byte written to data!
441{
442 switch (ATA[channel].command) //What command?
443 {
444 case 0x30: //Write sector(s) (w/retry)?
445 case 0x31: //Write sectors (w/o retry)?
446 ATA[channel].data[ATA[channel].datapos++] = data; //Write the data byte!
447 if (ATA[channel].datapos == ATA[channel].datablock) //Full block read?
448 {
449 if (ATA_writesector(channel)) //Sector written and to write another sector?
450 {
451 ATA_IRQ(channel, ATA_activeDrive(channel)); //Give our requesting IRQ!
452 }
453 }
454 break;
455 default: //Unknown?
456 break;
457 }
458}
459
460void ATA_executeCommand(byte channel, byte command) //Execute a command!
461{
462 ATA[channel].longop = 0; //Default: no long operation!
463 uint_64 disk_size;
464 int drive;
465 byte temp;
466 switch (command) //What command?
467 {
468 case 0x90: //Execute drive diagnostic?
469 dolog("ATA", "DIAGNOSTICS:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
470 ATA[channel].Drive[0].ERRORREGISTER.data = 0x1; //OK!
471 ATA[channel].Drive[1].ERRORREGISTER.data = 0x1; //OK!
472 ATA[channel].Drive[0].STATUSREGISTER.error = 0; //Not an error!
473 ATA[channel].Drive[1].STATUSREGISTER.error = 0; //Not an error!
474 ATA[channel].commandstatus = 0; //Reset status!
475 ATA_IRQ(channel, ATA_activeDrive(channel)); //IRQ!
476 break;
477 case 0xDB: //Acnowledge media change?
478 dolog("ATA", "ACNMEDIACHANGE:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
479 switch (ATA_Drives[channel][ATA_activeDrive(channel)]) //What kind of drive?
480 {
481 case CDROM0:
482 case CDROM1: //CD-ROM?
483 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.mediachanged = 0; //Not changed anymore!
484 ATA[channel].commandstatus = 0; //Reset status!
485 break;
486 default:
487 goto invalidcommand;
488 }
489 break;
490 case 0x10:
491 case 0x11:
492 case 0x12:
493 case 0x13:
494 case 0x14:
495 case 0x15:
496 case 0x16:
497 case 0x17:
498 case 0x18:
499 case 0x19:
500 case 0x1A:
501 case 0x1B:
502 case 0x1C:
503 case 0x1D:
504 case 0x1E:
505 case 0x1F: //Recalibrate?
506 dolog("ATA", "RECALIBRATE:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
507 temp = (command & 0xF); //???
508 if (has_drive(ATA_Drives[channel][ATA_activeDrive(channel)]) && (ATA_Drives[channel][ATA_activeDrive(channel)]>=HDD0) && (ATA_Drives[channel][ATA_activeDrive(channel)]<=HDD1)) //Gotten drive?
509 {
510 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow = 0; //Clear cylinder #!
511 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveseekcomplete = 1; //We've completed seeking!
512 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
513 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.data = 0; //No error!
514 ATA[channel].commandstatus = 0; //Reset status!
515 ATA_IRQ(channel, ATA_activeDrive(channel)); //Execute the IRQ!
516 }
517 else
518 {
519 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveseekcomplete = 0; //We've not completed seeking!
520 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.track0notfound = 1; //Track 0 couldn't be found!
521 ATA[channel].commandstatus = 0xFF; //Error!
522 ATA_IRQ(channel, ATA_activeDrive(channel)); //Execute the IRQ!
523 }
524 break;
525 case 0x70:
526 case 0x71:
527 case 0x72:
528 case 0x73:
529 case 0x74:
530 case 0x75:
531 case 0x76:
532 case 0x77:
533 case 0x78:
534 case 0x79:
535 case 0x7A:
536 case 0x7B:
537 case 0x7C:
538 case 0x7D:
539 case 0x7E:
540 case 0x7F: //Seek?
541 dolog("ATA", "SEEK:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
542 temp = (command & 0xF); //The head to select!
543 if (((ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh << 8) | ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow) < ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[54]) //Cylinder correct?
544 {
545 if (temp < ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[55]) //Head within range?
546 {
547 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.head = temp; //Set the head we use!
548 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.data = 0; //No error!
549 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveseekcomplete = 1; //We've completed seeking!
550 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
551 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.data = 0; //No error!
552 ATA[channel].commandstatus = 0; //Reset status!
553 ATA_IRQ(channel, ATA_activeDrive(channel)); //Execute an IRQ!
554 }
555 else goto invalidcommand; //Error out!
556 }
557 else goto invalidcommand; //Error out!
558 break;
559 case 0x22: //Read long (w/retry)?
560 case 0x23: //Read long (w/o retry)?
561 ATA[channel].longop = 1; //Long operation!
562 case 0x20: //Read sector(s) (w/retry)?
563 case 0x21: //Read sector(s) (w/o retry)?
564 dolog("ATA", "READ(long:%i):%i,%i=%02X", ATA[channel].longop,channel, ATA_activeDrive(channel), command);
565 ATA[channel].datasize = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectorcount; //Load sector count!
566 disk_size = ((ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[61] << 8) | ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[60]); //The size of the disk in sectors!
567 if (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBAMode) //Are we in LBA mode?
568 {
569 ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address = (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBA & 0xFFFFFFF); //The LBA address!
570 }
571 else //Normal CHS address?
572 {
573 ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address = ATA_CHS2LBA(channel,ATA_activeDrive(channel),
574 ((ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh << 8) | (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow)),
575 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.head,
576 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectornumber); //The LBA address based on the CHS address!
577
578 }
579 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
580 if (ATA_readsector(channel)) //OK?
581 {
582 ATA_IRQ(channel, ATA_activeDrive(channel)); //Give our requesting IRQ!
583 }
584 break;
585 case 0x32: //Write long (w/retry)?
586 case 0x33: //Write long (w/o retry)?
587 ATA[channel].longop = 1; //Long operation!
588 case 0x30: //Write sector(s) (w/retry)?
589 case 0x31: //Write sectors (w/o retry)?
590 dolog("ATA", "WRITE(LONG:%i):%i,%i=%02X",ATA[channel].longop, channel, ATA_activeDrive(channel), command);
591 ATA[channel].datasize = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectorcount; //Load sector count!
592 disk_size = ((ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[61] << 8) | ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[60]); //The size of the disk in sectors!
593 if (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBAMode) //Are we in LBA mode?
594 {
595 ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address = (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.LBA & 0xFFFFFFF); //The LBA address!
596 }
597 else //Normal CHS address?
598 {
599 ATA[channel].Drive[ATA_activeDrive(channel)].current_LBA_address = ATA_CHS2LBA(
600 ((ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh << 8) | (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow)),
601 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.head,
602 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectornumber,
603 ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[55],
604 (uint_64)disk_size); //The LBA address based on the CHS address!
605
606 }
607 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
608 ATA_IRQ(channel, ATA_activeDrive(channel)); //Give our requesting IRQ!
609 ATA[channel].commandstatus = 2; //Transferring data OUT!
610 break;
611 case 0x91: //Initialise device parameters?
612 dolog("ATA", "INITDRVPARAMS:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
613 ATA[channel].commandstatus = 0; //Requesting command again!
614 ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[55] = (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.head + 1); //Set the current maximum head!
615 ATA[channel].Drive[ATA_activeDrive(channel)].driveparams[56] = (ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectorcount); //Set the current sectors per track!
616 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.data = 0; //No errors!
617 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
618 break;
619 case 0xEC: //Identify drive?
620 dolog("ATA", "IDENTIFY:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
621 ATA[channel].command = 0xEC; //We're running this command!
622 memcpy(&ATA[channel].result, &ATA[channel].Drive[ATA_activeDrive(channel)].driveparams, sizeof(ATA[channel].Drive[ATA_activeDrive(channel)].driveparams)); //Set drive parameters currently set!
623 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.data = 0; //Clear any errors!
624 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.data = 0; //No errors!
625 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow = 0; //Needs to be 0 to detect!
626 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh = 0; //Needs to be 0 to detect!
627 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
628 //Finish up!
629 ATA[channel].resultpos = 0; //Initialise data position for the result!
630 ATA[channel].resultsize = sizeof(ATA[channel].Drive[ATA_activeDrive(channel)].driveparams); //512 byte result!
631 ATA[channel].commandstatus = 3; //We're requesting data to be read!
632 ATA_IRQ(channel, ATA_activeDrive(channel)); //Execute an IRQ from us!
633 break;
634 case 0xDA: //Get media status?
635 dolog("ATA", "GETMEDIASTATUS:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
636 if (ATA_Drives[channel][ATA_activeDrive(channel)] >= CDROM0) //CD-ROM drive?
637 {
638 drive = ATA_Drives[channel][ATA_activeDrive(channel)]; //Load the drive identifier!
639 if (has_drive(drive)) //Drive inserted?
640 {
641 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.uncorrectabledata = drivereadonly(drive); //Are we read-only!
642 }
643 else
644 {
645 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.uncorrectabledata = 0; //Are we read-only!
646 }
647 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.mediachanged = 0; //Not anymore!
648 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 0; //Not an error!
649 ATA_IRQ(channel, ATA_activeDrive(channel)); //Raise IRQ!
650 ATA[channel].commandstatus = 0; //Reset status!
651 }
652 else goto invalidcommand;
653 break;
654 case 0xDC: //BIOS - post-boot?
655 case 0xDD: //BIOS - pre-boot?
656 case 0x50: //Format track?
657 case 0x97:
658 case 0xE3: //Idle?
659 case 0x95:
660 case 0xE1: //Idle immediate?
661 case 0x00: //NOP?
662 case 0xE4: //Read buffer?
663 case 0xC8: //Read DMA (w/retry)?
664 case 0xC9: //Read DMA (w/o retry)?
665 case 0xC4: //Read multiple?
666 case 0x40: //Read verify sector(s) (w/retry)?
667 case 0x41: //Read verify sector(s) (w/o retry)?
668 case 0xEF: //Set features?
669 case 0xC6: //Set multiple mode?
670 case 0x99:
671 case 0xE6: //Sleep?
672 case 0x96:
673 case 0xE2: //Standby?
674 case 0x94:
675 case 0xE0: //Standby immediate?
676 case 0xE8: //Write buffer?
677 case 0xCA: //Write DMA (w/retry)?
678 case 0xCB: //Write DMA (w/o retry)?
679 case 0xC5: //Write multiple?
680 case 0xE9: //Write same?
681 case 0x3C: //Write verify?
682 default: //Unknown command?
683 //Invalid command?
684 invalidcommand:
685 dolog("ATA", "INVALIDCOMMAND:%i,%i=%02X", channel, ATA_activeDrive(channel), command);
686 ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.data = 1; //Reset error register!
687 ATA[channel].commandstatus = 0xFF; //Move to error mode!
688 ATA_IRQ(channel, ATA_activeDrive(channel)); //Raise IRQ!
689 break;
690 }
691}
692
693void ATA_updateStatus(byte channel)
694{
695 switch (ATA[channel].commandstatus) //What command status?
696 {
697 case 0: //Ready for command?
698 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.busy = 0; //Not busy! You can write to the CBRs!
699 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveready = 1; //We're ready to process a command!
700 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.datarequestready = 0; //Not requesting data to transfer!
701 break;
702 case 1: //Transferring data IN?
703 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.busy = 0; //Not busy! You can write to the CBRs!
704 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveready = 1; //We're ready to process a command!
705 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.datarequestready = 1; //We're requesting data to transfer!
706 break;
707 case 2: //Transferring data OUT?
708 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.busy = 0; //Not busy! You can write to the CBRs!
709 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveready = 1; //We're ready to process a command!
710 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.datarequestready = 1; //We're requesting data to transfer!
711 break;
712 case 3: //Transferring result?
713 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.busy = 0; //Not busy! You can write to the CBRs!
714 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveready = 1; //We're ready to process a command!
715 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.datarequestready = 1; //We're requesting data to transfer!
716 break;
717 case 4: //Busy waiting?
718 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.busy = 1; //Busy! You can write to the CBRs!
719 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveready = 0; //We're ready to process a command!
720 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.datarequestready = 0; //We're requesting data to transfer!
721 break;
722 default: //Unknown?
723 case 0xFF: //Error?
724 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.busy = 0; //Not busy! You can write to the CBRs!
725 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.driveready = 1; //We're ready to process a command!
726 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.datarequestready = 0; //We're not requesting data to transfer!
727 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.error = 1; //Error!
728 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.correcteddata = 0; //Not corrected data!
729 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.index = 0;
730 break;
731 }
732}
733
734void ATA_writedata(byte channel, byte value)
735{
736 if (!ATA_Drives[channel][ATA_activeDrive(channel)]) //Invalid drive?
737 {
738 return; //OK!
739 }
740 switch (ATA[channel].commandstatus) //Current status?
741 {
742 case 2: //DATA OUT?
743 ATA_dataOUT(channel,value); //Read data!
744 break;
745 default: //Unknown status?
746 break;
747 }
748}
749
750byte outATA16(word port, word value)
751{
752 byte channel = 0; //What channel?
753 if (port != getPORTaddress(channel)) //Primary channel?
754 {
755 channel = 1; //Try secondary channel!
756 if (port != getPORTaddress(channel)) //Secondary channel?
757 {
758 return 0; //Not our port?
759 }
760 }
761 ATA_writedata(channel, (value&0xFF)); //Write the data low!
762 ATA_writedata(channel, ((value >> 8) & 0xFF)); //Write the data high!
763 return 1;
764}
765
766byte outATA8(word port, byte value)
767{
768 byte channel = 0; //What channel?
769 if ((port<getPORTaddress(channel)) || (port>getPORTaddress(channel)+0xD)) //Primary channel?
770 {
771 if ((port >= getControlPORTaddress(channel)) && (port <= getControlPORTaddress(channel)+1)) goto port3_write;
772 channel = 1; //Try secondary channel!
773 if ((port<getPORTaddress(channel)) || (port>getPORTaddress(channel) + 0xD)) //Secondary channel?
774 {
775 if ((port >= getControlPORTaddress(channel)) && (port <= getControlPORTaddress(channel) + 1)) goto port3_write;
776 return 0; //Not our port?
777 }
778 }
779 port -= getPORTaddress(channel); //Get the port from the base!
780 switch (port) //What port?
781 {
782 case 0: //DATA?
783 ATA_writedata(channel, value); //Write the data!
784 return 1;
785 break;
786 case 1: //Features?
787 //ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.features = value; //Use the set data! Ignore!
788 return 1; //OK!
789 break;
790 case 2: //Sector count?
791 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectorcount = value; //Set sector count!
792 return 1; //OK!
793 break;
794 case 3: //Sector number?
795 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectornumber = value; //Set sector number!
796 return 1; //OK!
797 break;
798 case 4: //Cylinder low?
799 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow = value; //Set cylinder low!
800 return 1; //OK!
801 break;
802 case 5: //Cylinder high?
803 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh = value; //Set cylinder high!
804 return 1; //OK!
805 break;
806 case 6: //Drive/head?
807 ATA[channel].activedrive = (value >> 4) & 1; //The active drive!
808 ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.drivehead = value; //Set drive head!
809 return 1; //OK!
810 break;
811 case 7: //Command?
812 ATA_executeCommand(channel,value); //Execute a command!
813 return 1; //OK!
814 break;
815 default: //Unsupported!
816 break;
817 }
818 return 0; //Safety!
819port3_write: //Special port #3?
820 port -= getControlPORTaddress(channel); //Get the port from the base!
821 if (!ATA_Drives[channel][ATA_activeDrive(channel)]) //Invalid drive?
822 {
823 return 1; //OK!
824 }
825 switch (port) //What port?
826 {
827 case 0: //Control register?
828 ATA[channel].DriveControlRegister.data = value; //Give the drive control register!
829 return 1; //OK!
830 break;
831 default: //Unsupported!
832 break;
833 }
834 return 0; //Unsupported!
835}
836
837void ATA_readdata(byte channel, byte *result)
838{
839 if (!ATA_Drives[channel][ATA_activeDrive(channel)])
840 {
841 *result = 0; //No result!
842 return; //Abort!
843 }
844 switch (ATA[channel].commandstatus) //Current status?
845 {
846 case 1: //DATA IN?
847 *result = ATA_dataIN(channel); //Read data!
848 break;
849 case 3: //Result IN?
850 *result = ATA_resultIN(channel); //Read result!
851 break;
852 default: //Unknown status?
853 *result = 0; //Unsupported for now!
854 break;
855 }
856}
857
858byte inATA16(word port, word *result)
859{
860 byte channel = 0; //What channel?
861 if (port!=getPORTaddress(channel)) //Primary channel?
862 {
863 channel = 1; //Try secondary channel!
864 if (port!=getPORTaddress(channel)) //Secondary channel?
865 {
866 return 0; //Not our port?
867 }
868 }
869 byte buffer;
870 word resultbuffer;
871 ATA_readdata(channel, &buffer); //Read the low data!
872 resultbuffer = buffer; //Load the low byte!
873 ATA_readdata(channel, &buffer); //Read the high data!
874 resultbuffer |= (buffer << 8); //Load the high byte!
875 *result = resultbuffer; //Set the result!
876 return 1;
877}
878
879byte inATA8(word port, byte *result)
880{
881 byte channel = 0; //What channel?
882 if ((port<getPORTaddress(channel)) || (port>getPORTaddress(channel) + 0xD)) //Primary channel?
883 {
884 if ((port >= getControlPORTaddress(channel)) && (port <= getControlPORTaddress(channel) + 1)) goto port3_read;
885 channel = 1; //Try secondary channel!
886 if ((port<getPORTaddress(channel)) || (port>getPORTaddress(channel) + 0xD)) //Secondary channel?
887 {
888 if ((port >= getControlPORTaddress(channel)) && (port <= getControlPORTaddress(channel) + 1)) goto port3_read;
889 return 0; //Not our port?
890 }
891 }
892 if (!ATA_Drives[channel][ATA_activeDrive(channel)]) //Invalid drive?
893 {
894 *result = 0; //Give 0: we're not present!
895 return 1; //OK!
896 }
897 port -= getPORTaddress(channel); //Get the port from the base!
898 switch (port) //What port?
899 {
900 case 0: //DATA?
901 ATA_readdata(channel, result); //Read the data!
902 return 1;
903 break;
904 case 1: //Error register?
905 *result = ATA[channel].Drive[ATA_activeDrive(channel)].ERRORREGISTER.data; //Error register!
906 return 1;
907 break;
908 case 2: //Sector count?
909 *result = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectorcount; //Get sector count!
910 return 1;
911 break;
912 case 3: //Sector number?
913 *result = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.sectornumber; //Get sector number!
914 return 1; //OK!
915 break;
916 case 4: //Cylinder low?
917 *result = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderlow; //Get cylinder low!
918 return 1; //OK!
919 break;
920 case 5: //Cylinder high?
921 *result = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.cylinderhigh; //Get cylinder high!
922 return 1; //OK!
923 break;
924 case 6: //Drive/head?
925 *result = ATA[channel].Drive[ATA_activeDrive(channel)].PARAMETERS.drivehead; //Get drive/head!
926 return 1; //OK!
927 break;
928 case 7: //Status?
929 ATA_updateStatus(channel); //Update the status register if needed!
930 ATA_removeIRQ(channel,ATA_activeDrive(channel)); //Acnowledge IRQ!
931 *result = ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.data; //Get status!
932 ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.drivewritefault = 0; //Reset write fault flag!
933 return 1; //OK!
934 break;
935 default: //Unsupported?
936 break;
937 }
938 return 0; //Unsupported!
939port3_read: //Special port #3?
940 port -= getControlPORTaddress(channel); //Get the port from the base!
941 if (!ATA_Drives[channel][ATA_activeDrive(channel)]) //Invalid drive?
942 {
943 *result = 0; //Give 0: we're not present!
944 return 1; //OK!
945 }
946 switch (port) //What port?
947 {
948 case 0: //Alternate status register?
949 ATA_updateStatus(channel); //Update the status register if needed!
950 *result = ATA[channel].Drive[ATA_activeDrive(channel)].STATUSREGISTER.data; //Get status!
951 return 1; //OK!
952 break;
953 case 1: //Drive address register?
954 *result = ATA[channel].DriveAddressRegister.data; //Give the data!
955 return 1; //OK!
956 break;
957 default: //Unsupported!
958 break;
959 }
960 return 0; //Unsupported!
961}
962
963byte CDROM_DiskChanged = 0;
964
965void ATA_DiskChanged(int disk)
966{
967 byte disk_ATA, disk_channel, disk_nr;
968 switch (disk) //What disk?
969 {
970 //Four disk numbers!
971 case HDD0:
972 disk_nr = 0;
973 break;
974 case HDD1:
975 disk_nr = 1;
976 break;
977 case CDROM0:
978 disk_nr = 2;
979 break;
980 case CDROM1:
981 disk_nr = 3;
982 break;
983 default: //Unsupported?
984 return; //Abort!
985 }
986 disk_channel = ATA_DrivesReverse[disk_nr][0]; //The channel of the disk!
987 disk_ATA = ATA_DrivesReverse[disk_nr][1]; //The master/slave of the disk!
988 if ((disk_nr >= 2) && CDROM_DiskChanged) //CDROM changed?
989 {
990 ATA[disk_channel].Drive[disk_ATA].ERRORREGISTER.mediachanged = 1; //We've changed media!
991 }
992 if ((disk_channel == 0xFF) || (disk_ATA == 0xFF)) return; //Not mounted!
993 uint_64 disk_size;
994 switch (disk)
995 {
996 case HDD0: //HDD0 changed?
997 case HDD1: //HDD1 changed?
998 case CDROM0: //CDROM0 changed?
999 case CDROM1: //CDROM1 changed?
1000 if (has_drive(disk)) //Do we even have this drive?
1001 {
1002 disk_size = disksize(disk); //Get the disk's size!
1003 disk_size >>= 9; //Get the disk size in sectors!
1004 ATA[disk_channel].Drive[disk_ATA].driveparams[0] = ((disk==CDROM0)||(disk==CDROM1))? ((2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0)):0x40; //Hard sectored, Fixed drive/CDROM drive!
1005 ATA[disk_channel].Drive[disk_ATA].driveparams[1] = ATA[disk_channel].Drive[disk_ATA].driveparams[54] = get_cylinders(disk_size); //1=Number of cylinders
1006 ATA[disk_channel].Drive[disk_ATA].driveparams[2] = ATA[disk_channel].Drive[disk_ATA].driveparams[55] = get_heads(disk_size); //3=Number of heads
1007 ATA[disk_channel].Drive[disk_ATA].driveparams[6] = ATA[disk_channel].Drive[disk_ATA].driveparams[56] = get_SPT(disk_size); //6=Sectors per track
1008 ATA[disk_channel].Drive[disk_ATA].driveparams[20] = 1; //One transfer at a time!
1009 ATA[disk_channel].Drive[disk_ATA].driveparams[21] = 1; //512 byte buffer!
1010 ATA[disk_channel].Drive[disk_ATA].driveparams[49] = 0x200; //LBA supported, DMA unsupported!
1011 ATA[disk_channel].Drive[disk_ATA].driveparams[53] = 1; //Using soft-sectoring!
1012 ATA[disk_channel].Drive[disk_ATA].driveparams[60] = (disk_size & 0xFFFF); //Number of addressable sectors, low word!
1013 ATA[disk_channel].Drive[disk_ATA].driveparams[61] = (disk_size >> 16); //Number of addressable sectors, high word!
1014 }
1015 else //Drive not inserted?
1016 {
1017 memset(ATA[disk_channel].Drive[disk_ATA].driveparams, 0, sizeof(ATA[disk_channel].Drive[disk_ATA].driveparams)); //Clear the information on the drive: it's non-existant!
1018 }
1019 break;
1020 default: //Unknown?
1021 break;
1022 }
1023}
1024
1025void initATA()
1026{
1027 initTicksHolder(&ATATicks);
1028 memset(&ATA, 0, sizeof(ATA)); //Initialise our data!
1029 memset(&IRQtimer, 0, sizeof(IRQtimer)); //Init timers!
1030 //We don't register a disk change handler, because ATA doesn't change disks when running!
1031 //8-bits ports!
1032 register_PORTIN(&inATA8);
1033 register_PORTOUT(&outATA8);
1034 //16-bits port!
1035 register_PORTINW(&inATA16);
1036 register_PORTOUTW(&outATA16);
1037
1038 //We don't implement DMA: this is done by our own DMA controller!
1039 //First, detect HDDs!
1040 memset(ATA_Drives, 0, sizeof(ATA_Drives)); //Init drives to unused!
1041 memset(ATA_DrivesReverse, 0, sizeof(ATA_DrivesReverse)); //Init reverse drives to unused!
1042 byte CDROM_channel = 1; //CDROM is the second channel by default!
1043 if (has_drive(HDD0)) //Have HDD0?
1044 {
1045 ATA_Drives[0][0] = HDD0; //Mount HDD0!
1046 if (has_drive(HDD1)) //Have HDD1?
1047 {
1048 ATA_Drives[0][1] = HDD1; //Mount HDD1!
1049 }
1050 }
1051 else if (has_drive(HDD1)) //Have HDD1?
1052 {
1053 ATA_Drives[0][0] = HDD1; //Mount HDD1!
1054 }
1055 else
1056 {
1057 CDROM_channel = 0; //Move CDROM to primary channel!
1058 }
1059 ATA_Drives[CDROM_channel][0] = CDROM0; //CDROM0 always present as master!
1060 ATA_Drives[CDROM_channel][1] = CDROM1; //CDROM1 always present as master!
1061 int i,j,k;
1062 int disk_reverse[4] = { HDD0,HDD1,CDROM0,CDROM1 }; //Our reverse lookup information values!
1063 for (i = 0;i < 4;i++) //Check all drives mounted!
1064 {
1065 ATA_DrivesReverse[i][0] = 0xFF; //Unassigned!
1066 ATA_DrivesReverse[i][1] = 0xFF; //Unassigned!
1067 for (j = 0;j < 2;j++)
1068 {
1069 for (k = 0;k < 2;k++)
1070 {
1071 if (ATA_Drives[j][k] == disk_reverse[i]) //Found?
1072 {
1073 ATA_DrivesReverse[i][0] = j;
1074 ATA_DrivesReverse[i][1] = k; //Load reverse lookup!
1075 }
1076 }
1077 }
1078 }
1079 //Now, apply the basic disk information (disk change/initialisation of parameters)!
1080 register_DISKCHANGE(HDD0, &ATA_DiskChanged);
1081 register_DISKCHANGE(HDD1, &ATA_DiskChanged);
1082 register_DISKCHANGE(CDROM0, &ATA_DiskChanged);
1083 register_DISKCHANGE(CDROM1, &ATA_DiskChanged);
1084 CDROM_DiskChanged = 0; //Init!
1085 ATA_DiskChanged(HDD0); //Init HDD0!
1086 ATA_DiskChanged(HDD1); //Init HDD1!
1087 ATA_DiskChanged(CDROM0); //Init HDD0!
1088 ATA_DiskChanged(CDROM1); //Init HDD1!
1089 CDROM_DiskChanged = 1; //We're changing when updating!
1090 memset(&PCI_IDE, 0, sizeof(PCI_IDE)); //Initialise to 0!
1091 register_PCI(&PCI_IDE, sizeof(PCI_IDE)); //Register the PCI data area!
1092 //Initialise our data area!
1093 PCI_IDE.DeviceID = 1;
1094 PCI_IDE.VendorID = 1; //DEVICEID::VENDORID: We're a ATA device!
1095 PCI_IDE.ProgIF = 0x80; //We use our own set interrupts and we're a parallel ATA controller!
1096
1097#ifdef WD_ATA
1098 PCI_IDE.BAR[0] = 0x300; //Single controller only!
1099#endif
1100}