Алгоритм чтения сектора с дискеты в PM
В портик такой-то кидаем то то
Ждем столько-то
забираем из портика такого-то.
А то я чего то разобраться не могу. =(
Напиши, кстати, что с предыдущем вопросом получилось.
Моя реализация:
long floppyTimeToTurnOff[2];
long floppyTimeToWork[2];
long floppyIsRotated[2];
long floppyState[2]; // 0 - stop 1 - wait 2 - run
char p0x3f2;
void updateFloppies() {
long a=0;
for (a=0;a<2;a++) {
if ((floppyState[a]==0) && (floppyIsRotated[a]==1)) {
if ((--floppyTimeToTurnOff[a]) < 0) {
p0x3f2 &= ~(1<<(a+4));
out(0x3f2, p0x3f2);
floppyIsRotated[a] = 0;
floppyTimeToTurnOff[a] = 40;
floppyTimeToWork[a] = 20;
}
}
if (floppyState[a]==1) {
if (!floppyIsRotated[a]) {
p0x3f2 |= 1<<(a+4);
out(0x3f2, p0x3f2);
floppyTimeToTurnOff[a] = 40;
}
if (floppyTimeToWork[a]>0) floppyTimeToWork[a]--;
}
}
}
long floppyInterruptHappened;
void floppyInterruptHandler() {
floppyInterruptHappened = 1;
out(0x20, 0x20);
}
void floppyWait(long a) {
while (floppyState[a]!=0);
floppyState[a] = 1;
while (floppyTimeToWork[a]>0);
while (floppyState[1-a]==2);
floppyState[a] = 2;
p0x3f2 = (p0x3f2 & (~3)) | a;
out(0x3f2, p0x3f2);
}
long floppyFind(long a, long cylinder, long head) {
floppyInterruptHappened = 0;
if ((in(0x3f4)&0x40) != 0) return -6;
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 0xf);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, head==0?a:a|4);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, cylinder);
while (floppyInterruptHappened == 0);
if ((in(0x3f4)&0x40) != 0) return -6;
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 0x8);
while ((in(0x3f4)&0x40) == 0);
while ((in(0x3f4)&0x80) == 0);
long st0 = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long pc = in(0x3f5);
if (((8+16+64+128)&st0)!=0) return -6;
if (pc!=cylinder) return -6;
return 0;
}
long floppyReadWrite9kb(long a, long cylinder, long head, long write) {
sti();
floppyWait(a);
long res = floppyFind(a, cylinder, head);
if (res<0) return res;
if ((in(0x3f4)&0x40) != 0) {
floppyState[a] = 0;
return -6;
}
if (write==0) {
out(0xb, 0x46);
out(0xc, 0x46);
} else {
out(0xb, 0x4a);
out(0xc, 0x4a);
}
out(0x5, 0);
out(0x5, 36);
out(0x4, 0);
out(0x4, 0);
out(0x81, 5);
out(0xa, 2);
floppyInterruptHappened = 0;
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, write==0?0x66:0x45);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, head==0?a:a|4);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, cylinder);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, head);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 1);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 2);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 18);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 0x1a);
while ((in(0x3f4)&0x80) == 0);
out(0x3f5, 0xff);
while (floppyInterruptHappened == 0);
while ((in(0x3f4)&0x80) == 0);
long st0 = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long st1 = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long st2 = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long c = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long h = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long r = in(0x3f5);
while ((in(0x3f4)&0x80) == 0);
long n = in(0x3f5);
floppyState[a] = 0;
if (((8+16+64+128)&st0)!=0) return -6;
return 0;
}
long initFloppy() {
writeString("Floppy initialization... ", 6);
out(0x70, 0x10);
floppyTypes = in(0x71);
writeString("fda: ", 14);
switch (floppyTypes>>4) {
case 0 : writeString("NO", 14); break;
case 1 : writeString("360kb", 14); break;
case 2 : writeString("1.2mb", 14); break;
case 3 : writeString("720kb", 14); break;
case 4 : writeString("1.44mb", 14); break;
}
writeString(" fdb: ", 14);
switch (floppyTypes&0xf) {
case 0 : writeString("NO", 14); break;
case 1 : writeString("360kb", 14); break;
case 2 : writeString("1.2mb", 14); break;
case 3 : writeString("720kb", 14); break;
case 4 : writeString("1.44mb", 14); break;
}
floppyState[0] = 0;
floppyState[1] = 0;
floppyIsRotated[0] = 0;
floppyIsRotated[1] = 0;
floppyTimeToTurnOff[0] = 40;
floppyTimeToTurnOff[1] = 40;
floppyTimeToWork[0] = 20;
floppyTimeToWork[1] = 20;
p0x3f2 = 0x0c;
if (bootDisk<2) {
p0x3f2 |= 1<<(bootDisk+4);
floppyIsRotated[bootDisk] = 1;
floppyTimeToWork[bootDisk] = 0;
}
writeString(" OK.\n", 2);
}
long floppyWrite(long descriptor, char* data, long size) {
unsigned long fsize = *(unsigned long*)(0x30000 + descriptor*0x40 + 0x8);
unsigned long nowPos = *(unsigned long*)(0x30000 + descriptor*0x40 + 0xc);
long floppy = *(unsigned char*)(0x30000 + descriptor*0x40 + 0x4);
if (nowPos+size>fsize) size = fsize-nowPos;
long ans = size;
while (size>0) {
long cyl = (nowPos/(512*18))/2;
long head = (nowPos/(512*18))%2;
long res = floppyReadWrite9kb(floppy, cyl, head, 0);
if (res<0) return res;
long pos = nowPos%(512*18);
long a;
for (a=pos;a<min(pos+size, 512*18);a++)
*(char*)(0x40000+a) = *(data++);
res = floppyReadWrite9kb(floppy, cyl, head, 1);
if (res<0) return res;
nowPos += min(size, 512*18-pos);
size -= min(size, 512*18-pos);
}
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = nowPos;
return ans;
}
long floppyRead(long descriptor, char* data, long size) {
unsigned long fsize = *(unsigned long*)(0x30000 + descriptor*0x40 + 0x8);
unsigned long nowPos = *(unsigned long*)(0x30000 + descriptor*0x40 + 0xc);
long floppy = *(unsigned char*)(0x30000 + descriptor*0x40 + 0x4);
if (nowPos+size>fsize) size = fsize-nowPos;
long ans = size;
while (size>0) {
long cyl = (nowPos/(512*18))/2;
long head = (nowPos/(512*18))%2;
long res = floppyReadWrite9kb(floppy, cyl, head, 0);
if (res<0) return res;
long pos = nowPos%(512*18);
long a;
for (a=pos;a<min(pos+size, 512*18);a++)
*(data++) = *(char*)(0x40000+a);
nowPos += min(size, 512*18-pos);
size -= min(size, 512*18-pos);
}
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = nowPos;
return ans;
}
long floppyReadLine(long descriptor, char* data, long size) {
unsigned long fsize = *(unsigned long*)(0x30000 + descriptor*0x40 + 0x8);
unsigned long nowPos = *(unsigned long*)(0x30000 + descriptor*0x40 + 0xc);
long floppy = *(unsigned char*)(0x30000 + descriptor*0x40 + 0x4);
if (nowPos+size>fsize) size = fsize-nowPos;
long ans = 0;
size--;
while (size>0) {
long cyl = (nowPos/(512*18))/2;
long head = (nowPos/(512*18))%2;
long res = floppyReadWrite9kb(floppy, cyl, head, 0);
if (res<0) return res;
long pos = nowPos%(512*18);
long a;
for (a=pos;a<min(pos+size, 512*18);a++) {
*(data++) = *(char*)(0x40000+a);
nowPos+=1;
ans++;
if (*(char*)(0x40000+a) == '\n') {
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = nowPos;
*(--data) = 0;
return ans;
}
}
size -= min(size, 512*18-pos);
}
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = nowPos;
*data = 0;
return ans;
}
long floppySetPosition(long descriptor, long mode, long value) {
unsigned long size = *(unsigned long*)(0x30000 + descriptor*0x40 + 0x8);
if (mode == 0) {
if (value>size) value = size;
if (value<0) value = 0;
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = value;
}
if (mode == 1) {
value = *(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) + (long)value;
if (value>size) value = size;
if (value<0) value = 0;
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = value;
}
if (mode == 2) {
value = size - value;
if (value>size) value = size;
if (value<0) value = 0;
*(unsigned long*)(0x30000 + descriptor*0x40 + 0xc) = value;
}
return 0;
}
Напиши, кстати, что с предыдущем вопросом получилось.
[/code]
Да чего то не решилсо я переходить на си.Как то роднее мне мнемоники ассемблера чем сишные кракозябры. Все просто. Может позже, когда организую нормальную страничную адресацию, перейду.
Вот например написал я программулинку на сях.
Как ее компильнуть и слинковать в бинарь, и как указать линкеру адрес по которому я буду ее грузить?
Я вообще в Си и его компиляторах разбираюсь как в танках =)
Юзаю Dev-C++ под виндами. Может чего другого скачать?
Я писал, когда учился в десятом классе. Защищенный режим, многозадачность, виртуальная память и файловая система на дискете. Потом постепенно забросил, когда посмотрел исходный код minix и увидел, насколько он лучше написан.
Вот например написал я программулинку на сях.
Как ее компильнуть и слинковать в бинарь, и как указать линкеру адрес по которому я буду ее грузить?
Я вообще в Си и его компиляторах разбираюсь как в танках =)
Юзаю Dev-C++ под виндами. Может чего другого скачать?
Про винду ничего не скажу, я все делал под линуксом с компилятором gcc и линковщиком ld.
При компиляции и линковке надо указать в опциях
1) не подключать стандартные библиотеки
2) использовать архитектуру i386 (иначе на современных компьютерах скомпилится код для x86_64 и требуемым образом работать не будет)
3) выбрать формат бинарника. Для ld можно задать произвольное расположение файлов и секций: http://www.math.utah.edu/docs/info/ld_3.html
Все конкретные опции я в предыдущей теме писал.
void floppyInterruptHandler() - должно вызываться прерыванием floppy дисковода после окончания каждой операции. IRQ6. Настраивается в IDT
void floppyWait(long a) - включить и ждать, пока мотор разгонится до нужной скорости. "а" - это номер дисковода (0/1)
long floppyFind(long a, long cylinder, long head) - поиск нужной дорожки
long floppyReadWrite9kb(long a, long cylinder, long head, long write) - чтение, либо запись 9-и килобайт (одна дорожка целиком). Для данных используется буффер по фиксированному адресу. Этот адрес задается строками
out(0x4, 0); // младшие биты
out(0x81, 5); // старшие биты
long initFloppy() - определение имеющихся дисководов при загрузке системы
Последующие функции можно не смотреть - они все работают через эти.