commit d8e9ce15597bd711c52fe3ac7b28a66dcba03cc6 Author: ha Date: Thu Oct 6 17:56:22 2005 +0000 Kolibri 5 initial checkout git-svn-id: svn://kolibrios.org@1 a494cfbc-eb01-0410-851d-a64ba20cac60 diff --git a/trunk/blkdev/cdrom.inc b/trunk/blkdev/cdrom.inc new file mode 100644 index 000000000..6f8903e95 --- /dev/null +++ b/trunk/blkdev/cdrom.inc @@ -0,0 +1,261 @@ +sys_cd_audio: + + cmp word [cdbase],word 0 + jnz @f + mov eax,1 + ret + @@: + + ; eax=1 cdplay at ebx 0x00FFSSMM + ; eax=2 get tracklist size of ecx to [ebx] + ; eax=3 stop/pause playing + + cmp eax,1 + jnz nocdp + call sys_cdplay + ret + nocdp: + + cmp eax,2 + jnz nocdtl + mov edi,[0x3010] + add edi,0x10 + add ebx,[edi] + call sys_cdtracklist + ret + nocdtl: + + cmp eax,3 + jnz nocdpause + call sys_cdpause + ret + nocdpause: + + mov eax,0xffffff01 + ret + + + +sys_cd_atapi_command: + + pushad + + mov dx,word [cdbase] + add dx,6 + mov ax,word [cdid] + out dx,al + mov esi,10 + call delay_ms + mov dx,word [cdbase] + add dx,7 + in al,dx + and al,0x80 + cmp al,0 + jnz res + jmp cdl6 + res: + mov dx,word [cdbase] + add dx,7 + mov al,0x8 + out dx,al + mov dx,word [cdbase] + add dx,0x206 + mov al,0xe + out dx,al + mov esi,1 + call delay_ms + mov dx,word [cdbase] + add dx,0x206 + mov al,0x8 + out dx,al + mov esi,30 + call delay_ms + xor cx,cx + cdl5: + inc cx + cmp cx,10 + jz cdl6 + mov dx,word [cdbase] + add dx,7 + in al,dx + and al,0x88 + cmp al,0x00 + jz cdl5 + mov esi,100 + call delay_ms + jmp cdl5 + cdl6: + mov dx,word [cdbase] + add dx,4 + mov al,0 + out dx,al + mov dx,word [cdbase] + add dx,5 + mov al,0 + out dx,al + mov dx,word [cdbase] + add dx,7 + mov al,0xec + out dx,al + mov esi,5 + call delay_ms + mov dx,word [cdbase] + add dx,1 + mov al,0 + out dx,al + add dx,1 + mov al,0 + out dx,al + add dx,1 + mov al,0 + out dx,al + add dx,1 + mov al,0 + out dx,al + add dx,1 + mov al,128 + out dx,al + add dx,2 + mov al,0xa0 + out dx,al + xor cx,cx + mov dx,word [cdbase] + add dx,7 + cdl1: + inc cx + cmp cx,100 + jz cdl2 + in al,dx + and ax,0x88 + cmp al,0x8 + jz cdl2 + mov esi,2 + call delay_ms + jmp cdl1 + cdl2: + + popad + ret + + +sys_cdplay: + + mov ax,5 + push ax + push ebx + cdplay: + call sys_cd_atapi_command + cli + mov dx,word [cdbase] + mov ax,0x0047 + out dx,ax + mov al,1 + mov ah,[esp+0] ; min xx + out dx,ax + mov ax,[esp+1] ; fr sec + out dx,ax + mov ax,256+99 + out dx,ax + mov ax,0x0001 + out dx,ax + mov ax,0x0000 + out dx,ax + mov esi,10 + call delay_ms + sti + add dx,7 + in al,dx + test al,1 + jz cdplayok + mov ax,[esp+4] + dec ax + mov [esp+4],ax + cmp ax,0 + jz cdplayfail + jmp cdplay + cdplayfail: + cdplayok: + pop ebx + pop ax + xor eax, eax + ret + + +sys_cdtracklist: + + push ebx + tcdplay: + call sys_cd_atapi_command + mov dx,word [cdbase] + mov ax,0x43+2*256 + out dx,ax + mov ax,0x0 + out dx,ax + mov ax,0x0 + out dx,ax + mov ax,0x0 + out dx,ax + mov ax,200 + out dx,ax + mov ax,0x0 + out dx,ax + in al,dx + mov cx,1000 + mov dx,word [cdbase] + add dx,7 + cld + cdtrnwewait: + mov esi,10 + call delay_ms + in al,dx + and al,128 + cmp al,0 + jz cdtrl1 + loop cdtrnwewait + cdtrl1: + ; read the result + mov ecx,[esp+0] + mov dx,word [cdbase] + cdtrread: + add dx,7 + in al,dx + and al,8 + cmp al,8 + jnz cdtrdone + sub dx,7 + in ax,dx + mov [ecx],ax + add ecx,2 + jmp cdtrread + cdtrdone: + pop ecx + xor eax, eax + ret + + +sys_cdpause: + + call sys_cd_atapi_command + + mov dx,word [cdbase] + mov ax,0x004B + out dx,ax + mov ax,0 + out dx,ax + mov ax,0 + out dx,ax + mov ax,0 + out dx,ax + mov ax,0 + out dx,ax + mov ax,0 + out dx,ax + + mov esi,10 + call delay_ms + add dx,7 + in al,dx + + xor eax, eax + ret + diff --git a/trunk/blkdev/fdc.inc b/trunk/blkdev/fdc.inc new file mode 100644 index 000000000..529f217a0 --- /dev/null +++ b/trunk/blkdev/fdc.inc @@ -0,0 +1,369 @@ +;### fdc.inc ### Menuetos floppy stuff. +;Version 0.2: Write individual tracks. / Sync ramdisk <-> floppy +;Version 0.1: Write full ramdisk to floppy. +;гloppyright Tolle. + +;depends on: +;restorefatchain +;memmove +;Int 6 (sys32.inc) should call fdc_irq func. +;The ramdisk should be at 0x100000 + +;Keeping track of the tracks. +iglobal + cylinder db 0 + sector db 1 + head db 0 + + ;Memory and dma variables. + fdcmem dd 0x100000 + cpymem dd 0x100000 + dmamem dd 0x100000 +endg + +uglobal + dmasize db 0x0 + dmamode db 0x0 +endg + +iglobal + ;function pointers. + fdc_irq_func dd fdc_null + fdc_pump_func dd fdc_null +endg + +uglobal + ;General stuff + fdc_st0 db 0 ;status register 0 of last resultphase. + fdc_mutex db 0 ;wait in line. (Block calling app) + fdc_callspending db 0 ;mystery sauce + fdc_settings dd 0 ;bitfield. +endg + ;Bit 0 enable direct file write [yes/no] + +fdc_set: ;ebx: fdc_settings bitfield. +mov [fdc_settings],ebx +ret + +fdc_get: ;returns fdc_settings in ecx +mov ecx, [fdc_settings] +ret + +fdc_init: ;start with clean tracks. + mov edi,0xD201 + mov al,0 + mov ecx,160 + rep stosb +ret + +fdc_filesave: ;ebx: cluster to be saved. + pusha ;returns immediately. does not trigger a write. + mov eax,ebx + add eax,31 + mov bl,18 + div bl + mov ah,0 + add eax,0xD201 + mov [eax],byte 1 ;This track is now dirty. + popa +ret + + +fdc_writeramdisk: ;mark all tracks as dirty. + mov edi,0xD201 + mov al,1 + mov ecx,160 + rep stosb + jmp fdc_commitflush +fdc_commitfile: ;flush dirty tracks to floppy + test [fdc_settings],1 ;...but only if this is really wanted by the user. + je fdc_commitend +fdc_commitflush: + cmp [fdc_callspending],5 + je fdc_commitend + inc [fdc_callspending] + cmp [fdc_callspending],1 + je fdc_commitonce + fdc_commitend: +ret + +fdc_commitonce: ;One at a time. + .stall: +cli + cmp [fdc_mutex],0 + jne .stallret + mov [fdc_mutex],1 + jmp .goahead + .stallret: +sti + jmp .stall + .goahead: +sti + +fdc_commitramdisk: + + call restorefatchain + ;Move the bootsector to a safe place. + mov eax,0x100000 + mov ebx,0xD000 + mov ecx,512 + call memmove + ;Always write the FAT table + mov eax,0xD201 + mov [eax],byte 1 + inc eax + mov [eax],byte 1 + + mov [dmamode],0x4A ;read from memory to floppy. + mov [dmasize],0x1 ;read 512 bytes sectors. + mov [fdc_irq_func],fdc_commitramdisk1 + call fdc_floppy_on ;start floppy A: moter starts interruptflow. + ret +fdc_commitramdisk1: + mov [fdc_irq_func],fdc_recalibrate_result + mov [fdc_pump_func],fdc_commitramdisk2 + call fdc_recalibrate ;retract the head to cylinder 0, sector 1 + ret +fdc_commitramdisk2: + mov[head],0 ;set variables. + mov[cylinder],0 + mov [sector],1 + mov[cpymem],0x102400 + mov [fdc_pump_func],fdc_fullpump + call fdc_write ;fdc_write will continue interruptflow +ret + +fdc_fullpump: + add [dmamem],512 + add [sector],1 + cmp [sector],19 + jne .clusterwrite + sub [dmamem],9216 + mov eax,[cpymem] + mov ebx,[fdcmem] + mov ecx,9216 + call memmove + add [cpymem],9216 + cmp [head],0 + je .nocylinderchange + add [cylinder],1 + .nocylinderchange: + xor [head],1 + cmp [cylinder],80 + jne .noendofwrite + mov[fdc_irq_func],fdc_complete + call fdc_floppy_off + call fdc_init + jmp .end + .noendofwrite: + mov [sector],1 + .clusterwrite: + xor eax,eax + mov al,[cylinder] + shl eax,1 + add al,[head] + add eax,0xD201 + mov bl,[eax] + cmp bl,1 + jne fdc_fullpump + call fdc_write + .end: +ret + +fdc_write: + call fdc_program_dma + call fdc_seek +ret + +fdc_seek: + mov al, 0x0f + call fdc_write_reg + mov al,[head] + shl al,2 + call fdc_write_reg + mov al,[cylinder] + call fdc_write_reg + mov [fdc_irq_func],fdc_seek_result +ret + +fdc_seek_result: + call fdc_sensei + cmp al,[cylinder] + je .succes + call fdc_seek + jmp .end + .succes: + call fdc_write_sector + .end: +ret + +fdc_write_sector: + mov al,0x45 ;write sector command +fdc_commandphase: + call fdc_write_reg + mov al,[head] + shl al,2 + call fdc_write_reg + mov al,[cylinder] + call fdc_write_reg + mov al,[head] + call fdc_write_reg + mov al,[sector] + call fdc_write_reg + mov al,2 ;Sector size (2 ~> 512 bytes) + call fdc_write_reg + mov al,18 ;last sector on track. + call fdc_write_reg + mov al,27 ;length of GAP3 + call fdc_write_reg + mov al,0xFF ;data length, ignored. + call fdc_write_reg + mov [fdc_irq_func],fdc_resultphase +ret + +fdc_resultphase: + call fdc_read_reg + mov [fdc_st0],al + mov cx,6 + .readresult: + call fdc_read_reg + loop .readresult + and [fdc_st0],11000000b + cmp [fdc_st0],byte 0 + jz .succes + call fdc_seek + jmp .end + .succes: + call [fdc_pump_func] + .end: +ret + +fdc_sensei: + mov al,0x08 ;get interrupt status command + call fdc_write_reg + call fdc_read_reg ;get result in al; + and al,0x80 + cmp al,0x80 + je fdc_sensei ;retry + call fdc_read_reg +ret + +fdc_program_dma: + mov al,0 + out 0x0c,al ; reset the flip-flop to a known state. + mov al,6 ; mask channel 2 so we can reprogram it. + out 0x0a,al + mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy + out 0x0b,al + mov al,0 + out 0x0c,al ; reset the flip-flop to a known state. + mov eax,[dmamem] + out 0x04,al ; set the channel 2 starting address to 0 + shr eax,8 + out 0x04,al + shr eax,8 + out 0x81,al + mov al,0 + out 0x0c, al ; reset flip-flop + mov al, 0xff ;set count (actual size -1) + out 0x5, al + mov al, [dmasize] ;(0x1ff = 511 / 0x23ff =9215) + out 0x5,al + mov al,2 + out 0xa,al +ret + +fdc_recalibrate: + mov al,0x07 ;calibrate command + call fdc_write_reg + mov al,0 ;select drive 0 + call fdc_write_reg +ret + +fdc_recalibrate_result: + mov al,0x08 ;get interrupt status command + call fdc_write_reg ;send it + call fdc_read_reg ;get command in al; + cmp al,0x80 + je fdc_recalibrate_result + mov ah,al + call fdc_read_reg + cmp ah,0x70 + jne .end + call fdc_recalibrate + jmp .reallyend + .end: + call [fdc_pump_func] + .reallyend: +ret + +fdc_busy: + .command_check: + mov dx,0x3F4 + in al,dx + and al,0x10 + cmp al,0x10 + je .command_check +ret + +fdc_read_reg: + status_check: + mov dx,0x3F4 + in al,dx + and al,0xc0 + cmp al,0xc0 + jne status_check + mov dx, 0x3F5 + in al, dx +ret + +fdc_write_reg: + mov bl,al + .command_check: + mov dx,0x3F4 + in al,dx + and al,0x80 + cmp al,0x80 + jne .command_check + mov al,bl + mov dx,0x3F5 + out dx,al +ret + +fdc_floppy_off: + mov al,0xC + mov dx,0x3f2 + out dx,al +ret + +fdc_floppy_on: + mov dx,0x3f2 + mov al,0x0 + out dx,al + mov al,0x1C + out dx,al + + mov eax,50 + call delay_hs +ret + +fdc_complete: + mov eax,0xD000 + mov ebx,0x100000 + mov ecx,512 + call memmove + + mov [fdc_irq_func],fdc_null + mov [fdc_mutex],0 + dec [fdc_callspending] + cmp [fdc_callspending],0 + je .realyend + mov [fdc_mutex],1 + call fdc_commitramdisk + .realyend: +ret + +fdc_irq: + call [fdc_irq_func] +fdc_null: +ret \ No newline at end of file diff --git a/trunk/blkdev/flp_drv.inc b/trunk/blkdev/flp_drv.inc new file mode 100644 index 000000000..0db9d1e85 --- /dev/null +++ b/trunk/blkdev/flp_drv.inc @@ -0,0 +1,685 @@ +;********************************************************** +; Непосредственная работа с контроллером гибкого диска +;********************************************************** +; Автор исходного текста Кулаков Владимир Геннадьевич. +; Адаптация и доработка Mario79 +fdd_read_and_write: + pusha +read_sector: + cmp eax,1 + jne write_sector + call save_HTS_values + call flp_readsector + call give_back_application_data + jmp fdd_read_end +write_sector: + cmp eax,2 + jne fdd_read_end + call save_HTS_values + call take_data_from_application + call flp_writesector +fdd_read_end: + popa + ret + +save_HTS_values: + mov [FDD_Sector],bl + mov [FDD_Head],bh + shr ebx,16 + mov [FDD_Track],bl + mov [FDD_Type],bh + ret + +give_back_application_data: ; переслать приложению + mov edi,[3010h] + mov edi,[edi+10h] + add edi,ecx +give_back_application_data_1: + mov esi,0xD000 ;FDD_DataBuffer ;0x40000 + xor ecx,ecx + mov cx,128 + cld + rep movsd + ret + +take_data_from_application: ; взять из приложения + mov esi,[3010h] + mov esi,[esi+10h] + add esi,ecx +take_data_from_application_1: + mov edi,0xD000 ;FDD_DataBuffer ;0x40000 + xor ecx,ecx + mov cx,128 + cld + rep movsd + ret + +flp_initialization: +; Установить новый обработчик прерывания НГМД + call SetUserInterrupts +; Включить мотор дисковода + call FDDMotorON +; Инициализировать переменные +; mov [FDD_Track],0 +; mov [FDD_Head],0 +; mov [FDD_Sector],1 +; Провести рекалибровку и поиск нулевой дорожки + call RecalibrateFDD + call SeekTrack + ret + +flp_readsector: + call flp_initialization +; Прочитать сектор + call ReadSectWithRetr +; call ReadSector +; cmp [FDC_Status],0 +; jne @@SectorNotFound + mov [fdc_irq_func],fdc_null +; call FDDMotorOFF + ret + +flp_writesector: + call flp_initialization +; Записать сектор + call WriteSectWithRetr +; call WriteSector +; cmp [FDC_Status],0 +; jne @@SectorNotFound + mov [fdc_irq_func],fdc_null +; call FDDMotorOFF + ret + +@@DiskNotFound: + ret +@@SectorNotFound: + ret + +; Коды завершения операции с контроллером (FDC_Status) +FDC_Normal equ 0 ;нормальное завершение +FDC_TimeOut equ 1 ;ошибка тайм-аута +FDC_DiskNotFound equ 2 ;в дисководе нет диска +FDC_TrackNotFound equ 3 ;дорожка не найдена +FDC_SectorNotFound equ 4 ;сектор не найден + +; Максимальные значения координат сектора (заданные +; значения соответствуют параметрам стандартного +; трехдюймового гибкого диска объемом 1,44 Мб) +MAX_Track equ 79 +MAX_Head equ 1 +MAX_Sector equ 18 + +; Счетчик тиков таймера +TickCounter dd ? +; Код завершения операции с контроллером НГМД +FDC_Status DB ? +; Флаг прерывания от НГМД +FDD_IntFlag DB ? +; Момент начала последней операции с НГМД +FDD_Time DD ? +; Номер дисковода +FDD_Type db 0 +; Координаты сектора +FDD_Track DB ? +FDD_Head DB ? +FDD_Sector DB ? + +; Блок результата операции +FDC_ST0 DB ? +FDC_ST1 DB ? +FDC_ST2 DB ? +FDC_C DB ? +FDC_H DB ? +FDC_R DB ? +FDC_N DB ? +; Счетчик повторения операции чтения +ReadRepCounter DB ? +; Счетчик повторения операции рекалибровки +RecalRepCounter DB ? +; Область памяти для хранения прочитанного сектора +;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?) +fdd_motor_status db 0 +timer_fdd_motor dd 0 + +;************************************* +;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД * +;************************************* +Init_FDC_DMA: + pushad + mov al,0 + out 0x0c,al ; reset the flip-flop to a known state. + mov al,6 ; mask channel 2 so we can reprogram it. + out 0x0a,al + mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy + out 0x0b,al + mov al,0 + out 0x0c,al ; reset the flip-flop to a known state. + mov eax,0xD000 + out 0x04,al ; set the channel 2 starting address to 0 + shr eax,8 + out 0x04,al + shr eax,8 + out 0x81,al + mov al,0 + out 0x0c, al ; reset flip-flop + mov al, 0xff ;set count (actual size -1) + out 0x5, al + mov al,0x1 ;[dmasize] ;(0x1ff = 511 / 0x23ff =9215) + out 0x5,al + mov al,2 + out 0xa,al + popad + ret + +;*********************************** +;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC * +;* Параметры: * +;* AL - выводимый байт. * +;*********************************** +FDCDataOutput: +; pusha + push ax cx dx + mov AH,AL ;запомнить байт в AH +; Сбросить переменную состояния контроллера + mov [FDC_Status],FDC_Normal +; Проверить готовность контроллера к приему данных + mov DX,3F4h ;(порт состояния FDC) + xor CX,CX ;установить счетчик тайм-аута +@@TestRS: + in AL,DX ;прочитать регистр RS + and AL,0C0h ;выделить разряды 6 и 7 + cmp AL,80h ;проверить разряды 6 и 7 + je @@OutByteToFDC + loop @@TestRS +; Ошибка тайм-аута + mov [FDC_Status],FDC_TimeOut + jmp @@End_5 +; Вывести байт в порт данных +@@OutByteToFDC: + inc DX + mov AL,AH + out DX,AL +@@End_5: +; popa + pop dx cx ax + ret + +;****************************************** +;* ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC * +;* Процедура не имеет входных параметров. * +;* Выходные данные: * +;* AL - считанный байт. * +;****************************************** +FDCDataInput: + push ECX + push DX +; Сбросить переменную состояния контроллера + mov [FDC_Status],FDC_Normal +; Проверить готовность контроллера к передаче данных + mov DX,3F4h ;(порт состояния FDC) + xor CX,CX ;установить счетчик тайм-аута +@@TestRS_1: + in AL,DX ;прочитать регистр RS + and AL,0C0h ;выдлить разряды 6 и 7 + cmp AL,0C0h ;проверить разряды 6 и 7 + je @@GetByteFromFDC + loop @@TestRS_1 +; Ошибка тайм-аута + mov [FDC_Status],FDC_TimeOut + jmp @@End_6 +; Ввести байт из порта данных +@@GetByteFromFDC: + inc DX + in AL,DX +@@End_6: pop DX + pop ECX + ret + +;********************************************* +;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД * +;********************************************* +FDCInterrupt: +; Разрешить прерывания +; sti +; push AX +; Установить флаг прерывания + mov [FDD_IntFlag],1 +; Послать команду EOI контроллеру прерываний +; mov AL,20h +; out 20h,AL +; pop AX + ret + + +;****************************************** +;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЙ * +;* НГМД * +;****************************************** +SetUserInterrupts: + mov [fdc_irq_func],FDCInterrupt + ret + +;******************************************* +;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД * +;******************************************* +WaitFDCInterrupt: + pusha +; Сбросить байт состояния операции + mov [FDC_Status],FDC_Normal +; Сбросить флаг прерывания + mov [FDD_IntFlag],0 +; Обнулить счетчик тиков + mov eax,[timer_ticks] + mov [TickCounter],eax +; Ожидать установки флага прерывания НГМД +@@TestRS_2: + cmp [FDD_IntFlag],0 + jnz @@End_7 ;прерывание произошло + mov eax,[timer_ticks] + sub eax,[TickCounter] + cmp eax,50 ;25 ;5 ;ожидать 5 тиков + jb @@TestRS_2 +; jl @@TestRS_2 +; Ошибка тайм-аута + mov [FDC_Status],FDC_TimeOut +; mov [flp_status],0 +@@End_7: popa + ret + +;********************************* +;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" * +;********************************* +FDDMotorON: + pusha +; cmp [fdd_motor_status],1 +; je fdd_motor_on + mov al,[flp_number] + cmp [fdd_motor_status],al + je fdd_motor_on +; Произвести сброс контроллера НГМД + mov DX,3F2h ;порт управления двигателями + mov AL,0 + out DX,AL +; Выбрать и включить мотор дисковода + cmp [flp_number],1 + jne FDDMotorON_B +; call FDDMotorOFF_B + mov AL,1Ch ; Floppy A + jmp FDDMotorON_1 +FDDMotorON_B: +; call FDDMotorOFF_A + mov AL,2Dh ; Floppy B +FDDMotorON_1: + out DX,AL +; Обнулить счетчик тиков + mov eax,[timer_ticks] + mov [TickCounter],eax +; Ожидать 0,5 с +@@dT: + mov eax,[timer_ticks] + sub eax,[TickCounter] + cmp eax,50 ;10 + jb @@dT + cmp [flp_number],1 + jne fdd_motor_on_B + mov [fdd_motor_status],1 + jmp fdd_motor_on +fdd_motor_on_B: + mov [fdd_motor_status],2 +fdd_motor_on: + call save_timer_fdd_motor + popa + ret + +;***************************************** +;* СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ * +;***************************************** +save_timer_fdd_motor: + mov eax,[timer_ticks] + mov [timer_fdd_motor],eax + ret + +;***************************************** +;* ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА * +;***************************************** +check_fdd_motor_status: + cmp [fdd_motor_status],0 + je end_check_fdd_motor_status + mov eax,[timer_ticks] + sub eax,[timer_fdd_motor] + cmp eax,500 + jb end_check_fdd_motor_status + call FDDMotorOFF + mov [fdd_motor_status],0 +end_check_fdd_motor_status: + ret + +;********************************** +;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА * +;********************************** +FDDMotorOFF: + push AX + push DX + cmp [flp_number],1 + jne FDDMotorOFF_1 + call FDDMotorOFF_A + jmp FDDMotorOFF_2 +FDDMotorOFF_1: + call FDDMotorOFF_B +FDDMotorOFF_2: + pop DX + pop AX + ; сброс флагов кеширования в связи с устареванием информации + mov [root_read],0 + mov [flp_fat],0 + ret + +FDDMotorOFF_A: + mov DX,3F2h ;порт управления двигателями + mov AL,0Ch ; Floppy A + out DX,AL + ret + +FDDMotorOFF_B: + mov DX,3F2h ;порт управления двигателями + mov AL,5h ; Floppy B + out DX,AL + ret + +;******************************* +;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" * +;******************************* +RecalibrateFDD: + pusha + call save_timer_fdd_motor +; Подать команду "Рекалибровка" + mov AL,07h + call FDCDataOutput + mov AL,00h + call FDCDataOutput +; Ожидать завершения операции + call WaitFDCInterrupt +; cmp [FDC_Status],0 +; je no_fdc_status_error +; mov [flp_status],0 +;no_fdc_status_error: + call save_timer_fdd_motor + popa + ret + +;***************************************************** +;* ПОИСК ДОРОЖКИ * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1). * +;* Результат операции заносится в FDC_Status. * +;***************************************************** +SeekTrack: + pusha + call save_timer_fdd_motor +; Подать команду "Поиск" + mov AL,0Fh + call FDCDataOutput + ; Передать байт номера головки/накопителя + mov AL,[FDD_Head] + shl AL,2 + call FDCDataOutput + ; Передать байт номера дорожки + mov AL,[FDD_Track] + call FDCDataOutput +; Ожидать завершения операции + call WaitFDCInterrupt + cmp [FDC_Status],FDC_Normal + jne @@Exit +; Сохранить результат поиска + mov AL,08h + call FDCDataOutput + call FDCDataInput + mov [FDC_ST0],AL + call FDCDataInput + mov [FDC_C],AL +; Проверить результат поиска + ; Поиск завершен? + test [FDC_ST0],100000b + je @@Err + ; Заданный трек найден? + mov AL,[FDC_C] + cmp AL,[FDD_Track] + jne @@Err + ; Номер головки совпадает с заданным? + mov AL,[FDC_ST0] + and AL,100b + shr AL,2 + cmp AL,[FDD_Head] + jne @@Err + ; Операция завершена успешно + mov [FDC_Status],FDC_Normal + jmp @@Exit +@@Err: ; Трек не найден + mov [FDC_Status],FDC_TrackNotFound +; mov [flp_status],0 +@@Exit: + call save_timer_fdd_motor + popa + ret + +;******************************************************* +;* ЧТЕНИЕ СЕКТОРА ДАННЫХ * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции чтения * +;* содержимое сектора будет занесено в FDD_DataBuffer. * +;******************************************************* +ReadSector: + pushad + call save_timer_fdd_motor +; Установить скорость передачи 500 Кбайт/с + mov AX,0 + mov DX,03F7h + out DX,AL +; Инициализировать канал прямого доступа к памяти + mov [dmamode],0x46 + call Init_FDC_DMA +; Подать команду "Чтение данных" + mov AL,0E6h ;чтение в мультитрековом режиме + call FDCDataOutput + mov AL,[FDD_Head] + shl AL,2 + call FDCDataOutput + mov AL,[FDD_Track] + call FDCDataOutput + mov AL,[FDD_Head] + call FDCDataOutput + mov AL,[FDD_Sector] + call FDCDataOutput + mov AL,2 ;код размера сектора (512 байт) + call FDCDataOutput + mov AL,18 ;+1; 3Fh ;число секторов на дорожке + call FDCDataOutput + mov AL,1Bh ;значение GPL + call FDCDataOutput + mov AL,0FFh ;значение DTL + call FDCDataOutput + +; Ожидаем прерывание по завершении операции + call WaitFDCInterrupt + cmp [FDC_Status],FDC_Normal + jne @@Exit_1 +; Считываем статус завершения операции + call GetStatusInfo + test [FDC_ST0],11011000b + jnz @@Err_1 + mov [FDC_Status],FDC_Normal + jmp @@Exit_1 +@@Err_1: mov [FDC_Status],FDC_SectorNotFound +; mov [flp_status],0 +@@Exit_1: + call save_timer_fdd_motor + popad + ret + +;******************************************************* +;* ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции чтения * +;* содержимое сектора будет занесено в FDD_DataBuffer. * +;******************************************************* +ReadSectWithRetr: + pusha +; Обнулить счетчик повторения операции рекалибровки + mov [RecalRepCounter],0 +@@TryAgain: +; Обнулить счетчик повторения операции чтения + mov [ReadRepCounter],0 +@@ReadSector_1: + call ReadSector + cmp [FDC_Status],0 + je @@Exit_2 + cmp [FDC_Status],1 + je @@Err_3 + ; Троекратное повторение чтения + inc [ReadRepCounter] + cmp [ReadRepCounter],3 + jb @@ReadSector_1 + ; Троекратное повторение рекалибровки + call RecalibrateFDD + call SeekTrack + inc [RecalRepCounter] + cmp [RecalRepCounter],3 + jb @@TryAgain +; mov [flp_status],0 +@@Exit_2: + popa + ret +@@Err_3: + mov [flp_status],0 + popa + ret + +;******************************************************* +;* ЗАПИСЬ СЕКТОРА ДАННЫХ * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции записи * +;* содержимое FDD_DataBuffer будет занесено в сектор. * +;******************************************************* +WriteSector: + pushad + call save_timer_fdd_motor +; Установить скорость передачи 500 Кбайт/с + mov AX,0 + mov DX,03F7h + out DX,AL +; Инициализировать канал прямого доступа к памяти + mov [dmamode],0x4A + call Init_FDC_DMA +; Подать команду "Запись данных" + mov AL,0xC5 ;0x45 ;запись в мультитрековом режиме + call FDCDataOutput + mov AL,[FDD_Head] + shl AL,2 + call FDCDataOutput + mov AL,[FDD_Track] + call FDCDataOutput + mov AL,[FDD_Head] + call FDCDataOutput + mov AL,[FDD_Sector] + call FDCDataOutput + mov AL,2 ;код размера сектора (512 байт) + call FDCDataOutput + mov AL,18; 3Fh ;число секторов на дорожке + call FDCDataOutput + mov AL,1Bh ;значение GPL + call FDCDataOutput + mov AL,0FFh ;значение DTL + call FDCDataOutput + +; Ожидаем прерывание по завершении операции + call WaitFDCInterrupt + cmp [FDC_Status],FDC_Normal + jne @@Exit_3 +; Считываем статус завершения операции + call GetStatusInfo + test [FDC_ST0],11000000b ;11011000b + jnz @@Err_2 + mov [FDC_Status],FDC_Normal + jmp @@Exit_3 +@@Err_2: mov [FDC_Status],FDC_SectorNotFound +@@Exit_3: + call save_timer_fdd_motor + popad + ret + +;******************************************************* +;* ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции записи * +;* содержимое FDD_DataBuffer будет занесено в сектор. * +;******************************************************* +WriteSectWithRetr: + pusha +; Обнулить счетчик повторения операции рекалибровки + mov [RecalRepCounter],0 +@@TryAgain_1: +; Обнулить счетчик повторения операции чтения + mov [ReadRepCounter],0 +@@WriteSector_1: + call WriteSector + cmp [FDC_Status],0 + je @@Exit_4 + cmp [FDC_Status],1 + je @@Err_4 + ; Троекратное повторение чтения + inc [ReadRepCounter] + cmp [ReadRepCounter],3 + jb @@WriteSector_1 + ; Троекратное повторение рекалибровки + call RecalibrateFDD + call SeekTrack + inc [RecalRepCounter] + cmp [RecalRepCounter],3 + jb @@TryAgain_1 +@@Exit_4: + popa + ret +@@Err_4: + mov [flp_status],0 + popa + ret + +;********************************************* +;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ * +;********************************************* +GetStatusInfo: + push AX + call FDCDataInput + mov [FDC_ST0],AL + call FDCDataInput + mov [FDC_ST1],AL + call FDCDataInput + mov [FDC_ST2],AL + call FDCDataInput + mov [FDC_C],AL + call FDCDataInput + mov [FDC_H],AL + call FDCDataInput + mov [FDC_R],AL + call FDCDataInput + mov [FDC_N],AL + pop AX + ret + diff --git a/trunk/blkdev/rd.inc b/trunk/blkdev/rd.inc new file mode 100644 index 000000000..6e0e1e9ae --- /dev/null +++ b/trunk/blkdev/rd.inc @@ -0,0 +1,446 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; RAMDISK functions ;; +;; (C) 2004 Ville Turjanmaa, License: GPL ;; +;; Addings by M.Lisovin ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +ramdisk_free_space: +;--------------------------------------------- +; +; returns free space in edi +; rewr.by Mihasik +;--------------------------------------------- + + push eax ebx ecx + + mov edi,0x280000 ;start of FAT + xor ax,ax ;Free cluster=0x0000 in FAT + xor ebx,ebx ;counter + mov ecx,2847 ;2849 ;2849 clusters + cld + rdfs1: + repne scasw + jnz rdfs2 ;if last cluster not 0 + inc ebx + jcxz rdfs2 ;if last cluster=0 + jmp rdfs1 ;if not last + rdfs2: + shl ebx,9 ;free clusters*512 + mov edi,ebx + + pop ecx ebx eax + ret + + +expand_filename: +;--------------------------------------------- +; +; exapand filename with '.' to 11 character +; eax - pointer to filename +;--------------------------------------------- + + push esi edi ebx + + mov edi,esp ; check for '.' in the name + add edi,12+8 + + mov esi,eax + + mov eax,edi + mov [eax+0],dword ' ' + mov [eax+4],dword ' ' + mov [eax+8],dword ' ' + + flr1: + + cmp [esi],byte '.' + jne flr2 + mov edi,eax + add edi,7 + jmp flr3 + + flr2: + + mov bl,[esi] + mov [edi],bl + + flr3: + + inc esi + inc edi + + mov ebx,eax + add ebx,11 + + cmp edi,ebx + jbe flr1 + + pop ebx edi esi + ret + +fileread: +;---------------------------------------------------------------- +; +; fileread - sys floppy +; +; eax points to filename 11 chars +; ebx first wanted block ; 1+ ; if 0 then set to 1 +; ecx number of blocks to read ; 1+ ; if 0 then set to 1 +; edx mem location to return data +; esi length of filename 12*X 0=root +; +; ret ebx = size or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- + test ebx,ebx ;if ebx=0 - set to 1 + jnz frfl5 + inc ebx + frfl5: + test ecx,ecx ;if ecx=0 - set to 1 + jnz frfl6 + inc ecx + frfl6: + test esi,esi ; return ramdisk root + jnz fr_noroot ;if not root + cmp ebx,14 ;14 clusters=root dir + ja oorr + cmp ecx,14 + ja oorr + jmp fr_do + oorr: + mov eax,5 ;out of root range (fnf) + xor ebx,ebx + dec ebx ;0xffffffff + ret + + fr_do: ;reading rootdir + mov edi,edx + dec ebx + push edx + mov edx,ecx + add edx,ebx + cmp edx,14 ;ebx+ecx=14 + pushf + jbe fr_do1 + sub edx,14 + sub ecx,edx + fr_do1: + shl ebx,9 + mov esi,0x100000+512*19 + add esi,ebx + shl ecx,7 + cld + rep movsd + popf + pop edx +; jae fr_do2 + xor eax,eax ; ok read + xor ebx,ebx + ret + fr_do2: ;if last cluster + mov eax,6 ;end of file + xor ebx,ebx + ret + + fr_noroot: + + sub esp,32 + call expand_filename + + dec ebx + + push eax + + push eax ebx ecx edx esi edi + call rd_findfile + je fifound + add esp,32+28 ;if file not found + ret + + fifound: + + mov ebx,[edi-11+28] ;file size + mov [esp+20],ebx + mov [esp+24],ebx + add edi,0xf + movzx eax,word [edi] + mov edi,eax ;edi=cluster + + frnew: + + add eax,31 ;bootsector+2*fat+filenames + shl eax,9 ;*512 + add eax,0x100000 ;image base + mov ebx,[esp+8] + mov ecx,512 ;[esp+4] + + cmp [esp+16],dword 0 ; wanted cluster ? + jne frfl7 + call memmove + add [esp+8],dword 512 + dec dword [esp+12] ; last wanted cluster ? + cmp [esp+12],dword 0 + je frnoread + jmp frfl8 + frfl7: + dec dword [esp+16] + frfl8: + shl edi,1 ;find next cluster from FAT + add edi,0x280000 + movzx eax,word [edi] + mov edi,eax + cmp edi,4095 ;eof - cluster + jz frnoread2 + + cmp [esp+24],dword 512 ;eof - size + jb frnoread + sub [esp+24],dword 512 + + jmp frnew + + frnoread2: + + cmp [esp+16],dword 0 ; eof without read ? + je frnoread + + pop edi esi edx ecx + add esp,4 + pop ebx ; ebx <- eax : size of file + add esp,36 + mov eax,6 ; end of file + ret + + frnoread: + + pop edi esi edx ecx + add esp,4 + pop ebx ; ebx <- eax : size of file + add esp,36 + xor eax,eax ;read ok + ret + +filedelete: +;-------------------------------------------- +; +; filedelete - sys floppy +; in: +; eax - pointer to filename 11 chars +; +; out: +; eax - 0 = successful, 5 = file not found +; +;-------------------------------------------- + + sub esp,32 + call expand_filename + + push eax ebx ecx edx esi edi + + call rd_findfile + je fifoundd + pop edi esi edx ecx ebx eax ;file not found + add esp,32 + mov eax,5 + ret + + fifoundd: + + mov [edi-11],byte 0xE5 ;mark filename deleted + add edi,0xf + movzx eax,word [edi] + mov edi,eax ;edi = cluster + + frnewd: + + shl edi,1 ;find next cluster from FAT + add edi,0x280000 + movzx eax,word [edi] + mov [edi],word 0x0 ;clear fat chain cluster + mov edi,eax + cmp edi,dword 0xff8 ;last cluster ? + jb frnewd + + pop edi esi edx ecx ebx eax + add esp,32 + xor eax,eax ; file found + ret + + + +filesave: +;---------------------------------------------------------- +; +; filesave - sys floppy +; +; eax points to filename 11 chars +; +; eax ; pointer to file name +; ebx ; buffer +; ecx ; count to write in bytes +; edx ; 0 create new , 1 append +; +;----------------------------------------------------------- + + sub esp,32 + call expand_filename + test edx,edx + jnz fsdel + pusha + call filedelete + popa + + fsdel: + + call ramdisk_free_space + cmp ecx,edi + jbe rd_do_save + add esp,32 + mov eax,8 ;disk full + ret + + rd_do_save: + + push eax ebx ecx edx esi edi + + mov edi,0x100000+512*18+512 ;Point at directory + mov edx,224 +1 + ; find an empty spot for filename in the root dir + l20ds: + dec edx + test edx,edx + jz frnoreadds + l21ds: + cmp [edi],byte 0xE5 + jz fifoundds + cmp [edi],byte 0x0 + jz fifoundds + add edi,32 ; Advance to next entry + jmp l20ds + fifoundds: + + push edi ; move the filename to root dir + mov esi,[esp+4+20] + mov ecx,11 + cld + rep movsb + pop edi + mov edx,edi + add edx,11+0xf ; edx <- cluster save position + mov ebx,[esp+12] ; save file size + mov [edi+28],ebx + mov [edi+11],byte 0x20 ; attribute +; Ivan Poddubny 11/12/2003: +call get_date_for_file ; from FAT32.INC +mov [edi+24],ax ; date +call get_time_for_file ; from FAT32.INC +mov [edi+22],ax ; time +; End + mov edi,0x280000 ;pointer to first cluster + mov ecx,2849 + cld + frnewds: + xor ax,ax + repne scasw + mov ebx,2848 + sub ebx,ecx + mov [edx],bx ; save next cluster pos. to prev cl. + mov edx,edi ; next save pos abs mem add + dec edx + dec edx + call fdc_filesave + pusha ; move save to floppy cluster + add ebx,31 + shl ebx,9 + add ebx,0x100000 + mov eax,[esp+32+16] + mov ecx,512 + call memmove + popa + + mov eax,[esp+12] + cmp eax,512 + jb flnsa + sub eax,512 + mov [esp+12],eax + mov eax,[esp+16] + add eax,512 + mov [esp+16],eax + jmp frnewds + + flnsa: + dec edi + dec edi + mov [edi],word 4095 ; mark end of file - last cluster + + frnoreadds: + + pop edi esi edx ecx ebx eax + add esp,32 + + pusha + cli + call fdc_commitfile + sti + popa + + xor eax,eax ;ok write + ret + + rd_findfile: + ;by Mihasik + ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx + + mov edi,0x100000+512*18+512 ;Point at directory + cld + rd_newsearch: + mov esi,eax + mov ecx,11 + rep cmpsb + je rd_ff + add cl,21 + add edi,ecx + cmp edi,0x100000+512*33 + jb rd_newsearch + mov eax,5 ;if file not found - eax=5 + xor ebx,ebx + dec ebx ;ebx=0xffffffff and zf=0 + rd_ff: + ret + + rd_getfileinfo: + ;get date, time, size or attributes of file + ;IN: eax - pointer to file, ebx - type of function: 12-get filesize, 13-get fileattr, 14-get filedate + ;ecx - filelengh 0=root + ;OUT: eax=0 - Ok or 5 - file not found ebx - date/time, size or attributes + test ecx,ecx + jnz no_getfinfo_root + mov eax,5 ;if root - fnf + xor ebx,ebx + dec ebx + ret + no_getfinfo_root: ;if not root + sub esp,32 + call expand_filename + call rd_findfile + je fifoundi + add esp,32 ;if file not found + ret + fifoundi: + cmp ebx,13 + jne no_rd_attr + movzx ebx,byte [edi] ;get attributes + jmp rd_getfileinfo_end + no_rd_attr: + cmp ebx,14 + jne no_rd_date + mov ebx,dword [edi+11] ;get date/time + jmp rd_getfileinfo_end + no_rd_date: + mov ebx,dword [edi+17] ;get size + rd_getfileinfo_end: + xor eax,eax + add esp,32 + ret diff --git a/trunk/blkdev/rdsave.inc b/trunk/blkdev/rdsave.inc new file mode 100644 index 000000000..abfa8963b --- /dev/null +++ b/trunk/blkdev/rdsave.inc @@ -0,0 +1,26 @@ + cmp eax,6 ; SAVE FLOPPY IMAGE (HD version only) + jnz nosaveimage + cmp ebx,1 + jnz img_save_hd_1 + mov edx,bootpath ; path = '/KOLIBRI ' + jmp img_save_hd_3 + img_save_hd_1: + cmp ebx,2 + jnz img_save_hd_2 + mov edx,bootpath2 ; path = 0 (root dir) + jmp img_save_hd_3 + img_save_hd_2: + cmp ebx,3 + jnz exit_for_anyone + mov edx,[3010h] + mov edx,[edx+10h] + add edx,ecx + img_save_hd_3: + call restorefatchain ; restore FAT !!! + mov eax,image_save + mov ebx,1440*1024 ; size 1440 Kb + mov ecx,0x100000 ; address of image + call file_write + ret + + nosaveimage: diff --git a/trunk/boot/bootcode.inc b/trunk/boot/bootcode.inc new file mode 100644 index 000000000..e628adbef --- /dev/null +++ b/trunk/boot/bootcode.inc @@ -0,0 +1,917 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; BOOTCODE.INC ;; +;; ;; +;; 16 bit bootcode for MenuetOS ;; +;; ;; +;; Copyright 2002 Ville Turjanmaa ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +;========================================================================== +; +; 16 BIT FUNCTIONS +; +;========================================================================== + +print: push si + mov si,leftpr-0x10000 + call printplain + pop si + +printplain: pusha + mov dx,0x1000 + mov es,dx + cmp byte [es:display_atboot-0x10000],2 + je printplain_exit + mov ds,dx + cld + lodsb + prpl1: + mov ah,0xe + xor bh,bh + int 0x10 + lodsb + cmp al,0 + jne prpl1 + printplain_exit: + popa + ret + +setbase1000: push ax + mov ax,0x1000 + mov es,ax + mov ds,ax + pop ax + ret + +getkey: push ecx + push edx + add ebx,0x0101 + xor eax,eax + + gk1: + in al,0x60 + mov cl,al + gk0: + in al,0x60 + cmp al,cl + je gk0 + cmp ax,11 + jg gk0 + gk0_1: + mov cl,al + +; add al,47 +; mov [ds:keyinbs-0x10000],al +; mov si,keyinbs-0x10000 +; call printplain + + gk12: + in al,0x60 + cmp al,cl + je gk12 + cmp ax,240 + jne gk13 + mov al,cl + jmp gk14 + gk13: + add cl,128 + cmp al,cl + jne gk1 + sub al,128 + gk14: + + movzx edx,bl + cmp eax,edx + jb gk1 + movzx edx,bh + cmp eax,edx + jg gk1 + test ebx,0x010000 + jnz gk3 + mov cx,0x1000 + mov dx,cx + add eax,47 + mov cx,ax + cmp cx,58 + jb gk_nozero + sub cx,10 + gk_nozero: + mov [ds:keyin-0x10000],cl + mov si,keyin-0x10000 + call printplain + gk3: + sub eax,48 + pop edx + pop ecx + ret + + +;========================================================================= +; +; 16 BIT CODE +; +;========================================================================= + + +start_of_code: + +; RESET 16 BIT SELECTORS/REGISTERS/STACK + + mov ax,0x1000 + mov es,ax + mov ds,ax + + mov ax,0x2000 + mov ss,ax + mov sp,0xffff + + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + xor si,si + xor di,di + xor bp,bp + + + +; DRAW FRAMES + + call setbase1000 + + cmp byte [es:display_atboot-0x10000],2 + je no_mode_atboot + + mov ax,0x0003 + mov bx,0x0000 + mov dx,0x0000 + int 0x10 + + no_mode_atboot: + + ; Load & set russian VGA font (RU.INC) + mov bp,RU_FNT1-10000h ; RU_FNT1 - First part + mov bx,1000h ; 768 bytes + mov cx,30h ; 48 symbols + mov dx,80h ; 128 - position of first symbol + mov ax,1100h + push cs + pop es + int 10h + + mov bp,RU_FNT2-10000h ; RU_FNT2 -Second part + mov bx,1000h ; 512 bytes + mov cx,20h ; 32 symbols + mov dx,0E0h ; 224 - position of first symbol + mov ax,1100h + push cs + pop es + int 10h + ; End set VGA russian font + + call setbase1000 + mov ax,0xb800 + mov es,ax + mov di,0 + mov si,d80x25-0x10000 + mov cx,80*25 + mov ah,1*16+15 + dfl1: + cld + lodsb + stosw + loop dfl1 + + call setbase1000 + + +; SAY HI TO USER + + mov si,linef2-0x10000 + call printplain + mov si,version-0x10000 + call print + + +; TEST FOR 386+ + + pushf + pop ax + mov dx,ax + xor ax,0x4000 + push ax + popf + pushf + pop ax + and ax,0x4000 + and dx,0x4000 + cmp ax,dx + jnz cpugood + mov si,not386-0x10000 + call print + jmp $ + cpugood: + +; RESET 32 BIT SELECTORS/REGISTERS/SELECTORS + + mov ax,0x1000 + mov es,ax + mov ds,ax + + mov ax,0x2000 + mov ss,ax + mov esp,0xffff + + xor eax,eax + xor ebx,ebx + xor ecx,ecx + xor edx,edx + xor esi,esi + xor edi,edi + xor ebp,ebp + + + +; FLUSH 8042 KEYBOARD CONTROLLER + +;// mike.dld [ + ; mov al,0xED + ; out 0x60,al + ; or cx,-1 + ; @@: + ; in al,0x64 + ; test al,2 + ; jz @f + ; loop @b + ; @@: + ; mov al,0 + ; out 0x60,al + ; or cx,-1 + ; @@: + ; in al,0x64 + ; test al,2 + ; jz @f + ; loop @b + ; @@: +;// mike.dld ] + +; mov ecx,10000 +; fl1: +; in al,0x64 +; loop fl1 +; test al,1 +; jz fl2 +; in al,0x60 +; jmp fl1 +; fl2: + +;**************************************************************** +; The function is modified Mario79 +;***************************************************************** +; wait_kbd: ; variant 1 +; mov cx,2500h ;чрфхЁцър яюЁ фър 10 ьёхъ +; test_kbd: +; in al,64h ;ўшЄрхь ёюёЄю эшх ъыртшрЄєЁ√ +; test al,2 ;яЁютхЁър сшЄр уюЄютэюёЄш +; loopnz test_kbd + + mov al,0xf6 ; ╤сЁюё ъыртшрЄєЁ√, ЁрчЁх°шЄ№ ёърэшЁютрэшх + out 0x60,al + mov cx,0 +wait_loop: ; variant 2 +; reading state of port of 8042 controller + in al,64h + and al,00000010b ; ready flag +; wait until 8042 controller is ready + loopnz wait_loop + +; DISPLAY VESA INFORMATION + + mov ax,0x0 + mov es,ax + mov ax,0x4f00 + mov di,0xa000 + int 0x10 + cmp ax,0x004f + je vesaok2 + mov dx,0x1000 + mov es,dx + mov si,novesa-0x10000 + call print + mov ax,16 + jmp novesafound + vesaok2: + mov ax,[es:di+4] + mov dx,ax + add ax,'0'*256+'0' + push word 0x1000 + pop es + mov [es:vervesa+vervesa_off-0x10000], ah + mov [es:vervesa+vervesa_off+2-0x10000], al + ; ivan 24/11/2004 begin + ;push ax + ; ivan 24/11/2004 end + mov si,vervesa-0x10000 + call print + novesafound: + call setbase1000 + ; ivan 24/11/2004 begin + ;pop bx + ; ivan 24/11/2004 end + + +; ASK GRAPHICS MODE + + movzx eax,byte [es:preboot_graph-0x10000] + cmp eax,0 + jne pre_graph + mov si,gr_mode-0x10000 + call printplain + gml0: + mov ebx,0x0A01 + call getkey + pre_graph: + cmp eax,1 + jl sgml1 + cmp eax,8 + jg sgml1 + mov si,ax + sub si,1 + shl si,4 + add si,gr_table-0x10000 + mov bx,[es:si+0] + mov cx,[es:si+4] + mov dx,[es:si+8] + jmp gml10 + sgml1: + cmp al,9 + jnz gml00 + mov bx,0x13 + mov cx,640 + mov dx,480 + push word 0x0 + pop es + mov [es:0x9000],byte 32 + mov dword [es:0x9018],0x800000 + push word 0x1000 + pop es + jmp gml10 + gml00: + cmp al,0xa + jnz gml02 + mov bx,0x12 + mov cx,640 + mov dx,480 + push word 0x0 + pop es + mov [es:0x9000],byte 32 + mov dword [es:0x9018],0x800000 + push word 0x1000 + pop es + jmp gml10 + gml02: + jmp gml0 + gr_table: + dd 0x112+0100000000000000b , 640 , 480 , 0 + dd 0x115+0100000000000000b , 800 , 600 , 0 + dd 0x118+0100000000000000b , 1024 , 768 , 0 + dd 0x11B+0100000000000000b , 1280 , 1024 , 0 + dd 0x112 , 640 , 480 , 0 + dd 0x115 , 800 , 600 , 0 + dd 0x118 , 1024 , 768 , 0 + dd 0x11B , 1280 ,1024 , 0 + gml10: + push word 0x0000 + pop es + mov [es:0x9008],bx + mov [es:0x900A],cx + mov [es:0x900C],dx + push word 0x1000 + pop es + mov ax,32 + cmp bx,0x13 + je nov + cmp bx,0x12 + je nov + + +; USE DEFAULTS OR PROBE + +; bx - mode : cx - x size : dx - y size + + ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + movzx ax,[es:preboot_gprobe-0x10000] + test ax,ax + jne pre_probe + ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + test bx,0100000000000000b + jz noprobe + + mov si,probetext-0x10000 + call printplain + push bx + mov ebx,0x0201 + call getkey + pop bx + + pre_probe: + cmp ax,1 + je noprobe + + push cx dx + + mov bx,0x100 + + newprobe: + + inc bx + cmp bx,0x17f + jne probemore + + mov si,prnotfnd-0x10000 + call printplain + + jmp $ + + probemore: + + mov ax,0x4f01 + mov cx,bx + and cx,0xfff + push word 0x0000 + pop es + mov di,0xa000 + int 0x10 + + mov eax,[es:di] ; lfb ? + test eax,10000000b + jz newprobe + + mov eax,[es:di+0x12] ; x size ? + cmp ax,word [esp+2] + jne newprobe + + mov eax,[es:di+0x14] ; y size ? + cmp ax,dx + jne newprobe + + movzx eax,byte [es:di+0x19] + cmp eax,32 ;24 + jb newprobe + + push word 0x0000 ; save probed mode + pop es + add bx,0100000000000000b + mov [es:0x9008],bx + push word 0x1000 + pop es + + push bx + + mov si,prid-0x10000 + call printplain + + pop bx dx cx + + noprobe: + + +; FIND VESA 2.0 LFB & BPP + + mov ax,0x4f01 + mov cx,bx + and cx,0xfff + push word 0x0000 + pop es + mov di,0xa000 + int 0x10 + ; LFB + mov ecx,[es:di+0x28] + mov [es:0x9018],ecx + ; BPP + movzx ax,byte [es:di+0x19] + mov [es:0x9000],ax + ; ---- vbe voodoo + BytesPerScanLine equ 0x10 + push ax + mov ax, [es:di+BytesPerScanLine] + mov [es:0x9001],ax + pop ax + ; ----- + nov: + cmp ax,24 + jnz nbpp24 + mov si,bt24-0x10000 + jmp bppl + nbpp24: + cmp ax,32 + jnz nbpp32 + mov si,bt32-0x10000 + jmp bppl + nbpp32: + mov si,btns-0x10000 + call print + jmp $ + bppl: + call printplain + + +; FIND VESA 1.2 PM BANK SWITCH ADDRESS + + mov ax,0x4f0A + mov bx,0x0 + int 0x10 + xor eax,eax + xor ebx,ebx + mov ax,es + shl eax,4 + mov bx,di + add eax,ebx + xor ebx,ebx + mov bx,[es:di] + add eax,ebx + push word 0x0 + pop es + mov [es:0x9014],eax + push word 0x1000 + pop es + + + +; GRAPHICS ACCELERATION + + mov al, [es:preboot_mtrr-0x10000] + test al,al + jne pre_mtrr + mov si,gr_acc-0x10000 + call printplain + mov ebx,0x0201 + call getkey + pre_mtrr: + push word 0x0000 + pop es + mov [es:0x901C],al + push word 0x1000 + pop es + mov si,linef-0x10000 + call printplain + + +; VRR_M USE + + mov al,[es:preboot_vrrm-0x10000] + test al,al + jne pre_vrrm + mov si,vrrmprint-0x10000 + call print + mov ebx,0x0301 + call getkey + pre_vrrm: + push word 0x0000 + pop es + mov [es:0x9030],al + push word 0x1000 + pop es + mov si,linef2-0x10000 + call printplain + + +; MEMORY MODEL + +; movzx eax,byte [es:preboot_memory-0x10000] +; cmp eax,0 +; jne pre_mem +;;;;;;;;;;;;;;;;;;;;;;;;; +; mario79 - memory size ; +;;;;;;;;;;;;;;;;;;;;;;;;; +; mov ax,0E801h +;;; xor bx,bx ; thanks to Alexei for bugfix [18.07.2004] +; xor cx, cx +; xor dx, dx +; int 0x15 +; movzx ebx, dx ;bx +; movzx eax, cx ;ax +; shl ebx,6 ; яхЁхтюф т ъшыюсрщЄ√ (x64) +; add eax,ebx +; add eax, 1000h ;440h +; cmp eax,40000h ; 256? +; jge mem_256_z +; cmp eax,20000h ; 128? +; jge mem_128_z +; cmp eax,10000h ; 64? +; jge mem_64_z +; cmp eax,8000h ; 32? +; jge mem_32_z +; jmp mem_16_z +; +;mem_256_z: mov si,memokz256-0x10000 +; call printplain +; mov eax,5 +; jmp pre_mem +;mem_128_z: mov si,memokz128-0x10000 +; call printplain +; mov eax,4 +; jmp pre_mem +;mem_64_z: mov si,memokz64-0x10000 +; call printplain +; mov eax,3 +; jmp pre_mem +;mem_32_z: mov si,memokz32-0x10000 +; call printplain +; mov eax,2 +; jmp pre_mem +;mem_16_z: mov si,memokz16-0x10000 +; call printplain +; mov eax,1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; pre_mem: +; push word 0x0000 +; pop es +; mov [es:0x9030],al +; push word 0x1000 +; pop es +; mov si,linef-0x10000 +; call printplain + + + + +; DIRECT WRITE TO LFB, PAGING DISABLED + +; movzx eax,byte [es:preboot_lfb-0x10000] +; mov eax,1 ; paging disabled +; cmp eax,0 +; jne pre_lfb +; mov si,gr_direct-0x10000 +; call printplain +; mov ebx,0x0201 +; call getkey +; pre_lfb: +; push word 0x0000 +; pop es +; mov [es:0x901E],al +; mov ax,0x1000 +; mov es,ax +; mov si,linef-0x10000 +; call printplain + push 0 + pop es + mov [es:0x901E],byte 1 + push 0x1000 + pop es + + + +; BOOT DEVICE + + movzx eax,byte [es:preboot_device-0x10000] + cmp eax,0 + jne pre_device + mov si,bdev-0x10000 + call printplain + mov ebx,0x0301 + call getkey + pre_device: + dec al + mov [es:boot_dev-0x10000],al + mov si,linef-0x10000 + call printplain + + + +; READ DISKETTE TO MEMORY + + cmp [boot_dev-0x10000],0 + jne no_sys_on_floppy + mov si,diskload-0x10000 + call print + mov ax,0x0000 ; reset drive + mov dx,0x0000 + int 0x13 + mov cx,0x0001 ; startcyl,startsector + mov dx,0x0000 ; starthead,drive + push word 80*2 ; read no of sect + reads: + pusha + xor si,si + newread: + push word 0x0 + pop es + mov bx,0xa000 ; es:bx -> data area + mov ax,0x0200+18 ; read, no of sectors to read + int 0x13 + cmp ah,0 + jz goodread + add si,1 + cmp si,10 + jnz newread + mov si,badsect-0x10000 + call printplain + jmp $ + goodread: + ; move -> 1mb + mov si,movedesc-0x10000 + push word 0x1000 + pop es + mov cx,256*18 + mov ah,0x87 + int 0x15 + + cmp ah,0 ; was the move successfull ? + je goodmove + mov dx,0x3f2 ; floppy motor off + mov al,0 + out dx,al + mov si,memmovefailed-0x10000 + call print + jmp $ + goodmove: + + mov eax,[es:movedesc-0x10000+0x18+2] + add eax,512*18 + mov [es:movedesc-0x10000+0x18+2],eax + popa + inc dh + cmp dh,2 + jnz bb2 + mov dh,0 + inc ch + pusha ; print prosentage + push word 0x1000 + pop es + xor eax,eax ; 5 + mov al,ch + shr eax,2 + and eax,1 + mov ebx,5 + mul bx + add al,48 + mov [es:pros+1-0x10000],al + xor eax,eax ; 10 + mov al,ch + shr eax,3 + add al,48 + mov [es:pros-0x10000],al + mov si,pros-0x10000 + call printplain + popa + bb2: + pop ax + dec ax + push ax + cmp ax,0 + jnz rs + jmp readdone + rs: + jmp reads + movedesc: + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + + db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 + db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 + + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + readdone: + pop ax + mov dx,0x3f2 ; floppy motor off + mov al,0 + out dx,al + mov si,backspace-0x10000 + call printplain + call printplain + mov si,okt-0x10000 + call printplain + no_sys_on_floppy: + mov ax,0x0000 ; reset drive + mov dx,0x0000 + int 0x13 + mov dx,0x3f2 ; floppy motor off + mov al,0 + out dx,al + + +; PAGE TABLE + + push word 0x0000 + pop es + mov ecx,[es:0x9018] + push ecx + + map_mem equ 64 ; amount of memory to map + + mov bx,0x6000 + mov es,bx ; [es:di] = 6000:0 + xor edi,edi + mov ecx,256*map_mem ; Map (mapmem) M + mov eax,7 + cld + pt2: + cmp ecx,256*(map_mem-8) ; 8 M map to LFB + jnz pt3 + pop eax + add eax,7 + pt3: + cmp ecx,256*(map_mem-12) ; 12 M back to linear = physical + jnz pt4 + mov eax,12*0x100000 + 7 + pt4: + stosd + add eax,4096 + loop pt2 + + mov bx,0x7100 + mov es,bx + xor edi,edi + mov eax,8*0x100000+7 + mov ecx,256*4 + pt5: + stosd + add eax,0x1000 + loop pt5 + +; 4 KB PAGE DIRECTORY + + mov bx , 0x7F00 + mov es , bx ; [es:di] = 7000:0 + xor edi, edi + mov ecx, 64 / 4 + mov eax, 0x60007 ; for 0 M + cld + pd4k: + stosd + add eax, 0x1000 + loop pd4k + mov dword [es:0x800],0x71007 ;map region 0x80000000-0x803FFFFF to 0x800000-0xCFFFFF + xor esi,esi + mov edi,second_base_address shr 20 + mov ecx,64/4 + mov bx,0x7F00 + mov ds,bx + rep movsd + mov bx,0x1000 + mov ds,bx + + mov eax, 0x7F000 +8+16 ; Page directory and enable caches + mov cr3, eax + +; SET GRAPHICS + + mov dx,0x0000 + mov es,dx + mov bx,[es:0x9008] + mov ax,bx ; vga & 320x200 + cmp ax,0x13 + je setgr + cmp ax,0x12 + je setgr + mov ax,0x4f02 ; Vesa + setgr: + int 0x10 + cmp ah,0 + jz gmok + mov si,fatalsel-0x10000 + call print + jmp $ + + gmok: + mov dx,0x1000 + mov es,dx + +; set mode 0x12 graphics registers: + + cmp bx,0x12 + jne gmok2 + + mov al,0x05 + mov dx,0x03ce + out dx,al ; select GDC mode register + mov al,0x02 + mov dx,0x03cf + out dx,al ; set write mode 2 + + mov al,0x02 + mov dx,0x03c4 + out dx,al ; select VGA sequencer map mask register + mov al,0x0f + mov dx,0x03c5 + out dx,al ; set mask for all planes 0-3 + + mov al,0x08 + mov dx,0x03ce + out dx,al ; select GDC bit mask register + ; for writes to 0x03cf + + gmok2: + mov dx,0x1000 + mov es,dx diff --git a/trunk/boot/booteng.inc b/trunk/boot/booteng.inc new file mode 100644 index 000000000..89e873a77 --- /dev/null +++ b/trunk/boot/booteng.inc @@ -0,0 +1,109 @@ +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + +macro line_full_top { + db 201 + times 78 db 205 + db 187 +} +macro line_full_bottom { + db 200 + times 78 db 205 + db 188 +} +macro line_half { + db 186,' ' + times 76 db 0xc4 + db ' ',186 +} +macro line_space { + db 186 + times 78 db 32 + db 186 +} +d80x25: line_full_top + line_space + line_space + line_half + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + db 186,' Kolibri OS comes with ABSOLUTELY NO WARR' + db 'ANTY; See file COPYING for details ',186 + line_full_bottom + +novesa db "Display: EGA/CGA",13,10,0 +vervesa db "Version of Vesa: Vesa x.x ",13,10,0 +vervesa_off=22 +gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " + db "[3] 1024x768, [4] 1280x1024",13,10 + db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " + db "[7] 1024x768, [8] 1280x1024",13,10 + db 186," EGA/CGA 256 Colors: [9] 320x200, " + db "VGA 16 Colors: [0] 640x480",13,10 + db 186," Select mode: ",0 +bt24 db 13,10,186," Bits Per Pixel: 24",13,10,0 +bt32 db 13,10,186," Bits Per Pixel: 32",13,10,0 +vrrmprint db 13,10,186," Apply VRR? (picture frequency greater than 60Hz" + db " only for transfers:",13,10 + db 186," 1024*768->800*600 and 800*600->640*480) [1-yes,2-no]:",0 +askmouse db " Mouse at:" + db " [1] PS/2 (USB), [2] Com1, [3] Com2." + db " Select port [1-3]: ",0 +no_com1 db 13,10,186, " No COM1 mouse",0 +no_com2 db 13,10,186, " No COM2 mouse",0 +gr_acc db 13,10,186," Vesa 2.0+ : MTRR graphics acceleration " + db "[1-yes/2-no] ? ",0 +gr_direct db 186," Use direct LFB writing? " + db "[1-yes/2-no] ? ",0 +;mem_model db 13,10,186," Motherboard memory [1-16 Mb / 2-32 Mb / " +; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 +bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 +bdev db 13,10,186 + db " Load ramdisk from [1-floppy; 2-C:\menuet.img (FAT32);" + db 13,10,186," " + db "3-use preloaded ram-image from kernel restart]: ",0 +probetext db 13,10,13,10,186," Use standart graphics mode? [1-yes, " + db "2-probe bios (Vesa 3.0)]: ",0 +;memokz256 db 13,10,186," RAM 256 Mb",0 +;memokz128 db 13,10,186," RAM 128 Mb",0 +;memokz64 db 13,10,186," RAM 64 Mb",0 +;memokz32 db 13,10,186," RAM 32 Mb",0 +;memokz16 db 13,10,186," RAM 16 Mb",0 +prid db " pr.",0 +prnotfnd db " pr. - not found.",0 +modena db "Fatal - VBE 0x112+ required.",0 +not386 db "Fatal - CPU 386+ required.",0 +btns db 13,10,186,"Fatal - Can't determine color depth.",0 +fatalsel db 13,10,"Fatal - Graphics mode not supported by hardware.",0 +badsect db 13,10,186," Fatal - Bad sector. Replace floppy. ",0 +memmovefailed db "Fatal - Int 0x15 move failed.",0 +linef2 db 13,10 +linef db 13,10,0 +okt db " ... OK",0 +keyin db "x",0 +keyinbs db "x",8,0 +diskload db 13,10,186," Loading diskette: 00 %",8,8,8,8,0 +backspace db 8,0 +pros db "00",8,8,0 +leftpr db 186," ",0 +boot_dev db 0 ; 0=floppy, 1=hd diff --git a/trunk/boot/bootru.inc b/trunk/boot/bootru.inc new file mode 100644 index 000000000..c1579d82e --- /dev/null +++ b/trunk/boot/bootru.inc @@ -0,0 +1,110 @@ +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + +macro line_full_top { + db 201 + times 78 db 205 + db 187 +} +macro line_full_bottom { + db 200 + times 78 db 205 + db 188 +} +macro line_half { + db 186,' ' + times 76 db 0xc4 + db ' ',186 +} +macro line_space { + db 186 + times 78 db 32 + db 186 +} +d80x25: line_full_top + line_space + line_space + line_half + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + line_space + db 186,' Kolibri OS не предоставляет никаких гарa' + db 'нтий; Подробнее - см. GNU.TXT ',186 + line_full_bottom + +novesa db "Видеокарта: EGA/CGA",13,10,0 +vervesa db "Версия VESA: Vesa x.x ",13,10,0 +vervesa_off=19 +gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " + db "[3] 1024x768, [4] 1280x1024",13,10 + db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " + db "[7] 1024x768, [8] 1280x1024",13,10 + db 186," EGA/CGA 256 Цветов: [9] 320x200, " + db "VGA 16 Цветов: [0] 640x480",13,10 + db 186," Выберите видеорежим: ",0 +bt24 db 13,10,186," Глубина цвета: 24",13,10,0 +bt32 db 13,10,186," Глубина цвета: 32",13,10,0 +vrrmprint db 13,10,186," Использовать VRR? (частота кадров выше 60 Гц" + db " только для переходов:",13,10 + db 186," 1024*768>800*600 и 800*600>640*480) [1-да, 2-нет]: ",0 +askmouse db "Мышь:" ; 186, " " + db " [1] PS/2 (USB), [2] Com1, [3] Com2." + db " Выберите порт [1-3]: ",0 +no_com1 db 13,10,186," No COM1 mouse",0 +no_com2 db 13,10,186," No COM2 mouse",0 +gr_acc db 13,10,186," Vesa 2.0+: Включить MTRR для ускорения графики? " + db "[1-да/2-нет]: ",0 +gr_direct db 186," Использовать линейный видеобуфер? " + db "[1-да/2-нет]: ",0 +;mem_model db 13,10,186," Объ+м памяти [1-16 Mb / 2-32 Mb / " +; db "3-64Mb / 4-128 Mb / 5-256 Mb]: ",0 +bootlog db 13,10,186," Просмотреть журнал загрузки? [1-нет/2-да]: ",0 +bdev db 186 + db " Загрузить образ из [1-дискета; 2-C:\menuet.img (FAT32);" + db 13,10,186," " + db "3-использовать уже загруженный образ]: ",0 +probetext db 13,10,13,10,186," Стандартный видеорежим? [1-да, " + db "2-проверить другие (Vesa 3.0)]: ",0 +;memokz256 db 13,10,186," RAM 256 Mb",0 +;memokz128 db 13,10,186," RAM 128 Mb",0 +;memokz64 db 13,10,186," RAM 64 Mb",0 +;memokz32 db 13,10,186," RAM 32 Mb",0 +;memokz16 db 13,10,186," RAM 16 Mb",0 +prid db " pr.",0 +prnotfnd db " pr. - ошибка.",0 +modena db "Ошибка - Требуется поддержка VBE 0x112+.",0 +not386 db "Ошибка - Требуется процессор 386+.",0 +btns db 13,10,186," Ошибка - Не могу определить глубину цвета.",0 +fatalsel db 13,10,"Ошибка - Выбранный видеорежим не поддерживается.",0 +badsect db 13,10,186," Ошибка - Дискета повреждена. Попробуйте другую. " + db 0 +memmovefailed db "Fatal - Int 0x15 move failed.",0 +linef2 db 13,10 +linef db 13,10,0 +okt db " ... OK",0 +keyin db "x",0 +keyinbs db "x",8,0 +diskload db 13,10,186," Загрузка дискеты: 00 %",8,8,8,8,0 +backspace db 8,0 +pros db "00",8,8,0 +leftpr db 186," ",0 +boot_dev db 0 diff --git a/trunk/boot/preboot.inc b/trunk/boot/preboot.inc new file mode 100644 index 000000000..de61f8579 --- /dev/null +++ b/trunk/boot/preboot.inc @@ -0,0 +1,23 @@ +display_modechg db 0 ; display mode change for text, yes/no (0 or 2) + ; + ; !! Important note !! + ; + ; Must be set to 2, to avoid two screenmode + ; changes within a very short period of time. + +display_atboot db 0 ; show boot screen messages ( 2-no ) + +preboot_graph db 0 ; graph mode +preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) +preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) +;;preboot_mouse db 0 ; mouse port (1-PS2, 2-COM1, 3-COM2) +preboot_mtrr db 0 ; mtrr acceleration (1-yes, 2-no) +preboot_device db 0 ; boot device + ; (1-floppy 2-harddisk 3-kernel restart) +;;preboot_memory db 0 ; amount of memory + ; (1-16Mb;2-32Mb;3-64Mb;4-128Mb;5-256Mb) + ; !!!! 0 - autodetect !!!! +preboot_blogesc db 0 ; start immediately after bootlog + +hdsysimage db 'MENUET IMG' ; load from +image_save db 'MENUET IMG' ; save to diff --git a/trunk/boot/rdload.inc b/trunk/boot/rdload.inc new file mode 100644 index 000000000..cc98ec19c --- /dev/null +++ b/trunk/boot/rdload.inc @@ -0,0 +1,95 @@ +; READ RAMDISK IMAGE FROM HD + + cmp [boot_dev],1 + jne no_sys_on_hd + + test [0x40001],byte 0x40 + jz position_2 + mov [hdbase],0x1f0 + mov [hdid],0x0 + mov [hdpos],1 + mov [fat32part],0 + position_1_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved],1 + je yes_sys_on_hd + movzx eax,byte [0x40002] + cmp [fat32part],eax + jle position_1_1 + position_2: + test [0x40001],byte 0x10 + jz position_3 + mov [hdbase],0x1f0 + mov [hdid],0x10 + mov [hdpos],2 + mov [fat32part],0 + position_2_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved],1 + je yes_sys_on_hd + movzx eax,byte [0x40003] + cmp eax,[fat32part] + jle position_2_1 + position_3: + test [0x40001],byte 0x4 + jz position_4 + mov [hdbase],0x170 + mov [hdid],0x0 + mov [hdpos],3 + mov [fat32part],0 + position_3_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved],1 + je yes_sys_on_hd + movzx eax,byte [0x40004] + cmp eax,[fat32part] + jle position_3_1 + position_4: + test [0x40001],byte 0x1 + jz no_sys_on_hd + mov [hdbase],0x170 + mov [hdid],0x10 + mov [hdpos],4 + mov [fat32part],0 + position_4_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved],1 + je yes_sys_on_hd + movzx eax,byte [0x40005] + cmp eax,[fat32part] + jle position_4_1 + jmp yes_sys_on_hd + + search_and_read_image: +; mov [0xfe10],dword 0 ; entries in hd cache + call set_FAT32_variables + mov edx, bootpath + call read_image + test eax, eax + jz image_present + mov edx, bootpath2 + call read_image + test eax, eax + jz image_present + ret + image_present: + mov [image_retrieved],1 + ret + +read_image: + mov eax, hdsysimage + mov ebx, 1474560/512 + mov ecx, 0x100000 + mov esi, 0 + mov edi, 12 + call file_read + ret + +image_retrieved db 0 +counter_of_partitions db 0 +no_sys_on_hd: +yes_sys_on_hd: diff --git a/trunk/boot/ru.inc b/trunk/boot/ru.inc new file mode 100644 index 000000000..68ef06107 --- /dev/null +++ b/trunk/boot/ru.inc @@ -0,0 +1,92 @@ +; Generated by RUFNT.EXE +; By BadBugsKiller (C) +; Modifyed by BadBugsKiller 12.01.2004 17:45 +; ╪ЁшЇЄ єьхэ№°хэ т ЁрчьхЁх ш ЄхяхЁ№ ёюёЄюшЄ шч 2-єї ўрёЄхщ, +; ёюфхЁцр∙шї Єюы№ъю ёшьтюы√ Ёєёёъюую рыЇртшЄр. +; ёшьтюы√ т ъюфшЁютъх ASCII (─╬╤'ютёър ), ъюфютр  ёЄрэшЎр 866. +RU_FNT1: + db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + + db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 + + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + +RU_FNT2: + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 + db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 + + db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 + db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \ No newline at end of file diff --git a/trunk/boot/shutdown.inc b/trunk/boot/shutdown.inc new file mode 100644 index 000000000..5bfcc9f7e --- /dev/null +++ b/trunk/boot/shutdown.inc @@ -0,0 +1,496 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Shutdown for Menuet +;; +;; Distributed under General Public License +;; See file COPYING for details. +;; Copyright 2003 Ville Turjanmaa +;; + + +system_shutdown: ; shut down the system + + mov eax,3 ; stop playing cd + call sys_cd_audio + cli + cld + + mov al,[0x2f0000+0x9030] + cmp al,1 + jl no_shutdown_parameter + cmp al,4 + jg no_shutdown_parameter + jmp yes_shutdown_param + no_shutdown_parameter: + + movzx ecx,word [0x2f0000+0x900A] + movzx esi,word [0x2f0000+0x900C] + imul ecx,esi ;[0xfe04] +; mov ecx,0x500000/4 ;3fff00/4 ; darken screen + push ecx + mov esi,[0xfe80] + cmp esi,32*0x100000 + jbe no_darken_screen + mov edi,16*0x100000 + sdnewpix: + mov eax,[esi] + add esi,4 + shr eax,1 + and eax,0x7f7f7f7f + stosd + loop sdnewpix + pop ecx + mov esi,16*0x100000 + mov edi,[0xfe80] + cld + rep movsd + no_darken_screen: + + mov eax,[0xfe00] + shr eax,1 + sub eax,220 + + mov ebx,[0xfe04] + shr ebx,1 + mov [shutdownpos],ebx + sub ebx,120 + + mov edi,1 + mov ecx,0x0000ff + + sdnewpix2: + + call [putpixel] + + inc eax + mov esi,[0xfe00] + shr esi,1 + add esi,220 + cmp eax,esi + jnz sdnewpix2 + + dec ecx + + mov eax,[0xfe00] + shr eax,1 + sub eax,220 + + inc ebx + + mov edx,[shutdownpos] + add edx,105 + cmp ebx,edx + jnz sdnewpix2 + + + mov esi,[0xfe00] ; menuet version + shr esi,1 + sub esi,220 + add esi,27 + shl esi,16 + mov eax,esi + add eax,[shutdownpos] + sub eax,105 + mov ebx,0xffff00 + mov ecx,version + mov edx,34 + mov edi,1 + call dtext + + mov esi,[0xfe00] ; 'it is safe..' + shr esi,1 + sub esi,220 + add esi,27 + shl esi,16 + mov eax,esi + add eax,[shutdownpos] + add eax,33 + mov esi,6 + mov ebx,0xffffff + mov ecx,shutdowntext + mov edx,40 + mov edi,1 + newsdt: + call dtext + add eax,10 + add ecx,40 + dec esi + jnz newsdt + + mov eax,rosef ; load rose.txt + mov ebx,0 + mov ecx,16800 + mov edx,0x90000 + mov esi,12 + call fileread + + mov esi,[0xfe00] ; draw rose + shr esi,1 + add esi,20 + shl esi,16 + mov eax,esi + add eax,[shutdownpos] + sub eax,110 + + mov ebx,0x00ff00 + mov ecx,0x90001 + mov edx,27 + mov edi,1 + + nrl: + call dtext + sub ebx,0x050000 + add eax,8 + add ecx,31 + cmp ecx,dword 0x90001+25*31 + jnz nrl + + call checkEgaCga + + yes_shutdown_param: + + cli + + mov eax,kernel ; load kernel.mnt to 0x8000:0 + mov esi,12 + mov ebx,0 + mov ecx,-1 + mov edx,0x80000 + call fileread + + mov esi,restart_kernel_4000 ; move kernel re-starter to 0x4000:0 + mov edi,0x40000 + mov ecx,1000 + cld + rep movsb + + mov eax,0x2F0000 ; restore 0x0 - 0xffff + mov ebx,0x0000 + mov ecx,0xffff + call memmove + + call restorefatchain + + mov eax,pr_mode_exit + mov [0x467+0],ax + mov [0x467+2],word 0x1000 + + mov al,0x0F + out 0x70,al + mov al,0x05 + out 0x71,al + + mov al,0xFE + out 0x64,al + hlt + +use16 + +pr_mode_exit: + + mov ax,1000 + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax +; mov bl,[shutdown_parameter] + mov al,2 + out 0x21,al + mov al,0 + out 0xA1,al + +; mov [es:shutdown_parameter-0x10000],bl + + jmp real_mode-0x10000 + +old_ints_h: + dw 4*0x20 + dd 0 + dw 0 + +real_mode: + + lidt [cs:old_ints_h-0x10000] + mov sp,0xfff0 + + sti + + jmp temp_3456 + + nbw: + xor ax,ax + in al,0x60 + call pause_key + cmp al,7 + jge nbw + mov bl,al + nbw2: + in al,0x60 + call pause_key + cmp al,bl + je nbw2 + cmp al,240 ;ax,240 + jne nbw31 + mov al,bl + dec al + jmp nbw32 + nbw31: + add bl,128 + cmp al,bl + jne nbw + sub al,129 + + nbw32: + + cmp al,1 ; write floppy + jne no_floppy_write + call floppy_write + jmp temp_3456 ;nbw + no_floppy_write: + + cmp al,2 ; poweroff + jne no_apm_off + call APM_PowerOff + no_apm_off: + + cmp al,3 ; boot + jnz no_sys_boot + mov ax,0x0040 + mov ds,ax + mov word[0x0072],0x1234 + jmp 0xF000:0xFFF0 + no_sys_boot: + + cmp al,4 ; restart kernel + je restart_kernel + + temp_3456: + push word 0x0000 + pop es + mov al,byte [es:0x9030] + cmp al,1 + jl nbw + cmp al,4 + jg nbw + jmp nbw32 + +; jmp nbw + pause_key: + mov ecx,100 + pause_key_1: + loop pause_key_1 + ret + +iglobal + kernel db 'KERNEL MNT' +; shutdown_parameter db 0 +endg + +restart_kernel: + + mov ax,0x0003 ; set text mode for screen + int 0x10 + + jmp 0x4000:0000 + + +restart_kernel_4000: + + mov di,0x1000 ; load kernel image from 0x8000:0 -> 0x1000:0 + + new_kernel_block_move: + + mov ebx,0 + + new_kernel_byte_move: + + mov ax,di + add ax,0x7000 + mov es,ax + mov dl,[es:bx] + mov es,di + mov [es:bx],dl + + inc ebx + cmp ebx,65536 + jbe new_kernel_byte_move + + add di,0x1000 + cmp di,0x2000 + jbe new_kernel_block_move + + wbinvd ; write and invalidate cache + + mov ax,0x1000 + mov es,ax + mov ax,0x2000 + mov ss,ax + mov sp,0xff00 + + jmp 0x1000:0000 + + +APM_PowerOff: +;!!!!!!!!!!!!!!!!!!!!!!!! +mov ax,0x5300 +xor bx,bx +int 0x15 +push ax + +mov ax,0x5301 +xor bx,bx +int 0x15 + +mov ax,0x5308 +mov bx,1 +mov cx,bx +int 0x15 + +mov ax,0x530E +xor bx,bx +pop cx +int 0x15 + +mov ax,0x530D +mov bx,1 +mov cx,bx +int 0x15 + +mov ax,0x530F +mov bx,1 +mov cx,bx +int 0x15 + +mov ax,0x5307 +mov bx,1 +mov cx,3 +int 0x15 +;!!!!!!!!!!!!!!!!!!!!!!!! + ret +uglobal + flm db 0 +endg + +floppy_write: ; write diskette image to physical floppy + + pusha + + mov ax,0x1000 + mov es,ax + cmp [es:flm-0x10000],byte 1 + je fwwritedone + mov [es:flm-0x10000],byte 1 + + mov ax,0x0000 ; reset drive + mov dx,0x0000 + int 0x13 + + mov cx,0x0001 ; startcyl,startsector + mov dx,0x0000 ; starthead,drive + push word 80*2 ; read no of sect + + fwwrites: + pusha + + ; move 1mb+ -> 0:a000 + + pusha + mov si,fwmovedesc -0x10000 + push word 0x1000 + pop es + mov cx,256*18 + mov ah,0x87 + int 0x15 + mov eax,[es:fwmovedesc-0x10000+0x12] + add eax,512*18 + mov [es:fwmovedesc-0x10000+0x12],eax + popa + + xor si,si + fwnewwrite: + push word 0x0 + pop es + mov bx,0xa000 ; es:bx -> data area + mov ax,0x0300+18 ; read, no of sectors to read + int 0x13 + + cmp ah,0 + jz fwgoodwrite + + add si,1 + cmp si,10 + jnz fwnewwrite + + add esp,32+2 + + popa ; can't access diskette + ret + + fwgoodwrite: + + popa + + inc dh + cmp dh,2 + jnz fwbb2 + mov dh,0 + inc ch + + fwbb2: + + cld + pop ax + dec ax + push ax + cmp ax,0 + jnz fwrs + + pop ax + + jmp fwwritedone + fwrs: + jmp fwwrites + + fwmovedesc: + + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 + db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + + fwwritedone: + + popa + + ret + + +use32 + +uglobal + shutdownpos dd 0x0 +endg + +iglobal +;shutdowntext: +; db "IT'S SAFE TO POWER OFF COMPUTER OR " +; db ' ' +; db '1) SAVE RAMDISK TO FLOPPY ' +; db '2) APM - POWEROFF ' +; db '3) REBOOT ' +; db '4) RESTART KERNEL ' +shutdowntext: + db "Безопасное выключение компьютера или " + db ' ' + db '1) Сохранить рамдиск на дискету ' + db '2) APM - выключение питания ' + db '3) Перезагрузка системы ' + db '4) Рестарт ядра из ОЗУ ' +rosef: + db 'ROSE TXT' +endg diff --git a/trunk/build_en.bat b/trunk/build_en.bat new file mode 100644 index 000000000..3d5a30612 --- /dev/null +++ b/trunk/build_en.bat @@ -0,0 +1,4 @@ +@if not exist lang.inc ( +@echo lang fix en >lang.inc +) +@fasm kernel.asm kernel.mnt \ No newline at end of file diff --git a/trunk/build_ru.bat b/trunk/build_ru.bat new file mode 100644 index 000000000..2e05a6815 --- /dev/null +++ b/trunk/build_ru.bat @@ -0,0 +1,4 @@ +@if not exist lang.inc ( +@echo lang fix ru >lang.inc +) +@fasm kernel.asm kernel.mnt \ No newline at end of file diff --git a/trunk/bus/pci/pci16.inc b/trunk/bus/pci/pci16.inc new file mode 100644 index 000000000..c22914852 --- /dev/null +++ b/trunk/bus/pci/pci16.inc @@ -0,0 +1,46 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; PCI16.INC ;; +;; ;; +;; 16 bit PCI driver code ;; +;; ;; +;; Version 0.2 December 21st, 2002 ;; +;; ;; +;; Author: Victor Prodan, victorprodan@yahoo.com ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +init_pci_16: + + pushad + + xor ax,ax + mov es,ax + mov byte [es:0x9020],1 ;default mechanism:1 + mov ax,0xb101 + int 0x1a + or ah,ah + jnz pci16skip + + mov [es:0x9021],cl ;last PCI bus in system + mov [es:0x9022],bx + mov [es:0x9024],edi + +; we have a PCI BIOS, so check which configuration mechanism(s) +; it supports +; AL = PCI hardware characteristics (bit0 => mechanism1, bit1 => mechanism2) + test al,1 + jnz pci16skip + test al,2 + jz pci16skip + mov byte [es:0x9020],2 ; if (al&3)==2 => mechanism 2 + +pci16skip: + + mov ax,0x1000 + mov es,ax + + popad \ No newline at end of file diff --git a/trunk/bus/pci/pci32.inc b/trunk/bus/pci/pci32.inc new file mode 100644 index 000000000..c224880fe --- /dev/null +++ b/trunk/bus/pci/pci32.inc @@ -0,0 +1,358 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; PCI32.INC ;; +;; ;; +;; 32 bit PCI driver code ;; +;; ;; +;; Version 0.2 December 21st, 2002 ;; +;; ;; +;; Author: Victor Prodan, victorprodan@yahoo.com ;; +;; Credits: ;; +;; Ralf Brown ;; +;; Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;*************************************************************************** +; Function +; pci_api: +; +; Description +; entry point for system PCI calls +;*************************************************************************** + +align 4 + +pci_api: + + cmp [pci_access_enabled],1 + jne no_pci_access_for_applications + + or al,al + jnz pci_fn_1 + ; PCI function 0: get pci version (AH.AL) + movzx eax,word [0x2F0000+0x9022] + ret + +pci_fn_1: + cmp al,1 + jnz pci_fn_2 + + ; PCI function 1: get last bus in AL + mov al,[0x2F0000+0x9021] + ret + +pci_fn_2: + cmp al,2 + jne pci_fn_3 + ; PCI function 2: get pci access mechanism + mov al,[0x2F0000+0x9020] + ret +pci_fn_3: + + cmp al,4 + jz pci_read_reg ;byte + cmp al,5 + jz pci_read_reg ;word + cmp al,6 + jz pci_read_reg ;dword + + cmp al,8 + jz pci_write_reg ;byte + cmp al,9 + jz pci_write_reg ;word + cmp al,10 + jz pci_write_reg ;dword + + no_pci_access_for_applications: + + mov eax,-1 + + ret + +;*************************************************************************** +; Function +; pci_make_config_cmd +; +; Description +; creates a command dword for use with the PCI bus +; bus # in ah +; device+func in bh (dddddfff) +; register in bl +; +; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 ) +;*************************************************************************** + +align 4 + +pci_make_config_cmd: + shl eax,8 ; move bus to bits 16-23 + mov ax,bx ; combine all + and eax,0xffffff + or eax,0x80000000 + ret + +;*************************************************************************** +; Function +; pci_read_reg: +; +; Description +; read a register from the PCI config space into EAX/AX/AL +; IN: ah=bus,device+func=bh,register address=bl +; number of bytes to read (1,2,4) coded into AL, bits 0-1 +;*************************************************************************** + +align 4 + +pci_read_reg: + cmp byte [0x2F0000+0x9020],2 ;what mechanism will we use? + je pci_read_reg_2 + + ; mechanism 1 + push esi ; save register size into ESI + mov esi,eax + and esi,3 + + call pci_make_config_cmd + mov ebx,eax + ; get current state + mov dx,0xcf8 + in eax, dx + push eax + ; set up addressing to config data + mov eax,ebx + and al,0xfc ; make address dword-aligned + out dx,eax + ; get requested DWORD of config data + mov dl,0xfc + and bl,3 + or dl,bl ; add to port address first 2 bits of register address + + or esi,esi + jz pci_read_byte1 + cmp esi,1 + jz pci_read_word1 + cmp esi,2 + jz pci_read_dword1 + jmp pci_fin_read1 + +pci_read_byte1: + in al,dx + jmp pci_fin_read1 +pci_read_word1: + in ax,dx + jmp pci_fin_read1 +pci_read_dword1: + in eax,dx + jmp pci_fin_read1 +pci_fin_read1: + ; restore configuration control + xchg eax,[esp] + mov dx,0xcf8 + out dx,eax + + pop eax + pop esi + ret +pci_read_reg_2: + + test bh,128 ;mech#2 only supports 16 devices per bus + jnz pci_read_reg_err + + push esi ; save register size into ESI + mov esi,eax + and esi,3 + + push eax + ;store current state of config space + mov dx,0xcf8 + in al,dx + mov ah,al + mov dl,0xfa + in al,dx + + xchg eax,[esp] + ; out 0xcfa,bus + mov al,ah + out dx,al + ; out 0xcf8,0x80 + mov dl,0xf8 + mov al,0x80 + out dx,al + ; compute addr + shr bh,3 ; func is ignored in mechanism 2 + or bh,0xc0 + mov dx,bx + + or esi,esi + jz pci_read_byte2 + cmp esi,1 + jz pci_read_word2 + cmp esi,2 + jz pci_read_dword2 + jmp pci_fin_read2 + +pci_read_byte2: + in al,dx + jmp pci_fin_read2 +pci_read_word2: + in ax,dx + jmp pci_fin_read2 +pci_read_dword2: + in eax,dx +; jmp pci_fin_read2 +pci_fin_read2: + + ; restore configuration space + xchg eax,[esp] + mov dx,0xcfa + out dx,al + mov dl,0xf8 + mov al,ah + out dx,al + + pop eax + pop esi + ret + +pci_read_reg_err: + xor eax,eax + dec eax + ret + + +;*************************************************************************** +; Function +; pci_write_reg: +; +; Description +; write a register from ECX/CX/CL into the PCI config space +; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, +; value to write in ecx +; number of bytes to write (1,2,4) coded into AL, bits 0-1 +;*************************************************************************** + +align 4 + +pci_write_reg: + cmp byte [0x2F0000+0x9020],2 ;what mechanism will we use? + je pci_write_reg_2 + + ; mechanism 1 + push esi ; save register size into ESI + mov esi,eax + and esi,3 + + call pci_make_config_cmd + mov ebx,eax + ; get current state into ecx + mov dx,0xcf8 + in eax, dx + push eax + ; set up addressing to config data + mov eax,ebx + and al,0xfc ; make address dword-aligned + out dx,eax + ; write DWORD of config data + mov dl,0xfc + and bl,3 + or dl,bl + mov eax,ecx + + or esi,esi + jz pci_write_byte1 + cmp esi,1 + jz pci_write_word1 + cmp esi,2 + jz pci_write_dword1 + jmp pci_fin_write1 + +pci_write_byte1: + out dx,al + jmp pci_fin_write1 +pci_write_word1: + out dx,ax + jmp pci_fin_write1 +pci_write_dword1: + out dx,eax + jmp pci_fin_write1 +pci_fin_write1: + + ; restore configuration control + pop eax + mov dl,0xf8 + out dx,eax + + xor eax,eax + pop esi + + ret +pci_write_reg_2: + + test bh,128 ;mech#2 only supports 16 devices per bus + jnz pci_write_reg_err + + + push esi ; save register size into ESI + mov esi,eax + and esi,3 + + push eax + ;store current state of config space + mov dx,0xcf8 + in al,dx + mov ah,al + mov dl,0xfa + in al,dx + xchg eax,[esp] + ; out 0xcfa,bus + mov al,ah + out dx,al + ; out 0xcf8,0x80 + mov dl,0xf8 + mov al,0x80 + out dx,al + ; compute addr + shr bh,3 ; func is ignored in mechanism 2 + or bh,0xc0 + mov dx,bx + ; write register + mov eax,ecx + + or esi,esi + jz pci_write_byte2 + cmp esi,1 + jz pci_write_word2 + cmp esi,2 + jz pci_write_dword2 + jmp pci_fin_write2 + +pci_write_byte2: + out dx,al + jmp pci_fin_write2 +pci_write_word2: + out dx,ax + jmp pci_fin_write2 +pci_write_dword2: + out dx,eax + jmp pci_fin_write2 +pci_fin_write2: + ; restore configuration space + pop eax + mov dx,0xcfa + out dx,al + mov dl,0xf8 + mov al,ah + out dx,al + + xor eax,eax + pop esi + ret + +pci_write_reg_err: + xor eax,eax + dec eax + ret diff --git a/trunk/core/fpu.inc b/trunk/core/fpu.inc new file mode 100644 index 000000000..cf450751a --- /dev/null +++ b/trunk/core/fpu.inc @@ -0,0 +1,62 @@ +iglobal + prev_user_of_fpu dd 0x1 ; set to OS +endg + +label fpu_tss at 0xB080 +label fpu_stack dword at 0xB060 + + +align 4 +fpu_handler: + + ; clear TS flag in CR0 -> for task switching + clts + + ; save FPU context of the previous task + mov eax,[prev_user_of_fpu] + shl eax,8 + add eax,0x80000+0x10 + fsave [eax] + + ; next task switch save our FPU context + ; now restore context of current task (if exists) + mov eax,[0x3000] + mov [prev_user_of_fpu],eax + shl eax,8 + add eax,0x80000 + cmp [eax+0x7f],byte 0 + je bs7_first_fpu + frstor [eax+0x10] + bs7_first_fpu: + mov [eax+0x7f],byte 1 + + ; prepare structure in stack for proper IRET + movzx eax,word [fpu_tss+l.ss-tss_sceleton] ; push ss + push eax + mov eax,[fpu_tss+l.esp-tss_sceleton] ; push esp + push eax + mov eax,[fpu_tss+l.eflags-tss_sceleton] ; push eflags + push eax + + movzx eax,word [fpu_tss+l.cs-tss_sceleton] ; push cs + push eax + mov eax,[fpu_tss+l.eip-tss_sceleton] ; push eip + push eax + + ; save eax + push dword [fpu_tss+l.eax-tss_sceleton] + + ; restore all segment registers + mov ax,[fpu_tss+l.es-tss_sceleton] + mov es,ax + mov ax,[fpu_tss+l.fs-tss_sceleton] + mov fs,ax + mov ax,[fpu_tss+l.gs-tss_sceleton] + mov gs,ax + mov ax,[fpu_tss+l.ds-tss_sceleton] + mov ds,ax + + ; restore eax + pop eax + + iret diff --git a/trunk/core/mem.inc b/trunk/core/mem.inc new file mode 100644 index 000000000..06d944456 --- /dev/null +++ b/trunk/core/mem.inc @@ -0,0 +1,473 @@ +if ~defined mem_inc +mem_inc_fix: +mem_inc fix mem_inc_fix +;include "memmanag.inc" +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;High-level memory management in MenuetOS. +;;It uses memory manager in memmanager.inc +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +second_base_address=0xC0000000 +std_application_base_address=0x10000000 +general_page_table_ dd 0 +general_page_table=general_page_table_+second_base_address +;----------------------------------------------------------------------------- +create_general_page_table: +;input +; none +;output +; none +;Procedure create general page directory and write +;it address to [general_page_table]. + pushad + mov eax,1 ;alloc 1 page + mov ebx,general_page_table ;write address to [general_page_table] + call MEM_Alloc_Pages ;allocate page directory + mov eax,[general_page_table] + call MEM_Get_Linear_Address ;eax - linear address of page directory + mov edi,eax + mov ebx,eax + xor eax,eax + mov ecx,4096/4 + cld + rep stosd ;clear page directory + + mov eax,4 + mov edx,eax + call MEM_Alloc_Pages ;alloc page tables for 0x0-0x1000000 region + cmp eax,edx + jnz $ ;hang if not enough memory + +;fill page tables + xor esi,esi + mov ebp,7 + +.loop: +;esi - number of page in page directory +;ebp - current page address +;ebx - linear address of page directory + mov eax,[ebx+4*esi] + add dword [ebx+4*esi],7 ;add flags to address of page table + call MEM_Get_Linear_Address +;eax - linear address of page table + mov ecx,4096/4 +;ecx (counter) - number of pages in page table +;current address=4Mb*esi + cmp esi,2 + jz .start_lfb_map ;lfb map begin at 0x800000 + cmp esi,3 + jz .end_lfb_map ;lfb map end at 0xC00000 + jmp .loop1 +.start_lfb_map: +;current address=lfb address + mov ebp,[0x2f0000+0x9018] + add ebp,7 ;add flags + jmp .loop1 +.end_lfb_map: +;current address=linear address + mov ebp,12*0x100000+7 + +.loop1: + mov [eax],ebp ;write page address (with flags) in page table + add eax,4 + add ebp,4096 ;size of page=4096 bytes + loop .loop1 + + inc esi ;next page directory entry + cmp esi,edx + jnz .loop + +;map region 0x80000000-0x803fffff to 0x800000-0xcfffff + mov eax,1 ;size of the region is 4Mb so only 1 page table needed + mov edx,ebx ;ebx still contains linear address of the page directory + add ebx,0x800 + call MEM_Alloc_Pages ;alloc page table for the region + mov eax,[ebx] + add dword [ebx],7 ;add flags + call MEM_Get_Linear_Address ;get linear address of the page table + mov ebx,eax + mov ecx,4096/4 ;number of pages in page table + mov eax,8*0x100000+7 +.loop3: +;ebx - linear address of page table +;eax - current linear address with flags + mov [ebx],eax + add ebx,4 + add eax,4096 + loop .loop3 + +;map region 0xC0000000-* to 0x0-* + mov esi,edx ;esi=linear address of the page directory + lea edi,[esi+(second_base_address shr 20)];add offset of entry (0xC00) + mov ecx,4 + rep movsd ;first 16Mb of the region mapped as 0x0-0x1000000 block + mov eax,[0xfe8c] ;eax=memory size + add eax,0x3fffff + shr eax,22 + mov esi,eax ;calculate number of entries in page directory + sub esi,4 ;subtract entries for first 16Mb. + mov ebp,0x1000000+7 ;start physical address with flags + +;mapping memory higher than 16Mb +.loop4: +;esi (counter) - number of entries in page directory +;edi - address of entry + test esi,esi + jle .loop4end + call MEM_Alloc_Page ;alloc page table for entry in page directory + mov [edi],eax + add dword [edi],7 ;write physical address of page table in page directory + add edi,4 ;move entry pointer + call MEM_Get_Linear_Address + mov ecx,eax + xor edx,edx + +.loop5: +;ecx - linear address of page table +;edx - index of page in page table +;ebp - current mapped physical address with flags + mov [ecx+4*edx],ebp ;write address of page in page table + add ebp,0x1000 ;move to next page + inc edx + cmp edx,4096/4 + jl .loop5 + + dec esi + jmp .loop4 +.loop4end: + +.set_cr3: +;set value of cr3 register to the address of page directory + mov eax,[general_page_table] + add eax,8+16 ;add flags + mov cr3,eax ;now we have full access paging + + popad + ret +;----------------------------------------------------------------------------- +simple_clone_cr3_table: +;Parameters: +; eax - physical address of cr3 table (page directory) +;result: +; eax - physical address of clone of cr3 table. +;Function copy only page directory. + push ecx + push edx + push esi + push edi + call MEM_Get_Linear_Address +;eax - linear address of cr3 table + mov esi,eax + call MEM_Alloc_Page + test eax,eax + jz .failed +;eax - physical address of new page diretory + mov edx,eax + call MEM_Get_Linear_Address + mov edi,eax + mov ecx,4096/4 + cld +;esi - address of old page directory +;edi - address of new page directory + rep movsd ;copy page directory + mov eax,edx +.failed: + pop edi + pop esi + pop edx + pop ecx + ret + +;----------------------------------------------------------------------------- +create_app_cr3_table: +;Parameters: +; eax - slot of process (index in 0x3000 table) +;result: +; eax - physical address of table. +;This function create page directory for new process and +;write it physical address to offset 0xB8 of extended +;process information. + push ebx + + mov ebx,eax + mov eax,[general_page_table] + call simple_clone_cr3_table ;clone general page table + shl ebx,8 + mov [second_base_address+0x80000+ebx+0xB8],eax ;save address of page directory + + pop ebx + ret +;----------------------------------------------------------------------------- +get_cr3_table: +;Input: +; eax - slot of process +;result: +; eax - physical address of page directory + shl eax,8 ;size of process extended information=256 bytes + mov eax,[second_base_address+0x80000+eax+0xB8] + ret +;----------------------------------------------------------------------------- +dispose_app_cr3_table: +;Input: +; eax - slot of process +;result: +; none +;This procedure frees page directory, +;page tables and all memory of process. + pushad + mov ebp,eax +;ebp = process slot in the procedure. + shl eax,8 + mov eax,[second_base_address+0x80000+eax+0xB8] + mov ebx,eax +;ebx = physical address of page directory + call MEM_Get_Linear_Address + mov edi,eax +;edi = linear address of page directory + mov eax,[edi+(std_application_base_address shr 20)] + and eax,not (4096-1) + call MEM_Get_Linear_Address + mov esi,eax +;esi = linear address of first page table + +;search threads +; mov ecx,0x200 + xor edx,edx + mov eax,0x2 + +.loop: +;eax = current slot of process + mov ecx,eax + shl ecx,5 + cmp byte [second_base_address+0x3000+ecx+0xa],0 ;if process running? + jnz .next ;slot empty or process is terminating - go to next slot + shl ecx,3 + cmp [second_base_address+0x80000+ecx+0xB8],ebx ;compare page directory addresses + jnz .next + inc edx ;thread found +.next: + inc eax + cmp eax,[0x3004] ;exit loop if we look through all processes + jle .loop + +;edx = number of threads +;our process is zombi so it isn't counted + test edx,edx + jnz .threadsexists +;if there isn't threads then clear memory. + add edi,std_application_base_address shr 20 + +.loop1: +;edi = linear address of current directory entry +;esi = linear address of current page table + test esi,esi + jz .loop1end + xor ecx,ecx + +.loop2: +;ecx = index of page + mov eax,[esi+4*ecx] + test eax,eax + jz .loopend ;skip empty entries + and eax,not (4096-1) ;clear flags + push ecx + call MEM_Free_Page ;free page + pop ecx +.loopend: + inc ecx + cmp ecx,1024 ;there are 1024 pages in page table + jl .loop2 + + mov eax,esi + call MEM_Free_Page_Linear ;free page table +.loop1end: + add edi,4 ;move to next directory entry + mov eax,[edi] + and eax,not (4096-1) + call MEM_Get_Linear_Address + mov esi,eax ;calculate linear address of new page table + test edi,0x800 + jz .loop1 ;test if we at 0x80000000 address? + + and edi,not (4096-1) ;clear offset of page directory entry + mov eax,edi + call MEM_Free_Page_Linear ;free page directory + popad + ret + +.threadsexists: ;do nothing + popad ;last thread will free memory + ret +;----------------------------------------------------------------------------- +mem_alloc_specified_region: +;eax - linear directory address +;ebx - start address (aligned to 4096 bytes) +;ecx - size in pages +;result: +; eax=1 - ok +; eax=0 - failed +;Try to alloc and map ecx pages to [ebx;ebx+4096*ecx) interval. + pushad + mov ebp,ebx ;save start address for recoil + mov esi,eax +.gen_loop: +;esi = linear directory address +;ebx = current address +;ecx = remaining size in pages + mov edx,ebx + shr edx,22 + mov edi,[esi+4*edx] ;find directory entry for current address + test edi,edi + jnz .table_exists ;check if page table allocated + call MEM_Alloc_Page ;alloc page table + test eax,eax + jz .failed + mov [esi+4*edx],eax + add dword [esi+4*edx],7 ;write it address with flags + call MEM_Get_Linear_Address + call mem_fill_page ;clear page table + jmp .table_linear +.table_exists: +;calculate linear address of page table + mov eax,edi + and eax,not (4096-1) ;clear flags + call MEM_Get_Linear_Address +.table_linear: +;eax = linear address of page table + mov edx,ebx + shr edx,12 + and edx,(1024-1) ;calculate index in page table + mov edi,eax + +.loop: +;edi = linear address of page table +;edx = current page table index +;ecx = remaining size in pages +;ebx = current address + test ecx,ecx + jle .endloop1 ;all requested pages allocated + + call MEM_Alloc_Page ;alloc new page + test eax,eax + jz .failed + mov [edi+4*edx],eax + add dword [edi+4*edx],7 ;write it address with flags + call MEM_Get_Linear_Address + call mem_fill_page ;clear new page +;go to next page table entry + dec ecx + add ebx,4096 + inc edx + test edx,(1024-1) + jnz .loop + + jmp .gen_loop + +.endloop1: + popad + mov eax,1 ;ok + ret + +.failed: +;calculate data for recoil + sub ebx,ebp + shr ebx,12 + mov ecx,ebx ;calculate number of allocated pages + mov eax,esi ;restore linear address of page directory + mov ebx,ebp ;restore initial address + call mem_free_specified_region ;free all allocated pages + popad + xor eax,eax ;fail + ret +;----------------------------------------------------------------------------- +mem_fill_page: +;Input: +; eax - address +;result: +; none +;set to zero 4096 bytes at eax address. + push ecx + push edi + mov edi,eax + mov ecx,4096/4 + xor eax,eax + rep stosd + lea eax,[edi-4096] + pop edi + pop ecx + ret +;----------------------------------------------------------------------------- +mem_free_specified_region: +;eax - linear page directory address +;ebx - start address (aligned to 4096 bytes) +;ecx - size in pages +;result - none +;Free pages in [ebx;ebx+4096*ecx) region. + pushad + mov esi,eax + xor ebp,ebp + +.gen_loop: +;esi = linear page directory address +;ebx = current address +;ecx = remaining pages +;ebp = 0 for first page table +; 1 otherwise + mov edx,ebx + shr edx,22 + mov eax,[esi+4*edx] ;find directory entry for current address + and eax,not (4096-1) + test eax,eax + jnz .table_exists +;skip absent page tables + mov edx,ebx + shr edx,12 + and edx,(1024-1) ;edx - index of current page + add ebx,1 shl 22 + add ecx,edx + and ebx,not ((1 shl 22)-1) + mov ebp,1 ;set flag + sub ecx,1024 ;ecx=ecx-(1024-edx) + jg .gen_loop + popad + ret +.table_exists: + call MEM_Get_Linear_Address +;eax - linear address of table + mov edx,ebx + shr edx,12 + and edx,(1024-1) ;edx - index of current page + mov edi,eax + +.loop: +;edi = linear address of page table entry +;edx = index of page table entry +;ecx = remaining pages + test ecx,ecx + jle .endloop1 + + mov eax,[edi+4*edx] + and eax,not (4096-1) + call MEM_Free_Page ;free page + mov dword [edi+4*edx],0 ;and clear page table entry + dec ecx + inc edx + cmp edx,1024 + jl .loop + + test ebp,ebp + jz .first_page + mov eax,edi + call MEM_Free_Page_Linear ;free page table + mov edx,ebx + shr edx,22 + mov dword [esi+4*edx],0 ;and clear page directory entry +.first_page: + add ebx,1 shl 22 + and ebx,not ((1 shl 22)-1) ;calculate new current address + mov ebp,1 ;set flag + jmp .gen_loop + +.endloop1: + popad + ret +end if diff --git a/trunk/core/memmanag.inc b/trunk/core/memmanag.inc new file mode 100644 index 000000000..e1bea9c46 --- /dev/null +++ b/trunk/core/memmanag.inc @@ -0,0 +1,977 @@ +if ~defined memmanager_inc +memmanager_inc_fix: +memmanager_inc fix memmanager_inc_fix +;for testing in applications +if defined B32 + iskernel=1 +else + iskernel=0 +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Memory allocator for MenuetOS kernel +;; Andrey Halyavin, halyavin@land.ru 2005 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; heap block structure - +;; you can handle several ranges of +;; pages simultaneosly. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.heap_linear_address equ 0 +.heap_block_size equ 4 +.heap_physical_address equ 8 +.heap_reserved equ 12 +.heap_block_info equ 16 +max_heaps equ 8 +.range_info equ 36 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; memory manager data +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +MEM_heap_block_ rd .heap_block_info*max_heaps/4 +MEM_heap_block=MEM_heap_block_+second_base_address +MEM_heap_count_ rd 1 +MEM_heap_count=MEM_heap_count_+second_base_address +if iskernel = 0 +MEM_general_mutex rd 1 +MEM_call_count rd 1 +MEM_mutex_pid rd 1 +MEM_mutex_count rd 1 +else +MEM_cli_count_ rd 1 +MEM_cli_count=MEM_cli_count_+second_base_address +MEM_cli_prev_ rd 1 +MEM_cli_prev=MEM_cli_prev_+second_base_address +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Init +;;Initialize memory manager structures. +;;Must be called first. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +MEM_Init: + push eax + xor eax,eax +if iskernel = 0 + mov [MEM_heap_count],eax + mov [MEM_general_mutex],eax + mov [MEM_call_count],eax + mov [MEM_mutex_pid],eax + mov [MEM_mutex_count],eax +else + mov [MEM_cli_prev],eax ;init value = 0 + dec eax + mov [MEM_cli_count],eax ;init value = -1 +end if + pop eax + ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;change_task +;;procedure for changing tasks. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if iskernel = 0 +change_task: + push eax + push ebx + mov eax,5 + xor ebx,ebx + inc ebx + int 0x40 + pop ebx + pop eax + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_get_pid +;;determine current pid +;;result: +;; eax - pid +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if iskernel = 0 +MEM_get_pid: + push ebx + push ecx + sub esp,1024 + mov eax,9 + mov ebx,esp + mov ecx,-1 + int 0x40 + mov eax,[esp+30] + add esp,1024 + pop ecx + pop ebx + ret +else +; pid_address dd 0x3000 +;MEM_get_pid: +; mov eax,[pid_address] +; mov eax,[eax] +; ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Heap_Lock +;;Wait until all operations with heap will be finished. +;;Between MEM_Heap_Lock and MEM_Heap_UnLock operations +;;with heap are forbidden. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +MEM_Heap_Lock: +if iskernel = 0 + push eax + inc dword [MEM_call_count] +MEM_Heap_Lock_wait: + mov eax,1 + xchg [MEM_general_mutex],eax + test eax,eax + jz MEM_Heap_Lock_end + call MEM_get_pid + cmp [MEM_mutex_pid],eax + jz MEM_Heap_Lock_end1 + call change_task + jmp MEM_Heap_Lock_wait +MEM_Heap_Lock_end1: + inc dword [MEM_mutex_count] + pop eax + ret +MEM_Heap_Lock_end: + call MEM_get_pid + mov [MEM_mutex_pid],eax + mov dword [MEM_mutex_count],1 + pop eax + ret +else + pushfd + cli + inc dword [MEM_cli_count] + jz MEM_Heap_First_Lock + add esp,4 + ret +MEM_Heap_First_Lock: ;save interrupt flag + shr dword [esp],9 + and dword [esp],1 + pop dword [MEM_cli_prev] + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Heap_UnLock +;;After this routine operations with heap are allowed. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +MEM_Heap_UnLock: +if iskernel = 0 + push eax + xor eax,eax + dec dword [MEM_mutex_count] + jnz MEM_Heap_UnLock_No_Wait1 + dec dword [MEM_call_count] + mov [MEM_mutex_pid],eax + mov [MEM_general_mutex],eax;release mutex BEFORE task switching + jz MEM_Heap_UnLock_No_Wait + call change_task ;someone want to use heap - switch tasks +MEM_Heap_UnLock_No_Wait: + pop eax + ret +MEM_Heap_UnLock_No_Wait1: + dec dword [MEM_call_count] + jz MEM_Heap_UnLock_No_Wait2 + call change_task +MEM_Heap_UnLock_No_Wait2: + pop eax + ret +else + dec dword [MEM_cli_count] + js MEM_Heap_UnLock_last + ret +MEM_Heap_UnLock_last: + cmp dword [MEM_cli_prev],0 ;restore saved interrupt flag + jz MEM_Heap_UnLock_No_sti + sti +MEM_Heap_UnLock_No_sti: + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Add_Heap +;;Add new range to memory manager. +;;eax - linear address +;;ebx - size in pages +;;ecx - physical address +;;Result: +;; eax=1 - success +;; eax=0 - failed +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +MEM_Add_Heap: + push edx + call MEM_Heap_Lock + mov edx,[MEM_heap_count] + cmp edx,max_heaps + jz MEM_Add_Heap_Error + inc dword [MEM_heap_count] + shl edx,4 + mov [MEM_heap_block+edx+.heap_linear_address],eax + mov [MEM_heap_block+edx+.heap_block_size],ebx + shl dword [MEM_heap_block+edx+.heap_block_size],12 + mov [MEM_heap_block+edx+.heap_physical_address],ecx + lea edx,[4*ebx+.range_info+4095] ;calculate space for page info table + and edx,0xFFFFF000 + mov [eax],eax + add [eax],edx ;first 4 bytes - pointer to first free page +;clean page info area + push edi + lea edi,[eax+4] + mov ecx,edx + shr ecx,2 + push eax + xor eax,eax + rep stosd + pop eax + pop edi +;create free pages list. + mov ecx,[eax] + shl ebx,12 + add eax,ebx ;eax - address after block +MEM_Add_Heap_loop: + add ecx,4096 + mov [ecx-4096],ecx ;set forward pointer + cmp ecx,eax + jnz MEM_Add_Heap_loop + mov dword [ecx-4096],0 ;set end of list +MEM_Add_Heap_ret: + call MEM_Heap_UnLock + pop edx + ret +MEM_Add_Heap_Error: + xor eax,eax + jmp MEM_Add_Heap_ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Get_Physical_Address +;;Translate linear address to physical address +;;Parameters: +;; eax - linear address +;;Result: +;; eax - physical address +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Get_Physical_Address +MEM_Get_Physical_Address: + push ecx + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Get_Physical_Address_loop: + sub eax,[MEM_heap_block+ecx+.heap_linear_address] + jl MEM_Get_Physical_Address_next + cmp eax,[MEM_heap_block+ecx+.heap_block_size] + jge MEM_Get_Physical_Address_next + add eax,[MEM_heap_block+ecx+.heap_physical_address] + jmp MEM_Get_Physical_Address_loopend +MEM_Get_Physical_Address_next: + add eax,[MEM_heap_block+ecx+.heap_linear_address] + sub ecx,16 + jns MEM_Get_Physical_Address_loop + xor eax,eax ;address not found +MEM_Get_Physical_Address_loopend: + call MEM_Heap_UnLock + pop ecx + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Get_Linear_Address +;;Translate physical address to linear address. +;;Parameters: +;; eax - physical address +;;Result: +;; eax - linear address +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Get_Linear_Address +MEM_Get_Linear_Address: + push ecx + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Get_Linear_Address_loop: + sub eax,[MEM_heap_block+ecx+.heap_physical_address] + jl MEM_Get_Linear_Address_Next + cmp eax,[MEM_heap_block+ecx+.heap_block_size] + jge MEM_Get_Linear_Address_Next + add eax,[MEM_heap_block+ecx+.heap_linear_address] + call MEM_Heap_UnLock + pop ecx + ret +MEM_Get_Linear_Address_Next: + add eax,[MEM_heap_block+ecx+.heap_physical_address] + sub ecx,16 + jns MEM_Get_Linear_Address_loop + call MEM_Heap_UnLock + pop ecx + xor eax,eax ;address not found + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Alloc_Page +;;Allocate and add reference to page +;;Result: +;; eax<>0 - physical address of page +;; eax=0 - not enough memory +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Alloc_Page +MEM_Alloc_Page: + push ecx + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Alloc_Page_loop: + push ecx + mov ecx,[MEM_heap_block+ecx+.heap_linear_address] + cmp dword [ecx],0 + jz MEM_Alloc_Page_loopend + mov eax,[ecx] + push dword [eax] + pop dword [ecx] + sub eax,ecx + push eax + shr eax,10 + mov word [ecx+.range_info+eax],1 + pop eax + pop ecx + add eax,[MEM_heap_block+ecx+.heap_physical_address] + jmp MEM_Alloc_Page_ret +MEM_Alloc_Page_loopend: + pop ecx + sub ecx,16 + jns MEM_Alloc_Page_loop + xor eax,eax +MEM_Alloc_Page_ret: + call MEM_Heap_UnLock + pop ecx + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Alloc_Page_Linear +;;Allocate and add reference to page +;;Result: +;; eax<>0 - linear address of page +;; eax=0 - not enough memory +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Alloc_Page_Linear +MEM_Alloc_Page_Linear: + push ecx + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Alloc_Page_Linear_loop: + push ecx + mov ecx,[MEM_heap_block+ecx+.heap_linear_address] + cmp dword [ecx],0 + jz MEM_Alloc_Page_Linear_loopend + mov eax,[ecx] + push dword [eax] + pop dword [ecx] + push eax + sub eax,ecx + shr eax,10 + mov word [ecx+.range_info+eax],1 + pop eax + pop ecx + jmp MEM_Alloc_Page_Linear_ret +MEM_Alloc_Page_Linear_loopend: + pop ecx + sub ecx,16 + jns MEM_Alloc_Page_Linear_loop + xor eax,eax +MEM_Alloc_Page_Linear_ret: + call MEM_Heap_UnLock + pop ecx + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Free_Page +;;Remove reference and free page if number of +;;references is equal to 0 +;;Parameters: +;; eax - physical address of page +;;Result: +;; eax - 1 success +;; eax - 0 failed +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Free_Page +MEM_Free_Page: + test eax,eax + jz MEM_Free_Page_Zero + test eax,0xFFF + jnz MEM_Free_Page_Not_Aligned + push ebx + push ecx + push edx + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Free_Page_Heap_loop: + sub eax,[MEM_heap_block+ecx+.heap_physical_address] + js MEM_Free_Page_Heap_loopnext + cmp eax,[MEM_heap_block+ecx+.heap_block_size] + jl MEM_Free_Page_Heap_loopend +MEM_Free_Page_Heap_loopnext: + add eax,[MEM_heap_block+ecx+.heap_physical_address] + sub ecx,16 + jns MEM_Free_Page_Heap_loop + xor eax,eax + inc eax + jmp MEM_Free_Page_ret +MEM_Free_Page_Heap_loopend: + mov ecx,[MEM_heap_block+ecx+.heap_linear_address] + mov ebx,eax + add eax,ecx + shr ebx,10 + mov edx,[ecx+.range_info+ebx] + test edx,0x80000000 + jnz MEM_Free_Page_Bucket + test dx,dx + jz MEM_Free_Page_Error + dec word [ecx+.range_info+ebx] + jnz MEM_Free_Page_OK +MEM_Free_Page_Bucket: + push dword [ecx] + mov [ecx],eax + pop dword [eax] + mov dword [ecx+.range_info+ebx],0 +MEM_Free_Page_OK: + mov eax,1 +MEM_Free_Page_ret: + call MEM_Heap_UnLock + pop edx + pop ecx + pop ebx + ret +MEM_Free_Page_Error: + xor eax,eax + jmp MEM_Free_Page_ret +MEM_Free_Page_Zero: + inc eax + ret +MEM_Free_Page_Not_Aligned: + xor eax,eax + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Free_Page_Linear +;;Remove reference and free page if number of +;;references is equal to 0 +;;Parameters: +;; eax - linear address of page +;;Result: +;; eax - 1 success +;; eax - 0 failed +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Free_Page_Linear +MEM_Free_Page_Linear: + test eax,eax + jz MEM_Free_Page_Linear_Zero + test eax,0xFFF + jnz MEM_Free_Page_Linear_Not_Aligned + push ebx + push ecx + push edx + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 + +MEM_Free_Page_Linear_Heap_loop: + sub eax,[MEM_heap_block+ecx+.heap_linear_address] + js MEM_Free_Page_Linear_Heap_loopnext + cmp eax,[MEM_heap_block+ecx+.heap_block_size] + jl MEM_Free_Page_Linear_Heap_loopend +MEM_Free_Page_Linear_Heap_loopnext: + add eax,[MEM_heap_block+ecx+.heap_linear_address] + sub ecx,16 + jns MEM_Free_Page_Linear_Heap_loop + xor eax,eax + inc eax + jmp MEM_Free_Page_Linear_ret + +MEM_Free_Page_Linear_Heap_loopend: + mov ecx,[MEM_heap_block+ecx+.heap_linear_address] + mov ebx,eax + add eax,ecx + shr ebx,10 + mov edx,[ecx+.range_info+ebx] + test edx,0x80000000 + jnz MEM_Free_Page_Linear_Bucket + test dx,dx + jz MEM_Free_Page_Linear_Error + dec word [ecx+.range_info+ebx] + jnz MEM_Free_Page_Linear_OK +MEM_Free_Page_Linear_Bucket: + mov edx,[ecx] + mov [eax],edx + mov dword [eax+4],0 + mov [ecx],eax + test edx,edx + jz MEM_Free_Page_No_Next + mov [edx+4],eax +MEM_Free_Page_No_Next: + mov dword [ecx+.range_info+ebx],0 +MEM_Free_Page_Linear_OK: + xor eax, eax + inc eax +MEM_Free_Page_Linear_ret: + call MEM_Heap_UnLock + pop edx + pop ecx + pop ebx + ret + +MEM_Free_Page_Linear_Error: + xor eax,eax + jmp MEM_Free_Page_Linear_ret + +MEM_Free_Page_Linear_Zero: + inc eax + ret + +MEM_Free_Page_Linear_Not_Aligned: + xor eax,eax + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Alloc_Pages +;;Allocates set of pages. +;;Parameters: +;; eax - number of pages +;; ebx - buffer for physical addresses +;;Result: +;; eax - number of allocated pages +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Alloc_Pages +MEM_Alloc_Pages: + push eax + push ebx + push ecx + mov ecx,eax + test ecx,ecx + jz MEM_Alloc_Pages_ret +MEM_Alloc_Pages_loop: + call MEM_Alloc_Page + test eax,eax + jz MEM_Alloc_Pages_ret + mov [ebx],eax + add ebx,4 + dec ecx + jnz MEM_Alloc_Pages_loop +MEM_Alloc_Pages_ret: + sub [esp+8],ecx + pop ecx + pop ebx + pop eax + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Alloc_Pages_Linear +;;Allocates set of pages. +;;Parameters: +;; eax - number of pages +;; ebx - buffer for linear addresses +;;Result: +;; eax - number of allocated pages +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Alloc_Pages_Linear +MEM_Alloc_Pages_Linear: + push eax + push ebx + push ecx + mov ecx,eax + test ecx,ecx + jz MEM_Alloc_Pages_Linear_ret +MEM_Alloc_Pages_Linear_loop: + call MEM_Alloc_Page_Linear + test eax,eax + jz MEM_Alloc_Pages_Linear_ret + mov [ebx],eax + add ebx,4 + dec ecx + jnz MEM_Alloc_Pages_Linear_loop +MEM_Alloc_Pages_Linear_ret: + sub [esp+8],ecx + pop ecx + pop ebx + pop eax + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Free_Pages +;;Parameters: +;; eax - number of pages +;; ebx - array of addresses +;;Result: +;; eax=1 - succcess +;; eax=0 - failed +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Free_Pages +MEM_Free_Pages: + push ebx + push ecx + mov ecx,eax + test ecx,ecx + jz MEM_Free_Pages_ret +MEM_Free_Pages_loop: + mov eax,[ebx] + call MEM_Free_Page + add ebx,4 + test eax,eax + jz MEM_Free_Pages_ret + dec ecx + jnz MEM_Free_Pages_loop +MEM_Free_Pages_ret: + pop ecx + pop ebx + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Free_Pages_Linear +;;Parameters: +;; eax - number of pages +;; ebx - array of addresses +;;Result: +;; eax=1 - succcess +;; eax=0 - failed +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Free_Pages_Linear +MEM_Free_Pages_Linear: + push ebx + push ecx + mov ecx,eax + test ecx,ecx + jz MEM_Free_Pages_Linear_ret +MEM_Free_Pages_Linear_loop: + mov eax,[ebx] + call MEM_Free_Page_Linear + add ebx,4 + test eax,eax + jz MEM_Free_Pages_Linear_ret + dec ecx + jnz MEM_Free_Pages_Linear_loop +MEM_Free_Pages_Linear_ret: + pop ecx + pop ebx + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Get_Heap_Number +;;Calculate number of heap which pointer belongs to. +;;Parameter: +;; eax - address +;;Result: +;; ecx - number of heap*16. +;; eax=0 if address not found. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Get_Heap_Number +MEM_Get_Heap_Number: + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Get_Heap_loop: + sub eax,[MEM_heap_block+ecx+.heap_physical_address] + jl MEM_Get_Heap_loopnext + cmp eax,[MEM_heap_block+ecx+.heap_block_size] + jl MEM_Get_Heap_loopend +MEM_Get_Heap_loopnext: + add eax,[MEM_heap_block+ecx+.heap_physical_address] + sub ecx,16 + jns MEM_Get_Heap_loop + call MEM_Heap_UnLock + xor eax,eax + ret +MEM_Get_Heap_loopend: + add eax,[MEM_heap_block+ecx+.heap_physical_address] + call MEM_Heap_UnLock + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Get_Heap_Number_Linear +;;Calculate number of heap which pointer belongs to. +;;Parameter: +;; eax - address +;;Result: +;; ecx - number of heap*16. +;; eax=0 if address not found. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if used MEM_Get_Heap_Number_Linear +MEM_Get_Heap_Number_Linear: + call MEM_Heap_Lock + mov ecx,[MEM_heap_count] + dec ecx + shl ecx,4 +MEM_Get_Heap_Linear_loop: + sub eax,[MEM_heap_block+ecx+.heap_linear_address] + jl MEM_Get_Heap_Linear_loopnext + cmp eax,[MEM_heap_block+ecx+.heap_block_size] + jl MEM_Get_Heap_Linear_loopend +MEM_Get_Heap_Linear_loopnext: + add eax,[MEM_heap_block+ecx+.heap_linear_address] + sub ecx,16 + jns MEM_Get_Heap_Linear_loop + call MEM_Heap_UnLock + xor eax,eax + ret +MEM_Get_Heap_Linear_loopend: + add eax,[MEM_heap_block+ecx+.heap_linear_address] + call MEM_Heap_UnLock + ret +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;MEM_Alloc +;;Allocate small region. +;;Parameters: +;; eax - size (00 - ok +; 0 - failed. +;This function find least empty slot. +;It doesn't increase [0x3004]! + mov eax,0x3000+second_base_address + push ebx + mov ebx,[0x3004] + inc ebx + shl ebx,5 + add ebx,eax ;ebx - address of process information for (last+1) slot +.newprocessplace: +;eax = address of process information for current slot + cmp eax,ebx + jz .endnewprocessplace ;empty slot after high boundary + add eax,0x20 + cmp word [eax+0xa],9 ;check process state, 9 means that process slot is empty + jnz .newprocessplace +.endnewprocessplace: + mov ebx,eax + sub eax,0x3000+second_base_address + shr eax,5 ;calculate slot index + cmp eax,256 + jge .failed ;it should be <256 + mov word [ebx+0xa],9 ;set process state to 9 (for slot after hight boundary) + mov [new_process_place],eax ;save process slot + pop ebx + ret +.failed: + xor eax,eax + pop ebx + ret +;----------------------------------------------------------------------------- + +new_start_application_floppy: +;input: +; eax - pointer to filename +; ebx - parameters to pass +;result: +; eax - pid of new process +; or 0 if call fails. + pushad + mov esi,new_process_loading + call sys_msg_board_str ;write to debug board + +;wait application_table_status mutex +.table_status: + cli + cmp [application_table_status],0 + jz .stf + sti + call change_task + jmp .table_status +.stf: + call set_application_table_status +;we can change system tables now + push edi + push ebx + push eax + call find_new_process_place ;find empty process slot + sti + test eax,eax + jz .failed + + mov edi,eax + shl edi,8 + add edi,0x80000 + mov ecx,256/4 + xor eax,eax + cld + rep stosd ;clean extended information about process + +;set new process name + mov eax,[esp+8] +.find_last_byte: + cmp byte [eax],0 + jz .find_last_byte_end + inc eax + jmp .find_last_byte +.find_last_byte_end: + sub eax,11 ;last 11 bytes = application name +; mov eax,[esp] ;eax - pointer to file name + mov ebx,[new_process_place] + shl ebx,8 + add ebx,0x80000 + mov ecx,11 + call memmove + +;read header of file + mov eax,[esp] + mov ebx,1 ;index of first block + mov ecx,2 ;number of blocks + mov edx,0x90000 ;temp area + mov esi,12 ;file name length + mov edi,[esp+8] +; cli + call floppy_fileread ;read file from FD +; sti + cmp eax,0 + jne .cleanfailed +;check MENUET signature + cmp [0x90000],dword 'MENU' + jnz .cleanfailed + cmp [0x90004],word 'ET' + jnz .cleanfailed + + call get_app_params ;parse header fields + cmp esi,0 + jz .cleanfailed + + mov eax,[new_process_place] + call create_app_cr3_table ;create page directory for new process + test eax,eax + jz .cleanfailed_mem + + call MEM_Get_Linear_Address ;calculate linear address of it + + mov ebx,std_application_base_address + mov ecx,[app_mem] + add ecx,4095 + shr ecx,12 + mov edx,eax + call mem_alloc_specified_region ;allocate memory for application + test eax,eax + jz .cleanfailed_mem + + mov eax,[edx+(std_application_base_address shr 20)] + and eax,not (4096-1) ;eax - physical address of first (for application memory) page table + call MEM_Get_Linear_Address + mov edx,eax + +;read file + mov ebx,1 + mov esi,12 ;length of file name +.loop1: +;edx = linear address of current page table entry +;ebx = index of current block in file + push edx + mov eax,[edx] + and eax,not (4096-1) + call MEM_Get_Linear_Address + mov edx,eax ;read file block to current page + mov eax,[esp+4] ;restore pointer to file name + mov ecx,8 ;number of blocks read + push ebx + mov edi,[esp+16] +; cli + call floppy_fileread +;ebx=file size +; sti + pop ecx + shr ebx,9 + cmp ecx,ebx + jg .endloop1 ;if end of file? + mov ebx,ecx + test eax,eax + jnz .endloop1 ;check io errors + pop edx + add ebx,8 ;go to next page + add edx,4 + jmp .loop1 + +.endloop1: + add esp,8+4 ;pop linear address of page table entry and pointer to file name + call new_start_application_fl.add_app_parameters + mov [esp+28],eax + popad + ret +.cleanfailed_mem: + mov esi,start_not_enough_memory + call sys_msg_board_str +.cleanfailed: ;clean process name + mov edi,[new_process_place] + shl edi,8 + add edi,0x80000 + mov ecx,11 + mov eax,' ' + cld + rep stosb +.failed: + add esp,8+4 + mov [application_table_status],0 + popad + sti + mov eax,-1 + ret + +;----------------------------------------------------------------------------- +new_start_application_fl: +;input: +; eax - pointer to filename +; ebx - parameters to pass +;result: +; eax - pid of new process +; or 0 if call fails. + pushad + mov esi,new_process_loading + call sys_msg_board_str ;write to debug board + +;wait application_table_status mutex +.table_status: + cli + cmp [application_table_status],0 + jz .stf + sti + call change_task + jmp .table_status +.stf: + call set_application_table_status +;we can change system tables now + push ebx + push eax + call find_new_process_place ;find empty process slot + sti + test eax,eax + jz .failed + + mov edi,eax + shl edi,8 + add edi,0x80000 + mov ecx,256/4 + xor eax,eax + cld + rep stosd ;clean extended information about process + +;set new process name + mov eax,[esp] ;eax - pointer to file name + mov ebx,[new_process_place] + shl ebx,8 + add ebx,0x80000 + mov ecx,11 + call memmove + +;read header of file + mov ebx,1 ;index of first block + mov ecx,2 ;number of blocks + mov edx,0x90000 ;temp area + mov esi,12 ;file name length + cli + call fileread ;read file from RD + sti + cmp eax,0 + jne .cleanfailed +;check MENUET signature + cmp [0x90000],dword 'MENU' + jnz .cleanfailed + cmp [0x90004],word 'ET' + jnz .cleanfailed + + call get_app_params ;parse header fields + cmp esi,0 + jz .failed + + mov eax,[new_process_place] + call create_app_cr3_table ;create page directory for new process + test eax,eax + jz .cleanfailed_mem + + call MEM_Get_Linear_Address ;calculate linear address of it + + mov ebx,std_application_base_address + mov ecx,[app_mem] + add ecx,4095 + shr ecx,12 + mov edx,eax + call mem_alloc_specified_region ;allocate memory for application + test eax,eax + jz .cleanfailed_mem + + mov eax,[edx+(std_application_base_address shr 20)] + and eax,not (4096-1) ;eax - physical address of first (for application memory) page table + call MEM_Get_Linear_Address + mov edx,eax + +;read file + mov ebx,1 + mov esi,12 ;length of file name +.loop1: +;edx = linear address of current page table entry +;ebx = index of current block in file + push edx + mov eax,[edx] + and eax,not (4096-1) + call MEM_Get_Linear_Address + mov edx,eax ;read file block to current page + mov eax,[esp+4] ;restore pointer to file name + mov ecx,8 ;number of blocks read + push ebx + cli + call fileread +;ebx=file size + sti + pop ecx + shr ebx,9 + cmp ecx,ebx + jg .endloop1 ;if end of file? + mov ebx,ecx + test eax,eax + jnz .endloop1 ;check io errors + pop edx + add ebx,8 ;go to next page + add edx,4 + jmp .loop1 + +.endloop1: + add esp,8 ;pop linear address of page table entry and pointer to file name + call .add_app_parameters + mov [esp+28],eax + popad + ret + +.cleanfailed_mem: + mov esi,start_not_enough_memory + call sys_msg_board_str +.cleanfailed: ;clean process name + mov edi,[new_process_place] + shl edi,8 + add edi,0x80000 + mov ecx,11 + mov eax,' ' + cld + rep stosb +.failed: + add esp,8 + mov [application_table_status],0 + popad + sti + mov eax,-1 + ret + +.add_app_parameters: +;input: +; [esp] - pointer to parameters +; [esp+4]-[esp+36] pushad registers. +;result +; eax - pid of new process +; or zero if failed + cli + mov ebx,[new_process_place] + cmp ebx,[0x3004] + jle .noinc + inc dword [0x3004] ;update number of processes +.noinc: + +; mov ebx,[new_process_place] +;set 0x8c field of extended information about process +;(size of application memory) + shl ebx,8 + mov eax,[app_mem] + mov [second_base_address+0x80000+0x8c+ebx],eax +;set 0x10 field of information about process +;(application base address) +; mov ebx,[new_process_place] +; shl ebx,5 + shr ebx,3 + mov dword [second_base_address+0x3000+ebx+0x10],std_application_base_address + +;add command line parameters +.add_command_line: + mov edx,[app_i_param] + test edx,edx + jz .no_command_line ;application don't need parameters + mov eax,[esp+4] + test eax,eax + jz .no_command_line ;no parameters specified +;calculate parameter length + mov esi,eax + xor ecx,ecx +.command_line_len: + cmp byte [esi],0 + jz .command_line_len_end + inc esi + inc ecx + cmp ecx,256 + jl .command_line_len + +.command_line_len_end: +;ecx - parameter length +;edx - address of parameters in new process address space + mov ebx,eax ;ebx - address of parameters in our address space + mov eax,[new_process_place] + call write_process_memory ;copy parameters to new process address space + +.no_command_line: + mov ebx,[new_process_place] + mov eax,ebx + shl ebx,5 + add ebx,0x3000 ;ebx - pointer to information about process + mov [ebx+0xe],al ;set window number on screen = process slot + + mov [ebx],dword 1+2+4 ;set default event flags (see 40 function) + + inc dword [process_number] + mov eax,[process_number] + mov [ebx+4],eax ;set PID + + mov ecx,ebx + add ecx,draw_data-0x3000 ;ecx - pointer to draw data +;set draw data to full screen + mov [ecx+0],dword 0 + mov [ecx+4],dword 0 + mov eax,[0xfe00] + mov [ecx+8],eax + mov eax,[0xfe04] + mov [ecx+12],eax +;set cr3 register in TSS of application + mov ecx,[new_process_place] + shl ecx,8 + mov eax,[0x800B8+ecx] + add eax,8+16 ;add flags + mov [l.cr3],eax +;write cr3 in TSS of System Call Handler + mov ecx,[new_process_place] + shl ecx,7 + mov [0x298000+ecx+l.cr3-tss_sceleton],eax ;write directy to TSS + + mov eax,[app_start] + mov [l.eip],eax ;set eip in TSS + mov eax,[app_esp] + mov [l.esp],eax ;set stack in TSS + +;gdt + mov ebx,[new_process_place] + shl ebx,3 + mov ax,app_code ;ax - selector of code segment + add ax,bx + mov [l.cs],ax + mov ax,app_data + add ax,bx ;ax - selector of data segment + mov [l.ss],ax + mov [l.ds],ax + mov [l.es],ax + mov [l.fs],ax + mov ax,graph_data ;ax - selector of graphic segment + mov [l.gs],ax + mov [l.io],word 128 + mov [l.eflags],dword 0x11202 + mov [l.ss0],os_data + mov [l.esp0],0x55000 +; mov [l.esp1],0x56000 +; mov [l.esp2],0x57000 + +;copy tss to it place + mov eax,tss_sceleton + mov ebx,[new_process_place] + imul ebx,tss_step + add ebx,tss_data ;ebx - address of application TSS + mov ecx,120 + call memmove + +;Add IO access table - bit array of permitted ports + or eax,-1 + mov edi,[new_process_place] + imul edi,tss_step + add edi,tss_data+128 + mov ecx,2048 + cld + rep stosd ;full access to 2048*8=16384 ports + + mov ecx,ebx ;ecx - address of application TSS + mov edi,[new_process_place] + shl edi,3 +;set TSS descriptor + mov [edi+gdts+tss0+0],word tss_step ;limit (size) + mov [edi+gdts+tss0+2],cx ;part of offset + mov eax,ecx + shr eax,16 + mov [edi+gdts+tss0+4],al ;part of offset + mov [edi+gdts+tss0+7],ah ;part of offset + mov [edi+gdts+tss0+5],word 01010000b*256+11101001b ;system flags + +;set code and data segments + mov eax,[new_process_place] + shl eax,3 +;set base address of code segment + mov word [eax+gdts+app_code-3+2],0 + mov byte [eax+gdts+app_code-3+4],0 + mov byte [eax+gdts+app_code-3+7],std_application_base_address shr 24 +;set limit of code segment +; mov ebx,[app_mem] +; add ebx,4095 +; shr ebx,12 + mov ebx,(0x80000000-std_application_base_address) shr 12 + mov [eax+gdts+app_code-3+0],bx + mov [eax+gdts+app_code-3+5],word 11010000b*256+11111010b+256*((0x80000000-std_application_base_address) shr 28) +;set base address of data segment + mov word [eax+gdts+app_data-3+2],0 + mov byte [eax+gdts+app_data-3+4],0 + mov byte [eax+gdts+app_data-3+7],std_application_base_address shr 24 +;set limit of data segment + mov [eax+gdts+app_data-3+0],bx + mov [eax+gdts+app_data-3+5],word 11010000b*256+11110010b+256*((0x80000000-std_application_base_address) shr 28) + + +;flush keyboard and buttons queue + mov [0xf400],byte 0 + mov [0xf500],byte 0 + + mov edi,[new_process_place] + shl edi,5 + add edi,window_data + mov ebx,[new_process_place] + movzx esi,word [0xC000+ebx*2] + lea esi,[0xC400+esi*2] + call windowactivate ;gui initialization + + mov ebx,[new_process_place] + shl ebx,5 + mov [0x3000+ebx+0xa],byte 0 ;set process state - running + + mov esi,new_process_running + call sys_msg_board_str ;output information about succefull startup + +; add esp,4 ;pop pointer to parameters +; popad + mov eax,[process_number] ;set result + mov [application_table_status],0 ;unlock application_table_status mutex + sti + ret 4 +;----------------------------------------------------------------------------- +new_sys_threads: +;eax=1 - create thread +; ebx=thread start +; ecx=thread stack value +;result: +; eax=pid + pushad + + cmp eax,1 + jnz .ret ;other subfunctions + mov esi,new_process_loading + call sys_msg_board_str +;lock application_table_status mutex +.table_status: + cli + cmp [application_table_status],0 + je .stf + sti + call change_task + jmp .table_status +.stf: + call set_application_table_status +;find free process slot + + call find_new_process_place + test eax,eax + jz .failed + +;set parameters for thread + xor eax,eax + mov [app_i_param],eax + mov [app_i_icon],eax + mov [app_start],ebx + mov [app_esp],ecx + + mov esi,[0x3000] + shl esi,8 + add esi,0x80000 + mov ebx,esi ;ebx=esi - pointer to extended information about current thread + + mov edi,[new_process_place] + shl edi,8 + add edi,0x80000 + mov edx,edi ;edx=edi - pointer to extended infomation about new thread + mov ecx,256/4 + rep stosd ;clean extended information about new thread + mov edi,edx + mov ecx,11 + rep movsb ;copy process name + mov eax,[ebx+0x8c] + mov [app_mem],eax ;set memory size + mov eax,[ebx+0xb8] + mov [edx+0xb8],eax ;copy page directory +; mov eax,[new_process_place] +; mov ebx,[0x3000] +; call addreference_app_cr3_table + + push 0 ;no parameters + call new_start_application_fl.add_app_parameters ;start thread + mov [esp+28],eax + popad + ret + +.failed: + sti + popad + mov eax,-1 + ret +.ret: + popad + ret +;----------------------------------------------------------------------------- +new_mem_resize: +;input: +; ebx - new size +;result: +; [esp+36]:=0 - normal +; [esp+36]:=1 - error +;This function set new application memory size. + mov esi,ebx ;save new size + add ebx,4095 + and ebx,not (4096-1) ;round up size + mov ecx,[0x3000] + shl ecx,8 + mov edx,[0x8008C+ecx] + add edx,4095 + and edx,not (4096-1) ;old size + mov eax,[0x800B8+ecx] + call MEM_Get_Linear_Address +;eax - linear address of page directory + call MEM_Heap_Lock ;guarantee that two threads willn't + ;change memory size simultaneously + cmp ebx,edx +; mov esi,ebx ;save new size + jg .expand + +.free: + sub edx,ebx + jz .unlock ;do nothing + mov ecx,edx + shr ecx,12 + add ebx,std_application_base_address + call mem_free_specified_region ;free unnecessary pages + jmp .unlock + +.expand: + sub ebx,edx + mov ecx,ebx + shr ecx,12 + mov ebx,edx + add ebx,std_application_base_address + call mem_alloc_specified_region ;alloc necessary pages + test eax,eax + jz .failed ;not enough memory + +.unlock: + mov ebx,esi + mov eax,[0x3000] + shl eax,8 + mov [eax+0x8008c],ebx ;write new memory size +;search threads and update +;application memory size infomation + mov ecx,[eax+0x800b8] + mov eax,2 + +.search_threads: +;eax = current slot +;ebx = new memory size +;ecx = page directory + cmp eax,[0x3004] + jg .search_threads_end + mov edx,eax + shl edx,5 + cmp word [0x3000+edx+0xa],9 ;if slot empty? + jz .search_threads_next + shl edx,3 + cmp [edx+0x800b8],ecx ;if it is our thread? + jnz .search_threads_next + mov [edx+0x8008c],ebx ;update memory size +.search_threads_next: + inc eax + jmp .search_threads +.search_threads_end: + + call MEM_Heap_UnLock + mov dword [esp+36],0 + ret + +.failed: + call MEM_Heap_UnLock + mov dword [esp+36],1 + ret +;----------------------------------------------------------------------------- +pid_to_slot: +;Input: +; eax - pid of process +;Output: +; eax - slot of process or 0 if process don't exists +;Search process by PID. + push ebx + push ecx + mov ebx,[0x3004] + shl ebx,5 + mov ecx,2*32 + +.loop: +;ecx=offset of current process info entry +;ebx=maximum permitted offset + cmp byte [second_base_address+0x3000+ecx+0xa],9 + jz .endloop ;skip empty slots + cmp [second_base_address+0x3000+ecx+0x4],eax ;check PID + jz .pid_found +.endloop: + add ecx,32 + cmp ecx,ebx + jle .loop + + pop ecx + pop ebx + xor eax,eax + ret + +.pid_found: + shr ecx,5 + mov eax,ecx ;convert offset to index of slot + pop ecx + pop ebx + ret +;----------------------------------------------------------------------------- +is_new_process: +;Input: +; eax - process slot +;Output: +; eax=1 - it is new process +; eax=0 - it is old process +; shl eax,5 +; mov eax,[second_base_address+0x3000+eax+0x10] +; cmp eax,std_application_base_address ;check base address of application +; jz .new_process +; xor eax,eax +; ret + +;.new_process: + mov eax,1 + ret +;----------------------------------------------------------------------------- +write_process_memory: +;Input: +; eax - process slot +; ebx - buffer address +; ecx - buffer size +; edx - start address in other process +;Output: +; eax - number of bytes written + pushad + shl eax,8 + mov eax,[0x80000+eax+0xB8] + call MEM_Get_Linear_Address + mov ebp,eax +;ebp=linear address of page directory of other process. + add edx,std_application_base_address ;convert to linear address + test ecx,ecx + jle .ret + +.write_loop: +;ebx = current buffer address +;ecx>0 = current size +;edx = current address in other process +;ebp = linear address of page directory + + call MEM_Heap_Lock ;cli + mov esi,edx + shr esi,22 + mov eax,[ebp+4*esi] ;find page directory entry + and eax,not (4096-1) ;clear flags + test eax,eax + jz .page_not_found + call MEM_Get_Linear_Address ;calculate linear address of page table + test eax,eax + jz .page_not_found + mov esi,edx + shr esi,12 + and esi,1023 + mov eax,[eax+4*esi] ;find page table entry + and eax,not (4096-1) + test eax,eax + jz .page_not_found + call MEM_Get_Linear_Address ;calculate linear address of page + test eax,eax + jz .page_not_found + mov edi,eax + call MEM_Add_Reference_Linear;guarantee that page willn't disappear + call MEM_Heap_UnLock ;sti + + mov esi,edx + and esi,4095 + add edi,esi ;add offset in page +;edi = linear address corresponding edx in other process + sub esi,4096 + neg esi ;esi - number of remaining bytes in page + cmp esi,ecx + jl .min_ecx + mov esi,ecx +.min_ecx: ;esi=min(ecx,esi) - number of bytes to write + sub ecx,esi + push ecx + mov ecx,esi ;ecx - number of bytes to write + mov esi,ebx ;esi - source, edi - destination + add edx,ecx ;move pointer in address space of other process + push edi + +;move ecx bytes + test ecx,3 + jnz .not_aligned + shr ecx,2 + rep movsd + jmp .next_iter +.not_aligned: + rep movsb +.next_iter: + + pop eax + and eax,not (4096-1) ;eax - linear address of current page + call MEM_Free_Page_Linear ;free reference + mov ebx,esi ;new pointer to buffer - movsb automaticaly advance it. + pop ecx ;restore number of remaining bytes + test ecx,ecx + jnz .write_loop +.ret: + popad + mov eax,ecx + ret + +.page_not_found: + call MEM_Heap_UnLock ;error has appeared in critical region + sub ecx,[esp+24] ;[esp+24]<-->ecx + neg ecx ;ecx=number_of_written_bytes + mov [esp+28],ecx ;[esp+28]<-->eax + popad + ret +;----------------------------------------------------------------------------- +syscall_test: +;for testing memory manager from applications. + mov edx,ecx + mov ecx,ebx + call trans_address + mov ebx,eax + mov eax,[0x3000] + call read_process_memory + ret +;----------------------------------------------------------------------------- +read_process_memory: +;Input: +; eax - process slot +; ebx - buffer address +; ecx - buffer size +; edx - start address in other process +;Output: +; eax - number of bytes read. + pushad + shl eax,8 + mov eax,[0x80000+eax+0xB8] + call MEM_Get_Linear_Address + mov ebp,eax + add edx,std_application_base_address +.read_loop: +;ebx = current buffer address +;ecx>0 = current size +;edx = current address in other process +;ebp = linear address of page directory + + call MEM_Heap_Lock ;cli + mov esi,edx + shr esi,22 + mov eax,[ebp+4*esi] ;find page directory entry + and eax,not (4096-1) + test eax,eax + jz .page_not_found + call MEM_Get_Linear_Address + test eax,eax + jz .page_not_found + mov esi,edx + shr esi,12 + and esi,1023 + mov eax,[eax+4*esi] ;find page table entry + and eax,not (4096-1) + test eax,eax + jz .page_not_found + call MEM_Get_Linear_Address ;calculate linear address of page + test eax,eax + jz .page_not_found + mov esi,eax + call MEM_Add_Reference_Linear;guarantee that page willn't disappear + call MEM_Heap_UnLock ;sti + + mov edi,edx + and edi,4095 + add esi,edi ;add offset in page +;esi = linear address corresponding edx in other process + sub edi,4096 + neg edi + +;edi=min(edi,ecx) - number of bytes to copy + cmp edi,ecx + jl .min_ecx + mov edi,ecx +.min_ecx: + + sub ecx,edi ;update size of remaining bytes + add edx,edi ;update current pointer in other address space. + push ecx + mov ecx,edi ;ecx - number of bytes to read + mov edi,ebx ;esi - source, edi - destination + push esi +;move ecx bytes + test ecx,3 + jnz .not_aligned + shr ecx,2 + rep movsd + jmp .next_iter +.not_aligned: + rep movsb +.next_iter: + pop eax + and eax,not (4096-1) ;eax - linear address of current page + call MEM_Free_Page_Linear ;free reference + mov ebx,edi ;new pointer to buffer - movsb automaticaly advance it. + pop ecx ;restore number of remaining bytes + test ecx,ecx + jnz .read_loop + + popad + mov eax,ecx + ret + +.page_not_found: + call MEM_Heap_UnLock ;error has appeared in critical region + sub ecx,[esp+24] ;[esp+24]<-->ecx + neg ecx ;ecx=number_of_read_bytes + mov [esp+28],ecx ;[esp+28]<-->eax + popad + ret +;----------------------------------------------------------------------------- +check_region: +;input: +; ebx - start of buffer +; ecx - size of buffer +;result: +; eax = 1 region lays in app memory +; eax = 0 region don't lays in app memory + mov eax,[0x3000] + jmp check_process_region +;----------------------------------------------------------------------------- +check_process_region: +;input: +; eax - slot +; ebx - start of buffer +; ecx - size of buffer +;result: +; eax = 1 region lays in app memory +; eax = 0 region don't lays in app memory + test ecx,ecx + jle .ok + shl eax,5 + cmp word [0x3000+eax+0xa],0 + jnz .failed + shl eax,3 + mov eax,[0x80000+eax+0xb8] + test eax,eax + jz .failed + call MEM_Get_Linear_Address + push ebx + push ecx + push edx + mov edx,ebx + and edx,not (4096-1) + sub ebx,edx + add ecx,ebx + mov ebx,edx + add ecx,(4096-1) + and ecx,not (4096-1) +.loop: +;eax - linear address of page directory +;ebx - current page +;ecx - current size + mov edx,ebx + shr edx,22 + mov edx,[eax+4*edx] + and edx,not (4096-1) + test edx,edx + jz .failed1 + push eax + mov eax,edx + call MEM_Get_Linear_Address + mov edx,ebx + shr edx,12 + and edx,(1024-1) + mov eax,[eax+4*edx] + and eax,not (4096-1) + test eax,eax + pop eax + jz .failed1 + add ebx,4096 + sub ecx,4096 + jg .loop + pop edx + pop ecx + pop ebx +.ok: + mov eax,1 + ret + +.failed1: + pop edx + pop ecx + pop ebx +.failed: + xor eax,eax + ret +;----------------------------------------------------------------------------- +new_sys_ipc: +;input: +; eax=1 - set ipc buffer area +; ebx=address of buffer +; ecx=size of buffer +; eax=2 - send message +; ebx=PID +; ecx=address of message +; edx=size of message + cmp eax,1 + jnz .no_ipc_def +;set ipc buffer area + mov edi,[0x3000] + shl edi,8 + add edi,0x80000 + cli + mov [edi+0xA0],ebx ;set fields in extended information area + mov [edi+0xA4],ecx + sti + mov [esp+36],dword 0 ;success + ret + +.no_ipc_def: + cmp eax,2 + jnz .no_ipc_send +;send message + cli +;obtain slot from PID + mov eax,ebx + call pid_to_slot + test eax,eax + jz .no_pid + mov ebp,eax +;ebp = slot of other process + shl eax,8 + mov edi,[eax+0x80000+0xa0] ;is ipc area defined? + test edi,edi + jz .no_ipc_area + mov esi,[eax+0x80000+0xa4] ;esi - size of buffer + push dword -1 ;temp variable for read_process_memory + mov ebx,esp + push ecx + push edx + mov ecx,4 ;read 4 bytes + mov eax,ebp + mov edx,edi ;from beginning of buffer. + call read_process_memory + mov eax,[esp+8] + test eax,eax + jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now + add edx,4 ;move to next 4 bytes + mov eax,ebp + call read_process_memory ;read size of occupied space in buffer + sub esi,8 + sub esi,[esp] + sub esi,[esp+8] ;esi=(buffer size)-(occupied size)-(message size)-(header of message size) + js .buffer_overflow ;esi<0 - not enough memory in buffer + mov esi,[esp+8] ;previous offset + add dword [esp+8],8 + mov edi,[esp] + add [esp+8],edi ;add (size of message)+(size of header of message) to [buffer+4] + mov eax,ebp + call write_process_memory + add edx,esi + sub edx,4 ;move to beginning of place for our message + mov eax,[second_base_address+0x3010] + mov eax,[eax+0x4] ;eax - our PID + mov [esp+8],eax + mov eax,ebp + call write_process_memory ;write PID + mov ebx,esp ;address of size of message + mov eax,ebp + add edx,4 + call write_process_memory ;write size of message + add edx,4 + pop ecx ;ecx - size of message + pop eax + call trans_address + mov ebx,eax ;ebx - linear address of message + add esp,4 ;pop temporary variable + mov eax,ebp + call write_process_memory ;write message + sti +;awake other process + shl ebp,8 + mov eax,ebp + or [eax+0x800A8],dword 0x40 + + cmp dword [check_idle_semaphore],20 + jge .ipc_no_cis + mov dword [check_idle_semaphore],5 +.ipc_no_cis: + mov dword [esp+36],0 + ret +.no_ipc_send: + mov dword [esp+36],-1 + ret +.no_pid: + sti + mov dword [esp+36],4 + ret +.no_ipc_area: + sti + mov dword [esp+36],1 + ret +.ipc_blocked: + sti + add esp,12 + mov dword [esp+36],2 + ret +.buffer_overflow: + sti + add esp,12 + mov dword [esp+36],3 + ret +;----------------------------------------------------------------------------- +trans_address: +;Input +; eax - application address +;Output +; eax - linear address for kernel + add eax,std_application_base_address + ret +;----------------------------------------------------------------------------- +new_start_application_hd: +;eax - file name (kernel address) +;ebx - file name length +;ecx - work area (kernel address) +;ebp - parameters + pushad + + mov esi,new_process_loading + call sys_msg_board_str ;write message to message board + +;lock application_table_status mutex +.table_status: + cli + cmp [application_table_status],0 + jz .stf + sti + call change_task + jmp .table_status +.stf: + call set_application_table_status + + push ebp + push ebx + push eax + push ecx + call find_new_process_place ;find new process slot + sti + test eax,eax + jz .failed + +;write application name + mov eax,[esp+4] +.find_last_byte: + cmp byte [eax],0 + jz .find_last_byte_end + inc eax + jmp .find_last_byte +.find_last_byte_end: + lea esi,[eax-11] ;last 11 bytes = application name + mov edi,[new_process_place] + shl edi,8 + add edi,0x80000 + mov ecx,11 + cld + rep movsb ;copy name to extended information about process + +;read header + mov eax,[esp+4] ;file name + mov esi,[esp] ;work area + mov ecx,1 ;read from first block + mov edx,1 ;read 1 block + call read_hd_file + test eax,eax + jnz .cleanfailed + + mov esi,[esp] +;check menuet signature + cmp [esi+1024+0],dword 'MENU' ;read_hd_file function write file to +1024 offset + jnz .cleanfailed + cmp [esi+1024+4],word 'ET' + jnz .cleanfailed + add esi,1024 + mov edi,0x90000 + mov ecx,512/4 + cld + rep movsd ;copy first block to 0x90000 address for get_app_params function + call get_app_params + test esi,esi + jz .cleanfailed + + mov eax,[new_process_place] + call create_app_cr3_table ;create page directory + test eax,eax + jz .cleanfailed_mem + + call MEM_Get_Linear_Address + + mov ebx,std_application_base_address + mov ecx,[app_mem] + add ecx,4096-1 + shr ecx,12 + mov edx,eax ;edx - linear address of page directory + call mem_alloc_specified_region ;allocate memory for application + test eax,eax + jz .cleanfailed_mem + + add edx,(std_application_base_address shr 20) + mov eax,[edx] + and eax,not (4096-1) + call MEM_Get_Linear_Address + push edx ;save pointer to first page table + mov edx,eax +;read file + mov ecx,1 + xor ebp,ebp +.loop1: +;[esp] - pointer to current page directory entry +;edx - pointer to current page table +;ebp - offset in page +;ecx - current cluster + push edx + mov eax,[esp+12] ;file name + mov ebx,[esp+16] ;file name length + mov esi,[esp+8] ;work area + mov edx,1 ;number of blocks to read + push ecx + push ebp + cli + call read_hd_file + sti + pop ebp + test eax,eax + jnz .endloop1 ;check io errors + + mov esi,[esp+8+4] ;work area + add esi,1024 + mov eax,[esp+4] ;current page table + mov eax,[eax] + and eax,not (4096-1) + call MEM_Get_Linear_Address;calculate linear page address + lea edi,[eax+ebp] ;add page offset + mov ecx,512/4 + cld + rep movsd ;copy data + + pop ecx + inc ecx ;next block + mov eax,[app_i_end] ;todo: precalculate ([app_i_end]+4095)/4096 + add eax,512-1 + shr eax,9 ;calculate application image size + cmp ecx,eax + jg .endloop11 + pop edx + add ebp,512 ;new offset + test ebp,4096 + jz .loop1 + xor ebp,ebp + add edx,4 ;go to next page + test edx,(4096-1) + jnz .loop1 + add dword [esp],4 ;go to next directory entry + mov eax,[esp] + mov eax,[eax] + and eax,not (4096-1) + call MEM_Get_Linear_Address + mov edx,eax + jmp .loop1 +.endloop1: + add esp,4 ;pop ecx +.endloop11: + add esp,4+4 ;pop edx, pop edx + +;add_app_parameters + add esp,12 ;now pointer to parameters is on the top of the stack + call new_start_application_fl.add_app_parameters ;start process + mov [esp+28],eax + popad + ret + +.cleanfailed_mem: + mov esi,start_not_enough_memory + call sys_msg_board_str +.cleanfailed: ;clean process name + mov edi,[new_process_place] + shl edi,8 + add edi,0x80000 + mov ecx,11 + mov eax,' ' + cld + rep stosb +.failed: + add esp,16 + popad + mov eax,-1 + mov [application_table_status],0 + sti + ret +end if diff --git a/trunk/core/physmem.inc b/trunk/core/physmem.inc new file mode 100644 index 000000000..83531e6e9 --- /dev/null +++ b/trunk/core/physmem.inc @@ -0,0 +1,218 @@ +virtual at 0 +physical_mem_block: + .start rd 1 + .size rd 1 + .flags rd 1 ;0-free, pid-used. +.sizeof: +end virtual +max_physical_mem_blocks = 24 +uglobal + num_physical_mem_blocks rd 1 + physical_mem_blocks rd 3*max_physical_mem_blocks +endg +Init_Physical_Memory_Manager: + pushad + mov edi,physical_mem_blocks + mov ecx,3*max_physical_mem_blocks + xor eax,eax + cld + rep stosd + mov dword [num_physical_mem_blocks],2 + mov [physical_mem_blocks+physical_mem_block.start],0x60000 + mov [physical_mem_blocks+physical_mem_block.size],0x20000 ;128Kb + mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.start],0x780000 + mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.size],0x80000 ;512Kb + popad + ret +Insert_Block: +;input: +; eax - handle +;output: +; none + push eax ecx esi edi + sub eax,[num_physical_mem_blocks] + neg eax + mov edi,physical_mem_block.sizeof + imul eax,edi + shr eax,2 + mov ecx,eax + mov esi,[num_physical_mem_blocks] + imul esi,edi + add esi,physical_mem_blocks + lea edi,[esi+physical_mem_block.sizeof] + std + rep movsd + pop edi esi ecx eax + ret +Delete_Block: +;input: +; eax - handle +;output: +; none + pushad + mov edi,eax + sub eax,[num_physical_mem_blocks] + neg eax + dec eax + mov esi,physical_mem_block.sizeof + imul eax,esi + imul edi,esi + add edi,physical_mem_blocks + lea esi,[edi+physical_mem_block.sizeof] + mov ecx,eax + shr ecx,2 + cld + rep movsd + popad + ret +Allocate_Physical_Block: +;input: +; eax - size +;output: +; eax - address or 0 if not enough memory. + pushad + cmp [num_physical_mem_blocks],max_physical_mem_blocks + jge .error + mov ebx,eax + xor eax,eax + mov esi,physical_mem_blocks +.loop: + cmp dword [esi+physical_mem_block.flags],0 + jnz .next + cmp [esi+physical_mem_block.size],ebx + jg .addblock + jz .noaddblock +.next: + inc eax + add esi,physical_mem_block.sizeof + cmp eax,[num_physical_mem_blocks] + jl .loop +.error: + popad + xor eax,eax + ret +.noaddblock: + mov eax,[esi+physical_mem_block.start] + mov [esp+28],eax + mov eax,[0x3010] + mov eax,[eax+0x4] + mov [esi+physical_mem_block.flags],eax + popad + ret +.addblock: + call Insert_Block + inc dword [num_physical_mem_blocks] + mov eax,[esi+physical_mem_block.start] + mov [esp+28],eax + mov ecx,[0x3010] + mov ecx,[ecx+0x4] + mov [esi+physical_mem_block.flags],ecx + mov ecx,[esi+physical_mem_block.size] + mov [esi+physical_mem_block.size],ebx + sub ecx,ebx + mov [esi+physical_mem_block.sizeof+physical_mem_block.size],ecx + add ebx,[esi+physical_mem_block.start] + mov [esi+physical_mem_block.sizeof+physical_mem_block.start],ebx + mov dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 + popad + ret +Free_Physical_Block: +;input: +; eax - address +;output: +; none + pushad + test eax,eax + jz .ret + mov ebx,eax + xor eax,eax + mov esi,physical_mem_blocks +.loop: + cmp ebx,[esi+physical_mem_block.start] + jz .endloop + inc eax + add esi,physical_mem_block.sizeof + cmp eax,[num_physical_mem_blocks] + jl .loop + jmp .ret +.endloop: + mov dword [esi+physical_mem_block.flags],0 + test eax,eax + jz .no_union_previous + cmp dword [esi-physical_mem_block.sizeof+physical_mem_block.flags],0 + jnz .no_union_previous + mov ebx,[esi-physical_mem_block.sizeof+physical_mem_block.start] + add ebx,[esi-physical_mem_block.sizeof+physical_mem_block.size] + cmp ebx,[esi+physical_mem_block.start] + jnz .no_union_previous + mov ebx,[esi+physical_mem_block.size] + add [esi-physical_mem_block.sizeof+physical_mem_block.size],ebx + call Delete_Block + dec eax + dec [num_physical_mem_blocks] +.no_union_previous: + inc eax + cmp eax,[num_physical_mem_blocks] + jge .no_union_next + cmp dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 + jnz .no_union_next + mov ebx,[esi+physical_mem_block.start] + add ebx,[esi+physical_mem_block.size] + cmp ebx,[esi+physical_mem_block.sizeof+physical_mem_block.start] + jnz .no_union_next + mov ebx,[esi+physical_mem_block.sizeof+physical_mem_block.size] + add [esi+physical_mem_block.size],ebx + call Delete_Block + dec [num_physical_mem_blocks] +.no_union_next: +.ret: + popad + ret + +sys_allocate_physical_block: +;eax - subfunction number + mov eax,ebx + call Allocate_Physical_Block + mov [esp+36],eax + ret +sys_free_physical_block: +;eax - subfunction number + mov eax,ebx + call Free_Physical_Block + ret +sys_set_buffer: + add ecx,std_application_base_address +isys_set_buffer: ;for using in kernel +;eax - subfunction number +;ebx - physical address +;ecx - buffer start +;edx - buffer size + lea edi,[ebx+second_base_address] + mov esi,ecx + mov ecx,edx + rep movsb + ret +sys_get_buffer: + add ecx,std_application_base_address +isys_get_buffer: ;for using in kernel +;eax - subfunction number +;ebx - physical address +;ecx - buffer start +;edx - buffer size + mov edi,ecx + lea esi,[ebx+second_base_address] + mov ecx,edx + rep movsb + ret +sys_internal_services: + cmp eax,4 + jle sys_sheduler + cmp eax,5 + jz sys_allocate_physical_block + cmp eax,6 + jz sys_free_physical_block + cmp eax,7 + jz sys_set_buffer + cmp eax,8 + jz sys_get_buffer + ret \ No newline at end of file diff --git a/trunk/core/sched.inc b/trunk/core/sched.inc new file mode 100644 index 000000000..23962a88b --- /dev/null +++ b/trunk/core/sched.inc @@ -0,0 +1,286 @@ +label next_usage_update dword at 0xB008 +label timer_ticks dword at 0xFDF0 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; IRQ0 HANDLER (TIMER INTERRUPT) ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 32 +irq0: + + cmp [error_interrupt],-1 + je no_error_in_previous_process + + mov edi,[error_interrupt] + shl edi, 3 + mov [edi+tss0i_l +5], word 01010000b *256 +11101001b + + mov edi,[error_interrupt] + shl edi,7 + add edi,0x290000 + mov esi,[error_interrupt_entry] + mov [edi+l.eip-tss_sceleton],esi + mov [edi+l.eflags-tss_sceleton],dword 0x11002 + + mov [0xffff],byte 0 + + mov [error_interrupt],-1 + + no_error_in_previous_process: + + mov edi,[0x3000] + shl edi, 3 + ; fields of TSS descriptor: + mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + + inc dword [timer_ticks] + + mov eax, [timer_ticks] +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + call playNote ; <<<--- INSERT THIS LINE !!!!!!!!!! +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + cmp eax,[next_usage_update] + jb .nocounter + add eax,100 + mov [next_usage_update],eax + call updatecputimes + .nocounter: + + mov edi, [0x3010] + + mov ebx, [edi+0x18] ; time stamp counter add + call _rdtsc + sub eax, ebx + add eax, [edi+0x14] ; counter sum + mov [edi+0x14], eax + + mov ebx,[0x3000] + + cmp [0xffff], byte 1 ;1 + je do_not_change_task ;je + + .waiting_for_termination: + .waiting_for_reuse: + .waiting_on_queue: + add edi,0x20 + inc ebx + + mov al, byte [edi+0xA] + cmp al, 3 + je .waiting_for_termination + cmp al, 4 + je .waiting_for_termination + cmp al, 9 + je .waiting_for_reuse + cmp al, 16 + je .waiting_on_queue + cmp al, 17 + je .waiting_on_queue + + cmp ebx,[0x3004] + jbe nsched0 + mov ebx,1 + mov edi,0x3020 + + nsched0: + + mov [0x3000],ebx + mov [0x3010],edi + + do_not_change_task: + + mov edx,[0x3000] + lea edx,[tss0sys+8*edx] + ;mov [8*0x40+idts+8+0], word 0 + mov [8*0x40+idts+8+2],dx + ;mov [8*0x40+idts+8+4],word 11100101b*256 + ;mov [8*0x40+idts+8+6], word 0 + + call _rdtsc + mov [edi+0x18],eax + + cmp [0xffff],byte 0 + je nodecffff + dec byte [0xffff] + nodecffff: + + + shl ebx, 3 + xor eax, eax + add ebx, tss0 + mov word [0xB004], bx ; selector ;mov [tss_s],bx + mov dword [0xB000], eax ; offset + + mov al,0x20 ; send End Of Interrupt signal + mov dx,0x20 + out dx,al +.switch: + jmp pword [0xB000] + inc [context_counter] ;noname & halyavin + jmp irq0 + +iglobal +context_counter dd 0 ;noname & halyavin +endg + + +align 4 +change_task: + + mov [0xffff],byte 2 + + dec dword [timer_ticks] ; because irq0 will increase it + + int 0x20 ; irq0 handler + + ret + + + +align 4 +updatecputimes: + + mov eax,[idleuse] + mov [idleusesec],eax + mov [idleuse],dword 0 + mov ecx, [0x3004] + mov edi, 0x3020 + .newupdate: + mov ebx,[edi+0x14] + mov [edi+0x1c],ebx + mov [edi+0x14],dword 0 + add edi,0x20 + dec ecx + jnz .newupdate + + ret + + + +; +; Wait queue is 16 bytes +; dd return code +12 +; dd pointer to process +8 +; dd prev +4 +; dd next +0 +; +; eax - pointer to pointer to the wait queue +; return: +; ecx - return code +sleep_on_queue: + sub esp,16 ; reserve space for wait node + mov ecx,esp ; ecx=this_node, [eax]=queue + + pusha + + mov ebx,[0x3010] ; get pointer to the current process + mov [ecx+8],ebx + + pushf + cli ; adding element to the wait queue must be atomic + + mov edi,[eax] ; edi=queue + and edi,edi ; check if queue is empty + jz .is_empty + + ; add element at the end of wait queue + + mov edx,[edi+4] ; get pointer to prev edx=queue->prev + mov [ecx+4],edx ; this_node->prev=queue->prev + mov [ecx+0],edi ; this_node->next=queue + mov [edx+0],ecx ; this_node->prev->next=this_node + mov [edi+4],ecx ; queue->prev=this_node + jmp .added_ok +.is_empty: + ; set this element as first in the queue + mov [ecx+0],ecx ; this_node->next=this_node + mov [ecx+4],ecx ; this_node->prev=this_node + mov [eax],ecx ; [queue]=this_node +.added_ok: + + popf ; we can safely restore interrupts + + mov [ebx+0xa],byte 17 ; set current task state as sleeping + call change_task ; schedule new thread + + ; someone has called wake_up_queue + + pushf ; disable interrupts + cli + + mov edx,[ecx+0] ; edx=this_node->next + mov esi,[ecx+4] ; esi=this_node->prev + + ; check if we need to remove this node from head + cmp [eax],ecx + jne .no_head + + cmp [ecx+0],ecx ; check if queue is empty + jne .not_empty + + mov [eax],dword 0 + jmp .no_head + +.not_empty: + mov [eax],edx + + ; remove our node from the queue (this must be atomic) +.no_head: + mov [edx+4],esi ; this_node->next->prev=this_node->prev + mov [esi+0],edx ; this_node->prev->next=this_node->next + + popf + popa + add esp,12 + pop ecx + ret + +; eax - pointer to the wait queue +; ebx - wake up all (1=yes, 0=no) +; ecx - return code +; return: +; ebx - number of processes woken +wake_up_queue: + and eax,eax + jnz .nz + ret +.nz: + push eax + push ebx + push ecx + push edx + push esi + + pushf + cli + + xor ebx,ebx + mov edx,eax +.wake_loop: + + mov [edx+12],ecx + mov esi,[edx+8] + mov byte [esi+0xa],0 + inc ebx + + mov edx,[edx+0] + cmp edx,eax + jne .wake_loop + + and ebx,ebx + jz .wake_up_1 + +.return_it: + popf + pop esi + pop edx + pop ecx + add esp,4 + pop eax + ret +.wake_up_1: + mov [eax+12],ecx + mov ecx,[eax+8] + mov byte [ecx+0xa],0 + jmp .return_it diff --git a/trunk/core/sync.inc b/trunk/core/sync.inc new file mode 100644 index 000000000..1f50a74e4 --- /dev/null +++ b/trunk/core/sync.inc @@ -0,0 +1,111 @@ +if ~defined sync_inc +sync_inc_fix: +sync_inc fix sync_inc_fix +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;Synhronization for MenuetOS. ;; +;;Author: Halyavin Andrey, halyavin@land.ru ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;simplest mutex. +macro SimpleMutex name +{ +; iglobal + name dd 0 + name#.type = 1 +; endg +} +macro WaitSimpleMutex name +{ + local start_wait,ok +start_wait=$ + cli + cmp [name],dword 0 + jz ok + sti + call change_task + jmp start_wait +ok=$ + push eax + mov eax,dword [0x3010+second_base_address] + mov eax,[eax+0x4] + mov [name],eax + pop eax + sti +} +macro ReleaseSimpleMutex name +{ + mov [name],dword 0 +} +macro TryWaitSimpleMutex name ;result in eax and in flags +{ + local ok,try_end + cmp [name],dword 0 + jz ok + xor eax,eax + jmp try_end +ok=$ + xor eax,eax + inc eax +try_end=$ +} +macro SimpleCriticalSection name +{ +; iglobal + name dd 0 + dd 0 + name#.type=2 +; endg +} +macro WaitSimpleCriticalSection name +{ + local start_wait,first_wait,inc_counter,end_wait + push eax + mov eax,[0x3010+second_base_address] + mov eax,[eax+0x4] +start_wait=$ + cli + cmp [name],dword 0 + jz first_wait + cmp [name],eax + jz inc_counter + sti + call change_task + jmp start_wait +first_wait=$ + mov [name],eax + mov [name+4],dword 1 + jmp end_wait +inc_counter=$ + inc dword [name+4] +end_wait=$ + sti + pop eax +} +macro ReleaseSimpleCriticalSection name +{ + local release_end + dec dword [name+4] + jnz release_end + mov [name],dword 0 +release_end=$ +} +macro TryWaitSimpleCriticalSection name ;result in eax and in flags +{ + local ok,try_end + mov eax,[0x3000+second_base_address] + mov eax,[eax+0x4] + cmp [name],eax + jz ok + cmp [name],0 + jz ok + xor eax,eax + jmp try_end +ok=$ + xor eax,eax + inc eax +try_end=$ +} +_cli equ call MEM_HeapLock +_sti equ call MEM_HeapUnLock +end if + diff --git a/trunk/core/sys32.inc b/trunk/core/sys32.inc new file mode 100644 index 000000000..095cdc348 --- /dev/null +++ b/trunk/core/sys32.inc @@ -0,0 +1,2301 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; MenuetOS process management, protected ring3 ;; +;; ;; +;; Distributed under GPL. See file COPYING for details. ;; +;; Copyright 2003 Ville Turjanmaa ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 32 + +; GDT TABLE + +gdts: + + dw gdte-$-1 + dd gdts + dw 0 + +int_code_l: +os_code_l: + + dw 0xffff + dw 0x0000 + db 0x00 + dw 11011111b *256 +10011010b + db 0x00 + +int_data_l: +os_data_l: + + dw 0xffff + dw 0x0000 + db 0x00 + dw 11011111b *256 +10010010b + db 0x00 + +graph_data_l: + + dw 0x3ff + dw 0x0000 + db 0x00 + dw 11010000b *256 +11110010b + db 0x00 + +tss0_l: + times (max_processes+10) dd 0,0 + +tss0i_l: + times 0x41 dq 0 ;(256+10) dd 0,0 + +app_code_l: + times (max_processes+10) dd 0,0 + +app_data_l: + times (max_processes+10) dd 0,0 + +tss0sys_l: + times (max_processes+10) dd 0,0 + +gdte: + + + +; +idtreg: + dw 8*0x41-1 + dd idts+8 + +label idts at 0xB100-8 +;idte = idts + 8 + 0x60 + +; ; old code below: + + +;align 32 + +;idts: +; dw idte-$-1 +; dd idts+8 +; dw 0 + +; times 0x62 dd 0,0 + +;idte: + +build_process_gdt_tss_pointer: + + mov ecx,tss_data + mov edi,0 + setgdtl2: + mov [edi+gdts+ tss0 +0], word tss_step + mov [edi+gdts+ tss0 +2], cx + mov eax,ecx + shr eax,16 + mov [edi+gdts+ tss0 +4], al + mov [edi+gdts+ tss0 +7], ah + mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + add ecx,tss_step + add edi,8 + cmp edi,8*(max_processes+5) + jbe setgdtl2 + + ret + +;build_process_gdt_gate_pointer: + +; mov edi,0 +; mov dx,tss0 +; setidtl1: +; mov ecx,[esi] +; mov [edi+gdts+ tss0t +0], word 0 +; mov [edi+gdts+ tss0t +2], dx +; mov [edi+gdts+ tss0t +4], word 11100101b*256 +; mov [edi+gdts+ tss0t +6], word 0 +; add dx,8 +; add edi,8 +; cmp edi,8*(max_processes+5) +; jb setidtl1 + +; ret + +build_interrupt_table: + + mov [l.eflags],dword 0x11002 + mov [l.ss0], int_data + ;mov [l.ss1], ring1_data + ;mov [l.ss2], ring2_data + mov [l.esp0], 0x52000 + mov [l.esp1], 0x53000 + mov [l.esp2], 0x54000 + + mov eax,cr3 + mov [l.cr3],eax + mov [l.cs],int_code + mov [l.ss],int_data + mov [l.ds],int_data + mov [l.es],int_data + mov [l.fs],int_data + mov [l.gs],int_data + + mov eax,sys_int + mov [l.esp],0x720000 + mov edi,0x290000 + + newint: + push edi + mov ebx,[eax] + mov [l.eip],ebx + mov esi,tss_sceleton + mov ecx,120/4 + cld + rep movsd + pop edi + + add edi,128 + add [l.esp],1024 + add eax,4 + + cmp eax,sys_int+4*0x40 ;0x60 + jbe newint ;jb + +;; + + mov esi,boot_sched_3_2 + call boot_log + + mov ecx,0x290000 + mov edi,0 + setgdtl2i: + mov [edi+gdts+ tss0i +0], word 128 + mov [edi+gdts+ tss0i +2], cx + mov eax,ecx + shr eax,16 + mov [edi+gdts+ tss0i +4], al + mov [edi+gdts+ tss0i +7], ah + mov [edi+gdts+ tss0i +5], word 01010000b *256 +11101001b + add ecx,128 + add edi,8 + cmp edi,8*0x40 ;0x60 + jbe setgdtl2i + +;; + + mov esi,boot_sched_3_3 + call boot_log + + mov edi,0 + mov edx,tss0i + setidtl2: + mov [edi+idts+ 8 +0], word 0 + mov [edi+idts+ 8 +2], dx + mov [edi+idts+ 8 +4], word 10000101b*256 ; task gate DPL=0 +; cmp edi,0x40*8 +; jne no_sw_int +; mov [edi+idts+ 8 +4], word 11100101b*256 ; task gate DPL=3 +; no_sw_int: + mov [edi+idts+ 8 +6], word 0 + add edx,8 + add edi,8 + + cmp edi,8*0x40 ;0x60 + jbe setidtl2 ;jb + +; +; THIS CODE WON'T WORK ;-( +; because each process's 0-level stack points to the same area +; and if task switch occurs and another process is being interrupted +; a stack overflow happens +; The only way to solve that problem is to disable interrupts +; while 0x40-handler is working +; Then we have to make all entries in the IDT INTERRUPT gates, not TASK +; mov edi, idts+8 +; mov esi, sys_int +; mov ecx, 32 +; @@: +; mov eax, [esi] +; mov [edi], ax ; lower part of offset +; mov [edi+2], word os_code ; segment selector +; shr eax, 16 +; mov [edi+4], word 10001110b shl 8 ; interrupt descriptor +; mov [edi+6], ax +; add esi, 4 +; add edi, 8 +; dec ecx +; jnz @b +; + + ret + +build_syscall_interrupt_table: + + mov [l.eflags],dword 0x11002 + mov [l.ss0], int_data ;code + ;mov [l.ss1], ring1_data ;code + ;mov [l.ss2], ring2_data ;code + mov [l.esp0], 0x52000 + mov [l.esp1], 0x53000 + mov [l.esp2], 0x54000 + + mov eax,cr3 + mov [l.cr3],eax + mov [l.cs],int_code + mov [l.ss],int_data + mov [l.ds],int_data + mov [l.es],int_data + mov [l.fs],int_data + mov [l.gs],int_data + + mov [l.esp],sysint_stack_data + mov edi,0x298000 + + newint2: + push edi + mov ebx,i40 + mov [l.eip],ebx + mov esi,tss_sceleton + mov ecx,120/4 + cld + rep movsd + pop edi + + add [l.esp],4096 + add edi,128 + ;add eax,4 + + cmp edi,0x298000+128*(max_processes+5) + jb newint2 + +;; + + mov ecx,0x298000 + mov edi,0 + setgdtl2i2: + mov [edi+gdts+ tss0sys +0], word 128 + mov [edi+gdts+ tss0sys +2], cx + mov eax,ecx + shr eax,16 + mov [edi+gdts+ tss0sys +4], al + mov [edi+gdts+ tss0sys +7], ah + mov [edi+gdts+ tss0sys +5], word 01010000b *256 +11101001b + add ecx,128 + add edi,8 + cmp edi,8*(max_processes+5) + jbe setgdtl2i2 + +;; + + ;mov dx,tss0sys + mov edi,8*0x40+idts+8 + mov [edi + 0], word 0 + mov [edi + 2], word tss0sys ;dx + mov [edi + 4], word 11100101b*256 + mov [edi + 6], word 0 + + mov edi,8*0x38+idts+8 + mov eax, i38 + mov [edi], ax ; lower part of offset + mov [edi+2], word os_code ; segment selector + shr eax, 16 + mov [edi+4], word 11101110b shl 8 ; 32-bit interrupt gate, DPL 3 + mov [edi+6], ax + + ret + + +align 4 +i38: + ; load data selectors + pushfd + push ds es + push eax + mov ax, os_data + mov ds, ax + mov es, ax + pop eax + + pushad + push edi + mov edi, eax + mov eax, ebx + mov ebx, ecx + mov ecx, edx + mov esi, [esp] + and edi, 0xFF + call dword [servetable+edi*4] + add esp, 4 + popad + pop es ds + popfd +iret + + +iglobal + sys_int: + dd s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,sa,sb,sc,sd,se,sf + + dd s10 ,s11 ; ,i_unknown12,i_unknown13 +; dd i_unknown14,i_unknown15,i_unknown16,i_unknown17 +; dd i_unknown18,i_unknown19,i_unknown1a,i_unknown1b +; dd i_unknown1c,i_unknown1d,i_unknown1e,i_unknown1f + times 14 dd unknown_interrupt + + dd irq0 ,irq1 ,p_irq2 ,p_irq3 ,p_irq4 ,p_irq5,p_irq6 ,p_irq7 + dd p_irq8,p_irq9,p_irq10,p_irq11,p_irq12,irqD ,p_irq14,p_irq15 + + ;dd i_unknown30,i_unknown31,i_unknown32,i_unknown33 + ;dd i_unknown34,i_unknown35,i_unknown36,i_unknown37 + ;dd i_unknown38,i_unknown39,i_unknown3a,i_unknown3b + ;dd i_unknown3c,i_unknown3d,i_unknown3e,i_unknown3f + times 16 dd unknown_interrupt + + dd i40 +endg + +uglobal + tss_sceleton: + l.back dw 0,0 + l.esp0 dd 0 + l.ss0 dw 0,0 + l.esp1 dd 0 + l.ss1 dw 0,0 + l.esp2 dd 0 + l.ss2 dw 0,0 + l.cr3 dd 0 + l.eip dd 0 + l.eflags dd 0 + l.eax dd 0 + l.ecx dd 0 + l.edx dd 0 + l.ebx dd 0 + l.esp dd 0 + l.ebp dd 0 + l.esi dd 0 + l.edi dd 0 + l.es dw 0,0 + l.cs dw 0,0 + l.ss dw 0,0 + l.ds dw 0,0 + l.fs dw 0,0 + l.gs dw 0,0 + l.ldt dw 0,0 + l.trap dw 0 + l.io dw 0 +endg + +s0: + cli + + mov [error_interrupt],0x0 + mov [error_interrupt_entry],dword s0 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + + +s1: + cli + + mov [error_interrupt],0x1 + mov [error_interrupt_entry],dword s1 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s2: + cli + + mov [error_interrupt],0x2 + mov [error_interrupt_entry],dword s2 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s3: + cli + + mov [error_interrupt],0x3 + mov [error_interrupt_entry],dword s3 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s4: + cli + + mov [error_interrupt],0x4 + mov [error_interrupt_entry],dword s4 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s5: + cli + + mov [error_interrupt],0x5 + mov [error_interrupt_entry],dword s5 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s6: + cli + + mov [error_interrupt],0x6 + mov [error_interrupt_entry],dword s6 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + + +;;;;;;;;;;;;;;;;;;;;;;; +;; FPU ERROR HANDLER ;; +;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +s7: + ; + cli + ; + mov edi, 7*8 + mov [edi+gdts+ tss0i +5], word 01010000b *256 +11101001b + + mov edi,[0x3000] + shl edi, 3 + mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + + + ; save a copy of current task's TSS to fpu_tss + mov esi,[0x3000] + imul esi,tss_step + add esi,tss_data + mov edi,fpu_tss + mov ecx,120/4 + cld + rep movsd + + ; get base address of our TSS and... + mov esi,[0x3000] + imul esi,tss_step + add esi,tss_data + + ; ...init segments, stack, eip, flags + mov word [esi+l.cs-tss_sceleton],int_code + mov word [esi+l.ss-tss_sceleton],int_data + mov word [esi+l.ds-tss_sceleton],int_data + mov word [esi+l.es-tss_sceleton],int_data + mov word [esi+l.fs-tss_sceleton],int_data + mov word [esi+l.gs-tss_sceleton],int_data + mov dword [esi+l.esp-tss_sceleton],fpu_stack+4*8 + mov dword [esi+l.eip-tss_sceleton],fpu_handler + mov dword [esi+l.eflags-tss_sceleton],0x11002 + + ; then execute this task + mov ebx, [0x3000] + shl ebx,3 + add ebx, tss0 ;t + mov [0xB004], bx + + jmp pword [0xB000] + + jmp s7 + +s8: + cli + + mov [error_interrupt],0x8 + mov [error_interrupt_entry],dword s8 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s9: + cli + + mov [error_interrupt],0x9 + mov [error_interrupt_entry],dword s9 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +sa: + cli + + mov [error_interrupt],0xa + mov [error_interrupt_entry],dword sa + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +sb: + cli + + mov [error_interrupt],0xb + mov [error_interrupt_entry],dword sb + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +sc: + cli + + mov [error_interrupt],0xc + mov [error_interrupt_entry],dword sc + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +sd: + cli + + mov [error_interrupt],0xd + mov [error_interrupt_entry],dword sd + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +se: + cli + + mov [error_interrupt],0xe + mov [error_interrupt_entry],dword se + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +sf: + cli + + mov [error_interrupt],0xf + mov [error_interrupt_entry],dword sf + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s10: + cli + + mov [error_interrupt],0x10 + mov [error_interrupt_entry],dword s10 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +s11: + cli + + mov [error_interrupt],0x11 + mov [error_interrupt_entry],dword s11 + + call show_error_parameters + + mov edx,[0x3010] + mov [edx+0xa],byte 4 + + jmp change_task + +writehex: + + pusha + + mov ecx,eax + mov ax,word [printerrorat] + shl eax,16 + mov ax,[esp+32+4] + sub ax,60 + mov edx,1 + mov esi,8 + mov ebx,0xffffff + whl1: + push ecx + and ecx,0xf + add ecx,hexletters + mov edi,1 + + mov cl,[ecx] + mov edi,[write_error_to] + mov [edi],cl + dec [write_error_to] + + pop ecx + shr ecx,4 + sub eax,6*65536 + dec esi + jnz whl1 + + popa + ret + +iglobal + hexletters db '0123456789ABCDEF' + + error_interrupt dd -1 + error_interrupt_entry dd -1 + + printerrorat dd 300 + + process_error db 'K : Process - forced terminate INT: 00000000',13,10,0 + process_pid db 'K : Process - forced terminate PID: 00000000',13,10,0 + process_eip db 'K : Process - forced terminate EIP: 00000000',13,10,0 + system_error db 'K : Kernel error',13,10,0 +endg + +uglobal + write_error_to dd 0x0 +endg + +show_error_parameters: + + mov [write_error_to],process_pid+43 + mov eax,[0x3000] + shl eax, 5 + mov eax,[0x3000+4+eax] + call writehex + + mov [write_error_to],process_error+43 + mov eax,[error_interrupt] + call writehex + + mov eax,[0x3000] + shl eax,8 + cmp [0x80000+eax+0xB0],dword 0 + jnz .system_error + + mov eax,[0x3000] + imul eax,tss_step + mov eax,[eax+tss_data+l.eip-tss_sceleton] +.out_eip: + mov [write_error_to],process_eip+43 + call writehex + + mov esi,process_error + call sys_msg_board_str + + mov esi,process_pid + call sys_msg_board_str + + mov esi,process_eip + call sys_msg_board_str + + ret + +.system_error: + mov esi,system_error + call sys_msg_board_str + mov eax,[0x3000] + shl eax,7 + mov eax,[eax+0x298000+l.eip-tss_sceleton] + jmp .out_eip + + +irq5: + + call restore_caller + + mov dx,word [sb16] + add dx,0xe + in al,dx + +; mov byte [SB16_Status],0 + + mov [check_idle_semaphore],5 + + mov al,0x20 + out 0x20,al + + call return_to_caller + + jmp irq5 + +irqD: + + call restore_caller + + mov dx,0xf0 + mov al,0 + out dx,al + + mov dx,0xa0 + mov al,0x20 + out dx,al + mov dx,0x20 + out dx,al + + mov ds,cx + mov es,cx + mov fs,cx + + call return_to_caller + + jmp irqD + +p_irq2: + + call restore_caller + + mov edi,2 ; 1 + call irqhandler ; 2/5 + + call return_to_caller + + jmp p_irq2 + +p_irq3: + + call restore_caller + + mov edi,3 + call irqhandler + + call return_to_caller + + jmp p_irq3 + +p_irq4: + + call restore_caller + + mov edi,4 + call irqhandler + + call return_to_caller + + jmp p_irq4 + +p_irq5: + + call restore_caller + + mov edi,5 + call irqhandler + + call return_to_caller + + jmp p_irq5 + +p_irq6: + + call restore_caller + + call fdc_irq + + mov edi,6 + call irqhandler + + call return_to_caller + + jmp p_irq6 + +p_irq7: + + call restore_caller + + mov edi,7 + call irqhandler + + call return_to_caller + + jmp p_irq7 + +p_irq8: + + call restore_caller + + mov edi,8 + call irqhandler + + call return_to_caller + + jmp p_irq8 + +p_irq9: + + call restore_caller + + mov edi,9 + call irqhandler + + call return_to_caller + + jmp p_irq9 + +p_irq10: + + call restore_caller + + mov edi,10 + call irqhandler + + call return_to_caller + + jmp p_irq10 + +p_irq11: + + call restore_caller + + mov edi,11 + call irqhandler + + call return_to_caller + + jmp p_irq11 + +p_irq12: + + call restore_caller + + mov edi,12 + call irqhandler + + call return_to_caller + + jmp p_irq12 + +p_irq13: + + call restore_caller + + mov edi,13 + call irqhandler + + call return_to_caller + + jmp p_irq13 + +p_irq14: + + call restore_caller + + mov edi,14 + call irqhandler + + call return_to_caller + + jmp p_irq14 + +p_irq15: + + call restore_caller + + mov edi,15 + call irqhandler + + call return_to_caller + + jmp p_irq15 + + + +align 4 +restore_caller: + + mov edi,[0x3000] + shl edi, 3 + mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + + ret + +align 4 +return_to_caller: + + mov ebx,[0x3000] + shl bx,3 + add bx,tss0;t + mov [tss_irq12],bx + + db 0xea + dd 0 +tss_irq12 dw tss0;t + + ret + +uglobal + irqh dd 0x0 +endg + +irqhandler: + + push edi + + mov esi,edi ; 1 + shl esi,6 ; 1 + add esi,irq00read ; 1 + shl edi,12 ; 1 + add edi,0x2E0000 + + mov [check_idle_semaphore],5 + + irqnewread: + + mov dx,[esi] ; 2+ + + cmp dx,0 ; 1 + jz irqover + cmp [esi+3],byte 1 ; 2 ; byte read + jne noirqbyte ; 4-11 + + in al,dx + + mov edx,[edi] + cmp edx,4000 + je irqfull + mov ebx,edi + add ebx,0x10 + add ebx,edx + mov [ebx],al + inc edx + mov [edi],edx + + add esi,4 + jmp irqnewread + + noirqbyte: + + + cmp [esi+3],byte 2 ; word read + jne noirqword + + in ax,dx + + mov edx,[edi] + cmp edx,4000 + je irqfull + mov ebx,edi + add ebx,0x10 + add ebx,edx + mov [ebx],ax + add edx,2 + mov [edi],edx + add esi,4 + jmp irqnewread + + noirqword: + irqfull: + irqover: + + mov al,0x20 ; ready for next irq + out 0x20,al + + pop ebx + cmp ebx,7 + jbe noa0 + out 0xa0,al + noa0: + + ret + + +; this code should never get control! +; applications can use only 0x40 interrupt +unknown_interrupt: + @@: call change_task + jmp @b + + + +compare_to_thread: + + push ebx + + mov eax,edx + shl eax, 3 + add eax,gdts+ app_code-3 + mov ebx,[eax] + cmp ebx,[old_code_0] + jne ctt0 + mov ebx,[eax+4] + cmp ebx,[old_code_1] + jne ctt0 + + pop ebx + mov eax,1 + ret + + ctt0: + + pop ebx + mov eax,0 + ret + + + +check_for_thread_mem: + + pusha + + mov ecx,[0x3004] + cftm0: + mov eax,ecx + shl eax, 8 + add eax,gdts+ app_code-3 + mov ebx,[eax] + cmp ebx,[old_code_0] + jne cftm1 + mov ebx,[eax+4] + cmp ebx,[old_code_1] + jne cftm1 + + mov eax,ecx ; new code segments + shl eax, 3 ;imul eax,8 + add eax,gdts+ app_code-3 + + mov ebx,[new_code_0] + mov [eax],ebx + mov ebx,[new_code_1] + mov [eax+4],ebx + + mov eax,ecx ; new data segments + shl eax, 3 + + add eax,gdts+ app_data-3 + + mov ebx,[new_data_0] + mov [eax],ebx + mov ebx,[new_data_1] + mov [eax+4],ebx + + cmp [new_pos],0 ; new memory position segments + je no_new_postition_for_thread + mov eax,ecx + shl eax, 5 + add eax,0x3000 + mov ebx,[new_pos] + mov [eax+0x10],ebx + no_new_postition_for_thread: + + mov eax,ecx ; new amount of memory + shl eax, 8 + add eax,0x80000 + mov ebx,[new_amount] + mov [eax+0x8C],ebx + + cftm1: + + dec ecx + jnz cftm0 + + popa + + ret + + +save_for_thread_check: + + ; save for thread check + + pusha + mov esi,[0x3000] + ;imul esi,8 + shl esi, 3 + add esi,gdts+ app_code-3 +0 + mov edi,old_code_0 + mov ecx,8 + cld + rep movsb + popa + + ret + + +save_new_position_for_threads: + + ; new code segment for thread check + pusha + mov esi,[0x3000] + ;imul esi,8 + shl esi, 3 + add esi,gdts+ app_code-3 +0 + mov edi,new_code_0 + mov ecx,8 + cld + rep movsb + popa + + ; new data segment for thread check + pusha + mov esi,[0x3000] + ;imul esi,8 + shl esi, 3 + add esi,gdts+ app_data-3 +0 + mov edi,new_data_0 + mov ecx,8 + cld + rep movsb + popa + + ret + +set_application_table_status: + push eax + + mov eax,[0x3000] + ;imul eax,32 + shl eax, 5 + add eax,0x3000+4 + mov eax,[eax] + + mov [application_table_status],eax + + pop eax + + ret + + +clear_application_table_status: + push eax + + mov eax,[0x3000] + ;imul eax,32 + shl eax, 5 + add eax,0x3000+4 + mov eax,[eax] + + cmp eax,[application_table_status] + jne apptsl1 + mov [application_table_status],0 + apptsl1: + + pop eax + + ret + +uglobal + old_code_0 dd 0x0 + old_code_1 dd 0x0 + + ; + + new_code_0 dd 0x0 + new_code_1 dd 0x0 + + new_data_0 dd 0x0 + new_data_1 dd 0x0 + + new_pos dd 0x0 + new_amount dd 0x0 +endg + + +sys_resize_app_memory: + ; eax = 1 - resize + ; ebx = new amount of memory + + cmp eax,1 + jne no_application_mem_resize + + mov eax,[0x3010] + cmp dword [eax+0x10],std_application_base_address + jz new_mem_resize ;resize for new type of processes + + add ebx,4095 + shr ebx,12 + shl ebx,12 + mov ebp,ebx + + ; wait for process table to be free + + rsm0: + + cli + cmp [application_table_status],0 + je rsm1 + sti + call change_task + jmp rsm0 + + rsm1: + + call set_application_table_status + sti + + cmp ebx,0 ; other than zero + je mem_resize_unsuccess + + call save_for_thread_check + + ; find a free place + + mov esi,[0xfe84] ; application memory start + mov edi,ebp + add edi,esi + dec edi + + rfgdt: + + mov edx,2 + + rfindgdtl1: + + call compare_to_thread + cmp eax,1 + je rfindfl3 + + mov ecx,edx + shl ecx,3 + + ; eax run base -> ebx limit + + mov al,[ecx+gdts+ app_code-3 +4] + mov ah,[ecx+gdts+ app_code-3 +7] + shl eax,16 + mov ax,[ecx+gdts+ app_code-3 +2] + +;!!mem + cmp eax,std_application_base_address + jz rfindfl3 +;!!mem + + movzx ebx,word [ecx+gdts+ app_code-3 +0] + shl ebx,12 + add ebx,eax + + cmp eax,edi + jg rfindfl3 + cmp ebx,esi + jb rfindfl3 + + add esi,4096 + add edi,4096 + + cmp edi,[0xfe8c] ; < c_memory + jbe rfgdt + + jmp rfind_free_ret_2 ;; not enough memory + + rfindfl3: + + inc edx + cmp edx,[0x3004] + jbe rfindgdtl1 + + rfindfl1: + rthread_c: + + mov ecx,[0x3000] + shl ecx,3 + + inc edi + sub edi,esi + add edi,4095 + shr edi,12 + dec edi + + ; code + + mov eax,esi + mov ebx,edi + + mov [ecx+gdts+ app_code-3 +2], ax ; base 0:15 + shr eax,16 + mov [ecx+gdts+ app_code-3 +4], al ; base 23:16 + mov [ecx+gdts+ app_code-3 +7], ah ; base 31:24 + mov [ecx+gdts+ app_code-3 +0], bx ; limit + + ; data + + mov eax,esi + mov [ecx+gdts+ app_data-3 +2], ax ; base 0:15 + shr eax,16 + mov [ecx+gdts+ app_data-3 +4], al ; base 23:16 + mov [ecx+gdts+ app_data-3 +7], ah ; base 31:24 + + movzx edx,word [ecx+gdts+ app_code-3 +0] ; save limit + + mov [ecx+gdts+ app_data-3 +0], bx ; limit + + and ebx,0xffff + + cmp ebx,edx ; copy smaller from memory sizes + jge noedxebxxchg + mov edx,ebx + noedxebxxchg: + + movzx ecx,dx + shl ecx,12 + add ecx,4096 + + mov edi,esi + + mov eax,[0x3010] + mov esi,[eax+0x10] + + mov [eax+0x10],edi ; new memory position + + mov eax,[0x3000] ; new memory size + shl eax,8 + add eax,0x80000 + mov [eax+0x8c],ebp + + mov [new_pos],edi ; new position for threads + mov [new_amount],ebp ; new amount of mem for threads + + cmp esi,edi + je no_app_move + + cld + rep movsb ; move the app image to the new position + + no_app_move: + + call save_new_position_for_threads + call check_for_thread_mem + + mov [application_table_status],0 + + mov [esp+36],dword 0 ; eax <- 0 ; successfull + + ret + + rfind_free_ret_2: + + mem_resize_unsuccess: + + mov [application_table_status],0 + + mov [esp+36],dword 1 ; eax <- 1 ; unsuccessfull + + ret + + no_application_mem_resize: + + + ret + + +align 4 +find_free_mem: + + push eax + push ebx + push ecx + push edx + push edi + + call find_free_process_slot + mov eax,[new_process_place] + + cmp eax,max_processes + jg find_free_ret_2 + + cmp [thread_create],1 + je thread_c + + mov esi,[0xfe84] + add edi,esi + dec edi + + mov eax,2 + cmp dword [0x3004],1 + je findf4 + + fgdt: + + mov edx,2 + + findgdtl1: + + mov ecx,edx + shl ecx,3 + + ; eax run base -> ebx limit + + mov al,[ecx+gdts+ app_code-3 +4] + mov ah,[ecx+gdts+ app_code-3 +7] + shl eax,16 + mov ax,[ecx+gdts+ app_code-3 +2] +;!!mem + cmp eax,std_application_base_address + jz findfl3 +;!!mem + + movzx ebx,word [ecx+gdts+ app_code-3 +0] + shl ebx,12 + add ebx,eax + + cmp eax,edi + jg findfl3 + cmp ebx,esi + jb findfl3 + + add esi,4096 + add edi,4096 + + cmp edi,[0xfe8c] ; < c_memory + jbe fgdt + + jmp find_free_ret_2 + + findfl3: + + inc edx + cmp edx,[check_processes] + jbe findgdtl1 + + findfl1: + thread_c: + + mov eax,[new_process_place] + + findf4: + + mov [first_gdt_search],eax + mov [gdt_place],eax + + mov ecx,eax + shl ecx,3 + + inc edi + sub edi,esi + add edi,4095 + shr edi,12 + dec edi + + ; code + + mov eax,esi + mov ebx,edi + + mov [ecx+gdts+ app_code-3 +2], ax ; base 0:15 + shr eax,16 + mov [ecx+gdts+ app_code-3 +4], al ; base 23:16 + mov [ecx+gdts+ app_code-3 +7], ah ; base 31:24 + mov [ecx+gdts+ app_code-3 +0], bx ; limit + mov [ecx+gdts+ app_code-3 +5], word 11010000b *256 +11111010b + + ; data + + mov eax,esi + mov [ecx+gdts+ app_data-3 +2], ax ; base 0:15 + shr eax,16 + mov [ecx+gdts+ app_data-3 +4], al ; base 23:16 + mov [ecx+gdts+ app_data-3 +7], ah ; base 31:24 + mov [ecx+gdts+ app_data-3 +0], bx ; limit + mov [ecx+gdts+ app_data-3 +5], word 11010000b *256 +11110010b + + push esi + mov esi,process_loading + call sys_msg_board_str + pop esi + + find_free_ret: + + pop edi + pop edx + pop ecx + pop ebx + pop eax + ret + + find_free_ret_2: + + cmp [dec3004],0 + je no3004inc + dec dword [0x3004] + no3004inc: + + pop edi + pop edx + pop ecx + pop ebx + pop eax + mov esi,0 + ret + + +get_app_params: + + push eax + + cmp [0x90000+6],word '00' + jne no_00_header + + mov eax,[0x90000+12] + mov [app_start],eax + mov eax,[0x90000+16] + mov [app_i_end],eax + mov eax,[0x90000+20] + mov [app_mem],eax + shr eax,1 + sub eax,0x10 + mov [app_esp],eax + mov eax,[0x90000+24] + mov [app_i_param],eax + mov [app_i_icon],dword 0 + + pop eax + mov esi,1 + ret + + no_00_header: + + + cmp [0x90000+6],word '01' + jne no_01_header + + mov eax,[0x90000+12] + mov [app_start],eax + mov eax,[0x90000+16] + mov [app_i_end],eax + mov eax,[0x90000+20] + mov [app_mem],eax + mov eax,[0x90000+24] + mov [app_esp],eax + mov eax,[0x90000+28] + mov [app_i_param],eax + mov eax,[0x90000+32] + mov [app_i_icon],eax + + pop eax + mov esi,1 + ret + + no_01_header: + + pop eax + mov esi,0 + ret + + +start_application_fl: + jmp new_start_application_fl + +;************************************************************************ + +start_application_floppy: + jmp new_start_application_floppy + +;******************************************************************** + +start_application_hd: + jmp new_start_application_hd + +uglobal + threadstring dd 0x0 + new_process_place dd 0x0 + check_processes dd 0x0 + dec3004 db 0x0 + app_start dd 0x0 + app_i_end dd 0x0 + app_mem dd 0x0 + app_esp dd 0x0 + app_i_param dd 0x0 + app_i_icon dd 0x0 + app_mem_pos dd 0x0 + thread_create dd 0x0 + gdt_place dd 0x0 +endg + +iglobal + hd_app_string db 'HDAPP ' + process_loading db 'K : Process - loading ',13,10,0 + process_running db 'K : Process - done',13,10,0 + first_gdt_search dd 0x2 +endg + + +sys_threads: + +; eax=1 create thread +; +; ebx=thread start +; ecx=thread stack value +; +; on return : eax = pid +jmp new_sys_threads + cli + cmp [application_table_status],0 + je stth9 + sti + call change_task + jmp sys_threads + stth9: + + call set_application_table_status + + sti + + cmp eax,1 + jne no_sys_thread_create + cli + + mov eax,[0x3010] + mov eax,[eax+0x10] + mov [app_mem_pos],eax + + mov [app_i_param],0 + mov [app_i_icon],0 + + mov [app_start],ebx + mov [app_esp],ecx + + mov ebx,[0x3000] + shl ebx,8 + add ebx,0x80000 + mov [threadstring],ebx + mov ebx,[ebx+0x8c] + mov [app_mem],ebx + + mov esi,[app_mem_pos] + mov edi,[app_mem] + add edi,esi + dec edi + mov [thread_create],1 + call find_free_mem + cmp esi,0 + jne th_cr1 + mov [application_table_status],0 + mov eax,1 ; no free memory + sti + ret + th_cr1: + push dword 0 + push dword [threadstring] + jmp add_app_parameters + no_sys_thread_create: + + mov eax,-1 + mov [application_table_status],0 + ret + + +find_free_process_slot: + + pusha + + mov ebx,[0x3004] + mov [check_processes],ebx + inc ebx + mov [new_process_place],ebx + + mov ebx,2 + + newfps: + + mov eax,ebx + ;imul eax,0x20 + shl eax, 5 + add eax,0x3000+0xa + cmp [eax],byte 9 + je ffpl + + inc ebx + cmp ebx,[0x3004] + jbe newfps + + ;mov [dec3004],0 + mov [dec3004],1 + shl ebx,5 + mov [0x3000+0xa+ebx],byte 9 + inc dword [0x3004] + + popa + ret + + ffpl: + + ;mov [dec3004],1 + ;dec dword [0x3004] + mov [dec3004],0 + mov [new_process_place],ebx + + popa + ret + + +add_app_parameters: +; returns: eax = pid or -1 if unsuccesfull + cmp [app_i_param],dword 0 ; parameter + jz no_app_params + xor eax, eax + mov edi,[app_i_param] + add edi,[app_mem_pos] + mov ecx,256/4 + cld + rep stosd + mov esi,[esp+4] + test esi, esi + jz no_app_params + mov eax,[app_i_param] + add eax,[app_mem_pos] + mov edi,eax + mov ecx,256 + cld + app_new_param: + cmp [esi],byte 0 + jz no_app_params + movsb + loop app_new_param + no_app_params: + + ;inc dword [0x3004] ; increase number of processes + mov ebx,[new_process_place] + + mov edi,ebx ; clear 0x80000 (256 bytes) + shl edi,8 + add edi,0x80000 + mov ecx,256 / 4 + mov eax,0 + cld + rep stosd + + shl ebx,5 ; * 32 +0x3000 + add ebx,0x3000 + + mov al,byte [new_process_place] ; screen id ? + mov [ebx+0xe],al + + mov [ebx],dword 1+2+4 ; report events: windowdraw, key, button + + inc dword [process_number] ; process id number + mov eax,[process_number] + mov [ebx+4],eax + + mov ecx,ebx ; set draw limits + add ecx,draw_data-0x3000 + mov [ecx+0],dword 0 + mov [ecx+4],dword 0 + mov eax,[0xfe00] + mov [ecx+8],eax + mov eax,[0xfe04] + mov [ecx+12],eax + + mov eax,[app_mem_pos] ; position in memory + mov [ebx+0x10],eax + + ; TSS + xor ebx,ebx + cmp [thread_create],ebx + jnz clone_cr3_table + mov eax,[new_process_place] + call create_app_cr3_table + jmp set_cr3 +clone_cr3_table: +; mov eax,[new_process_place] +; mov ebx,[0x3000] +; call addreference_app_cr3_table + mov eax,[0x3000] + call get_cr3_table +set_cr3: + add eax,8+16 + mov [l.cr3],eax + + mov eax,[app_start] + mov [l.eip],eax + mov eax,[app_esp] + mov [l.esp],eax + + mov ebx,[new_process_place] ; gdt's + shl ebx,3 + + mov ax,app_code + add ax,bx + mov [l.cs],ax + mov ax,app_data + add ax,bx + mov [l.ss],ax + mov [l.ds],ax + mov [l.es],ax + mov [l.fs],ax + mov ax,graph_data + mov [l.gs],ax + mov [l.io],word 128 + mov [l.eflags],dword 0x11202 + mov [l.ss0], os_data + ;mov [l.ss1], ring1_data + ;mov [l.ss2], ring2_data + ; [Ivan 07.03.2005] + mov [l.esp0], 0x8000 ;0x55000 ; used by i38 handler + ; [/Ivan 07.03.2005] + mov [l.esp1], 0x56000 + mov [l.esp2], 0x57000 + + mov eax,tss_sceleton ; move tss to tss_data+ + mov ebx,[new_process_place] + imul ebx,tss_step + add ebx,tss_data + mov ecx,120 + call memmove + + + ; Add IO access table + + or eax, -1 + mov edi, [new_process_place] + imul edi, tss_step + add edi, tss_data + 128 + mov ecx, 2048 ; for 2048 * 4 * 8 bits = 65536 ports + cld + rep stosd + + ; make sure gdt is pointing to the process + ; and not to i40 handler + + mov ecx,ebx + mov edi,[new_process_place] +; imul edi,8 + shl edi, 3 + + mov [edi+gdts+ tss0 +0], word tss_step ; limit 0:15 + mov [edi+gdts+ tss0 +2], cx ; base 0:15 + mov eax,ecx + shr eax,16 + mov [edi+gdts+ tss0 +4], al ; base 23:16 + mov [edi+gdts+ tss0 +7], ah ; base 31:24 + mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + + pop eax + pop ebx + + mov ebx,[new_process_place] ; save name of the process + shl ebx,8 + add ebx,0x80000 + mov ecx,11 + call memmove + + mov ebx,[new_process_place] ; save image size + shl ebx,8 + add ebx,0x80000+0x8C + mov eax,[app_mem] + mov [ebx],eax + + mov [0xf400],byte 0 ; empty keyboard buffer + mov [0xf500],byte 0 ; empty button buffer + + mov [application_table_status],0 + mov eax,[process_number] + + mov ebx,[new_process_place] + shl ebx, 5 ;imul ebx,0x20 + mov [0x3000+ebx+0xa],byte 0 + + mov edi,[new_process_place] + shl edi,5 + add edi,window_data + + mov ebx,[new_process_place] + movzx esi, word [0xC000 + ebx*2] + lea esi, [0xC400 + esi*2] + call windowactivate + + sti + + push esi + mov esi,process_running + call sys_msg_board_str + pop esi + + ret + +iglobal + process_terminating db 'K : Process - terminating',13,10,0 + process_terminated db 'K : Process - done',13,10,0 +endg + + +terminate: ; terminate application + push esi + mov esi,process_terminating + call sys_msg_board_str + pop esi +;start memory manager code +; mov eax,esi +; call MEM_Heap_Clean +;end memory manager code + + + cli + cmp [application_table_status],0 + je term9 + sti + call change_task + jmp terminate + term9: + + call set_application_table_status + + mov eax,esi + call dispose_app_cr3_table + + mov [first_gdt_search],0x2 ; start gdt search from beginning + + cmp [prev_user_of_fpu],esi ; if user fpu last -> fpu user = 1 + jne fpu_ok_1 + mov [prev_user_of_fpu],1 + fpu_ok_1: + + mov [0xf400],byte 0 ; empty keyboard buffer + mov [0xf500],byte 0 ; empty button buffer + + mov ecx,esi ; clear memory reserv. + shl ecx,3 + mov [ecx+gdts+ app_code-3 +0],dword 0 + mov [ecx+gdts+ app_code-3 +4],dword 0 + mov [ecx+gdts+ app_data-3 +0],dword 0 + mov [ecx+gdts+ app_data-3 +4],dword 0 + + mov edi, esi +; shl edi, 5 +; add edi, 0x3000 +; cmp [edi+0xa],byte 3 ; if normal terminate then clear int40 handler +; jne nocl40 + +; mov edi,esi ; free the used interrupt 0x40 handler +; shl edi, 8 ;imul edi,256 +; mov eax,[edi+0x80000+0xb0] + +; cmp eax,0 ; is application using a systemcall interrupt ? +; je nocl40 + + mov [usedi40+eax],byte 0 + +; mov edi,8 +; imul edi,eax + mov edi, eax + shl edi, 3 + mov [edi+tss0sys_l +5], word 01010000b *256 +11101001b + +; mov edi,128 +; imul edi,eax + mov edi, eax + shl edi, 7 + mov [edi+0x298000+l.eip-tss_sceleton],dword i40 + mov [edi+0x298000+l.eflags-tss_sceleton],dword 0x11002 + + mov ebx,eax + shl ebx, 12 ;imul ebx,4096 + add ebx,sysint_stack_data + mov [edi+0x298000+l.esp-tss_sceleton],ebx + + nocl40: + + mov ecx,esi ; remove buttons + bnewba2: + mov edi,[0xfe88] + mov eax,edi + cld + movzx ebx,word [edi] + inc bx + bnewba: + dec bx + jz bnmba + add eax,0x10 + cmp cx,[eax] + jnz bnewba + pusha + mov ecx,ebx + inc ecx + shl ecx,4 + mov ebx,eax + add eax,0x10 + call memmove + dec dword [edi] + popa + jmp bnewba2 + bnmba: + + pusha ; save window coordinates for window restoring + cld + shl esi,5 + add esi,window_data + mov ax,[esi+0] + mov word [dlx],ax + mov bx,[esi+8] + add ax,bx + mov word [dlxe],ax + mov ax,[esi+4] + mov word [dly],ax + mov bx,[esi+12] + add ax,bx + mov word [dlye],ax + mov [esi+0],word 0 + mov [esi+8],word 5 + mov ax,[0xFE04] + mov [esi+4],ax + mov [esi+12],word 5 + xor eax, eax + mov [esi+16],eax;dword 0 + mov [esi+20],eax;dword 0 + mov [esi+24],eax;dword 0 + mov [esi+28],eax;dword 0 + popa + + pusha + mov edi,esi + shl edi,5 + add edi,window_data + mov ecx,32/4 + xor eax, eax + ; cld + rep stosd + + mov eax,[0xFE04] ; set window to start from maxy+1 + add eax,2 + + mov edi,esi + shl edi,5 + add edi,window_data + mov [edi+4],eax + + popa + + pusha + mov edi,esi + shl edi,5 + add edi,draw_data + mov ecx,32/4 + xor eax, eax + ; cld + rep stosd + popa + + pusha ; at 0x80000+ + mov edi,esi + shl edi,8 + add edi,0x80000 + mov ecx,256/4 + xor eax, eax + ; cld + rep stosd + popa + + pusha ; name to spaces + mov edi,esi + shl edi,8 + add edi,0x80000 + mov ecx,11 + mov eax,' ' + ; cld + rep stosb + popa + + pusha ; C000 --> C400 + mov eax, 0xc000 + mov esi, 0 + nlc40: + add eax, 2 + inc esi + cmp esi, [0x3004] + jae nlc41 + movzx ecx, word [eax] + mov [0xC400 + ecx*2], si + jmp nlc40 + nlc41: + ; ivan 08.12.2004 begin + ;mov ebx, [0x3004] + ;dec ebx + ;lea esi, [0xC400 + ebx*2] + ;call windowactivate + ; ivan 08.12.2004 end + popa + + pusha ; remove hd1 reservation + mov edx,esi + shl edx, 5 ;imul edx,0x20 + add edx,0x3000 + mov edx,[edx+4] + cmp [hd1_status],edx + jne no_hd1_s_remove + mov [hd1_status],0 + no_hd1_s_remove: + popa + + pusha ; remove all irq reservations + mov edx,esi + shl edx, 5 ;imul edx,0x20 + add edx,0x3000 + mov edx,[edx+4] + mov edi,irq_owner + mov ecx,16 + newirqfree: + cmp [edi],edx + jne nofreeirq + mov [edi],dword 0 + nofreeirq: + add edi,4 + loop newirqfree + popa + + + pusha ; remove all port reservations + + mov edx,esi + shl edx, 5 ;imul edx,0x20 + add edx,0x3000 + mov edx,[edx+4] + + rmpr0: + + mov esi,[0x2d0000] + + cmp esi,0 + je rmpr9 + + rmpr3: + + mov edi,esi + shl edi,4 + add edi,0x2d0000 + + cmp edx,[edi] + je rmpr4 + + dec esi + jnz rmpr3 + + jmp rmpr9 + + rmpr4: + + mov ecx,256 + sub ecx,esi + shl ecx,4 + + mov esi,edi + add esi,16 + cld + rep movsb + + dec dword [0x2d0000] + + jmp rmpr0 + + rmpr9: + + popa + mov edi,esi ; do not run this process slot + shl edi, 5 ;imul edi,0x20 +; add edi,0x3000 + mov [edi+0x300A],byte 9 +; call systest + sti ; .. and life goes on + +; movzx eax,word [dlx] +; movzx ebx,word [dly] +; movzx ecx,word [dlxe] +; movzx edx,word [dlye] + call calculatescreen + + xor eax, eax + xor esi, esi + call redrawscreen + + mov [0xfff4],byte 0 ; no mouse background + mov [0xfff5],byte 0 ; draw mouse + + mov [application_table_status],0 + + mov esi,process_terminated + call sys_msg_board_str + +;* start code - fix error redraw for terminate (2) - Mario79 +; cmp [draw_present],1 +; je no_draw_background_temp +; mov [0xfff0],byte 1 +;no_draw_background_temp: +; mov [draw_present],0 + ret +;draw_present db 0 +;* end code - fix error redraw for terminate (2) - Mario79 + +iglobal + boot_sched_1 db 'Building gdt tss pointer',0 + ;boot_sched_2 db 'Building gdt gate pointer',0 + boot_sched_3 db 'Building interrupt table - TSS',0 + boot_sched_3_2 db 'Building interrupt table - GDT',0 + boot_sched_3_3 db 'Building interrupt table - IDT',0 + boot_sched_4 db 'Building syscall interrupt table',0 +endg + + +build_scheduler: + ; { Ivan 06.03.2005 + mov edi, usedi40 + mov ecx, 256/4 + xor eax, eax + rep stosd + ; } Ivan 06.03.2005 + + mov esi,boot_sched_1 + call boot_log + call build_process_gdt_tss_pointer + +; mov esi,boot_sched_2 +; call boot_log +; call build_process_gdt_gate_pointer + + mov esi,boot_sched_3 + call boot_log + call build_interrupt_table + + mov esi,boot_sched_4 + call boot_log + call build_syscall_interrupt_table + + ret + diff --git a/trunk/core/syscall.inc b/trunk/core/syscall.inc new file mode 100644 index 000000000..d6c2d187c --- /dev/null +++ b/trunk/core/syscall.inc @@ -0,0 +1,238 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SYSTEM CALL ENTRY ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 32 +i40: + cli + + mov edi,[0x3000] + mov eax,edi + shl edi, 3 +;clear busy flag in application's TSS + mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + +;save GDT TSS entry + mov edx,[edi+tss0_l] + mov [reg1+eax*4],edx + mov edx,[edi+tss0_l+4] + mov [reg2+eax*4],edx +;and then write there i40's descriptor + mov edx,[tss0sys_l+edi] + mov [edi+tss0_l],edx + mov edx,[tss0sys_l+edi+4] + mov [edi+tss0_l+4],edx + + + shl edi,5 + mov [edi+0x80000+0xB0],eax ; used i40 handler + + ; for syscall trace function + call save_registers + + mov esi, [0x3000] + imul esi, tss_step + add esi, tss_data + ; esi holds address of TSS of interupted program + ; load first 3 registers + mov eax,[esi+l.eax-tss_sceleton] + mov ebx,[esi+l.ebx-tss_sceleton] + mov ecx,[esi+l.ecx-tss_sceleton] + + ; save current registers + ; stack may be modified by a system function to return some value to caller! + pushad + + ; load all registers from TSS of the application, in crossed order (why?) + mov edi,[esi+l.eax-tss_sceleton] + mov eax,[esi+l.ebx-tss_sceleton] + mov ebx,[esi+l.ecx-tss_sceleton] + mov ecx,[esi+l.edx-tss_sceleton] + mov edx,[esi+l.esi-tss_sceleton] + mov esi,[esi+l.edi-tss_sceleton] + + ; enable interupts - a task switch or an IRQ _CAN_ interrupt i40 handler + sti + ; eax doesn't need to be saved, but... + push eax + and edi,0xff + call dword [servetable+edi*4] + pop eax + cli + + ; return saved and probably even changed regs + popad + + ; esi already loaded - look above "pusha" + ;mov esi,[0x3000] + ;imul esi,tss_step + ;add esi,tss_data + ; + + ; modify 3 program's registers (in its TSS) + mov [esi+l.eax-tss_sceleton], eax + mov [esi+l.ebx-tss_sceleton], ebx + mov [esi+l.ecx-tss_sceleton], ecx + + ; calculate app's TSS address + mov ebx, [0x3000] + shl ebx, 3 + add ebx, tss0_l + + mov ecx, [0x3000] + + ; restore saved TSS descriptor + mov eax, [reg1+ecx*4] + mov [ebx], eax + mov eax, [reg2+ecx*4] + mov [ebx+4], eax + + xor eax, eax + mov edi, [0x3000] ; no syscall interrupt in use anymore + shl edi, 8 + mov [edi+0x80000+0xB0],eax + + ; clear busy flag in TSS of this handler + mov edi, [0x3000] + shl edi, 3 + mov [edi+tss0sys_l +5], word 01010000b *256 +11101001b + + add edi,tss0 + mov [0xB004], di + + jmp pword [0xB000] + + jmp i40 + +label reg1 dword at 0x6000 +label reg2 dword at 0x6400 +label usedi40 byte at 0x6800 + +uglobal + schd dd 0x0 +endg + +align 4 +save_registers: + + mov esi,[0x3000] + imul esi,tss_step + add esi,tss_data + + mov eax,[esi+l.eax-tss_sceleton] + mov ebx,[esi+l.ebx-tss_sceleton] + mov ecx,[esi+l.ecx-tss_sceleton] + mov edx,[esi+l.edx-tss_sceleton] + mov edi,[esi+l.edi-tss_sceleton] + mov ebp,[esi+l.ebp-tss_sceleton] + + mov esi,[esi+l.esi-tss_sceleton] + + push eax ecx esi edi + mov esi,[0x3010] + mov eax,[esi+0x4] + mov esi,esp + inc [save_syscall_count] + mov edi,[save_syscall_count] + and edi,0xF + shl edi,6 + add edi,save_syscall_data+32 + mov [edi-32],eax + mov ecx,32 / 4 + cld + rep movsd + pop edi esi ecx eax + ret + +uglobal + save_syscall_count dd 0x0 +endg + +label save_syscall_data dword at 0x5000 + + +iglobal + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; SYSTEM FUNCTIONS TABLE ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + align 4 + servetable: + + dd sys_drawwindow ; 0-DrawWindow + dd syscall_setpixel ; 1-SetPixel + dd sys_getkey ; 2-GetKey + dd sys_clock ; 3-GetTime + dd syscall_writetext ; 4-WriteText + dd delay_hs ; 5-DelayHs + dd syscall_openramdiskfile ; 6-OpenRamdiskFile + dd syscall_putimage ; 7-PutImage + dd sys_button ; 8-DefineButton + dd sys_cpuusage ; 9-GetProcessInfo + dd sys_waitforevent ; 10-WaitForEvent + dd sys_getevent ; 11-CheckForEvent + dd sys_redrawstat ; 12-BeginDraw and EndDraw + dd syscall_drawrect ; 13-DrawRect + dd syscall_getscreensize ; 14-GetScreenSize + dd sys_background ; 15-bgr + dd sys_cachetodiskette ; 16-FlushFloppyCache + dd sys_getbutton ; 17-GetButton + dd syscall_system ; 18-Shutdown,KillApp,WindowActivate + dd syscall_startapp ; 19-StartApp + dd sys_midi ; 20-ResetMidi and OutputMidi + dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. + dd sys_settime ; 22-setting date,time,clock and alarm-clock + dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent + dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist + dd sys_sb16 ; 25-SetSb16 + dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. + dd sys_wss ; 27-SetWssMainVol and SetWssCdVol + dd sys_sb16II ; 28-SetSb16 + dd sys_date ; 29-GetDate + dd syscall_readhd ; 30-ReadHd + dd syscall_starthdapp ; 31-StartHdApp + dd syscall_delramdiskfile ; 32-DelRamdiskFile + dd syscall_writeramdiskfile; 33-WriteRamdiskFile + dd read_floppy_file ; 34-ReadFloppyDrive + dd syscall_getpixel ; 35-GetPixel + dd syscall_readstring ; 36-ReadString (not yet ready) + dd readmousepos ; 37-GetMousePosition_ScreenRelative,. + dd syscall_drawline ; 38-DrawLine + dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. + dd set_app_param ; 40-WantEvents + dd syscall_getirqowner ; 41-GetIrqOwner + dd get_irq_data ; 42-ReadIrqData + dd sys_outport ; 43-SendDeviceData + dd sys_programirq ; 44-ProgramIrqs + dd reserve_free_irq ; 45-ReserveIrq and FreeIrq + dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea + dd display_number ; 47-WriteNum + dd display_settings ; 48-SetRedrawType and SetButtonType + dd syscall_appints ; 49-AppInts + dd random_shaped_window ; 50-Window shape & scale + dd syscall_threads ; 51-Threads + dd stack_driver_stat ; 52-Stack driver status + dd socket ; 53-Socket interface + dd user_events ; 54-User events + dd sound_interface ; 55-Sound interface + dd write_to_hd ; 56-Write a file to hd + dd delete_from_hd ; 57-Delete a file from hd + dd file_system ; 58-Common file system interface + dd sys_trace ; 59-System call trace + dd new_sys_ipc ; 60-Inter Process Communication + dd sys_gs ; 61-Direct graphics access + dd sys_pci ; 62-PCI functions + dd sys_msg_board ; 63-System message board + dd sys_resize_app_memory ; 64-Resize application memory usage + dd undefined_syscall ; 65-UTF + dd sys_process_def ; 66-Process definitions - keyboard + dd sys_window_move ; 67-Window move or resize + dd sys_internal_services ; 68-Some internal services + + times 255 - ( ($-servetable) /4 ) dd undefined_syscall + + dd sys_end ; -1-end application +endg + diff --git a/trunk/detect/commouse.inc b/trunk/detect/commouse.inc new file mode 100644 index 000000000..bfce6133a --- /dev/null +++ b/trunk/detect/commouse.inc @@ -0,0 +1,121 @@ +;************************************************** +;* ╧╬╚╤╩ ╠█╪╚ ╧╬ ╧╬╤╦┼─╬┬└╥┼╦▄═█╠ ╧╬╨╥└╠ * +;* ╧ЁюЎхфєЁр яюфуюЄртыштрхЄ уыюсры№э√х яхЁхьхээ√х * +;* COMPortNum ш COMPortBaseAddr фы  яюфяЁюуЁрьь√ * +;* єёЄрэютъш юсЁрсюЄўшър яЁхЁ√трэш  * +;************************************************** +; └тЄюЁ шёїюфэюую ЄхъёЄр ╩єыръют ┬ырфшьшЁ ├хээрф№хтшў. +; └фряЄрЎш  ш фюЁрсюЄър Mario79 + +MSMouseSearch: + pusha +; ╟ряЁхЄшЄ№ яЁхЁ√трэшх COM1 ш COM2 + cli + in AL,21h ;яЁюўшЄрЄ№ ьрёъє яЁхЁ√трэшщ + or AL,18h ;чряЁхЄшЄ№ IRQ3 ш IRQ4 + out 21h,AL ;чрьхэшЄ№ ьрёъє + sti +; ╧╬╚╤╩ ╠█╪╚ ╫┼╨┼╟ COM-╧╬╨╥█ +MouseSearch: + ; ╙ёЄрэртыштрхь ёъюЁюёЄ№ + ; яЁшхьр/яхЁхфрўш 1200 сюф + mov DX,[COMPortBaseAddr] + add DX,3 + in AL,DX + or AL,80h ;єёЄрэютшЄ№ сшЄ DLAB + out DX,AL + mov DX,[COMPortBaseAddr] + mov AL,60h ;1200 сюф + out DX,AL + inc DX + mov AL,0 + out DX,AL + ; ╙ёЄрэютшЄ№ фышэє ёыютр 7 сшЄ, 1 ёЄюяют√щ сшЄ, + ; ўхЄэюёЄ№ эх ъюэЄЁюышЁютрЄ№ + mov DX,[COMPortBaseAddr] + add DX,3 + mov AL,00000010b + out DX,AL + ; ╟ряЁхЄшЄ№ тёх яЁхЁ√трэш  + mov DX,[COMPortBaseAddr] + inc DX + mov AL,0 + out DX,AL +; ╧ЁютхЁшЄ№, ўЄю єёЄЁющёЄтю яюфъы■ўхэю ш  ты хЄё  +; ь√°№■ Єшяр MSMouse + ; ╬Єъы■ўшЄ№ яшЄрэшх ь√°ш ш яЁхЁ√трэш  + mov DX,[COMPortBaseAddr] + add DX,4 ;ЁхушёЄЁ єяЁртыхэш  ьюфхьюь + mov AL,0 ;ёсЁюёшЄ№ DTR, RTS ш OUT2 + out DX,AL + ; ╬цшфрЄ№ 5 "Єшъют" (0,2 ё) + mov ecx,0xffff +dT_1: + dec ecx + cmp ecx,0 + jne dT_1 + mov ecx,0xffff + ; ┬ъы■ўшЄ№ яшЄрэшх ь√°ш + mov AL,11b ;єёЄрэютшЄ№ DTR ш RTS + out DX,AL + ; ╬ўшёЄшЄ№ ЁхушёЄЁ фрээ√ї + mov DX,[COMPortBaseAddr] + in AL,DX +; ╓шъы юяЁюёр яюЁЄр +WaitData: + ; ╬цшфрЄ№ х∙х 10 "Єшъют" + dec ecx + cmp ecx,0 + je NoMouse + ; ╧ЁютхЁшЄ№ эрышўшх шфхэЄшЇшърЎшюээюую срщЄр + mov DX,[COMPortBaseAddr] + add DX,5 + in AL,DX + test AL,1 ;─рээ√х уюЄют√? + jz WaitData + ; ┬тхёЄш фрээ√х + mov DX,[COMPortBaseAddr] + in AL,DX + ; ╙ёЄЁющёЄтю  ты хЄё  ь√°№■? + cmp AL,'M' + je EndDetect +NoMouse: + inc [COMPortNum] + cmp [COMPortNum],1 + ja EndDetect + sub [COMPortBaseAddr],100h + jmp MouseSearch + +iglobal +COMPortBaseAddr dw 3F8h +COMPortNum dw 0 +endg + +iglobal +boot_setmouse_type db 'No COM mouse, set PS2',0 + db 'Detected - COM1 mouse',0 + db 'Detected - COM2 mouse',0 + +endg + +EndDetect: + cmp [COMPortNum],0 ;эюьхЁ яюЁЄр ьхэ№°х 0? + jl ComMouseNotFound ;ь√°№ эх эрщфхэр + cmp [COMPortNum],1 ;эюьхЁ яюЁЄр сюы№°х 1? + ja ComMouseNotFound ;ь√°№ эх эрщфхэр + mov ax,[COMPortNum] + add al,2 + jmp set_detecting_mouse + ComMouseNotFound: + mov al,1 + set_detecting_mouse: + mov [0xF604],al + dec al + movzx eax,al + imul eax,22 + mov esi,boot_setmouse_type + add esi,eax + call boot_log + popa + + diff --git a/trunk/detect/dev_fd.inc b/trunk/detect/dev_fd.inc new file mode 100644 index 000000000..753844d71 --- /dev/null +++ b/trunk/detect/dev_fd.inc @@ -0,0 +1,20 @@ +;*************************************************** +; яЁхфтрЁшЄхы№эр  юўшёЄър юсырёЄш ЄрсышЎ√ +; яюшёъ ш чрэхёхэшх т ЄрсышЎє яЁштюфют FDD +; ртЄюЁ Mario79 +;*************************************************** + xor eax,eax + mov edi,0x40000 + mov ecx,16384 + cld + rep stosd + + mov al,0x10 + out 0x70,al + mov cx,0xff +wait_cmos: + dec cx + cmp cx,0 + jne wait_cmos + in al,0x71 + mov [0x40000],al diff --git a/trunk/detect/dev_hdcd.inc b/trunk/detect/dev_hdcd.inc new file mode 100644 index 000000000..0c1e4c597 --- /dev/null +++ b/trunk/detect/dev_hdcd.inc @@ -0,0 +1,374 @@ +;****************************************************** +; яюшёъ яЁштюфют HDD ш CD +; ртЄюЁ шёїюфэюую ЄхъёЄр ╩єыръют ┬ырфшьшЁ ├хээрф№хтшў. +; рфряЄрЎш  ш фюЁрсюЄър Mario79 +;****************************************************** + +;**************************************************** +;* ╧╬╚╤╩ HDD ш CD * +;**************************************************** +FindHDD: + mov [ChannelNumber],1 + mov [DiskNumber],0 + call FindHDD_3 +; mov ax,[Sector512+176] +; mov [0x40006],ax +; mov ax,[Sector512+126] +; mov [0x40008],ax +; mov ax,[Sector512+128] +; mov [0x40008],ax + mov [DiskNumber],1 + call FindHDD_3 +; mov al,[Sector512+176] +; mov [0x40007],al + inc [ChannelNumber] + mov [DiskNumber],0 + call FindHDD_3 +; mov al,[Sector512+176] +; mov [0x40008],al + mov [DiskNumber],1 + call FindHDD_1 +; mov al,[Sector512+176] +; mov [0x40009],al + + jmp EndFindHDD + +FindHDD_1: + call ReadHDD_ID + cmp [DevErrorCode],0 + jne FindHDD_2 + cmp [Sector512+6],word 16 + ja FindHDD_2 + cmp [Sector512+12],word 255 + ja FindHDD_2 + inc byte [0x40001] + jmp FindHDD_2_2 + FindHDD_2: + call DeviceReset + cmp [DevErrorCode],0 + jne FindHDD_2_2 + call ReadCD_ID + cmp [DevErrorCode],0 + jne FindHDD_2_2 + inc byte [0x40001] + inc byte [0x40001] + FindHDD_2_2: + ret + +FindHDD_3: + call FindHDD_1 + shl byte [0x40001],2 + ret + + +; └фЁхё ёўшЄ√трхьюую ёхъЄюЁр т Ёхцшьх LBA +SectorAddress DD ? + +;************************************************* +;* ╫╥┼═╚┼ ╚─┼═╥╚╘╚╩└╥╬╨└ ╞┼╤╥╩╬├╬ ─╚╤╩└ * +;* ┬їюфэ√х ярЁрьхЄЁ√ яхЁхфр■Єё  ўхЁхч уыюсры№э√х * +;* яхЁхьхээ√х: * +;* ChannelNumber - эюьхЁ ърэрыр (1 шыш 2); * +;* DiskNumber - эюьхЁ фшёър эр ърэрых (0 шыш 1). * +;* ╚фхэЄшЇшърЎшюээ√щ сыюъ фрээ√ї ёўшЄ√трхЄё  * +;* т ьрёёшт Sector512. * +;************************************************* +ReadHDD_ID: +; ╟рфрЄ№ Ёхцшь CHS + mov [ATAAddressMode],0 +; ╧юёырЄ№ ъюьрэфє шфхэЄшЇшърЎшш єёЄЁющёЄтр + mov [ATAFeatures],0 + mov [ATAHead],0 + mov [ATACommand],0ECh + call SendCommandToHDD + cmp [DevErrorCode],0 ;яЁютхЁшЄ№ ъюф ю°шсъш + jne @@End ;чръюэўшЄ№, ёюїЁрэшт ъюф ю°шсъш + mov DX,[ATABasePortAddr] + add DX,7 ;рфЁхё ЁхушёЄЁр ёюёЄю эш  + mov ecx,0xffff +@@WaitCompleet: + ; ╧ЁютхЁшЄ№ тЁхь  т√яюыэхэш  ъюьрэф√ + dec ecx + cmp ecx,0 + je @@Error1 ;ю°шсър Єрщь-рєЄр + ; ╧ЁютхЁшЄ№ уюЄютэюёЄ№ + in AL,DX + test AL,80h ;ёюёЄю эшх ёшуэрыр BSY + jnz @@WaitCompleet + test AL,1 ;ёюёЄю эшх ёшуэрыр ERR + jnz @@Error6 + test AL,08h ;ёюёЄю эшх ёшуэрыр DRQ + jz @@WaitCompleet +; ╧Ёшэ Є№ сыюъ фрээ√ї юЄ ъюэЄЁюыыхЁр +; mov AX,DS +; mov ES,AX + mov EDI,Sector512 ;offset Sector512 + mov DX,[ATABasePortAddr] ;ЁхушёЄЁ фрээ√ї + mov CX,256 ;ўшёыю ёўшЄ√трхь√ї ёыют + rep insw ;яЁшэ Є№ сыюъ фрээ√ї + jmp @@End +; ╟ряшёрЄ№ ъюф ю°шсъш +@@Error1: + mov [DevErrorCode],1 + jmp @@End +@@Error6: + mov [DevErrorCode],6 +@@End: ret + + + +; ╤ЄрэфрЁЄэ√х срчют√х рфЁхёр ърэрыют 1 ш 2 +StandardATABases DW 1F0h, 170h +; ═юьхЁ ърэрыр +ChannelNumber DW ? +; ═юьхЁ фшёър +DiskNumber DB ? +; ┴рчют√щ рфЁхё уЁєяя√ яюЁЄют ъюэЄЁюыыхЁр ATA +ATABasePortAddr DW ? +; ╧рЁрьхЄЁ√ ATA-ъюьрэф√ +ATAFeatures DB ? ;юёюсхээюёЄш +ATASectorCount DB ? ;ъюышўхёЄтю юсЁрсрЄ√трхь√ї ёхъЄюЁют +ATASectorNumber DB ? ;эюьхЁ эрўры№эюую ёхъЄюЁр +ATACylinder DW ? ;эюьхЁ эрўры№эюую ЎшышэфЁр +ATAHead DB ? ;эюьхЁ эрўры№эющ уюыютъш +ATAAddressMode DB ? ;Ёхцшь рфЁхёрЎшш (0 - CHS, 1 - LBA) +ATACommand DB ? ;ъюф ъюьрэф√, яюфыхцр∙хщ т√яюыэхэш■ +; ╩юф ю°шсъш (0 - эхЄ ю°шсюъ, 1 - яЁхт√°хэ фюяєёЄшь√щ +; шэЄхЁтры юцшфрэш , 2 - эхтхЁэ√щ ъюф Ёхцшьр рфЁхёрЎшш, +; 3 - эхтхЁэ√щ эюьхЁ ърэрыр, 4 - эхтхЁэ√щ эюьхЁ фшёър, +; 5 - эхтхЁэ√щ эюьхЁ уюыютъш, 6 - ю°шсър яЁш т√яюыэхэшш +; ъюьрэф√) +DevErrorCode DB ? + +;**************************************************** +;* ╧╬╤╦└╥▄ ╩╬╠└═─╙ ╟└─└══╬╠╙ ─╚╤╩╙ * +;* ┬їюфэ√х ярЁрьхЄЁ√ яхЁхфр■Єё  ўхЁхч уыюсры№э√х * +;* яхЁхьхээ√х: * +;* ChannelNumber - эюьхЁ ърэрыр (1 шыш 2); * +;* DiskNumber - эюьхЁ фшёър (0 шыш 1); * +;* ATAFeatures - "юёюсхээюёЄш"; * +;* ATASectorCount - ъюышўхёЄтю ёхъЄюЁют; * +;* ATASectorNumber - эюьхЁ эрўры№эюую ёхъЄюЁр; * +;* ATACylinder - эюьхЁ эрўры№эюую ЎшышэфЁр; * +;* ATAHead - эюьхЁ эрўры№эющ уюыютъш; * +;* ATAAddressMode - Ёхцшь рфЁхёрЎшш (0-CHS, 1-LBA); * +;* ATACommand - ъюф ъюьрэф√. * +;* ╧юёых єёях°эюую т√яюыэхэш  ЇєэъЎшш: * +;* т ATABasePortAddr - срчют√щ рфЁхё HDD; * +;* т DevErrorCode - эюы№. * +;* ╧Ёш тючэшъэютхэшш ю°шсъш т DevErrorCode сєфхЄ * +;* тючтЁр∙хэ ъюф ю°шсъш. * +;**************************************************** +SendCommandToHDD: +; ╧ЁютхЁшЄ№ чэрўхэшх ъюфр Ёхцшьр + cmp [ATAAddressMode],1 + ja @@Err2 +; ╧ЁютхЁшЄ№ ъюЁЁхъЄэюёЄ№ эюьхЁр ърэрыр + mov BX,[ChannelNumber] + cmp BX,1 + jb @@Err3 + cmp BX,2 + ja @@Err3 +; ╙ёЄрэютшЄ№ срчют√щ рфЁхё + dec BX + shl BX,1 + movzx ebx,bx + mov AX,[ebx+StandardATABases] + mov [ATABasePortAddr],AX +; ╬цшфрэшх уюЄютэюёЄш HDD ъ яЁшхьє ъюьрэф√ + ; ┬√сЁрЄ№ эєцэ√щ фшёъ + mov DX,[ATABasePortAddr] + add DX,6 ;рфЁхё ЁхушёЄЁр уюыютюъ + mov AL,[DiskNumber] + cmp AL,1 ;яЁютхЁшЄ№ эюьхЁр фшёър + ja @@Err4 + shl AL,4 + or AL,10100000b + out DX,AL + ; ╬цшфрЄ№, яюър фшёъ эх сєфхЄ уюЄют + inc DX + mov ecx,0xfff +; mov eax,[timer_ticks] +; mov [TickCounter_1],eax +@@WaitHDReady: + ; ╧ЁютхЁшЄ№ тЁхь  юцшфрэш  + dec ecx + cmp ecx,0 + je @@Err1 +; mov eax,[timer_ticks] +; sub eax,[TickCounter_1] +; cmp eax,300 ;юцшфрЄ№ 300 Єшъют +; ja @@Err1 ;ю°шсър Єрщь-рєЄр + ; ╧ЁюўшЄрЄ№ ЁхушёЄЁ ёюёЄю эш  + in AL,DX + ; ╧ЁютхЁшЄ№ ёюёЄю эшх ёшуэрыр BSY + test AL,80h + jnz @@WaitHDReady + ; ╧ЁютхЁшЄ№ ёюёЄю эшх ёшуэрыр DRQ + test AL,08h + jnz @@WaitHDReady +; ╟руЁєчшЄ№ ъюьрэфє т ЁхушёЄЁ√ ъюэЄЁюыыхЁр + cli + mov DX,[ATABasePortAddr] + inc DX ;ЁхушёЄЁ "юёюсхээюёЄхщ" + mov AL,[ATAFeatures] + out DX,AL + inc DX ;ёўхЄўшъ ёхъЄюЁют + mov AL,[ATASectorCount] + out DX,AL + inc DX ;ЁхушёЄЁ эюьхЁр ёхъЄюЁр + mov AL,[ATASectorNumber] + out DX,AL + inc DX ;эюьхЁ ЎшышэфЁр (ьырф°шщ срщЄ) + mov AX,[ATACylinder] + out DX,AL + inc DX ;эюьхЁ ЎшышэфЁр (ёЄрЁ°шщ срщЄ) + mov AL,AH + out DX,AL + inc DX ;эюьхЁ уюыютъш/эюьхЁ фшёър + mov AL,[DiskNumber] + shl AL,4 + cmp [ATAHead],0Fh ;яЁютхЁшЄ№ эюьхЁ уюыютъш + ja @@Err5 + or AL,[ATAHead] + or AL,10100000b + mov AH,[ATAAddressMode] + shl AH,6 + or AL,AH + out DX,AL +; ╧юёырЄ№ ъюьрэфє + mov AL,[ATACommand] + inc DX ;ЁхушёЄЁ ъюьрэф + out DX,AL + sti +; ╤сЁюёшЄ№ яЁшчэръ ю°шсъш + mov [DevErrorCode],0 + jmp @@End_2 +; ╟ряшёрЄ№ ъюф ю°шсъш +@@Err1: mov [DevErrorCode],1 + jmp @@End_2 +@@Err2: mov [DevErrorCode],2 + jmp @@End_2 +@@Err3: mov [DevErrorCode],3 + jmp @@End_2 +@@Err4: mov [DevErrorCode],4 + jmp @@End_2 +@@Err5: mov [DevErrorCode],5 +; ╟ртхЁ°хэшх ЁрсюЄ√ яЁюуЁрьь√ +@@End_2: + ret + +;************************************************* +;* ╫╥┼═╚┼ ╚─┼═╥╚╘╚╩└╥╬╨└ ╙╤╥╨╬╔╤╥┬└ ATAPI * +;* ┬їюфэ√х ярЁрьхЄЁ√ яхЁхфр■Єё  ўхЁхч уыюсры№э√х * +;* яхЁьхээ√х: * +;* ChannelNumber - эюьхЁ ърэрыр; * +;* DiskNumber - эюьхЁ фшёър эр ърэрых. * +;* ╚фхэЄшЇшърЎшюээ√щ сыюъ фрээ√ї ёўшЄ√трхЄё  * +;* т ьрёёшт Sector512. * +;************************************************* +ReadCD_ID: +; ╟рфрЄ№ Ёхцшь CHS + mov [ATAAddressMode],0 +; ╧юёырЄ№ ъюьрэфє шфхэЄшЇшърЎшш єёЄЁющёЄтр + mov [ATAFeatures],0 + mov [ATASectorCount],0 + mov [ATASectorNumber],0 + mov [ATACylinder],0 + mov [ATAHead],0 + mov [ATACommand],0A1h + call SendCommandToHDD + cmp [DevErrorCode],0 ;яЁютхЁшЄ№ ъюф ю°шсъш + jne @@End_1 ;чръюэўшЄ№, ёюїЁрэшт ъюф ю°шсъш +; ╬цшфрЄ№ уюЄютэюёЄ№ фрээ√ї HDD + mov DX,[ATABasePortAddr] + add DX,7 ;яюЁЄ 1ї7h + mov ecx,0xffff +@@WaitCompleet_1: + ; ╧ЁютхЁшЄ№ тЁхь  + dec ecx + cmp ecx,0 + je @@Error1_1 ;ю°шсър Єрщь-рєЄр + ; ╧ЁютхЁшЄ№ уюЄютэюёЄ№ + in AL,DX + test AL,80h ;ёюёЄю эшх ёшуэрыр BSY + jnz @@WaitCompleet_1 + test AL,1 ;ёюёЄю эшх ёшуэрыр ERR + jnz @@Error6_1 + test AL,08h ;ёюёЄю эшх ёшуэрыр DRQ + jz @@WaitCompleet_1 +; ╧Ёшэ Є№ сыюъ фрээ√ї юЄ ъюэЄЁюыыхЁр +; mov AX,DS +; mov ES,AX + mov EDI,Sector512 ;offset Sector512 + mov DX,[ATABasePortAddr] ;яюЁЄ 1x0h + mov CX,256 ;ўшёыю ёўшЄ√трхь√ї ёыют + rep insw + jmp @@End_1 +; ╟ряшёрЄ№ ъюф ю°шсъш +@@Error1_1: + mov [DevErrorCode],1 + jmp @@End_1 +@@Error6_1: + mov [DevErrorCode],6 +@@End_1: + ret + +;************************************************* +;* ╤┴╨╬╤ ╙╤╥╨╬╔╤╥┬└ * +;* ┬їюфэ√х ярЁрьхЄЁ√ яхЁхфр■Єё  ўхЁхч уыюсры№э√х * +;* яхЁхьхээ√х: * +;* ChannelNumber - эюьхЁ ърэрыр (1 шыш 2); * +;* DiskNumber - эюьхЁ фшёър (0 шыш 1). * +;************************************************* +DeviceReset: +; ╧ЁютхЁшЄ№ ъюЁЁхъЄэюёЄ№ эюьхЁр ърэрыр + mov BX,[ChannelNumber] + cmp BX,1 + jb @@Err3_2 + cmp BX,2 + ja @@Err3_2 +; ╙ёЄрэютшЄ№ срчют√щ рфЁхё + dec BX + shl BX,1 + movzx ebx,bx + mov DX,[ebx+StandardATABases] + mov [ATABasePortAddr],DX +; ┬√сЁрЄ№ эєцэ√щ фшёъ + add DX,6 ;рфЁхё ЁхушёЄЁр уюыютюъ + mov AL,[DiskNumber] + cmp AL,1 ;яЁютхЁшЄ№ эюьхЁр фшёър + ja @@Err4_2 + shl AL,4 + or AL,10100000b + out DX,AL +; ╧юёырЄ№ ъюьрэфє "╤сЁюё" + mov AL,08h + inc DX ;ЁхушёЄЁ ъюьрэф + out DX,AL + mov ecx,0xffff +@@WaitHDReady_1: + ; ╧ЁютхЁшЄ№ тЁхь  юцшфрэш  + dec ecx + cmp ecx,0 + je @@Err1_2 ;ю°шсър Єрщь-рєЄр + ; ╧ЁюўшЄрЄ№ ЁхушёЄЁ ёюёЄю эш  + in AL,DX + ; ╧ЁютхЁшЄ№ ёюёЄю эшх ёшуэрыр BSY + test AL,80h + jnz @@WaitHDReady_1 +; ╤сЁюёшЄ№ яЁшчэръ ю°шсъш + mov [DevErrorCode],0 + jmp @@End_3 +; ╬сЁрсюЄър ю°шсюъ +@@Err1_2: mov [DevErrorCode],1 + jmp @@End_3 +@@Err3_2: mov [DevErrorCode],3 + jmp @@End_3 +@@Err4_2: mov [DevErrorCode],4 +; ╟ряшёрЄ№ ъюф ю°шсъш +@@End_3: + ret + +EndFindHDD: + diff --git a/trunk/detect/disks.inc b/trunk/detect/disks.inc new file mode 100644 index 000000000..31b02f25c --- /dev/null +++ b/trunk/detect/disks.inc @@ -0,0 +1,4 @@ +include 'dev_fd.inc' +include 'dev_hdcd.inc' +include 'sear_par.inc' + diff --git a/trunk/detect/sear_par.inc b/trunk/detect/sear_par.inc new file mode 100644 index 000000000..082f75ac8 --- /dev/null +++ b/trunk/detect/sear_par.inc @@ -0,0 +1,116 @@ +;**************************************************** +; яюшёъ ыюушўхёъшї фшёъют эр юсэрЁєцхээ√ї HDD +; ш чрэхёхэшх фрээ√ї т юсырёЄ№ ЄрсышЎ√ +; ртЄюЁ Mario79 +;**************************************************** + mov [transfer_adress],0x4000a + search_partitions_ide0: + test [0x40001],byte 0x40 + jz search_partitions_ide1 + mov [hdbase],0x1f0 + mov [hdid],0x0 + mov [hdpos],1 + mov [fat32part],1 + search_partitions_ide0_1: + call set_FAT32_variables + cmp [problem_partition],0 + jne search_partitions_ide1 + inc byte [0x40002] + call partition_data_transfer + add [transfer_adress],100 + inc [fat32part] + jmp search_partitions_ide0_1 + + search_partitions_ide1: + test [0x40001],byte 0x10 + jz search_partitions_ide2 + mov [hdbase],0x1f0 + mov [hdid],0x10 + mov [hdpos],2 + mov [fat32part],1 + search_partitions_ide1_1: + call set_FAT32_variables + cmp [problem_partition],0 + jne search_partitions_ide2 + inc byte [0x40003] + call partition_data_transfer + add [transfer_adress],100 + inc [fat32part] + jmp search_partitions_ide1_1 + + search_partitions_ide2: + test [0x40001],byte 0x4 + jz search_partitions_ide3 + mov [hdbase],0x170 + mov [hdid],0x0 + mov [hdpos],3 + mov [fat32part],1 + search_partitions_ide2_1: + call set_FAT32_variables + cmp [problem_partition],0 + jne search_partitions_ide3 + inc byte [0x40004] + call partition_data_transfer + add [transfer_adress],100 + inc [fat32part] + jmp search_partitions_ide2_1 + + search_partitions_ide3: + test [0x40001],byte 0x1 + jz end_search_partitions_ide + mov [hdbase],0x170 + mov [hdid],0x10 + mov [hdpos],4 + mov [fat32part],1 + search_partitions_ide3_1: + call set_FAT32_variables + cmp [problem_partition],0 + jne end_search_partitions_ide + inc byte [0x40005] + call partition_data_transfer + add [transfer_adress],100 + inc [fat32part] + jmp search_partitions_ide3_1 + + +partition_data_transfer: + mov edi,[transfer_adress] + mov esi,PARTITION_START + xor ecx,ecx + mov cx,69 ;100 + rep movsb + ret +transfer_adress dd 0 +partition_data_transfer_1: + cli + mov edi,PARTITION_START + mov esi,[transfer_adress] + xor ecx,ecx + mov cx,69 ;100 + rep movsb + sti + ret + + end_search_partitions_ide: + +;PARTITION_START dd 0x3f +;PARTITION_END dd 0 +;SECTORS_PER_FAT dd 0x1f3a +;NUMBER_OF_FATS dd 0x2 +;SECTORS_PER_CLUSTER dd 0x8 +;BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes +;ROOT_CLUSTER dd 2 ; first rootdir cluster +;FAT_START dd 0 ; start of fat table +;ROOT_START dd 0 ; start of rootdir (only fat16) +;ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) +;DATA_START dd 0 ; start of data area (=first cluster 2) +;LAST_CLUSTER dd 0 ; last availabe cluster +;ADR_FSINFO dd 0 ; used only by fat32 +; +;fatRESERVED dd 0x0FFFFFF6 +;fatBAD dd 0x0FFFFFF7 +;fatEND dd 0x0FFFFFF8 +;fatMASK dd 0x0FFFFFFF +; +;fat_type db 0 ; 0=none, 16=fat16, 32=fat32 + diff --git a/trunk/fs/fat12.inc b/trunk/fs/fat12.inc new file mode 100644 index 000000000..4ae37876a --- /dev/null +++ b/trunk/fs/fat12.inc @@ -0,0 +1,1084 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; FAT12.INC ;; +;; (C) 2005 Mario79, License: GPL ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +n_sector dd 0 ; temporary save for sector value +flp_status dd 0 +clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write +path_pointer_flp dd 0 +pointer_file_name_flp dd 0 +save_root_flag db 0 +save_flag db 0 +root_read db 0 ; 0-necessary to load root, 1-not to load root +flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat +flp_number db 0 ; 1- Floppy A, 2-Floppy B +old_track db 0 ; old value track +flp_label rb 15 ; Label and ID of inserted floppy disk + +reserve_flp: + + cli + cmp [flp_status],0 + je reserve_flp_ok + + sti + call change_task + jmp reserve_flp + + reserve_flp_ok: + + push eax + mov eax,[0x3000] + shl eax,5 + mov eax,[eax+0x3000+4] + mov [flp_status],eax + pop eax + sti + ret + +floppy_free_space: +;--------------------------------------------- +; +; returns free space in edi +; +;--------------------------------------------- + push eax ebx ecx + call read_flp_fat + cmp [FDC_Status],0 + jne fdc_status_error_2 + mov eax,0x282000 + xor edi,edi + mov ecx,2847 ;1448000/512 +rdfs1_1: + mov ebx,[eax] + and ebx,4095 + cmp ebx,0 + jne rdfs2_1 + add edi,512 +rdfs2_1: + add eax,2 + loop rdfs1_1 +fdc_status_error_2: + pop ecx ebx eax + ret + + + + +floppy_fileread: +;---------------------------------------------------------------- +; +; fileread - sys floppy +; +; eax points to filename 11 chars - for root directory +; ebx first wanted block ; 1+ ; if 0 then set to 1 +; ecx number of blocks to read ; 1+ ; if 0 then set to 1 +; edx mem location to return data +; esi length of filename 12*X +; edi pointer to path /fd/1/...... - for all files in nested directories +; +; ret ebx = size or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; 10 = access denied +;-------------------------------------------------------------- + + mov [save_flag],0 + mov [path_pointer_flp],edi + cmp esi,0 ; return ramdisk root + jne fr_noroot_1 + cmp ebx,224/16 + jbe fr_do_1 + mov eax,5 + mov ebx,0 + mov [flp_status],0 + ret + +fr_do_1: + push ebx ecx edx + call read_flp_root + pop edx ecx ebx + cmp [FDC_Status],0 + jne fdc_status_error_1 + mov edi,edx + dec ebx + shl ebx,9 + mov esi,0x8000 + add esi,ebx + shl ecx,9 + cld + rep movsb + mov eax,0 ; ok read + mov ebx,0 + mov [flp_status],0 + ret +fdc_status_error_1: + mov [flp_status],0 + mov eax,10 + mov ebx,-1 + ret + +fr_noroot_1: + sub esp,32 + call expand_filename +frfloppy_1: + cmp ebx,0 + jne frfl5_1 + mov ebx,1 +frfl5_1: + cmp ecx,0 + jne frfl6_1 + mov ecx,1 +frfl6_1: + dec ebx + push eax + push eax ebx ecx edx esi edi + call read_flp_fat + cmp [FDC_Status],0 + jne fdc_status_error_3_1 + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],1 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + call SeekTrack + mov dh,14 +l.20_1: + call ReadSectWithRetr + cmp [FDC_Status],0 + jne fdc_status_error_3_1 + mov dl,16 + mov edi,0xD000 + inc [FDD_Sector] +l.21_1: + mov esi,eax ;Name of file we want + mov ecx,11 + cld + rep cmpsb ;Found the file? + je fifound_1 ;Yes + add ecx,21 + add edi, ecx ;Advance to next entry + dec dl + cmp dl,0 + jne l.21_1 + dec dh + cmp dh,0 + jne l.20_1 +fdc_status_error_3: + mov eax,5 ; file not found ? + mov ebx,-1 + add esp,32+28 + mov [flp_status],0 + ret +fdc_status_error_3_2: + cmp [FDC_Status],0 + je fdc_status_error_3 +fdc_status_error_3_1: + add esp,32+28 + jmp fdc_status_error_1 + +fifound_1: + mov eax,[path_pointer_flp] + cmp [eax+36],byte 0 + je fifound_2 + add edi,0xf + mov eax,[edi] + and eax,65535 + mov ebx,[path_pointer_flp] + add ebx,36 + call get_cluster_of_a_path_flp + jc fdc_status_error_3_2 + mov ebx,[ebx-11+28] ;file size + mov [esp+20],ebx + mov [esp+24],ebx + jmp fifound_3 +fifound_2: + mov ebx,[edi-11+28] ;file size + mov [esp+20],ebx + mov [esp+24],ebx + add edi,0xf + mov eax,[edi] +fifound_3: + and eax,65535 + mov [n_sector],eax ;eax=cluster +frnew_1: + add eax,31 ;bootsector+2*fat+filenames + cmp [esp+16],dword 0 ; wanted cluster ? + jne frfl7_1 + call read_chs_sector + cmp [FDC_Status],0 + jne fdc_status_error_5 + mov edi,[esp+8] + call give_back_application_data_1 + add [esp+8],dword 512 + dec dword [esp+12] ; last wanted cluster ? + cmp [esp+12],dword 0 + je frnoread_1 + jmp frfl8_1 +frfl7_1: + dec dword [esp+16] +frfl8_1: + mov edi,[n_sector] + shl edi,1 ;find next cluster from FAT + add edi,0x282000 + mov eax,[edi] + and eax,4095 + mov edi,eax + mov [n_sector],edi + cmp edi,4095 ;eof - cluster + jz frnoread2_1 + cmp [esp+24],dword 512 ;eof - size + jb frnoread_1 + sub [esp+24],dword 512 + jmp frnew_1 + +read_chs_sector: + call calculate_chs + call ReadSectWithRetr + ret + +frnoread2_1: + cmp [esp+16],dword 0 ; eof without read ? + je frnoread_1 + mov [fdc_irq_func],fdc_null + pop edi esi edx ecx + add esp,4 + pop ebx ; ebx <- eax : size of file + add esp,36 + mov eax,6 ; end of file + mov [flp_status],0 + ret + +frnoread_1: + pop edi esi edx ecx + add esp,4 + pop ebx ; ebx <- eax : size of file + add esp,36 + mov eax,0 + mov [flp_status],0 + ret + +fdc_status_error_5: + pop edi esi edx ecx + add esp,4 + pop ebx ; ebx <- eax : size of file + add esp,36 + jmp fdc_status_error_1 + +read_flp_root: + pusha + call check_label + cmp [FDC_Status],0 + jne unnecessary_root_read + cmp [root_read],1 + je unnecessary_root_read + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],1 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + mov edi,0x8000 + call SeekTrack +read_flp_root_1: + call ReadSectWithRetr + cmp [FDC_Status],0 + jne unnecessary_root_read + push edi + call give_back_application_data_1 + pop edi + add edi,512 + inc [FDD_Sector] + cmp [FDD_Sector],16 + jne read_flp_root_1 + mov [root_read],1 +unnecessary_root_read: + popa + ret + + +read_flp_fat: + pusha + call check_label + cmp [FDC_Status],0 + jne unnecessary_flp_fat + cmp [flp_fat],1 + je unnecessary_flp_fat + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],0 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + mov edi,0x8000 + call SeekTrack +read_flp_fat_1: + call ReadSectWithRetr + cmp [FDC_Status],0 + jne unnecessary_flp_fat + push edi + call give_back_application_data_1 + pop edi + add edi,512 + inc [FDD_Sector] + cmp [FDD_Sector],19 + jne read_flp_fat_1 + mov [FDD_Sector],1 + mov [FDD_Head],1 + call ReadSectWithRetr + cmp [FDC_Status],0 + jne unnecessary_flp_fat + call give_back_application_data_1 + call calculatefatchain_flp + mov [root_read],0 + mov [flp_fat],1 +unnecessary_flp_fat: + popa + ret + +calculatefatchain_flp: + pushad + + mov esi,0x8000 + mov edi,0x282000 + + fcnew_1: + mov eax,dword [esi] + mov ebx,dword [esi+4] + mov ecx,dword [esi+8] + mov edx,ecx + shr edx,4 ;8 ok + shr dx,4 ;7 ok + xor ch,ch + shld ecx,ebx,20 ;6 ok + shr cx,4 ;5 ok + shld ebx,eax,12 + and ebx,0x0fffffff ;4 ok + shr bx,4 ;3 ok + shl eax,4 + and eax,0x0fffffff ;2 ok + shr ax,4 ;1 ok + mov dword [edi],eax + add edi,4 + mov dword [edi],ebx + add edi,4 + mov dword [edi],ecx + add edi,4 + mov dword [edi],edx + add edi,4 + add esi,12 + + cmp edi,0x282000+2856*2 ;2849 clusters + jnz fcnew_1 + + popad + ret + +check_label: + pushad + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],0 ; ╤ЄюЁюэр + mov [FDD_Sector],1 ; ╤хъЄюЁ + call SetUserInterrupts + call FDDMotorON + call RecalibrateFDD + cmp [FDC_Status],0 + jne fdc_status_error + call SeekTrack + cmp [FDC_Status],0 + jne fdc_status_error + call ReadSectWithRetr + cmp [FDC_Status],0 + jne fdc_status_error + mov esi,flp_label + mov edi,0xD000+39 + mov ecx,15 + cld + rep cmpsb + je same_label + mov [root_read],0 + mov [flp_fat],0 +same_label: + mov esi,0xD000+39 + mov edi,flp_label + mov ecx,15 + cld + rep movsb + popad + ret +fdc_status_error: + popad + ret + +save_flp_root: + pusha + call check_label + cmp [FDC_Status],0 + jne unnecessary_root_save + cmp [root_read],0 + je unnecessary_root_save + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],1 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + mov esi,0x8000 + call SeekTrack +save_flp_root_1: + push esi + call take_data_from_application_1 + pop esi + add esi,512 + call WriteSectWithRetr + cmp [FDC_Status],0 + jne unnecessary_root_save + inc [FDD_Sector] + cmp [FDD_Sector],16 + jne save_flp_root_1 +unnecessary_root_save: + mov [fdc_irq_func],fdc_null + popa + ret + +save_flp_fat: + pusha + call check_label + cmp [FDC_Status],0 + jne unnecessary_flp_fat_save + cmp [flp_fat],0 + je unnecessary_flp_fat_save + call restorefatchain_flp + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],0 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + mov esi,0x8000 + call SeekTrack +save_flp_fat_1: + push esi + call take_data_from_application_1 + pop esi + add esi,512 + call WriteSectWithRetr + cmp [FDC_Status],0 + jne unnecessary_flp_fat_save + inc [FDD_Sector] + cmp [FDD_Sector],19 + jne save_flp_fat_1 + mov [FDD_Sector],1 + mov [FDD_Head],1 + call take_data_from_application_1 + call WriteSectWithRetr + cmp [FDC_Status],0 + jne unnecessary_flp_fat_save + mov [root_read],0 +unnecessary_flp_fat_save: + mov [fdc_irq_func],fdc_null + popa + ret + + +restorefatchain_flp: ; restore fat chain + pushad + + mov esi,0x282000 + mov edi,0x8000 + + fcnew2_1: + mov eax,dword [esi] + mov ebx,dword [esi+4] + shl ax,4 + shl eax,4 + shl bx,4 + shr ebx,4 + shrd eax,ebx,8 + shr ebx,8 + mov dword [edi],eax + add edi,4 + mov word [edi],bx + add edi,2 + add esi,8 + + cmp edi,0x8000+0x1200 ;4274 bytes - all used FAT + jb fcnew2_1 + + mov esi,0x8000 ; duplicate fat chain + mov edi,0x8000+0x1200 + mov ecx,0x1200/4 + cld + rep movsd + + popad + ret + + +floppy_filedelete: +;-------------------------------------------- +; +; filedelete - sys floppy +; in: +; eax - filename 11 chars - for root directory +; edi pointer to path /fd/1/...... - for all files in nested directories +; +; out: +; eax - 0 = successful, 1 = file not found, 10 = access denied +; +;-------------------------------------------- + mov [path_pointer_flp],edi + mov [save_flag],0 + mov ebp,1 ; file not found as default +filedelete_newtry_1: + sub esp,32 + call expand_filename + push eax ebx ecx edx esi edi + call read_flp_fat + cmp [FDC_Status],0 + jne frnoreadd_1 + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],1 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + call SeekTrack + mov dh,14 +l.20_2: + call ReadSectWithRetr + cmp [FDC_Status],0 + jne fdc_status_error_4 + mov dl,16 + mov edi,0xD000 + inc [FDD_Sector] +l.21_2: + mov esi,eax ;Name of file we want + mov ecx,11 + cld + rep cmpsb ;Found the file? + je fifoundd_1 ;Yes + add ecx,21 + add edi, ecx ;Advance to next entry + dec dl + cmp dl,0 + jne l.21_2 + dec dh + cmp dh,0 + jne l.20_2 + jmp frnoreadd_1 + +fdc_status_error_4: + pop edi esi edx ecx ebx eax + add esp,32 + jmp fdc_status_error_1 + +fifoundd_1: + mov eax,[path_pointer_flp] + cmp [eax+36],byte 0 + je fifoundd_2 + add edi,0xf + mov eax,[edi] + and eax,65535 + mov ebx,[path_pointer_flp] + add ebx,36 + call get_cluster_of_a_path_flp + jc frnoreadd_1_1 + mov edi,ebx + add edi,11 + jmp fifoundd_2_1 +fifoundd_2: + dec [FDD_Sector] +fifoundd_2_1: + mov [edi-11],byte 0xE5 ;mark filename deleted + add edi,0xf + mov eax,[edi] + and eax,65535 + mov edi,eax ;edi = cluster +frnewd_1: + shl edi,1 ;find next cluster from FAT + add edi,0x282000 + mov eax,[edi] + mov [edi],word 0x0 ;clear fat chain cluster + and eax,4095 + mov edi,eax + cmp edi,dword 4095 ;last cluster ? + jz frnoreadd2_1 + jmp frnewd_1 + +frnoreadd2_1: + call WriteSectWithRetr + cmp [FDC_Status],0 + jne fdc_status_error_4 + call save_flp_fat + cmp [FDC_Status],0 + jne fdc_status_error_4 +; pop edi esi edx ecx ebx eax +; add esp,32 + mov ebp,0 ; file found +; jmp filedelete_newtry_1 + jmp frnoreadd_1 + +frnoreadd_1_1: + cmp [FDC_Status],0 + jne fdc_status_error_4 +frnoreadd_1: + pop edi esi edx ecx ebx eax + add esp,32 + mov eax,ebp + ret + +floppy_filesave: +;---------------------------------------------------------- +; +; filesave - sys floppy +; +; eax ; pointer to file name 11 chars - for root directory +; ebx ; buffer +; ecx ; count to write in bytes +; edx ; 0 create new , 1 append +; edi pointer to path /fd/1/...... - for all files in nested directories +; +; output : eax = 0 - ok +; 5 - file not found / directory not found +; 8 - disk full +; 10 - access denied +;----------------------------------------------------------- + mov [path_pointer_flp],edi + sub esp,32 + call expand_filename + cmp edx,0 + jnz fsdel_1 + pusha + call floppy_filedelete + cmp [FDC_Status],0 + jne fdc_status_error_6 + popa + mov [save_flag],1 +fsdel_1: + call floppy_free_space + cmp [FDC_Status],0 + jne fdc_status_error_6 + cmp ecx,edi + jb rd_do_save_1 + add esp,32 + mov eax,8 ; not enough free space + mov [flp_status],0 + ret + +fdc_status_error_6: + popa + add esp,32 + jmp fdc_status_error_1 + +rd_do_save_1: + push eax ebx ecx edx esi edi + call read_flp_fat + cmp [FDC_Status],0 + jne fdc_status_error_7 + push eax + mov eax,[path_pointer_flp] + cmp [eax+36],byte 0 + jne fifoundds_2 + pop eax + mov [save_root_flag],1 + call read_flp_root + cmp [FDC_Status],0 + jne fdc_status_error_7 + mov edi,0x8000 ;Point at directory + mov edx,224 +1 + ; find an empty spot for filename in the root dir +l20ds_1: + sub edx,1 + cmp edx,0 + jnz l21ds_1 + jmp frnoreadds_1 +l21ds_1: + cmp [edi],byte 0xE5 + jz fifoundds_1 + cmp [edi],byte 0x0 + jz fifoundds_1 + add edi,32 ; Advance to next entry + jmp l20ds_1 + +fifoundds_2: + pop eax + mov [save_root_flag],0 + mov [FDD_Track],0 ; ╓шышэфЁ + mov [FDD_Head],1 ; ╤ЄюЁюэр + mov [FDD_Sector],2 ; ╤хъЄюЁ + call SeekTrack + mov dh,14 +l.20_3: + call ReadSectWithRetr + cmp [FDC_Status],0 + jne fdc_status_error_7 + mov dl,16 + mov edi,0xD000 + inc [FDD_Sector] +l.21_3: + mov esi,eax ;Name of file we want + mov ecx,11 + cld + rep cmpsb ;Found the file? + je fifoundds_3 ;Yes + add ecx,21 + add edi, ecx ;Advance to next entry + dec dl + cmp dl,0 + jne l.21_3 + dec dh + cmp dh,0 + jne l.20_3 +fdc_status_error_8: + pop edi esi edx ecx ebx eax + mov eax,5 ; file not found ? + mov ebx,-1 + add esp,32 + mov [flp_status],0 + ret + +fifoundds_3: + add edi,0xf + mov eax,[edi] + and eax,65535 + mov ebx,[path_pointer_flp] + add ebx,36 + call get_cluster_of_a_path_flp + jc fdc_status_error_7_1 +found_directory_for_writing_flp: + call analyze_directory_to_write_flp + jc fdc_status_error_7_1 + mov edi,ebx +fifoundds_1: + push edi ; move the filename to root dir + mov esi,[esp+4+20] + cmp [save_root_flag],0 + jne fifoundds_4 + mov esi,[pointer_file_name_flp] +fifoundds_4: + mov ecx,11 + cld + rep movsb + pop edi + mov edx,edi + add edx,11+0xf ; edx <- cluster save position + mov ebx,[esp+12] ; save file size + mov [edi+28],ebx + mov [edi+11],byte 0x20 ; attribute + call get_date_for_file ; from FAT32.INC + mov [edi+24],ax ; date + mov [edi+18],ax ; date + call get_time_for_file ; from FAT32.INC + mov [edi+22],ax ; time + xor ax,ax + mov [edi+20],ax + mov ebx,1 ; first cluster + cmp [save_root_flag],0 + jne frnewds_1 + call frnewds_2 + pusha + call WriteSectWithRetr + popa + cmp [FDC_Status],0 + jne fdc_status_error_7 + jmp frnewds_3 + +frnewds_1: + call frnewds_2 +frnewds_3: + pusha ; move save to floppy cluster + add ebx,31 + mov eax,ebx + mov esi,[esp+32+16] + call take_data_from_application_1 + call save_chs_sector + cmp [FDC_Status],0 + jne fdc_status_error_7 + popa + mov eax,[esp+12] + cmp eax,512 + jb flnsa_1 + sub eax,512 + mov [esp+12],eax + mov eax,[esp+16] + add eax,512 + mov [esp+16],eax + jmp frnewds_1 + +frnewds_2: + add ebx,1 + mov edi,ebx ; find free cluster in FAT + shl edi,1 + add edi,0x282000 + mov eax,[edi] + and eax,4095 + cmp eax,0x0 + jnz frnewds_2 + mov [edx],bx ; save next cluster pos. to prev cl. + mov edx,edi ; next save pos abs mem add + ret + +flnsa_1: + mov [edi],word 4095 ; mark end of file - last cluster + cmp [save_root_flag],1 + jne flnsa_2 + call save_flp_root + cmp [FDC_Status],0 + jne fdc_status_error_7 +flnsa_2: + call save_flp_fat + cmp [FDC_Status],0 + jne fdc_status_error_7 +frnoreadds_1: + pop edi esi edx ecx ebx eax + add esp,32 + mov eax,0 + mov [flp_status],0 + ret + +fdc_status_error_7_1: + cmp [FDC_Status],0 + je fdc_status_error_8 +fdc_status_error_7: + pop edi esi edx ecx ebx eax + add esp,32 + jmp fdc_status_error_1 + +save_chs_sector: + call calculate_chs + call WriteSectWithRetr + ret + +calculate_chs: + mov bl,[FDD_Track] + mov [old_track],bl + mov ebx,18 + xor edx,edx + div ebx + inc edx + mov [FDD_Sector],dl + xor edx,edx + mov ebx,2 + div ebx + mov [FDD_Track],al + mov [FDD_Head],0 + cmp edx,0 + je no_head_2 + inc [FDD_Head] +no_head_2: + mov dl,[old_track] + cmp dl,[FDD_Track] + je no_seek_track_1 + call SeekTrack +no_seek_track_1: + ret + + +get_cluster_of_a_path_flp: +;--------------------------------------------------------- +; input : EBX = pointer to a path string +; (example: the path "/files/data/document" become +; "files......data.......document...0" +; '.' = space char +; '0' = char(0) (ASCII=0) !!! ) +; output : if (CARRY=1) -> ERROR in the PATH +; if (CARRY=0) -> EAX=cluster +;--------------------------------------------------------- + + push edx + mov edx,ebx + +search_end_of_path_flp: + cmp [save_flag],0 + jne search_end_of_path_flp_1 + cmp byte [edx],0 + je found_end_of_path_flp + jmp search_end_of_path_flp_2 +search_end_of_path_flp_1: + cmp byte [edx+12],0 + je found_end_of_path_flp +search_end_of_path_flp_2: + inc edx ; '/' + call analyze_directory_flp + jc directory_not_found_flp + + mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field + mov ax,[ebx+26] ; read the LOW 16bit cluster field + and eax,0xfff ;[fatMASK] + add edx,11 ; 8+3 (name+extension) + jmp search_end_of_path_flp + +found_end_of_path_flp: + inc edx + mov [pointer_file_name_flp],edx + pop edx + clc ; no errors + ret + +directory_not_found_flp: + pop edx + stc ; errors occour + ret + +analyze_directory_flp: +;-------------------------------- +; input : EAX = first cluster of the directory +; EBX = pointer to filename +; output : IF CARRY=0 EAX = sector where th file is found +; EBX = pointer in buffer +; [buffer .. buffer+511] +; ECX,EDX,EDI,EDI not changed +; IF CARRY=1 +;-------------------------------- + push ebx ;[esp+16] + push ecx + push edx + push esi + push edi + + +adr56_flp: + mov [clust_tmp_flp],eax + add eax,31 + pusha + call read_chs_sector + popa + cmp [FDC_Status],0 + jne not_found_file_analyze_flp + + mov ecx,512/32 + mov ebx,0xD000 + +adr1_analyze_flp: + mov esi,edx ;[esp+16] + mov edi,ebx + cld + push ecx + mov ecx,11 + rep cmpsb + pop ecx + je found_file_analyze_flp + + add ebx,32 + loop adr1_analyze_flp + + mov eax,[clust_tmp_flp] + shl eax,1 ;find next cluster from FAT + add eax,0x282000 + mov eax,[eax] + and eax,4095 + cmp eax,0x0ff8 + jb adr56_flp +not_found_file_analyze_flp: + pop edi + pop esi + pop edx + pop ecx + add esp,4 + stc ;file not found + ret + +found_file_analyze_flp: + pop edi + pop esi + pop edx + pop ecx + add esp,4 + clc ;file found + ret + + +analyze_directory_to_write_flp: +;-------------------------------- +; input : EAX = first cluster of the directory +; output : IF CARRY=0 EAX = sector where the file is found +; EBX = pointer in buffer +; [buffer .. buffer+511] +; ECX,EDX,EDI,EDI not changed +; IF CARRY=1 +;-------------------------------- + + push ecx + push edx + push esi + +adr561: + mov [clust_tmp_flp],eax + add eax,31 + pusha + call read_chs_sector + popa + cmp [FDC_Status],0 + jne error_found_file_analyze1 + + mov ecx,512/32 + mov ebx,0xD000 + +adr1_analyze1: + cmp byte [ebx],0x00 + je found_file_analyze1 + cmp byte [ebx],0xe5 + je found_file_analyze1 + +avanti: + add ebx,32 + loop adr1_analyze1 + + mov eax,[clust_tmp_flp] + shl eax,1 ;find next cluster from FAT + add eax,0x282000 + mov eax,[eax] + and eax,4095 + cmp eax,0x0ff8 + jb adr561 + + call get_free_FAT ;this block of code add a new cluster + ;for the directory because the directory + ;is full + + mov [edi],word 0x0fff + + mov eax,[clust_tmp_flp] + shl eax,1 ;find next cluster from FAT + add eax,0x282000 + sub edi,0x282000 + mov [eax],di + + pusha + mov ecx,512/4 + xor eax,eax + mov edi,0xD000 + cld + rep stosd + popa + + mov eax,edi + add eax,31 + pusha + call save_chs_sector + popa + cmp [FDC_Status],0 + jne error_found_file_analyze1 + mov ebx,0xD000 + +found_file_analyze1: + + pop esi + pop edx + pop ecx + clc ;file found + ret + +error_found_file_analyze1: + pop esi + pop edx + pop ecx + stc + ret + +get_free_FAT_flp: +;------------------------------------------ +; input : EAX = # cluster for start the searching +; output : EAX = # first cluster found free +;------------------------------------------- + push ebx + + mov ebx,1 +check_new_flp: + add ebx,1 + mov edi,ebx ; find free cluster in FAT + shl edi,1 + add edi,0x282000 + mov eax,[edi] + and eax,4095 + cmp eax,0x0 + jnz check_new_flp + + pop ebx + ret diff --git a/trunk/fs/fat32.inc b/trunk/fs/fat32.inc new file mode 100644 index 000000000..9a32219d3 --- /dev/null +++ b/trunk/fs/fat32.inc @@ -0,0 +1,2827 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; FAT32.INC ;; +;; ;; +;; FAT16/32 functions for MenuetOS ;; +;; ;; +;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; 15.01.2005 get file size/attr/date, file_append - ATV ;; +;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;; +;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;; +;; 23.11.2004 don't allow overwrite dir with file - ATV ;; +;; 18.11.2004 get_disk_info and more error codes - ATV ;; +;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;; +;; 10.11.2004 removedir clear whole directory structure - ATV ;; +;; 08.11.2004 rename - ATV ;; +;; 30.10.2004 file_read return also dirsize in bytes - ATV ;; +;; 20.10.2004 Makedir/Removedir - ATV ;; +;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;; +;; 06.9.2004 Fix free space by Mario79 added - MH ;; +;; 24.5.2004 Write back buffer for File_write -VT ;; +;; 20.5.2004 File_read function to work with syscall 58 - VT ;; +;; 30.3.2004 Error parameters at function return - VT ;; +;; 01.5.2002 Bugfix in device write - VT ;; +;; 20.5.2002 Hd status check - VT ;; +;; 29.6.2002 Improved fat32 verification - VT ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 + +ERROR_DISK_BASE equ 1 +ERROR_UNSUPPORTED_FS equ 2 +ERROR_UNKNOWN_FS equ 3 +ERROR_PARTITION equ 4 +ERROR_FILE_NOT_FOUND equ 5 +ERROR_END_OF_FILE equ 6 +ERROR_MEMORY_POINTER equ 7 +ERROR_DISK_FULL equ 8 +ERROR_FAT_TABLE equ 9 +ERROR_ACCESS_DENIED equ 10 + +PUSHAD_EAX equ [esp+28] +PUSHAD_ECX equ [esp+24] +PUSHAD_EDX equ [esp+20] +PUSHAD_EBX equ [esp+16] +PUSHAD_EBP equ [esp+8] +PUSHAD_ESI equ [esp+4] +PUSHAD_EDI equ [esp+0] + +align 4 +;****************************************************** +; Please do not change this place - variables in text +; Mario79 +; START place +;****************************************************** +PARTITION_START dd 0x3f +PARTITION_END dd 0 +SECTORS_PER_FAT dd 0x1f3a +NUMBER_OF_FATS dd 0x2 +SECTORS_PER_CLUSTER dd 0x8 +BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes +ROOT_CLUSTER dd 2 ; first rootdir cluster +FAT_START dd 0 ; start of fat table +ROOT_START dd 0 ; start of rootdir (only fat16) +ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) +DATA_START dd 0 ; start of data area (=first cluster 2) +LAST_CLUSTER dd 0 ; last availabe cluster +ADR_FSINFO dd 0 ; used only by fat32 + +fatRESERVED dd 0x0FFFFFF6 +fatBAD dd 0x0FFFFFF7 +fatEND dd 0x0FFFFFF8 +fatMASK dd 0x0FFFFFFF + +fat_type db 0 ; 0=none, 16=fat16, 32=fat32 +;*************************************************************************** +; End place +; Mario79 +;*************************************************************************** +cluster dd 0 ; used by file_write,makedir,append +partition_count dd 0 ; partitions found by set_FAT32_variables +longname_sec1 dd 0 ; used by analyze_directory to save 2 previous +longname_sec2 dd 0 ; directory sectors for delete long filename + +hd_error dd 0 ; set by wait_for_sector_buffer +hd_setup dd 0 +hd_wait_timeout dd 0 + +cluster_tmp dd 0 ; used by analyze_directory + ; and analyze_directory_to_write + +file_size dd 0 ; used by file_read + +sector_tmp dd 0 ; used by rename,append,file_write +entry_pos dd 0 ; used by rename,append,file_write + +old_filesize dd 0 ; used by append +new_filepos dd 0 ; used by append +bytes2write dd 0 ; used by append + +cache_search_start dd 0 ; used by find_empty_slot + +fat_in_cache dd -1 +fat_cache: times 512 db 0 + +uglobal + Sector512: ; label for dev_hdcd.inc + buffer: times 512 db 0 + deltree_buffer: times 512 db 0 +endg + +iglobal + NewDirEntry1 db ". ",0x10 + times 20 db 0 + NewDirEntry2 db ".. ",0x10 + times 20 db 0 +endg + +uglobal + dir_entry: times 32 db 0 + + startpath: times 255 db 0 + + fat16_root db 0 ; flag for fat16 rootdir + f_del db 0 ; 1=overwrite fat entry + fat_change db 0 ; 1=fat has changed + +endg + +iglobal + partition_types: ; list of fat16/32 partitions + db 0x04 ; DOS: fat16 <32M + db 0x06 ; DOS: fat16 >32M + db 0x0b ; WIN95: fat32 + db 0x0c ; WIN95: fat32, LBA-mapped + db 0x0e ; WIN95: fat16, LBA-mapped + db 0x14 ; Hidden DOS: fat16 <32M + db 0x16 ; Hidden DOS: fat16 >32M + db 0x1b ; Hidden WIN95: fat32 + db 0x1c ; Hidden WIN95: fat32, LBA-mapped + db 0x1e ; Hidden WIN95: fat16, LBA-mapped + db 0xc4 ; DRDOS/secured: fat16 <32M + db 0xc6 ; DRDOS/secured: fat16 >32M + db 0xcb ; DRDOS/secured: fat32 + db 0xcc ; DRDOS/secured: fat32, LBA-mapped + db 0xce ; DRDOS/secured: fat16, LBA-mapped + db 0xd4 ; Old Multiuser DOS secured: fat16 <32M + db 0xd6 ; Old Multiuser DOS secured: fat16 >32M + partition_types_end: + + + extended_types: ; list of extended partitions + db 0x05 ; DOS: extended partition + db 0x0f ; WIN95: extended partition, LBA-mapped + db 0xc5 ; DRDOS/secured: extended partition + db 0xd5 ; Old Multiuser DOS secured: extended partition + extended_types_end: + +endg + + +reserve_hd1: + + cli + cmp [hd1_status],0 + je reserve_ok1 + + sti + call change_task + jmp reserve_hd1 + + reserve_ok1: + + push eax + mov eax,[0x3000] + shl eax,5 + mov eax,[eax+0x3000+4] + mov [hd1_status],eax + pop eax + sti + ret + + +clear_hd_cache: + + push eax ecx edi + mov edi,0x600000 + mov ecx,16384 + xor eax,eax + cld + rep stosd ; clear hd cache with 0 + mov [cache_search_start],eax + mov [fat_in_cache],-1 + mov [fat_change],0 + pop edi ecx eax + ret + +problem_partition db 0 ; used for partitions search + +; Partition chain used: +; MBR ; PARTITION2 ; PARTITION3 ; PARTITION4 +;========================================================== +; fat16/32 +-- fat16/32 +-- fat16/32 +-- fat16/32 +-- +; extended --+ extended --+ extended --+ extended --+ +; 0 0 0 0 +; 0 0 0 0 +; Notes: +; - extended partition need to be in second entry on table +; - it will skip over removed partitions + +set_FAT32_variables: + mov [0xfe10],dword 0 ; entries in hd cache + mov [problem_partition],0 + call reserve_hd1 + call clear_hd_cache + + cmp dword [hdpos],0 + je problem_hd + + pushad + xor ecx,ecx ; partition count + mov edx,-1 ; flag for partition + xor eax,eax ; read MBR + xor ebp,ebp ; extended partition start + +new_partition: + test ebp,ebp ; is there extended partition? + jnz extended_already_set ; yes + xchg ebp,eax ; no. set it now + +extended_already_set: + add eax,ebp ; mbr=mbr+0, ext_part=ext_start+relat_start + mov ebx,buffer + call hd_read + + cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? + jnz end_partition_chain + cmp dword [ebx+0x1be+0xc],0 ; skip over empty partition + jz next_partition + + push eax ecx + mov edi,partition_types + mov ecx,partition_types_end-partition_types + mov al,[ebx+0x1be+4] ; get partition type + cld + repne scasb ; is partition type ok? + pop ecx eax + jnz next_partition ; no. skip over + + inc ecx + cmp ecx,[fat32part] ; is it wanted partition? + jnz next_partition ; no + + mov edx,eax ; start sector + add edx,[ebx+0x1be+8] ; add relative start + +next_partition: + push ecx + mov edi,extended_types + mov ecx,extended_types_end-extended_types + mov al,[ebx+0x1be+4+16] ; get second partition type + cld + repne scasb ; is it extended partition? + pop ecx + jnz end_partition_chain ; no. end chain + + mov eax,[ebx+0x1be+8+16] ; get start of extended partition + test eax,eax ; is there extended partition? + jnz new_partition ; yes. read it + +end_partition_chain: + mov [partition_count],ecx + + cmp edx,-1 ; found wanted partition? + jnz hd_and_partition_ok ; yes. install it + jmp problem_partition_or_fat + +problem_fat_dec_count: ; bootsector is missing or another problem + dec [partition_count] ; remove it from partition_count + +problem_partition_or_fat: + popad + +problem_hd: + mov [fat_type],0 + mov [hd1_status],0 ; free + mov [problem_partition],1 + ret + +hd_and_partition_ok: + mov eax,edx + mov [PARTITION_START],eax + + mov [hd_setup],1 + mov ebx,buffer + call hd_read ; read boot sector of partition + mov [hd_setup],0 + + cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? + jnz problem_fat_dec_count + + movzx eax,word [ebx+0xe] ; sectors reserved + add eax,[PARTITION_START] + mov [FAT_START],eax ; fat_start = partition_start + reserved + + movzx eax,byte [ebx+0xd] ; sectors per cluster + mov [SECTORS_PER_CLUSTER],eax + + movzx ecx,word [ebx+0xb] ; bytes per sector + mov [BYTES_PER_SECTOR],ecx + + movzx eax,word [ebx+0x11] ; count of rootdir entries (=0 fat32) + mov edx,32 + mul edx + dec ecx + add eax,ecx ; round up if not equal count + inc ecx ; bytes per sector + div ecx + mov [ROOT_SECTORS],eax ; count of rootdir sectors + + movzx eax,word [ebx+0x16] ; sectors per fat <65536 + test eax,eax + jnz fat16_fatsize + mov eax,[ebx+0x24] ; sectors per fat + fat16_fatsize: + mov [SECTORS_PER_FAT],eax + + movzx eax,byte [ebx+0x10] ; number of fats + test eax,eax ; if 0 it's not fat partition + jz problem_fat_dec_count + mov [NUMBER_OF_FATS],eax + imul eax,[SECTORS_PER_FAT] + add eax,[FAT_START] + mov [ROOT_START],eax ; rootdir = fat_start + fat_size * fat_count + add eax,[ROOT_SECTORS] ; rootdir sectors should be 0 on fat32 + mov [DATA_START],eax ; data area = rootdir + rootdir_size + + movzx eax,word [ebx+0x13] ; total sector count <65536 + test eax,eax + jnz fat16_total + mov eax,[ebx+0x20] ; total sector count + fat16_total: + add eax,[PARTITION_START] + dec eax + mov [PARTITION_END],eax + inc eax + sub eax,[DATA_START] ; eax = count of data sectors + xor edx,edx + div dword [SECTORS_PER_CLUSTER] + inc eax + mov [LAST_CLUSTER],eax + dec eax ; cluster count + + ; limits by Microsoft Hardware White Paper v1.03 + cmp eax,4085 ; 0xff5 + jb problem_fat_dec_count ; fat12 not supported + cmp eax,65525 ; 0xfff5 + jb fat16_partition + +fat32_partition: + mov eax,[ebx+0x2c] ; rootdir cluster + mov [ROOT_CLUSTER],eax + movzx eax,word [ebx+0x30] ; fs info sector + add eax,[PARTITION_START] + mov [ADR_FSINFO],eax + + popad + + mov [fatRESERVED],0x0FFFFFF6 + mov [fatBAD],0x0FFFFFF7 + mov [fatEND],0x0FFFFFF8 + mov [fatMASK],0x0FFFFFFF + mov [fat_type],32 ; Fat32 + mov [hd1_status],0 ; free + ret + +fat16_partition: + xor eax,eax + mov [ROOT_CLUSTER],eax + + popad + + mov [fatRESERVED],0x0000FFF6 + mov [fatBAD],0x0000FFF7 + mov [fatEND],0x0000FFF8 + mov [fatMASK],0x0000FFFF + mov [fat_type],16 ; Fat16 + mov [hd1_status],0 ; free + ret + + +set_FAT: +;-------------------------------- +; input : EAX = cluster +; EDX = value to save +; output : EDX = old value +;-------------------------------- + push eax ebx esi + + cmp eax,2 + jb sfc_error + cmp eax,[LAST_CLUSTER] + ja sfc_error + cmp [fat_type],16 + je sfc_1 + add eax,eax + sfc_1: + add eax,eax + mov esi,511 + and esi,eax ; esi = position in fat sector + shr eax,9 ; eax = fat sector + add eax,[FAT_START] + mov ebx,fat_cache + + cmp eax,[fat_in_cache] ; is fat sector already in memory? + je sfc_in_cache ; yes + + cmp [fat_change],0 ; is fat changed? + je sfc_no_change ; no + call write_fat_sector ; yes. write it into disk + + sfc_no_change: + mov [fat_in_cache],eax ; save fat sector + call hd_read + + sfc_in_cache: + cmp [fat_type],16 + jne sfc_test32 + + cmp [f_del],1 ; overwrite previous value? + je sfc_set16 ; yes + cmp word [ebx+esi],0 ; is cluster free? + je sfc_set16 ; yes + mov dword [8*0x100000],0xffffff + mov edx,[ebx+esi] ; get old value + jmp sfc_nonzero + + sfc_set16: + xchg [ebx+esi],dx ; save new value and get old value + jmp sfc_write + + sfc_test32: + mov eax,[fatMASK] + cmp [f_del],1 ; overwrite previous value? + je sfc_set32 ; yes + test eax,[ebx+esi] ; is cluster free? + je sfc_set32 ; yes + mov dword [8*0x100000],0xffffff + mov edx,[ebx+esi] ; get old value + jmp sfc_nonzero + + sfc_set32: + and edx,eax + xor eax,-1 ; mask for high bits + and eax,[ebx+esi] ; get high 4 bits + or eax,edx + mov edx,[ebx+esi] ; get old value + mov [ebx+esi],eax ; save new value + + sfc_write: + mov [fat_change],1 ; fat has changed + + sfc_nonzero: + and edx,[fatMASK] + + sfc_error: + pop esi ebx eax + ret + + +get_FAT: +;-------------------------------- +; input : EAX = cluster +; output : EAX = next cluster +;-------------------------------- + push ebx esi + + cmp [fat_type],16 + je gfc_1 + add eax,eax + gfc_1: + add eax,eax + mov esi,511 + and esi,eax ; esi = position in fat sector + shr eax,9 ; eax = fat sector + add eax,[FAT_START] + mov ebx,fat_cache + + cmp eax,[fat_in_cache] ; is fat sector already in memory? + je gfc_in_cache + + cmp [fat_change],0 ; is fat changed? + je gfc_no_change ; no + call write_fat_sector ; yes. write it into disk + + gfc_no_change: + mov [fat_in_cache],eax + call hd_read + + gfc_in_cache: + mov eax,[ebx+esi] + and eax,[fatMASK] + pop esi ebx + ret + + +get_free_FAT: +;----------------------------------------------------------- +; input : EAX = # cluster for start the searching +; output : if CARRY=0 EAX = # first cluster found free +; if CARRY=1 disk full +; Note : for more speed need to use fat_cache directly +;----------------------------------------------------------- + push ecx + mov ecx,[LAST_CLUSTER] ; counter for full disk + sub ecx,2 + + gff_test: + cmp eax,[LAST_CLUSTER] ; if above last cluster start at cluster 2 + jbe gff_in_range + mov eax,2 + + gff_in_range: + push eax + call get_FAT ; get cluster state + test eax,eax ; is it free? + pop eax + je gff_found ; yes + inc eax ; next cluster + dec ecx ; is all checked? + jns gff_test ; no + + gff_not_found: + pop ecx ; yes. disk is full + stc + ret + + gff_found: + pop ecx + clc + ret + + +write_fat_sector: +;----------------------------------------------------------- +; write changed fat to disk +;----------------------------------------------------------- + push eax ebx ecx + + mov [fat_change],0 + mov eax,[fat_in_cache] + cmp eax,-1 + jz write_fat_not_used + mov ebx,fat_cache + mov ecx,[NUMBER_OF_FATS] + + write_next_fat: + call hd_write + add eax,[SECTORS_PER_FAT] + dec ecx + jnz write_next_fat + + write_fat_not_used: + pop ecx ebx eax + ret + + +analyze_directory: +;----------------------------------------------------------- +; input : EAX = first cluster of the directory +; EBX = pointer to filename +; output : IF CARRY=0 EAX = sector where th file is found +; EBX = pointer in buffer +; [buffer .. buffer+511] +; ECX,EDX,ESI,EDI not changed +; IF CARRY=1 filename not found +; Note : if cluster=0 it's changed to read rootdir +; save 2 previous directory sectors in longname_sec +;----------------------------------------------------------- + push ecx edx esi edi ebx ; ebx = [esp+0] + mov [longname_sec1],0 + mov [longname_sec2],0 + + adr_new_cluster: + mov [cluster_tmp],eax + mov [fat16_root],0 + cmp eax,[LAST_CLUSTER] + ja adr_not_found ; too big cluster number, something is wrong + cmp eax,2 + jnb adr_data_cluster + + mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir + cmp [fat_type],16 + jne adr_data_cluster + mov eax,[ROOT_START] + mov edx,[ROOT_SECTORS] + mov [fat16_root],1 ; flag for fat16 rootdir + jmp adr_new_sector + + adr_data_cluster: + sub eax,2 + mov edx,[SECTORS_PER_CLUSTER] + imul eax,edx + add eax,[DATA_START] + + adr_new_sector: + mov ebx,buffer + call hd_read + mov ecx,512/32 ; count of dir entrys per sector = 16 + + adr_analyze: + mov edi,[ebx+11] ; file attribute + and edi,0xf + cmp edi,0xf + je adr_long_filename + test edi,0x8 ; skip over volume label + jne adr_long_filename ; Note: label can be same name as file/dir + + mov esi,[esp+0] ; filename need to be uppercase + mov edi,ebx + push ecx + mov ecx,11 + cld + rep cmpsb ; compare 8+3 filename + pop ecx + je adr_found + + adr_long_filename: + add ebx,32 ; position of next dir entry + dec ecx + jnz adr_analyze + + mov ecx,[longname_sec1] ; save 2 previous directory sectors + mov [longname_sec1],eax ; for delete long filename + mov [longname_sec2],ecx + inc eax ; next sector + dec edx + jne adr_new_sector + cmp [fat16_root],1 ; end of fat16 rootdir + je adr_not_found + + adr_next_cluster: + mov eax,[cluster_tmp] + call get_FAT ; get next cluster + cmp eax,2 ; incorrect fat chain? + jb adr_not_found ; yes + cmp eax,[fatRESERVED] ; is it end of directory? + jb adr_new_cluster ; no. analyse it + + adr_not_found: + pop edi edi esi edx ecx ; first edi will remove ebx + stc ; file not found + ret + + adr_found: + pop edi edi esi edx ecx ; first edi will remove ebx + clc ; file found + ret + + +analyze_directory_to_write: +;----------------------------------------------------------- +; input : EAX = first cluster of the directory +; output : IF CARRY=0 EAX = sector where the empty pos is found +; EBX = pointer in buffer +; [buffer .. buffer+511] +; ECX,EDX,ESI,EDI not changed +; IF CARRY=1 disk full or fat corrupted +; Note : if cluster=0 it's changed to read rootdir +;----------------------------------------------------------- + push ecx edx edi + + adw_new_cluster: + mov [cluster_tmp],eax + mov [fat16_root],0 + cmp eax,[LAST_CLUSTER] + ja adw_not_found ; too big cluster number, something is wrong + cmp eax,2 + jnb adw_data_cluster + + mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir + cmp [fat_type],16 + jne adw_data_cluster + mov eax,[ROOT_START] + mov edx,[ROOT_SECTORS] + mov [fat16_root],1 ; flag for fat16 rootdir + jmp adw_new_sector + + adw_data_cluster: + sub eax,2 + mov edx,[SECTORS_PER_CLUSTER] + imul eax,edx + add eax,[DATA_START] + + adw_new_sector: + mov ebx,buffer + call hd_read + mov ecx,512/32 ; count of dir entrys per sector = 16 + + adw_analyze: + cmp byte [ebx],0x00 ; is free entry? + je adw_found ; yes + cmp byte [ebx],0xe5 ; is deleted entry? + je adw_found ; yes + add ebx,32 ; position of next dir entry + dec ecx + jnz adw_analyze + + inc eax ; next sector + dec edx + jne adw_new_sector + cmp [fat16_root],1 ; end of fat16 rootdir + je adw_not_found + + mov eax,[cluster_tmp] + call get_FAT ; get next cluster + cmp eax,2 ; incorrect fat chain? + jb adw_not_found ; yes + cmp eax,[fatRESERVED] ; is it end of directory? + jb adw_new_cluster ; no. analyse it + + mov eax,2 ; this block of code add a new cluster + call get_free_FAT ; for the directory because the directory + jc adw_not_found ; is full + + mov edx,[fatEND] ; new end for directory + call set_FAT + + push eax ; save new cluster + mov edx,eax + mov eax,[cluster_tmp] ; change last cluster to point new cluster + mov [f_del],1 + call set_FAT + mov [f_del],0 + + mov ecx,-1 ; remove 1 cluster from free disk space + call add_disk_free_space + + mov ecx,512/4 + xor eax,eax + mov edi,buffer + cld + rep stosd ; clear new directory cluster + pop eax + + sub eax,2 + mov ecx,[SECTORS_PER_CLUSTER] + imul eax,ecx + add eax,[DATA_START] + mov ebx,buffer + push eax ; save sector number + + adw_set_empty_directory: + call hd_write + inc eax ; next sector + dec ecx + jnz adw_set_empty_directory + + pop eax + + adw_found: + pop edi edx ecx + clc ; free space found + ret + + adw_not_found: + pop edi edx ecx + stc ; free space not found + ret + + +get_data_cluster: +;----------------------------------------------------------- +; input : EAX = cluster +; EBX = pointer to buffer +; EDX = # blocks to read in buffer +; ESI = # blocks to skip over +; output : if CARRY=0 ok EBX/EDX/ESI updated +; if CARRY=1 cluster out of range +; Note : if cluster=0 it's changed to read rootdir +;----------------------------------------------------------- + push eax ecx + + mov [fat16_root],0 + cmp eax,[LAST_CLUSTER] + ja gdc_error ; too big cluster number, something is wrong + cmp eax,2 + jnb gdc_cluster + + mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir + cmp [fat_type],16 + jne gdc_cluster + mov eax,[ROOT_START] + mov ecx,[ROOT_SECTORS] ; Note: not cluster size + mov [fat16_root],1 ; flag for fat16 rootdir + jmp gdc_read + + gdc_cluster: + sub eax,2 + mov ecx,[SECTORS_PER_CLUSTER] + imul eax,ecx + add eax,[DATA_START] + + gdc_read: + test esi,esi ; first wanted block + je gdcl1 ; yes, skip count is 0 + dec esi + jmp gdcl2 + + gdcl1: + call hd_read + add ebx,512 ; update pointer + dec edx + + gdcl2: + test edx,edx ; is all read? + je out_of_read + + inc eax ; next sector + dec ecx + jnz gdc_read + + out_of_read: + pop ecx eax + clc + ret + + gdc_error: + pop ecx eax + stc + ret + + +set_data_cluster: +;----------------------------------------------------------- +; input : EAX = cluster +; EBX = pointer to buffer +; output : if CARRY=0 ok +; if CARRY=1 cluster out of range +;----------------------------------------------------------- + push eax ebx edx + + cmp eax,[LAST_CLUSTER] + ja sdc_error ; too big cluster number, something is wrong + sub eax,2 + jb sdc_error ; don't allow rootdir write + + mov edx,[SECTORS_PER_CLUSTER] + imul eax,edx + add eax,[DATA_START] + + sdc_write: + call hd_write + add ebx,512 ; update pointer + inc eax + dec edx + jnz sdc_write + pop edx ebx eax + clc + ret + + sdc_error: + pop edx ebx eax + stc + ret + + +get_cluster_of_a_path: +;--------------------------------------------------------- +; input : EBX = pointer to a path string +; (example: the path "/files/data/document" become +; "files......data.......document...0" +; '.' = space char +; '0' = char(0) (ASCII=0) !!! ) +; output : if (CARRY=1) -> ERROR in the PATH +; if (CARRY=0) -> EAX=cluster +;--------------------------------------------------------- + push ebx edx + + mov eax,[ROOT_CLUSTER] + mov edx,ebx + +search_end_of_path: + cmp byte [edx],0 + je found_end_of_path + + inc edx ; '/' + mov ebx,edx + call analyze_directory + jc directory_not_found + + mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field + mov ax,[ebx+26] ; read the LOW 16bit cluster field + and eax,[fatMASK] + add edx,11 ; 8+3 (name+extension) + jmp search_end_of_path + +found_end_of_path: + pop edx ebx + clc ; no errors + ret + +directory_not_found: + pop edx ebx + stc ; errors occour + ret + + +bcd2bin: +;---------------------------------- +; input : AL=BCD number (eg. 0x11) +; output : AH=0 +; AL=decimal number (eg. 11) +;---------------------------------- + xor ah,ah + shl ax,4 + shr al,4 + aad + ret + + +get_date_for_file: +;----------------------------------------------------- +; Get date from CMOS and pack day,month,year in AX +; DATE bits 0..4 : day of month 0..31 +; 5..8 : month of year 1..12 +; 9..15 : count of years from 1980 +;----------------------------------------------------- + mov al,0x7 ;day + out 0x70,al + in al,0x71 + call bcd2bin + ror eax,5 + + mov al,0x8 ;month + out 0x70,al + in al,0x71 + call bcd2bin + ror eax,4 + + mov al,0x9 ;year + out 0x70,al + in al,0x71 + call bcd2bin + add ax,20 ;because CMOS return only the two last + ;digit (eg. 2000 -> 00 , 2001 -> 01) and we + rol eax,9 ;need the difference with 1980 (eg. 2001-1980) + ret + + +get_time_for_file: +;----------------------------------------------------- +; Get time from CMOS and pack hour,minute,second in AX +; TIME bits 0..4 : second (the low bit is lost) +; 5..10 : minute 0..59 +; 11..15 : hour 0..23 +;----------------------------------------------------- + mov al,0x0 ;second + out 0x70,al + in al,0x71 + call bcd2bin + ror eax,6 + + mov al,0x2 ;minute + out 0x70,al + in al,0x71 + call bcd2bin + ror eax,6 + + mov al,0x4 ;hour + out 0x70,al + in al,0x71 + call bcd2bin + rol eax,11 + ret + + +set_current_time_for_entry: +;----------------------------------------------------- +; Set current time/date for file entry +; input : ebx = file entry pointer +;----------------------------------------------------- + push eax + call get_time_for_file ; update files date/time + mov [ebx+22],ax + call get_date_for_file + mov [ebx+24],ax + pop eax + ret + + +makedir: +;----------------------------------------------------- +; input : eax = directory name +; edx = path +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 8 - disk full +; 10 - access denied +; Note : can only make one directory at time +;----------------------------------------------------- + cmp [fat_type],0 + jnz make_dir_fat_ok + mov eax,ERROR_UNKNOWN_FS + ret + + make_dir_fat_ok: +; call reserve_hd1 + + pushad + + mov ebx,edx + call get_cluster_of_a_path + jnc make_dir_found_path + + make_dir_path_not_found: + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + mov eax,ERROR_FILE_NOT_FOUND + ret + + make_dir_disk_full: + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + mov eax,ERROR_DISK_FULL + ret + + make_dir_already_exist: + mov eax,[cluster] ; directory cluster + xor edx,edx ; free + mov [f_del],1 + call set_FAT + mov [f_del],0 + + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + mov eax,ERROR_ACCESS_DENIED + ret + + make_dir_found_path: + cmp eax,[ROOT_CLUSTER] + jnz make_dir_not_root + xor eax,eax + + make_dir_not_root: + mov ecx,eax ; directorys start cluster + mov word [NewDirEntry2+26],cx ; 16 bits low of cluster + shr ecx,16 + mov word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16) + + push eax ; save parent directory cluster + mov eax,2 + call get_free_FAT + mov [cluster],eax ; first free cluster + pop eax + jc make_dir_disk_full + + push eax + mov eax,[cluster] ; directory cluster + mov edx,[fatEND] ; end for directory + call set_FAT + pop eax + + mov ebx,PUSHAD_EAX ; dir name + push eax + call analyze_directory ; check if directory already exist + pop eax + jnc make_dir_already_exist ; need to free allocated cluster! + + call analyze_directory_to_write + jc make_dir_already_exist ; need to free allocated cluster! + + mov esi,PUSHAD_EAX ; dir name + mov edi,ebx ; pointer in buffer + mov ecx,11 + cld + rep movsb + + mov dword [ebx+28],0 ; dir size is always 0 + mov ecx,[cluster] + mov [ebx+26],cx ; 16 bits low of cluster + mov word [NewDirEntry1+26],cx + shr ecx,16 + mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) + mov word [NewDirEntry1+20],cx + mov byte [ebx+11],0x10 ; attribute = directory + + call set_current_time_for_entry + mov ecx,[ebx+22] + mov dword [NewDirEntry1+22],ecx + mov dword [NewDirEntry2+22],ecx + + mov ebx,buffer ; save the directory name,length,cluster + call hd_write + + mov ecx,512/4 + xor eax,eax + mov edi,buffer + cld + rep stosd ; clear new directory cluster + + mov eax,[cluster] ; new directory cluster + sub eax,2 + mov edx,[SECTORS_PER_CLUSTER] + imul eax,edx + add eax,[DATA_START] + mov ebx,buffer + add eax,edx ; start from last sector + + dir_set_empty_directory: + dec eax ; next sector + cmp edx,1 ; is first directory sector? + jnz not_first_sector ; no. write empty sector + mov esi,NewDirEntry1 + mov edi,buffer + mov ecx,64/4 + cld + rep movsd ; copy 2 first directory entrys "." and ".." + + not_first_sector: + call hd_write + dec edx + jnz dir_set_empty_directory + + mov ecx,-1 ; remove 1 cluster from free disk space + call add_disk_free_space + + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + xor eax,eax + ret + + +removedir: +;----------------------------------------------------- +; input : eax = file/directory name +; edx = path +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 10 - access denied +;----------------------------------------------------- + cmp [fat_type],0 + jnz remove_dir_fat_ok + mov eax,ERROR_UNKNOWN_FS + ret + + remove_dir_fat_ok: +; call reserve_hd1 + + push edi + mov edi,1 ; allow directory remove + call file_delete + pop edi + + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + ret + + +add_disk_free_space: +;----------------------------------------------------- +; input : ecx = cluster count +; Note : negative = remove clusters from free space +; positive = add clusters to free space +;----------------------------------------------------- + test ecx,ecx ; no change + je add_dfs_no + cmp [fat_type],32 ; free disk space only used by fat32 + jne add_dfs_no + + push eax ebx + mov eax,[ADR_FSINFO] + mov ebx,buffer + call hd_read + cmp dword [ebx+0x1fc],0xaa550000 ; check sector id + jne add_not_fs + + add [ebx+0x1e8],ecx + call hd_write + + add_not_fs: + pop ebx eax + + add_dfs_no: + ret + + +file_append: +;----------------------------------------------------- +; input : eax = file name +; edx = path +; ecx = pointer to buffer +; ebx = bytes to write (0 = truncate file) +; esi = start position (-1 = end of file) +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 6 - end of file +; 8 - disk full +; 9 - fat table corrupted +; 10 - access denied +; ebx = bytes written +;----------------------------------------------------- + cmp [fat_type],0 + jnz append_fat_ok + mov eax,ERROR_UNKNOWN_FS + ret + + append_fat_ok: +; call reserve_hd1 + + pushad + + mov ebx,edx + call get_cluster_of_a_path + jc append_not_found + + mov ebx,PUSHAD_EAX ; file name + call analyze_directory + jc append_not_found + + mov [sector_tmp],eax + mov [entry_pos],ebx + + test byte [ebx+11],0x10 ; is it directory? + jnz append_access ; yes + + mov ecx,[ebx+28] ; file size + mov edi,PUSHAD_ESI ; write position + cmp edi,-1 ; -1 = eof + jnz append_inside_file + mov edi,ecx ; file size + + append_inside_file: + cmp edi,ecx ; start above old file size? + ja append_eof ; yes + + mov [old_filesize],ecx + mov [new_filepos],edi + + mov ecx,PUSHAD_EBX ; bytes to write + test ecx,ecx ; truncate? + jz append_truncate ; yes + + mov [bytes2write],ecx ; bytes to write + mov esi,PUSHAD_ECX ; pointer to buffer + mov eax,[ebx+20-2] ; FAT entry + mov ax,[ebx+26] + and eax,[fatMASK] + jnz append_find_pos ; first cluster <> 0 + + mov eax,2 + call get_free_FAT + jc append_disk_full + mov ecx,eax ; set files first cluster + mov [ebx+26],cx ; 16 bits low of cluster + shr ecx,16 + mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) + mov edx,[fatEND] ; new end for cluster chain + call set_FAT + + push eax ; save first cluster + mov eax,[sector_tmp] + mov ebx,buffer + call hd_write ; write new file entry back to disk + pop eax + + append_remove_free: + mov ecx,-1 ; remove 1 cluster from free disk space + call add_disk_free_space ; Note: uses buffer + + append_found_cluster: + mov [cluster],eax + sub eax,2 + mov ecx,[SECTORS_PER_CLUSTER] + imul eax,ecx + add eax,[DATA_START] + xor edi,edi + + append_new_sector: + push ecx + mov ecx,[bytes2write] ; bytes left in buffer + mov ebx,512 + sub ebx,edi ; bytes left in sector + cmp ecx,ebx + jb append_bytes_ok + mov ecx,ebx + + append_bytes_ok: + cmp ecx,512 ; overwrite full sector? + jz append_full_sector ; yes + mov ebx,buffer ; overwrite part of sector + call hd_read ; read old sector + + append_full_sector: + sub [bytes2write],ecx + add [new_filepos],ecx + add edi,buffer + cld + rep movsb + pop ecx + + mov ebx,buffer + call hd_write + cmp [bytes2write],0 ; is all done? + jz append_done + xor edi,edi + inc eax + dec ecx + jnz append_new_sector + + mov eax,[cluster] + call get_FAT + cmp eax,2 + jb append_fat + cmp eax,[LAST_CLUSTER] + jbe append_found_cluster + + append_alloc_cluster: + mov eax,2 ; ToDo: use temp array to keep track + call get_free_FAT ; of last free cluster + jc append_disk_full + push eax ; save new cluster + mov edx,[fatEND] ; new end for cluster chain + call set_FAT + mov edx,eax + mov eax,[cluster] + mov [f_del],1 + call set_FAT ; update previous cluster + mov [f_del],0 + pop eax + jmp append_remove_free + + append_find_pos: + call find_filepos + mov [cluster],ebx + jnc append_new_sector + test edi,edi + jz append_alloc_cluster + + append_fat: + mov eax,ERROR_FAT_TABLE + jmp append_ret_code + + append_disk_full: + mov eax,ERROR_DISK_FULL + jmp append_ret_code + + append_done: + xor eax,eax + + append_ret_code: + mov PUSHAD_EAX,eax ; return code + + mov eax,[sector_tmp] ; update directory entry + mov ebx,buffer + call hd_read + mov ebx,[entry_pos] + mov ecx,[new_filepos] + cmp ecx,[old_filesize] ; is file pos above old size? + jbe append_size_ok ; no + mov [ebx+28],ecx ; new file size + + append_size_ok: + call set_current_time_for_entry + mov ebx,buffer + call hd_write ; write new file entry back to disk + + sub ecx,PUSHAD_ESI ; start position + mov PUSHAD_EBX,ecx ; bytes written + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + ret + + append_eof: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_END_OF_FILE + ret + + append_not_found: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_FILE_NOT_FOUND + ret + + append_access: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_ACCESS_DENIED + ret + + append_truncate: + mov edx,[ebx+20-2] ; FAT entry + mov dx,[ebx+26] + and edx,[fatMASK] + mov [ebx+28],edi ; set new file size + test edi,edi ; 0 length file? + jnz truncate_save_size ; no + mov [ebx+20],di ; FAT entry = 0 + mov [ebx+26],di + + truncate_save_size: + call set_current_time_for_entry + mov ebx,buffer + call hd_write + mov eax,edx ; first cluster + test edi,edi ; 0 length file? + jz truncate_clear_chain + + imul esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes + + truncate_new_cluster: + cmp eax,2 ; incorrect fat chain? + jb truncate_eof ; yes + cmp eax,[fatRESERVED] ; is it end of file? + jnb truncate_eof ; yes + sub edi,esi + jbe truncate_pos_found + call get_FAT ; get next cluster + jmp truncate_new_cluster + + truncate_pos_found: + mov edx,[fatEND] ; new end for cluster chain + mov [f_del],1 + call set_FAT + mov [f_del],0 + mov eax,edx ; clear rest of chain + + truncate_clear_chain: + call clear_cluster_chain + + truncate_eof: + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + xor ebx,ebx + xor eax,eax + ret + + +find_filepos: +;----------------------------------------------------- +; input : eax = first cluster +; edi = bytes to skip over (start position) +; output : if CARRY=0 file position found +; if CARRY=1 end of file found +; eax = current file sector +; ebx = last cluster +; ecx = sector count in last cluster +; edi = bytes to skip over (sector position) +;----------------------------------------------------- + push esi + mov ecx,[SECTORS_PER_CLUSTER] + imul esi,ecx,512 ; esi = cluster size in bytes + mov ebx,eax + + filepos_new_cluster: + cmp eax,2 ; incorrect fat chain? + jb filepos_eof ; yes + cmp eax,[fatRESERVED] ; is it end of file? + jnb filepos_eof ; yes + + mov ebx,eax + cmp edi,esi ; skip over full cluster? + jb filepos_cluster_ok ; no + + sub edi,esi + call get_FAT ; get next cluster + jmp filepos_new_cluster + + filepos_cluster_ok: + sub eax,2 + imul eax,ecx + add eax,[DATA_START] + + filepos_new_sector: + cmp edi,512 ; skip over full sector? + jb filepos_sector_ok ; no + sub edi,512 + inc eax + dec ecx + jnz filepos_new_sector + + filepos_eof: + pop esi + stc + ret + + filepos_sector_ok: + pop esi + clc + ret + + +file_write: +;-------------------------------------------------------------------------- +; INPUT : user-reg register-in-this meaning symbol-in-this-routine +; +; EAX EDI system call to write / +; EBX EAX (PAR0) pointer to file-name PAR0 +; EDX ECX (PAR1) pointer to buffer PAR1 +; ECX EBX (PAR2) file size PAR2 +; ESI EDX (PAR3) pointer to path PAR3 +; +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 8 - disk full +; 10 - access denied +;-------------------------------------------------------------------------- + cmp [fat_type],0 + jnz fat_ok_for_writing + mov eax,ERROR_UNKNOWN_FS + ret + + fat_ok_for_writing: +; call reserve_hd1 + + pushad + + xor edi,edi ; don't allow directory remove + call file_delete ; try to delete the file first + test eax,eax + jz old_deleted ; deleted ok + cmp eax,ERROR_FILE_NOT_FOUND + jnz exit_write_access ; it exist but can't delete + + old_deleted: + mov ebx,PUSHAD_EDX + call get_cluster_of_a_path + jnc found_directory_for_writing + + exit_writing_with_error: + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + mov eax,ERROR_FILE_NOT_FOUND + ret + + exit_writing_disk_full_clear: + mov eax,[sector_tmp] + mov ebx,buffer + call hd_read ; read directory sector + mov edx,[entry_pos] + mov byte [edx],0xe5 ; mark as deleted + call hd_write + mov eax,[edx+20-2] ; FAT entry + mov ax,[edx+26] + and eax,[fatMASK] + call clear_cluster_chain + + exit_writing_disk_full: + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + mov eax,ERROR_DISK_FULL + ret + + exit_write_access: + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + mov eax,ERROR_ACCESS_DENIED + ret + +found_directory_for_writing: + call analyze_directory_to_write + jc exit_writing_disk_full + + mov [sector_tmp],eax + mov [entry_pos],ebx + push eax ; save directory sector + mov eax,2 + call get_free_FAT + mov [cluster],eax ; first free cluster + pop eax + jc exit_writing_disk_full + + mov esi,PUSHAD_EAX ; file name + mov edi,ebx ; pointer in buffer + mov ecx,11 + cld + rep movsb + + mov esi,PUSHAD_EBX ; file size (bytes left) + mov [ebx+28],esi ; file size + mov ecx,[cluster] + mov [ebx+26],cx ; 16 bits low of cluster + shr ecx,16 + mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16) + mov byte [ebx+11],0x20 ; attribute = archive + + call set_current_time_for_entry + + mov ebx,buffer ; save the directory name,length,cluster + call hd_write + + imul edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes + xor ecx,ecx ; cluster count + mov ebx,PUSHAD_ECX ; ebx = buffer + +hd_new_block_write: + + mov eax,[cluster] ; eax = block + call set_data_cluster + + sub esi,edi ; sub wrote bytes + jbe file_saved_OK ; end if all done + add ebx,edi ; update buffer position + + inc eax + call get_free_FAT ; next free in FAT + jc exit_writing_disk_full_clear + + mov edx,eax + xchg eax,[cluster] ; get old cluster and save new cluster + call set_FAT ; add it in cluster chain + dec ecx ; update cluster count + jmp hd_new_block_write + +file_saved_OK: + + mov edx,[fatEND] ; new end for cluster chain + call set_FAT + dec ecx ; update cluster count + + call add_disk_free_space ; remove clusters from free disk space + + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + xor eax,eax + ret + + +file_read: +;-------------------------------------------------------------------------- +; INPUT : user-register register-in-this meaning symbol-in-this +; +; EAX EDI system call to write / +; EBX EAX (PAR0) pointer to file-name PAR0 +; EDX ECX (PAR1) pointer to buffer PAR1 +; ECX EBX (PAR2) vt file blocks to read PAR2 +; ESI EDX (PAR3) pointer to path PAR3 +; EDI ESI vt first 512 block to read +; EDI if 0 - read root +; +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 6 - end of file +; 9 - fat table corrupted +; ebx = size of file/directory +;-------------------------------------------------------------------------- + cmp [fat_type],0 + jnz fat_ok_for_reading + xor ebx,ebx + mov eax,ERROR_UNKNOWN_FS + ret + + fat_ok_for_reading: +; call reserve_hd1 + + pushad + + mov ebx,edx + call get_cluster_of_a_path + jc file_to_read_not_found + + test edi,edi ; read rootdir + jne no_read_root + + xor eax,eax + call get_dir_size ; return rootdir size + mov [file_size],eax + mov eax,[ROOT_CLUSTER] + jmp file_read_start + + no_read_root: + mov ebx,PUSHAD_EAX ; file name + call analyze_directory + jc file_to_read_not_found + + mov eax,[ebx+28] ; file size + test byte [ebx+11],0x10 ; is it directory? + jz read_set_size ; no + + mov eax,[ebx+20-2] ; FAT entry + mov ax,[ebx+26] + and eax,[fatMASK] + call get_dir_size + + read_set_size: + mov [file_size],eax + + mov eax,[ebx+20-2] ; FAT entry + mov ax,[ebx+26] + and eax,[fatMASK] + + file_read_start: + mov ebx,PUSHAD_ECX ; pointer to buffer + mov edx,PUSHAD_EBX ; file blocks to read + mov esi,PUSHAD_ESI ; first 512 block to read + + file_read_new_cluster: + call get_data_cluster + jc file_read_eof ; end of file or cluster out of range + + test edx,edx ; is all read? + je file_read_OK ; yes + + call get_FAT ; get next cluster + cmp eax,[fatRESERVED] ; end of file + jnb file_read_eof + cmp eax,2 ; incorrect fat chain + jnb file_read_new_cluster + + popad + mov [hd1_status],0 + mov ebx,[file_size] + mov eax,ERROR_FAT_TABLE + ret + + file_read_eof: + popad + mov [hd1_status],0 + mov ebx,[file_size] + mov eax,ERROR_END_OF_FILE + ret + + file_read_OK: + popad + mov [hd1_status],0 + mov ebx,[file_size] + xor eax,eax + ret + + file_to_read_not_found: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_FILE_NOT_FOUND + ret + + +get_dir_size: +;----------------------------------------------------- +; input : eax = first cluster (0=rootdir) +; output : eax = directory size in bytes +;----------------------------------------------------- + push edx + xor edx,edx ; count of directory clusters + test eax,eax + jnz dir_size_next + + mov eax,[ROOT_SECTORS] + shl eax,9 ; fat16 rootdir size in bytes + cmp [fat_type],16 + je dir_size_ret + mov eax,[ROOT_CLUSTER] + + dir_size_next: + cmp eax,2 ; incorrect fat chain + jb dir_size_end + cmp eax,[fatRESERVED] ; end of directory + ja dir_size_end + call get_FAT ; get next cluster + inc edx + jmp dir_size_next + + dir_size_end: + imul eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes + imul eax,edx + + dir_size_ret: + pop edx + ret + + +file_delete: +;----------------------------------------------------- +; input : eax = file/directory name +; edx = path +; edi = 1 - allow directory remove else don't remove directory +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 10 - access denied +;----------------------------------------------------- + cmp [fat_type],0 + jnz file_del_fat_ok + mov eax,ERROR_UNKNOWN_FS + ret + + file_del_fat_ok: + pushad + + mov ebx,edx + call get_cluster_of_a_path + jc file_to_delete_not_found + + mov ebx,PUSHAD_EAX ; file/directory name + call analyze_directory + jc file_to_delete_not_found + + test byte [ebx+11],0x10 ; is it directory? + jz delete_notdir ; no. it's file + cmp edi,1 ; allow directory remove + jnz delete_no_access ; no + + push eax ; save directory sector + mov eax,[ebx+20-2] ; first cluster of file + mov ax,[ebx+26] ; 0 length files start cluster = 0 + and eax,[fatMASK] + xor ebp,ebp ; counter for directory deepnes + call clear_directory + pop eax + jc delete_no_access + + push ebx ; save directory pointer in buffer + mov ebx,buffer + call hd_read ; read directory sector + pop ebx + + delete_notdir: + call delete_entry_name + mov eax,ecx ; first cluster of file + call clear_cluster_chain + popad + xor eax,eax + ret + + delete_no_access: + popad + mov eax,ERROR_ACCESS_DENIED + ret + + file_to_delete_not_found: + popad + mov eax,ERROR_FILE_NOT_FOUND + ret + + +clear_cluster_chain: +;----------------------------------------------------- +; input : eax = first cluster +;----------------------------------------------------- + push eax ecx edx + xor ecx,ecx ; cluster count + mov [f_del],1 ; delete on + + clean_new_chain: + cmp eax,[LAST_CLUSTER] ; end of file + ja delete_OK + cmp eax,2 ; unfinished fat chain or zero length file + jb delete_OK + cmp eax,[ROOT_CLUSTER] ; don't remove root cluster + jz delete_OK + + xor edx,edx + call set_FAT ; clear fat entry + inc ecx ; update cluster count + mov eax,edx ; old cluster + jmp clean_new_chain + + delete_OK: + call add_disk_free_space ; add clusters to free disk space + mov [f_del],0 + pop edx ecx eax + ret + + +clear_directory: +;----------------------------------------------------- +; input : eax = directory cluster +; ebp = directory deepnes +; Note : use recursive call +;----------------------------------------------------- + pushad + inc ebp + cmp ebp,64 ; if over 63 directory deep + jnb clear_error ; something must be wrong + + clear_new_cluster: + cmp eax,[LAST_CLUSTER] + ja clear_end + cmp eax,[ROOT_CLUSTER] ; don't remove root cluster + jz clear_end + mov esi,eax ; esi = current directory cluster + sub eax,2 + jb clear_end + mov ecx,[SECTORS_PER_CLUSTER] + imul eax,ecx + add eax,[DATA_START] + + clear_new_sector: + mov edi,eax ; edi = current directory sector + mov ebx,deltree_buffer + call hd_read + mov edx,512/32 ; count of dir entrys per sector = 16 + + clear_analyze: + mov al,[ebx+11] ; file attribute + and al,0xf + cmp al,0xf + je clear_long_filename + + cmp byte [ebx],'.' ; parent or current directory + je clear_next_entry + cmp byte [ebx],0xe5 ; deleted + je clear_next_entry + cmp byte [ebx],0 ; empty + je clear_write_last + ;je clear_next_entry + + mov eax,[ebx+20-2] ; first cluster of entry + mov ax,[ebx+26] + and eax,[fatMASK] + + test byte [ebx+11],0x10 ; is it directory? + jz clear_file ; no + + push eax ebx + mov eax,edi + mov ebx,deltree_buffer ; save buffer over recursive call + call hd_write ; write directory sector to disk + pop ebx eax + + call clear_directory ; recursive call !!! + jc clear_error ; exit if error found + + push eax ebx + mov eax,edi + mov ebx,deltree_buffer + call hd_read ; read directory sector again + pop ebx eax + + clear_file: + call clear_cluster_chain + + clear_long_filename: + mov byte [ebx],0xe5 + + clear_next_entry: + add ebx,32 ; position of next dir entry + dec edx + jnz clear_analyze + + mov eax,edi + mov ebx,deltree_buffer + call hd_write ; write directory sector to disk + + inc eax ; next sector + dec ecx + jnz clear_new_sector + + mov eax,esi + call get_FAT ; get next cluster + jmp clear_new_cluster ; clear it + + clear_write_last: + mov eax,edi + mov ebx,deltree_buffer + call hd_write ; write directory sector to disk + + clear_end: + popad + clc + ret + + clear_error: + popad + stc + ret + + +delete_entry_name: +;----------------------------------------------------- +; input : eax = directory sector +; ebx = directory pointer in buffer +; longname_sec = 2 previous directory sectors +; output : ecx = first cluster +; change : eax,ebx,edx +;----------------------------------------------------- + mov byte [ebx],0xe5 + mov ecx,[ebx+20-2] ; first cluster of file + mov cx,[ebx+26] ; 0 length files start cluster = 0 + and ecx,[fatMASK] + + delete_empty: + sub ebx,32 + cmp ebx,buffer + jnb delete_test_long + + mov ebx,buffer + call hd_write ; write directory sector back + xor eax,eax + xchg eax,[longname_sec2] + xchg eax,[longname_sec1] + test eax,eax ; is there previous directory sector? + jz delete_name_end ; no + + mov ebx,buffer + call hd_read ; read previous sector + mov ebx,buffer+0x1e0 ; start from last entry + + delete_test_long: + mov dh,[ebx+11] ; file attribute + and dh,0xf + cmp dh,0xf + jne delete_write_buffer + + cmp byte [ebx],0x40 ; end of long dir entry? + mov byte [ebx],0xe5 + jb delete_empty + + delete_write_buffer: + mov ebx,buffer + call hd_write ; write directory sector back + + delete_name_end: + ret + + +rename: +;----------------------------------------------------------- +; input : eax = source directory name +; edx = source path +; ebx = dest directory name +; edi = dest path +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 8 - disk full +; 10 - access denied +;----------------------------------------------------------- + cmp [fat_type],0 + jnz fat_ok_for_rename + mov eax,ERROR_UNKNOWN_FS + ret + + fat_ok_for_rename: +; call reserve_hd1 + + pushad + + mov ebx,edx ; source path + call get_cluster_of_a_path + jc rename_entry_not_found + + mov ebx,PUSHAD_EAX ; source directory name + call analyze_directory + jc rename_entry_not_found + + mov [sector_tmp],eax ; save source sector + mov [entry_pos],ebx + mov esi,ebx + mov edi,dir_entry + mov ecx,32/4 + cld + rep movsd ; save entry + + mov ebx,PUSHAD_EDI ; dest path + call get_cluster_of_a_path + jc rename_entry_not_found + + mov edx,eax ; save dest directory cluster + mov ebx,PUSHAD_EBX ; dest directory name + push [longname_sec1] + push [longname_sec2] + call analyze_directory ; check if entry already exist + pop [longname_sec2] + pop [longname_sec1] + jnc rename_entry_already_exist + + mov eax,edx + call analyze_directory_to_write + jc rename_disk_full + + mov esi,dir_entry + mov edi,ebx + mov ecx,32/4 + cld + rep movsd ; copy entry + mov esi,PUSHAD_EBX ; dest directory name + mov edi,ebx + mov ecx,11 + rep movsb ; copy name + + mov ebx,buffer ; save the directory name,length,cluster + call hd_write + + test byte [dir_entry+11],0x10 ; is it directory? + jz rename_not_dir ; no + mov eax,[dir_entry+20-2] ; FAT entry + mov ax,[dir_entry+26] + and eax,[fatMASK] + call change_2dot_cluster + + rename_not_dir: + mov eax,[sector_tmp] + mov ebx,buffer + call hd_read ; read source directory sector + + mov ebx,[entry_pos] + call delete_entry_name + + popad + call update_disk ; write all of cache and fat to hd + mov [hd1_status],0 + xor eax,eax + ret + + rename_entry_not_found: + popad + mov [hd1_status],0 + mov eax,ERROR_FILE_NOT_FOUND + ret + + rename_entry_already_exist: + popad + mov [hd1_status],0 + mov eax,ERROR_ACCESS_DENIED + ret + + rename_disk_full: + popad + mov [hd1_status],0 + mov eax,ERROR_DISK_FULL + ret + + +change_2dot_cluster: +;----------------------------------------------------------- +; input : eax = directory cluster +; edx = value to save +; change : eax,ebx,edx +;----------------------------------------------------------- + cmp eax,[LAST_CLUSTER] + ja not_2dot ; too big cluster number, something is wrong + sub eax,2 + jb not_2dot + + imul eax,[SECTORS_PER_CLUSTER] + add eax,[DATA_START] + mov ebx,buffer + call hd_read + + cmp dword [ebx+32],'.. ' + jnz not_2dot + + cmp edx,[ROOT_CLUSTER] ; is rootdir cluster? + jne not_2dot_root + xor edx,edx ; yes. set it zero + + not_2dot_root: + mov [ebx+32+26],dx ; 16 bits low of cluster + shr edx,16 + mov [ebx+32+20],dx ; 16 bits high of cluster (=0 fat16) + call hd_write + + not_2dot: + ret + + +get_filesize: +;----------------------------------------------------------- +; input : eax = file name +; edx = path +; edi = if 0 - read rootdir else normal dir/file size +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; ebx = file size +;----------------------------------------------------------- + cmp [fat_type],0 + jnz get_filesize_fat_ok + xor ebx,ebx + mov eax,ERROR_UNKNOWN_FS + ret + + get_filesize_fat_ok: +; call reserve_hd1 + + pushad + xor eax,eax + test edi,edi ; is read rootdir? + je get_filesize_dirsize ; yes + + get_filesize_no_root: + mov ebx,edx + call get_cluster_of_a_path + jc get_filesize_not_found + + mov ebx,PUSHAD_EAX ; file name + call analyze_directory + jc get_filesize_not_found + + mov eax,[ebx+28] ; file size + test byte [ebx+11],0x10 ; is it directory? + jz get_filesize_set_size ; no + + mov eax,[ebx+20-2] ; FAT entry + mov ax,[ebx+26] + and eax,[fatMASK] + + get_filesize_dirsize: + call get_dir_size + + get_filesize_set_size: + mov PUSHAD_EBX,eax + popad + mov [hd1_status],0 + xor eax,eax + ret + + get_filesize_not_found: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_FILE_NOT_FOUND + ret + + +get_fileattr: +;----------------------------------------------------------- +; input : eax = file name +; edx = path +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; ebx = file attribute +;----------------------------------------------------------- + cmp [fat_type],0 + jnz get_fileattr_fat_ok + xor ebx,ebx + mov eax,ERROR_UNKNOWN_FS + ret + + get_fileattr_fat_ok: +; call reserve_hd1 + + pushad + mov ebx,edx + call get_cluster_of_a_path + jc get_fileattr_not_found + + mov ebx,PUSHAD_EAX ; file name + call analyze_directory + jc get_fileattr_not_found + + movzx eax,byte [ebx+11] ; file attribute + mov PUSHAD_EBX,eax + popad + mov [hd1_status],0 + xor eax,eax + ret + + get_fileattr_not_found: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_FILE_NOT_FOUND + ret + + +get_filedate: +;----------------------------------------------------------- +; input : eax = file name +; edx = path +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; ebx = file date/time +; bits 31..25 = year-1980 +; bits 24..21 = month +; bits 20..16 = day +; bits 15..11 = hour +; bits 10..5 = minute +; bits 4..0 = second/2 +;----------------------------------------------------------- + cmp [fat_type],0 + jnz get_filedate_fat_ok + xor ebx,ebx + mov eax,ERROR_UNKNOWN_FS + ret + + get_filedate_fat_ok: +; call reserve_hd1 + + pushad + mov ebx,edx + call get_cluster_of_a_path + jc get_filedate_not_found + + mov ebx,PUSHAD_EAX ; file name + call analyze_directory + jc get_filedate_not_found + + mov eax,[ebx+22] ; file date/time + mov PUSHAD_EBX,eax + popad + mov [hd1_status],0 + xor eax,eax + ret + + get_filedate_not_found: + popad + mov [hd1_status],0 + xor ebx,ebx + mov eax,ERROR_FILE_NOT_FOUND + ret + + +get_hd_info: +;----------------------------------------------------------- +; output : eax = 0 - ok +; 3 - unknown FS +; edx = cluster size in bytes +; ebx = total clusters on disk +; ecx = free clusters on disk +;----------------------------------------------------------- + cmp [fat_type],0 + jnz info_fat_ok + xor edx,edx + xor ebx,ebx + xor ecx,ecx + mov eax,ERROR_UNKNOWN_FS + ret + + info_fat_ok: +; call reserve_hd1 + + xor ecx,ecx ; count of free clusters + mov eax,2 + mov ebx,[LAST_CLUSTER] + + info_cluster: + push eax + call get_FAT ; get cluster info + test eax,eax ; is it free? + jnz info_used ; no + inc ecx + + info_used: + pop eax + inc eax + cmp eax,ebx ; is above last cluster? + jbe info_cluster ; no. test next cluster + + dec ebx ; cluster count + imul edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes + mov [hd1_status],0 + xor eax,eax + ret + + +update_disk: +;----------------------------------------------------------- +; write changed fat and cache to disk +;----------------------------------------------------------- + cmp [fat_change],0 ; is fat changed? + je upd_no_change + + call write_fat_sector + + upd_no_change: + + call write_cache + ret + + +;************************************************************************** +; +; 0x600008 - first entry in cache list +; +; +0 - lba sector +; +4 - state of cache sector +; 0 = empty +; 1 = used for read ( same as in hd ) +; 2 = used for write ( differs from hd ) +; +; +65536 - cache entries +; +;************************************************************************** + + +hd_read: +;----------------------------------------------------------- +; input : eax = block to read +; ebx = destination +;----------------------------------------------------------- + push ecx esi edi ; scan cache + + mov ecx,cache_max ; entries in cache + mov esi,0x600000+8 + mov edi,1 + + hdreadcache: + + cmp dword [esi+4],0 ; empty + je nohdcache + + cmp [esi],eax ; correct sector + je yeshdcache + + nohdcache: + + add esi,8 + inc edi + dec ecx + jnz hdreadcache + + call find_empty_slot ; ret in edi + + call wait_for_hd_idle + push eax edx + + cli + xor eax,eax + mov edx,[hdbase] + inc edx + out dx,al ; ATAFeatures ЁхушёЄЁ "юёюсхээюёЄхщ" + inc edx + inc eax + out dx,al ; ATASectorCount ёўхЄўшъ ёхъЄюЁют + inc edx + mov eax,[esp+4] + out dx,al ; ATASectorNumber ЁхушёЄЁ эюьхЁр ёхъЄюЁр + shr eax,8 + inc edx + out dx,al ; ATACylinder эюьхЁ ЎшышэфЁр (ьырф°шщ срщЄ) + shr eax,8 + inc edx + out dx,al ; эюьхЁ ЎшышэфЁр (ёЄрЁ°шщ срщЄ) + shr eax,8 + inc edx + and al,1+2+4+8 + add al,byte [hdid] + add al,128+64+32 + out dx,al ; эюьхЁ уюыютъш/эюьхЁ фшёър + inc edx + mov al,20h + out dx,al ; ATACommand ЁхушёЄЁ ъюьрэф + sti + + call wait_for_sector_buffer + + cmp [hd_error],0 + jne hd_read_error + + cli + push edi + shl edi,9 + add edi,0x600000+65536 + mov ecx,256 + mov edx,[hdbase] + cld + rep insw + pop edi + sti + + pop edx eax + blok_read_2: + lea esi,[edi*8+0x600000] + mov [esi],eax ; sector number + mov dword [esi+4],1 ; hd read - mark as same as in hd + + yeshdcache: + + mov esi,edi + shl esi,9 + add esi,0x600000+65536 + mov edi,ebx + mov ecx,512/4 + cld + rep movsd ; move data +; blok_read_2: + pop edi esi ecx + ret + + +hd_write: +;----------------------------------------------------------- +; input : eax = block +; ebx = pointer to memory +;----------------------------------------------------------- + push ecx esi edi + + ; check if the cache already has the sector and overwrite it + + mov ecx,cache_max + mov esi,0x600000+8 + mov edi,1 + + hdwritecache: + + cmp dword [esi+4],0 ; if cache slot is empty + je not_in_cache_write + + cmp [esi],eax ; if the slot has the sector + je yes_in_cache_write + + not_in_cache_write: + + add esi,8 + inc edi + dec ecx + jnz hdwritecache + + ; sector not found in cache + ; write the block to a new location + + call find_empty_slot ; ret in edi + + lea esi,[edi*8+0x600000] + mov [esi],eax ; sector number + + yes_in_cache_write: + + mov dword [esi+4],2 ; write - differs from hd + + shl edi,9 + add edi,0x600000+65536 + mov esi,ebx + mov ecx,512/4 + cld + rep movsd ; move data + + pop edi esi ecx + ret + + +write_cache: +;----------------------------------------------------------- +; write all changed sectors to disk +;----------------------------------------------------------- + push eax ecx edx esi edi + + ; write difference ( 2 ) from cache to hd + + mov ecx,cache_max + mov esi,0x600000+8 + mov edi,1 + + write_cache_more: + + cmp dword [esi+4],2 ; if cache slot is not different + jne does_not_need_writing + + mov dword [esi+4],1 ; same as in hd + mov eax,[esi] ; eax = sector to write + + cmp eax,[PARTITION_START] + jb danger + cmp eax,[PARTITION_END] + ja danger + + call wait_for_hd_idle + + cli + xor eax,eax + mov edx,[hdbase] + inc edx + out dx,al + inc edx + inc eax + out dx,al + inc edx + mov eax,[esi] ; eax = sector to write + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + and al,1+2+4+8 + add al,byte [hdid] + add al,128+64+32 + out dx,al + inc edx + mov al,30h + out dx,al + sti + + call wait_for_sector_buffer + + cmp [hd_error],0 + jne hd_write_error + + push ecx esi + + cli + mov esi,edi + shl esi,9 + add esi,0x600000+65536 ; esi = from memory position + mov ecx,256 + mov edx,[hdbase] + cld + rep outsw + sti + + pop esi ecx + + danger: + does_not_need_writing: + + add esi,8 + inc edi + dec ecx + jnz write_cache_more + + pop edi esi edx ecx eax + ret + + +find_empty_slot: +;----------------------------------------------------------- +; find empty or read slot, flush cache if next 10% is used by write +; output : edi = cache slot +;----------------------------------------------------------- + push ecx esi + + search_again: + + mov ecx,cache_max*10/100 + mov edi,[cache_search_start] + + search_for_empty: + + inc edi + cmp edi,cache_max + jbe inside_cache + mov edi,1 + + inside_cache: + + cmp dword [edi*8+0x600000+4],2 ; get cache slot info + jb found_slot ; it's empty or read + dec ecx + jnz search_for_empty + + call write_cache ; no empty slots found, write all + jmp search_again ; and start again + + found_slot: + + mov [cache_search_start],edi + + pop esi ecx + ret + + +save_hd_wait_timeout: + + push eax + mov eax,[timer_ticks];[0xfdf0] + add eax,300 ; 3 sec timeout + mov [hd_wait_timeout],eax + pop eax + ret + + +check_hd_wait_timeout: + + push eax + mov eax,[hd_wait_timeout] + cmp [timer_ticks], eax ;[0xfdf0],eax + jg hd_timeout_error + pop eax + ret + +iglobal + hd_timeout_str db 'K : FS - HD timeout',13,10,0 + hd_read_str db 'K : FS - HD read error',13,10,0 + hd_write_str db 'K : FS - HD write error',13,10,0 +endg + +hd_timeout_error: + + call clear_hd_cache + call clear_application_table_status + mov esi,hd_timeout_str + call sys_msg_board_str + jmp $ + + +hd_read_error: + + call clear_hd_cache + call clear_application_table_status + mov esi,hd_read_str + call sys_msg_board_str + jmp $ + +hd_write_error: + + call clear_hd_cache + call clear_application_table_status + mov esi,hd_write_str + call sys_msg_board_str + jmp $ + + + + +wait_for_hd_idle: + + push eax edx + + call save_hd_wait_timeout + + mov edx,[hdbase] + add edx,0x7 + + wfhil1: + + call check_hd_wait_timeout + + in al,dx + test al,128 + jnz wfhil1 + + pop edx eax + ret + + +wait_for_sector_buffer: + + push eax edx + + mov edx,[hdbase] + add edx,0x7 + + call save_hd_wait_timeout + + hdwait_sbuf: ; wait for sector buffer to be ready + + call check_hd_wait_timeout + + in al,dx + test al,8 + jz hdwait_sbuf + + mov [hd_error],0 + + cmp [hd_setup],1 ; do not mark error for setup request + je buf_wait_ok + + test al,1 ; previous command ended up with an error + jz buf_wait_ok + mov [hd_error],1 + + buf_wait_ok: + + pop edx eax + ret + + + +read_hd_file: +;----------------------------------------------------------------- +; +; Converting old reading function for hd-application start. +; +; IN: +; +; eax - pointer to file (0 = read only first sector of drive: eg 'label') +; ebx - file lenght +; ecx - start 512 byte block number +; edx - number of blocks to read +; esi - pointer to return/work area (atleast 20 000 bytes) +; +; For new read function +; +; EAX (PAR0) pointer to file-name +; ECX (PAR1) pointer to buffer +; EBX (PAR2) vt file blocks to read +; EDX (PAR3) pointer to path +; ESI vt first 512 block to read +; EDI if 0 - return root +;-------------------------------------------------------------------------- + + push ecx esi edi + mov esi,eax + mov edi,startpath + mov ecx,250 + cld + rep movsb + pop edi esi ecx + + mov eax,startpath + mov [eax+ebx-12],byte 0 + + push eax ebx ecx edx esi + + pop ecx ; pointer to buffer + add ecx,1024 + pop ebx ; number of blocks to read + pop esi ; first block to read + dec esi + pop eax ; file length + pop edx ; pointer to path + + mov edi,12 + lea eax,[eax+edx-12+1] + call file_read + + ret + diff --git a/trunk/fs/fs.inc b/trunk/fs/fs.inc new file mode 100644 index 000000000..5197a7da1 --- /dev/null +++ b/trunk/fs/fs.inc @@ -0,0 +1,1095 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; System service for filesystem call ;; +;; (C) 2004 Ville Turjanmaa, License: GPL ;; +;; ;; +;; 15.01.2005 get file size/attr/date, file_append (only for hd) - ATV ;; +;; 23.11.2004 test if hd/partition is set - ATV ;; +;; 18.11.2004 get_disk_info and more error codes - ATV ;; +;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;; +;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +iglobal +dir0: db 'HARDDISK ' + db 'RAMDISK ' + db 'FLOPPYDISK ' + db 0 + +dir1: db 'FIRST ' + db 'SECOND ' + db 'THIRD ' + db 'FOURTH ' + db 0 + +not_select_IDE db 0 + +hd_address_table: dd 0x1f0,0x00,0x1f0,0x10 + dd 0x170,0x00,0x170,0x10 +endg + +file_system: +; IN: +; +; eax = 0 ; read file /RamDisk/First 6 /HardDisk/First 30 +; eax = 1 ; write file /RamDisk/First 33 /HardDisk/First 56 +; eax = 2 ; delete file /RamDisk/First 32 /HardDisk/First 57 +; eax = 3 ; append to a file /RamDisk/First ?? /HardDisk/First ?? +; eax = 4 ; makedir +; eax = 5 ; rename file/directory +; eax = 8 ; lba read +; eax = 12 ; get_filesize +; eax = 13 ; get_fileattr +; eax = 14 ; get_filedate +; eax = 15 ; get_disk_info +; eax = 16 ; start application +; +; OUT: +; +; eax = 0 : read ok +; eax = 1 : no fd base and/or partition defined +; eax = 2 : yet unsupported FS +; eax = 3 : unknown FS +; eax = 4 : partition not defined at hd +; eax = 5 : file not found +; eax = 6 : end of file +; eax = 7 : memory pointer not in application area +; eax = 8 : disk full +; eax = 9 : fat table corrupted +; eax = 10 : access denied +; +; ebx = size + + ; Extract parameters + + mov edi,[0x3010] + add eax,[edi+0x10] ; abs start of info block + + cmp dword [eax+0],12 ; Get file size + je fs_read + cmp dword [eax+0],13 ; Get file attribute + je fs_read + cmp dword [eax+0],14 ; Get file date/time + je fs_read + cmp dword [eax+0],15 ; GET_DISK_INFO + je fs_info + cmp dword [eax+0],16 ; RUN - dont care about read&write blocks + je fs_read + cmp dword [eax+0],5 ; RENAME - dont care about read&write blocks + je fs_read + cmp dword [eax+0],4 ; MAKEDIR - dont care about read&write blocks + je fs_read + cmp dword [eax+0],2 ; DELETE - dont care about read&write blocks + je fs_read + + cmp dword [0x3000],1 ; no memory checks for kernel requests + jz no_checks_for_kernel +;iglobal +; buffer_failed db 'Buffer check failed',13,10,0 +;endg + mov edx,eax + cmp dword [eax+0],1 + jz .check_for_write_op + cmp dword [eax+0],3 + jnz .usual_check +.check_for_write_op: + mov ebx,[eax+12] + add ebx,std_application_base_address + mov ecx,[eax+8] + call check_region + test eax,eax + jnz area_in_app_mem + +.error_output: + mov esi,buffer_failed + call sys_msg_board_str + mov eax,7 + mov dword [esp+36],7 + ret +iglobal + buffer_failed db 'Buffer check failed',13,10,0 +endg +.usual_check: + cmp dword [eax+0],0 + mov ecx,512 + jnz .small_size + mov ecx,[eax+8] + shl ecx,9 +.small_size: + mov ebx,[eax+12] + add ebx,std_application_base_address + call check_region + test eax,eax + jz .error_output + jmp area_in_app_mem +; mov ebx,[0x3000] ; pointer in application memory ? +; shl ebx,8 +; mov ebx,[ebx+0x80000+0x8c] + +; mov ebp,ebx ; save for checking at stack save +; sub ebp,[eax+12] +; shr ebp,9 + +; sub ebx,512 ; need atleast one block + +; cmp ebx,[eax+12] +; ja area_in_app_mem +; mov eax,7 +; mov dword [esp+36],7 +; ret + area_in_app_mem: + mov eax,edx + no_checks_for_kernel: + + + cmp dword [eax+0],3 ; APPEND - allow write 0 bytes (truncate) + je fs_read + cmp dword [eax+8],0 ; read or write 0 blocks/bytes ? + jne fs_read + mov dword [esp+36],0 + ret + fs_read: + + mov ebx,[eax+20] ; program wants root directory ? + test bl,bl + je fs_getroot + test bh,bh + jne fs_noroot + fs_getroot: + mov edx,[edi+0x10] + mov esi,dir0 + mov edi,[eax+12] + add edi,edx + mov ecx,11 + cld + rep movsb + mov eax,0x10 + stosb + add edi,32-11-1 + mov ecx,11 + rep movsb + stosb + mov dword [esp+36],0 ; ok read + mov dword [esp+24],32*2 ; size of root + ret + + fs_info: ;start of code - Mihasik + mov edi,eax + push edi + cmp [eax+21],byte 'h' + je fs_info_h + cmp [eax+21],byte 'H' + je fs_info_h + cmp [eax+21],byte 'r' + je fs_info_r + cmp [eax+21],byte 'R' + je fs_info_r + mov eax,3 ;if unknown disk + xor ebx,ebx + xor ecx,ecx + xor edx,edx + jmp fs_info1 + fs_info_r: + call ramdisk_free_space ;if ramdisk + mov ecx,edi ;free space in ecx + shr ecx,9 ;free clusters + mov ebx,2847 ;total clusters + mov edx,512 ;cluster size + xor eax,eax ;always 0 + jmp fs_info1 + fs_info_h: ;if harddisk + call get_hd_info + fs_info1: + pop edi + mov [esp+36],eax + mov [esp+24],ebx ; total clusters on disk + mov [esp+32],ecx ; free clusters on disk + mov [edi],edx ; cluster size in bytes + ret ;end of code - Mihasik + + fs_noroot: + + mov ebx,[eax+0] + push ebx ; read/write/delete/.../makedir/rename/lba/run + mov ebx,[eax+4] + push ebx ; 512 block number to read + mov ebx,[eax+8] + +; cmp dword [eax+0],0 ; if read, check that the data stays at +; jne ret_size_fine ; application memory +; cmp ebx,ebp +; jbe ret_size_fine +; mov ebx,ebp +; ret_size_fine: + + push ebx ; bytes to write/append or 512 blocks to read + mov ebx,[eax+12] + add ebx,[edi+0x10] + push ebx ; abs start of return/save area + + lea esi,[eax+20] ; abs start of dir + filename + mov edi,[edi+0x10] ; abs start of work area + add edi,[eax+16] + + call expand_pathz + + push edi ; dir start + push ebx ; name of file start + + mov ebx,[dir0+11] ; /RAMDISK + mov eax,[edi+1] + cmp eax,'RD ' + je fs_yesramdisk + cmp eax,ebx + jne fs_noramdisk + + fs_yesramdisk: + + cmp byte [edi+1+11],0 + je fs_give_dir1 + + mov ebx,[dir1] ; /FIRST + mov eax,[edi+1+12] + cmp eax,'1 ' + je fs_yesramdisk_first + cmp eax,ebx + jne fs_noramdisk + + fs_yesramdisk_first: + + cmp dword [esp+20],8 ; LBA read ramdisk + jne fs_no_LBA_read_ramdisk + + mov eax,[esp+16] ; LBA block to read + mov ecx,[esp+8] ; abs pointer to return area + + call LBA_read_ramdisk + jmp file_system_return + + + fs_no_LBA_read_ramdisk: + + cmp dword [esp+20],0 ; READ + jne fs_noramdisk_read + + mov eax,[esp+4] ; fname + add eax,2*12+1 + mov ebx,[esp+16] ; block start + inc ebx + mov ecx,[esp+12] ; block count + mov edx,[esp+8] ; return + mov esi,[esp+0] + sub esi,eax + add esi,12+1 ; file name length + call fileread + + jmp file_system_return + + + fs_noramdisk_read: + + cmp dword [esp+20],1 ; WRITE + jne fs_noramdisk_write + + mov eax,[esp+4] ; fname + add eax,2*12+1 + mov ebx,[esp+8] ; buffer + mov ecx,[esp+12] ; count to write + mov edx,0 ; create new + call filesave + + ; eax=0 ok - eax=1 not enough free space + + jmp file_system_return + + fs_noramdisk_write: + + cmp dword [esp+20],16 ; START APPLICATION + jne fs_noramdisk_start_application + + mov eax,[esp+4] ; fname + add eax,2*12+1 + + xor ebx,ebx ; parameters to pass + cmp dword [esp+12],0 + je no_fl_start_param + mov ebx,[0x3010] + mov ebx,[ebx+0x10] + add ebx,[esp+12] + no_fl_start_param: + + call start_application_fl + + jmp file_system_return + + fs_noramdisk_start_application: ;there's new code - Mihasik + cmp dword [esp+20],2 ;DELETE + jne fs_noramdisk_delete + mov eax,[esp+4] ; fname + add eax,2*12+1 + call filedelete + jmp file_system_return + + fs_noramdisk_delete: + cmp dword [esp+20],12 ;GET TIME,DATE,SIZE AND ATTRS + jb fs_noramdisk_getinfo + cmp dword [esp+20],14 + ja fs_noramdisk_getinfo + mov eax,[esp+4] ; fname + add eax,2*12+1 + mov ebx,[esp+20] + mov ecx,[esp+0] + sub ecx,eax + add ecx,12+1 ; file name length + call rd_getfileinfo + jmp file_system_return + fs_noramdisk_getinfo: ;End of code - Mihasik + + fs_noramdisk: + + ;******************************************************************** + mov ebx,[dir0+22] ; /FLOPPYDISK + mov eax,[edi+1] + cmp eax,'FD ' + je fs_yesflpdisk + cmp eax,ebx + jne fs_noflpdisk + + fs_yesflpdisk: + call reserve_flp + + cmp byte [edi+1+11],0 + je fs_give_dir1 + + mov ebx,[dir1] ; /FIRST + mov eax,[edi+1+12] + cmp eax,'1 ' + je fs_yesflpdisk_first + cmp eax,ebx + je fs_yesflpdisk_first + mov ebx,[dir1+11] ; /SECOND + cmp eax,'2 ' + je fs_yesflpdisk_second + cmp eax,ebx + jne fs_noflpdisk + jmp fs_yesflpdisk_second + + fs_yesflpdisk_first: + mov [flp_number],1 + jmp fs_yesflpdisk_start + fs_yesflpdisk_second: + mov [flp_number],2 + fs_yesflpdisk_start: + cmp dword [esp+20],0 ; READ + jne fs_noflpdisk_read + + mov eax,[esp+4] ; fname + add eax,2*12+1 + mov ebx,[esp+16] ; block start + inc ebx + mov ecx,[esp+12] ; block count + mov edx,[esp+8] ; return + mov esi,[esp+0] + sub esi,eax + add esi,12+1 ; file name length + call floppy_fileread + + jmp file_system_return + + + fs_noflpdisk_read: + + cmp dword [esp+20],1 ; WRITE + jne fs_noflpdisk_write + + mov eax,[esp+4] ; fname + add eax,2*12+1 + mov ebx,[esp+8] ; buffer + mov ecx,[esp+12] ; count to write + mov edx,0 ; create new + call floppy_filesave + + ; eax=0 ok - eax=1 not enough free space + + jmp file_system_return + + fs_noflpdisk_write: + + cmp dword [esp+20],2 ; DELETE + jne fs_noflpdisk_delete + + mov eax,[esp+4] ; fname + add eax,2*12+1 + call floppy_filedelete + mov [flp_status],0 + jmp file_system_return + + fs_noflpdisk_delete: + cmp dword [esp+20],16 ; START APPLICATION + jne fs_noflpdisk_start_application + + mov eax,[esp+4] ; fname + add eax,2*12+1 + + xor ebx,ebx ; parameters to pass + cmp dword [esp+12],0 + je no_flp_start_param + mov ebx,[0x3010] + mov ebx,[ebx+0x10] + add ebx,[esp+12] + + no_flp_start_param: + + call start_application_floppy + + jmp file_system_return + + fs_noflpdisk_start_application: + + fs_noflpdisk: + ;***************************************************************** + + mov eax,[edi+1] + cmp eax,'HD0 ' + je fs_yesharddisk_IDE0 + cmp eax,'HD1 ' + je fs_yesharddisk_IDE1 + cmp eax,'HD2 ' + je fs_yesharddisk_IDE2 + cmp eax,'HD3 ' + je fs_yesharddisk_IDE3 + jmp old_path_harddisk +fs_yesharddisk_IDE0: + call reserve_hd1 + mov [hdbase],0x1f0 + mov [hdid],0x0 + mov [hdpos],1 + jmp fs_yesharddisk_partition +fs_yesharddisk_IDE1: + call reserve_hd1 + mov [hdbase],0x1f0 + mov [hdid],0x10 + mov [hdpos],2 + jmp fs_yesharddisk_partition +fs_yesharddisk_IDE2: + call reserve_hd1 + mov [hdbase],0x170 + mov [hdid],0x0 + mov [hdpos],3 + jmp fs_yesharddisk_partition +fs_yesharddisk_IDE3: + call reserve_hd1 + mov [hdbase],0x170 + mov [hdid],0x10 + mov [hdpos],4 +fs_yesharddisk_partition: +; call choice_necessity_partition +; jmp fs_yesharddisk_all + jmp fs_for_new_semantic + +choice_necessity_partition: + mov eax,[edi+1+12] + call StringToNumber + mov [fat32part],eax +choice_necessity_partition_1: + mov [0xfe10],dword 0 ; entries in hd cache + mov ecx,[hdpos] + xor eax,eax + mov edx,0x40002 + search_partition_array: + mov bl,[edx] + movzx ebx,bl + add eax,ebx + inc edx + loop search_partition_array + sub eax,ebx + add eax,[fat32part] + dec eax + xor edx,edx + imul eax,100 + add eax,0x4000a + mov [transfer_adress],eax + call partition_data_transfer_1 + ret + + old_path_harddisk: + mov ebx,[dir0] ; /HARDDISK + mov eax,[edi+1] + cmp eax,'HD ' + je fs_yesharddisk + cmp eax,ebx + jne fs_noharddisk + + fs_yesharddisk: + call reserve_hd1 + + cmp dword [esp+20],8 ; LBA read + jne fs_no_LBA_read + mov eax,[esp+16] ; LBA block to read + lea ebx,[edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH + mov ecx,[esp+8] ; abs pointer to return area + call LBA_read + jmp file_system_return + + fs_no_LBA_read: + + cmp byte [edi+1+11],0 ; directory read + je fs_give_dir1 + fs_for_new_semantic: + call choice_necessity_partition + + fs_yesharddisk_all: + mov eax,1 + cmp [hdpos],0 ; is hd base set? + jz file_system_return ; no + cmp [fat32part],0 ; is partition set? + jz file_system_return ; no + + cmp dword [esp+20],0 ; READ + jne fs_noharddisk_read + + mov eax,[esp+0] ; /fname + lea edi,[eax+12] + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + + mov ebx,[esp+12] ; count to read + mov ecx,[esp+8] ; buffer + mov edx,[esp+4] + add edx,12*2 ; dir start + sub edi,edx ; path length + mov esi,[esp+16] ; blocks to read + + call file_read + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_read: + + + cmp dword [esp+20],1 ; WRITE + jne fs_noharddisk_write + + mov eax,[esp+0] ; /fname + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + + mov ebx,[esp+12] ; count to write + mov ecx,[esp+8] ; buffer + mov edx,[esp+4] + add edx,12*2 ; path start + + call file_write + + mov edi,[esp+0] + mov byte [edi],'/' + + ; eax=0 ok - eax=1 not enough free space + + jmp file_system_return + + + fs_noharddisk_write: + + cmp dword [esp+20],2 ; DELETE + jne fs_noharddisk_delete + + mov eax,[esp+0] ; /dirname or /filename + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + + call removedir + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_delete: + + cmp dword [esp+20],3 ; APPEND + jne fs_noharddisk_append + + mov eax,[esp+0] ; /dirname or /filename + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + mov ecx,[esp+8] ; buffer + mov ebx,[esp+12] ; count to write + mov esi,[esp+16] ; bytes to skip over + + call file_append + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_append: + + cmp dword [esp+20],4 ; MAKEDIR + jne fs_noharddisk_makedir + + mov eax,[esp+0] ; /dirname + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + + call makedir + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_makedir: + + cmp dword [esp+20],5 ; RENAME + jne fs_noharddisk_rename + + mov edi,[esp+0] ; start of source file name + add edi,12+1 ; continue after name + call expand_pathz ; convert destination name + + mov edx,[dir0] ; /HARDDISK + mov eax,[edi+1] + cmp eax,'HD ' + je fs_rename_test1 + cmp eax,edx + jne fs_rename_error + + fs_rename_test1: + mov edx,[dir1] ; /FIRST + mov eax,[edi+1+12] + cmp eax,'1 ' + je fs_rename_start + cmp eax,edx + jne fs_rename_error + + fs_rename_start: + mov byte [ebx],0 ; path to asciiz + inc ebx ; filename start + add edi,12*2 ; path start + cmp byte [ebx],0 + je fs_rename_error + cmp byte [ebx],32 + je fs_rename_error + + mov eax,[esp+0] ; /filename + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + + call rename + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_rename_error: + mov eax,4 ; partition not defined at hd + jmp file_system_return + + fs_noharddisk_rename: + + cmp dword [esp+20],12 ; get FILESIZE + jne fs_noharddisk_get_filesize + + mov eax,[esp+0] ; /fname + lea edi,[eax+12] + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + sub edi,edx ; path length + + call get_filesize + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_get_filesize: + + cmp dword [esp+20],13 ; get FILEATTR + jne fs_noharddisk_get_fileattr + + mov eax,[esp+0] ; /dirname + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + + call get_fileattr + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_get_fileattr: + + cmp dword [esp+20],14 ; get FILEDATE + jne fs_noharddisk_get_filedate + + mov eax,[esp+0] ; /dirname + mov byte [eax],0 ; path to asciiz + inc eax ; filename start + mov edx,[esp+4] + add edx,12*2 ; path start + + call get_filedate + + mov edi,[esp+0] + mov byte [edi],'/' + + jmp file_system_return + + fs_noharddisk_get_filedate: + + cmp dword [esp+20],16 ; START APPLICATION + jne fs_noharddisk_start_application + + mov eax,[esp+4] ; fname + add eax,12*2 + + mov ebx,[esp+0] ; length + sub ebx,eax + add ebx,12 + + mov ecx,[esp+4] ; work area + add ecx,512 + + xor ebp,ebp ; parameters to pass + cmp dword [esp+12],0 + je no_hd_start_param + mov ebp,[0x3010] + mov ebp,[ebp+0x10] + add ebp,[esp+12] + no_hd_start_param: + + call start_application_hd + + jmp file_system_return + + fs_noharddisk_start_application: + + fs_noharddisk: + + file_system_return: + + add esp,24 + + mov [esp+36],eax + mov [esp+24],ebx + ret + + + fs_give_dir1: + + mov eax,0x10 + mov ebx,1 + mov edi,[esp+8] + mov esi,dir1 + fs_d1_new: + mov ecx,11 + cld + rep movsb + stosb + add edi,32-11-1 + dec ebx + jne fs_d1_new + + add esp,24 + + mov dword [esp+36],0 ; ok read + mov dword [esp+24],32*1 ; dir/data size + ret + + + +LBA_read_ramdisk: + + cmp [lba_read_enabled],1 + je lbarrl1 + + xor ebx,ebx + mov eax,2 + ret + + lbarrl1: + + cmp eax,18*2*80 + jb lbarrl2 + xor ebx,ebx + mov eax,3 + ret + + lbarrl2: + + pushad + + call restorefatchain + + mov edi,ecx + mov esi,eax + + shl esi,9 + add esi,0x100000 + mov ecx,512/4 + cld + rep movsd + + popad + + xor ebx,ebx + xor eax,eax + ret + +LBA_read: + +; IN: +; +; eax = LBA block to read +; ebx = pointer to FIRST/SECOND/THIRD/FOURTH +; ecx = abs pointer to return area + + cmp [lba_read_enabled],1 + je lbarl1 + mov eax,2 + ret + + lbarl1: + +; call reserve_hd1 + + push eax + push ecx + + mov edi,hd_address_table + mov esi,dir1 + mov eax,[ebx] + mov edx,'1 ' + mov ecx,4 + blar0: + cmp eax,[esi] + je blar2 + cmp eax,edx + je blar2 + inc edx + add edi,8 + add esi,11 + dec ecx + jnz blar0 + + mov eax,1 + mov ebx,1 + jmp LBA_read_ret + + blar2: + mov eax,[edi+0] + mov ebx,[edi+4] + + call wait_for_hd_idle + + ; eax = hd port + ; ebx = set for primary (0x00) or slave (0x10) + + cli + + mov edx,eax + inc edx + xor eax,eax + out dx,al + inc edx + inc eax + out dx,al + inc edx + mov eax,[esp+4] + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + and al,1+2+4+8 + add al,bl + add al,128+64+32 + out dx,al + + inc edx + mov al,20h + out dx,al + + sti + + call wait_for_sector_buffer + + cli + + mov edi,[esp+0] + mov ecx,256 + sub edx,7 + cld + rep insw + + sti + + xor eax,eax + xor ebx,ebx + + LBA_read_ret: + + mov [hd1_status],0 + add esp,2*4 + + ret + + +expand_pathz: +; IN: +; esi = asciiz path & file +; edi = buffer for path & file name +; OUT: +; edi = directory & file : / 11 + / 11 + / 11 - zero terminated +; ebx = /file name - zero terminated +; esi = pointer after source + + push eax + push ecx + push edi ;[esp+0] + + pathz_start: + mov byte [edi],'/' + inc edi + mov al,32 + mov ecx,11 + cld + rep stosb ; clear filename area + sub edi,11 + mov ebx,edi ; start of dir/file name + + pathz_new_char: + mov al,[esi] + inc esi + cmp al,0 + je pathz_end + + cmp al,'/' + jne pathz_not_path + cmp edi,ebx ; skip first '/' + jz pathz_new_char + lea edi,[ebx+11] ; start of next directory + jmp pathz_start + + pathz_not_path: + cmp al,'.' + jne pathz_not_ext + lea edi,[ebx+8] ; start of extension + jmp pathz_new_char + + pathz_not_ext: + cmp al,'a' + jb pathz_not_low + cmp al,'z' + ja pathz_not_low + sub al,0x20 ; char to uppercase + + pathz_not_low: + mov [edi],al + inc edi + mov eax,[esp+0] ; start_of_dest_path + add eax,512 ; keep maximum path under 512 bytes + cmp edi,eax + jb pathz_new_char + + pathz_end: + cmp ebx,edi ; if path end with '/' + jnz pathz_put_zero ; go back 1 level + sub ebx,12 + + pathz_put_zero: + mov byte [ebx+11],0 + dec ebx ; include '/' char into file name + pop edi + pop ecx + pop eax + ret + +;******************************************* +;* string to number +;* input eax - 4 byte string +;* output eax - number +;******************************************* +StringToNumber: +; ╧┼╨┼┬╬─ ╤╥╨╬╩╬┬╬├╬ ╫╚╤╦└ ┬ ╫╚╤╦╬┬╬╔ ┬╚─ +; ┬їюф: +; EDI - рфЁхё ёЄЁюъш ё ўшёыюь. ╩юэхЎ ўшёыр юЄьхўхэ ъюфюь 0Dh +; ┬√їюф: +; CF - шэфшърЄюЁ ю°шсюъ: +; 0 - ю°шсюъ эхЄ; +; 1 - ю°шсър +; ┼ёыш CF=0, Єю AX - ўшёыю. + + push bx + push cx + push dx + push edi + mov [partition_string],eax + mov edi,partition_string + xor cx,cx +i1: + mov al,[edi] + cmp al,32 ;13 + je i_exit +; cmp al,'0' +; jb err +; cmp al,'9' +; ja err + sub al,48 + shl cx,1 + jc err + mov bx,cx + shl cx,1 + jc err + shl cx,1 + jc err + add cx,bx + jc err + cbw + add cx,ax + jc err +i3: + inc edi + jmp i1 +i_exit: + mov ax,cx + clc +i4: + movzx eax,ax + pop edi + pop dx + pop cx + pop bx + ret + +err: + stc + jmp i4 + +partition_string: dd 0 + db 32 diff --git a/trunk/fs/fs_phys.inc b/trunk/fs/fs_phys.inc new file mode 100644 index 000000000..418945d02 --- /dev/null +++ b/trunk/fs/fs_phys.inc @@ -0,0 +1,111 @@ +hd_phys_read: +;eax - sector number +;ebx - destination + pushad + call wait_for_hd_idle + popad + push edx + push eax + cli + xor eax,eax + mov edx,[hdbase] + inc edx + out dx,al + inc edx + inc eax + out dx,al + inc edx +;write sector number. + mov eax,[esp] + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + and al,1+2+4+8 + add al,byte [hdid] ;+0 or +16 + or al,32+64+128 + out dx,al + inc edx + mov al,0x20 + out dx,al + sti + + call wait_for_sector_buffer + cmp [hd_error],0 + jnz hd_read_error + cli + push edi + mov edi,ebx + mov ecx,256 + mov edx,[hdbase] + cld + rep insw + pop edi + sti + pop edx + pop eax + ret + +hd_phys_write: +;eax - sector number +;ebx - destination + cmp eax,[partition_start] + jb .ret + cmp eax,[partition_end] + ja .ret + pushad + call wait_for_hd_idle + popad + push edx + push eax + cli + xor eax,eax + mov edx,[hdbase] + inc edx + out dx,al + inc edx + inc eax + out dx,al +;write sector number + inc edx + mov eax,[esp] + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + and al,1+2+4+8 + add al,byte [hdid] ;+0 or +16 + or al,32+64+128 + out dx,al + + inc edx + mov al,0x30 + out dx,al + sti + + call wait_for_sector_buffer + cmp [hd_error],0 + jnz hd_write_error + cli + push esi + mov esi,ebx + mov ecx,256 + mov edx,[hdbase] + cld + rep outsw + pop esi + sti + pop edx + pop eax +.ret: + ret \ No newline at end of file diff --git a/trunk/gui/button.inc b/trunk/gui/button.inc new file mode 100644 index 000000000..06f3fa60a --- /dev/null +++ b/trunk/gui/button.inc @@ -0,0 +1,551 @@ +max_buttons=4095 +dececx: + + push eax + push edx + push ecx + + mov edx,1 + dececl: + + movzx eax,byte [esp+edx] + cmp eax,0x20 + jge @f + mov [esp+edx],byte 0x20 + @@: + sub [esp+edx],byte 0x20 + + add edx,1 + cmp edx,4 + jbe dececl + + pop ecx + pop edx + pop eax + ret + + +drawbuttonframes: + + push esi + push edi + push eax + push ebx + push ecx + push edx + + shr eax,16 + shr ebx,16 + mov edx,[0x3010] + + add eax,[edx-twdw] + add ebx,[edx-twdw+4] + mov cx,ax + mov dx,bx + shl eax,16 + shl ebx,16 + mov ax,cx + mov bx,dx + add ax,word [esp+12] + mov esi,ebx + mov edi,0 + mov ecx,[esp+0] + add ecx,0x202020 + call [draw_line] + + movzx edx,word [esp+8] + add ebx,edx + shl edx,16 + add ebx,edx + mov ecx,[esp+0] + call dececx + call [draw_line] + + mov ebx,esi + push edx + mov edx,eax + shr edx,16 + mov ax,dx + mov edx,ebx + shr edx,16 + mov bx,dx + mov dx,[esp+8+4] + add bx,dx + pop edx + mov edi,0 + mov ecx,[esp+0] + add ecx,0x202020 + call [draw_line] + + mov esi,edx + mov dx,[esp+12] + add ax,dx + shl edx,16 + add eax,edx + add ebx,1*65536 + mov edx,esi + mov ecx,[esp+0] + call dececx + call [draw_line] + + pop edx + pop ecx + pop ebx + pop eax + pop edi + pop esi + + ret + +button_dececx: + + cmp [buttontype],dword 1 + jne .finish +; je bdece +; ret +; bdece: + push eax + mov eax,0x01 + cmp edi,20 + jg @f + mov eax,0x02 + @@: + test ecx,0xff + jz @f + sub ecx,eax + @@: + shl eax,8 + test ecx,0xff00 + jz @f + sub ecx,eax + @@: + shl eax,8 + test ecx,0xff0000 + jz @f + sub ecx,eax + @@: + pop eax + .finish: + ret + + +sys_button: + + test ecx,0x80000000 + jnz remove_button + + push esi + push edi + push eax + push ebx + push ecx + push edx + + test ecx,0x40000000 + jnz button_no_draw + + pushad ; button body + push ebx + shr eax,16 + shr ebx,16 + mov edx,[0x3010] + mov esi,[edx-twdw] + mov edi,[edx-twdw+4] + add eax,esi + add ebx,edi + mov cx,ax + mov dx,bx + shl eax,16 + shl ebx,16 + mov ax,cx + mov bx,dx + movzx ecx,word [4+32+esp+12] + add eax,ecx + mov ecx,[4+32+esp+0] + cmp [buttontype],dword 0 + je @f + add ecx,0x141414 + @@: + movzx edi,word [esp] + +; + pop edx + and edx, 0xFFFF + ;;cli + .newline: + call button_dececx + push edi + xor edi, edi + call [draw_line] + pop edi + add ebx,1*65536+1 ; [ y start | y end ] + dec edx + jnz .newline + ;;sti +;; pop ebx +; + popad + + call drawbuttonframes + + button_no_draw: + + and ecx,0xffff + + mov edi,[0x3010] + sub edi,twdw + + mov edi,[0xfe88] + movzx eax,word [edi] + cmp eax,max_buttons + jge noaddbutt + inc eax + mov [edi],ax + + shl eax,4 + add eax,edi + + mov bx,[0x3000] + mov [eax],bx + + add eax,2 ; save button id number + mov ebx,[esp+4] + mov [eax],bx ; bits 0-15 + shr ebx,16 + mov [eax-2+0xc],bx; bits 16-31 + add eax,2 ; x start + mov bx,[esp+12+2] + mov [eax],bx + add eax,2 ; x size + mov bx,[esp+12+0] + mov [eax],bx + add eax,2 ; y start + mov bx,[esp+8+2] + mov [eax],bx + add eax,2 ; y size + mov bx,[esp+8+0] + mov [eax],bx + + noaddbutt: + + pop edx + pop ecx + pop ebx + pop eax + pop edi + pop esi + + ret + + +remove_button: + + and ecx,0x7fffffff + + rnewba2: + + mov edi,[0xfe88] + mov eax,edi + movzx ebx,word [edi] + inc bx + + rnewba: + + dec bx + jz rnmba + + add eax,0x10 + + mov dx,[0x3000] + cmp dx,[eax] + jnz rnewba + + cmp cx,[eax+2] + jnz rnewba + + pushad + mov ecx,ebx + inc ecx + shl ecx,4 + mov ebx,eax + add eax,0x10 + call memmove + dec dword [edi] + popad + + jmp rnewba2 + + rnmba: + + ret + +find_pressed_button_frames: + + pushad + + movzx ebx,word [eax+0] + shl ebx,5 + add ebx,window_data + movzx ecx,word [ebx+0] ; window x start + movzx edx,word [eax+4] ; button x start + add ecx,edx + push ecx + + mov dx,[eax+6] ; button x size + add cx,dx + mov esi,ecx + inc esi + mov cx,[ebx+4] ; window y start + mov dx,[eax+8] ; button y start + add ecx,edx + mov ebx,ecx + mov dx,[eax+10] ; button y size + add dx,cx + inc dx + + pop eax + + ; eax x beginning + ; ebx y beginning + ; esi x end + ; edx y end + ; ecx color + + mov [pressed_button_eax],eax + mov [pressed_button_ebx],ebx + mov [pressed_button_ecx],ecx + mov [pressed_button_edx],edx + mov [pressed_button_esi],esi + + popad + ret + +uglobal + pressed_button_eax dd 0 + pressed_button_ebx dd 0 + pressed_button_ecx dd 0 + pressed_button_edx dd 0 + pressed_button_esi dd 0 +endg + +; negative button image + +negativebutton: + ; If requested, do not display button + ; boarder on press. + test ebx,0x20000000 + jz draw_negative_button + ret + draw_negative_button: + + pushad + + mov eax,[pressed_button_eax] + mov ebx,[pressed_button_ebx] + mov ecx,[pressed_button_ecx] + mov edx,[pressed_button_edx] + mov esi,[pressed_button_esi] + mov ecx,0x01000000 + + dec edx + push edx + inc edx + dec esi + push esi + inc esi + + push eax + push ebx + push ecx + push edx + push edi + + call [disable_mouse] + + bdbnewline: + mov edi,1 ; force + cmp eax,[esp+16] + jz bneg + cmp eax,[esp+20] + jz bneg + cmp ebx,[esp+12] + jz bneg + cmp ebx,[esp+24] + jnz nbneg +; jz bneg +; jmp nbneg + + bneg: + + ;;;call [disable_mouse] + call [putpixel] + + nbneg: + + inc eax + cmp eax,esi + jnz bdbnewline + mov eax,[esp+16] + inc ebx + cmp ebx,edx + jnz bdbnewline + + add esp,28 + + popad + + ret + +; check buttons + + +; 0000 word process number +; 0002 word button id number : bits 0-15 +; 0004 word x start +; 0006 word x size +; 0008 word y start +; 000A word y size +; 000C word button id number : bits 16-31 +; +; button table in 0x10 increments +; +; first at 0x10 + + +checkbuttons: + + cmp [0xfb40],byte 0 ; mouse buttons pressed + jnz @f + ret + @@: + + pushad + + xor esi, esi + mov edi, [0xfe88] + movzx edx, word [edi] + test edx, edx + jne @f + popad + ret + + @@: + + push esi + inc edx + push edx + + buttonnewcheck: + + pop edx + pop esi + inc esi + cmp edx,esi + jge bch + + popad ; no button pressed + ret + + bch: + + push esi + push edx + mov eax,esi + shl eax,4 + add eax,edi + + ; check that button is at top of windowing stack + + movzx ebx,word [eax] + movzx ecx,word [0xC000 + ebx * 2] + cmp ecx,[0x3004] + jne buttonnewcheck + + ; check that button start is inside window x/y end + + movzx ebx,word [eax+0] + shl ebx,5 +; add ebx,window_data +; mov ecx,[window_data+ebx+8] ; window end X + movzx edx,word [eax+4] ; button start X + cmp edx, [window_data+ebx+8] ;ecx + jge buttonnewcheck + +; mov ecx,[window_data+ebx+12] ; window end Y + movzx edx, word [eax+8] ; button start Y + cmp edx, [window_data+ebx+12] ;ecx + jge buttonnewcheck + + ; check coordinates + ; mouse x >= button x ? + movzx ebx,word [eax+0] + shl ebx,5 + add ebx,window_data + movzx ecx,word [ebx+0] ; window x start + movzx edx,word [eax+4] ; button x start + add edx,ecx + mov cx,[0xfb0a] + cmp edx,ecx + jg buttonnewcheck + + movzx ebx,word [eax+6] ; button x size + add edx,ebx + cmp ecx,edx + jg buttonnewcheck + + ; mouse y >= button y ? + movzx ebx,word [eax+0] + shl ebx,5 + add ebx,window_data + movzx ecx,word [ebx+4] ; window y start + movzx edx,word [eax+8] ; button y start + add edx,ecx + mov cx,[0xfb0c] + cmp edx,ecx + jg buttonnewcheck + + movzx ebx,word [eax+10] ; button y size + add edx,ebx + cmp ecx,edx + jg buttonnewcheck + + ; mouse on button + + pop edx + pop esi + + mov bx,[eax+0xc] ; button id : bits 16-31 + shl ebx,16 + mov bx,[eax+2] ; button id : bits 00-16 + push ebx + + mov [0xfb44],byte 1 ; no mouse down checks + call find_pressed_button_frames + call negativebutton + + pushad + cbwaitmouseup: + + call checkidle + + call check_mouse_data + call [draw_pointer] + + pushad + call stack_handler + popad + + cmp [0xfb40],byte 0 ; mouse buttons pressed ? + jnz cbwaitmouseup + popad + + call negativebutton + mov [0xfff4],byte 0 ; no mouse background + mov [0xfff5],byte 0 ; draw mouse + mov [0xf500],byte 1 + pop ebx + mov [0xf501],ebx + mov [0xfb44],byte 0 ; mouse down checks + popad + ret + diff --git a/trunk/gui/event.inc b/trunk/gui/event.inc new file mode 100644 index 000000000..30c253f4b --- /dev/null +++ b/trunk/gui/event.inc @@ -0,0 +1,188 @@ +sys_getevent: + + call get_event_for_app + mov [esp+36],eax + ret + + +align 4 + +sys_wait_event_timeout: + + mov ebx,[timer_ticks];[0xfdf0] + add ebx,eax + cmp ebx,[timer_ticks];[0xfdf0] + jna .swfet2 + .swfet1: + call get_event_for_app + test eax,eax + jne .eventoccur_time + call change_task + cmp ebx,[timer_ticks];[0xfdf0] + jg .swfet1 + .swfet2: + xor eax,eax + .eventoccur_time: + mov [esp+36],eax + ret + + +align 4 + +sys_waitforevent: + + call get_event_for_app + test eax,eax + jne eventoccur + newwait: + + call change_task + call get_event_for_app + test eax,eax + je newwait + + eventoccur: + mov [esp+36],eax + ret + + +get_event_for_app: + + pushad + + mov edi,[0x3010] ; WINDOW REDRAW + test [edi],dword 1 + jz no_eventoccur1 + mov edi,[0x3010] + cmp [edi-twdw+31],byte 0 + je no_eventoccur1 + popad + mov eax,1 + ret + no_eventoccur1: + + mov edi,[0x3010] ; KEY IN BUFFER + test [edi],dword 2 + jz no_eventoccur2 + mov ecx, [0x3000] + movzx edx,word [0xC000+ecx*2] + mov eax, [0x3004] + cmp eax,edx + jne no_eventoccur2 + cmp [0xf400],byte 0 + je no_eventoccur2 + popad + mov eax,2 + ret + no_eventoccur2: + + mov edi,[0x3010] ; BUTTON IN BUFFER + test [edi],dword 4 + jz no_eventoccur3 + mov ecx, [0x3000] + movzx edx, word [0xC000+ecx*2] + mov eax, [0x3004] + cmp eax,edx + jnz no_eventoccur3 + cmp [0xf500],byte 0 + je no_eventoccur3 + popad + mov eax,[0xf501] + cmp eax,65535 + je no_event_1 + mov eax,3 + ret + + no_event_1: + mov [window_minimize],1 + mov [0xf500],byte 0 + xor eax, eax + ret + + no_eventoccur3: + + mov edi,[0x3010] ; DESKTOP BACKGROUND REDRAW + test [edi],dword 16 + jz no_eventoccur5 + cmp [0xfff0],byte 2 + jnz no_eventoccur5 + popad + mov eax,5 + ret + no_eventoccur5: + + mov edi,[0x3010] ; mouse event + test [edi],dword 00100000b + jz no_mouse_event + mov edi,[0x3000] + shl edi,8 + test [edi+0x80000+0xA8],dword 00100000b + jz no_mouse_event + and [edi+0x80000+0xA8],dword 0xffffffff-00100000b + popad + mov eax,6 + ret + no_mouse_event: + + mov edi,[0x3010] ; IPC + test [edi],dword 01000000b + jz no_ipc + mov edi,[0x3000] + shl edi,8 + test [edi+0x80000+0xA8],dword 01000000b + jz no_ipc + and [edi+0x80000+0xA8],dword 0xffffffff-01000000b + popad + mov eax,7 + ret + no_ipc: + + + mov edi,[0x3010] ; STACK + test [edi],dword 10000000b + jz no_stack_event + mov edi,[0x3000] + shl edi,8 + test [edi+0x80000+0xA8],dword 10000000b + jz no_stack_event + and [edi+0x80000+0xA8],dword 0xffffffff-10000000b + popad + mov eax,7 + ret + no_stack_event: + + + mov esi,0x2e0000 ; IRQ'S AND DATA + mov ebx,0x00010000 + xor ecx, ecx + irq_event_test: + mov edi,[0x3010] + test [edi],ebx + jz no_irq_event + mov edi,ecx + shl edi,2 + add edi,irq_owner + mov edx,[edi] + mov eax,[0x3010] + mov eax,[eax+0x4] + cmp edx,eax + jne no_irq_event + cmp [esi],dword 0 + jz no_irq_event + mov eax,ecx + add eax,16 + mov [esp+28],eax + popad + ret + no_irq_event: + add esi,0x1000 + shl ebx,1 + inc ecx + cmp ecx,16 + jb irq_event_test + + popad + xor eax, eax + ret + + diff --git a/trunk/gui/font.inc b/trunk/gui/font.inc new file mode 100644 index 000000000..0d47bb64b --- /dev/null +++ b/trunk/gui/font.inc @@ -0,0 +1,225 @@ +align 4 +dtext: + ; eax x & y + ; ebx font ( 0xX0000000 ) & color ( 0x00RRGGBB ) + ; ecx start of text + ; edx length + ; edi 1 force + + test ebx,0x10000000 + jnz dtext2 + + pushad + + mov esi, edx + and esi, 0xff + test esi, esi ; zero length ? + jnz @f + popad + ret + @@: + align 4 + .letnew: + + push eax ecx edx + movzx ebx,ax + shr eax,16 + movzx edx,byte [ecx] + mov ecx,[esp+3*4+32-16] + call drawletter + pop edx ecx eax + + add eax,6*65536 + + inc ecx + dec edx + jnz .letnew + + popad + ret + +align 4 +drawletter: + +; eax x +; ebx y +; ecx color +; edx letter +; esi shl size +; edi force + + pushad + call [disable_mouse] + xor eax, eax + xor ebx, ebx ; 0x37000+eax+ebx*8 + inc esi + align 4 + chc: + + push eax + push ebx + + mov edx,ebx + shl edx,3 + add edx,eax + add edx,0x37000+8 + mov ecx,[esp+32-12+8] + imul ecx,8*10 + add edx,ecx + cmp [edx],byte 'o' + jnz .nopix + mov eax,[esp+4] + mov ebx,[esp+0] + add eax,[esp+32+2*4-4] + add ebx,[esp+32+2*4-16] + mov ecx,[esp+32+2*4-8] + ;;;call [disable_mouse] + call [putpixel] + .nopix: + pop ebx + pop eax + + inc eax + cmp eax,5 ; ebp + jne chc + + xor eax, eax + + inc ebx + cmp ebx,9 ; ebp + jne chc + + popad + ret + + +dtext2: + + ; eax x & y + ; ebx color + ; ecx start of text + ; edx length + ; edi 1 force + + pushad + + mov esi,edx + and esi,0xff + test esi,esi ; zero length ? + jnz @f + popad + ret + @@: + + align 4 + letnew2: + + push eax + push ecx + push edx + movzx ebx,ax + shr eax,16 + movzx edx,byte [ecx] + mov ecx,[esp+3*4+32-16] + call drawletter2 + pop edx + pop ecx + pop eax + + push edx + movzx edx,byte [ecx] + imul edx,10*10 + add edx,0x30000 + cmp [edx+6],byte ' ' + jne nocharadd8 + add eax,8*65536 + jmp charaddok + nocharadd8: + movzx edx,byte [edx+6] + sub edx,47 + shl edx,16 + add eax,edx + charaddok: + pop edx + + inc ecx + dec edx + jnz letnew2 + + popad + ret + +align 4 +drawletter2: + +; eax x +; ebx y +; ecx color +; edx letter +; esi shl size +; edi force + + pushad + call [disable_mouse] + xor eax, eax + xor ebx, ebx ; +eax+ebx*8 + inc esi + + align 4 + chc2: + + push eax + push ebx + +; cmp esi,1 +; je noldiv +; xor edx,edx +; div esi +; push eax +; xor edx,edx +; mov eax,ebx +; div esi +; mov ebx,eax +; pop eax +; noldiv: + + mov edx,ebx + ;shl edx,3 + imul edx,10 + add edx,eax + add edx,0x30000+8+2 + mov ecx,[esp+32-12+8] + ;shl ecx,6 + imul ecx,10*10 + add edx,ecx + cmp [edx],byte 'o' + jnz nopix2 + mov eax,[esp+4] + mov ebx,[esp+0] + add eax,[esp+32+2*4-4] + add ebx,[esp+32+2*4-16] + mov ecx,[esp+32+2*4-8] + ;;;call [disable_mouse] + call [putpixel] + nopix2: + pop ebx + pop eax + + ;mov ebp,7 + ;imul ebp,esi + + inc eax + cmp eax,7 ;ebp + jnz chc2 + + xor eax, eax + + ;mov ebp,9 + ;imul ebp,esi + + inc ebx + cmp ebx,9 ; ebp + jnz chc2 + + popad + ret diff --git a/trunk/gui/mouse.inc b/trunk/gui/mouse.inc new file mode 100644 index 000000000..8c6d18e7b --- /dev/null +++ b/trunk/gui/mouse.inc @@ -0,0 +1,243 @@ +;mouseunder: +; times 16*24 dd 0 +label mouseunder dword at 0x6900 + +iglobal + +mousepointer: +db 0x00,0x00,0x00,0x74,0x74,0x74,0x6e,0x6e,0x6e,0x6f +db 0x6f,0x6f,0x71,0x71,0x71,0x75,0x75,0x75,0x79,0x79 +db 0x79,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63 +db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 +db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0 +db 0xc0,0xc0,0x00,0x00,0x00,0x54,0x54,0x54,0x57,0x57 +db 0x57,0x5f,0x5f,0x5f,0x68,0x68,0x68,0x71,0x71,0x71 +db 0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x47,0x47,0x47,0x50 +db 0x50,0x50,0x5b,0x5b,0x5b,0x67,0x67,0x67,0x70,0x70 +db 0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x3f +db 0x4b,0x4b,0x4b,0x59,0x59,0x59,0x66,0x66,0x66,0x70 +db 0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e +db 0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3a,0x3a +db 0x3a,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66,0x66 +db 0x70,0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e +db 0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x39 +db 0x39,0x39,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66 +db 0x66,0x71,0x71,0x71,0x78,0x78,0x78,0x7c,0x7c,0x7c +db 0x7e,0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0xff +db 0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00 +db 0x39,0x39,0x39,0x4a,0x4a,0x4a,0x5a,0x5a,0x5a,0x68 +db 0x68,0x68,0x72,0x72,0x72,0x79,0x79,0x79,0x7d,0x7d +db 0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00 +db 0x00,0x3c,0x3c,0x3c,0x4e,0x4e,0x4e,0x5e,0x5e,0x5e +db 0x6b,0x6b,0x6b,0x75,0x75,0x75,0x7a,0x7a,0x7a,0x7e +db 0x7e,0x7e,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00 +db 0x00,0x00,0x43,0x43,0x43,0x55,0x55,0x55,0x64,0x64 +db 0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d +db 0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0 +db 0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x4e,0x4e,0x4e,0x5f,0x5f,0x5f,0x6d +db 0x6d,0x6d,0x76,0x76,0x76,0x7c,0x7c,0x7c,0x80,0x80 +db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x14 +db 0x14,0x14,0x1b,0x1b,0x1b,0x29,0x29,0x29,0x3a,0x3a +db 0x3a,0x4c,0x4c,0x4c,0x5d,0x5d,0x5d,0x6c,0x6c,0x6c +db 0x75,0x75,0x75,0x7b,0x7b,0x7b,0x80,0x80,0x80,0xc0 +db 0xc0,0xc0,0x00,0x00,0x00,0x2f,0x2f,0x2f,0x80,0x80 +db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 +db 0x21,0x21,0x21,0x2e,0x2e,0x2e,0x40,0x40,0x40,0x52 +db 0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f,0x77,0x77 +db 0x77,0x7c,0x7c,0x7c,0x80,0x80,0x80,0x00,0x00,0x00 +db 0x47,0x47,0x47,0x3b,0x3b,0x3b,0x80,0x80,0x80,0xff +db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x25,0x25 +db 0x25,0x30,0x30,0x30,0x42,0x42,0x42,0x54,0x54,0x54 +db 0x64,0x64,0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d +db 0x7d,0x7d,0x00,0x00,0x00,0x62,0x62,0x62,0x52,0x52 +db 0x52,0x4a,0x4a,0x4a,0x43,0x43,0x43,0x80,0x80,0x80 +db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x33 +db 0x33,0x33,0x42,0x42,0x42,0x54,0x54,0x54,0x64,0x64 +db 0x64,0x71,0x71,0x71,0x79,0x79,0x79,0x7d,0x7d,0x7d +db 0x72,0x72,0x72,0x6b,0x6b,0x6b,0x5f,0x5f,0x5f,0x5a +db 0x5a,0x5a,0x54,0x54,0x54,0x80,0x80,0x80,0xff,0xff +db 0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x35,0x35,0x35 +db 0x41,0x41,0x41,0x53,0x53,0x53,0x63,0x63,0x63,0x70 +db 0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d,0x77,0x77 +db 0x77,0x73,0x73,0x73,0x6c,0x6c,0x6c,0x68,0x68,0x68 +db 0x62,0x62,0x62,0x5a,0x5a,0x5a,0x80,0x80,0x80,0xff +db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x41,0x41 +db 0x41,0x52,0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f +db 0x78,0x78,0x78,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x79 +db 0x79,0x79,0x74,0x74,0x74,0x72,0x72,0x72,0x6e,0x6e +db 0x6e,0x66,0x66,0x66,0x80,0x80,0x80,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x44,0x44,0x44,0x52 +db 0x52,0x52,0x62,0x62,0x62,0x6e,0x6e,0x6e,0x77,0x77 +db 0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7c,0x7c,0x7c +db 0x7a,0x7a,0x7a,0x79,0x79,0x79,0x75,0x75,0x75,0x6f +db 0x6f,0x6f,0x65,0x65,0x65,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x48,0x48,0x48,0x4b,0x4b,0x4b,0x56,0x56,0x56 +db 0x65,0x65,0x65,0x70,0x70,0x70,0x78,0x78,0x78,0x7d +db 0x7d,0x7d,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e +db 0x7e,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76,0x76 +db 0x6f,0x6f,0x6f,0x65,0x65,0x65,0x5c,0x5c,0x5c,0x56 +db 0x56,0x56,0x58,0x58,0x58,0x60,0x60,0x60,0x6b,0x6b +db 0x6b,0x73,0x73,0x73,0x7a,0x7a,0x7a,0x7d,0x7d,0x7d +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f +db 0x7f,0x7f,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76 +db 0x76,0x70,0x70,0x70,0x6a,0x6a,0x6a,0x66,0x66,0x66 +db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 +db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x77 +db 0x77,0x77,0x73,0x73,0x73,0x71,0x71,0x71,0x71,0x71 +db 0x71,0x74,0x74,0x74,0x78,0x78,0x78,0x7b,0x7b,0x7b +db 0x7d,0x7d,0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c +db 0x7a,0x7a,0x7a,0x78,0x78,0x78,0x78,0x78,0x78,0x7a +db 0x7a,0x7a,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7f,0x7f +db 0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,0x7e +db 0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e +db 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 +db 0x80,0x80 + +mousepointer1: +db 0xff,0xff,0xff,0x06,0x06,0x06,0x0a,0x0a +db 0x0a,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x19,0x16 +db 0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2e,0x2e,0x2e +db 0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f +db 0x3f,0x29,0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x47 +db 0x47,0x47,0x2c,0x2c,0x2c,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0x47,0x47,0x47,0x29,0x29,0x29 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0x40,0x40,0x40,0x23,0x23 +db 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xaa,0xaa,0xaa,0x9f,0x9f,0x9f,0x8c,0x8c,0x8c +db 0x70,0x70,0x70,0x4f,0x4f,0x4f,0x30,0x30,0x30,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x8f,0x8f +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0x9c,0x9c,0x9c,0x87,0x87,0x87,0x6c,0x6c +db 0x6c,0x4f,0x4f,0x4f,0x32,0x32,0x32,0x19,0x19,0x19 +db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +db 0xff,0xff,0x69,0x69,0x69,0x84,0x84,0x84,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0x92,0x92,0x92,0x79,0x79,0x79,0x59,0x59,0x59,0x3c +db 0x3c,0x3c,0x24,0x24,0x24,0x11,0x11,0x11,0x00,0x00 +db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x37,0x37,0x37 +db 0x5d,0x5d,0x5d,0x70,0x70,0x70,0x76,0x76,0x76,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0x75,0x75,0x75,0x51,0x51,0x51,0x31,0x31,0x31 +db 0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x16,0x16,0x16,0x2d,0x2d,0x2d,0x49,0x49 +db 0x49,0x53,0x53,0x53,0x54,0x54,0x54,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x78 +db 0x78,0x78,0x54,0x54,0x54,0x30,0x30,0x30,0x16,0x16 +db 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x0f,0x0f,0x0f,0x1f,0x1f,0x1f,0x30,0x30,0x30,0x33 +db 0x33,0x33,0x33,0x33,0x33,0x3b,0x3b,0x3b,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0x62,0x62,0x62,0x3b,0x3b,0x3b,0x1c,0x1c,0x1c,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08 +db 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x24,0x24,0x24,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6e,0x6e +db 0x6e,0x48,0x48,0x48,0x25,0x25,0x25,0x0e,0x0e,0x0e +db 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00 +db 0x00,0x00,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x29,0x29,0x29,0xff,0xff,0xff +db 0xff,0xff,0xff,0x7c,0x7c,0x7c,0x71,0x71,0x71,0x50 +db 0x50,0x50,0x2b,0x2b,0x2b,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x02,0x02,0x02,0x04,0x04,0x04,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x56,0x56 +db 0x56,0x69,0x69,0x69,0x64,0x64,0x64,0x4a,0x4a,0x4a +db 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x05,0x05,0x05 +db 0x00,0x00,0x00,0x21,0x21,0x21,0x39,0x39,0x39,0x49 +db 0x49,0x49,0x48,0x48,0x48,0x35,0x35,0x35,0x1d,0x1d +db 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x1d,0x1d,0x1d,0x27,0x27,0x27 +db 0x27,0x27,0x27,0x1d,0x1d,0x1d,0x0f,0x0f,0x0f,0x06 +db 0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00 + +endg \ No newline at end of file diff --git a/trunk/gui/skincode.inc b/trunk/gui/skincode.inc new file mode 100644 index 000000000..4acee6eb2 --- /dev/null +++ b/trunk/gui/skincode.inc @@ -0,0 +1,388 @@ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; WINDOW SKIN for MenuetOS ;; +;; ;; +;; entryway@bkg.lt ;; +;; ;; +;; Bugfixes & upgrades by ;; +;; Samuel Rodriguez Perez ;; +;; Xeoda@ciberirmandade.org ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +include "SKINDATA.INC" + +virtual at 0 + bmp_header: + .type rw 1 ; "BM" signature + .filesize rd 1 ; size of the file + .reserved rd 1 ; zero + .offbits rd 1 ; pointer to image data + ;---------------- + .headsize rd 1 ; usually 40 bytes for image header + .width rd 1 + .height rd 1 + .planes rw 1 ; usually 1 + .bitcount rw 1 ; currently 24 bits/pixel (0x18) + .compress rd 1 ; zero + .sizeimage rd 1 ; x*y*(bitcount/8) + .unused rd 4 ; these bits aren't used by MeOS + bmp_data: +end virtual + +virtual at 0x778000 + _bmp_bpl dd ? ; bytes per line + _bmp_dpl dd ? ; dwords per line + _bmp_zb dd ? ; bytes filled by zeroes at the end of a scanline + align 32 + raw_data: +end virtual + +bmp2raw: +; esi = to bmp data (source) +; edi = to raw data (destination) + cmp [esi+bmp_header.type],'BM' ; check if bmp file is really loaded + jne .finish + mov edx,esi + + mov eax,[edx+bmp_header.width] + imul eax,3 + push eax + test eax,11b + jz @f + add eax,4 + @@: + shr eax,2 + mov [_bmp_dpl],eax + shl eax,2 + mov [_bmp_bpl],eax + pop ebx + sub eax,ebx + mov [_bmp_zb],eax + + add esi,bmp_data + mov eax,[_bmp_bpl] + imul eax,[edx+bmp_header.height] + add esi,eax + mov ebx,[edx+bmp_header.height] ; ebx = y + cld + .y_begin: + sub esi,[_bmp_bpl] + push esi + mov ecx,[_bmp_dpl] + rep movsd + pop esi + sub edi,[_bmp_zb] + dec ebx + jne .y_begin + +.finish: + ret + + +; BMP support by Ivan Poddubny +; 1) load LEFT.BMP +; a) _skinleftw = bmp_width +; b) _skinleft = 0 +; c) _refleft = 0x778000 +; d) convert +; 2) load BASE.BMP +; a) _skinbasew = bmp_width +; b) _skinbase = _skinleftw +; c) _refbase = _refleft+sizeof(left_raw_converted) +; d) convert +; 3) load OPER.BMP +; a) _skinoper = minus width from bmp file +; b) _skinoperw = width from bmp file +; c) _refoper = _refbase+sizeof(oper_raw_converted) +; d) convert +; 4) set height + +load_bmp_file: +; eax = pointer to filename + mov ebx, 1 + or ecx, -1 + mov edx, 0x90000 + mov esi, 12 + call fileread + ret + + +load_default_skin: + pushad + mov eax, _fileleft + call load_bmp_file + mov eax, [0x90000+bmp_header.width] + mov [_skinleftw], eax + mov [_skinleft], 0 + mov edi, raw_data + mov [_refleft], edi + mov esi, 0x90000 + call bmp2raw + mov eax, [_bmp_bpl] + imul eax, [0x90000+bmp_header.height] + push eax + + mov eax, _filebase + call load_bmp_file + mov eax, [0x90000+bmp_header.width] + mov [_skinbasew], eax + mov eax, [_skinleftw] + mov [_skinbase], eax + pop eax + add eax, [_refleft] + ; align to 32-byte boundary + test eax, 11111b + jz @f + shr eax, 5 + inc eax + shl eax, 5 + @@: + ; save base address + mov [_refbase], eax + ; convert + mov edi, eax + mov esi, 0x90000 + call bmp2raw + mov eax, [_bmp_bpl] + imul eax, [0x90000+bmp_header.height] + push eax + + mov eax, _fileoper + call load_bmp_file + mov eax, [0x90000+bmp_header.width] + mov [_skinoperw], eax + neg eax + mov [_skinoper], eax + pop eax + add eax, [_refbase] + ; align to 32-byte boundary + test eax, 11111b + jz @f + shr eax, 5 + inc eax + shl eax, 5 + @@: + mov [_refoper], eax + mov edi, eax + mov esi, 0x90000 + call bmp2raw + + +; mov eax, [0x90000+bmp_header.height] +; imul eax, [0x90000+bmp_header.width] +; imul eax, 3 +; add eax, raw_data ; now eax points to the last line of image + +; mov ecx, [eax] +; mov [_coloroutborder], ecx +; mov [_colorborder], ecx +; sub eax, 2*3 +; mov ecx, [eax] +; mov [_colorframe], ecx + + + mov eax, [0x90000+bmp_header.height] + mov [_skinh], eax + popad + ret + + + +drawwindow_IV: + + pusha + + push edx + + mov edi,[esp] ; RECTANGLE + + mov eax,[edi+0] + shl eax,16 + mov ax,[edi+0] + add ax,[edi+8] + mov ebx,[edi+4] + shl ebx,16 + mov bx,[edi+4] + add bx,[edi+12] +; mov esi,[edi+24] +; shr esi,1 +; and esi,0x007f7f7f + mov esi,[_coloroutborder] + call draw_rectangle + mov ecx,3 + _dw3l: + add eax,1*65536-1 + add ebx,1*65536-1 + test ax,ax + js no_skin_add_button + test bx,bx + js no_skin_add_button + mov esi,[_colorframe] ;[edi+24] + call draw_rectangle + dec ecx + jnz _dw3l + mov esi,[_colorborder] + add eax,1*65536-1 + add ebx,1*65536-1 + test ax,ax + js no_skin_add_button + test bx,bx + js no_skin_add_button + call draw_rectangle + + mov esi,[esp] + mov eax,[esi+8] ; window width + mov edx,[_skinleft] + shl edx,16 + mov ecx,[_skinleftw] + shl ecx,16 + add ecx,[_skinh] + mov ebx,[_refleft] + call sys_putimage + + mov esi,[esp] + mov eax,[esi+8] + sub eax,[_skinleftw] + sub eax,[_skinoperw] + cmp eax,[_skinbase] + jng non_base + xor edx,edx + mov ebx,[_skinbasew] + div ebx + + inc eax + + mov ebx,[_refbase] + mov ecx,[_skinbasew] + shl ecx,16 + add ecx,[_skinh] + mov edx,[_skinbase] + sub edx,[_skinbasew] + shl edx,16 + baseskinloop: + shr edx,16 + add edx,[_skinbasew] + shl edx,16 + + push eax ebx ecx edx + call sys_putimage + pop edx ecx ebx eax + + dec eax + jnz baseskinloop + non_base: + + mov esi,[esp] + mov edx,[esi+8] + sub edx,[_skinoperw] + inc edx + shl edx,16 + mov ebx,[_refoper] + mov ecx,[_skinoperw] + shl ecx,16 + add ecx,[_skinh] + call sys_putimage + + mov esi,[esp] + + mov edx,[esi+04] ; WORK AREA + add edx,21+5 + mov ebx,[esi+04] + add ebx,[esi+12] + cmp edx,ebx + jg _noinside2 + mov eax,5 + mov ebx,[_skinh] + mov ecx,[esi+8] + mov edx,[esi+12] + sub ecx,4 + sub edx,4 + mov edi,[esi+16] + call [drawbar] + _noinside2: + + mov edi,[0xfe88] + movzx eax,word [edi] + cmp eax,1000 + jge no_skin_add_button + inc eax + mov [edi],ax + + shl eax,4 + add eax,edi + + mov bx,[0x3000] + mov [eax],bx + + add eax,2 ; save button id number + mov bx,1 + mov [eax],bx + add eax,2 ; x start + mov ebx,[esp] + mov ebx,[ebx+8] + cmp [_buttonCx],0 + jg _bCx_at_right + mov ebx,[_buttonCw] ; ebx will be 0 in next instruction + _bCx_at_right: + sub ebx,[_buttonCw] + sub ebx,[_buttonCx] + mov [eax],bx + add eax,2 ; x size + mov ebx,[_buttonCw] + mov [eax],bx + add eax,2 ; y start + mov ebx,[_buttonCy] + mov [eax],bx + add eax,2 ; y size + mov ebx,[_buttonCh] + mov [eax],bx + +;* minimize button + mov edi,[0xfe88] + movzx eax,word [edi] + cmp eax,1000 + jge no_skin_add_button + inc eax + mov [edi],ax + + shl eax,4 + add eax,edi + + mov bx,[0x3000] + mov [eax],bx + + add eax,2 ; save button id number + mov bx,65535 ;999 + mov [eax],bx + add eax,2 ; x start + mov ebx,[esp] + mov ebx,[ebx+8] + cmp [_buttonMx],0 + jg _bMx_at_right + mov ebx,[_buttonMw] ; ebx will be 0 in next instruction + _bMx_at_right: + sub ebx,[_buttonMw] + sub ebx,[_buttonMx] + mov [eax],bx + add eax,2 ; x size + mov ebx,[_buttonMw] + mov [eax],bx + add eax,2 ; y start + mov ebx,[_buttonMy] + mov [eax],bx + add eax,2 ; y size + mov ebx,[_buttonMh] + mov [eax],bx +;* minimize button + + no_skin_add_button: + + add esp,4 + popa + ret + + diff --git a/trunk/gui/skindata.inc b/trunk/gui/skindata.inc new file mode 100644 index 000000000..a76961c12 --- /dev/null +++ b/trunk/gui/skindata.inc @@ -0,0 +1,44 @@ +; +; WINDOW SKIN for MenuetOS +; ivan-yar@bk.ru +; + +iglobal + _skinh dd 22 + + _skinleftw dd 10 + + _skinbase dd 10 + _skinbasew dd 8 + + _skinoper dd -39 ;-21 + _skinoperw dd 39 ;21 + + _buttonCx dd 5 ; close + _buttonCy dd 2 + _buttonCw dd 15 + _buttonCh dd 17 + + _buttonMx dd 23 ; minimize + _buttonMy dd 2 + _buttonMw dd 15 + _buttonMh dd 17 + + + _colorframe dd 0x3a6cb6 ;0x586E93 + _colorborder dd 0x00081D + _coloroutborder dd 0x00081D + + _fileleft db 'LEFT.BMP ' + _filebase db 'BASE.BMP ' + _fileoper db 'OPER.BMP ' +endg + +uglobal + _refoper dd 0 + _refbase dd 0 + _refleft dd 0 + _skinleft dd 0 + _skinwinw dd 0 +endg + diff --git a/trunk/gui/window.inc b/trunk/gui/window.inc new file mode 100644 index 000000000..9a17bcb99 --- /dev/null +++ b/trunk/gui/window.inc @@ -0,0 +1,1613 @@ +setwindowdefaults: + pushad + + xor eax,eax + mov ecx,0xc000 + @@: + inc eax + add ecx,2 + mov [ecx+0x000],ax ; process no + mov [ecx+0x400],ax ; positions in stack + cmp ecx,0xc400-2 ; the more high, the more surface + jnz @b + + popad + ret + + + +; eax = cx +; ebx = cy +; ecx = ex +; edx = ey +; шфх : яхЁхсЁрЄ№ тёх юъэр, эрўшэр  ё ёрьюую эшцэхую, +; ш фы  ърцфюую т√чтрЄ№ setscreen +align 4 +calculatescreen: + pushad + cli + + mov esi, 1 + xor eax, eax + xor ebx, ebx + mov ecx, [0xFE00] + mov edx, [0xFE04] + call setscreen + + mov ebp, [0x3004] ; number of processes + cmp ebp, 1 + jbe .finish + align 4 + .new_wnd: + movzx edi, word [0xC400 + esi * 2] + shl edi, 5 + add edi, window_data + mov eax, [edi+0] + mov ebx, [edi+4] + mov ecx, [edi+8] + test ecx, ecx + jz .not_wnd + add ecx, eax + mov edx, [edi+12] + add edx, ebx + push esi + movzx esi, word [0xC400 + esi * 2] + call setscreen + pop esi + .not_wnd: + inc esi + dec ebp + jnz .new_wnd + .finish: + sti + popad +ret + + + +virtual at esp + ff_xsz dd ? + ff_ysz dd ? + ff_scale dd ? +end virtual + +align 4 +; ЁхчхЁтшЁєхЄ ьхёЄю яюф юъэю чрфрээюую яЁюЎхёёр +setscreen: +; eax x start +; ebx y start +; ecx x end +; edx y end +; esi process number +pushad + mov edi, esi ;;;word [esi*2+0xc400] + shl edi, 8 + add edi, 0x80000+0x80 ; address of random shaped window area + cmp [edi], dword 0 + jne .free_form + + ; get x&y size + sub ecx, eax + sub edx, ebx + inc ecx + inc edx + + ; get WinMap start + mov edi, [0xFE00] ; screen_sx + inc edi + imul edi, ebx + add edi, eax + add edi, WinMapAddress + + .new_y: + push ecx ; sx + push edx + + mov edx, esi + align 4 + .new_x: + mov byte [edi], dl + inc edi + dec ecx + jnz .new_x + + pop edx + pop ecx + add edi, [0xFE00] + inc edi + sub edi, ecx + dec edx + jnz .new_y + popad + ret + .read_byte: + ;eax - address + ;esi - slot + push eax + push ebx + push ecx + push edx + mov edx,eax + mov eax,esi + lea ebx,[esp+12] + mov ecx,1 + call read_process_memory + pop edx + pop ecx + pop ebx + pop eax + ret + .free_form: + + ; for (y=0; y <= x_size; y++) + ; for (x=0; x <= x_size; x++) + ; if (shape[coord(x,y,scale)]==1) + ; set_pixel(x, y, process_number); + + sub ecx, eax + sub edx, ebx + inc ecx + inc edx + + push dword [edi+4] ; push scale first -> for loop + + ; get WinMap start -> ebp + push eax + mov eax, [0xFE00] ; screen_sx + inc eax + imul eax, ebx ;ebx + add eax, [esp] ;eax + add eax, WinMapAddress + mov ebp, eax + + mov edi, [edi] +; mov eax, esi +; shl eax, 5 +; add edi, [eax+0x3000+0x10] + pop eax + + ; eax = x_start + ; ebx = y_start + ; ecx = x_size + ; edx = y_size + ; esi = process_number + ; edi = &shape + ; [scale] + push edx ecx ;ebx eax + xor ebx, ebx + align 4 + .ff_new_y: + xor edx, edx + align 4 + .ff_new_x: + ; -- body -- + mov ecx, [ff_scale] + mov eax, [ff_xsz] + shr eax, cl + push ebx edx + shr ebx, cl + shr edx, cl + imul eax, ebx + add eax, edx + pop edx ebx + add eax, edi ;[ff_shape] + call .read_byte +; cmp byte [eax], 1 +; jne @f + test al,al + jz @f + mov eax, esi ; [ff_proc] + mov [ebp], al + @@: + ; -- end body -- + inc ebp + inc edx + cmp edx, [ff_xsz] + jb .ff_new_x + sub ebp, [ff_xsz] + add ebp, [0xFE00] ; screen.x + inc ebp + inc ebx + cmp ebx, [ff_ysz] + jb .ff_new_y + + pop ecx edx ; eax ebx first + add esp, 4 +popad +ret + + +display_settings: + +; eax = 0 ; DISPLAY redraw +; ebx = 0 ; all +; +; eax = 1 ; BUTTON type +; ebx = 0 ; flat +; ebx = 1 ; 3D +; eax = 2 ; set WINDOW colours +; ebx = pointer to table +; ecx = number of bytes define +; eax = 3 ; get WINDOW colours +; ebx = pointer to table +; ecx = number of bytes wanted +; eax = 4 ; get skin height +; input : nothing +; output : eax = skin height in pixel + + + pushad + + test eax, eax ; redraw display + jnz dspl0 + test ebx, ebx + jnz dspl0 + cmp [windowtypechanged],dword 1 + jne dspl00 + mov [windowtypechanged],dword 0 + mov [dlx],dword 0 + mov [dly],dword 0 + mov eax,[0xfe00] + mov [dlxe],eax + mov eax,[0xfe04] + mov [dlye],eax + mov eax,window_data + call redrawscreen + dspl00: + popad + ret + dspl0: + + cmp eax,1 ; button type + jne dspl1 + and ebx,1 + cmp ebx,[buttontype] + je dspl9 + mov [buttontype],ebx + mov [windowtypechanged],dword 1 + dspl9: + popad + ret + dspl1: + + cmp eax,2 ; set common window colours + jne no_com_colours + mov [windowtypechanged],dword 1 + mov esi,[0x3010] + add esi,0x10 + add ebx,[esi] + mov esi,ebx + mov edi,common_colours + and ecx,127 + cld + rep movsb + popad + ret + no_com_colours: + + cmp eax,3 ; get common window colours + jne no_get_com + mov esi,[0x3010] + add esi,0x10 + add ebx,[esi] + mov edi,ebx + mov esi,common_colours + and ecx,127 + cld + rep movsb + popad + ret + no_get_com: + + cmp eax,4 ; get skin height + jne no_skin_height + popad + mov eax,[_skinh] + mov [esp+36],eax + ret + no_skin_height: + + popad + ret + +uglobal + common_colours: + times 128 db 0x0 +endg + +check_window_move_request: + + pushad + + mov edi,[window_move_pr] ; requestor process base + + cmp edi,0 + je window_move_return + + shl edi,5 + add edi,window_data + + push dword [edi+0] ; save old coordinates + push dword [edi+4] + push dword [edi+8] + push dword [edi+12] + + mov eax,[window_move_eax] + mov ebx,[window_move_ebx] + mov ecx,[window_move_ecx] + mov edx,[window_move_edx] + + cmp eax,-1 ; set new position and size + je no_x_reposition + mov [edi+0],eax + no_x_reposition: + cmp ebx,-1 + je no_y_reposition + mov [edi+4],ebx + no_y_reposition: + cmp ecx,-1 + je no_x_resizing + mov [edi+8],ecx + no_x_resizing: + cmp edx,-1 + je no_y_resizing + mov [edi+12],edx + no_y_resizing: + + call check_window_position + + pushad ; save for window fullscreen/resize + mov esi,edi + sub edi,window_data + shr edi,5 + shl edi,8 + add edi,0x80000+0x90 + mov ecx,4 + cld + rep movsd + popad + + pushad ; calculcate screen at new position + mov eax,[edi+00] + mov ebx,[edi+04] + mov ecx,[edi+8] + mov edx,[edi+12] + add ecx,eax + add edx,ebx + call calculatescreen + popad + + pop edx ; calculcate screen at old position + pop ecx + pop ebx + pop eax + add ecx,eax + add edx,ebx + mov [dlx],eax ; save for drawlimits + mov [dly],ebx + mov [dlxe],ecx + mov [dlye],edx + call calculatescreen + + mov [edi+31],byte 1 ; flag the process as redraw + + mov eax,edi ; redraw screen at old position + xor esi,esi + call redrawscreen + + mov [0xfff5],byte 0 ; mouse pointer + mov [0xfff4],byte 0 ; no mouse under + mov [0xfb44],byte 0 ; react to mouse up/down + + mov ecx,10 ; wait 1/10 second + wmrl3: + call check_mouse_data + call [draw_pointer] + mov eax,1 + call delay_hs + loop wmrl3 + + mov [window_move_pr],0 + + window_move_return: + + popad + + ret + + + + +check_window_position: + + pushad ; window inside screen ? + + movzx eax,word [edi+0] + movzx ebx,word [edi+4] + movzx ecx,word [edi+8] + movzx edx,word [edi+12] + + mov esi,ecx ; check x pos + add esi,eax + cmp esi,[0xfe00] + jbe x_pos_ok + mov [edi+0],dword 0 + xor eax, eax + x_pos_ok: + + mov esi,edx ; check y pos + add esi,ebx + cmp esi,[0xfe04] + jbe y_pos_ok + mov [edi+4],dword 0 + mov ebx,0 + y_pos_ok: + + mov esi,ecx ; check x size + add esi,eax + cmp esi,[0xfe00] + jbe x_size_ok + mov ecx,[0xfe00] + mov [edi+8],ecx + x_size_ok: + + mov esi,edx ; check y size + add esi,ebx + cmp esi,[0xfe04] + jbe y_size_ok + mov edx,[0xfe04] + mov [edi+12],edx + y_size_ok: + + popad + + ret + + +uglobal + new_window_starting dd 0 +endg + + +sys_window_mouse: + + push eax + + mov eax,[timer_ticks] ;[0xfdf0] + cmp [new_window_starting],eax + jb swml1 + + mov [0xfff4],byte 0 ; no mouse background + mov [0xfff5],byte 0 ; draw mouse + + mov [new_window_starting],eax + + swml1: + + pop eax + + ret + +drawwindow_I: + + pushad + + mov esi,[edx+24] ; rectangle + mov eax,[edx+0] + shl eax,16 + add eax,[edx+0] + add eax,[edx+8] + mov ebx,[edx+04] + shl ebx,16 + add ebx,[edx+4] + add ebx,[edx+12] + call draw_rectangle + + mov ecx,[edx+20] ; grab bar + push ecx + mov esi,edx + mov edx,[esi+04] + add edx,1 + mov ebx,[esi+04] + add ebx,25 + mov eax,[esi+04] + add eax,[esi+12] + cmp ebx,eax + jb wdsizeok + mov ebx,eax + wdsizeok: + push ebx + drwi: + mov ebx,edx + shl ebx,16 + add ebx,edx + mov eax,[esi+00] + inc eax + shl eax,16 + add eax,[esi+00] + add eax,[esi+8] + sub eax,1 + push edx + mov edx,0x80000000 + mov ecx,[esi+20] + and ecx,edx + cmp ecx,edx + jnz nofa + mov ecx,[esi+20] + sub ecx,0x00040404 + mov [esi+20],ecx + and ecx,0x00ffffff + jmp faj + nofa: + mov ecx,[esi+20] + and ecx,0x00ffffff + faj: + pop edx + mov edi,0 + call [draw_line] + inc edx + cmp edx,[esp] + jb drwi + add esp,4 + pop ecx + mov [esi+20],ecx + + mov edx,[esi+04] ; inside work area + add edx,21+5 + mov ebx,[esi+04] + add ebx,[esi+12] + cmp edx,ebx + jg noinside + mov eax,1 + mov ebx,21 + mov ecx,[esi+8] + mov edx,[esi+12] + mov edi,[esi+16] + call [drawbar] + noinside: + + popad + + ret + + +draw_rectangle: + +r_eax equ [esp+28] ; x start +r_ax equ [esp+30] ; x end +r_ebx equ [esp+16] ; y start +r_bx equ [esp+18] ; y end +;esi ; color + + pushad + + mov ecx,esi ; yb,xb -> yb,xe + ;<<< 14.11.2004 Ivan Poddubny +; mov eax,r_eax +; shl eax,16 +; mov ax,r_ax + mov eax, r_eax + rol eax, 16 + ;>>> 14.11.2004 Ivan Poddubny + mov ebx,r_ebx + shl ebx,16 + mov bx,r_ebx + xor edi, edi + call [draw_line] + + mov ebx,r_bx ; ye,xb -> ye,xe + shl ebx,16 + mov bx,r_bx + call [draw_line] + + mov ecx,esi ; ya,xa -> ye,xa + mov eax,r_eax + shl eax,16 + mov ax,r_eax + mov ebx,r_ebx + shl ebx,16 + mov bx,r_bx + mov edi,0 + call [draw_line] + + mov eax,r_ax ; ya,xe -> ye,xe + shl eax,16 + mov ax,r_ax + call [draw_line] + + popad + ret + + +drawwindow_III: + + pushad + + mov edi,edx ; RECTANGLE + mov eax,[edi+0] + shl eax,16 + mov ax,[edi+0] + add ax,[edi+8] + mov ebx,[edi+4] + shl ebx,16 + mov bx,[edi+4] + add bx,[edi+12] + mov esi,[edi+24] + shr esi,1 + and esi,0x007f7f7f + push esi + call draw_rectangle + mov ecx,3 + dw3l: + add eax,1*65536-1 + add ebx,1*65536-1 + mov esi,[edi+24] + call draw_rectangle + dec ecx + jnz dw3l + pop esi + add eax,1*65536-1 + add ebx,1*65536-1 + call draw_rectangle + + mov ecx,[edx+20] ; GRAB BAR + push ecx + mov esi,edx + mov edx,[esi+04] + add edx,4 + mov ebx,[esi+04] + add ebx,20 + mov eax,[esi+04] + add eax,[esi+12] + cmp ebx,eax + jb wdsizeok2 + mov ebx,eax + wdsizeok2: + push ebx + drwi2: + mov ebx,edx + shl ebx,16 + add ebx,edx + mov eax,[esi+00] + shl eax,16 + add eax,[esi+00] + add eax,[esi+8] + add eax,4*65536-4 + mov ecx,[esi+20] + test ecx,0x40000000 + jz nofa3 + add ecx,0x040404 + nofa3: + test ecx,0x80000000 + jz nofa2 + sub ecx,0x040404 + nofa2: + mov [esi+20],ecx + and ecx,0xffffff + xor edi, edi + call [draw_line] + inc edx + cmp edx,[esp] + jb drwi2 + add esp,4 + pop ecx + mov [esi+20],ecx + + mov edx,[esi+04] ; WORK AREA + add edx,21+5 + mov ebx,[esi+04] + add ebx,[esi+12] + cmp edx,ebx + jg noinside2 + mov eax,5 + mov ebx,20 + mov ecx,[esi+8] + mov edx,[esi+12] + sub ecx,4 + sub edx,4 + mov edi,[esi+16] + call [drawbar] + noinside2: + + popad + + ret + + + +; activate window +align 4 +windowactivate: + + ; esi = abs mem position in stack 0xC400+ + + pushad + + push esi + movzx eax, word [esi] ; ax <- process no + movzx eax, word [0xC000+eax*2] ; ax <- position in window stack + + xor esi, esi ; drop others + waloop: + cmp esi, dword [0x3004] + jae wacont + inc esi + lea edi, [0xC000 + esi*2] + mov bx, [edi] ; position of the current process + cmp bx, ax + jbe @f + dec bx ; upper? => drop! + mov [edi], bx + @@: + jmp waloop + wacont: + ; set to no 1 + pop esi ; esi = pointer at 0xC400 + + movzx eax, word [esi] + mov bx, [0x3004] ; number of processes + mov [0xC000+eax*2], bx ; this is the last (and the upper) + +;* start code - get active process (4) - Mario79 + mov [active_process],eax +;* end code - get active process (4) - Mario79 + + ; update on screen -window stack + xor esi, esi + waloop2: + mov edi, [0x3004] + cmp esi, edi + jae wacont2 + inc esi + movzx ebx, word [esi*2 + 0xC000] + mov [ebx*2 + 0xC400], si + jmp waloop2 + wacont2: + + mov [0xf400], byte 0 ; empty keyboard buffer + mov [0xf500], byte 0 ; empty button buffer + + popad + ret + + +; check if window is necessary to draw + +checkwindowdraw: + + ; edi = position in window_data+ + + mov esi, edi + sub esi, window_data + shr esi, 5 + + ; esi = process number + +; + movzx eax, word [0xC000 + esi * 2] ; get value of the curr process + lea esi, [0xC400 + eax * 2] ; get address of this process at 0xC400 +; + + push esi + + .new_check: + + pop esi + add esi, 2 + push esi + + mov eax, [0x3004] + lea eax, word [0xC400 + eax * 2] ; number of the upper window + + cmp esi, eax + ja .all_wnds_to_top + + movzx eax, word [esi] + shl eax, 5 + add eax, window_data + mov esi, eax + + mov ebx, [edi+4] + mov edx, [edi+12] + add edx, ebx + + mov ecx, [esi+4] ; y check + cmp ecx, edx + jae .new_check + mov eax, [esi+12] + add ecx, eax + cmp ebx, ecx + ja .new_check + + mov eax, [edi+0] + mov ecx, [edi+8] + add ecx, eax + + mov edx, [esi+0] ; x check + cmp edx, ecx + jae .new_check + mov ecx, [esi+8] + add edx, ecx + cmp eax, edx + ja .new_check + + pop esi + mov ecx,1 ; overlap some window + ret + + .all_wnds_to_top: + + pop esi + + xor ecx, ecx ; passed all windows to top + ret + + + + +waredraw: ; if redraw necessary at activate + + pushad + + call checkwindowdraw ; draw window on activation ? + test ecx, ecx + jz .do_not_draw + + popad + mov [0xfb44], byte 1 ; do draw mouse + call windowactivate + + ; update screen info + pushad + mov edi, [0x3004] ; the last process (number) + movzx esi, word [0xC400 + edi * 2] + shl esi, 5 + add esi, window_data + + ; coordinates of the upper window + mov eax, [esi+00] ; cx + mov ebx, [esi+04] ; cy + mov ecx, [esi+08] ; sx + mov edx, [esi+12] ; sy + + add ecx, eax ; ecx = x_end + add edx, ebx ; edx = y_end + + mov edi, [0x3004] + movzx esi, word [0xC400 + edi * 2] + shl esi, 5 + movzx esi, byte [esi + 0x3000 + 0xE] + call setscreen ;;;calculatescreen ; setscreen + popad + + cmp [0xff01], dword 1 ; if > 1 then activate process + jbe .not_activate + +;;; mov eax, 10 ; wait for putimages to finish +;;; call delay_hs + + mov [edi+31],byte 1 ; redraw flag for app + mov [0xfb44],byte 0 ; mouse down checks + + ret + + .not_activate: + +; mov eax,5 ; wait for putimages to finish +; call delay_hs + + mov [edi+31],byte 1 ; redraw flag for app + + mov ecx, 25 ;100 + .waitflagdown: + dec ecx + jz .nowait + mov eax, 2 + call delay_hs + cmp [edi+31], byte 0 ; wait flag to drop + jnz .waitflagdown + .nowait: + +; mov ecx,10 +; .wait: +; mov eax,1 ; wait for draw to finish +; call delay_hs +; loop .wait + + mov [0xfb44],byte 0 + + ret + + .do_not_draw: + + popad + + call windowactivate + mov [0xfb44],byte 0 ; mouse down checks + mov [0xfff4],byte 0 ; no mouse background + mov [0xfff5],byte 0 ; draw mouse + ret + + +iglobal + window_moving db 'K : Window - move/resize',13,10,0 + window_moved db 'K : Window - done',13,10,0 +endg + +; check window touch +align 4 +checkwindows: + pushad + + cmp [0xff01],dword 1 ; activate request from app ? + jbe .no_activate_request + mov edi,[0xff01] ; process number + shl edi,5 + add edi,window_data + mov ebx,[0xff01] + movzx esi, word [0xC000 + ebx * 2] + lea esi, [0xC400 + esi * 2] + call waredraw + +;* start code - get active process (2) - Mario79 + mov eax,[0xff01] + mov [active_process],eax +;* end code - get active process (2) - Mario79 + + mov [0xff01],dword 0 ; activated + + popad + ret + + .no_activate_request: + + cmp [0xfb40],byte 0 ; mouse buttons pressed ? + jne .mouse_buttons_pressed +; cmp [window_minimize],2 +; jne .no_activate_request_1 + cmp [window_minimize],0 + je .no_activate_request_2 + cmp [window_minimize],1 + je .mouse_buttons_pressed + mov esi,[0x3004] + movzx edi, word [0xC400 + esi * 2] + shl edi, 5 + add edi, window_data + cmp [edi+12],dword 0 + je .mouse_buttons_pressed +; jne .no_activate_request_2 +; .no_activate_request_1: +; cmp [window_minimize],1 +; jge .mouse_buttons_pressed +; jmp .mouse_buttons_pressed + .no_activate_request_2: + mov [window_minimize],0 + popad + ret + + .mouse_buttons_pressed: + + mov esi,[0x3004] + inc esi + + cwloop: + cmp esi,2 + jb .exit + .temp_window_minimize_1: + dec esi + movzx edi, word [0xC400 + esi * 2] ; ebx + shl edi, 5 + add edi, window_data +; mov edi, ebx + mov ecx, [edi+0] + mov edx, [edi+4] + + mov eax,ecx + mov ebx,edx + cmp [window_minimize],1 + jge .window_minimize_no_check_mouse + + movzx eax, word [0xfb0a] + movzx ebx, word [0xfb0c] + + cmp ecx, eax + jae cwloop + cmp edx, ebx + jae cwloop + add ecx, [edi+8] + add edx, [edi+12] + cmp eax, ecx + jae cwloop + cmp ebx, edx + jae cwloop + + .window_minimize_no_check_mouse: + + pushad + mov eax, esi + mov ebx, [0x3004] + cmp eax, ebx ; is this window active? + jz .move_resize_window + + ; eax = position in windowing stack + ; redraw must ? + lea esi, [0xC400 + esi * 2] + call waredraw + add esp, 32 + + .exit: + popad + ret + + .move_resize_window: ; MOVE OR RESIZE WINDOW + + popad + + ; Check for user enabled fixed window + mov edx, [edi+0x14] + and edx, 0x0f000000 + cmp edx, 0x01000000 + jne .window_move_enabled_for_user + popad + ret + .window_move_enabled_for_user: + + mov [do_resize_from_corner],byte 0 ; resize for skinned window + mov edx, [edi+0x10] + and edx, 0x0f000000 + cmp edx, 0x02000000 + jb .no_resize_2 ; not type 2 wnd + + mov edx, [edi+4] + add edx, [edi+12] + sub edx, 6 ; edx = y_end - 6 + cmp ebx, edx ; ebx = mouse_y + jb .no_resize_2 + mov [do_resize_from_corner],byte 1 + jmp .continue + .no_resize_2: + +;// mike.dld [ + mov dl,[edi+0x10+3] + and dl,0x0F + cmp dl,0x03 + jne @f + mov edx, [edi+4] ; check if touch on bar + add edx, [_skinh] + cmp ebx, edx + jae .exit + jmp .continue + @@: +;// mike.dld ] + + mov edx, [edi+4] ; check if touch on bar + add edx, 21 + cmp ebx, edx + jae .exit + + .continue: + + push esi + mov esi, window_moving + call sys_msg_board_str + pop esi + + mov ecx, [timer_ticks] ;[0xfdf0] ; double-click ? + mov edx, ecx + sub edx, [latest_window_touch] + mov [latest_window_touch], ecx + mov [latest_window_touch_delta], edx + + mov cl, [0xfb40] ; save for shade check + mov [do_resize], cl + cmp [window_minimize],0 + je no_emulation_righ_button + mov [do_resize], byte 2 + no_emulation_righ_button: + mov ecx, [edi+0] + mov edx, [edi+4] + + push eax ecx edx + mov [dlx], ecx ; save for drawlimits + mov [dly], edx + mov eax, [edi+8] + add ecx, eax + mov eax, [edi+12] + add edx, eax + mov [dlxe], ecx + mov [dlye], edx + pop edx ecx eax + + sub eax, ecx + sub ebx, edx + + mov esi, [0xfb0a] + mov [0xf300], esi + + pushad ; wait for putimages to finish +; mov eax,5 +; call delay_hs + mov eax,[edi+0] + mov [npx],eax + mov eax,[edi+4] + mov [npy],eax + popad + + push eax ; save old coordinates + mov ax,[edi+00] + mov word [oldc+00],ax + mov ax,[edi+04] + mov word [oldc+04],ax + mov ax,[edi+8] + mov word [oldc+8],ax + mov word [npxe],ax + mov ax,[edi+12] + mov word [oldc+12],ax + mov word [npye],ax + pop eax + + call drawwindowframes + + mov [reposition],0 + mov [0xfb44],byte 1 ; no reaction to mouse up/down + + ; move window + + newchm: + + mov [0xfff5],byte 1 + + call checkidle + + call checkEgaCga + + mov [0xfff4],byte 0 + + call check_mouse_data + call [draw_pointer] + + pushad + call stack_handler + popad + + mov esi,[0xf300] + cmp esi,[0xfb0a] + je cwb + + mov cx,[0xfb0a] + mov dx,[0xfb0c] + sub cx,ax + sub dx,bx + + push ax + push bx + + call drawwindowframes + + mov ax,[0xfe00] + mov bx,[0xfe04] + + cmp [do_resize_from_corner],1 + je no_new_position + + mov word [npx],word 0 ; x repos ? + cmp ax,cx + jb noreposx + mov [reposition],1 + sub ax,word [npxe] + mov word [npx],ax + cmp ax,cx + jb noreposx + mov word [npx],cx + noreposx: + + mov word [npy],word 0 ; y repos ? + cmp bx,dx + jb noreposy + mov [reposition],1 + sub bx,word [npye] + mov word [npy],bx + cmp bx,dx + jb noreposy + mov word [npy],dx + noreposy: + + no_new_position: + + cmp [do_resize_from_corner],0 ; resize from right corner + je norepos_size + pushad + + mov edx,edi + sub edx,window_data + shr edx,5 + shl edx,8 + add edx,0x80000 ; process base at 0x80000+ + + movzx eax,word [0xfb0a] + cmp eax,[edi+0] + jb nnepx + sub eax,[edi+0] + cmp eax,[edx+0x90+8] + jge nnepx2 + mov eax,[edx+0x90+8] + nnepx2: + mov [npxe],eax + nnepx: + + movzx eax,word [0xfb0c] + cmp eax,[edi+4] + jb nnepy + sub eax,[edi+4] + cmp eax,23 ; [edx+0x90+12] + jge nnepy2 + mov eax,23 ; [edx+0x90+12] + nnepy2: + mov [npye],eax + nnepy: + + mov [reposition],1 + + popad + norepos_size: + + pop bx + pop ax + call drawwindowframes + + mov esi,[0xfb0a] + mov [0xf300],esi + + cwb: + cmp [0xfb40],byte 0 + jne newchm + ; new position done + call drawwindowframes + mov [0xfff5],byte 1 + + mov eax,[npx] + mov [edi+0],eax + mov eax,[npy] + mov [edi+4],eax + mov eax,[npxe] + mov [edi+8],eax + mov eax,[npye] + mov [edi+12],eax + + cmp [reposition],1 ; save new X and Y start + jne no_xy_save + ; + push esi edi ecx + mov esi,edi + sub edi,window_data + shr edi,5 + shl edi,8 + add edi,0x80000+0x90 + mov ecx,2 + cld + rep movsd + pop ecx edi esi + ; + no_xy_save: + + pushad ; WINDOW SHADE/FULLSCREEN + + cmp [reposition],1 + je no_window_sizing + mov edx,edi + sub edx,window_data + shr edx,5 + shl edx,8 + add edx,0x80000 ; process base at 0x80000+ + + cmp [do_resize],2 ; window shade ? + jb no_window_shade + mov [reposition],1 + + cmp [window_minimize],1 + jge for_window_minimize + cmp [edi+12],dword 23 + jle window_shade_up + jmp for_window_shade + for_window_minimize: + cmp [edi+12],dword 0 + je window_shade_up + for_window_shade: + cmp [window_minimize],0 + je no_window_minimize + cmp [window_minimize],2 + je window_minimize_no_shade_full ;window_shade_up + mov [edi+8],dword 0 ;66 + mov [edi+12],dword 0 ;279 ; on + jmp no_window_shade + no_window_minimize: + mov [edi+12],dword 23 ; on + jmp no_window_shade + window_shade_up: + cmp [window_minimize],1 + jge window_minimize_no_shade_full + mov eax,[edi+0] + add eax,[edi+4] + test eax, eax + je shade_full + push edi + lea esi, [edx + 0x90] + mov ecx,4 + cld + rep movsd + pop edi + + window_minimize_no_shade_full: +; mov eax,[edx+0x90] ; off +; mov [edi+0],eax +; mov eax,[edx+0x94] ; off +; mov [edi+4],eax +; mov eax,[edx+0x98] ; off +; mov [edi+8],eax +; mov eax,[edx+0x9C] ; off +; mov [edi+12],eax + + push edi + lea esi, [edx + 0x90] + mov ecx,4 + cld + rep movsd + pop edi + jmp no_window_shade + + shade_full: +; mov eax,[0xfe00] +; mov [edi+8],eax + mov eax,[0xfe04] + sub eax,19 + mov [edi+12],eax + no_window_shade: + + cmp [do_resize],1 ; fullscreen/restore ? + jne no_fullscreen_restore + cmp [latest_window_touch_delta],dword 50 + jg no_fullscreen_restore + mov [reposition],1 + mov eax,[edi+12] + add eax,19 + cmp eax,[0xfe04] + je restore_from_fullscreen + mov [edi+0],dword 0 ; set fullscreen + mov [edi+4],dword 0 + mov eax,[0xfe00] + mov [edi+8],eax + mov eax,[0xfe04] + sub eax,19 + mov [edi+12],eax + jmp no_fullscreen_restore + restore_from_fullscreen: + push edi ; restore +; mov esi,edx +; add esi,0x90 + lea esi, [edx + 0x90] + mov ecx,4 + cld + rep movsd + pop edi + + no_fullscreen_restore: + + mov eax,[edi+4] ; check Y inside screen + add eax,[edi+12] + cmp eax,[0xfe04] + jbe no_window_sizing + mov eax,[edi+0] ; check X inside screen + add eax,[edi+8] + cmp eax,[0xfe00] + jbe no_window_sizing + mov eax,[0xfe00] + sub eax,[edi+8] + mov [edi+0],eax + mov eax,[0xfe04] + sub eax,[edi+12] + mov [edi+4],eax + no_window_sizing: + + popad + + cmp [reposition],0 + je retwm + + pushad + mov eax,[edi+00] + mov ebx,[edi+04] + mov ecx,[edi+8] + mov edx,[edi+12] + add ecx,eax + add edx,ebx + mov edi,[0x3004] + shl edi,1 + add edi,0xc400 + movzx esi,byte [edi] + shl esi,5 + add esi,0x3000+0xe + movzx esi,byte [esi] + + sub edi,draw_data + shr edi,5 + shl edi,8 + add edi,0x80000+0x80 + ;cmp [edi],dword 0 + ;jne no_rect_shaped_move + call setscreen + jmp move_calculated + no_rect_shaped_move: + call calculatescreen + move_calculated: + + popad + + mov [edi+31],byte 1 ; mark first as redraw + mov [0xfff5],byte 1 ; no mouse + + push eax ebx ecx edx + mov eax,[oldc+00] + mov ebx,[oldc+04] + mov ecx,[oldc+8] + mov edx,[oldc+12] + add ecx,eax + add edx,ebx + call calculatescreen + pop edx ecx ebx eax + + mov eax,edi + call redrawscreen + + mov ecx,100 ; wait to avoid mouse residuals + waitre2: + call check_mouse_data + mov [0xfff5],byte 1 + call checkidle + cmp [edi+31],byte 0 + jz retwm + loop waitre2 + + retwm: + + mov [0xfff5],byte 0 ; mouse pointer + mov [0xfff4],byte 0 ; no mouse under + mov [0xfb44],byte 0 ; react to mouse up/down + + mov esi,window_moved + call sys_msg_board_str + + popad + + mov [window_minimize],0 +; sti + ret + +;temp_mouse_1 dw 0 +;temp_mouse_2 dw 0 + +uglobal + add_window_data dd 0 + do_resize_from_corner db 0x0 + reposition db 0x0 + latest_window_touch dd 0x0 + latest_window_touch_delta dd 0x0 + + do_resize db 0x0 + + oldc dd 0x0,0x0,0x0,0x0 + + dlx dd 0x0 + dly dd 0x0 + dlxe dd 0x0 + dlye dd 0x0 + + npx dd 0x0 + npy dd 0x0 + npxe dd 0x0 + npye dd 0x0 + + mpx dd 0x0 + mpy dd 0x0 +endg + + +; draw negative window frames + +drawwindowframes: + + pushad + + mov eax,[npx] + shl eax,16 + add eax,[npx] + add eax,[npxe] + add eax,65536*1-1 + mov ebx,[npy] + shl ebx,16 + add ebx,[npy] + mov ecx,0x01000000 + push edi + mov edi,1 + call [draw_line] + pop edi + + mov eax,[npx] + shl eax,16 + add eax,[npx] + add eax,[npxe] + add eax,65536*1-1 + mov ebx,[npy] + add ebx,[npye] + shl ebx,16 + add ebx,[npy] + add ebx,[npye] + mov ecx,0x01000000 + push edi + mov edi,1 + call [draw_line] + pop edi + + mov eax,[npx] + shl eax,16 + add eax,[npx] + mov ebx,[npy] + shl ebx,16 + add ebx,[npy] + add ebx,[npye] + mov ecx,0x01000000 + push edi + mov edi,1 + call [draw_line] + pop edi + + mov eax,[npx] + add eax,[npxe] + shl eax,16 + add eax,[npx] + add eax,[npxe] + mov ebx,[npy] + shl ebx,16 + add ebx,[npy] + add ebx,[npye] + mov ecx,0x01000000 + push edi + mov edi,1 + call [draw_line] + mov edi,[0x3000] + shl edi,5 + add edi,window_data + mov [edi+30],byte 1 + pop edi + + popad + + ret + + + +random_shaped_window: + +; +; eax = 0 giving address of data area +; ebx address +; ebx = 1 shape area scale +; ebx 2^ebx scale + + test eax, eax + jne rsw_no_address + mov eax,[0x3000] + shl eax,8 + + mov [eax+0x80000+0x80],ebx + rsw_no_address: + + cmp eax,1 + jne rsw_no_scale + mov eax,[0x3000] + shl eax,8 + mov [eax+0x80000+0x84],bl + rsw_no_scale: + + ret + + diff --git a/trunk/hid/keyboard.inc b/trunk/hid/keyboard.inc new file mode 100644 index 000000000..4a4d23cd1 --- /dev/null +++ b/trunk/hid/keyboard.inc @@ -0,0 +1,223 @@ +;// mike.dld [ + +VKEY_LSHIFT = 0000000000000001b +VKEY_RSHIFT = 0000000000000010b +VKEY_LCONTROL = 0000000000000100b +VKEY_RCONTROL = 0000000000001000b +VKEY_LALT = 0000000000010000b +VKEY_RALT = 0000000000100000b +VKEY_CAPSLOCK = 0000000001000000b +VKEY_NUMLOCK = 0000000010000000b +VKEY_SCRLOCK = 0000000100000000b + +VKEY_SHIFT = 0000000000000011b +VKEY_CONTROL = 0000000000001100b +VKEY_ALT = 0000000000110000b + +uglobal + align 4 + kb_state dd 0 + ext_code db 0 + + keyboard_mode db 0 + keyboard_data db 0 + + altmouseb db 0 + ctrl_alt_del db 0 + + kb_lights db 0 +endg + +align 4 +irq1: + + call restore_caller + + movzx eax,word[0x3004] ; top window process + movzx eax,word[0xC400+eax*2] + shl eax,8 + mov al,[0x800B4+eax] + mov [keyboard_mode],al + + in al,0x60 + mov [keyboard_data],al + + mov ch,al + cmp al,0xE0 + je @f + cmp al,0xE1 + jne .normal_code + @@: mov [ext_code],al + jmp .no_key.end + .normal_code: + mov cl,[ext_code] + mov [ext_code],0 + and al,0x7F + @@: cmp al,0x2A + jne @f + cmp cl,0xE0 + je .no_key.end + mov eax,VKEY_LSHIFT + jmp .no_key + @@: cmp al,0x36 + jne @f + cmp cl,0xE0 + je .no_key.end + mov eax,VKEY_RSHIFT + jmp .no_key + @@: cmp al,0x38 + jne @f + cmp cl,0xE0 + je .alt.r + mov eax,VKEY_LALT + jmp .no_key + .alt.r: + mov eax,VKEY_RALT + jmp .no_key + @@: cmp al,0x1D + jne @f + cmp cl,0 + jne .ctrl.r + mov eax,VKEY_LCONTROL + jmp .no_key + .ctrl.r: + cmp cl,0xE1 + jne .ctrl.r.2 + mov [ext_code],cl + jmp .no_key.end + .ctrl.r.2: + mov eax,VKEY_RCONTROL + jmp .no_key + @@: cmp al,0x3A + jne @f + mov bl,4 + mov eax,VKEY_CAPSLOCK + jmp .no_key.xor + @@: cmp al,0x45 + jne @f + cmp cl,0 + jne .no_key.end + mov bl,2 + mov eax,VKEY_NUMLOCK + jmp .no_key.xor + @@: cmp al,0x46 + jne @f + mov bl,1 + mov eax,VKEY_SCRLOCK + jmp .no_key.xor + @@: + test ch,0x80 + jnz .no_key.end + movzx eax,ch ; plain key + mov bl,[keymap+eax] + mov edx,[kb_state] + test dl,VKEY_CONTROL ; ctrl alt del + jz .noctrlaltdel + test dl,VKEY_ALT + jz .noctrlaltdel + cmp bl,134+48 + jne .noctrlaltdel + mov [ctrl_alt_del],1 + jmp .no_key.end + .noctrlaltdel: + test dl,VKEY_CONTROL ; ctrl on ? + jz @f + sub bl,0x60 + @@: test dl,VKEY_SHIFT ; shift on ? + jz @f + mov bl,[keymap_shift+eax] + @@: test dl,VKEY_ALT ; alt on ? + jz @f + mov bl,[keymap_alt+eax] +; alt mouse ? + xor edx,edx + cmp bl,178 + jnz .no_alt.up + mov edx,5*65536 + jmp .mouse.change + .no_alt.up: + cmp bl,177 + jnz .no_alt.down + mov edx,251*65536 + jmp .mouse.change + .no_alt.down: + cmp bl,176 + jnz .no_alt.left + mov edx,251*256 + jmp .mouse.change + .no_alt.left: + cmp bl,179 + jnz .no_alt.right + mov edx,5*256 + jmp .mouse.change + .no_alt.right: + cmp bl,' ' + jne @f + xor [altmouseb],1 + .mouse.change: + mov byte[0xF604],1; ps2 data + mov byte[0xFB00],0; ps2 chunk count + mov word[0x2E0000+4096*12],3; mouse data count + mov dl,[altmouseb] + mov [0x2E0000+4096*12+0x10],edx + mov bl,0 + @@: + cmp [keyboard_mode],0 ; return from keymap + jne .no_key.end + mov [keyboard_mode_sys],0 + cmp bl,0 + je .no_key.end + movzx eax,byte[0xF400] + cmp al,120 + jae .no_key.end + inc al + mov [0xF400],al + mov [0xF400+eax],bl + + jmp .no_key.end + + .no_key: + test ch,0x80 + jz .no_key.down + not eax + and [kb_state],eax + jmp .no_key.end + .no_key.xor: + test ch,0x80 + jnz .no_key.end + xor [kb_state],eax + xor [kb_lights],bl + call set_lights + jmp .no_key.end + .no_key.down: + or [kb_state],eax + .no_key.end: + cmp [keyboard_mode],1 ; return scancode + jne .no_scancode + mov [keyboard_mode_sys],1 + movzx eax,byte[0xF400] + cmp al,120 + jae .no_scancode + inc al + mov [0xF400],al + mov [0xF400+eax],ch + .no_scancode: + + .exit.irq1: + mov [check_idle_semaphore],5 + + mov al,0x20 ; ready for next irq + out 0x20,al + + call return_to_caller + + jmp irq1 + +set_lights: + mov al,0xED + call kb_write + mov al,[kb_lights] + call kb_write + ret + +;// mike.dld ] diff --git a/trunk/hid/set_dtc.inc b/trunk/hid/set_dtc.inc new file mode 100644 index 000000000..479ebce80 --- /dev/null +++ b/trunk/hid/set_dtc.inc @@ -0,0 +1,191 @@ +;setting date,time,clock and alarm-clock +;add sys_settime at servetable as for ex. 22 fcn: +; 22 - SETTING DATE TIME, CLOCK AND ALARM-CLOCK +; ebx =0 - set time ecx - 00SSMMHH +; ebx =1 - set date ecx=00DDMMYY +; ebx =2 - set day of week ecx- 1-7 +; ebx =3 - set alarm-clock ecx - 00SSMMHH +; out: 0 -Ok 1 -wrong format 2 -battery low +sys_settime: + mov ecx,eax + cli + mov al,0x0d + out 0x70,al + in al,0x71 + bt ax,7 + jnc bat_low + cmp ecx,2 ;day of week + jne nosetweek + test ebx,ebx ;test day of week + je wrongtime + cmp ebx,7 + ja wrongtime + mov dx,0x70 + call startstopclk + dec edx + mov al,6 + out dx,al + inc edx + mov al,bl + out dx,al + jmp endsettime + nosetweek: ;set date + cmp ecx,1 + jne nosetdate + cmp bl,0x99 ;test year + ja wrongtime + shl ebx,4 + cmp bl,0x90 + ja wrongtime + cmp bh,0x99 ;test month + ja wrongtime + shr ebx,4 + test bh,bh + je wrongtime + cmp bh,0x12 + ja wrongtime + shl ebx,8 + bswap ebx ;ebx=00YYMMDD + test bl,bl ;test day + je wrongtime + shl ebx,4 + cmp bl,0x90 + ja wrongtime + shr ebx,4 + cmp bh,2 ;February + jne testday + cmp bl,0x29 + ja wrongtime + jmp setdate + testday: + cmp bh,8 + jb testday1 ;Aug-Dec + bt bx,8 + jnc days31 + jmp days30 + testday1: + bt bx,8 ;Jan-Jul ex.Feb + jnc days30 + days31: + cmp bl,0x31 + ja wrongtime + jmp setdate + days30: + cmp bl,0x30 + ja wrongtime + setdate: + mov dx,0x70 + call startstopclk + dec edx + mov al,7 ;set days + out dx,al + inc edx + mov al,bl + out dx,al + dec edx + mov al,8 ;set months + out dx,al + inc edx + mov al,bh + out dx,al + dec edx + mov al,9 ;set years + out dx,al + inc edx + shr ebx,8 + mov al,bh + out dx,al + jmp endsettime + nosetdate: ;set time or alarm-clock + cmp ecx,3 + ja wrongtime + cmp bl,0x23 + ja wrongtime + cmp bh,0x59 + ja wrongtime + shl ebx,4 + cmp bl,0x90 + ja wrongtime + cmp bh,0x92 + ja wrongtime + shl ebx,4 + bswap ebx ;00HHMMSS + cmp bl,0x59 + ja wrongtime + shl ebx,4 + cmp bl,0x90 + ja wrongtime + shr ebx,4 + mov dx,0x70 + call startstopclk + dec edx + cmp ecx,3 + je setalarm + xor eax,eax ;al=0-set seconds + out dx,al + inc edx + mov al,bl + out dx,al + dec edx + mov al,2 ;set minutes + out dx,al + inc edx + mov al,bh + out dx,al + dec edx + mov al,4 ;set hours + out dx,al + inc edx + shr ebx,8 + mov al,bh + out dx,al + jmp endsettime + setalarm: + mov al,1 ;set seconds for al. + out dx,al + inc edx + mov al,bl + out dx,al + dec edx + mov al,3 ;set minutes for al. + out dx,al + inc edx + mov al,bh + out dx,al + dec edx + mov al,5 ;set hours for al. + out dx,al + inc edx + shr ebx,8 + mov al,bh + out dx,al + dec edx + mov al,0x0b ;enable irq's + out dx,al + inc dx + in al,dx + bts ax,5 ;set bit 5 + out dx,al + endsettime: + dec edx + call startstopclk + sti + mov [esp+36],dword 0 + ret + bat_low: + sti + mov [esp+36],dword 2 + ret + wrongtime: + sti + mov [esp+36],dword 1 + ret + +startstopclk: + mov al,0x0b + out dx,al + inc dx + in al,dx + btc ax,7 + out dx,al + ret diff --git a/trunk/kernel.asm b/trunk/kernel.asm new file mode 100644 index 000000000..9f15aa2b6 --- /dev/null +++ b/trunk/kernel.asm @@ -0,0 +1,5730 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Kolibri OS - based on source code Menuet OS, but not 100% compatible. +;; +;; See file COPYING or GNU.TXT for details with these additional details: +;; - All code written in 32 bit x86 assembly language +;; - No external code (eg. bios) at process execution time +;; +;; +;; Compile with last version FASM +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +include "KGLOBALS.INC" +include "lang.inc" + +WinMapAddress equ 0x460000 +display_data = 0x460000 + +max_processes equ 255 + +window_data equ 0x0000 +tss_data equ 0xD20000 +;tss_step equ (128+2048) ; tss & i/o - 16384 ports, * 256=557056 +tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4 +draw_data equ 0xC00000 +sysint_stack_data equ 0xC03000 + + +twdw equ (0x3000-window_data) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Included files: +;; +;; Kernel16.inc +;; - Booteng.inc English text for bootup +;; - Bootcode.inc Hardware setup +;; - Pci16.inc PCI functions +;; +;; Kernel32.inc +;; - Sys32.inc Process management +;; - Shutdown.inc Shutdown and restart +;; - Fat32.inc Read / write hd +;; - Vesa12.inc Vesa 1.2 driver +;; - Vesa20.inc Vesa 2.0 driver +;; - Vga.inc VGA driver +;; - Stack.inc Network interface +;; - Mouse.inc Mouse pointer +;; - Scincode.inc Window skinning +;; - Pci32.inc PCI functions +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; 16 BIT ENTRY FROM BOOTSECTOR ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +use16 + org 0x10000 +macro diff16 title,l2 + { + local s,d,l1 + s = l2 + display title,': 0x' + repeat 8 + d = 48 + s shr ((8-%) shl 2) and $0F + if d > 57 + d = d + 65-57-1 + end if + display d + end repeat + display 13,10 + } + jmp start_of_code + +; mike.dld { +db 0 +dd servetable-0x10000 +draw_line dd __sys_draw_line +disable_mouse dd __sys_disable_mouse +draw_pointer dd __sys_draw_pointer +drawbar dd __sys_drawbar +putpixel dd __sys_putpixel +; } mike.dld + +version db 'Kolibri OS version 0.5.0.0 ',13,10,13,10,0 + ;dd endofcode-0x10000 + + ;db 'Boot02' +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +include "boot/preboot.inc" +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +preboot_lfb db 0 +preboot_bootlog db 0 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; 16 BIT INCLUDED FILES ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +include "KERNEL16.INC" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SWITCH TO 32 BIT PROTECTED MODE ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +os_data equ os_data_l-gdts ; GDTs +os_code equ os_code_l-gdts +int_code equ int_code_l-gdts +int_data equ int_data_l-gdts +tss0sys equ tss0sys_l-gdts +graph_data equ 3+graph_data_l-gdts +tss0 equ tss0_l-gdts +tss0i equ tss0i_l-gdts +app_code equ 3+app_code_l-gdts +app_data equ 3+app_data_l-gdts + + + +; CR0 Flags - Protected mode and Paging + + mov ecx,0x00000001 + ;and ebx,65535 + ;cmp ebx,00100000000000000b ; lfb -> paging + ;jb no_paging + ;mov ax,0x0000 + ;mov es,ax + ;mov al,[es:0x901E] + ;cmp al,1 + ;je no_paging + ;or ecx, 0x80000000 + ;no_paging: + +; Enabling 32 bit protected mode + + sidt [cs:old_ints_h-0x10000] + + cli ; disable all irqs + cld + mov al,255 ; mask all irqs + out 0xa1,al + out 0x21,al + l.5: in al, 0x64 ; Enable A20 + test al, 2 + jnz l.5 + mov al, 0xD1 + out 0x64, al + l.6: in al, 0x64 + test al, 2 + jnz l.6 + mov al, 0xDF + out 0x60, al + lgdt [cs:gdts-0x10000] ; Load GDT + mov eax, cr0 ; Turn on paging // protected mode + or eax, ecx + and eax, 10011111b *65536*256 + 0xffffff ; caching enabled + mov cr0, eax + jmp byte $+2 + mov ax,os_data ; Selector for os + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,0x30000 ; Set stack + jmp pword os_code:B32 ; jmp to enable 32 bit mode + +use32 + +iglobal + boot_memdetect db 'Determining amount of memory',0 + boot_fonts db 'Fonts loaded',0 + boot_tss db 'Setting TSSs',0 + boot_cpuid db 'Reading CPUIDs',0 + boot_devices db 'Detecting devices',0 + boot_timer db 'Setting timer',0 + boot_irqs db 'Reprogramming IRQs',0 + boot_setmouse db 'Setting mouse',0 + boot_windefs db 'Setting window defaults',0 + boot_bgr db 'Calculating background',0 + boot_resirqports db 'Reserving IRQs & ports',0 + boot_setrports db 'Setting addresses for IRQs',0 + boot_setostask db 'Setting OS task',0 + boot_allirqs db 'Unmasking all IRQs',0 + boot_tsc db 'Reading TSC',0 + boot_pal_ega db 'Setting EGA/CGA 320x200 palette',0 + boot_pal_vga db 'Setting VGA 640x480 palette',0 + boot_mtrr db 'Setting MTRR',0 + boot_tasking db 'All set - press ESC to start',0 +endg + +iglobal + boot_y dd 10 +endg + +boot_log: + pushad + + mov edx,esi +.bll3: inc edx + cmp [edx],byte 0 + jne .bll3 + sub edx,esi + mov eax,10*65536 + mov ax,word [boot_y] + add [boot_y],dword 10 + mov ebx,0xffffff + mov ecx,esi + mov edi,1 + call dtext + + mov [novesachecksum],1000 + call checkEgaCga + + cmp [preboot_blogesc],byte 1 + je .bll2 + + cmp esi,boot_tasking + jne .bll2 + ; begin ealex 04.08.05 +; in al,0x61 +; and al,01111111b +; out 0x61,al + ; end ealex 04.08.05 +.bll1: in al,0x60 ; wait for ESC key press + cmp al,129 + jne .bll1 + +.bll2: popad + + ret + +uglobal + cpuid_0 dd 0,0,0,0 + cpuid_1 dd 0,0,0,0 + cpuid_2 dd 0,0,0,0 + cpuid_3 dd 0,0,0,0 +endg + +iglobal + firstapp db 'LAUNCHER ' + char db 'CHAR MT ' + char2 db 'CHAR2 MT ' + bootpath db '/KOLIBRI ' + bootpath2 db 0 + vmode db 'VMODE MDR' + vrr_m db 'VRR_M ' +endg + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; 32 BIT ENTRY ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 + +B32: +; CLEAR 0x280000-0xF00000 + + xor eax,eax + mov edi,0x280000 + mov ecx,(0x100000*0xF-0x280000) / 4 + cld + rep stosd +; CLEAR 0x80000-0x90000 +; xor eax,eax + mov edi,0x80000 + mov ecx,(0x90000-0x80000)/4 +; cld + rep stosd + +; CLEAR KERNEL UNDEFINED GLOBALS + mov edi, endofcode + mov ecx, (uglobals_size/4)+4 + rep stosd + +; SAVE & CLEAR 0-0xffff + + mov esi,0x0000 + mov edi,0x2F0000 + mov ecx,0x10000 / 4 + cld + rep movsd + xor eax,eax + mov edi,0 + mov ecx,0x10000 / 4 + cld + rep stosd + +; SAVE REAL MODE VARIABLES +; movzx eax,byte [0x2f0000+0x9010] ; mouse port +; mov [0xF604],byte 1 ;al + mov al,[0x2f0000+0x9000] ; bpp + mov [0xFBF1],al + movzx eax,word [0x2f0000+0x900A] ; X max + dec eax + mov [0xfe00],eax + movzx eax,word [0x2f0000+0x900C] ; Y max + dec eax + mov [0xfe04],eax + movzx eax,word [0x2f0000+0x9008] ; screen mode + mov [0xFE0C],eax + mov eax,[0x2f0000+0x9014] ; Vesa 1.2 bnk sw add + mov [0xE030],eax + mov [0xfe08],word 640*4 ; Bytes PerScanLine + cmp [0xFE0C],word 0x13 ; 320x200 + je @f + cmp [0xFE0C],word 0x12 ; VGA 640x480 + je @f + mov ax,[0x2f0000+0x9001] ; for other modes + mov [0xfe08],ax + @@: + +; GRAPHICS ADDRESSES + + ;mov eax,0x100000*8 ; LFB address + ;cmp [0xfe0c],word 0x13 + ;je no_d_lfb + ;cmp [0xfe0c],word 0x12 + ;je no_d_lfb + ;cmp [0x2f0000+0x901e],byte 1 + ;jne no_d_lfb + mov byte [0x2f0000+0x901e],0x0 + mov eax,[0x2f0000+0x9018] + ;no_d_lfb: + mov [0xfe80],eax + + cmp [0xfe0c],word 0100000000000000b + jge setvesa20 + cmp [0xfe0c],word 0x13 + je v20ga32 + mov [0xe020],dword Vesa12_putpixel24 ; Vesa 1.2 + mov [0xe024],dword Vesa12_getpixel24 + cmp [0xfbf1],byte 24 + jz ga24 + mov [0xe020],dword Vesa12_putpixel32 + mov [0xe024],dword Vesa12_getpixel32 + ga24: + jmp v20ga24 + setvesa20: + mov [0xe020],dword Vesa20_putpixel24 ; Vesa 2.0 + mov [0xe024],dword Vesa20_getpixel24 + cmp [0xfbf1],byte 24 + jz v20ga24 + v20ga32: + mov [0xe020],dword Vesa20_putpixel32 + mov [0xe024],dword Vesa20_getpixel32 + v20ga24: + cmp [0xfe0c],word 0x12 ; 16 C VGA 640x480 + jne no_mode_0x12 + mov [0xe020],dword VGA_putpixel + mov [0xe024],dword Vesa20_getpixel32 + no_mode_0x12: + +; MEMORY MODEL + +; mov [0xfe84],dword 0x100000*16 ; apps mem base address +; movzx ecx,byte [0x2f0000+0x9030] +; dec ecx +; mov eax,16*0x100000 ; memory-16 +; shl eax,cl +; mov [0xfe8c],eax ; memory for use +; cmp eax,16*0x100000 +; jne no16mb +; mov [0xfe84],dword 0xD80000 ; !!! 10 !!! +; no16mb: + +; init: +; 1) 0xFE84 - applications base +; 2) 0xFE8C - total amount of memory + + xor edi, edi + m_GMS_loop: + add edi, 0x400000 + mov eax, dword [edi] + mov dword [edi], 'TEST' + wbinvd + cmp dword [edi], 'TEST' + jne m_GMS_exit + cmp dword [0], 'TEST' + je m_GMS_exit + mov dword [es:edi], eax + jmp m_GMS_loop + m_GMS_exit: + mov [edi], eax + ; now edi contains the EXACT amount of memory + + mov eax, 0x100000*16 + cmp edi, eax ;0x100000*16 + jb $ ; less than 16 Mb + + mov dword [0xFE84], eax ;0x100000*16 + cmp edi, eax ;0x100000*16 + jne @f + mov dword [0xFE84], 0xD80000 ; =0x100000*13.5 + @@: + mov dword [0xFE8C], edi + +;!!!!!!!!!!!!!!!!!!!!!!!!!! +include 'detect/disks.inc' +;!!!!!!!!!!!!!!!!!!!!!!!!!! + +; CHECK EXTRA REGION +; ENABLE PAGING + mov eax,cr0 + or eax,0x80000000 + mov cr0,eax + jmp $+2 + mov dword [0xfe80],0x800000 + +;Set base of graphic segment to linear address of LFB + mov eax,[0xfe80] ; set for gs + mov [graph_data_l+2],ax + shr eax,16 + mov [graph_data_l+4],al + mov [graph_data_l+7],ah + +; READ RAMDISK IMAGE FROM HD + +;!!!!!!!!!!!!!!!!!!!!!!! +include 'boot/rdload.inc' +;!!!!!!!!!!!!!!!!!!!!!!! +; mov [dma_hdd],1 +; CALCULATE FAT CHAIN FOR RAMDISK + + call calculatefatchain + +; LOAD VMODE DRIVER + +;!!!!!!!!!!!!!!!!!!!!!!! +include 'vmodeld.inc' +;!!!!!!!!!!!!!!!!!!!!!!! + +; LOAD FONTS I and II + + mov [0x3000],dword 1 + mov [0x3004],dword 1 + mov [0x3010],dword 0x3020 + + mov eax,char + mov esi,12 + xor ebx,ebx + mov ecx,26000 + mov edx,0x37000 + call fileread + + mov eax,char2 + mov esi,12 + xor ebx,ebx + mov ecx,26000 + mov edx,0x30000 + call fileread + + mov esi,boot_fonts + call boot_log + +; PRINT AMOUNT OF MEMORY + mov esi, boot_memdetect + call boot_log + + movzx ecx, word [boot_y] + or ecx, (10+29*6) shl 16 ; "Determining amount of memory" + sub ecx, 10 + mov edx, 0xFFFFFF + mov ebx, [0xFE8C] + shr ebx, 20 + mov edi, 1 + mov eax, 0x00040000 + call display_number + +; CHECK EXTENDED REGION +; mov dword [0x80000000],0x12345678 +; cmp dword [0x80000000],0x12345678 +; jz extended_region_found +; mov esi,boot_ext_region +; call boot_log +; jmp $ +;extended_region_found: + + call MEM_Init +;add 0x800000-0xc00000 area + cmp word [0xfe0c],0x13 + jle .less_memory + mov eax,0x80000000 ;linear address + mov ebx,0x400000 shr 12 ;size in pages (4Mb) + mov ecx,0x800000 ;physical address + jmp .end_first_block +.less_memory: + mov eax,0x80180000 ;linear address + mov ebx,0x280000 shr 12 ;size in pages (2.5Mb) + mov ecx,0x980000 ;physical address +.end_first_block: + call MEM_Add_Heap ;nobody can lock mutex yet + + call create_general_page_table +;add 0x1000000(0xd80000)-end_of_memory area + mov eax,second_base_address + mov ebx,[0xfe8c] + mov ecx,[0xfe84] + sub ebx,ecx + shr ebx,12 + add eax,ecx + call MEM_Add_Heap +;init physical memory manager. + call Init_Physical_Memory_Manager + +; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f + + mov esi,boot_irqs + call boot_log + call rerouteirqs + + mov esi,boot_tss + call boot_log + +; BUILD SCHEDULER + + call build_scheduler ; sys32.inc + +; LOAD IDT + ; + lidt [cs:idtreg] ;[cs:idts] + ; + +; READ CPUID RESULT + + mov esi,boot_cpuid + call boot_log + pushfd ; get current flags + pop eax + mov ecx,eax + xor eax,0x00200000 ; attempt to toggle ID bit + push eax + popfd + pushfd ; get new EFLAGS + pop eax + push ecx ; restore original flags + popfd + and eax,0x00200000 ; if we couldn't toggle ID, + and ecx,0x00200000 ; then this is i486 + cmp eax,ecx + jz nopentium + ; It's Pentium or later. Use CPUID + mov edi,cpuid_0 + mov esi,0 + cpuid_new_read: + mov eax,esi + cpuid + call cpuid_save + add edi,4*4 + cmp esi,3 + jge cpuid_done + cmp esi,[cpuid_0] + jge cpuid_done + inc esi + jmp cpuid_new_read + cpuid_save: + mov [edi+00],eax + mov [edi+04],ebx + mov [edi+8],ecx + mov [edi+12],edx + ret + cpuid_done: + nopentium: + +; CR4 flags - enable fxsave / fxrstore +; +; finit +; mov eax,1 +; cpuid +; test edx,1000000h +; jz fail_fpu +; mov eax,cr4 +; or eax,200h ; Enable fxsave/fxstor +; mov cr4,eax +; fail_fpu: + +; DETECT DEVICES + + mov esi,boot_devices + call boot_log + call detect_devices + + ; TIMER SET TO 1/100 S + + mov esi,boot_timer + call boot_log + mov al,0x34 ; set to 100Hz + out 0x43,al + mov al,0x9b ; lsb 1193180 / 1193 + out 0x40,al + mov al,0x2e ; msb + out 0x40,al + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +;include 'detect/commouse.inc' +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; SET MOUSE + + mov esi,boot_setmouse + call boot_log + call setmouse + +; SET PRELIMINARY WINDOW STACK AND POSITIONS + + mov esi,boot_windefs + call boot_log + call setwindowdefaults + +; SET BACKGROUND DEFAULTS + + mov esi,boot_bgr + call boot_log + call calculatebackground + +; RESERVE SYSTEM IRQ'S JA PORT'S + + mov esi,boot_resirqports + call boot_log + call reserve_irqs_ports + +; SET PORTS FOR IRQ HANDLERS + + mov esi,boot_setrports + call boot_log + call setirqreadports + +; SET UP OS TASK + + mov esi,boot_setostask + call boot_log + ; name for OS/IDLE process + mov [0x80000+256+0],dword 'OS/I' + mov [0x80000+256+4],dword 'DLE ' + ; task list + mov [0x3004],dword 2 ; number of processes + mov [0x3000],dword 0 ; process count - start with os task + mov [0x3020+0xE],byte 1 ; on screen number + mov [0x3020+0x4],dword 1 ; process id number + + ; set default flags & stacks + mov [l.eflags],dword 0x11202 ; sti and resume + mov [l.ss0], os_data + ;mov [l.ss1], ring1_data + ;mov [l.ss2], ring2_data + mov [l.esp0], 0x52000 + mov [l.esp1], 0x53000 + mov [l.esp2], 0x54000 + ; osloop - TSS + mov eax,cr3 + mov [l.cr3],eax + mov [l.eip],osloop +; + mov [l.esp],0x30000 ;0x2ffff +; + mov [l.cs],os_code + mov [l.ss],os_data + mov [l.ds],os_data + mov [l.es],os_data + mov [l.fs],os_data + mov [l.gs],os_data + ; move tss to tss_data+tss_step + mov esi,tss_sceleton + mov edi,tss_data+tss_step + mov ecx,120/4 + cld + rep movsd + + mov ax,tss0 + ltr ax + + +; READ TSC / SECOND + + mov esi,boot_tsc + call boot_log + call _rdtsc + mov ecx,eax + mov esi,250 ; wait 1/4 a second + call delay_ms + call _rdtsc + sub eax,ecx + shl eax,2 + mov [0xf600],eax ; save tsc / sec + +; SET VARIABLES + + call set_variables + +; STACK AND FDC + + call stack_init + call fdc_init + +; PALETTE FOR 320x200 and 640x480 16 col + + cmp [0xfe0c],word 0x12 + jne no_pal_vga + mov esi,boot_pal_vga + call boot_log + call paletteVGA + no_pal_vga: + + cmp [0xfe0c],word 0x13 + jne no_pal_ega + mov esi,boot_pal_ega + call boot_log + call palette320x200 + no_pal_ega: + +; LOAD DEFAULT SKIN + + call load_default_skin + +; MTRR'S + + call enable_mtrr + + +; LOAD FIRST APPLICATION + mov [0x3000],dword 1 ;1 + mov [0x3004],dword 1 ;1 + cli + mov al,[0x2f0000+0x9030] + cmp al,1 + jne no_load_vrr_m + mov eax,vrr_m + call start_application_fl + cmp eax,2 ; if no vrr_m app found + je first_app_found + + no_load_vrr_m: + mov eax,firstapp + call start_application_fl + + cmp eax,2 ; if no first app found - halt + je first_app_found + mov eax, 0xDEADBEEF + hlt ;jmp $ + first_app_found: + cli + + mov [0x3004],dword 2 + mov [0x3000],dword 1 + + +; START MULTITASKING + + mov esi,boot_tasking + call boot_log + + mov [0xe000],byte 1 ; multitasking enabled + + mov al, 0xf6 ; ╤сЁюё ъыртшрЄєЁ√, ЁрчЁх°шЄ№ ёърэшЁютрэшх + call kb_write + + mov ecx,0 +wait_loop_1: ; variant 2 +; ўшЄрхь яюЁЄ ёюёЄю эш  яЁюЎхёёюЁр 8042 + in al,64h + and al,00000010b ; Їыру уюЄютэюёЄш +; юцшфрхь уюЄютэюёЄ№ яЁюЎхёёюЁр 8042 + loopnz wait_loop_1 + +; SET KEYBOARD PARAMETERS + ; mov al, 0xED ; svetodiody - only for testing! + ; call kb_write + ; call kb_read + ; mov al, 111b + ; call kb_write + ; call kb_read + + mov al, 0xF3 ; set repeat rate & delay + call kb_write + call kb_read + mov al, 00100010b ; 24 500 ;00100100b ; 20 500 + call kb_write + call kb_read + ;// mike.dld [ + call set_lights + ;// mike.dld ] + + +; UNMASK ALL IRQ'S + + mov esi,boot_allirqs + call boot_log + + cli ;guarantee forbidance of interrupts. + mov al,0 ; unmask all irq's + out 0xA1,al + out 0x21,al + + mov ecx,32 + + ready_for_irqs: + + mov al,0x20 ; ready for irqs + out 0x20,al + out 0xa0,al + + loop ready_for_irqs ; flush the queue + +; mov [dma_hdd],1 + + sti + jmp $ ; wait here for timer to take control + + ; Fly :) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; MAIN OS LOOP ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +align 32 +osloop: + + call check_mouse_data + call [draw_pointer] + + call checkbuttons + call main_loop_sys_getkey + call checkwindows + call check_window_move_request + + call checkmisc + call checkEgaCga + + call stack_handler + + call checkidle + call check_fdd_motor_status + jmp osloop +;temp_pointers: +; rd 32 +; seed dd 0x12345678 + +checkidle: + + pushad + + cmp [check_idle_semaphore],0 + jne no_idle_state + + call change_task + mov eax,[idlemem] + mov ebx,[timer_ticks] ;[0xfdf0] + cmp eax,ebx + jnz idle_exit + call _rdtsc + mov ecx,eax + idle_loop: + hlt + cmp [check_idle_semaphore],0 + jne idle_loop_exit + mov eax,[timer_ticks] ;[0xfdf0] + cmp ebx,eax + jz idle_loop + idle_loop_exit: + mov [idlemem],eax + call _rdtsc + sub eax,ecx + mov ebx,[idleuse] + add ebx,eax + mov [idleuse],ebx + + popad + ret + + idle_exit: + + mov ebx,[timer_ticks] ;[0xfdf0] + mov [idlemem],ebx + call change_task + + popad + ret + + no_idle_state: + + dec [check_idle_semaphore] + + mov ebx,[timer_ticks] ;[0xfdf0] + mov [idlemem],ebx + call change_task + + popad + ret + +uglobal + idlemem dd 0x0 + idleuse dd 0x0 + idleusesec dd 0x0 + check_idle_semaphore dd 0x0 +endg + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; INCLUDED SYSTEM FILES ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +include "KERNEL32.INC" + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; KERNEL FUNCTIONS ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +enable_mtrr: + + pushad + + cmp [0x2f0000+0x901c],byte 2 + je no_mtrr + mov eax,[0xFE0C] ; if no LFB then no MTRR + test eax,0100000000000000b + jz no_mtrr + mov edx,[cpuid_1+3*4] ; edx - MTRR's supported ? + test edx,1000000000000b + jz no_mtrr + call find_empty_mtrr + cmp ecx,0 + jz no_mtrr + mov esi,boot_mtrr ; 'setting mtrr' + call boot_log + mov edx,0x0 ; LFB , +8 M , write combine + mov eax,[0x2f9018] + or eax,1 + wrmsr + inc ecx + mov edx,0xf + mov eax,0xff800800 + wrmsr + mov ecx,0x2ff ; enable mtrr's + rdmsr + or eax,100000000000b ; set + wrmsr + no_mtrr: + + popad + ret + + +find_empty_mtrr: ; 8 pairs checked + + mov ecx,0x201-2 + mtrr_find: + add ecx,2 + cmp ecx,0x200+8*2 + jge no_free_mtrr + rdmsr + test eax,0x0800 + jnz mtrr_find + dec ecx + ret + no_free_mtrr: + mov ecx,0 + ret + +reserve_irqs_ports: + + pushad + + mov [irq_owner+4*0],byte 1 ; timer + mov [irq_owner+4*1],byte 1 ; keyboard + mov [irq_owner+4*5],byte 1 ; sound blaster + mov [irq_owner+4*6],byte 1 ; floppy diskette + mov [irq_owner+4*13],byte 1 ; math co-pros + mov [irq_owner+4*14],byte 1 ; ide I + mov [irq_owner+4*15],byte 1 ; ide II + movzx eax,byte [0xf604] ; mouse irq + dec eax + add eax,mouseirqtable + movzx eax,byte [eax] + shl eax,2 + mov [irq_owner+eax],byte 1 + + + ; RESERVE PORTS + mov edi,1 ; 0x00-0xff + mov [0x2d0000],edi + shl edi,4 + mov [0x2d0000+edi+0],dword 1 + mov [0x2d0000+edi+4],dword 0x0 + mov [0x2d0000+edi+8],dword 0xff + cmp [0xf604],byte 2 ; com1 mouse -> 0x3f0-0x3ff + jne ripl1 + inc dword [0x2d0000] + mov edi,[0x2d0000] + shl edi,4 + mov [0x2d0000+edi+0],dword 1 + mov [0x2d0000+edi+4],dword 0x3f0 + mov [0x2d0000+edi+8],dword 0x3ff + ripl1: + cmp [0xf604],byte 3 ; com2 mouse -> 0x2f0-0x2ff + jne ripl2 + inc dword [0x2d0000] + mov edi,[0x2d0000] + shl edi,4 + mov [0x2d0000+edi+0],dword 1 + mov [0x2d0000+edi+4],dword 0x2f0 + mov [0x2d0000+edi+8],dword 0x2ff + ripl2: + + popad + ret + +iglobal +mouseirqtable db 12 ; ps2 + db 4 ; com1 + db 3 ; com2 +endg + +setirqreadports: + + mov [irq12read+0],dword 0x60 + 0x01000000 ; read port 0x60 , byte + mov [irq12read+4],dword 0 ; end of port list + mov [irq04read+0],dword 0x3f8 + 0x01000000 ; read port 0x3f8 , byte + mov [irq04read+4],dword 0 ; end of port list + mov [irq03read+0],dword 0x2f8 + 0x01000000 ; read port 0x2f8 , byte + mov [irq03read+4],dword 0 ; end of port list + + ret + +iglobal + process_number dd 0x1 +endg + +uglobal + novesachecksum dd 0x0 +endg + +checkEgaCga: + + cmp [0xfe0c],dword 0x13 + je cnvl + ret + cnvl: + + pushad + mov ecx,[0xfb0a] + cmp ecx,[novesachecksum] + jne novesal + popad + ret + + novesal: + mov [novesachecksum],ecx + mov ecx,0 + movzx eax,word [0xfb0c] + cmp eax,100 + jge m13l3 + mov eax,100 + m13l3: + cmp eax,480-100 + jbe m13l4 + mov eax,480-100 + m13l4: + sub eax,100 + imul eax,640*4 + add ecx,eax + movzx eax,word [0xfb0a] + cmp eax,160 + jge m13l1 + mov eax,160 + m13l1: + cmp eax,640-160 + jbe m13l2 + mov eax,640-160 + m13l2: + sub eax,160 + shl eax,2 + add ecx,eax + mov esi,[0xfe80] + add esi,ecx + mov edi,0xa0000 + mov edx,200 + mov ecx,320 + cld + m13pix: + lodsd + push eax + mov ebx,eax + and eax,(128+64+32) ; blue + shr eax,5 + and ebx,(128+64+32)*256 ; green + shr ebx,8+2 + add eax,ebx + pop ebx + and ebx,(128+64)*256*256 ; red + shr ebx,8+8 + add eax,ebx + stosb + loop m13pix + mov ecx,320 + add esi,4*(640-320) + dec edx + jnz m13pix + + popad + ret + + +palette320x200: + + mov edx,0x3c8 + xor eax, eax + out dx,al + mov ecx,256 + mov edx,0x3c9 + xor eax,eax + + palnew: + mov al,0 + test ah,64 + jz pallbl1 + add al,21 + pallbl1: + test ah,128 + jz pallbl2 + add al,42 + pallbl2: + out dx,al + mov al,0 + test ah,8 + jz pallbl3 + add al,8 + pallbl3: + test ah,16 + jz pallbl4 + add al,15 + pallbl4: + test ah,32 + jz pallbl5 + add al,40 + pallbl5: + out dx,al + mov al,0 + test ah,1 + jz pallbl6 + add al,8 + pallbl6: + test ah,2 + jz pallbl7 + add al,15 + pallbl7: + test ah,4 + jz pallbl8 + add al,40 + pallbl8: + out dx,al + add ah,1 + loop palnew + + ret + +set_variables: + + mov ecx,0x100 ; flush port 0x60 +.fl60: in al,0x60 + loop .fl60 + mov [0xfcff],byte 0 ; mouse buffer + mov [0xf400],byte 0 ; keyboard buffer + mov [0xf500],byte 0 ; button buffer +; mov [0xfb0a],dword 100*65536+100 ; mouse x/y + + push eax + mov ax,[0x2f0000+0x900c] + shr ax,1 + shl eax,16 + mov ax,[0x2f0000+0x900A] + shr ax,1 + mov [0xfb0a],eax + pop eax + + mov byte [SB16_Status],0 ; Minazzi Paolo + mov [display_data-12],dword 1 ; tiled background + mov [0xfe88],dword 0x2C0000 ; address of button list + + ;!! IP 04.02.2005: + mov [next_usage_update], 100 + mov byte [0xFFFF], 0 ; change task if possible + + ret + +;* mouse centered - start code- Mario79 +mouse_centered: + push eax + mov eax,[0xFE00] + shr eax,1 + mov [0xFB0A],ax + mov eax,[0xFE04] + shr eax,1 + mov [0xFB0C],ax + pop eax + ret +;* mouse centered - end code- Mario79 + +align 4 + +sys_outport: + + mov edi,ebx ; separate flag for read / write + and ebx,65535 + + mov ecx,[0x2d0000] + test ecx,ecx + jne sopl8 + mov [esp+36],dword 1 + ret + + sopl8: + mov edx,[0x3010] + mov edx,[edx+0x4] + and ebx,65535 + cld + sopl1: + + mov esi,ecx + shl esi,4 + add esi,0x2d0000 + cmp edx,[esi+0] + jne sopl2 + cmp ebx,[esi+4] + jb sopl2 + cmp ebx,[esi+8] + jg sopl2 + jmp sopl3 + + sopl2: + + dec ecx + jnz sopl1 + mov [esp+36],dword 1 + ret + + sopl3: + + test edi,0x80000000 ; read ? + jnz sopl4 + + mov dx,bx ; write + out dx,al + mov [esp+36],dword 0 + ret + + sopl4: + + mov dx,bx ; read + in al,dx + and eax,0xff + mov [esp+36],dword 0 + mov [esp+24],eax + ret + + + +align 4 +sys_sb16: + + cmp word [sb16],word 0 + jnz sb16l1 + mov [esp+36],dword 1 + ret + sb16l1: + mov [esp+36],dword 0 + cmp eax,1 ; set volume - main + jnz sb16l2 + mov dx,word [sb16] + add dx,4 + mov al,0x22 + out dx,al + mov esi,1 + call delay_ms + mov eax,ebx + inc edx + out dx,al + ret + sb16l2: + + cmp eax,2 ; set volume - cd + jnz sb16l3 + mov dx,word [sb16] + add dx,4 + mov al,0x28 + out dx,al + mov esi,1 + call delay_ms + mov eax,ebx + add edx,1 + out dx,al + ret + sb16l3: + mov [esp+36],dword 2 + ret + + +align 4 + +sys_sb16II: + + cmp word [sb16],word 0 + jnz IIsb16l1 + mov [esp+36],dword 1 + ret + IIsb16l1: + + cmp eax,1 ; set volume - main + jnz IIsb16l2 + ; L + mov dx,word [sb16] + add dx,4 + mov al,0x30 + out dx,al + mov eax,ebx + inc edx + out dx,al + ; R + mov dx,word [sb16] + add dx,4 + mov al,0x31 + out dx,al + mov eax,ebx + inc edx + out dx,al + mov [esp+36],dword 0 + ret + IIsb16l2: + + cmp eax,2 ; set volume - cd + jnz IIsb16l3 + ; L + mov dx,word [sb16] + add dx,4 + mov al,0x36 + out dx,al + mov eax,ebx + inc edx + out dx,al + ; R + mov dx,word [sb16] + add dx,4 + mov al,0x37 + out dx,al + mov eax,ebx + inc edx + out dx,al + mov [esp+36],dword 0 + ret + IIsb16l3: + + mov [esp+36],dword 2 + ret + + +align 4 + +sys_wss: + + cmp word [wss],word 0 + jnz wssl1 + mov [esp+36],dword 1 + ret + wssl1: + + cmp eax,1 ; set volume - main + jnz wssl2 + mov [esp+36],dword 0 + ret + wssl2: + + cmp eax,2 ; set volume - cd + jnz wssl3 + ; L + mov dx,word [wss] + add dx,4 + mov al,0x2 + out dx,al + mov esi,1 + call delay_ms + mov eax,ebx + inc edx + out dx,al + ; R + mov dx,word [wss] + add dx,4 + mov al,0x3 + out dx,al + mov esi,1 + call delay_ms + mov eax,ebx + inc edx + out dx,al + mov [esp+36],dword 0 + ret + wssl3: + mov [esp+36],dword 2 + ret + +display_number: + +; eax = print type, al=0 -> ebx is number +; al=1 -> ebx is pointer +; ah=0 -> display decimal +; ah=1 -> display hexadecimal +; ah=2 -> display binary +; eax bits 16-21 = number of digits to display (0-32) +; eax bits 22-31 = reserved +; +; ebx = number or pointer +; ecx = x shl 16 + y +; edx = color + + cmp eax,0xffff ; length > 0 ? + jge cont_displ + ret + cont_displ: + + cmp eax,60*0x10000 ; length <= 60 ? + jbe cont_displ2 + ret + cont_displ2: + + pushad + + cmp al,1 ; ecx is a pointer ? + jne displnl1 + mov edi,[0x3010] + mov edi,[edi+0x10] + mov ebx,[edi+ebx] + displnl1: + sub esp,64 + + cmp ah,0 ; DECIMAL + jne no_display_desnum + shr eax,16 + and eax,0x2f + push eax + ;mov edi,[0x3010] + ;mov edi,[edi+0x10] + mov edi,esp + add edi,4+64 + mov ecx,eax + mov eax,ebx + mov ebx,10 + d_desnum: + xor edx,edx + div ebx + add dl,48 + mov [edi],dl + dec edi + loop d_desnum + pop eax + call draw_num_text + add esp,64 + popad + ret + no_display_desnum: + + cmp ah,0x01 ; HEXADECIMAL + jne no_display_hexnum + shr eax,16 + and eax,0x2f + push eax + ;mov edi,[0x3010] + ;mov edi,[edi+0x10] + mov edi,esp + add edi,4+64 + mov ecx,eax + mov eax,ebx + mov ebx,16 + d_hexnum: + xor edx,edx + div ebx + add edx,hexletters + mov dl,[edx] + mov [edi],dl + dec edi + loop d_hexnum + pop eax + call draw_num_text + add esp,64 + popad + ret + no_display_hexnum: + + cmp ah,0x02 ; BINARY + jne no_display_binnum + shr eax,16 + and eax,0x2f + push eax + ;mov edi,[0x3010] + ;mov edi,[edi+0x10] + mov edi,esp + add edi,4+64 + mov ecx,eax + mov eax,ebx + mov ebx,2 + d_binnum: + xor edx,edx + div ebx + add dl,48 + mov [edi],dl + dec edi + loop d_binnum + pop eax + call draw_num_text + add esp,64 + popad + ret + no_display_binnum: + + add esp,64 + popad + ret + + +draw_num_text: + + ; dtext + ; + ; eax x & y + ; ebx color + ; ecx start of text + ; edx length + ; edi 1 force + + mov edx,eax + mov ecx,65 + sub ecx,eax + add ecx,esp + add ecx,4 + mov eax,[esp+64+32-8+4] + mov ebx,[esp+64+32-12+4] + push edx ; add window start x & y + push ebx + mov edx,[0x3010] + mov ebx,[edx-twdw] + shl ebx,16 + add ebx,[edx-twdw+4] + add eax,ebx + pop ebx + pop edx + mov edi,0 + call dtext + + ret + + +read_string: + + ; eax read_area + ; ebx color of letter + ; ecx color of background + ; edx number of letters to read + ; esi [x start]*65536 + [y_start] + + ret + + +align 4 + +sys_setup: + +; 1=roland mpu midi base , base io address +; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus +; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 4=sb16 base , base io address +; 5=system language, 1eng 2fi 3ger 4rus +; 6=wss base , base io address +; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 8=fat32 partition in hd +; 9 +; 10 = sound dma channel +; 11 = enable lba read +; 12 = enable pci access + + + mov [esp+36],dword 0 + cmp eax,1 ; MIDI + jnz nsyse1 + cmp ebx,0x100 + jb nsyse1 + mov edx,65535 + cmp edx,ebx + jb nsyse1 + mov [midi_base],bx + mov word [mididp],bx + inc bx + mov word [midisp],bx + ret + +midi_base dw 0 + + nsyse1: + + cmp eax,2 ; KEYBOARD + jnz nsyse2 + cmp ebx,1 + jnz kbnobase + mov edi,[0x3010] + add ecx,[edi+0x10] + mov eax,ecx + mov ebx,keymap + mov ecx,128 + call memmove + ret + kbnobase: + cmp ebx,2 + jnz kbnoshift + mov edi,[0x3010] + add ecx,[edi+0x10] + mov eax,ecx + mov ebx,keymap_shift + mov ecx,128 + call memmove + ret + kbnoshift: + cmp ebx,3 + jne kbnoalt + mov edi,[0x3010] + add ecx,[edi+0x10] + mov eax,ecx + mov ebx,keymap_alt + mov ecx,128 + call memmove + ret + kbnoalt: + cmp ebx,9 + jnz kbnocountry + mov word [keyboard],cx + ret + kbnocountry: + mov [esp+36],dword 1 + ret + nsyse2: + cmp eax,3 ; CD + jnz nsyse3 + mov [cd_base],bl + cmp ebx,1 + jnz noprma + mov [cdbase],0x1f0 + mov [cdid],0xa0 + noprma: + cmp ebx,2 + jnz noprsl + mov [cdbase],0x1f0 + mov [cdid],0xb0 + noprsl: + cmp ebx,3 + jnz nosema + mov [cdbase],0x170 + mov [cdid],0xa0 + nosema: + cmp ebx,4 + jnz nosesl + mov [cdbase],0x170 + mov [cdid],0xb0 + nosesl: + ret + +cd_base db 0 + + nsyse3: + + cmp eax,4 ; SB + jnz nsyse4 + cmp ebx,0x100 + jb nsyse4 + mov edx,65535 + cmp edx,ebx + jb nsyse4 + mov word [sb16],bx + ret + nsyse4: + + cmp eax,5 ; SYSTEM LANGUAGE + jnz nsyse5 + mov [syslang],ebx + ret + nsyse5: + + cmp eax,6 ; WSS + jnz nsyse6 + cmp ebx,0x100 + jb nsyse6 + mov [wss],ebx + ret + +wss_temp dd 0 + + nsyse6: + + cmp eax,7 ; HD BASE + jne nsyse7 + mov [hd_base],bl + cmp ebx,1 + jnz noprmahd + mov [hdbase],0x1f0 + mov [hdid],0x0 + mov [hdpos],1 +; call set_FAT32_variables + noprmahd: + cmp ebx,2 + jnz noprslhd + mov [hdbase],0x1f0 + mov [hdid],0x10 + mov [hdpos],2 +; call set_FAT32_variables + noprslhd: + cmp ebx,3 + jnz nosemahd + mov [hdbase],0x170 + mov [hdid],0x0 + mov [hdpos],3 +; call set_FAT32_variables + nosemahd: + cmp ebx,4 + jnz noseslhd + mov [hdbase],0x170 + mov [hdid],0x10 + mov [hdpos],4 +; call set_FAT32_variables + noseslhd: + mov [0xfe10],dword 0 + call reserve_hd1 + call clear_hd_cache + mov [hd1_status],0 ; free + ret + +hd_base db 0 + + nsyse7: + + cmp eax,8 ; HD PARTITION + jne nsyse8 + mov [fat32part],ebx +; call set_FAT32_variables + call reserve_hd1 + call clear_hd_cache + pusha + call choice_necessity_partition_1 + popa + mov [hd1_status],0 ; free + ret + nsyse8: + + cmp eax,10 ; SOUND DMA CHANNEL + jne no_set_sound_dma + mov [sound_dma],ebx + ret + no_set_sound_dma: + + cmp eax,11 ; ENABLE LBA READ + jne no_set_lba_read + and ebx,1 + mov [lba_read_enabled],ebx + ret + no_set_lba_read: + + cmp eax,12 ; ENABLE PCI ACCESS + jne no_set_pci_access + and ebx,1 + mov [pci_access_enabled],ebx + ret + no_set_pci_access: + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +include 'vmodeint.inc' +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + mov [esp+36],dword -1 + ret + + +align 4 + +sys_getsetup: + +; 1=roland mpu midi base , base io address +; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus +; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 4=sb16 base , base io address +; 5=system language, 1eng 2fi 3ger 4rus +; 6=wss base +; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 8=fat32 partition in hd +; 9=get hs timer tic + + cmp eax,1 + jne ngsyse1 + movzx eax,[midi_base] + mov [esp+36],eax + ret + ngsyse1: + + cmp eax,2 + jne ngsyse2 + cmp ebx,1 + jnz kbnobaseret + mov edi,[0x3010] + add ecx,[edi+0x10] + mov ebx,ecx + mov eax,keymap + mov ecx,128 + call memmove + ret + kbnobaseret: + cmp ebx,2 + jnz kbnoshiftret + mov edi,[0x3010] + add ecx,[edi+0x10] + mov ebx,ecx + mov eax,keymap_shift + mov ecx,128 + call memmove + ret + kbnoshiftret: + cmp ebx,3 + jne kbnoaltret + mov edi,[0x3010] + add ecx,[edi+0x10] + mov ebx,ecx + mov eax,keymap_alt + mov ecx,128 + call memmove + ret + kbnoaltret: + cmp ebx,9 + jnz ngsyse2 + movzx eax,word [keyboard] + mov [esp+36],eax + ret + ngsyse2: + + cmp eax,3 + jnz ngsyse3 + movzx eax,[cd_base] + mov [esp+36],eax + ret + ngsyse3: + + cmp eax,4 + jne ngsyse4 + mov eax,[sb16] + mov [esp+36],eax + ret + ngsyse4: + + cmp eax,5 + jnz ngsyse5 + mov eax,[syslang] + mov [esp+36],eax + ret + ngsyse5: + cmp eax,6 + jnz ngsyse6 + mov eax,[wss] + mov [esp+36],eax + ret + ngsyse6: + cmp eax,7 + jnz ngsyse7 + movzx eax,[hd_base] + mov [esp+36],eax + ret + ngsyse7: + cmp eax,8 + jnz ngsyse8 + mov eax,[fat32part] + mov [esp+36],eax + ret + ngsyse8: + cmp eax,9 + jne ngsyse9 + mov eax,[timer_ticks] ;[0xfdf0] + mov [esp+36],eax + ret + ngsyse9: + cmp eax,10 + jnz ngsyse10 + mov eax,[sound_dma] + mov [esp+36],eax + ret + ngsyse10: + cmp eax,11 + jnz ngsyse11 + mov eax,[lba_read_enabled] + mov [esp+36],eax + ret + ngsyse11: + cmp eax,12 + jnz ngsyse12 + mov eax,[pci_access_enabled] + mov [esp+36],eax + ret + ngsyse12: + mov [esp+36],dword 1 + ret + + +align 4 + +readmousepos: + +; eax=0 screen relative +; eax=1 window relative +; eax=2 buttons pressed + + test eax,eax + jnz nosr + mov eax,[0xfb0a] + shl eax,16 + mov ax,[0xfb0c] + mov [esp+36],eax + ret + nosr: + + cmp eax,1 + jnz nowr + mov eax,[0xfb0a] + shl eax,16 + mov ax,[0xfb0c] + mov esi,[0x3010] + sub esi,twdw + mov bx,[esi] + shl ebx,16 + mov bx,[esi+4] + sub eax,ebx + mov [esp+36],eax + ret + nowr: + + cmp eax,2 + jnz nomb + movzx eax,byte [0xfb40] + nomb: + mov [esp+36],eax + + ret + +is_input: + + push edx + mov dx,word [midisp] + in al,dx + and al,0x80 + pop edx + ret + + +is_output: + + push edx + mov dx,word [midisp] + in al,dx + and al,0x40 + pop edx + ret + + +get_mpu_in: + + push edx + mov dx,word [mididp] + in al,dx + pop edx + ret + + +put_mpu_out: + + push edx + mov dx,word [mididp] + out dx,al + pop edx + ret + + +setuart: + + su1: + call is_output + cmp al,0 + jnz su1 + mov dx,word [midisp] + mov al,0xff + out dx,al + su2: + mov dx,word [midisp] + mov al,0xff + out dx,al + call is_input + cmp al,0 + jnz su2 + call get_mpu_in + cmp al,0xfe + jnz su2 + su3: + call is_output + cmp al,0 + jnz su3 + mov dx,word [midisp] + mov al,0x3f + out dx,al + + ret + + +align 4 + +sys_midi: + + cmp [mididp],0 + jnz sm0 + mov [esp+36],dword 1 + ret + sm0: + + cmp eax,1 + mov [esp+36],dword 0 + jnz smn1 + call setuart + ret + smn1: + + cmp eax,2 + jnz smn2 + sm10: + call get_mpu_in + call is_output + test al,al + jnz sm10 + mov al,bl + call put_mpu_out + ret + smn2: + + ret + + +detect_devices: +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +include 'detect/commouse.inc' +;include 'detect/dev_fd.inc' +;include 'detect/dev_hdcd.inc' +;include 'detect/sear_par.inc' +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ret + + +sys_end: + + mov eax,[0x3010] + add eax,0xa + mov [eax],byte 3 ; terminate this program + + waitterm: ; wait here for termination + mov eax,5 + call delay_hs + jmp waitterm + +sys_system: + + cmp eax,1 ; BOOT + jnz nosystemboot + mov [0x2f0000+0x9030],byte 0 + for_shutdown_parameter: + mov eax,[0x3004] + add eax,2 + mov [shutdown_processes],eax + mov [0xFF00],al + xor eax, eax + ret + uglobal + shutdown_processes: dd 0x0 + endg + nosystemboot: + + cmp eax,2 ; TERMINATE + jnz noprocessterminate + cmp ebx,2 + jb noprocessterminate + mov edx,[0x3004] + cmp ebx,edx + jg noprocessterminate + mov eax,[0x3004] + shl ebx,5 + mov edx,[ebx+0x3000+4] + add ebx,0x3000+0xa + + ;call MEM_Heap_Lock ;guarantee that process isn't working with heap + mov [ebx],byte 3 ; clear possible i40's + ;call MEM_Heap_UnLock + + cmp edx,[application_table_status] ; clear app table stat + jne noatsc + mov [application_table_status],0 + noatsc: + ret + noprocessterminate: + + cmp eax,3 ; ACTIVATE WINDOW + jnz nowindowactivate + cmp ebx,2 + jb nowindowactivate + cmp ebx,[0x3004] + ja nowindowactivate + ; edi = position at window_data+ + mov edi, ebx ; edi = process number + ;shl ebx, 1 + ;add ebx, 0xc000 + ;mov esi, [ebx] ; esi = window stack value + ;and esi, 0xffff ; word + movzx esi, word [0xC000 + ebx*2] + mov edx, [0x3004] ; edx = number of processes + cmp esi, edx + jz nowindowactivate ; continue if window_stack_value != number_of_processes + ; i.e. if window is not already active + +;* start code - get active process (1) - Mario79 + mov [window_minimize],2 + mov [active_process],edi +;* end code - get active process (1) - Mario79 + + mov [0xff01],edi ; activate + xor eax, eax + ret + + nowindowactivate: + + cmp eax,4 ; GET IDLETIME + jnz nogetidletime + mov eax,[idleusesec] + ret + nogetidletime: + + cmp eax,5 ; GET TSC/SEC + jnz nogettscsec + mov eax,[0xf600] + ret + nogettscsec: + +; SAVE ramdisk to /hd/1/menuet.img +;!!!!!!!!!!!!!!!!!!!!!!!! + include 'blkdev/rdsave.inc' +;!!!!!!!!!!!!!!!!!!!!!!!! +;* start code - get active process (2) - Mario79 + cmp eax,7 + jnz nogetactiveprocess + mov eax,[active_process] + ret + nogetactiveprocess: + cmp eax,8 + jnz nosoundflag + cmp ebx,1 + jne nogetsoundflag + movzx eax,byte [sound_flag] ; get sound_flag + ret + nogetsoundflag: + cmp ebx,2 + jnz nosoundflag + inc byte [sound_flag] ; set sound_flag + and byte [sound_flag],1 ; + ret +nosoundflag: + cmp eax,9 ; system shutdown with param + jnz noshutdownsystem + cmp ebx,1 + jl exit_for_anyone + cmp ebx,4 + jg exit_for_anyone + mov [0x2f0000+0x9030],bl + jmp for_shutdown_parameter +noshutdownsystem: + cmp eax,10 ; minimize window + jnz nominimizewindow + mov [window_minimize],1 + exit_for_anyone: + ret +nominimizewindow: + cmp eax,11 ; get disk info table + jnz nogetdiskinfo + cmp ebx,1 + jnz full_table + small_table: + call for_all_tables + mov cx,10 + cld + rep movsb + ret + for_all_tables: + mov edi,[3010h] + mov edi,[edi+10h] + add edi,ecx + mov esi,0x40000 + xor ecx,ecx + ret + full_table: + cmp ebx,2 + jnz exit_for_anyone + call for_all_tables + mov cx,16384 + cld + rep movsd + ret +nogetdiskinfo: + cmp eax,12 ; get all key pressed with ALT + jnz nogetkey + mov eax,[last_key_press] + mov al,[keyboard_mode_sys] + mov [esp+36],eax + mov [last_key_press],0 + .finish: + ret +nogetkey: + cmp eax,13 ; get kernel ID and version + jnz nogetkernel_id + mov edi,[3010h] + mov edi,[edi+10h] + add edi,ebx + mov esi,version_inf + mov ecx,version_end-version_inf + cld + rep movsb + ret +nogetkernel_id: + cmp eax,14 ; sys wait retrace + jnz nosys_wait_retrace + ;wait retrace functions + sys_wait_retrace: + mov edx,0x3da + WaitRetrace_loop: + in al,dx + test al,1000b + jz WaitRetrace_loop + mov [esp+36],dword 0 + ret +nosys_wait_retrace: + cmp eax,15 ; mouse centered + jnz no_mouse_centered + call mouse_centered + mov [esp+36],dword 0 + ret +no_mouse_centered: +;* end code - get active process (2) - Mario79 + ret +window_minimize db 0 +sound_flag db 0 +last_key_press dd 0 +keyboard_mode_sys db 0 + +iglobal +version_inf: + db 0,5,0,0 ; version 0.5.0.0 + db UID_KOLIBRI + db 'Kolibri',0 +version_end: +endg + +UID_NONE=0 +UID_MENUETOS=1 ;official +UID_KOLIBRI=2 ;russian + +main_loop_sys_getkey: + cmp [0xf400],byte 0 + je .finish + movzx eax,byte [0xf401] + shl eax,8 + mov [last_key_press],eax + .finish: + ret + +sys_cachetodiskette: + pushad + cmp eax,1 + jne no_write_all_of_ramdisk + + call fdc_writeramdisk + popad + ret + no_write_all_of_ramdisk: + cmp eax,2 + jne no_write_part_of_ramdisk + call fdc_commitflush + popad + ret + no_write_part_of_ramdisk: + cmp eax,3 + jne no_set_fdc + call fdc_set + popad + ret + no_set_fdc: + cmp eax,4 + jne no_get_fdc + popad + call fdc_get + mov [esp+36],ecx + ret + no_get_fdc: + popad + ret + +uglobal +; bgrchanged dd 0x0 +endg + +sys_background: + + cmp eax,1 ; BACKGROUND SIZE + jnz nosb1 + cmp ebx,0 + je sbgrr + cmp ecx,0 + je sbgrr + mov [display_data-8],ebx + mov [display_data-4],ecx +; mov [bgrchanged],1 + sbgrr: + ret + nosb1: + + cmp eax,2 ; SET PIXEL + jnz nosb2 + mov edx,0x160000-16 + cmp edx,ebx + jbe nosb2 + mov edx,[ebx] + and edx,0xFF000000 ;255*256*256*256 + and ecx,0x00FFFFFF ;255*256*256+255*256+255 + add edx,ecx + mov [ebx+0x300000],edx +; mov [bgrchanged],1 + ret + nosb2: + + cmp eax,3 ; DRAW BACKGROUND + jnz nosb3 +draw_background_temp: +; cmp [bgrchanged],1 ;0 +; je nosb31 +;draw_background_temp: +; mov [bgrchanged],1 ;0 + mov [0xfff0],byte 1 + nosb31: + ret + nosb3: + + cmp eax,4 ; TILED / STRETCHED + jnz nosb4 + cmp ebx,[display_data-12] + je nosb41 + mov [display_data-12],ebx +; mov [bgrchanged],1 + nosb41: + ret + nosb4: + + cmp eax,5 ; BLOCK MOVE TO BGR + jnz nosb5 + ; bughere + mov edi, [0x3010] + add ebx, [edi+0x10] + ; mov esi, ebx + ; mov edi, ecx + mov eax, ebx + mov ebx, ecx + add ecx, edx + cmp ecx, 0x160000-16 + ja .fin + ; add edi, 0x300000 + add ebx, 0x300000 + mov ecx, edx + cmp ecx, 0x160000-16 + ja .fin +; mov [bgrchanged],1 + ; cld + ; rep movsb + call memmove + .fin: + ret + nosb5: + + ret + + +align 4 + +sys_getbackground: + + cmp eax,1 ; SIZE + jnz nogb1 + mov eax,[display_data-8] + shl eax,16 + mov ax,[display_data-4] + mov [esp+36],eax + ret + nogb1: + + cmp eax,2 ; PIXEL + jnz nogb2 + mov edx,0x160000-16 + cmp edx,ebx + jbe nogb2 + mov eax, [ebx+0x300000] + and eax, 0xFFFFFF + mov [esp+36],eax + ret + nogb2: + + cmp eax,4 ; TILED / STRETCHED + jnz nogb4 + mov eax,[display_data-12] + nogb4: + mov [esp+36],eax + ret + + +align 4 + +sys_getkey: + mov [esp+36],dword 1 + mov ebx, [0x3000] ; TOP OF WINDOW STACK + movzx ecx,word [0xC000 + ebx * 2] + mov edx,[0x3004] + cmp ecx,edx + jne .finish + cmp [0xf400],byte 0 + je .finish + movzx eax,byte [0xf401] + shl eax,8 + push eax + dec byte [0xf400] + and byte [0xf400],127 + movzx ecx,byte [0xf400] + add ecx,2 + ; mov esi,0xf402 + ; mov edi,0xf401 + ; cld + ; rep movsb + mov eax, 0xF402 + mov ebx, 0xF401 + call memmove + pop eax + mov [last_key_press],eax + + mov eax,[kb_state] + and al,110000b + cmp al,100000b + je .yes_win_key + cmp al,10000b + je .yes_win_key + mov eax,[last_key_press] + jmp .no_win_key +; cmp ah,232 +; je .yes_win_key +; cmp ah,233 +; jne .no_win_key + .yes_win_key: + mov eax,1 + .no_win_key: + mov [esp+36],eax + .finish: + ret + + +align 4 + +sys_getbutton: + + mov ebx, [0x3000] ; TOP OF WINDOW STACK + mov [esp+36],dword 1 + movzx ecx, word [0xC000 + ebx * 2] + mov edx, [0x3004] ; less than 256 processes + cmp ecx,edx + jne .exit + movzx eax,byte [0xf500] + test eax,eax + jz .exit + mov eax,[0xf501] + shl eax,8 + mov [0xf500],byte 0 + mov [esp+36],eax + .exit: + ret + + +align 4 + +sys_cpuusage: + +; RETURN: +; +; +00 dword process cpu usage +; +04 word position in windowing stack +; +06 word windowing stack value at current position (cpu nro) +; +10 12 bytes name +; +22 dword start in mem +; +26 dword used mem +; +30 dword PID , process idenfification number +; + + mov edi,[0x3010] ; eax = return area + add edi,0x10 + add eax,[edi] + + cmp ebx,-1 ; who am I ? + jne no_who_am_i + mov ebx,[0x3000] + no_who_am_i: + + push eax ; return area + push ebx ; process number + + push ebx + push ebx + push eax + + ; return memory usage + + xor edx,edx + mov eax,0x20 + mul ebx + add eax,0x3000+0x1c + mov ebx,eax + pop eax + mov ecx,[ebx] + mov [eax],ecx + pop ebx +; mov ebx,[esp] +; shl ebx,1 +; add ebx,0xc000 + mov cx, [0xC000 + ebx * 2] + mov [eax+4],cx +; mov ebx,[esp] +; shl ebx,1 +; add ebx,0xc400 + mov cx, [0xC400 + ebx * 2] + mov [eax+6],cx +; pop ebx + push eax + mov eax,ebx + shl eax,8 + add eax,0x80000 + pop ebx + add ebx,10 + mov ecx,11 + call memmove + + ; memory usage + + xor eax,eax + mov edx,0x100000*16 + pop ecx ; get gdt of tss + cmp ecx,1 + je os_mem + shl ecx,8 + mov edx,[0x80000+ecx+0x8c] + mov eax,std_application_base_address + ;add ecx,0x80000+0x88 + ;mov ecx,[ecx] +; shl ecx,3 + ; eax run base -> edx used memory +; mov al,[ecx+gdts+ app_code-3 +4] ; base 23:16 +; mov ah,[ecx+gdts+ app_code-3 +7] ; base 31:24 +; shl eax,16 +; mov ax,[ecx+gdts+ app_code-3 +2] ; base 0:15 +; movzx edx,word [ecx+gdts+ app_code-3 +0] +; shl edx,12 + + os_mem: + dec edx + mov [ebx+12],eax + mov [ebx+16],edx + + ; PID (+30) + + mov eax,[esp] + shl eax,5 + add eax,0x3000+0x4 + mov eax,[eax] + mov [ebx+20],eax + + ; window position and size + + mov esi,[esp] + shl esi,5 + add esi,window_data + mov edi,[esp+4] + add edi,34 + mov ecx,4*4 + cld + rep movsb + + ; Process state (+50) + + mov eax,[esp] + shl eax,5 + add eax,0x3000+0xa + mov eax,[eax] + mov [ebx+40],ax + + + pop ebx + pop eax + + ; return number of processes + + mov eax,[0x3004] + mov [esp+36],eax + ret + + + + +align 4 +sys_clock: + cli + ; Mikhail Lisovin xx Jan 2005 + @@: mov al, 10 + out 0x70, al + in al, 0x71 + test al, al + jns @f + mov esi, 1 + call delay_ms + jmp @b + @@: + ; end Lisovin's fix + + xor al,al ; seconds + out 0x70,al + in al,0x71 + movzx ecx,al + mov al,02 ; minutes + shl ecx,16 + out 0x70,al + in al,0x71 + movzx edx,al + mov al,04 ; hours + shl edx,8 + out 0x70,al + in al,0x71 + add ecx,edx + movzx edx,al + add ecx,edx + sti + mov [esp+36],ecx + ret + + +align 4 + +sys_date: + + cli + mov al,6 ; day of week + out 0x70,al + in al,0x71 + mov ch,al + mov al,7 ; date + out 0x70,al + in al,0x71 + mov cl,al + mov al,8 ; month + shl ecx,16 + out 0x70,al + in al,0x71 + mov ch,al + mov al,9 ; year + out 0x70,al + in al,0x71 + mov cl,al + sti + mov [esp+36],ecx + ret + + +; redraw status + +sys_redrawstat: + + cmp eax,1 + jne no_widgets_away + + ; buttons away + + mov ecx,[0x3000] + + sys_newba2: + + mov edi,[0xfe88] + cmp [edi],dword 0 ; empty button list ? + je end_of_buttons_away + + movzx ebx,word [edi] + inc ebx + + mov eax,edi + + sys_newba: + + dec ebx + jz end_of_buttons_away + + add eax,0x10 + cmp cx,[eax] + jnz sys_newba + + push eax ebx ecx + mov ecx,ebx + inc ecx + shl ecx,4 + mov ebx,eax + add eax,0x10 + call memmove + dec dword [edi] + pop ecx ebx eax + + jmp sys_newba2 + + end_of_buttons_away: + + ret + + no_widgets_away: + + cmp eax,2 + jnz srl1 + + mov edx,[0x3010] ; return whole screen draw area for this app + add edx,draw_data-0x3000 + mov [edx+0],dword 0 + mov [edx+4],dword 0 + mov eax,[0xfe00] + mov [edx+8],eax + mov eax,[0xfe04] + mov [edx+12],eax + + mov edi,[0x3010] + sub edi,twdw + mov [edi+30],byte 1 ; no new position & buttons from app + + call sys_window_mouse + + ret + + srl1: + + ret + + +sys_drawwindow: + + mov edi,ecx + shr edi,16+8 + and edi,15 + + cmp edi,0 ; type I - original style + jne nosyswI + call sys_set_window + call drawwindow_I + ret + nosyswI: + + cmp edi,1 ; type II - only reserve area, no draw + jne nosyswII + call sys_set_window + call sys_window_mouse + ret + nosyswII: + + cmp edi,2 ; type III - new style + jne nosyswIII + call sys_set_window + call drawwindow_III + ret + nosyswIII: + + cmp edi,3 ; type IV - skinned window + jne nosyswIV + call sys_set_window + call drawwindow_IV + ret + nosyswIV: + + ret + + +sys_set_window: + + mov edi,[0x3000] + shl edi,5 + add edi,window_data + + ; colors + mov [edi+16],ecx + mov [edi+20],edx + mov [edi+24],esi + + ; check flag (?) + cmp [edi+30],byte 1 + jz newd + + push eax + mov eax,[timer_ticks] ;[0xfdf0] + add eax,100 + mov [new_window_starting],eax + pop eax + + mov [edi+8],ax + mov [edi+12],bx + shr eax,16 + shr ebx,16 + mov [edi+00],ax + mov [edi+04],bx + + + call check_window_position + + + push ecx esi edi ; save for window fullscreen/resize + mov esi,edi + sub edi,window_data + shr edi,5 + shl edi,8 + add edi,0x80000+0x90 + mov ecx,4 + cld + rep movsd + pop edi esi ecx + + push eax ebx ecx edx +;;; mov eax, 1 +;;; call delay_hs + movzx eax, word [edi+00] + movzx ebx, word [edi+04] + movzx ecx, word [edi+8] + movzx edx, word [edi+12] + add ecx, eax + add edx, ebx + call calculatescreen + pop edx ecx ebx eax + + mov [0xf400],byte 0 ; empty keyboard buffer + mov [0xf500],byte 0 ; empty button buffer + + newd: + mov [edi+31],byte 0 ; no redraw + mov edx,edi + + ret + + +sys_window_move: + + cmp [window_move_pr],0 + je mwrl1 + + mov [esp+36],dword 1 ; return queue error + + ret + + mwrl1: + + mov edi,[0x3000] ; requestor process base + mov [window_move_pr],edi + + mov [window_move_eax],eax + mov [window_move_ebx],ebx + mov [window_move_ecx],ecx + mov [window_move_edx],edx + + mov [esp+36],dword 0 ; return success + + ret + +type_background_1: + cmp [0xfff0],byte 0 ; background update ? + jz temp_nobackgr + mov [0xfff0],byte 2 + call change_task + mov [draw_data+32+0],dword 0 + mov [draw_data+32+4],dword 0 + mov eax,[0xfe00] + mov ebx,[0xfe04] + mov [draw_data+32+8],eax + mov [draw_data+32+12],ebx + call drawbackground + mov [0xfff0],byte 0 + mov [0xfff4],byte 0 +temp_nobackgr: + ret + +uglobal + window_move_pr dd 0x0 + window_move_eax dd 0x0 + window_move_ebx dd 0x0 + window_move_ecx dd 0x0 + window_move_edx dd 0x0 +endg + +;ok - 100% work +;nt - not tested +;--------------------------------------------------------------------------------------------- +;eax +;0 - task switch counter. Ret switch counter in eax. Block. ok. +;1 - change task. Ret nothing. Block. ok. +;2 - performance control +; ebx +; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode. +; returned new cr4 in eax. Ret cr4 in eax. Block. ok. +; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok. +; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok. +; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok. +;eax +;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. +;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. +;--------------------------------------------------------------------------------------------- +sys_sheduler: ;noname & halyavin + cmp eax,0 + je shed_counter + cmp eax,2 + je perf_control + cmp eax,3 + je rdmsr_instr + cmp eax,4 + je wrmsr_instr + cmp eax,1 + jne not_supported + call change_task ;delay,0 +ret +shed_counter: + mov eax,[context_counter] + mov [esp+36],eax +not_supported: +ret +perf_control: + inc eax ;now eax=3 + cmp ebx,eax + je cache_disable + dec eax + cmp ebx,eax + je cache_enable + dec eax + cmp ebx,eax + je is_cache_enabled + dec eax + cmp ebx,eax + je modify_pce +ret + +rdmsr_instr: +;now counter in ecx +;(edx:eax) esi:edi => edx:esi +mov eax,esi +rdmsr +mov [esp+36],eax +mov [esp+24],edx ;ret in ebx? +ret + +wrmsr_instr: +;now counter in ecx +;(edx:eax) esi:edi => edx:esi +mov eax,esi +wrmsr +mov [esp+36],eax +mov [esp+24],edx ;ret in ebx? +ret + +cache_disable: + mov eax,cr0 + or eax,01100000000000000000000000000000b + mov cr0,eax + wbinvd ;set MESI +ret + +cache_enable: + mov eax,cr0 + and eax,10011111111111111111111111111111b + mov cr0,eax +ret + +is_cache_enabled: + mov eax,cr0 + mov ebx,eax + and eax,01100000000000000000000000000000b + jz cache_disabled + mov [esp+36],ebx +cache_disabled: + mov dword [esp+36],eax ;0 +ret + +modify_pce: + mov eax,cr4 +; mov ebx,0 +; or bx,100000000b ;pce +; xor eax,ebx ;invert pce + btr eax,8 ;pce=cr4[8] + mov cr4,eax + mov [esp+36],eax +ret +;--------------------------------------------------------------------------------------------- + +; check pixel limits + +;cplimit: +; push edi + +; cmp byte [0xe000], 1 ; Multitasking enabled? +; jnz .ret0 +; mov edi,[0x3010] +; add edi, draw_data-0x3000 +; mov ecx, 1 +; cmp [edi+0], eax ; xs +; ja .ret1 +; cmp [edi+4], ebx ; ys +; ja .ret1 +; cmp eax, [edi+8] ; xe +; ja .ret1 +; cmp ebx, [edi+12] ; ye +; ja .ret1 + +;.ret0: +; xor ecx, ecx +;.ret1: +; pop edi +; ret + + +; check if pixel is allowed to be drawn + +checkpixel: + + push eax + push ebx + push edx + +; mov ecx,[0x3000] ; process count +; shl ecx, 6 ; *64 +; add ecx,0xc000 ; +window_stack +; mov dx,word [ecx] ; window_stack_value + +; cmp dx, word [0x3004] ; is this window active right now?! +; jz .ret0 + +; call cplimit +; test ecx, ecx +; jnz .ret1 + + mov edx,[0xfe00] ; screen x size + inc edx + imul edx, ebx + mov dl, [eax+edx+display_data] ; lea eax, [...] +;;; mov dl,[eax] + + mov eax,[0x3000] + shl eax,5 + add eax,0x3000+0xe + + mov ecx, 1 + cmp byte [eax], dl + jnz .ret1 + +.ret0: + xor ecx, ecx +.ret1: + pop edx + pop ebx + pop eax + ret + +uglobal + mouse_active db 0 +endg +iglobal + cpustring db 'CPU ' +endg + + +align 4 +; check misc + +checkmisc: + + cmp [ctrl_alt_del], 1 + jne nocpustart + mov eax, cpustring + call start_application_fl + mov [ctrl_alt_del], 0 + nocpustart: + cmp [mouse_active], 1 + jne mouse_not_active + mov [mouse_active], 0 + xor edi, edi + mov ecx, [0x3004] + set_mouse_event: + add edi, 256 + or [edi+0x80000+0xA8], dword 00100000b + loop set_mouse_event + mouse_not_active: + + + cmp [0xfff0],byte 0 ; background update ? + jz nobackgr + mov [0xfff0],byte 2 + call change_task + mov [draw_data+32+0],dword 0 + mov [draw_data+32+4],dword 0 + mov eax,[0xfe00] + mov ebx,[0xfe04] + mov [draw_data+32+8],eax + mov [draw_data+32+12],ebx + call drawbackground + mov [0xfff0],byte 0 + mov [0xfff4],byte 0 + + nobackgr: + + + ; system shutdown request + + cmp [0xFF00],byte 0 + je noshutdown + + mov edx,[shutdown_processes] + sub dl,2 + + cmp [0xff00],dl + jne no_mark_system_shutdown + + mov edx,0x3040 + movzx ecx,byte [0xff00] + add ecx,5 + markz: + mov [edx+0xa],byte 3 + add edx,0x20 + loop markz + + no_mark_system_shutdown: + + call [disable_mouse] + + dec byte [0xff00] + + cmp [0xff00],byte 0 + je system_shutdown + + noshutdown: + + + mov eax,[0x3004] ; termination + mov ebx,0x3020+0xa + mov esi,1 + + newct: + mov cl,[ebx] + cmp cl,byte 3 + jz terminate + cmp cl,byte 4 + jz terminate + + add ebx,0x20 + inc esi + dec eax + jnz newct + + ret + + + + +; redraw screen + +redrawscreen: + +; eax , if process window_data base is eax, do not set flag/limits + + pushad + push eax + +;;; mov eax,2 +;;; call delay_hs + + ;mov ecx,0 ; redraw flags for apps + xor ecx,ecx + newdw2: + + inc ecx + push ecx + + mov eax,ecx + shl eax,5 + add eax,window_data + + cmp eax,[esp+4] + je not_this_task + ; check if window in redraw area + mov edi,eax + + cmp ecx,1 ; limit for background + jz bgli + + mov eax,[edi+0] + mov ebx,[edi+4] + mov ecx,[edi+8] + mov edx,[edi+12] + add ecx,eax + add edx,ebx + + mov ecx,[dlye] ; ecx = area y end ebx = window y start + cmp ecx,ebx + jb ricino + + mov ecx,[dlxe] ; ecx = area x end eax = window x start + cmp ecx,eax + jb ricino + + mov eax,[edi+0] + mov ebx,[edi+4] + mov ecx,[edi+8] + mov edx,[edi+12] + add ecx,eax + add edx,ebx + + mov eax,[dly] ; eax = area y start edx = window y end + cmp edx,eax + jb ricino + + mov eax,[dlx] ; eax = area x start ecx = window x end + cmp ecx,eax + jb ricino + + bgli: + + cmp edi,esi + jz ricino + + mov eax,edi + add eax,draw_data-window_data + + mov ebx,[dlx] ; set limits + mov [eax+0],ebx + mov ebx,[dly] + mov [eax+4],ebx + mov ebx,[dlxe] + mov [eax+8],ebx + mov ebx,[dlye] + mov [eax+12],ebx + + sub eax,draw_data-window_data + + cmp ecx,1 + jne nobgrd + cmp esi,1 + je newdw8 + call drawbackground + + newdw8: + nobgrd: + + mov [eax+31],byte 1 ; mark as redraw + + ricino: + + not_this_task: + + pop ecx + + cmp ecx,[0x3004] + jle newdw2 +; jg newdw3 +; jmp newdw2 + +; newdw3: + + pop eax + popad + + ret + +; check mouse +; +; +; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y +; FB10 -> FB17 mouse color mem +; FB21 x move +; FB22 y move +; FB30 color temp +; FB28 high bits temp +; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under +; FC00 -> FCFE com1/ps2 buffer +; FCFF com1/ps2 buffer count starting from FC00 + +uglobal + mousecount dd 0x0 + mousedata dd 0x0 +endg + + +check_mouse_data: + + pushad + + cmp [0xF604],byte 1 + jne no_ps2_mouse + mov [mousecount],dword 0x2e0000+12*4096 + mov [mousedata],dword 0x2e0000+12*4096+0x10 + jmp uusicheckmouse +no_ps2_mouse: + cmp [0xF604],byte 2 + jne no_com1_mouse + mov [mousecount],dword 0x2e0000+4*4096 + mov [mousedata],dword 0x2e0000+4*4096+0x10 + jmp uusicheckmouse +no_com1_mouse: + mov [mousecount],dword 0x2e0000+3*4096 + mov [mousedata],dword 0x2e0000+3*4096+0x10 + + uusicheckmouse: + + mov ebx,[mousecount] ; anything at buffer for mouse + cmp dword [ebx], 0 ; !!! + jz checkmouseret + + ; first byte of comX or ps2 ? + + cmp [0xF604],byte 1 + je ps2mousefirst + + ; ****************************************** + ; *********** COMX mouse driver ************ + ; ****************************************** + + com1mousefirst: + + mov edi,[mousedata] + mov dl,byte [edi] ; first com1 ? + test dl,64 + jz @f + mov [0xfb00],byte 0 ; zero mouse block count + @@: + xor ebx,ebx + + mov bl,[0xfb00] + inc bl + mov [0xfb00],bl + mov eax,0xfb00 + add eax,ebx + mov edi,[mousedata] + mov dl,byte [edi] + mov [eax],byte dl + cmp bl,3 ; three ? + jnz decm + + ; buttons + +;* change right and left button by places - start code - Mario79 + mov al,[0xfb01] + mov ah,al + shr al,3 + and al,2 + shr ah,5 + and ah,1 + add al,ah +;* change right and left button by places - end code - Mario79 + + mov [0xfb40],al + + ; com1 mouse + ; x + + mov dl,[0xfb01] ; x high bits + movzx eax,dl + and al,3 + shl al,6 + mov dl,byte[0xfb02] ; x low bits + add al,dl + mov [0xfb21],byte al + movzx ebx,word[0xfb0a] + + mov al,byte [0xfb01] ; + or - ? + test al,2 + jz x_add + + x_sub: ; x- + sub bx,255 + sub bx,255 + x_add: ; x+ + movzx eax,byte [0xfb21] + add bx,ax + add bx,ax + push ebx + mov [0xfb00],byte 0 + + ; y + + + my_event: + + mov dl,[0xfb01] ; y high bits + movzx eax,dl + and al,12 + shl al,4 + mov dl,byte[0xfb03] ; y low bits + add al,dl + mov [0xfb22],byte al + movzx ebx,word[0xfb0c] + + mov al,byte [0xfb01] ; + or - ? + test al,8 + je y_add + + y_sub: ; y- + sub bx,255 + sub bx,255 + y_add: ; y+ + movzx eax,byte [0xfb22] + add bx,ax + add bx,ax + push ebx + mov [0xfb00],byte 0 + jmp mdraw + + ; end of com1 mouse + + + ; ****************************************** + ; ******** PS2 MOUSE DRIVER ************** + ; ****************************************** + + ps2mousefirst: + + movzx edx,byte [0x2E0000+4096*12+0x10] ; first ps2 ? + cmp edx,40 + jne @f + mov [0xfb00],byte 0 ; zero mouse block count + @@: + + movzx ebx,byte [0xfb00] + add ebx,1 + mov [0xfb00],bl + mov eax,0xfb00 + add eax,ebx + mov dl,byte [0x2E0000+4096*12+0x10] + mov [eax],byte dl + + cmp bl,3 ; full packet of three bytes ? + jnz decm +; jz ps2mouse +; jmp decm + + +; ps2mouse: + + mov [0xfb00],byte 0 ; zero mouse block count + + ; buttons + + movzx eax,byte [0xfb01] + and eax,3 + mov [0xfb40],al + + ; x + + movzx eax,word [0xfb0a] + movzx edx,byte [0xfb02] + cmp edx,128 + jb ps2xp + shl edx,1 + add eax,edx + cmp eax,512 + jge ps2xsok + xor eax, eax + jmp ps2xready + ps2xsok: + sub eax,512 + jmp ps2xready + ps2xp: + shl edx,1 + add eax,edx + jmp ps2xready + ps2xready: + push eax + + ; y + + movzx eax,word [0xfb0c] + movzx edx,byte [0xfb03] + cmp edx,128 + jb ps2yp + add eax,512 + shl edx,1 + sub eax,edx + jmp ps2yready + ps2yp: + shl edx,1 + cmp edx,eax + jb ps201 + mov edx,eax + ps201: + sub eax,edx + jmp ps2yready + ps2yready: + push eax + + ;jmp mdraw + + ; end of ps2 mouse + + + ; **************************** + ; ***** CHECK FOR LIMITS ***** + ; **************************** + + mdraw: + + cmp [0xfb44],byte 0 + jne mousedraw4 + cmp [0xfb40],byte 0 + je mousedraw4 + mov [0xfff5],byte 1 + + mousedraw4: + + pop ebx + pop eax + + mov [mouse_active],1 + +; mov dx,0 ; smaller than zero + xor dx,dx + cmp bx,dx + jge mnb11 +; mov bx,0 + xor bx,bx + mnb11: + mov [0xfb0c],word bx + +; mov dx,0 + xor dx,dx + cmp ax,dx + jge mnb22 +; mov ax,0 + xor ax,ax + mnb22: + mov [0xfb0a],word ax + + mov edx,[0xfe04] ; bigger than maximum + cmp ebx,edx + jb mnb1 + mov bx,[0xfe04] + mnb1: + mov [0xfb0c],word bx + + mov edx,[0xfe00] + cmp eax,edx + jb mnb2 + mov ax,[0xfe00] + mnb2: + mov [0xfb0a],word ax + + + ; **** NEXT DATA BYTE FROM MOUSE BUFFER **** + + decm: + + mov edi,[mousecount] ; decrease counter + dec dword [edi] + + mov esi,[mousedata] + mov edi,esi + inc esi +; mov ecx,250 + mov ecx,[mousecount] + mov ecx,[ecx] + cld + rep movsb + + jmp uusicheckmouse + + checkmouseret: + + cmp [0xfb44],byte 0 + jne cmret + + cmp [0xfb40],byte 0 + je cmret + + mov [0xfff4],byte 0 + mov [0xfff5],byte 0 + + cmret: + + popad + + ret + + +draw_mouse_under: + + ; return old picture +; cli + + pushad + + xor ecx,ecx + xor edx,edx + + ;cli ; !!!**** + align 4 + mres: + + movzx eax,word [0xfb4a] + movzx ebx,word [0xfb4c] + + add eax,ecx + add ebx,edx + + push ecx + push edx + push eax + push ebx + + mov eax,edx + shl eax,6 + shl ecx,2 + add eax,ecx + add eax,mouseunder + mov ecx,[eax] + + pop ebx + pop eax + + ;;;push edi + mov edi,1 ;force + call [putpixel] + ;;;pop edi + + pop edx + pop ecx + + inc ecx + cmp ecx, 16 + jnz mres + xor ecx, ecx + inc edx + cmp edx, 24 + jnz mres + ;sti ; !!!**** + + popad + +; sti + + ret + + +save_draw_mouse: + + ; save & draw +; cli + + mov [0xfb4a],ax + mov [0xfb4c],bx + push eax + push ebx + mov ecx,0 + mov edx,0 + + ;cli ; !!!**** + + drm: + + push eax + push ebx + push ecx + push edx + + ; helloworld + push eax ebx ecx + add eax,ecx ; save picture under mouse + add ebx,edx + push ecx + call getpixel + mov [0xfb30],ecx + pop ecx + mov eax,edx + shl eax,6 + shl ecx,2 + add eax,ecx + add eax,mouseunder + mov ebx,[0xfb30] + mov [eax],ebx + pop ecx ebx eax + + mov edi,edx ; y cycle + shl edi,4 ; *16 bytes per row + add edi,ecx ; x cycle + mov esi, edi + add edi, esi + add edi, esi ; *3 + add edi,[0xf200] ; we have our str address + mov esi, edi + add esi, 16*24*3 + push ecx + mov ecx, [0xfb30] + call combine_colors + mov [0xfb10], ecx + pop ecx + + + pop edx + pop ecx + pop ebx + pop eax + + add eax,ecx ; we have x coord+cycle + add ebx,edx ; and y coord+cycle + + push ecx edi + mov ecx, [0xfb10] + mov edi, 1 + call [putpixel] + pop edi ecx + + mnext: + + mov ebx,[esp+0] ; pure y coord again + mov eax,[esp+4] ; and x + + inc ecx ; +1 cycle + cmp ecx,16 ; if more than 16 + jnz drm + xor ecx, ecx + inc edx + cmp edx,24 + jnz drm + + pop ebx + pop eax + +; sti ; !!!**** + + ret + + +combine_colors: + + ; in + ; ecx - color ( 00 RR GG BB ) + ; edi - ref to new color byte + ; esi - ref to alpha byte + ; + ; out + ; ecx - new color ( roughly (ecx*[esi]>>8)+([edi]*[esi]>>8) ) + + push eax + push ebx + push edx + push ecx + xor ecx, ecx + ; byte 2 + mov eax, 0xff + sub al, [esi+0] + mov ebx, [esp] + shr ebx, 16 + and ebx, 0xff + mul ebx + shr eax, 8 + add ecx, eax +; xor eax, eax +; xor ebx, ebx +; mov al, [edi+0] +; mov bl, [esi+0] + movzx eax, byte [edi+0] + movzx ebx, byte [esi+0] + mul ebx + shr eax, 8 + add ecx, eax + shl ecx, 8 + ; byte 1 + mov eax, 0xff + sub al, [esi+1] + mov ebx, [esp] + shr ebx, 8 + and ebx, 0xff + mul ebx + shr eax, 8 + add ecx, eax +; xor eax, eax +; xor ebx, ebx +; mov al, [edi+1] +; mov bl, [esi+1] + movzx eax, byte [edi+1] + movzx ebx, byte [esi+1] + mul ebx + shr eax, 8 + add ecx, eax + shl ecx, 8 + ; byte 2 + mov eax, 0xff + sub al, [esi+2] + mov ebx, [esp] + and ebx, 0xff + mul ebx + shr eax, 8 + add ecx, eax +; xor eax, eax +; xor ebx, ebx +; mov al, [edi+2] +; mov bl, [esi+2] + movzx eax, byte [edi+2] + movzx ebx, byte [esi+2] + mul ebx + shr eax, 8 + add ecx, eax + + pop eax + pop edx + pop ebx + pop eax + ret + + +__sys_disable_mouse: + + pushad + + cmp [0x3000],dword 1 + je disable_m + + mov edx,[0x3000] + shl edx,5 + add edx,window_data + + movzx eax, word [0xfb0a] + movzx ebx, word [0xfb0c] + + mov ecx,[0xfe00] + inc ecx + imul ecx,ebx + add ecx,eax + add ecx, display_data + + movzx eax, byte [edx+twdw+0xe] + + movzx ebx, byte [ecx] + cmp eax,ebx + je yes_mouse_disable + movzx ebx, byte [ecx+16] + cmp eax,ebx + je yes_mouse_disable + + mov ebx,[0xfe00] + inc ebx + imul ebx,10 + add ecx,ebx + + movzx ebx, byte [ecx] + cmp eax,ebx + je yes_mouse_disable + + mov ebx,[0xfe00] + inc ebx + imul ebx,10 + add ecx,ebx + + movzx ebx, byte [ecx] + cmp eax,ebx + je yes_mouse_disable + movzx ebx, byte [ecx+16] + cmp eax,ebx + je yes_mouse_disable + + jmp no_mouse_disable + + yes_mouse_disable: + + mov edx,[0x3000] + shl edx,5 + add edx,window_data + + movzx eax, word [0xfb0a] + movzx ebx, word [0xfb0c] + + mov ecx,[edx+0] ; mouse inside the area ? + add eax,14 + cmp eax,ecx + jb no_mouse_disable + sub eax,14 + + add ecx,[edx+8] + cmp eax,ecx + jg no_mouse_disable + + mov ecx,[edx+4] + add ebx,20 + cmp ebx,ecx + jb no_mouse_disable + sub ebx,20 + + add ecx,[edx+12] + cmp ebx,ecx + jg no_mouse_disable + + disable_m: + + cmp dword [0xf204],dword 0 + jne @f + call draw_mouse_under + @@: + + mov [0xf204],dword 1 + + no_mouse_disable: + + popad + + ret + + + +__sys_draw_pointer: + cli + + pushad + + cmp dword [0xf204],dword 0 ; mouse visible ? + je chms00 + + dec dword [0xf204] + + cmp [0xf204],dword 0 + jnz nodmu2 + + movzx ebx,word [0xfb0c] + movzx eax,word [0xfb0a] + call save_draw_mouse + + popad + sti + ret + + nodmu2: + + popad + sti + ret + + chms00: + +; popad + +; pushad + +; cmp [0xf204],dword 0 +; jne nodmp + + movzx ecx,word [0xfb4a] + movzx edx,word [0xfb4c] + + movzx ebx,word [0xfb0c] + movzx eax,word [0xfb0a] + + cmp eax,ecx + jne redrawmouse + + cmp ebx,edx + jne redrawmouse + + jmp nodmp + + redrawmouse: + + + call draw_mouse_under +redrawmouse_1: + call save_draw_mouse + + nodmp: + + popad + sti + ret + + + +calculatebackground: ; background + + ; all black + + mov [display_data-8],dword 4 ; size x + mov [display_data-4],dword 2 ; size y + + mov edi, 0x300000 ; set background to black + xor eax, eax + mov ecx, 0x0fff00 / 4 + cld + rep stosd + + mov edi,display_data ; set os to use all pixels + mov eax,0x01010101 + mov ecx,0x1fff00 / 4 + rep stosd + + mov byte [0xFFF0], 0 ; do not draw background! + + ret + +uglobal + imax dd 0x0 +endg + + + +delay_ms: ; delay in 1/1000 sec + + + push eax + push ecx + + mov ecx,esi + ; + imul ecx, 33941 + shr ecx, 9 + ; + + in al,0x61 + and al,0x10 + mov ah,al + cld + + cnt1: in al,0x61 + and al,0x10 + cmp al,ah + jz cnt1 + + mov ah,al + loop cnt1 + + pop ecx + pop eax + + ret + + +set_app_param: + push edi + + mov edi,[0x3010] + mov [edi],eax + + pop edi + ret + + + +delay_hs: ; delay in 1/100 secs + push eax + push ecx + push edx + + mov edx,[timer_ticks];[0xfdf0] + add edx,eax + + newtic: + mov ecx,[timer_ticks];[0xfdf0] + cmp edx,ecx + jbe zerodelay + + call change_task + + jmp newtic + + zerodelay: + pop edx + pop ecx + pop eax + + ret + + +memmove: ; memory move in bytes + +; eax = from +; ebx = to +; ecx = no of bytes + test ecx, ecx + jle .ret + + + push esi edi ecx + + mov edi, ebx + mov esi, eax + + test ecx, not 11b + jz @f + + push ecx + shr ecx, 2 + rep movsd + pop ecx + and ecx, 11b + jz .finish + @@: + rep movsb + + .finish: + pop ecx edi esi + .ret: + ret + + + +; calculate fat chain + +calculatefatchain: + + pushad + + mov esi,0x100000+512 + mov edi,0x280000 + + fcnew: + xor eax,eax + xor ebx,ebx + xor ecx,ecx + xor edx,edx + mov al,[esi+0] ; 1 + mov bl,[esi+1] + and ebx,15 + shl ebx,8 + add eax,ebx + mov [edi],ax + add edi,2 + + xor eax,eax + xor ebx,ebx + xor ecx,ecx + xor edx,edx + mov bl,[esi+1] ; 2 + mov cl,[esi+2] + shr ebx,4 + shl ecx,4 + add ecx,ebx + mov [edi],cx + add edi,2 + + add esi,3 + + cmp edi,0x280000+4100*4 + jnz fcnew + + popad + ret + + +restorefatchain: ; restore fat chain + + pushad + + mov esi,0x280000 + mov edi,0x100000+512 + + fcnew2: + cld + xor eax,eax + xor ebx,ebx + xor ecx,ecx ; esi XXXXxxxxxxxx yyyyyyyyYYYY + xor edx,edx + mov ax,[esi] ; edi xxxxxxxx YYYYXXXX yyyyyyyy + mov bx,ax + shr bx,8 + and ebx,15 + mov [edi+0],al ; 1 -> 1 & 2 + mov [edi+1],bl + add esi,2 + + xor eax,eax + xor ebx,ebx + xor ecx,ecx + xor edx,edx + mov bx,[esi] + mov cx,bx + shr ecx,4 + mov [edi+2],cl + and ebx,15 + shl ebx,4 + mov edx,[edi+1] + add edx,ebx + mov [edi+1],dl ; 2 -> 2 & 3 + add esi,2 + + add edi,3 + + cmp edi,0x100000+512+0x1200 + jb fcnew2 + + mov esi,0x100000+512 ; duplicate fat chain + mov edi,0x100000+512+0x1200 + mov ecx,0x1200/4 + cld + rep movsd + + popad + ret + + +align 4 + +read_floppy_file: + +; as input +; +; eax pointer to file +; ebx file lenght +; ecx start 512 byte block number +; edx number of blocks to read +; esi pointer to return/work area (atleast 20 000 bytes) +; +; +; on return +; +; eax = 0 command succesful +; 1 no fd base and/or partition defined +; 2 yet unsupported FS +; 3 unknown FS +; 4 partition not defined at hd +; 5 file not found +; ebx = size of file + + mov edi,[0x3010] + add edi,0x10 + add esi,[edi] + add eax,[edi] + + pushad + mov edi,esi + add edi,1024 + mov esi,0x100000+19*512 + sub ecx,1 + shl ecx,9 + add esi,ecx + shl edx,9 + mov ecx,edx + cld + rep movsb + popad + + mov [esp+36],eax + mov [esp+24],ebx + ret + + + +align 4 + +sys_programirq: + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + + mov edx,ebx + shl edx,2 + add edx,irq_owner + mov edx,[edx] + mov edi,[0x3010] + mov edi,[edi+0x4] + cmp edx,edi + je spril1 + mov [esp+36],dword 1 + ret + spril1: + + mov esi,eax + shl ebx,6 + add ebx,irq00read + mov edi,ebx + mov ecx,16 + cld + rep movsd + mov [esp+36],dword 0 + ret + + +align 4 + +get_irq_data: + + mov edx,eax ; check for correct owner + shl edx,2 + add edx,irq_owner + mov edx,[edx] + mov edi,[0x3010] + mov edi,[edi+0x4] + cmp edx,edi + je gidril1 + mov [esp+36],eax + mov [esp+32],dword 2 + mov [esp+24],ebx + ret + + gidril1: + + mov ebx,eax + shl ebx,12 + add ebx,0x2e0000 + mov eax,[ebx] + mov ecx,1 + test eax,eax + jz gid1 + + dec eax + mov esi,ebx + mov [ebx],eax + movzx ebx,byte [ebx+0x10] + add esi,0x10 + mov edi,esi + inc esi + mov ecx,4000 / 4 + cld + rep movsd + xor ecx,ecx + gid1: + mov [esp+36],eax + mov [esp+32],ecx + mov [esp+24],ebx + ret + + +set_io_access_rights: + + pushad + + mov edi,[0x3000] + imul edi,tss_step + add edi,tss_data+128 +; add edi,128 + + mov ecx,eax + and ecx,7 ; offset in byte + + shr eax,3 ; number of byte + add edi,eax + + mov ebx,1 + shl ebx,cl + + cmp ebp,0 ; enable access - ebp = 0 + jne siar1 + + not ebx + and [edi],byte bl + + popad + + ret + + siar1: + + or [edi],byte bl ; disable access - ebp = 1 + + popad + + ret + + + + + +r_f_port_area: + + test eax, eax + jnz free_port_area +; je r_port_area +; jmp free_port_area + +; r_port_area: + + pushad + + cmp ebx,ecx ; beginning > end ? + jg rpal1 + mov esi,[0x2d0000] + cmp esi,0 ; no reserved areas ? + je rpal2 + cmp esi,255 ; max reserved + jge rpal1 + rpal3: + mov edi,esi + shl edi,4 + add edi,0x2d0000 + cmp ebx,[edi+8] + jg rpal4 + cmp ecx,[edi+4] + jae rpal1 +; jb rpal4 +; jmp rpal1 + rpal4: + + dec esi + jnz rpal3 + jmp rpal2 + rpal1: + popad + mov eax,1 + ret + + rpal2: + popad + + + ; enable port access at port IO map + cli + pushad ; start enable io map + + cmp ecx,65536 ;16384 + jae no_unmask_io ; jge + + mov eax,ebx + + new_port_access: + + pushad + + mov ebp,0 ; enable - eax = port + call set_io_access_rights + + popad + + inc eax + cmp eax,ecx + jbe new_port_access + + no_unmask_io: + + popad ; end enable io map + sti + + mov edi,[0x2d0000] + add edi,1 + mov [0x2d0000],edi + shl edi,4 + add edi,0x2d0000 + mov esi,[0x3010] + mov esi,[esi+0x4] + mov [edi],esi + mov [edi+4],ebx + mov [edi+8],ecx + + xor eax, eax + ret + + + + +free_port_area: + + pushad + + mov esi,[0x2d0000] ; no reserved areas ? + cmp esi,0 + je frpal2 + mov edx,[0x3010] + mov edx,[edx+4] + frpal3: + mov edi,esi + shl edi,4 + add edi,0x2d0000 + cmp edx,[edi] + jne frpal4 + cmp ebx,[edi+4] + jne frpal4 + cmp ecx,[edi+8] + jne frpal4 + jmp frpal1 + frpal4: + dec esi + jnz frpal3 + frpal2: + popad + mov eax,1 + ret + frpal1: + mov ecx,256 + sub ecx,esi + shl ecx,4 + mov esi,edi + add esi,16 + cld + rep movsb + + dec dword [0x2d0000] + + popad + + + ; disable port access at port IO map + + pushad ; start disable io map + + cmp ecx,65536 ;16384 + jge no_mask_io + + mov eax,ebx + + new_port_access_disable: + + pushad + + mov ebp,1 ; disable - eax = port + call set_io_access_rights + + popad + + inc eax + cmp eax,ecx + jbe new_port_access_disable + + no_mask_io: + + popad ; end disable io map + + xor eax, eax + ret + + +reserve_free_irq: + + cmp eax,0 + jz reserve_irq + + mov edi,ebx + shl edi,2 + add edi,irq_owner + mov edx,[edi] + mov eax,[0x3010] + mov eax,[eax+0x4] + mov ecx,1 + cmp edx,eax + jne fril1 + mov [edi],dword 0 + mov ecx,0 + fril1: + mov [esp+36],ecx ; return in eax + ret + + reserve_irq: + + mov edi,ebx + shl edi,2 + add edi,irq_owner + mov edx,[edi] + mov ecx,1 + cmp edx,0 + jne ril1 + + mov edx,[0x3010] + mov edx,[edx+0x4] + mov [edi],edx + mov ecx,0 + + ril1: + + mov [esp+36],ecx ; return in eax + + ret + + + +drawbackground: + + cmp [0xfe0c],word 0x12 + jne dbrv12 + cmp [display_data-12],dword 1 + jne bgrstr12 + call vga_drawbackground_tiled + ret + bgrstr12: + call vga_drawbackground_stretch + ret + dbrv12: + + cmp [0xfe0c],word 0100000000000000b + jge dbrv20 + cmp [0xfe0c],word 0x13 + je dbrv20 + call vesa12_drawbackground + ret + dbrv20: + cmp [display_data-12],dword 1 + jne bgrstr + call vesa20_drawbackground_tiled + ret + bgrstr: + call vesa20_drawbackground_stretch + ret + + +sys_putimage: + + cmp [0xfe0c],word 0x12 + jne spiv20 + call vga_putimage + ret + spiv20: + + cmp [0xfe0c],word 0100000000000000b + jge piv20 + cmp [0xfe0c],word 0x13 + je piv20 + call vesa12_putimage + ret + piv20: + call vesa20_putimage + ret + + + +; eax x beginning +; ebx y beginning +; ecx x end +; edx y end +; edi color + +__sys_drawbar: + + cmp [0xfe0c],word 0x12 + jne sdbv20 + call vga_drawbar + ret + sdbv20: + + cmp [0xfe0c],word 0100000000000000b + jge dbv20 + cmp [0xfe0c],word 0x13 + je dbv20 + call vesa12_drawbar + ret + + dbv20: + + call vesa20_drawbar + ret + + + +kb_read: + + push ecx edx + + mov ecx,0xffff + kr_loop: + in al,0x64 + test al,1 + jnz kr_ready + loop kr_loop + mov ah,1 + jmp kr_exit + kr_ready: + push ecx + mov ecx,32 + kr_delay: + loop kr_delay + pop ecx + in al,0x60 + xor ah,ah + kr_exit: + + pop edx ecx + + ret + + +kb_write: + + push ecx edx + + mov dl,al + mov ecx,0xffff + kw_loop1: + in al,0x64 + test al,0x20 + jz kw_ok1 + loop kw_loop1 + mov ah,1 + jmp kw_exit + kw_ok1: + in al,0x60 + mov ecx,0xffff + kw_loop: + in al,0x64 + test al,2 + jz kw_ok + loop kw_loop + mov ah,1 + jmp kw_exit + kw_ok: + mov al,dl + out 0x60,al + mov ecx,0xffff + kw_loop3: + in al,0x64 + test al,2 + jz kw_ok3 + loop kw_loop3 + mov ah,1 + jmp kw_exit + kw_ok3: + mov ah,8 + kw_loop4: + mov ecx,0xffff + kw_loop5: + in al,0x64 + test al,1 + jnz kw_ok4 + loop kw_loop5 + dec ah + jnz kw_loop4 + kw_ok4: + xor ah,ah + kw_exit: + + pop edx ecx + + ret + + +kb_cmd: + + mov ecx,0xffff + c_wait: + in al,0x64 + test al,2 + jz c_send + loop c_wait + jmp c_error + c_send: + mov al,bl + out 0x64,al + mov ecx,0xffff + c_accept: + in al,0x64 + test al,2 + jz c_ok + loop c_accept + c_error: + mov ah,1 + jmp c_exit + c_ok: + xor ah,ah + c_exit: + ret + + +setmouse: ; set mousepicture -pointer + ; ps2 mouse enable + + mov [0xf200],dword mousepointer + + cli + mov bl,0xa8 ; enable mouse cmd + call kb_cmd + call kb_read ; read status + + mov bl,0x20 ; get command byte + call kb_cmd + call kb_read + or al,3 ; enable interrupt + mov bl,0x60 ; write command + push eax + call kb_cmd + pop eax + call kb_write + + mov bl,0xd4 ; for mouse + call kb_cmd + mov al,0xf4 ; enable mouse device + call kb_write + call kb_read ; read status return + + ; com1 mouse enable + + mov bx,0x3f8 ; combase + + mov dx,bx + add dx,3 + mov al,0x80 + out dx,al + + mov dx,bx + add dx,1 + mov al,0 + out dx,al + + mov dx,bx + add dx,0 + mov al,0x30*2 ; 0x30 / 4 + out dx,al + + mov dx,bx + add dx,3 + mov al,2 ; 3 + out dx,al + + mov dx,bx + add dx,4 + mov al,0xb + out dx,al + + mov dx,bx + add dx,1 + mov al,1 + out dx,al + + + ; com2 mouse enable + + mov bx,0x2f8 ; combase + + mov dx,bx + add dx,3 + mov al,0x80 + out dx,al + + mov dx,bx + add dx,1 + mov al,0 + out dx,al + + mov dx,bx + add dx,0 + mov al,0x30*2 + out dx,al + + mov dx,bx + add dx,3 + mov al,2 + out dx,al + + mov dx,bx + add dx,4 + mov al,0xb + out dx,al + + mov dx,bx + add dx,1 + mov al,1 + out dx,al + + ret + + +_rdtsc: + + mov edx,[cpuid_1+3*4] + test edx,00010000b + jz ret_rdtsc + rdtsc + ret + ret_rdtsc: + mov edx,0xffffffff + mov eax,0xffffffff + ret + + + +rerouteirqs: + + cli + + mov al,0x11 ; icw4, edge triggered + out 0x20,al + call pic_delay + out 0xA0,al + call pic_delay + + mov al,0x20 ; generate 0x20 + + out 0x21,al + call pic_delay + mov al,0x28 ; generate 0x28 + + out 0xA1,al + call pic_delay + + mov al,0x04 ; slave at irq2 + out 0x21,al + call pic_delay + mov al,0x02 ; at irq9 + out 0xA1,al + call pic_delay + + mov al,0x01 ; 8086 mode + out 0x21,al + call pic_delay + out 0xA1,al + call pic_delay + + mov al,255 ; mask all irq's + out 0xA1,al + call pic_delay + out 0x21,al + call pic_delay + + mov ecx,0x1000 + cld +picl1: call pic_delay + loop picl1 + + mov al,255 ; mask all irq's + out 0xA1,al + call pic_delay + out 0x21,al + call pic_delay + + cli + + ret + + +pic_delay: + + jmp pdl1 +pdl1: ret + + +sys_msg_board_str: + + pushad + @@: + cmp [esi],byte 0 + je @f + mov eax,1 + movzx ebx,byte [esi] + call sys_msg_board + inc esi + jmp @b + @@: + popad + ret + +uglobal + msg_board_data: times 512 db 0 + msg_board_count dd 0x0 +endg + +sys_msg_board: + +; eax=1 : write : bl byte to write +; eax=2 : read : ebx=0 -> no data, ebx=1 -> data in al + + mov ecx,[msg_board_count] + cmp eax, 1 + jne smbl1 + + + mov [msg_board_data+ecx],bl + inc ecx + and ecx, 511 + mov [msg_board_count], ecx + mov [check_idle_semaphore], 5 + ret + smbl1: + + cmp eax, 2 + jne smbl2 + test ecx, ecx + jz smbl21 +; mov edi, msg_board_data +; mov esi, msg_board_data+1 +; movzx eax, byte [edi] + mov eax, msg_board_data+1 + mov ebx, msg_board_data + movzx edx, byte [ebx] + call memmove +; push ecx +; shr ecx, 2 +; cld +; rep movsd +; pop ecx +; and ecx, 3 +; rep movsb + dec [msg_board_count] + mov [esp+36], edx ;eax + mov [esp+24], dword 1 + ret + smbl21: + mov [esp+36], ecx + mov [esp+24], ecx + + smbl2: + ret + + + +sys_trace: + + test eax, eax ; get event data + jnz no_get_sys_events + + mov esi,save_syscall_data ; data + mov edi,[0x3010] + mov edi,[edi+0x10] + add edi,ebx + cld + rep movsb + + mov [esp+24],dword 0 + mov eax,[save_syscall_count] ; count + mov [esp+36],eax + ret + + no_get_sys_events: + + ret + + +sys_process_def: + + cmp eax,1 ; set keyboard mode + jne no_set_keyboard_setup + + mov edi,[0x3000] + shl edi,8 + add edi,0x80000+0xB4 + mov [edi],bl + + ret + + no_set_keyboard_setup: + + cmp eax,2 ; get keyboard mode + jne no_get_keyboard_setup + + mov edi,[0x3000] + shl edi,8 + add edi,0x80000+0xB4 + movzx eax, byte [edi] + + mov [esp+36],eax + + ret + + no_get_keyboard_setup: + + cmp eax,3 ; get keyboard ctrl, alt, shift + jne no_get_keyboard_cas + +; xor eax,eax +; movzx eax,byte [shift] +; movzx ebx,byte [ctrl] +; shl ebx,2 +; add eax,ebx +; movzx ebx,byte [alt] +; shl ebx,3 +; add eax,ebx + + ;// mike.dld [ + mov eax, [kb_state] + ;// mike.dld ] + + mov [esp+36],eax + + ret + + no_get_keyboard_cas: + + + ret + + +sys_ipc: + cmp eax,1 ; DEFINE IPC MEMORY + jne no_ipc_def + mov edi,[0x3000] + shl edi,8 + add edi,0x80000 + mov [edi+0xA0],ebx + mov [edi+0xA4],ecx + mov [esp+36],dword 0 + ret + no_ipc_def: + + cmp eax,2 ; SEND IPC MESSAGE + jne no_ipc_send + mov esi,1 + mov edi,0x3020 + ipcs1: + cmp [edi+4],ebx + je ipcs2 + add edi,0x20 + inc esi + cmp esi,[0x3004] + jbe ipcs1 + mov [esp+36],dword 4 + ret + ipcs2: + + cli + + push esi + mov eax,esi + shl eax,8 + mov ebx,[eax+0x80000+0xa0] + test ebx,ebx ; ipc area not defined ? + je ipc_err1 + + add ebx,[eax+0x80000+0xa4] + mov eax,esi + shl eax,5 + add ebx,[eax+0x3000+0x10] ; ebx <- max data position + + mov eax,esi ; to + shl esi,8 + add esi,0x80000 + mov edi,[esi+0xa0] + shl eax,5 + add eax,0x3000 + add edi,[eax+0x10] + + cmp [edi],byte 0 ; overrun ? + jne ipc_err2 + + mov ebp,edi + add edi,[edi+4] + add edi,8 + + mov esi,ecx ; from + mov eax,[0x3010] + mov eax,[eax+0x10] + add esi,eax + + mov ecx,edx ; size + + mov eax,edi + add eax,ecx + cmp eax,ebx + jge ipc_err3 ; not enough room ? + + push ecx + + mov eax,[0x3010] + mov eax,[eax+4] + mov [edi-8],eax + mov [edi-4],ecx + cld + rep movsb + + pop ecx + add ecx,8 + + mov edi,ebp ; increase memory position + add dword [edi+4],ecx + + mov edi,[esp] + shl edi,8 + or dword [edi+0x80000+0xA8],dword 01000000b ; ipc message + + cmp [check_idle_semaphore],dword 20 + jge ipc_no_cis + mov [check_idle_semaphore],5 + ipc_no_cis: + + xor eax, eax + + ipc_err: + add esp,4 + mov [esp+36],eax + sti + ret + + ipc_err1: + add esp,4 + mov [esp+36],dword 1 + sti + ret + ipc_err2: + add esp,4 + mov [esp+36],dword 2 + sti + ret + ipc_err3: + add esp,4 + mov [esp+36],dword 3 + sti + ret + + no_ipc_send: + + mov [esp+36],dword -1 + ret + + +align 4 + +sys_gs: ; direct screen access + + cmp eax,1 ; resolution + jne no_gs1 + mov eax,[0xfe00] + shl eax,16 + mov ax,[0xfe04] + add eax,0x00010001 + mov [esp+36],eax + ret + no_gs1: + + cmp eax,2 ; bits per pixel + jne no_gs2 + movzx eax,byte [0xfbf1] + mov [esp+36],eax + ret + no_gs2: + + cmp eax,3 ; bytes per scanline + jne no_gs3 + mov eax,[0xfe08] + mov [esp+36],eax + ret + no_gs3: + + mov [esp+36],dword -1 + ret + + +align 4 ; PCI functions + +sys_pci: + + call pci_api + mov [esp+36],eax + ret + + +align 4 ; system functions + +syscall_setpixel: ; SetPixel + + + mov edx,[0x3010] + add eax,[edx-twdw] + add ebx,[edx-twdw+4] + xor edi,edi ; no force + call [disable_mouse] + jmp [putpixel] + +align 4 + +syscall_writetext: ; WriteText + + mov edi,[0x3010] + mov ebp,[edi-twdw] + shl ebp,16 + add ebp,[edi-twdw+4] + add edi,0x10 + add ecx,[edi] + add eax,ebp + xor edi,edi + jmp dtext + +align 4 + +syscall_openramdiskfile: ; OpenRamdiskFile + + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + add edx,[edi] + mov esi,12 + call fileread + mov [esp+36],ebx + ret + +align 4 + +syscall_putimage: ; PutImage + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + mov edx,ecx + mov ecx,ebx + mov ebx,eax + call sys_putimage + mov [esp+36],eax + ret + +align 4 + +syscall_drawrect: ; DrawRect + + mov edi,ecx + test ax,ax + je drectr + test bx,bx + je drectr + movzx ecx,ax + shr eax,16 + movzx edx,bx + shr ebx,16 + add ecx,eax + add edx,ebx + jmp [drawbar] + drectr: + ret + +align 4 + +syscall_getscreensize: ; GetScreenSize + + movzx eax,word[0xfe00] + shl eax,16 + mov ax,[0xfe04] + mov [esp+36],eax + ret + +align 4 + +syscall_system: ; System + + call sys_system + mov [esp+36],eax + ret + +align 4 + +syscall_startapp: ; StartApp + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + test ebx,ebx + jz noapppar + add ebx,[edi] + noapppar: +; call start_application_fl + call new_start_application_fl + mov [esp+36],eax + ret + + +align 4 + +syscall_cdaudio: ; CD + + call sys_cd_audio + mov [esp+36],eax + ret + +align 4 + +syscall_readhd: ; ReadHd + + mov edi,[0x3010] + add edi,0x10 + add esi,[edi] + add eax,[edi] + call read_hd_file + mov [esp+36],eax + mov [esp+24],ebx + ret + +align 4 + +syscall_starthdapp: ; StartHdApp + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + add ecx,[edi] + mov ebp,0 + call start_application_hd + mov [esp+36],eax + ret + +align 4 + +syscall_delramdiskfile: ; DelRamdiskFile + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + call filedelete + mov [esp+36],eax + ret + +align 4 + +syscall_writeramdiskfile: ; WriteRamdiskFile + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + add ebx,[edi] + call filesave + mov [esp+36],eax + ret + +align 4 + +syscall_getpixel: ; GetPixel + + mov ecx,[0xfe00] + inc ecx + xor edx,edx + div ecx + mov ebx,edx + xchg eax,ebx + call dword [0xe024] + mov [esp+36],ecx + ret + +align 4 + +syscall_readstring: ; ReadString + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + call read_string + mov [esp+36],eax + ret + +align 4 + +syscall_drawline: ; DrawLine + + mov edi,[0x3010] + movzx edx,word[edi-twdw] + mov ebp,edx + shl edx,16 + add ebp,edx + movzx edx,word[edi-twdw+4] + add eax,ebp + mov ebp,edx + shl edx,16 + xor edi,edi + add edx,ebp + add ebx,edx + jmp [draw_line] + +align 4 + +syscall_getirqowner: ; GetIrqOwner + + shl eax,2 + add eax,irq_owner + mov eax,[eax] + mov [esp+36],eax + ret + +align 4 + +syscall_reserveportarea: ; ReservePortArea and FreePortArea + + call r_f_port_area + mov [esp+36],eax + ret + +align 4 + +syscall_appints: ; AppInts + + test eax,eax + jnz unknown_app_int_fn + mov edi,[0x3010] + mov [edi+draw_data-0x3000+0x1c],ebx + ret + unknown_app_int_fn: + mov [esp+36],dword -1 + ret + +align 4 + +syscall_threads: ; CreateThreads + + call sys_threads + mov [esp+36],eax + ret + +align 4 + +stack_driver_stat: + + call app_stack_handler ; Stack status + +; mov [check_idle_semaphore],5 ; enable these for zero delay +; call change_task ; between sent packet + + mov [esp+36],eax + ret + +align 4 + +socket: ; Socket interface + call app_socket_handler + +; mov [check_idle_semaphore],5 ; enable these for zero delay +; call change_task ; between sent packet + + mov [esp+36],eax + mov [esp+24],ebx + ret + +align 4 + +user_events: ; User event times + + mov eax,0x12345678 + mov [esp+36],eax + + ret + +align 4 + +read_from_hd: ; Read from hd - fn not in use + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + add ecx,[edi] + add edx,[edi] + call file_read + + mov [esp+36],eax + mov [esp+24],ebx + + ret + + +align 4 + +write_to_hd: ; Write a file to hd + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + add ecx,[edi] + add edx,[edi] + call file_write + ret + +align 4 + +delete_from_hd: ; Delete a file from hd + + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + add ecx,[edi] + call file_delete + ret + + +align 4 + +undefined_syscall: ; Undefined system call + + mov [esp+36],dword -1 + ret + + +;clear_busy_flag_at_caller: + +; push edi + +; mov edi,[0x3000] ; restore processes tss pointer in gdt, busyfl? +; imul edi,8 +; mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b + +; pop edi + +; ret + + + + +keymap: + + db '6',27 + db '1234567890-=',8,9 + db 'qwertyuiop[]',13 + db '~asdfghjkl;',39,96,0,'\zxcvbnm,./',0,'45 ' + db '@234567890123',180,178,184,'6',176,'7' + db 179,'8',181,177,183,185,182 + db 'AB?',0,'45 ' + db '@234567890123',180,178,184,'6',176,'7' + db 179,'8',181,177,183,185,182 + db 'AB>D',255,'FGHIJKLMNOPQRSTUVWXYZ' + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + +keymap_alt: + + db ' ',27 + db ' @ $ {[]}\ ',8,9 + db ' ',13 + db ' ',0,' ',0,'4',0,' ' + db ' ',180,178,184,'6',176,'7' + db 179,'8',181,177,183,185,182 + db 'ABCD',255,'FGHIJKLMNOPQRSTUVWXYZ' + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + +; device irq owners +uglobal +irq_owner: ; process id + + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 + dd 0x0 +endg + + +; on irq read ports +uglobal + irq00read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq01read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq02read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq03read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq04read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq05read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq06read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq07read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq08read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq09read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq10read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq11read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq12read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq13read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq14read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + irq15read dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +endg + +; status +uglobal + hd1_status dd 0x0 ; 0 - free : other - pid + application_table_status dd 0x0 ; 0 - free : other - pid +endg + +; device addresses +uglobal + mididp dd 0x0 + midisp dd 0x0 + + cdbase dd 0x0 + cdid dd 0x0 + + hdbase dd 0x0 ; for boot 0x1f0 + hdid dd 0x0 + hdpos dd 0x0 ; for boot 0x1 + fat32part dd 0x0 ; for boot 0x1 + + ;part2_ld dd 0x0 + +;* start code - get process (3) - Mario79 +active_process dd 0 +;* end code - get active process (3) - Mario79 + +wraw_bacground_select db 0 + lba_read_enabled dd 0x0 ; 0 = disabled , 1 = enabled + pci_access_enabled dd 0x0 ; 0 = disabled , 1 = enabled + + sb16 dd 0x0 + wss dd 0x0 + + buttontype dd 0x0 + windowtypechanged dd 0x0 +endg + +iglobal + keyboard dd 0x1 + sound_dma dd 0x1 + syslang dd 0x1 +endg + +IncludeIGlobals +endofcode: +IncludeUGlobals +uglobals_size = $ - endofcode +diff16 "end of kernel code",$ + diff --git a/trunk/kernel16.inc b/trunk/kernel16.inc new file mode 100644 index 000000000..790abd712 --- /dev/null +++ b/trunk/kernel16.inc @@ -0,0 +1,31 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; KERNEL16.INC ;; +;; ;; +;; Included 16 bit kernel files for MenuetOS ;; +;; ;; +;; This file is kept separate as it will be easier to ;; +;; maintain and compile with an automated SETUP program ;; +;; in the future. ;; +;; ;; +;; Copyright Ville Turjanmaa, see file COPYING for details. ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;% +include + +;!!! +if lang eq en +include "boot/booteng.inc" ; english system boot messages +else +include "boot/bootru.inc" ; russian system boot messages +;!!! +end if +include "boot/ru.inc" ; Russian font + +include "boot/bootcode.inc" ; 16 bit system boot code + +include "bus/pci/pci16.inc" + +;% -include \ No newline at end of file diff --git a/trunk/kernel32.inc b/trunk/kernel32.inc new file mode 100644 index 000000000..34298524f --- /dev/null +++ b/trunk/kernel32.inc @@ -0,0 +1,105 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; KERNEL32.INC ;; +;; ;; +;; Included 32 bit kernel files for MenuetOS ;; +;; ;; +;; This file is kept separate as it will be easier to ;; +;; maintain and compile with an automated SETUP program ;; +;; in the future. ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; structure definition helper +macro struct name, [arg] + { + common + name@struct fix name + struc name arg { + } + +macro struct_helper name + { + virtual at 0 + name name + sizeof.#name = $ - name + name equ sizeof.#name + end virtual + } + +ends fix } struct_helper name@struct + + +; Core functions +include "core/sync.inc" +include "core/sys32.inc" ; process management +include "core/sched.inc" ; process scheduling +include "core/fpu.inc" ; FPU handler +include "core/syscall.inc" ; system call +include "core/mem.inc" ; high-level memory management +include "core/newproce.inc" ;new process management +include "core/physmem.inc" ; access to physical memory for applications +include "core/sync.inc" ; macros for synhronization objects + +; GUI stuff +include "gui/window.inc" +include "gui/event.inc" +include "gui/font.inc" +include "gui/button.inc" + +; shutdown + +include "boot/shutdown.inc" ; shutdown or restart + +; file system + +include "fs/fs.inc" ; syscall +include "fs/fat32.inc" ; read / write for fat32 filesystem +include "fs/fat12.inc" ; read / write for fat12 filesystem +include "blkdev/rd.inc" ; ramdisk read /write + +; sound + +include "sound/sb16.inc" ; playback for Sound Blaster 16 +include "sound/playnote.inc" ; player Note for Speaker PC + +; display + +include "video/vesa12.inc" ; Vesa 1.2 functions +include "video/vesa20.inc" ; Vesa 2.0 functions +include "video/vga.inc" ; VGA 16 color functions + +; Network Interface & TCPIP Stack + +include "network/stack.inc" + +; Mouse pointer + +include "gui/mouse.inc" + +; Window skinning + +include "gui/skincode.inc" + +; Pci functions + +include "bus/pci/pci32.inc" + +; Floppy drive controller + +include "blkdev/fdc.inc" +include "blkdev/flp_drv.inc" + +; CD drive controller + +include "blkdev/cdrom.inc" + +; Character devices + +include "hid/keyboard.inc" + +; setting date,time,clock and alarm-clock + +include "hid/set_dtc.inc" + +;% -include diff --git a/trunk/kglobals.inc b/trunk/kglobals.inc new file mode 100644 index 000000000..75688d765 --- /dev/null +++ b/trunk/kglobals.inc @@ -0,0 +1,50 @@ +;------------------------------------------------------------------ +; use "iglobal" for inserting initialized global data definitions. +;------------------------------------------------------------------ +macro iglobal { + IGlobals equ IGlobals, + macro __IGlobalBlock { } + +;------------------------------------------------------------- +; use 'uglobal' for inserting uninitialized global definitions. +; even when you define some data values, these variables +; will be stored as uninitialized data. +;------------------------------------------------------------- +macro uglobal { + UGlobals equ UGlobals, + macro __UGlobalBlock { } + +endg fix } ; Use endg for ending iglobal and uglobal blocks. + +macro IncludeIGlobals{ + macro IGlobals dummy,[n] \{ __IGlobalBlock + purge __IGlobalBlock \} + match I, IGlobals \{ I \} } + + +macro IncludeUGlobals{ + macro UGlobals dummy,[n] \{ + \common + \local begin, size + begin = $ + virtual at $ + \forward + __UGlobalBlock + purge __UGlobalBlock + \common + size = $ - begin + end virtual + rb size + \} + match U, UGlobals \{ U \} } + +macro IncludeAllGlobals { + IncludeIGlobals + IncludeUGlobals +} + +iglobal +endg + +uglobal +endg diff --git a/trunk/memmap.inc b/trunk/memmap.inc new file mode 100644 index 000000000..beb5af88e --- /dev/null +++ b/trunk/memmap.inc @@ -0,0 +1,239 @@ +; +; MEMORY MAP +; +; Boot: +; +; 0:9000 byte bits per pixel +; 0:9001 word scanline length +; 0:9008 word vesa video mode +; 0:900A word X res +; 0:900C word Y res +; 0:9010 byte mouse port - not used +; 0:9014 dword Vesa 1.2 pm bank switch +; 0:9018 dword Vesa 2.0 LFB address +; 0:901C byte 0 or 1 : enable MTRR graphics acceleration +; 0:901D byte not used anymore (0 or 1 : enable system log display) +; 0:901E byte 0 or 1 : enable direct lfb write, paging disabled +; 0:9020 8bytes pci data +; 0:9030 byte VRR start enabled 1, 2-no +; 0:9031 word IDEContrRegsBaseAddr +; +; +; Runtime: +; +; 0000 -> 2FFF window_data - 256 entries +; +; 0000 dword x start +; 0004 dword y start +; 0008 dword x size +; 000C dword y size +; 0010 dword color of work area +; 0014 dword color of grab bar +; 0018 dword color of frames +; 001C dword window flags, +30 = window drawn, +31 redraw flag +; +; 3000 -> 4FFF task list - 256 entries +; +; 00 dword process count +; 04 dword no of processes +; 10 dword base of running process at 0x3000+ +; +; 20 dword application event mask +; 24 dword PID - process identification number +; 2a word 0, state 3=zombie, 4=terminate +; 2e byte window number on screen +; 30 dword exact position in memory +; 34 dword counter sum +; 38 dword time stamp counter add +; 3c dword cpu usage in cpu timer tics +; +; -> delete -> 5000 -> AFFF free +; +;!!! +; 5000 -> 5FFF save_syscall_data - syscall trace +; 6000 -> 63FF reg1 array - for i40 (first parts of saved TSS descriptor) +; 6400 -> 67FF reg2 array - same thing, second part +; 6800 -> 68FF used i40 (1 if used, 0 if free), first element not used +; 6900 -> 6EFF saved picture under mouse pointer +; +; 6F00 -> 7FFF i38 stack (4,25Kb) +; +; 8000 -> A3FF used FLOPPY driver +; +; A400 -> AFFF free +; +; B000 -> B005 jump address for irq0 (task switch) +; B008 -> B00B count of ticks remaining to updating CPU usage info +; +; B060 -> B07F fpu error handler's stack +; B080 -> B0FF fpu_tss -> temporary TSS for FPU context switching +; B100 -> B2FF IDT +; B300 -> BAFF tasknum array - for i40 handler +; BB00 -> BEFF free +;!!! + +; BF00 -> BFFF bytes, 1 if process running/memory in use +; C000 -> C3FF window stack C000 no of windows - all in words +; C402 -> C7FF window position in stack +; D000 -> D1FF FDC controller +; D200 -> D3FF FDC controller for Fat12 +; D400 -> DFFF free +; E000 byte multitasking started +; E004 dword save for boot mem 0x24 +; E010 dword pm bank switch address +; E014 dword window multiplier +; E020 dword putpixel address +; E024 dword getpixel address +; E030 dword Vesa 1.2 pm bank switch address +; F000 dword hd partition 1 start +; F004 dword root start at partition 1 +; F008 dword root start at hd +; F100 byte 1=only os draw on screen +; F200 dword mousepicture -pointer +; F204 dword mouse appearance counter +; F300 dword x & y temp for windowmove +; F400 byte no of keys in buffer +; F401 byte 'buffer' +; F402 -> F4FF reserved for keys +; F500 byte no of buttons in buffer +; F501 dword 'buffer' +; F502 -> F5FF reserved for buttons +; F600 dword tsc / second +; F604 byte mouse port: 1 ps2, 2 com1, 3 com2 +; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y +; FB10 -> FB17 mouse color mem +; FB21 x move +; FB22 y move +; FB28 high bits temp +; FB30 color temp +; FB40 byte buttons down +; FB44 byte 0 mouse down -> do not draw +; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under +; FBF0 byte multiplied window +; FBF1 byte bits per pixel +; FC00 -> FCFE com1/ps2 buffer +; FCFF com1/ps2 buffer count starting from FC00 +; FDF0 -> FDF3 timer tick inc every 1/100 sec 4 bytes +; FE00 dword screen x size +; FE04 dword screen y size +; FE08 dword screen y multiplier +; FE0C dword screen mode +; FE10 dword entries in hd cache +; FE80 dword address of LFB in physical +; FE84 dword address of applications memory start in physical +; FE88 dword address of button list +; FE8C dword memory to use +; FF00 byte 1 = system shutdown request +; FF01 dword if >1 then activate process +; FFF0 byte 1 = redraw background request from app +; FFF1 byte 1 = diskette int occur +; FFF2 write and read bank in screen +; FFF4 byte 0 if first mouse draw & do not return picture under +; FFF5 byte 1 do not draw pointer +; FFFF byte do not change task for 1/100 sec. +; +; 10000 -> 1FFFF 32 bit os +; 20000 -> 2FFFF 32 bit stack +; 30000 -> 36FFF basic text font II +; 37000 -> 3BFFF basic text font I +; 40000 -> 4FFFF data of retrieved disks and partitions (Mario79) +; 50000 -> 500FF TSS of scheduler +; 51000 -> 54000 esp0,esp1,esp2 +; 5F000 -> 5FFFF schedulers stack +; 60000 -> 7FFFF paging tables +; 80000 -> 8FFFF additional app info, in 256 byte steps - 256 entries +; +; 00 11db name of app running +; 10 108db floating point unit save area +; 7f byte 0= no fpu saved , 1= fpu saved to 0x10 -> restore +; 80 dword address of random shaped window area +; 84 byte shape area scale +; 88 dword used GDT of TSS +; 8C dword application memory size +; 90 dword window X position save +; 94 dword window Y position save +; 98 dword window X size save +; 9C dword window Y size save +; A0 dword IPC memory start +; A4 dword IPC memory size +; A8 dword event bits: mouse, stack,.. +; +; B0 dword int40 handler in use ; 0 if not in use +; B4 byte keyboard mode: 0 = keymap, 1 = scancodes +; +; 90000 -> 9FFFF tmp +; A0000 -> AFFFF screen access area +; B0000 -> FFFFF bios rest in peace -area +; 100000 -> 27FFFF diskette image +; 280000 -> 281FFF ramdisk fat +; 282000 -> 283FFF floppy fat +; +; 284000 -> 28FFFF free +; +; 290000 -> 297FFF TSS's of interrupts +; 298000 -> 29FFFF TSS's of SYSTEM interrupts - 256 entries +; 2A0000 -> 2B00ff wav device data +; 2C0000 -> 2C3fff button info +; +; 0000 word number of buttons +; first button entry at 0x10 +; +0000 word process number +; +0002 word button id number : bits 00-15 +; +0004 word x start +; +0006 word x size +; +0008 word y start +; +000A word y size +; +000C word button id number : bits 16-31 +; +; 2D0000 -> 2DFFFF reserved port area +; +; 0000 dword no of port areas reserved +; 0010 dword process id +; dword start port +; dword end port +; dword 0 +; +; 2E0000 -> 2EFFFF irq data area +; 2F0000 -> 2FFFFF low memory save +; +; 300000 -> 45FFFF background image, max 1 M +; +; 460000 -> 5FFFFF display info +; +; 600000 -> 6FFFFF hd cache +; +; 700000 -> 71ffff tcp memory (128 kb) +; 720000 -> 75ffff interrupt stacks (256 kpl * 1024) +; +; 760000 -> 76ffff !vrr driver +; 770000 -> 777fff tcp memory ( 32 kb) +; +; 778000 -> 77ffff window skinning ( 32 kb) +; 780000 -> 7fffff free +; +; 800000 -> BFFFFF mapped to LFB +; +; C00000 -> DFFFFF * Application information +; +; C00000 -> C01FFF draw_data - 256 entries +; +; 00 dword draw limit - x start +; 04 dword draw limit - y start +; 08 dword draw limit - x end +; 0C dword draw limit - y end +; 1C dword app int vector +; +; C03000 -> D11fff sysint_stack_data +; - system interrupt stacks +; - 256 entries * 4096 step +; +; D20000 -> DA8000 TSS and IO map for (2048*8)=16384 ports +; (128+2048)*256 = 557956 = 0x88000 +; +; 1000000 -> 3FFFFFF for applications +; + + + + + diff --git a/trunk/network/eth_drv/3c59x.inc b/trunk/network/eth_drv/3c59x.inc new file mode 100644 index 000000000..4280823c5 --- /dev/null +++ b/trunk/network/eth_drv/3c59x.inc @@ -0,0 +1,2380 @@ +;; Copyright (c) 2004, Endre Kozma +;; All rights reserved. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions are +;; met: +;; +;; 1. Redistributions of source code must retain the above copyright notice, +;; this list of conditions and the following disclaimer. +;; +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; +;; 3. The name of the author may not be used to endorse or promote products +;; derived from this software without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; 3C59X.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Driver for 3Com fast etherlink 3c59x and ;; +;; etherlink XL 3c900 and 3c905 cards ;; +;; References: ;; +;; www.3Com.com - data sheets ;; +;; DP83840A.pdf - ethernet physical layer ;; +;; 3c59x.c - linux driver ;; +;; ethernet driver template by Mike Hibbett ;; +;; ;; +;; Credits ;; +;; Mike Hibbett, ;; +;; who kindly supplied me with a 3Com905C-TX-M card ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; History +;; ======= +;; $Log: 3C59X.INC,v $ +;; Revision 1.3 2004/07/11 12:21:12 kozma +;; Support of vortex chips (3c59x) added. +;; Support of 3c920 and 3c982 added. +;; Corrections. +;; +;; Revision 1.2 2004/06/12 19:40:20 kozma +;; Function e3c59x_set_available_media added in order to set +;; the default media in case auto detection finds no valid link. +;; Incorrect mii check removed (3c900 Cyclone works now). +;; Cleanups. +;; +;; Revision 1.1 2004/06/12 18:27:15 kozma +;; Initial revision +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; comment the next line out if you don't want debug info printed +; on the debug board. This option adds a lot of bytes to the driver +; so it's worth to comment it out. +; E3C59X_DEBUG equ 1 + +; forcing full duplex mode makes sense at some cards and link types + E3C59X_FORCE_FD equ 1 + +macro virt_to_dma reg +{ +if defined E3C59X_LINUX + sub reg, [virt_addr] + add reg, [dma_addr] +end if +} + +macro dma_to_virt reg +{ +if defined E3C59X_LINUX + sub reg, [dma_addr] + add reg, [virt_addr] +end if +} + +macro zero_to_virt reg +{ +if defined E3C59X_LINUX + add reg, [virt_addr] +end if +} + +macro virt_to_zero reg +{ +if defined E3C59X_LINUX + sub reg, [virt_addr] +end if +} + +macro zero_to_dma reg +{ +if defined E3C59X_LINUX + add reg, [dma_addr] +end if +} + +macro dma_to_zero reg +{ +if defined E3C59X_LINUX + sub reg, [dma_addr] +end if +} + +macro strtbl name, [string] +{ +common + label name dword +forward + local label + dd label +forward + label db string, 0 +} + +; Ethernet frame symbols + ETH_ALEN equ 6 + ETH_HLEN equ (2*ETH_ALEN+2) + ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length +; PCI programming + PCI_REG_COMMAND equ 0x4 ; command register + PCI_REG_STATUS equ 0x6 ; status register + PCI_REG_LATENCY equ 0xd ; latency timer register + PCI_REG_CAP_PTR equ 0x34 ; capabilities pointer + PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block + PCI_REG_PM_STATUS equ 0x4 ; power management status register + PCI_REG_PM_CTRL equ 0x4 ; power management control register + PCI_BIT_PIO equ 0 ; bit0: io space control + PCI_BIT_MMIO equ 1 ; bit1: memory space control + PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master +; Registers + E3C59X_REG_POWER_MGMT_CTRL equ 0x7c + E3C59X_REG_UP_LIST_PTR equ 0x38 + E3C59X_REG_UP_PKT_STATUS equ 0x30 + E3C59X_REG_TX_FREE_THRESH equ 0x2f + E3C59X_REG_DN_LIST_PTR equ 0x24 + E3C59X_REG_DMA_CTRL equ 0x20 + E3C59X_REG_TX_STATUS equ 0x1b + E3C59X_REG_RX_STATUS equ 0x18 + E3C59X_REG_TX_DATA equ 0x10 +; Common window registers + E3C59X_REG_INT_STATUS equ 0xe + E3C59X_REG_COMMAND equ 0xe +; Register window 7 + E3C59X_REG_MASTER_STATUS equ 0xc + E3C59X_REG_POWER_MGMT_EVENT equ 0xc + E3C59X_REG_MASTER_LEN equ 0x6 + E3C59X_REG_VLAN_ETHER_TYPE equ 0x4 + E3C59X_REG_VLAN_MASK equ 0x0 + E3C59X_REG_MASTER_ADDRESS equ 0x0 +; Register window 6 + E3C59X_REG_BYTES_XMITTED_OK equ 0xc + E3C59X_REG_BYTES_RCVD_OK equ 0xa + E3C59X_REG_UPPER_FRAMES_OK equ 0x9 + E3C59X_REG_FRAMES_DEFERRED equ 0x8 + E3C59X_REG_FRAMES_RCVD_OK equ 0x7 + E3C59X_REG_FRAMES_XMITTED_OK equ 0x6 + E3C59X_REG_RX_OVERRUNS equ 0x5 + E3C59X_REG_LATE_COLLISIONS equ 0x4 + E3C59X_REG_SINGLE_COLLISIONS equ 0x3 + E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2 + E3C59X_REG_SQE_ERRORS equ 0x1 + E3C59X_REG_CARRIER_LOST equ 0x0 +; Register window 5 + E3C59X_REG_INDICATION_ENABLE equ 0xc + E3C59X_REG_INTERRUPT_ENABLE equ 0xa + E3C59X_REG_TX_RECLAIM_THRESH equ 0x9 + E3C59X_REG_RX_FILTER equ 0x8 + E3C59X_REG_RX_EARLY_THRESH equ 0x6 + E3C59X_REG_TX_START_THRESH equ 0x0 +; Register window 4 + E3C59X_REG_UPPER_BYTES_OK equ 0xe + E3C59X_REG_BAD_SSD equ 0xc + E3C59X_REG_MEDIA_STATUS equ 0xa + E3C59X_REG_PHYSICAL_MGMT equ 0x8 + E3C59X_REG_NETWORK_DIAGNOSTIC equ 0x6 + E3C59X_REG_FIFO_DIAGNOSTIC equ 0x4 + E3C59X_REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported +; Bits in register window 4 + E3C59X_BIT_AUTOSELECT equ 24 +; Register window 3 + E3C59X_REG_TX_FREE equ 0xc + E3C59X_REG_RX_FREE equ 0xa + E3C59X_REG_MEDIA_OPTIONS equ 0x8 + E3C59X_REG_MAC_CONTROL equ 0x6 + E3C59X_REG_MAX_PKT_SIZE equ 0x4 + E3C59X_REG_INTERNAL_CONFIG equ 0x0 +; Register window 2 + E3C59X_REG_RESET_OPTIONS equ 0xc + E3C59X_REG_STATION_MASK_HI equ 0xa + E3C59X_REG_STATION_MASK_MID equ 0x8 + E3C59X_REG_STATION_MASK_LO equ 0x6 + E3C59X_REG_STATION_ADDRESS_HI equ 0x4 + E3C59X_REG_STATION_ADDRESS_MID equ 0x2 + E3C59X_REG_STATION_ADDRESS_LO equ 0x0 +; Register window 1 + E3C59X_REG_TRIGGER_BITS equ 0xc + E3C59X_REG_SOS_BITS equ 0xa + E3C59X_REG_WAKE_ON_TIMER equ 0x8 + E3C59X_REG_SMB_RXBYTES equ 0x7 + E3C59X_REG_SMB_DIAG equ 0x5 + E3C59X_REG_SMB_ARB equ 0x4 + E3C59X_REG_SMB_STATUS equ 0x2 + E3C59X_REG_SMB_ADDRESS equ 0x1 + E3C59X_REG_SMB_FIFO_DATA equ 0x0 +; Register window 0 + E3C59X_REG_EEPROM_DATA equ 0xc + E3C59X_REG_EEPROM_COMMAND equ 0xa + E3C59X_REG_BIOS_ROM_DATA equ 0x8 + E3C59X_REG_BIOS_ROM_ADDR equ 0x4 +; Physical management bits + E3C59X_BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData + E3C59X_BIT_MGMT_DATA equ 1 ; MII management data bit + E3C59X_BIT_MGMT_CLK equ 0 ; MII management clock +; MII commands + E3C59X_MII_CMD_MASK equ (1111b shl 10) + E3C59X_MII_CMD_READ equ (0110b shl 10) + E3C59X_MII_CMD_WRITE equ (0101b shl 10) +; MII registers + E3C59X_REG_MII_BMCR equ 0 ; basic mode control register + E3C59X_REG_MII_BMSR equ 1 ; basic mode status register + E3C59X_REG_MII_ANAR equ 4 ; auto negotiation advertisement register + E3C59X_REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register + E3C59X_REG_MII_ANER equ 6 ; auto negotiation expansion register +; MII bits + E3C59X_BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete + E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6 +; eeprom bits and commands + E3C59X_EEPROM_CMD_READ equ 0x80 + E3C59X_EEPROM_BIT_BUSY equ 15 +; eeprom registers + E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa + E3C59X_EEPROM_REG_CAPABILITIES equ 0x10 +; Commands for command register + E3C59X_SELECT_REGISTER_WINDOW equ (1 shl 11) + + IS_VORTEX equ 0x1 + IS_BOOMERANG equ 0x2 + IS_CYCLONE equ 0x4 + IS_TORNADO equ 0x8 + EEPROM_8BIT equ 0x10 + HAS_PWR_CTRL equ 0x20 + HAS_MII equ 0x40 + HAS_NWAY equ 0x80 + HAS_CB_FNS equ 0x100 + INVERT_MII_PWR equ 0x200 + INVERT_LED_PWR equ 0x400 + MAX_COLLISION_RESET equ 0x800 + EEPROM_OFFSET equ 0x1000 + HAS_HWCKSM equ 0x2000 + EXTRA_PREAMBLE equ 0x4000 + +iglobal + align 4 +e3c59x_hw_versions: + dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps + dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex + dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex + dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx + dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 + dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII + dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT + dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo + dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO + dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo + dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC + dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL + dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx + dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 + dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx + dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC + dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx + dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado + dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone + dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone + dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane + dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane + dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \ + or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado + dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \ + or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane + dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus + dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus + dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \ + or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus + dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus + dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus + dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus + dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus + dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado + dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado + dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A + dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B + dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 + dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado +E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions +endg + +; RX/TX buffers sizes + E3C59X_MAX_ETH_PKT_SIZE equ 1536 ; max packet size + E3C59X_NUM_RX_DESC equ 4 ; a power of 2 number + E3C59X_NUM_TX_DESC equ 4 ; a power of 2 number + E3C59X_RX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC) + E3C59X_TX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC) +; Download Packet Descriptor + E3C59X_DPD_DN_NEXT_PTR equ 0 + E3C59X_DPD_FRAME_START_HDR equ 4 + E3C59X_DPD_DN_FRAG_ADDR equ 8 ; for packet data + E3C59X_DPD_DN_FRAG_LEN equ 12 ; for packet data + E3C59X_DPD_SIZE equ 16 ; a power of 2 number +; Upload Packet Descriptor + E3C59X_UPD_UP_NEXT_PTR equ 0 + E3C59X_UPD_PKT_STATUS equ 4 + E3C59X_UPD_UP_FRAG_ADDR equ 8 ; for packet data + E3C59X_UPD_UP_FRAG_LEN equ 12 ; for packet data + E3C59X_UPD_SIZE equ 16 + +; RX/TX buffers +if defined E3C59X_LINUX + E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment + e3c59x_rx_buff = 0 +else + E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment + e3c59x_rx_buff = eth_data_start +end if + + e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE + e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE + e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC) + +uglobal +e3c59x_curr_upd: dd 0 +e3c59x_prev_dpd: dd 0 +e3c59x_prev_tx_frame: dd 0 +e3c59x_transmit_function: dd 0 +e3c59x_receive_function: dd 0 +endg + +iglobal +e3c59x_ver_id: db 17 +endg +uglobal +e3c59x_full_bus_master: db 0 +e3c59x_has_hwcksm: db 0 +e3c59x_preamble: db 0 +e3c59x_dn_list_ptr_cleared: db 0 +e3c59x_self_directed_packet: rb 6 +endg + +if defined E3C59X_DEBUG +e3c59x_hw_type_str: db "Detected hardware type : ", 0 +e3c59x_device_str: db "Device ID : 0x" +e3c59x_device_id_str: db "ffff", 13, 10, 0 +e3c59x_vendor_str: db "Vendor ID : 0x" +e3c59x_vendor_id_str: db "ffff", 13, 10, 0 +e3c59x_io_info_str: db "IO address : 0x" +e3c59x_io_addr_str: db "ffff", 13, 10, 0 +e3c59x_mac_info_str: db "MAC address : " +e3c59x_mac_addr_str: db "ff:ff:ff:ff:ff:ff", 13, 10, 0 +e3c59x_boomerang_str: db " (boomerang)", 13, 10, 0 +e3c59x_vortex_str: db " (vortex)", 13, 10, 0 +e3c59x_link_type_str: db "Established link type : ", 0 +e3c59x_new_line_str: db 13, 10, 0 +e3c59x_link_type: dd 0 + +e3c59x_charset: db '0123456789abcdef' + +strtbl e3c59x_link_str, \ + "No valid link type detected", \ + "10BASE-T half duplex", \ + "10BASE-T full-duplex", \ + "100BASE-TX half duplex", \ + "100BASE-TX full duplex", \ + "100BASE-T4", \ + "100BASE-FX", \ + "10Mbps AUI", \ + "10Mbps COAX (BNC)", \ + "miiDevice - not supported" + +strtbl e3c59x_hw_str, \ + "3c590 Vortex 10Mbps", \ + "3c592 EISA 10Mbps Demon/Vortex", \ + "3c597 EISA Fast Demon/Vortex", \ + "3c595 Vortex 100baseTx", \ + "3c595 Vortex 100baseT4", \ + "3c595 Vortex 100base-MII", \ + "3c900 Boomerang 10baseT", \ + "3c900 Boomerang 10Mbps Combo", \ + "3c900 Cyclone 10Mbps TPO", \ + "3c900 Cyclone 10Mbps Combo", \ + "3c900 Cyclone 10Mbps TPC", \ + "3c900B-FL Cyclone 10base-FL", \ + "3c905 Boomerang 100baseTx", \ + "3c905 Boomerang 100baseT4", \ + "3c905B Cyclone 100baseTx", \ + "3c905B Cyclone 10/100/BNC", \ + "3c905B-FX Cyclone 100baseFx", \ + "3c905C Tornado", \ + "3c980 Cyclone", \ + "3c982 Dual Port Server Cyclone", \ + "3cSOHO100-TX Hurricane", \ + "3c555 Laptop Hurricane", \ + "3c556 Laptop Tornado", \ + "3c556B Laptop Hurricane", \ + "3c575 [Megahertz] 10/100 LAN CardBus", \ + "3c575 Boomerang CardBus", \ + "3CCFE575BT Cyclone CardBus", \ + "3CCFE575CT Tornado CardBus", \ + "3CCFE656 Cyclone CardBus", \ + "3CCFEM656B Cyclone+Winmodem CardBus", \ + "3CXFEM656C Tornado+Winmodem CardBus", \ + "3c450 HomePNA Tornado", \ + "3c920 Tornado", \ + "3c982 Hydra Dual Port A", \ + "3c982 Hydra Dual Port B", \ + "3c905B-T4", \ + "3c920B-EMB-WNM Tornado" + +end if ; defined E3C59X_DEBUG + +;*************************************************************************** +; Function +; e3c59x_debug +; Description +; prints debug info to the debug board +; Parameters +; ebp - io_addr +; Return value +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** +if defined E3C59X_DEBUG + align 4 +e3c59x_debug: + pushad +; print device type + mov esi, e3c59x_hw_type_str + call sys_msg_board_str + movzx ecx, byte [e3c59x_ver_id] + mov esi, [e3c59x_hw_str+ecx*4] + call sys_msg_board_str + mov esi, e3c59x_boomerang_str + cmp dword [e3c59x_transmit_function], e3c59x_boomerang_transmit + jz .boomerang + mov esi, e3c59x_vortex_str +.boomerang: + call sys_msg_board_str +; print device/vendor + mov ax, [pci_data+2] + mov cl, 2 + mov ebx, e3c59x_device_id_str + call e3c59x_print_hex + mov esi, e3c59x_device_str + call sys_msg_board_str + mov ax, [pci_data] + mov cl, 2 + mov ebx, e3c59x_vendor_id_str + call e3c59x_print_hex + mov esi, e3c59x_vendor_str + call sys_msg_board_str +; print io address + mov ax, [io_addr] + mov ebx, e3c59x_io_addr_str + mov cl, 2 + call e3c59x_print_hex + mov esi, e3c59x_io_info_str + call sys_msg_board_str +; print MAC address + mov ebx, e3c59x_mac_addr_str + xor ecx, ecx +.mac_loop: + push ecx + mov al, [node_addr+ecx] + mov cl, 1 + call e3c59x_print_hex + inc ebx + pop ecx + inc cl + cmp cl, 6 + jne .mac_loop + mov esi, e3c59x_mac_info_str + call sys_msg_board_str +; print link type + mov esi, e3c59x_link_type_str + call sys_msg_board_str + xor eax, eax + bsr ax, word [e3c59x_link_type] + jz @f + sub ax, 4 +@@: + mov esi, [e3c59x_link_str+eax*4] + call sys_msg_board_str + mov esi, e3c59x_new_line_str + call sys_msg_board_str + popad + ret + +;*************************************************************************** +; Function +; e3c59x_print_hex +; Description +; prints a hexadecimal value +; Parameters +; eax - value to be printed out +; ebx - where to print +; cl - value size (1, 2, 4) +; Return value +; ebx - end address after the print +; Destroyed registers +; eax, ebx +; +;*************************************************************************** + align 4 +e3c59x_print_hex: + cmp cl, 1 + je .print_byte + cmp cl, 2 + jz .print_word +.print_dword: + push eax + bswap eax + xchg ah, al + call .print_word + pop eax +.print_word: + push eax + xchg ah, al + call .print_byte + pop eax +.print_byte: + movzx eax, al + push eax + and al, 0xf0 + shr al, 4 + mov al, byte [eax+e3c59x_charset] + mov [ebx], al + inc ebx + pop eax + and al, 0x0f + mov al, byte [eax+e3c59x_charset] + mov [ebx], al + inc ebx + ret +end if ; defined E3C59X_DEBUG + +;*************************************************************************** +; Function +; e3c59x_try_link_detect +; Description +; e3c59x_try_link_detect checks if link exists +; Parameters +; ebp - io_addr +; Return value +; al - 0 ; no link detected +; al - 1 ; link detected +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_try_link_detect: +; download self-directed packet + mov edi, node_addr + mov bx, 0x0608 ; packet type + mov esi, e3c59x_self_directed_packet + mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes + call dword [e3c59x_transmit_function] +; switch to register window 5 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 + out dx, ax +; program RxFilter for promiscuous operation + mov ax, (10000b shl 11) + lea edx, [ebp+E3C59X_REG_RX_FILTER] + in al, dx + or al, 1111b + lea edx, [ebp+E3C59X_REG_COMMAND] + out dx, ax +; switch to register window 4 + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; check loop + xor ebx, ebx + mov ecx, 0xffff ; 65535 tries +.loop: + push ecx ebx + call dword [e3c59x_receive_function] + pop ebx ecx + test al, al + jnz .finish +.no_packet_received: +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; read linkbeatdetect + lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] + in ax, dx + test ah, 1000b ; test linkBeatDetect + jnz .link_detected + xor al, al + jmp .finish +.link_detected: +; test carrierSense + test al, 100000b + jz .no_carrier_sense + inc ebx +.no_carrier_sense: + dec ecx + jns .loop +; assume the link is good if 0 < ebx < 25 % + test ebx, ebx + setnz al + jz .finish + cmp ebx, 16384 ; 25% + setb al +.finish: +if defined E3C59X_DEBUG + test al, al + jz @f + or byte [e3c59x_link_type+1], 100b +@@: +end if ; defined E3C59X_DEBUG + ret + +;*************************************************************************** +; Function +; e3c59x_try_phy +; Description +; e3c59x_try_phy checks the auto-negotiation function +; in the PHY at PHY index. It can also be extended to +; include link detection for non-IEEE 802.3u +; auto-negotiation devices, for instance the BCM5000. +; Parameters +; ah - PHY index +; ebp - io_addr +; Return value +; al - 0 link is auto-negotiated +; al - 1 no link is auto-negotiated +; Destroyed registers +; eax, ebx, ecx, edx, esi +; +;*************************************************************************** + align 4 +e3c59x_try_phy: + mov al, E3C59X_REG_MII_BMCR + push eax + call e3c59x_mdio_read ; returns with window #4 + or ah, 0x80 ; software reset + mov ebx, eax + pop eax + push eax + call e3c59x_mdio_write ; returns with window #4 +; wait for reset to complete + mov esi, 2000 ; 2000ms = 2s + call delay_ms + pop eax + push eax + call e3c59x_mdio_read ; returns with window #4 + test ah, 0x80 + jnz .fail_finish + pop eax + push eax +; wait for a while after reset + mov esi, 20 ; 20ms + call delay_ms + pop eax + push eax + mov al, E3C59X_REG_MII_BMSR + call e3c59x_mdio_read ; returns with window #4 + test al, 1 ; extended capability supported? + jz .no_ext_cap +; auto-neg capable? + test al, 1000b + jz .fail_finish ; not auto-negotiation capable +; auto-neg complete? + test al, 100000b + jnz .auto_neg_ok +; restart auto-negotiation + pop eax + push eax + mov al, E3C59X_REG_MII_ANAR + push eax + call e3c59x_mdio_read ; returns with window #4 + or ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX + mov ebx, eax + pop eax + call e3c59x_mdio_write ; returns with window #4 + pop eax + push eax + call e3c59x_mdio_read ; returns with window #4 + mov ebx, eax + or bh, 10010b ; restart auto-negotiation + pop eax + push eax + call e3c59x_mdio_write ; returns with window #4 + mov esi, 4000 ; 4000ms = 4 seconds + call delay_ms + pop eax + push eax + mov al, E3C59X_REG_MII_BMSR + call e3c59x_mdio_read ; returns with window #4 + test al, 100000b ; auto-neg complete? + jnz .auto_neg_ok + jmp .fail_finish +.auto_neg_ok: +; compare advertisement and link partner ability registers + pop eax + push eax + mov al, E3C59X_REG_MII_ANAR + call e3c59x_mdio_read ; returns with window #4 + xchg eax, [esp] + mov al, E3C59X_REG_MII_ANLPAR + call e3c59x_mdio_read ; returns with window #4 + pop ebx + and eax, ebx + and eax, 1111100000b + push eax +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], ax +end if ; defined E3C59X_DEBUG +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; set full-duplex mode + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + and ax, not 0x120 ; clear full duplex and flow control + pop ebx + test ebx, (1010b shl 5) ; check for full-duplex + jz .half_duplex + or ax, 0x120 ; set full duplex and flow control +.half_duplex: + out dx, ax + mov al, 1 + ret +.no_ext_cap: +; not yet implemented BCM5000 +.fail_finish: + pop eax + xor al, al + ret + +;*************************************************************************** +; Function +; e3c59x_try_mii +; Description +; e3c59x_try_MII checks the on-chip auto-negotiation logic +; or an off-chip MII PHY, depending upon what is set in +; xcvrSelect by the caller. +; It exits when it finds the first device with a good link. +; Parameters +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, ebx, ecx, edx, esi +; +;*************************************************************************** + align 4 +e3c59x_try_mii: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, (1111b shl 20) + cmp eax, (1000b shl 20) ; is auto-negotiation set? + jne .mii_device +; auto-negotiation is set +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; PHY==24 is the on-chip auto-negotiation logic +; it supports only 10base-T and 100base-TX + mov ah, 24 + call e3c59x_try_phy + test al, al + jz .fail_finish + mov cl, 24 + jmp .check_preamble +.mii_device: + cmp eax, (0110b shl 20) + jne .fail_finish + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + in ax, dx + and al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA) + cmp al, (1 shl E3C59X_BIT_MGMT_DATA) + je .serch_for_phy + xor al, al + ret +.serch_for_phy: +; search for PHY + mov cl, 31 +.search_phy_loop: + cmp cl, 24 + je .next_phy + mov ah, cl ; ah = phy + mov al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register + push ecx + call e3c59x_mdio_read + pop ecx + test ax, ax + jz .next_phy + cmp ax, 0xffff + je .next_phy + mov ah, cl ; ah = phy + push ecx + call e3c59x_try_phy + pop ecx + test al, al + jnz .check_preamble +.next_phy: + dec cl + jns .search_phy_loop +.fail_finish: + xor al, al + ret +; epilog +.check_preamble: + push eax ; eax contains the return value of e3c59x_try_phy +; check hard coded preamble forcing + movzx eax, byte [e3c59x_ver_id] + test word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE + setnz [e3c59x_preamble] ; force preamble + jnz .finish +; check mii for preamble suppression + mov ah, cl + mov al, E3C59X_REG_MII_BMSR + call e3c59x_mdio_read + test al, 1000000b ; preamble suppression? + setz [e3c59x_preamble] ; no +.finish: + pop eax + ret + +;*************************************************************************** +; Function +; e3c59x_test_packet +; Description +; e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port +; Parameters +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_test_packet: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; set fullDuplexEnable in MacControl register + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + or ax, 0x120 + out dx, ax +; switch to register window 5 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 + out dx, ax +; set RxFilter to enable individual address matches + mov ax, (10000b shl 11) + lea edx, [ebp+E3C59X_REG_RX_FILTER] + in al, dx + or al, 1 + lea edx, [ebp+E3C59X_REG_COMMAND] + out dx, ax +; issue RxEnable and TxEnable + call e3c59x_rx_reset + call e3c59x_tx_reset +; download a self-directed test packet + mov edi, node_addr + mov bx, 0x0608 ; packet type + mov esi, e3c59x_self_directed_packet + mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes + call dword [e3c59x_transmit_function] +; wait for 2s + mov esi, 2000 ; 2000ms = 2s + call delay_ms +; check if self-directed packet is received + call dword [e3c59x_receive_function] + test al, al + jnz .finish +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; clear fullDuplexEnable in MacControl register + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + and ax, not 0x120 + out dx, ax + xor al, al +.finish: + ret + +;*************************************************************************** +; Function +; e3c59x_try_loopback +; Description +; tries a loopback packet for 10BASE2 or AUI port +; Parameters +; al - 0: 10Mbps AUI connector +; 1: 10BASE-2 +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_try_loopback: + push eax +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + pop eax + push eax +if defined E3C59X_DEBUG + mov bl, al + inc bl + shl bl, 3 + or byte [e3c59x_link_type+1], bl +end if ; defined E3C59X_DEBUG + test al, al ; aui or coax? + jz .complete_loopback +; enable 100BASE-2 DC-DC converter + mov ax, (10b shl 11) ; EnableDcConverter + out dx, ax +.complete_loopback: + mov cl, 2 ; give a port 3 chances to complete a loopback +.next_try: + push ecx + call e3c59x_test_packet + pop ecx + test al, al + jnz .finish + dec cl + jns .next_try +.finish: + xchg eax, [esp] + test al, al + jz .aui_finish +; issue DisableDcConverter command + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10111b shl 11) + out dx, ax +.aui_finish: + pop eax ; al contains the result of operation +if defined E3C59X_DEBUG + test al, al + jnz @f + and byte [e3c59x_link_type+1], not 11000b +@@: +end if ; defined E3C59X_DEBUG + ret + +;*************************************************************************** +; Function +; e3c59x_set_available_media +; Description +; sets the first available media +; Parameters +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, edx +; +;*************************************************************************** + align 4 +e3c59x_set_available_media: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + push eax + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx + test al, 10b + jz @f +; baseTXAvailable + pop eax + and eax, not (1111b shl 20) + or eax, (100b shl 20) +if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD + mov word [e3c59x_link_type], (1 shl 8) +else if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 7) +end if + jmp .set_media +@@: + test al, 100b + jz @f +; baseFXAvailable + pop eax + and eax, not (1111b shl 20) + or eax, (101b shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 10) +end if + jmp .set_media +@@: + test al, 1000000b + jz @f +; miiDevice + pop eax + and eax, not (1111b shl 20) + or eax, (0110b shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 13) +end if + jmp .set_media +@@: + test al, 1000b + jz @f +.set_default: +; 10bTAvailable + pop eax + and eax, not (1111b shl 20) +if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD + mov word [e3c59x_link_type], (1 shl 6) +else if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 5) +end if ; E3C59X_FORCE_FD + jmp .set_media +@@: + test al, 10000b + jz @f +; coaxAvailable + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10b shl 11) ; EnableDcConverter + out dx, ax + pop eax + and eax, not (1111b shl 20) + or eax, (11b shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 12) +end if ; defined E3C59X_DEBUG + jmp .set_media +@@: + test al, 10000b + jz .set_default +; auiAvailable + pop eax + and eax, not (1111b shl 20) + or eax, (1 shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 11) +end if ; defined E3C59X_DEBUG +.set_media: + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + out dx, eax +if defined E3C59X_FORCE_FD +; set fullDuplexEnable in MacControl register + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + or ax, 0x120 + out dx, ax +end if ; E3C59X_FORCE_FD + mov al, 1 + ret + +;*************************************************************************** +; Function +; e3c59x_set_active_port +; Description +; It selects the media port (transceiver) to be used +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_set_active_port: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + test eax, (1 shl 24) ; check if autoselect enable + jz .set_first_available_media +; check 100BASE-TX and 10BASE-T + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx + test al, 1010b ; check whether 100BASE-TX or 10BASE-T available + jz .mii_device ; they are not available +; set auto-negotiation + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (1000b shl 20) + out dx, eax + call e3c59x_try_mii + test al, al + jz .mii_device + ret +.mii_device: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for off-chip mii device + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx + test al, 1000000b ; check miiDevice + jz .base_fx + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0110b shl 20) ; set MIIDevice + out dx, eax + call e3c59x_try_mii + test al, al + jz .base_fx + ret +.base_fx: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for 100BASE-FX + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx ; read media option register + test al, 100b ; check 100BASE-FX + jz .aui_enable + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0101b shl 20) ; set 100base-FX + out dx, eax + call e3c59x_try_link_detect + test al, al + jz .aui_enable + ret +.aui_enable: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for 10Mbps AUI connector + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx ; read media option register + test al, 100000b ; check 10Mbps AUI connector + jz .coax_available + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0001b shl 20) ; set 10Mbps AUI connector + out dx, eax + xor al, al ; try 10Mbps AUI connector + call e3c59x_try_loopback + test al, al + jz .coax_available + ret +.coax_available: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for coaxial 10BASE-2 port + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx ; read media option register + test al, 10000b ; check 10BASE-2 + jz .set_first_available_media + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0011b shl 20) ; set 10BASE-2 + out dx, eax + mov al, 1 + call e3c59x_try_loopback + test al, al + jz .set_first_available_media + ret +.set_first_available_media: + jmp e3c59x_set_available_media + +;*************************************************************************** +; Function +; e3c59x_wake_up +; Description +; set the power state to D0 +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_wake_up: +; wake up - we directly do it by programming PCI +; check if the device is power management capable + mov al, 2 + mov ah, [pci_bus] + mov bl, PCI_REG_STATUS + mov bh, [pci_dev] + push eax ebx + call pci_read_reg + test al, 10000b ; is there "new capabilities" linked list? + pop ebx eax + jz .device_awake +; search for power management register + mov al, 1 + mov bl, PCI_REG_CAP_PTR + push eax ebx + call pci_read_reg + mov cl, al + cmp cl, 0x3f + pop ebx eax + jbe .device_awake +; traverse the list + mov al, 2 +.pm_loop: + mov bl, cl + push eax ebx + call pci_read_reg + cmp al, 1 + je .set_pm_state + test ah, ah + mov cl, ah + pop ebx eax + jnz .pm_loop + jmp .device_awake +; waku up the device if necessary +.set_pm_state: + pop ebx eax + add bl, PCI_REG_PM_CTRL + push eax ebx + call pci_read_reg + mov cx, ax + test cl, 3 + pop ebx eax + jz .device_awake + and cl, not 11b ; set state to D0 + call pci_write_reg +.device_awake: + ret + +;*************************************************************************** +; Function +; e3c59x_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_probe: + movzx ebp, word [io_addr] + mov al, 2 + mov ah, [pci_bus] + mov bh, [pci_dev] + mov bl, PCI_REG_COMMAND + push ebp eax ebx + call pci_read_reg + mov cx, ax + or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) + and cl, not (1 shl PCI_BIT_MMIO) + pop ebx eax + call pci_write_reg +; wake up the card + call e3c59x_wake_up + pop ebp +; get chip version + mov ax, [pci_data+2] + mov ecx, E3C59X_HW_VERSIONS_SIZE/4-1 +.chip_ver_loop: + cmp ax, [e3c59x_hw_versions+ecx*4] + jz .chip_ver_found + dec ecx + jns .chip_ver_loop + xor ecx, ecx +.chip_ver_found: + mov [e3c59x_ver_id], cl + test word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM + setnz [e3c59x_has_hwcksm] +; set pci latency for vortex cards + test word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX + jz .not_vortex + mov cx, 11111000b ; 248 = max latency + mov al, 1 + mov ah, [pci_bus] + mov bl, PCI_REG_LATENCY + mov bh, [pci_dev] + call pci_write_reg +.not_vortex: +; set RX/TX functions + mov ax, E3C59X_EEPROM_REG_CAPABILITIES + call e3c59x_read_eeprom + test al, 100000b ; full bus master? + setnz [e3c59x_full_bus_master] + jnz .boomerang_func + mov dword [e3c59x_transmit_function], e3c59x_vortex_transmit + mov dword [e3c59x_receive_function], e3c59x_vortex_poll + jmp @f +.boomerang_func: ; full bus master, so use boomerang functions + mov dword [e3c59x_transmit_function], e3c59x_boomerang_transmit + mov dword [e3c59x_receive_function], e3c59x_boomerang_poll +@@: +; read MAC from eeprom + mov ecx, 2 +.mac_loop: + lea ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx] + call e3c59x_read_eeprom + xchg ah, al ; htons + mov [node_addr+ecx*2], ax + dec ecx + jns .mac_loop + test byte [e3c59x_full_bus_master], 0xff + jz .set_preamble +; switch to register window 2 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 + out dx, ax +; activate xcvr by setting some magic bits + lea edx, [ebp+E3C59X_REG_RESET_OPTIONS] + in ax, dx + and ax, not 0x4010 + movzx ebx, byte [e3c59x_ver_id] + test word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR + jz @f + or al, 0x10 +@@: + test word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR + jz @f + or ah, 0x40 +@@: + out dx, ax +.set_preamble: +; use preamble as default + mov byte [e3c59x_preamble], 1 ; enable preamble + +;*************************************************************************** +; Function +; e3c59x_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** +e3c59x_reset: +; issue global reset + call e3c59x_global_reset +; disable interrupts + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (1110b shl 11) + out dx, ax +; enable Statistics + mov ax, (10101b shl 11) + out dx, ax +; set indication + mov ax, (1111b shl 11) or 0x6c6 + out dx, ax +; acknowledge (clear) every interrupt indicator + mov ax, (1101b shl 11) or 0x661 + out dx, ax +; switch to register window 2 + mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 + out dx, ax +; write MAC addres back into the station address registers + lea edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO] + mov esi, node_addr + cld + outsw + add edx, 2 + outsw + add edx, 2 + outsw + add edx, 2 +; clear station mask + xor eax, eax + out dx, ax + add edx, 2 + out dx, ax + add edx, 2 + out dx, ax +; switch to register window 6 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+6 + out dx, ax +; clear all statistics by reading + lea edx, [ebp+E3C59X_REG_CARRIER_LOST] + mov cl, 9 +.stat_clearing_loop: + in al, dx + inc edx + dec cl + jns .stat_clearing_loop + in ax, dx + add dx, 2 + in ax, dx +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; clear BadSSD + lea edx, [ebp+E3C59X_REG_BAD_SSD] + in al, dx +; clear extra statistics bit in NetworkDiagnostic + lea edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC] + in ax, dx + or ax, 0x0040 + out dx, ax +; SetRxEarlyThreshold + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2) + out dx, ax + test byte [e3c59x_full_bus_master], 0xff + jz .skip_boomerang_setting +; set upRxEarlyEnable + lea edx, [ebp+E3C59X_REG_DMA_CTRL] + in eax, dx + or eax, 0x20 + out dx, eax +; TxFreeThreshold + lea edx, [ebp+E3C59X_REG_TX_FREE_THRESH] + mov al, (E3C59X_MAX_ETH_PKT_SIZE / 256) + out dx, al +; program DnListPtr + lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] + xor eax, eax + out dx, eax +.skip_boomerang_setting: +; initialization + call e3c59x_rx_reset + call e3c59x_tx_reset + call e3c59x_set_active_port + call e3c59x_rx_reset + call e3c59x_tx_reset +; switch to register window 5 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 + out dx, ax +; program RxFilter for promiscuous operation + mov ax, (10000b shl 11) + lea edx, [ebp+E3C59X_REG_RX_FILTER] + in al, dx + or al, 1111b + lea edx, [ebp+E3C59X_REG_COMMAND] + out dx, ax +; switch to register window 4 + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; wait for linkDetect + lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] + mov cl, 20 ; wait for max 2s + mov esi, 100 ; 100ms +.link_detect_loop: + call delay_ms + in ax, dx + test ah, 1000b ; linkDetect + jnz @f + dec cl + jnz .link_detect_loop +@@: +; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax +if defined E3C59X_DEBUG + call e3c59x_debug +end if ; defined E3C59X_DEBUG + ret + +;*************************************************************************** +; Function +; e3c59x_global_reset +; Description +; resets the device +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; ax, ecx, edx, esi +; +;*************************************************************************** + align 4 +e3c59x_global_reset: +; GlobalReset + lea edx, [ebp+E3C59X_REG_COMMAND] + xor eax, eax +; or al, 0x14 + out dx, ax +; wait for GlobalReset to complete + mov ecx, 64000 +.global_reset_loop: + in ax, dx + test ah, 10000b ; check CmdInProgress + jz .finish + dec ecx + jnz .global_reset_loop +.finish: +; wait for 2 seconds for NIC to boot + mov esi, 2000 ; 2000ms = 2s + push ebp + call delay_ms + pop ebp + ret + +;*************************************************************************** +; Function +; e3c59x_tx_reset +; Description +; resets and enables transmitter engine +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; ax, ecx, edx +; +;*************************************************************************** + align 4 +e3c59x_tx_reset: +; TxReset + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (01011b shl 11) + out dx, ax +; wait for TxReset to complete + mov ecx, 2000 +.tx_reset_loop: + in ax, dx + test ah, 10000b ; check CmdInProgress + jz .tx_enable + dec ecx + jns .tx_reset_loop + test byte [e3c59x_full_bus_master], 0xff + jz .tx_enable +; init last_dpd + mov dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE + mov dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE +.tx_enable: + mov ax, (01001b shl 11) ; TxEnable + out dx, ax + ret + +;*************************************************************************** +; Function +; e3c59x_rx_reset +; Description +; resets and enables receiver engine +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_rx_reset: + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (0101b shl 11) or 0x4 ; RxReset + out dx, ax +; wait for RxReset to complete + mov ecx, 200000 +.rx_reset_loop: + in ax, dx + test ah, 10000b ; check CmdInProgress + jz .setup_upd + dec ecx + jns .rx_reset_loop +.setup_upd: +; check if full bus mastering + test byte [e3c59x_full_bus_master], 0xff + jz .rx_enable +; create upd ring + mov eax, e3c59x_upd_buff + zero_to_virt eax + mov [e3c59x_curr_upd], eax + mov esi, eax + virt_to_dma esi + mov edi, e3c59x_rx_buff + zero_to_dma edi + mov ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE + zero_to_virt ebx + mov cl, E3C59X_NUM_RX_DESC-1 +.upd_loop: + mov [ebx+E3C59X_UPD_UP_NEXT_PTR], esi + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + mov [eax+E3C59X_UPD_UP_FRAG_ADDR], edi + mov dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31) + add edi, E3C59X_MAX_ETH_FRAME_SIZE + add esi, E3C59X_UPD_SIZE + mov ebx, eax + add eax, E3C59X_UPD_SIZE + dec cl + jns .upd_loop + mov eax, e3c59x_upd_buff + zero_to_dma eax + lea edx, [ebp+E3C59X_REG_UP_LIST_PTR] + out dx, eax ; write E3C59X_REG_UP_LIST_PTR + lea edx, [ebp+E3C59X_REG_COMMAND] +.rx_enable: + mov ax, (00100b shl 11) ; RxEnable + out dx, ax + ret + +;*************************************************************************** +; Function +; e3c59x_write_eeprom +; Description +; reads eeprom +; Note : the caller must switch to the register window 0 +; before calling this function +; Parameters: +; ax - register to be read (only the first 63 words can be read) +; cx - value to be read into the register +; Return value: +; ax - word read +; Destroyed registers +; ax, ebx, edx +; +;*************************************************************************** +; align 4 +;e3c59x_write_eeprom: +; mov edx, [io_addr] +; add edx, E3C59X_REG_EEPROM_COMMAND +; cmp ah, 11b +; ja .finish ; address may have a value of maximal 1023 +; shl ax, 2 +; shr al, 2 +; push eax +;; wait for busy +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .write_enable +; dec ebx +; jns @r +;; write enable +;.write_enable: +; xor eax, eax +; mov eax, (11b shl 4) +; out dx, ax +;; wait for busy +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .erase_loop +; dec ebx +; jns @r +;.erase_loop: +; pop eax +; push eax +; or ax, (11b shl 6) ; erase register +; out dx, ax +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .write_reg +; dec ebx +; jns @r +;.write_reg: +; add edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND +; mov eax, ecx +; out dx, ax +;; write enable +; add edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA +; xor eax, eax +; mov eax, (11b shl 4) +; out dx, ax +; wait for busy +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .issue_write_reg +; dec ebx +; jns @r +;.issue_write_reg: +; pop eax +; or ax, 01b shl 6 +; out dx, ax +;.finish: +; ret +;*************************************************************************** +; Function +; e3c59x_read_eeprom +; Description +; reads eeprom +; Parameters: +; ax - register to be read (only the first 63 words can be read) +; ebp - io_addr +; Return value: +; ax - word read +; Destroyed registers +; ax, ebx, edx, ebp +; +;*************************************************************************** + align 4 +e3c59x_read_eeprom: + push eax +; switch to register window 0 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+0 + out dx, ax + pop eax + and ax, 111111b ; take only the first 6 bits into account + movzx ebx, byte [e3c59x_ver_id] + test word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT + jz @f + add ax, 0x230 ; hardware constant + jmp .read +@@: + add ax, E3C59X_EEPROM_CMD_READ + test word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET + jz .read + add ax, 0x30 +.read: + lea edx, [ebp+E3C59X_REG_EEPROM_COMMAND] + out dx, ax + mov ebx, 0xffff ; duration of about 162 us ;-) +.wait_for_reading: + in ax, dx + test ah, 0x80 ; check bit eepromBusy + jz .read_data + dec ebx + jns .wait_for_reading +.read_data: + lea edx, [ebp+E3C59X_REG_EEPROM_DATA] + in ax, dx + ret + +;*************************************************************************** +; Function +; e3c59x_mdio_sync +; Description +; initial synchronization +; Parameters +; ebp - io_addr +; Return value +; Destroyed registers +; ax, edx, cl +; +;*************************************************************************** + align 4 +e3c59x_mdio_sync: +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax + cmp byte [e3c59x_preamble], 0 + je .no_preamble +; send 32 logic ones + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + mov cl, 31 +.loop: + mov ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR) + out dx, ax + in ax, dx ; delay + mov ax, (1 shl E3C59X_BIT_MGMT_DATA) \ + or (1 shl E3C59X_BIT_MGMT_DIR) \ + or (1 shl E3C59X_BIT_MGMT_CLK) + out dx, ax + in ax, dx ; delay + dec cl + jns .loop +.no_preamble: + ret + +;*************************************************************************** +; Function +; e3c59x_mdio_read +; Description +; read MII register +; see page 16 in D83840A.pdf +; Parameters +; ah - PHY addr +; al - register addr +; ebp - io_addr +; Return value +; ax - register read +; Destroyed registers +; eax, ebx, cx, edx +; +;*************************************************************************** + align 4 +e3c59x_mdio_read: + push eax + call e3c59x_mdio_sync ; returns with window #4 + pop eax + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + shl al, 3 + shr ax, 3 + and ax, not E3C59X_MII_CMD_MASK + or ax, E3C59X_MII_CMD_READ + mov ebx, eax + xor ecx, ecx + mov cl, 13 +.cmd_loop: + mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii + bt ebx, ecx + jnc .zero_bit + or al, (1 shl E3C59X_BIT_MGMT_DATA) +.zero_bit: + out dx, ax + push eax + in ax, dx ; delay + pop eax + or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write + out dx, ax + in ax, dx ; delay + dec cl + jns .cmd_loop +; read data (18 bits with the two transition bits) + mov cl, 17 + xor ebx, ebx +.read_loop: + shl ebx, 1 + xor eax, eax ; read comand + out dx, ax + in ax, dx ; delay + in ax, dx + test al, (1 shl E3C59X_BIT_MGMT_DATA) + jz .dont_set + inc ebx +.dont_set: + mov ax, (1 shl E3C59X_BIT_MGMT_CLK) + out dx, ax + in ax, dx ; delay + dec cl + jns .read_loop + mov eax, ebx + ret + +;*************************************************************************** +; Function +; e3c59x_mdio_write +; Description +; write MII register +; see page 16 in D83840A.pdf +; Parameters +; ah - PHY addr +; al - register addr +; bx - word to be written +; ebp - io_addr +; Return value +; ax - register read +; Destroyed registers +; eax, ebx, cx, edx +; +;*************************************************************************** + align 4 +e3c59x_mdio_write: + push eax + call e3c59x_mdio_sync + pop eax + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + shl al, 3 + shr ax, 3 + and ax, not E3C59X_MII_CMD_MASK + or ax, E3C59X_MII_CMD_WRITE + shl eax, 2 + or eax, 10b ; transition bits + shl eax, 16 + mov ax, bx + mov ebx, eax + mov ecx, 31 +.cmd_loop: + mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii + bt ebx, ecx + jnc .zero_bit + or al, (1 shl E3C59X_BIT_MGMT_DATA) +.zero_bit: + out dx, ax + push eax + in ax, dx ; delay + pop eax + or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write + out dx, ax + in ax, dx ; delay + dec ecx + jns .cmd_loop + ret + +;*************************************************************************** +; Function +; e3c59x_transmit +; Description +; Transmits a packet of data via the ethernet card +; edi - Pointer to 48 bit destination address +; bx - Type of packet +; ecx - size of packet +; esi - pointer to packet data +; ebp - io_addr +; Destroyed registers +; eax, ecx, edx, ebp +; +;*************************************************************************** + align 4 +e3c59x_transmit: + jmp dword [e3c59x_transmit_function] + +;*************************************************************************** +; Function +; e3c59x_check_tx_status +; Description +; Checks TxStatus queue. +; Return value +; al - 0 no error was found +; al - 1 error was found TxReset is needed +; Destroyed registers +; eax, ecx, edx, ebp +; +;*************************************************************************** +e3c59x_check_tx_status: + movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC +; clear TxStatus queue + lea edx, [ebp+E3C59X_REG_TX_STATUS] + mov cl, 31 ; max number of queue entries +.tx_status_loop: + in al, dx + test al, al + jz .finish ; no error + test al, 0x3f + jnz .finish ; error +.no_error_found: +; clear current TxStatus entry which advances the next one + xor al, al + out dx, al + dec cl + jns .tx_status_loop +.finish: + ret + +;*************************************************************************** +; Function +; e3c59x_vortex_transmit +; Description +; Transmits a packet of data via the ethernet card +; edi - Pointer to 48 bit destination address +; bx - Type of packet +; ecx - size of packet +; esi - pointer to packet data +; ebp - io_addr +; Destroyed registers +; eax, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_vortex_transmit: + push ecx + call e3c59x_check_tx_status + pop ecx + test al, al + jz .no_error_found + jmp e3c59x_tx_reset +.no_error_found: +; switch to register window 7 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 + out dx, ax +; check for master operation in progress + lea edx, [ebp+E3C59X_REG_MASTER_STATUS] + in ax, dx + test ah, 0x80 + jnz .finish ; no DMA for sending +; dword boundary correction + cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE + ja .finish ; packet is too long +; write Frame Start Header + mov eax, ecx +; add header length and extend the complete length to dword boundary + add eax, ETH_HLEN+3 + and eax, not 3 + lea edx, [ebp+E3C59X_REG_TX_DATA] + out dx, eax +; prepare the complete frame + push esi + mov esi, edi + mov edi, e3c59x_tx_buff + zero_to_virt edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy packet data + pop esi + push ecx + shr ecx, 2 + rep movsd + pop ecx + and ecx, 3 + rep movsb + mov ecx, eax +; program frame address to be sent + lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] + mov eax, e3c59x_tx_buff + zero_to_dma eax + out dx, eax +; program frame length + lea edx, [ebp+E3C59X_REG_MASTER_LEN] + mov eax, ecx + out dx, ax +; start DMA Down + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10100b shl 11) + 1 ; StartDMADown + out dx, ax +.finish: + ret + +;*************************************************************************** +; Function +; e3c59x_boomerang_transmit +; Description +; Transmits a packet of data via the ethernet card +; edi - Pointer to 48 bit destination address +; bx - Type of packet +; ecx - size of packet +; esi - pointer to packet data +; ebp - io_addr +; Destroyed registers +; eax, ebx, ecx, edx, esi, edi, ebp +; +;*************************************************************************** + align 4 +e3c59x_boomerang_transmit: + push ecx + call e3c59x_check_tx_status + pop ecx + test al, al + jz .no_error_found + jmp e3c59x_tx_reset +.no_error_found: + cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE + ja .finish ; packet is too long +; calculate descriptor address + mov eax, [e3c59x_prev_dpd] + cmp eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE + jb @f +; wrap around + mov eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE +@@: + add eax, E3C59X_DPD_SIZE + zero_to_virt eax + push eax +; check DnListPtr + lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] + in eax, dx +; mark if Dn_List_Ptr is cleared + test eax, eax + setz [e3c59x_dn_list_ptr_cleared] +; finish if no more free descriptor is available - FIXME! + cmp eax, [esp] + pop eax + jz .finish + push eax esi + mov esi, edi +; calculate tx_buffer address + mov edi, [e3c59x_prev_tx_frame] + cmp edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE + jb @f +; wrap around + mov edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE +@@: + add edi, E3C59X_MAX_ETH_FRAME_SIZE + zero_to_virt edi + mov eax, edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy packet data + pop esi + push ecx + shr ecx, 2 + rep movsd + pop ecx + push ecx + and ecx, 3 + rep movsb +; padding, do we really need it? + pop ecx + add ecx, ETH_HLEN + cmp ecx, ETH_ZLEN + jae @f + mov ecx, ETH_ZLEN +@@: +; calculate + mov ebx, ecx + test byte [e3c59x_has_hwcksm], 0xff + jz @f + or ebx, (1 shl 26) ; set AddTcpChecksum +@@: + or ebx, 0x8000 ; transmission complete notification + or ecx, 0x80000000 ; last fragment +; program DPD + mov edi, eax + pop eax + and dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0 + mov dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx + virt_to_dma edi + mov dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi + mov [eax+E3C59X_DPD_DN_FRAG_LEN], ecx +; calculate physical address + virt_to_dma eax + push eax + cmp byte [e3c59x_dn_list_ptr_cleared], 0 + jz .add_to_list +; write Dn_List_Ptr + out dx, eax + jmp .finish +.add_to_list: +; DnStall + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, ((110b shl 11)+2) + out dx, ax +; wait for DnStall to complete + mov ecx, 6000 +.wait_for_stall: + in ax, dx ; read E3C59X_REG_INT_STATUS + test ah, 10000b + jz .dnstall_ok + dec ecx + jnz .wait_for_stall +.dnstall_ok: + pop eax + push eax + mov ebx, [e3c59x_prev_dpd] + zero_to_virt ebx + mov [ebx], eax + lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] + in eax, dx + test eax, eax + jnz .dnunstall +; if Dn_List_Ptr has been cleared fill it up + pop eax + push eax + out dx, eax +.dnunstall: +; DnUnStall + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, ((110b shl 11)+3) + out dx, ax +.finish: + pop eax + dma_to_zero eax + mov [e3c59x_prev_dpd], eax + dma_to_zero edi + mov [e3c59x_prev_tx_frame], edi + ret + +;*************************************************************************** +; Function +; e3c59x_poll +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Destroyed registers +; eax, ebx, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_poll: + jmp dword [e3c59x_receive_function] + +;*************************************************************************** +; Function +; e3c59x_vortex_poll +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Parameters +; ebp - io_addr +; Return value +; al - 0 ; no packet received +; al - 1 ; packet received +; Destroyed registers +; eax, ebx, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_vortex_poll: + and word [eth_rx_data_len], 0 ; assume no packet received + movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC +.rx_status_loop: +; examine RxStatus + lea edx, [ebp+E3C59X_REG_RX_STATUS] + in ax, dx + test ax, ax + jz .finish + test ah, 0x80 ; rxIncomplete + jz .check_error + jmp .finish +.check_error: + test ah, 0x40 + jz .check_length +; discard the top frame received advancing the next one + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (01000b shl 11) + out dx, ax + jmp .rx_status_loop +.check_length: + and eax, 0x1fff + cmp eax, E3C59X_MAX_ETH_PKT_SIZE + ja .discard_frame ; frame is too long discard it +.check_dma: + push eax +; switch to register window 7 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 + out dx, ax +; check for master operation in progress + lea edx, [ebp+E3C59X_REG_MASTER_STATUS] + in ax, dx + test ah, 0x80 + jz .read_frame ; no DMA for receiving + pop eax + jmp .finish +.read_frame: +; program buffer address to read in + lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] +if defined E3C59X_LINUX + mov eax, e3c59x_rx_buff + zero_to_dma eax +else + mov eax, Ether_buffer +end if + out dx, eax +; program frame length + lea edx, [ebp+E3C59X_REG_MASTER_LEN] + mov ax, 1560 + out dx, ax +; start DMA Up + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10100b shl 11) ; StartDMAUp + out dx, ax +; check for master operation in progress +.dma_loop: + lea edx, [ebp+E3C59X_REG_MASTER_STATUS] + in ax, dx + test ah, 0x80 + jnz .dma_loop +; registrate the received packet length + pop eax + mov word [eth_rx_data_len], ax +; discard the top frame received +.discard_frame: + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (01000b shl 11) + out dx, ax +.finish: +; set return value + cmp word [eth_rx_data_len], 0 + setne al + ret + +;*************************************************************************** +; Function +; e3c59x_boomerang_poll +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Parameters +; ebp - io_addr +; Return value +; al - 0 ; no packet received +; al - 1 ; packet received +; Destroyed registers +; eax, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_boomerang_poll: + and word [eth_rx_data_len], 0 ; assume no packet received + movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC +; check if packet is uploaded + mov eax, [e3c59x_curr_upd] + test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete + jnz .check_error + jmp .finish +; packet is uploaded check for any error +.check_error: + test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError + jz .copy_packet_length + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + jmp .finish +.copy_packet_length: + mov ecx, [eax+E3C59X_UPD_PKT_STATUS] + and ecx, 0x1fff + cmp ecx, E3C59X_MAX_ETH_PKT_SIZE + jbe .copy_packet + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + jmp .finish +.copy_packet: + push ecx + mov word [eth_rx_data_len], cx + mov esi, [eax+E3C59X_UPD_UP_FRAG_ADDR] + dma_to_virt esi + mov edi, Ether_buffer + shr ecx, 2 ; first copy dword-wise + cld + rep movsd ; copy the dwords + pop ecx + and ecx, 3 + rep movsb ; copy the rest bytes + mov eax, [e3c59x_curr_upd] + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + virt_to_zero eax + cmp eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE + jb .no_wrap +; wrap around + mov eax, e3c59x_upd_buff-E3C59X_UPD_SIZE +.no_wrap: + add eax, E3C59X_UPD_SIZE + zero_to_virt eax + mov [e3c59x_curr_upd], eax +.finish: +; check if the NIC is in the upStall state + lea edx, [ebp+E3C59X_REG_UP_PKT_STATUS] + in eax, dx + test ah, 0x20 ; UpStalled + jz .noUpUnStall +; issue upUnStall command + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, ((110b shl 11)+1) ; upUnStall + out dx, ax +.noUpUnStall: +; set return value + cmp word [eth_rx_data_len], 0 + setnz al + ret diff --git a/trunk/network/eth_drv/ethernet.inc b/trunk/network/eth_drv/ethernet.inc new file mode 100644 index 000000000..bc1591fd7 --- /dev/null +++ b/trunk/network/eth_drv/ethernet.inc @@ -0,0 +1,1681 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; ETHERNET.INC ;; +;; ;; +;; Ethernet network layer for Menuet OS ;; +;; ;; +;; Version 0.4 22 September 2003 ;; +;; ;; +;; This file contains the following: ;; +;; PCI bus scanning for valid devices ;; +;; Table of supported ethernet drivers ;; +;; Code to identify and activate a supported driver ;; +;; ARP handler ;; +;; Driver interface to the IP layer ;; +;; Gateway support ;; +;; ;; +;; Individual driver files are included here ;; +;; ;; +;; The PCI bus scanning code was ported from the etherboot ;; +;; 5.0.6 project. The copyright statement for that code is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2002 Mike Hibbett ;; +;; mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;******************************************************************** +; Interface +; ethernet_driver called by stack_handler in stack.inc +; eth_probe called by app_stack_handler in stack.inc +; +;******************************************************************** + +; Some useful information on data structures + +; Ethernet Packet - ARP Request example +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Dest H/W Address | +; | ( 14 byte header ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | Source H/W Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Protocol - ARP 08 06 | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | H/W Type 00 01 | Protocol Type 08 00 | +; | ( ARP Request packet ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | HLen 0x06 | PLen 0x04 | OpCode 00 01 | +; | ( 0001 for request, 0002 for reply ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Source Hardware Address ( MAC Address ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | Source IP Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | Destination Hardware Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Destination IP Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +; Include individual drivers source files at this point. +; If you create a new driver, include it below. + +include "rtl8029.inc" +include "i8255x.inc" +include "rtl8139.inc" +include "3c59x.inc" +include "sis900.inc" +include "pcnet32.inc" + +; DEBUGGING_STATE enables or disables output of received and transmitted +; data over the serial port +DEBUGGING_ENABLED equ 1 +DEBUGGING_DISABLED equ 0 +DEBUGGING_STATE equ DEBUGGING_DISABLED + +; PCICards +; ======== +; PCI vendor and hardware types for hardware supported by the above drivers +; If you add a driver, ensure you update this datastructure, otherwise the +; card will not be probed. +; Each driver is defined by 4 double words. These are +; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction +; The last entry must be kept at all zeros, to indicate the end of the list +; As a PCI driver may support more than one hardware implementation, there may +; be several lines which refer to the same functions. +; The first driver found on the PCI bus will be the one used. + +PCICARDS_ENTRY_SIZE equ 20 ; Size of each PCICARDS entry + +iglobal +PCICards: +dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit +dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit +dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit +dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit +dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit +dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit +dd 0x12111113, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit +dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit +dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit +dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit +dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit +dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit +dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit +; following card is untested +dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit +dd 0,0,0,0,0 ; end of list marker, do not remove +endg + +; PCI Bus defines +PCI_HEADER_TYPE equ 0x0e ;8 bit +PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit +PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits +PCI_BASE_ADDRESS_SPACE_IO equ 0x01 +PCI_VENDOR_ID equ 0x00 ;16 bit +PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC + +ETHER_IP equ 0x0008 ; Reversed from 0800 for intel +ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel +ETHER_RARP equ 0x3580 +ARP_REQ_OPCODE equ 0x0100 +ARP_REP_OPCODE equ 0x0200 + +uglobal + arp_rx_count: dd 0 + ip_rx_count: dd 0 + dumped_rx_count: dd 0 + ip_tx_count: dd 0 + node_addr: db 0,0,0,0,0,0 + eth_rx_data_len: dw 0 + eth_status: dd 0 + io_addr: dd 0 + hdrtype: db 0 + vendor_device: dd 0 + pci_data: dd 0 + pci_dev: dd 0 + pci_bus: dd 0 + + ; These will hold pointers to the selected driver functions + drvr_probe: dd 0 + drvr_reset: dd 0 + drvr_poll: dd 0 + drvr_transmit: dd 0 + + ; These hold the destination Host identity for ARP responses + remote_ip_add: dd 0 + remote_hw_add: db 0, 0, 0, 0, 0, 0 +endg + +iglobal + broadcast_add: db 0xff,0xff,0xff,0xff,0xff,0xff + subnet_mask: dd 0x00ffffff +endg + +uglobal + ; This is used by getMACfromIP + MACAddress: db 0,0,0,0,0,0 + gateway_ip: db 0, 0, 0, 0 + dns_ip: dd 0 +endg + +; The follow is the ARP Table. +; This table must be manually updated and the kernel recompilied if +; changes are made to it. +; ARP_TABLE_SIZE defines the size of the table +; ARP_TABLE_ENTRIES defines the number of entries in the table +; Each entry is 10 bytes: 4 Byte IP address, 6 byte MAC Address, +; 2 bytes status, 2 bytes TTL ( in seconds ) +; Empty entries are filled with zeros +; The TTL field is decremented every second, and is deleted when it +; reaches 0. It is refreshed every time a packet is received +; If the TTL field is 0xFFFF it is a permanent entry and is never deleted +; The status field can be the following values +; 0x0000 entry not used +; 0x0001 entry holds a valid mapping +; 0x0002 entry contains an IP address, awaiting ARP response +; 0x0003 No response received to ARP request. +; The last status value is provided to allow the network layer to delete +; a packet that is queued awaiting an ARP response + +ARP_NO_ENTRY equ 0 +ARP_VALID_MAPPING equ 1 +ARP_AWAITING_RESPONSE equ 2 +ARP_RESPONSE_TIMEOUT equ 3 + +ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry +ARP_TABLE_SIZE equ 20 ; Size of table +ARP_TABLE_ENTRIES equ 0 ; Inital, hardcoded entries + +uglobal + ARPTable: + times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 +endg + +iglobal + NumARP: db ARP_TABLE_ENTRIES +endg + +;*************************************************************************** +; Function +; eth_probe +; Description +; Searches for an ethernet card. If found, the card is enabled and +; the ethernet -> IP link established +; +; This function scans the PCI bus looking for a supported device. +; ISA bus is currently not supported. +; +; eax is 0 if no hardware found +;*************************************************************************** +eth_probe: + ; Find a card on the PCI bus, and get it's address + call scan_bus ; Find the ethernet cards PIC address + xor eax, eax + cmp [io_addr], eax + je ep_00x ; Return 0 in eax if no cards found + + call dword [drvr_probe] ; Call the drivers probe function + + mov eax, [io_addr] ; return a non zero value + +ep_00x: + ret + +;*************************************************************************** +; Function +; ethernet_driver +; +; Description +; The ethernet RX and TX handler +; This is a kernel function, called by stack_handler +; +;*************************************************************************** +ethernet_driver: + ; Do nothing if the driver is inactive + cmp [ethernet_active], byte 0 + je eth_exit + + call eth_rx + call eth_tx + +eth_exit: + ret + +;*************************************************************************** +; Function +; eth_rx +; +; Description +; Polls the ethernet card for received data. Extracts if present +; Depending on the Protocol within the packet: +; ARP : Pass to ARP_handler. This may result in an ARP reply +; being tx'ed +; IP : Store in an IP buffer +; +;*************************************************************************** +eth_rx: + xor ax, ax + mov [eth_rx_data_len], ax + call dword [drvr_poll] ; Call the drivers poll function + + mov ax, [eth_rx_data_len] + cmp ax, 0 + je erx_exit + +if DEBUGGING_STATE = DEBUGGING_ENABLED + pusha + mov eax, 0 ;Indicate that this is a received packet + mov cx, [eth_rx_data_len] + mov esi, Ether_buffer + cmp word [esi + 12], ETHER_IP + jnz erxd_done +; cmp byte [esi + 14 + 9], 0x06 ; TCP +; jnz erxd_done + call eth_dump +erxd_done: + popa +end if + + ; Check the protocol. Call appropriate handler + mov eax, Ether_buffer + add eax, 12 ; The address of the protocol word + + mov ax, [eax] + + cmp ax, ETHER_ARP + je erx_001 ; It is ARP + + cmp ax, ETHER_IP + je erx_002 ; It's IP + +; inc dword [dumped_rx_count] + + jmp erx_exit ; If not IP or ARP, ignore + +erx_001: + mov eax, [arp_rx_count] + inc eax + mov [arp_rx_count], eax + + ; At this point, the packet is still in the Ether_buffer + call arp_handler + + jmp erx_exit + +erx_002: + mov eax, [ip_rx_count] + inc eax + mov [ip_rx_count], eax + + ; Check to see if the MAC address is in our arp table + ; refresh the arp ttl if so + + mov esi, Ether_buffer + add esi, 6 + + call refreshARP + + call ether_IP_handler + + jmp erx_exit + +erx_exit: + ret + +;*************************************************************************** +; Function +; eth_tx +; +; Description +; Looks at the NET1OUT_QUEUE for data to send. +; Stores that destination IP in a location used by the tx routine +; Looks up the MAC address in the ARP table; stores that where +; the tx routine can get it +; Get the length of the data. Store that where the tx routine wants it +; Call tx +; Places buffer on empty queue when the tx routine finished +; +;*************************************************************************** +eth_tx: + ; Look for a buffer to tx + mov eax, NET1OUT_QUEUE + call dequeue + cmp ax, NO_BUFFER + je eth_exit ; Exit if no buffer available + + push eax + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + ; Extract the destination IP + ; find the destination IP in the ARP table, get MAC + ; store this MAC in 'MACAddress' + mov ebx, eax ; Save buffer address + mov edx, [ebx + 16] ; get destination address + + ; If the destination address is 255.255.255.255, + ; set the MACAddress to all ones ( broadcast ) + mov [MACAddress], dword 0xffffffff + mov [MACAddress + 4], word 0xffff + cmp edx, 0xffffffff + je etx_send ; If it is broadcast, just send + + call getMACfromIP ; Get the MAC address. + + cmp eax, ARP_VALID_MAPPING + jz etx_send + + ; No valid entry. Are we waiting for a response? + cmp eax, ARP_AWAITING_RESPONSE + jne etx_001 + + ; Re-queue the packet, and exit + pop ebx + mov eax, NET1OUT_QUEUE + call queue + jmp etx_exit + +etx_001: + ; HAs the request been sent, but timed out? + cmp eax, ARP_RESPONSE_TIMEOUT + jne etx_002 + + pop eax + call freeBuff + jmp etx_exit + +etx_002: + ; There is no entry. Re queue the request, and ask ARP to send a request + + ; IP address is in edx + push edx + call arp_request + pop ebx + + ; Add an entry in the ARP table, awaiting response + + cmp byte [NumARP], ARP_TABLE_SIZE + je etx_003 ; We cannot add a new entry in the table + + inc byte [NumARP] + + movzx eax, byte [NumARP] + mov ecx, ARP_ENTRY_SIZE + mul ecx + sub eax, ARP_ENTRY_SIZE + + mov [eax + ARPTable], ebx + xor ebx, ebx + mov [eax + ARPTable + 4], ebx + mov [eax + ARPTable + 8], bx + + ; set the status field up - awaiting response + mov cl, 0x00 + mov [eax + ARPTable + 10], cl + mov cl, 0x02 + mov [eax + ARPTable + 11], cl + + ; Initialise the time to live field - 10s + mov cx, 0x000A + mov [eax + ARPTable + 12], cx + +etx_003: + pop ebx ; Get the buffer back + mov eax, NET1OUT_QUEUE + call queue + jmp etx_exit + +etx_send: + xor ecx, ecx + mov ch, [ebx+2] + mov cl, [ebx+3] ; ; Size of IP packet to send + + mov esi, ebx + + mov edi, MACAddress + +if DEBUGGING_STATE = DEBUGGING_ENABLED + pusha + mov cx, 42 + mov eax, 1 ; Indicate that this is a tx packet + call eth_dump + popa +end if + + mov bx, ETHER_IP + call dword [drvr_transmit] ; Call the drivers transmit function + + ; OK, we have sent a packet, so increment the count + inc dword [ip_tx_count] + + ; And finally, return the buffer to the free queue + pop eax + call freeBuff + +etx_exit: + ret + +;*************************************************************************** +; Function +; ether_IP_handler +; +; Description +; Called when an IP ethernet packet is received on the ethernet +; Header + Data is in Ether_buffer[] +; We just need to get a buffer from the 'free' queue, and +; store the packet in it, then insert the packet number into the +; IPRX queue. +; If no queue entry is available, the packet is silently discarded +; All registers may be destroyed +; +;*************************************************************************** +ether_IP_handler: + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je eiph00x + + ; convert buffer pointer eax to the absolute address + push eax + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edi, eax + + ; get a pointer to the start of the DATA + mov esi, Ether_buffer + 14 + + ; Now store it all away + mov ecx, IPBUFFSIZE / 4 ; Copy all of the available + ; data across - worse case + cld + rep movsd + + ; And finally, place the buffer in the IPRX queue + pop ebx + mov eax, IPIN_QUEUE + call queue + +eiph00x: + ret + +;*************************************************************************** +; +; ARP CODE FOLLOWS +; +; The ARP code is used by ethernet drivers to translate an destination +; IP address into an ethernet hardware address. Functions to broadcast +; requests and handle response are (or will be) here. +; The IP layer has no knowledge of ARP, as this is a network interface +; issue +; +;*************************************************************************** + +;*************************************************************************** +; Function +; arp_timer +; +; Description +; Called every 1s +; It is responsible for removing expired routes +; All registers may be destroyed +; +;*************************************************************************** +arp_timer: + ; loop through all the ARP entries, decrementing each one + ; that doesn't have a TTL of 0xFFFF + movzx eax, byte [NumARP] + +arp_001: + cmp eax, 0 + je arp_003 + + push eax + dec eax + mov ecx, ARP_ENTRY_SIZE + mul ecx + cmp word [ eax + ARPTable + 12], 0xFFFF + je arp_002 + + cmp word [ eax + ARPTable + 12], 0 + je arp_002 + + dec word [eax + ARPTable + 12] + +arp_002: + pop eax + dec eax + jmp arp_001 + + ; Now, look for entries with a TTL of 0 + ; Valid entries and response timeout entries get removed + ; awaiting response gets converted into a response timeout, with a + ; short life time - this allows queued packets to be flushed +arp_003: + movzx edx, byte [NumARP] + cmp edx, 0 + je arp_exit + + ; EDX holds the # of entries to search through + mov eax, 0 + +arp_005: + cmp word [ eax + ARPTable + 12], 0 + jne arp_004 + + ; If it's status code is 0001 or 0003, delete the entry + cmp word [eax + ARPTable + 10], 0x0100 + je arp_007 + cmp word [eax + ARPTable + 10], 0x0300 + je arp_007 + + ; The only other valid code is 0002 - indicating a + ; timeout while waiting for a response. Change the + ; entry to response timed out + + mov [eax + ARPTable + 10], word 0x0300 + mov [eax + ARPTable + 12], word 0x000A + jmp arp_004 + +arp_007: + ; Delete this entry + mov edi, ARPTable + add edi, eax + mov esi, edi + add esi, ARP_ENTRY_SIZE + + mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE + sub ecx, eax + + rep movsb + + dec byte [NumARP] + jmp arp_006 + +arp_004: + add eax, ARP_ENTRY_SIZE +arp_006: + dec edx + cmp edx, 0 + jne arp_005 + +arp_exit: + ret + +;*************************************************************************** +; Function +; arp_request +; +; Description +; Sends an ARP request on the ethernet +; The requested IP address is in edx +; All registers may be destroyed +; +;*************************************************************************** +arp_request: + mov ebx, Ether_buffer + mov ax, 0x0100 + mov [ebx], ax + add ebx, 2 + + mov ax, 0x0008 + mov [ebx], ax + add ebx, 2 + + mov ax, 0x0406 + mov [ebx], ax + add ebx, 2 + + mov ax, 0x0100 + mov [ebx], ax + add ebx, 2 + + mov ecx, node_addr + mov eax, [ecx] + mov [ebx], eax + add ecx, 4 + add ebx, 4 + mov ax, [ecx] + mov [ebx], ax + add ebx, 2 + mov eax, [stack_ip] + mov [ebx], eax + add ebx, 4 + + xor eax, eax + mov [ebx], eax + add ebx, 4 + mov [ebx], ax + + add ebx, 2 + mov [ebx], edx + + ; Now, send it! + + ; Pointer to 48 bit destination address in edi + ; Type of packet in bx + ; size of packet in ecx + ; pointer to packet data in esi + mov edi, broadcast_add + +;if DEBUGGING_STATE = DEBUGGING_ENABLED +; pusha +; mov eax, 1 ; Indicate that this is a tx packet +; mov ecx, 28 +; mov esi, Ether_buffer +; call eth_dump +; popa +;end if + + mov bx, ETHER_ARP + mov ecx, 28 + mov esi, Ether_buffer + call dword [drvr_transmit] ; Call the drivers transmit function + ret + +;*************************************************************************** +; Function +; arp_handler +; +; Description +; Called when an ARP packet is received on the ethernet +; Header + Data is in Ether_buffer[] +; It looks to see if the packet is a request to resolve this Hosts +; IP address. If it is, send the ARP reply packet. +; This Hosts IP address is in dword [stack_ip] ( in network format ) +; This Hosts MAC address is in node_addr[6] +; All registers may be destroyed +; +;*************************************************************************** +arp_handler: + ; Is this a REQUEST? + ; Is this a request for My Host IP + ; Yes - So construct a response message. + ; Send this message to the ethernet card for transmission + + mov ebx, Ether_buffer + + mov edx, ebx + add edx, 20 + mov ax, [edx] + cmp ax, ARP_REQ_OPCODE ; Is this a request packet? + jne arph_resp ; No - so test for response + + mov edx, ebx + add edx, 38 + mov eax, [edx] + + cmp eax, [stack_ip] ; Is it looking for my IP address? + jne arph_exit ; No - so quit now + + ; OK, it is a request for my MAC address. Build the frame and send it + + ; Save the important data from the original packet + ; remote MAC address first + mov ecx, remote_hw_add + mov edx, ebx + add edx, 22 ; edx points to Source h/w address + mov eax, [edx] + mov [ecx], eax + add edx, 4 + add ecx, 4 + mov ax, [edx] + mov [ecx],ax + + ; and also the remote IP address + add edx, 2 + mov eax,[edx] + mov [remote_ip_add], eax + + ; So now we can reuse the packet. ebx still holds the address of + ; the header + packet + ; We dont need the header ( first 14 bytes ) + + mov edx, ebx + add edx, 20 + mov ax, ARP_REP_OPCODE + mov [edx], ax + add edx, 2 + + mov ecx, node_addr + mov eax, [ecx] + mov [edx], eax + add ecx, 4 + add edx, 4 + mov ax, [ecx] + mov [edx], ax + add edx, 2 + mov eax, [stack_ip] + mov [edx], eax + add edx, 4 + mov ecx, remote_hw_add + mov eax, [ecx] + mov [edx], eax + add ecx, 4 + add edx, 4 + mov ax, [ecx] + mov [edx], ax + + add edx, 2 + mov eax, [remote_ip_add] + mov [edx], eax + + ; Now, send it! + + ; Pointer to 48 bit destination address in edi + ; Type of packet in bx + ; size of packet in ecx + ; pointer to packet data in esi + mov edi, remote_hw_add + +;if DEBUGGING_STATE = DEBUGGING_ENABLED +; pusha +; mov eax, 1 ; Indicate that this is a tx packet +; mov ecx, 28 +; mov esi, Ether_buffer + 14 + ; call eth_dump +; popa +;end if + + mov bx, ETHER_ARP + mov ecx, 28 + mov esi, Ether_buffer + 14 + call dword [drvr_transmit] ; Call the drivers transmit function + jmp arph_exit + +arph_resp: + cmp ax, ARP_REP_OPCODE ; Is this a replypacket? + jne arph_resp ; No - so quit + + ; This was a reply, probably directed at me. + ; save the remotes MAC & IP + mov ecx, remote_hw_add + mov edx, ebx + add edx, 22 ; edx points to Source h/w address + mov eax, [edx] + mov [ecx], eax + add edx, 4 + add ecx, 4 + mov ax, [edx] + mov [ecx],ax + + ; and also the remote IP address + add edx, 2 + mov eax,[edx] + mov [remote_ip_add], eax + + ; Now, add an entry in the table for this IP address if it doesn't exist + + push eax + movzx eax, byte [NumARP] + mov ecx, ARP_ENTRY_SIZE + mul ecx + pop edx + movzx ecx, byte [NumARP] + cmp ecx, 0 + je arph_002 + +arph_001: + sub eax, ARP_ENTRY_SIZE + cmp [eax + ARPTable], edx + loopnz arph_001 ; Return back if non match + + jnz arph_002 ; None found, add to end + + mov ecx, [remote_hw_add] + mov [eax + ARPTable + 4], ecx + mov cx, [remote_hw_add+4] + mov [eax + ARPTable + 8], cx + + ; specify the type - a valid entry + mov cl, 0x00 + mov [eax + ARPTable + 10], cl + mov cl, 0x01 + mov [eax + ARPTable + 11], cl + + ; Initialise the time to live field - 1 hour + mov cx, 0x0E10 + mov [eax + ARPTable + 12], cx + jmp arph_exit + +arph_002: + + cmp byte [NumARP], ARP_TABLE_SIZE + je arph_exit + + inc byte [NumARP] + + movzx eax, byte [NumARP] + mov ecx, ARP_ENTRY_SIZE + mul ecx + sub eax, ARP_ENTRY_SIZE + + mov ecx, [remote_ip_add] + mov [eax + ARPTable], ecx + mov ecx, [remote_hw_add] + mov [eax + ARPTable + 4], ecx + mov cx, [remote_hw_add+4] + mov [eax + ARPTable + 8], cx + + mov cl, 0x00 + mov [eax + ARPTable + 10], cl + mov cl, 0x01 + mov [eax + ARPTable + 11], cl + + ; Initialise the time to live field - 1 hour + mov cx, 0x0E10 + mov [eax + ARPTable + 12], cx + +arph_exit: + ret + +; pointer to MAC in esi +refreshARP: + mov ebx, [esi] + mov dx, [esi+4] + push edx + movzx eax, byte [NumARP] + mov ecx, ARP_ENTRY_SIZE + mul ecx + pop edx + movzx ecx, byte [NumARP] + cmp ecx, 0 + je rf_exit + +rf_001: + sub eax, ARP_ENTRY_SIZE + cmp [eax + ARPTable+4], ebx + + je rf_002 + loop rf_001 + jmp rf_exit + +rf_002: + cmp [eax + ARPTable+8], dx + je rf_gotone + loop rf_001 + jmp rf_exit + +rf_gotone: + ; Initialise the time to live field - 1 hour + mov cx, 0x0E10 + mov [eax + ARPTable + 12], cx + +rf_exit: + ret + +;*************************************************************************** +; Function +; getMACfromIP +; +; Description +; Takes an IP address in edx and scans the ARP table for +; a matching entry +; If a match is found, it's MAC address is stored in MACAddress. +; Otherwise the value 0 is writen to MACAddress +; eax holds ARP table entry status code ( ARP_ ) +; ebx unchanged +; +;*************************************************************************** +getMACfromIP: + ; first, check destination IP to see if it is on 'this' network. + ; The test is: + ; if ( destIP & subnet_mask == stack_ip & subnet_mask ) + ; desitnation is local + ; else + ; destination is remote, so pass to gateway + + mov eax, edx + and eax, [subnet_mask] + mov ecx, [stack_ip] + and ecx, [subnet_mask] + cmp eax, ecx + je gm0 + + mov edx, [gateway_ip] +gm0: + push edx + xor eax, eax + mov [MACAddress], eax + mov [MACAddress + 4], ax + + movzx eax, byte [NumARP] + mov ecx, ARP_ENTRY_SIZE + mul ecx + + pop edx + + movzx ecx, byte [NumARP] + cmp ecx, 0 + je gm_none +gm1: + sub eax, ARP_ENTRY_SIZE + cmp [eax + ARPTable], edx + loopnz gm1 ; Return back if non match + jnz gm_none ; Quit if none found + + ; eax holds index + mov ecx, [eax + ARPTable + 4] + mov [MACAddress], ecx + mov cx, [eax + ARPTable + 8] + mov [MACAddress+4], cx + + ; Return the entry status in eax + mov ch, [eax + ARPTable + 10] + mov cl, [eax + ARPTable + 11] + movzx eax, cx + jmp gm_exit + +gm_none: + mov eax, ARP_NO_ENTRY + +gm_exit: + ret + +;*************************************************************************** +; +; PCI CODE FOLLOWS +; +; the following functions provide access to the PCI interface. +; These functions are used by scan_bus, and also some ethernet drivers +; +;*************************************************************************** + +;*************************************************************************** +; Function +; config_cmd +; +; Description +; creates a command dword for use with the PCI bus +; bus # in ebx +; devfn in ecx +; where in edx +; +; command dword returned in eax +; Only eax destroyed +;*************************************************************************** +config_cmd: + push ecx + mov eax, ebx + shl eax, 16 + or eax, 0x80000000 + shl ecx, 8 + or eax, ecx + pop ecx + or eax, edx + and eax, 0xFFFFFFFC + ret + +;*************************************************************************** +; Function +; pcibios_read_config_byte +; +; Description +; reads a byte from the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; byte returned in al ( rest of eax zero ) +; Only eax/edx destroyed +;*************************************************************************** +pcibios_read_config_byte: + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + + xor eax, eax + and dx, 0x03 + add dx, 0xCFC +; and dx, 0xFFC + in al, dx + ret + +;*************************************************************************** +; Function +; pcibios_read_config_word +; +; Description +; reads a word from the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; word returned in ax ( rest of eax zero ) +; Only eax/edx destroyed +;*************************************************************************** +pcibios_read_config_word: + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + + xor eax, eax + and dx, 0x02 + add dx, 0xCFC +; and dx, 0xFFC + in ax, dx + ret + +;*************************************************************************** +; Function +; pcibios_read_config_dword +; +; Description +; reads a dword from the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; dword returned in eax +; Only eax/edx destroyed +;*************************************************************************** +pcibios_read_config_dword: + push edx + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + xor eax, eax + mov dx, 0xCFC + in eax, dx + pop edx + ret + +;*************************************************************************** +; Function +; pcibios_write_config_byte +; +; Description +; write a byte in al to the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; Only eax/edx destroyed +;*************************************************************************** +pcibios_write_config_byte: + push ax + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + pop ax + + and dx, 0x03 + add dx, 0xCFC + out dx, al + ret + +;*************************************************************************** +; Function +; pcibios_write_config_word +; +; Description +; write a word in ax to the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; Only eax/edx destroyed +;*************************************************************************** +pcibios_write_config_word: + push ax + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + pop ax + + and dx, 0x02 + add dx, 0xCFC + out dx, ax + ret + +;*************************************************************************** +; Function +; delay_us +; +; Description +; delays for 30 to 60 us +; +; I would prefer this routine to be able to delay for +; a selectable number of microseconds, but this works for now. +; +; If you know a better way to do 2us delay, pleae tell me! +;*************************************************************************** +delay_us: + push eax + push ecx + + mov ecx,2 + + in al,0x61 + and al,0x10 + mov ah,al + cld + +dcnt1: + in al,0x61 + and al,0x10 + cmp al,ah + jz dcnt1 + + mov ah,al + loop dcnt1 + + pop ecx + pop eax + + ret + +;*************************************************************************** +; Function +; scan_bus +; +; Description +; Scans the PCI bus for a supported device +; If a supported device is found, the drvr_ variables are initialised +; to that drivers functions ( as defined in the PCICards table) +; +; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid +; pci_data holds the PCI vendor + device code +; pci_dev holds PCI bus dev # +; pci_bus holds PCI bus # +; +; io_addr will be zero if no card found +; +;*************************************************************************** +scan_bus: + xor eax, eax + mov [hdrtype], al + mov [pci_data], eax + + xor ebx, ebx ; ebx = bus# 0 .. 255 + +sb_bus_loop: + xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? ) + +sb_devf_loop: + mov eax, ecx + and eax, 0x07 + + cmp eax, 0 + jne sb_001 + + mov edx, PCI_HEADER_TYPE + call pcibios_read_config_byte + mov [hdrtype], al + jmp sb_002 + +sb_001: + mov al, [hdrtype] + and al, 0x80 + cmp al, 0x80 + jne sb_inc_devf + +sb_002: + mov edx, PCI_VENDOR_ID + call pcibios_read_config_dword + mov [vendor_device], eax + cmp eax, 0xffffffff + je sb_empty + cmp eax, 0 + jne sb_check_vendor + +sb_empty: + mov [hdrtype], byte 0 + jmp sb_inc_devf + +sb_check_vendor: + ; iterate though PCICards until end or match found + mov esi, PCICards + +sb_check: + cmp [esi], dword 0 + je sb_inc_devf ; Quit if at last entry + cmp eax, [esi] + je sb_got_card + add esi, PCICARDS_ENTRY_SIZE + jmp sb_check + +sb_got_card: + ; indicate that we have found the card + mov [pci_data], eax + mov [pci_dev], ecx + mov [pci_bus], ebx + + ; Define the driver functions + push eax + mov eax, [esi+4] + mov [drvr_probe], eax + mov eax, [esi+8] + mov [drvr_reset], eax + mov eax, [esi+12] + mov [drvr_poll], eax + mov eax, [esi+16] + mov [drvr_transmit], eax + pop eax + + mov edx, PCI_BASE_ADDRESS_0 + +sb_reg_check: + call pcibios_read_config_dword + mov [io_addr], eax + and eax, PCI_BASE_ADDRESS_IO_MASK + cmp eax, 0 + je sb_inc_reg + mov eax, [io_addr] + and eax, PCI_BASE_ADDRESS_SPACE_IO + cmp eax, 0 + je sb_inc_reg + + mov eax, [io_addr] + and eax, PCI_BASE_ADDRESS_IO_MASK + mov [io_addr], eax + +sb_exit1: + ret + +sb_inc_reg: + add edx, 4 + cmp edx, PCI_BASE_ADDRESS_5 + jbe sb_reg_check + +sb_inc_devf: + inc ecx + cmp ecx, 255 + jb sb_devf_loop + inc ebx + cmp ebx, 256 + jb sb_bus_loop + + ; We get here if we didn't find our card + ; set io_addr to 0 as an indication + xor eax, eax + mov [io_addr], eax + +sb_exit2: + ret + +;*************************************************************************** +; +; DEBUGGING CODE FOLLOWS +; +; If debugging data output is not required, ALL code & data below may +; be removed. +; +;*************************************************************************** + +if DEBUGGING_STATE = DEBUGGING_ENABLED + +;*************************************************************************** +; Function +; eth_dump +; +; Description +; Dumps a tx or rx ethernet packet over the rs232 link +; This is a debugging routine that seriously slows down the stack. +; Use with caution. +; +; Baud rate is 57600, 8n1 com1 +; eax : type (0 == rx, 1 == tx ) +; cx : # of bytes in buffer +; esi : address of buffer start +; edi : pointer to MACAddress ( tx only ) +; +;*************************************************************************** +eth_dump: + pusha + + ; Set the port to the desired speed + mov ebx, 0x3f8 ; combase + + mov edx, ebx + add edx, 3 ; data format register + mov al, 0x80 ; enable access to divisor latch + out dx, al + + mov edx, ebx + add edx, 1 ; interrupt enable register + mov al, 0x00 ; No interruts enabled + out dx, al + + mov edx, ebx + mov al, 0x20 / 16 ; set baud rate to 57600 0x10 =115200 + out dx, al + + mov edx, ebx + add edx, 3 ; data format register + mov al, 0x03 ; 8 data bits + out dx, al + + mov edx, ebx + add edx, 4 ; Modem control register + mov al, 0x08 ; out2 enabled. No handshaking. + out dx, al + + mov edx, ebx + add edx, 1 ; interrupt enable register + mov al, 0x01 ; Receive data interrupt enabled, + out dx, al + + popa + + ; First, display the type of the buffer. + ; If it is a tx buffer, display the macaddress + + pusha + + cmp eax, 0 + jne dd001 + + mov bl, 0x0a + call tx_byted + mov bl, 0x0d + call tx_byted + + ; Output "RX:" + mov bl, 'R' + call tx_byted + mov bl, 'X' + call tx_byted + mov bl, ':' + call tx_byted + jmp dump_data + +dd001: + mov bl, 0x0a + call tx_byted + mov bl, 0x0d + call tx_byted + + ; Output TX: xxxxxxxxxxxx + mov bl, 'T' + call tx_byted + mov bl, 'X' + call tx_byted + mov bl, ':' + call tx_byted + mov bl, ' ' + call tx_byted + + ; Display MAC address + xor eax, eax + mov al, [edi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [edi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + inc edi + xor eax, eax + mov al, [edi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [edi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + inc edi + xor eax, eax + mov al, [edi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [edi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + inc edi + xor eax, eax + mov al, [edi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [edi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + inc edi + xor eax, eax + mov al, [edi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [edi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + inc edi + xor eax, eax + mov al, [edi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [edi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + +dump_data: + popa + + ; OK, we come in here with + ; cx == number of byte to send + ; esi == buffer start + ; +dd_000: + mov bl, 0x0a + call tx_byted + mov bl, 0x0d + call tx_byted + + mov eax, 16 ; Number of characters on the line + mov edi, esi ; Save first byte position for later + + push ecx + +dd_001: + push eax + + ; Print a byte, and a space + xor eax, eax + mov al, [esi] + shr al, 4 + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + xor eax, eax + mov al, [esi] + and al, 0x0f + mov bl, [eax + hexchars] + call tx_byted ; byte in bl eax ebx edx destroyed + + mov bl, ' ' + call tx_byted + + pop eax + + inc esi + dec ecx + cmp ecx, 0 + je dd_0011 ; Print the ASCII format + + dec eax + + cmp eax, 0 + je dd_002 ; Print the ASCII format + jmp dd_001 ; Print rest of line + +dd_0011: + ; First, complete the 16 bytes of data, by printing spaces + dec eax + cmp eax, 0 + je dd_002 + + push eax + mov bl, ' ' + call tx_byted + mov bl, ' ' + call tx_byted + mov bl, ' ' + call tx_byted + pop eax + jmp dd_0011 + +dd_002: + pop ecx + mov esi, edi ; Go back to the start of the line data + + mov eax, 16 + +outLineAscii: + push eax + + xor eax, eax + mov al, [esi] + mov bl, '.' + + cmp al, 0x1F + jle outAscii + cmp al, 0x7e + jge outAscii + + mov bl, al + +outAscii: + call tx_byted ; byte in bl eax ebx edx destroyed + + pop eax + dec ecx + inc esi + cmp ecx, 0 + je dd_003 + + dec eax + cmp eax, 0 + je dd_003 + jmp outLineAscii + +dd_003: + cmp ecx, 0 + je dd_004 + jmp dd_000 + +dd_004: + ret + +;*************************************************************************** +; Function +; tx_byte +; +; Description +; Send a byte in bl out of the com port 1 +; destroys eax, edx +; +;*************************************************************************** +tx_byted: + push ebx ; Save the byte + + mov ebx, 0x3f8 ; get the com port address + + ; Wait for transmit buffer to empty. This could take 1ms @ 9600baud + + mov edx, ebx + add edx, 5 + +wait_txd: + in al, dx ; read uart serialisation status + and al, 0x40 + cmp al, 0 + jz wait_txd ; loop until free + + mov edx, ebx + pop eax ; restore the byte to send + out dx, al + ret + +iglobal + ; This is used for translating hex to ASCII for display or output + hexchars db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' +endg +end if + diff --git a/trunk/network/eth_drv/i8255x.inc b/trunk/network/eth_drv/i8255x.inc new file mode 100644 index 000000000..2aeb86414 --- /dev/null +++ b/trunk/network/eth_drv/i8255x.inc @@ -0,0 +1,739 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; I8255X.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.3 11 August 2003 ;; +;; ;; +;; This driver is based on the eepro100 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2002 Mike Hibbett, ;; +;; mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;******************************************************************** +; Interface +; I8255x_reset +; I8255x_probe +; I8255x_poll +; I8255x_transmit +; +; These functions are referenced in ethernet.inc +; +;******************************************************************** + + +rxfd_status equ eth_data_start +rxfd_command equ eth_data_start + 2 +rxfd_link equ eth_data_start + 4 +rxfd_rx_buf_addr equ eth_data_start + 8 +rxfd_count equ eth_data_start + 12 +rxfd_size equ eth_data_start + 14 +rxfd_packet equ eth_data_start + 16 + + + +uglobal +eeprom_data: times 16 dd 0 + +align 4 + +lstats: +tx_good_frames: dd 0 +tx_coll16_errs: dd 0 +tx_late_colls: dd 0 +tx_underruns: dd 0 +tx_lost_carrier: dd 0 +tx_deferred: dd 0 +tx_one_colls: dd 0 +tx_multi_colls: dd 0 +tx_total_colls: dd 0 +rx_good_frames: dd 0 +rx_crc_errs: dd 0 +rx_align_errs: dd 0 +rx_resource_errs: dd 0 +rx_overrun_errs: dd 0 +rx_colls_errs: dd 0 +rx_runt_errs: dd 0 +done_marker: dd 0 + +align 4 + +confcmd: +confcmd_status: dw 0 +confcmd_command: dw 0 +confcmd_link: dd 0 +endg + +iglobal +confcmd_data: db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 + db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 + db 0x80, 0x3f, 0x05 +endg + +uglobal +align 4 + +txfd: +txfd_status: dw 0 +txfd_command: dw 0 +txfd_link: dd 0 +txfd_tx_desc_addr: dd 0 +txfd_count: dd 0 +txfd_tx_buf_addr0: dd 0 +txfd_tx_buf_size0: dd 0 +txfd_tx_buf_addr1: dd 0 +txfd_tx_buf_size1: dd 0 + +align 4 + +hdr: +hdr_dst_addr: times 6 db 0 +hdr_src_addr: times 6 db 0 +hdr_type: dw 0 +endg + + +;*************************************************************************** +; Function +; wait_for_cmd_done +; +; Description +; waits for the hardware to complete a command +; port address in edx +; +; al destroyed +;*************************************************************************** +wait_for_cmd_done: + in al, dx + cmp al, 0 + jne wait_for_cmd_done + ret + + + +;*************************************************************************** +; Function +; mdio_read +; +; Description +; This probably reads a register in the "physical media interface chip" +; Phy_id in ebx +; location in ecx +; +; Data returned in eax +; +;*************************************************************************** +mdio_read: + mov edx, [io_addr] + add edx, 16 ; SCBCtrlMDI + + mov eax, 0x08000000 + shl ecx, 16 + or eax, ecx + shl ebx, 21 + or eax, ebx + + out dx, eax + +mrlp: + call delay_us + in eax, dx + mov ecx, eax + and ecx, 0x10000000 + jz mrlp + + and eax, 0xffff + ret + + + +;*************************************************************************** +; Function +; mdio_write +; +; Description +; This probably writes a register in the "physical media interface chip" +; Phy_id in ebx +; location in ecx +; data in edx +; Data returned in eax +; +;*************************************************************************** +mdio_write: + mov eax, 0x04000000 + shl ecx, 16 + or eax, ecx + shl ebx, 21 + or eax, ebx + or eax, edx + + mov edx, [io_addr] + add edx, 16 ; SCBCtrlMDI + out dx, eax + +mwlp: + call delay_us + in eax, dx + mov ecx, eax + and ecx, 0x10000000 + jz mwlp + + and eax, 0xffff + ret + + + +;/***********************************************************************/ +;/* I82557 related defines */ +;/***********************************************************************/ + +; Serial EEPROM section. +; A "bit" grungy, but we work our way through bit-by-bit :->. +; EEPROM_Ctrl bits. +EE_SHIFT_CLK equ 0x01 ; EEPROM shift clock. +EE_CS equ 0x02 ; EEPROM chip select. +EE_DATA_WRITE equ 0x04 ; EEPROM chip data in. +EE_DATA_READ equ 0x08 ; EEPROM chip data out. +EE_WRITE_0 equ 0x4802 +EE_WRITE_1 equ 0x4806 +EE_ENB equ 0x4802 + + +; The EEPROM commands include the alway-set leading bit. +EE_READ_CMD equ 6 + +; The SCB accepts the following controls for the Tx and Rx units: +CU_START equ 0x0010 +CU_RESUME equ 0x0020 +CU_STATSADDR equ 0x0040 +CU_SHOWSTATS equ 0x0050 ; Dump statistics counters. +CU_CMD_BASE equ 0x0060 ; Base address to add to add CU commands. +CU_DUMPSTATS equ 0x0070 ; Dump then reset stats counters. + +RX_START equ 0x0001 +RX_RESUME equ 0x0002 +RX_ABORT equ 0x0004 +RX_ADDR_LOAD equ 0x0006 +RX_RESUMENR equ 0x0007 +INT_MASK equ 0x0100 +DRVR_INT equ 0x0200 ; Driver generated interrupt. + + +;*************************************************************************** +; Function +; do_eeprom_cmd +; +; Description +; writes a cmd to the ethernet cards eeprom, by bit bashing +; cmd in ebx +; cmd length in ecx +; return in eax +;*************************************************************************** +do_eeprom_cmd: + mov edx, [io_addr] ; We only require the value in dx + add dx, 14 ; the value SCBeeprom + + mov ax, EE_ENB + out dx, ax + call delay_us + + mov ax, 0x4803 ; EE_ENB | EE_SHIFT_CLK + out dx, ax + call delay_us + + ; dx holds ee_addr + ; ecx holds count + ; eax holds cmd + xor edi, edi ; this will be the receive data + +dec_001: + mov esi, 1 + + dec ecx + shl esi, cl + inc ecx + and esi, ebx + mov eax, EE_WRITE_0 ; I am assuming this doesnt affect the flags.. + cmp esi,0 + jz dec_002 + mov eax, EE_WRITE_1 + +dec_002: + out dx, ax + call delay_us + + or ax, EE_SHIFT_CLK + out dx, ax + call delay_us + + shl edi,1 + + in ax, dx + and ax, EE_DATA_READ + cmp ax,0 + jz dec_003 + inc edi + +dec_003: + loop dec_001 + + mov ax, EE_ENB + out dx, ax + call delay_us + + mov ax, 0x4800 + out dx, ax + call delay_us + + mov eax, edi + + ret + + + +;*************************************************************************** +; Function +; I8255x_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; No inputs +; All registers destroyed +; +;*************************************************************************** +I8255x_reset: + ret + + + +;*************************************************************************** +; Function +; I8255x_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; +;*************************************************************************** +I8255x_probe: + mov eax, [io_addr] + + mov ebx, [pci_bus] + mov ecx, [pci_dev] + mov edx, 0x04 ; PCI_COMMAND + call pcibios_read_config_word + + or ax, 0x05 + mov ebx, [pci_bus] + mov ecx, [pci_dev] + mov edx, 0x04 ; PCI_COMMAND + call pcibios_write_config_word + + mov ebx, 0x6000000 + mov ecx, 27 + call do_eeprom_cmd + and eax, 0xffe0000 + cmp eax, 0xffe0000 + je bige + + mov ebx, 0x1800000 + mov ecx, 0x40 + jmp doread + +bige: + mov ebx, 0x6000000 + mov ecx, 0x100 + +doread: + ; do-eeprom-cmd will destroy all registers + ; we have eesize in ecx + ; read_cmd in ebx + + ; Ignore full eeprom - just load the mac address + mov ecx, 0 + +drlp: + push ecx ; save count + push ebx + mov eax, ecx + shl eax, 16 + or ebx, eax + mov ecx, 27 + call do_eeprom_cmd + + pop ebx + pop ecx + + mov edx, ecx + shl edx, 2 + mov esi, eeprom_data + add esi, edx + mov [esi], eax + + inc ecx + cmp ecx, 16 + jne drlp + + ; OK, we have the MAC address. + ; Now reset the card + + mov edx, [io_addr] + add dx, 8 ; SCBPort + xor eax, eax ; The reset cmd == 0 + out dx, eax + + mov esi, 10 + call delay_ms ; Give the card time to warm up. + + mov eax, lstats + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov eax, 0x0140 ; INT_MASK | CU_STATSADDR + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + + mov eax, 0 + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov eax, 0x0106 ; INT_MASK | RX_ADDR_LOAD + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + + ; build rxrd structure + mov ax, 0x0001 + mov [rxfd_status], ax + mov ax, 0x0000 + mov [rxfd_command], ax + + mov eax, rxfd_status + mov [rxfd_link], eax + + mov eax, Ether_buffer + mov [rxfd_rx_buf_addr], eax + + mov ax, 0 + mov [rxfd_count], ax + + mov ax, 1528 + mov [rxfd_size], ax + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, rxfd_status + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0101 ; INT_MASK | RX_START + out dx, ax + + call wait_for_cmd_done + + ; start the reciver + + mov ax, 0 + mov [rxfd_status], ax + + mov ax, 0xc000 + mov [rxfd_command], ax + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, rxfd_status + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0101 ; INT_MASK | RX_START + out dx, ax + + ; Init TX Stuff + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, 0 + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0160 ; INT_MASK | CU_CMD_BASE + out dx, ax + + call wait_for_cmd_done + + ; Set TX Base address + + ; First, set up confcmd values + + mov ax, 2 + mov [confcmd_command], ax + mov eax, txfd + mov [confcmd_link], eax + + mov ax, 1 + mov [txfd_command], ax ; CmdIASetup + + mov ax, 0 + mov [txfd_status], ax + + mov eax, confcmd + mov [txfd_link], eax + + ; ETH_ALEN is 6 bytes + + mov esi, eeprom_data + mov edi, node_addr + mov ecx, 3 +drp000: + mov eax, [esi] + mov [edi], al + shr eax, 8 + inc edi + mov [edi], al + inc edi + add esi, 4 + loop drp000 + + ; Hard code your MAC address into node_addr at this point, + ; If you cannot read the MAC address from the eeprom in the previous step. + ; You also have to write the mac address into txfd_tx_desc_addr, rather + ; than taking data from eeprom_data + + mov esi, eeprom_data + mov edi, txfd_tx_desc_addr + mov ecx, 3 +drp001: + mov eax, [esi] + mov [edi], al + shr eax, 8 + inc edi + mov [edi], al + inc edi + add esi, 4 + loop drp001 + + mov esi, eeprom_data + (6 * 4) + mov eax, [esi] + shr eax, 8 + and eax, 0x3f + cmp eax, 4 ; DP83840 + je drp002 + cmp eax, 10 ; DP83840A + je drp002 + jmp drp003 + +drp002: + mov ebx, [esi] + and ebx, 0x1f + push ebx + mov ecx, 23 + call mdio_read + pop ebx + or eax, 0x0422 + mov ecx, 23 + mov edx, eax + call mdio_write + +drp003: + mov ax, 0x4002 ; Cmdsuspend | CmdConfigure + mov [confcmd_command], ax + mov ax, 0 + mov [confcmd_status], ax + mov eax, txfd + mov [confcmd_link], eax + mov ebx, confcmd_data + mov al, 0x88 ; fifo of 8 each + mov [ebx + 1], al + mov al, 0 + mov [ebx + 4], al + mov al, 0x80 + mov [ebx + 5], al + mov al, 0x48 + mov [ebx + 15], al + mov al, 0x80 + mov [ebx + 19], al + mov al, 0x05 + mov [ebx + 21], al + + mov eax, txfd + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov eax, 0x0110 ; INT_MASK | CU_START + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done +jmp skip + + ; wait for thing to start +drp004: + mov ax, [txfd_status] + cmp ax, 0 + je drp004 + +skip: + ; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + +I8255x_exit: + ret + + + +;*************************************************************************** +; Function +; I8255x_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; +;*************************************************************************** +I8255x_poll: + mov ax, 0 ; assume no data + mov [eth_rx_data_len], ax + + mov ax, [rxfd_status] + cmp ax, 0 + je i8p_exit + + mov ax, 0 + mov [rxfd_status], ax + + mov ax, 0xc000 + mov [rxfd_command], ax + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, rxfd_status + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0101 ; INT_MASK | RX_START + out dx, ax + + call wait_for_cmd_done + + mov esi, rxfd_packet + mov edi, Ether_buffer + mov ecx, 1518 + cld + rep movsb + + mov ax, [rxfd_count] + and ax, 0x3fff + mov [eth_rx_data_len], ax + +i8p_exit: + ret + + + +;*************************************************************************** +; Function +; I8255x_transmit +; +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +;*************************************************************************** +I8255x_transmit: + + mov [hdr_type], bx + + mov eax, [edi] + mov [hdr_dst_addr], eax + mov ax, [edi+4] + mov [hdr_dst_addr+4], ax + + mov eax, [node_addr] + mov [hdr_src_addr], eax + mov ax, [node_addr+4] + mov [hdr_src_addr+4], ax + + mov edx, [io_addr] + in ax, dx + and ax, 0xfc00 + out dx, ax + + xor ax, ax + mov [txfd_status], ax + mov ax, 0x400C ; Cmdsuspend | CmdTx | CmdTxFlex + mov [txfd_command], ax + mov eax, txfd + mov [txfd_link], eax + mov eax, 0x02208000 + mov [txfd_count], eax + mov eax, txfd_tx_buf_addr0 + mov [txfd_tx_desc_addr], eax + mov eax, hdr + mov [txfd_tx_buf_addr0], eax + mov eax, 14 ; sizeof hdr + mov [txfd_tx_buf_size0], eax + + ; Copy the buffer address and size in + mov eax, esi + mov [txfd_tx_buf_addr1], eax + mov eax, ecx + mov [txfd_tx_buf_size1], eax + + mov eax, txfd + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov ax, 0x0110 ; INT_MASK | CU_START + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + + mov edx, [io_addr] + in ax, dx + +I8t_001: + mov ax, [txfd_status] + cmp ax, 0 + je I8t_001 + + mov edx, [io_addr] + in ax, dx + + ret \ No newline at end of file diff --git a/trunk/network/eth_drv/pcnet32.inc b/trunk/network/eth_drv/pcnet32.inc new file mode 100644 index 000000000..4f6e3db1a --- /dev/null +++ b/trunk/network/eth_drv/pcnet32.inc @@ -0,0 +1,814 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; PCNET32.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 1.0 31 July 2004 ;; +;; ;; +;; This driver is based on the PCNet32 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2004 Jarek Pelczar, ;; +;; jpelczar@interia.pl ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;macro PutStr X +;{ +; local .__xyz1 +; local .__xyz2 +; push esi +; mov esi,.__xyz1 +; call sys_msg_board_str +; push eax +; mov eax,1 +; call delay_hs +; pop eax +; jmp .__xyz2 +;.__xyz1: +; db X +; db 13,10,0 +;.__xyz2: +; pop esi +;} +PCNET32_PORT_AUI equ 0x00 +PCNET32_PORT_10BT equ 0x01 +PCNET32_PORT_GPSI equ 0x02 +PCNET32_PORT_MII equ 0x03 +PCNET32_PORT_PORTSEL equ 0x03 +PCNET32_PORT_ASEL equ 0x04 +PCNET32_PORT_100 equ 0x40 +PCNET32_PORT_FD equ 0x80 +PCNET32_DMA_MASK equ 0xffffffff +PCNET32_LOG_TX_BUFFERS equ 1 +PCNET32_LOG_RX_BUFFERS equ 2 +PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS) +PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1) +PCNET32_TX_RING_LEN_BITS equ 0 +PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS) +PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1) +PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4) +PCNET32_PKT_BUF_SZ equ 1544 +PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8 +pcnet32_txb equ (eth_data_start) +pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) +pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) +pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) +virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) +pcnet32_private: +.mode dw ? +.tlen_rlen dw ? +.phys_addr db ?,?,?,?,?,? +.reserved dw ? +.filter dd ?,? +.rx_ring dd ? +.tx_ring dd ? +.cur_rx dd ? +.cur_tx dd ? +.dirty_rx dd ? +.dirty_tx dd ? +.tx_full db ? +.options dd ? +.full_duplex db ? +.chip_version dd ? +.mii db ? +.ltint db ? +.dxsuflo db ? +.fset db ? +.fdx db ? +end virtual +virtual at 0 +pcnet32_rx_head: +.base dd ? +.buf_length dw ? +.status dw ? +.msg_length dd ? +.reserved dd ? +end virtual +virtual at 0 +pcnet32_tx_head: +.base dd ? +.length dw ? +.status dw ? +.misc dd ? +.reserved dd ? +end virtual + +uglobal +pcnet32_access: +.read_csr dd ? +.write_csr dd ? +.read_bcr dd ? +.write_bcr dd ? +.read_rap dd ? +.write_rap dd ? +.reset dd ? +endg + +iglobal +pcnet32_options_mapping: +dd PCNET32_PORT_ASEL ; 0 Auto-select +dd PCNET32_PORT_AUI ; 1 BNC/AUI +dd PCNET32_PORT_AUI ; 2 AUI/BNC +dd PCNET32_PORT_ASEL ; 3 not supported +dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD +dd PCNET32_PORT_ASEL ; 5 not supported +dd PCNET32_PORT_ASEL ; 6 not supported +dd PCNET32_PORT_ASEL ; 7 not supported +dd PCNET32_PORT_ASEL ; 8 not supported +dd PCNET32_PORT_MII ; 9 MII 10baseT +dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD +dd PCNET32_PORT_MII ; 11 MII (autosel) +dd PCNET32_PORT_10BT ; 12 10BaseT +dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx +dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD +dd PCNET32_PORT_ASEL ; 15 not supported +endg + +PCNET32_WIO_RDP equ 0x10 +PCNET32_WIO_RAP equ 0x12 +PCNET32_WIO_RESET equ 0x14 +PCNET32_WIO_BDP equ 0x16 +PCNET32_DWIO_RDP equ 0x10 +PCNET32_DWIO_RAP equ 0x14 +PCNET32_DWIO_RESET equ 0x18 +PCNET32_DWIO_BDP equ 0x1C +PCNET32_TOTAL_SIZE equ 0x20 +; ebx - index +; return: +; eax - data +pcnet32_wio_read_csr: + push edx + lea edx,[ebp+PCNET32_WIO_RAP] + mov ax,bx + out dx,ax + lea edx,[ebp+PCNET32_WIO_RDP] + in ax,dx + and eax,0xffff + pop edx + ret +; eax - data +; ebx - index +pcnet32_wio_write_csr: + push edx + lea edx,[ebp+PCNET32_WIO_RAP] + xchg eax,ebx + out dx,ax + xchg eax,ebx + lea edx,[ebp+PCNET32_WIO_RDP] + out dx,ax + pop edx + ret +; ebx - index +; return: +; eax - data +pcnet32_wio_read_bcr: + push edx + lea edx,[ebp+PCNET32_WIO_RAP] + mov ax,bx + out dx,ax + lea edx,[ebp+PCNET32_WIO_BDP] + in ax,dx + and eax,0xffff + pop edx + ret +; eax - data +; ebx - index +pcnet32_wio_write_bcr: + push edx + lea edx,[ebp+PCNET32_WIO_RAP] + xchg eax,ebx + out dx,ax + xchg eax,ebx + lea edx,[ebp+PCNET32_WIO_BDP] + out dx,ax + pop edx + ret +pcnet32_wio_read_rap: + push edx + lea edx,[ebp+PCNET32_WIO_RAP] + in ax,dx + and eax,0xffff + pop edx + ret +; eax - val +pcnet32_wio_write_rap: + push edx + lea edx,[ebp+PCNET32_WIO_RAP] + out dx,ax + pop edx + ret +pcnet32_wio_reset: + push edx + push eax + lea edx,[ebp+PCNET32_WIO_RESET] + in ax,dx + pop eax + pop edx + ret +pcnet32_wio_check: + push edx + mov ax,88 + lea edx,[ebp+PCNET32_WIO_RAP] + out dx,ax + nop + nop + in ax,dx + cmp ax,88 + sete al + pop edx + ret + +iglobal +pcnet32_wio: + dd pcnet32_wio_read_csr + dd pcnet32_wio_write_csr + dd pcnet32_wio_read_bcr + dd pcnet32_wio_write_bcr + dd pcnet32_wio_read_rap + dd pcnet32_wio_write_rap + dd pcnet32_wio_reset +endg + +; ebx - index +; return: +; eax - data +pcnet32_dwio_read_csr: + push edx + lea edx,[ebp+PCNET32_DWIO_RAP] + mov ebx,eax + out dx,eax + lea edx,[ebp+PCNET32_DWIO_RDP] + in eax,dx + and eax,0xffff + pop edx + ret +; ebx - index +; eax - data +pcnet32_dwio_write_csr: + push edx + lea edx,[ebp+PCNET32_DWIO_RAP] + xchg eax,ebx + out dx,eax + lea edx,[ebp+PCNET32_DWIO_RDP] + xchg eax,ebx + out dx,eax + pop edx + ret +; ebx - index +; return: +; eax - data +pcnet32_dwio_read_bcr: + push edx + lea edx,[ebp+PCNET32_DWIO_RAP] + mov ebx,eax + out dx,eax + lea edx,[ebp+PCNET32_DWIO_BDP] + in eax,dx + and eax,0xffff + pop edx + ret +; ebx - index +; eax - data +pcnet32_dwio_write_bcr: + push edx + lea edx,[ebp+PCNET32_DWIO_RAP] + xchg eax,ebx + out dx,eax + lea edx,[ebp+PCNET32_DWIO_BDP] + xchg eax,ebx + out dx,eax + pop edx + ret +pcnet32_dwio_read_rap: + push edx + lea edx,[ebp+PCNET32_DWIO_RAP] + in eax,dx + and eax,0xffff + pop edx + ret +; eax - val +pcnet32_dwio_write_rap: + push edx + lea edx,[ebp+PCNET32_DWIO_RAP] + out dx,eax + pop edx + ret +pcnet32_dwio_reset: + push edx + push eax + lea edx,[ebp+PCNET32_DWIO_RESET] + in eax,dx + pop eax + pop edx + ret +pcnet32_dwio_check: + push edx + lea edx,[PCNET32_DWIO_RAP] + mov eax,88 + out dx,eax + nop + nop + in eax,dx + and eax,0xffff + cmp eax,88 + sete al + pop edx + ret + +iglobal +pcnet32_dwio: + dd pcnet32_dwio_read_csr + dd pcnet32_dwio_write_csr + dd pcnet32_dwio_read_bcr + dd pcnet32_dwio_write_bcr + dd pcnet32_dwio_read_rap + dd pcnet32_dwio_write_rap + dd pcnet32_dwio_reset +endg + +pcnet32_init_ring: + mov [pcnet32_private.tx_full],0 + mov [pcnet32_private.cur_rx],0 + mov [pcnet32_private.cur_tx],0 + mov [pcnet32_private.dirty_rx],0 + mov [pcnet32_private.dirty_tx],0 + mov edi,pcnet32_rx_ring + mov ecx,PCNET32_RX_RING_SIZE + mov ebx,pcnet32_rxb +.rx_init: + mov [edi+pcnet32_rx_head.base],ebx + mov [edi+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG + mov [edi+pcnet32_rx_head.status],word 0x8000 + add ebx,PCNET32_PKT_BUF_SZ +; inc ebx + add edi,16 + loop .rx_init + mov edi,pcnet32_tx_ring + mov ecx,PCNET32_TX_RING_SIZE +.tx_init: + mov [edi+pcnet32_tx_head.base],dword 0 + mov [edi+pcnet32_tx_head.status],word 0 + add edi,16 + loop .tx_init + mov [pcnet32_private.tlen_rlen],(PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) + mov esi,node_addr + mov edi,pcnet32_private.phys_addr + cld + movsd + movsw + mov dword [pcnet32_private.rx_ring],pcnet32_rx_ring + mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring + ret +pcnet32_reset: + ; Reset PCNET32 + mov ebp,[io_addr] + call dword [pcnet32_access.reset] + ; set 32bit mode + mov ebx,20 + mov eax,2 + call dword [pcnet32_access.write_bcr] + ; set/reset autoselect bit + mov ebx,2 + call dword [pcnet32_access.read_bcr] + and eax,not 2 + test [pcnet32_private.options],PCNET32_PORT_ASEL + jz .L1 + or eax,2 +.L1: + call dword [pcnet32_access.write_bcr] + ; Handle full duplex setting + cmp byte [pcnet32_private.full_duplex],0 + je .L2 + mov ebx,9 + call dword [pcnet32_access.read_bcr] + and eax,not 3 + test [pcnet32_private.options],PCNET32_PORT_FD + jz .L3 + or eax,1 + cmp [pcnet32_private.options],PCNET32_PORT_FD or PCNET32_PORT_AUI + jne .L4 + or eax,2 + jmp .L4 +.L3: + test [pcnet32_private.options],PCNET32_PORT_ASEL + jz .L4 + cmp [pcnet32_private.chip_version],0x2627 + jne .L4 + or eax,3 +.L4: + mov ebx,9 + call dword [pcnet32_access.write_bcr] +.L2: + ; set/reset GPSI bit + mov ebx,124 + call dword [pcnet32_access.read_csr] + mov ecx,[pcnet32_private.options] + and ecx,PCNET32_PORT_PORTSEL + cmp ecx,PCNET32_PORT_GPSI + jne .L5 + or eax,0x10 +.L5: + call dword [pcnet32_access.write_csr] + cmp [pcnet32_private.mii],0 + je .L6 + test [pcnet32_private.options],PCNET32_PORT_ASEL + jnz .L6 + mov ebx,32 + call dword [pcnet32_access.read_bcr] + and eax,not 0x38 + test [pcnet32_private.options],PCNET32_PORT_FD + jz .L7 + or eax,0x10 +.L7: + test [pcnet32_private.options],PCNET32_PORT_100 + jz .L8 + or eax,0x08 +.L8: + call dword [pcnet32_access.write_bcr] + jmp .L9 +.L6: + test [pcnet32_private.options],PCNET32_PORT_ASEL + jz .L9 + mov ebx,32 +; PutStr "ASEL, enable auto-negotiation" + call dword [pcnet32_access.read_bcr] + and eax,not 0x98 + or eax,0x20 + call dword [pcnet32_access.write_bcr] +.L9: + cmp [pcnet32_private.ltint],0 + je .L10 + mov ebx,5 + call dword [pcnet32_access.read_csr] + or eax,(1 shl 14) + call dword [pcnet32_access.write_csr] +.L10: + mov eax,[pcnet32_private.options] + and eax,PCNET32_PORT_PORTSEL + shl eax,7 + mov [pcnet32_private.mode],ax + mov [pcnet32_private.filter],dword 0xffffffff + mov [pcnet32_private.filter+4],dword 0xffffffff + call pcnet32_init_ring + mov ebx,1 + mov eax,pcnet32_private + and eax,0xffff + call dword [pcnet32_access.write_csr] + mov eax,pcnet32_private + mov ebx,2 + shr eax,16 + call dword [pcnet32_access.write_csr] + mov ebx,4 + mov eax,0x0915 + call dword [pcnet32_access.write_csr] + mov ebx,0 + mov eax,1 + call dword [pcnet32_access.write_csr] + mov ecx,100 +.L11: + xor ebx,ebx + call dword [pcnet32_access.read_csr] + test ax,0x100 + jnz .L12 + loop .L11 +.L12: +; PutStr "hardware reset" + xor ebx,ebx + mov eax,0x0002 + call dword [pcnet32_access.write_csr] + xor ebx,ebx + call dword [pcnet32_access.read_csr] +; PutStr "PCNET reset complete" + ret +pcnet32_adjust_pci_device: + ;*******Get current setting************************ + mov al, 2 ;read a word + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x04 ;from command Register + call pci_read_reg + ;******see if its already set as bus master******** + mov bx, ax + and bx,5 + cmp bx,5 + je pcnet32_adjust_pci_device_Latency + ;******Make card a bus master******* + mov cx, ax ;value to write + mov bh, [pci_dev] + mov al, 2 ;write a word + or cx,5 + mov ah, [pci_bus] + mov bl, 0x04 ;to command register + call pci_write_reg + ;******Check latency setting*********** +pcnet32_adjust_pci_device_Latency: + ;*******Get current latency setting************************ +; mov al, 1 ;read a byte +; mov bh, [pci_dev] +; mov ah, [pci_bus] +; mov bl, 0x0D ;from Lantency Timer Register +; call pci_read_reg + ;******see if its aat least 64 clocks******** +; cmp ax,64 +; jge pcnet32_adjust_pci_device_Done + ;******Set latency to 32 clocks******* +; mov cx, 64 ;value to write +; mov bh, [pci_dev] +; mov al, 1 ;write a byte +; mov ah, [pci_bus] +; mov bl, 0x0D ;to Lantency Timer Register +; call pci_write_reg + ;******Check latency setting*********** +pcnet32_adjust_pci_device_Done: + ret +pcnet32_probe: + mov ebp,[io_addr] + call pcnet32_wio_reset + xor ebx,ebx + call pcnet32_wio_read_csr + cmp eax,4 + jne .try_dwio + call pcnet32_wio_check + and al,al + jz .try_dwio +; PutStr "Using WIO" + mov esi,pcnet32_wio + jmp .L1 +.try_dwio: + call pcnet32_dwio_reset + xor ebx,ebx + call pcnet32_dwio_read_csr + cmp eax,4 + jne .no_dev + call pcnet32_dwio_check + and al,al + jz .no_dev +; PutStr "Using DWIO" + mov esi,pcnet32_dwio + jmp .L1 +.no_dev: +; PutStr "PCNET32 not found" + ret +.L1: + mov edi,pcnet32_access + mov ecx,7 + cld + rep movsd + mov ebx,88 + call dword [pcnet32_access.read_csr] + mov ecx,eax + mov ebx,89 + call dword [pcnet32_access.read_csr] + shl eax,16 + or eax,ecx + mov ecx,eax + and ecx,0xfff + cmp ecx,3 + jne .no_dev + shr eax,12 + and eax,0xffff + mov [pcnet32_private.chip_version],eax +; PutStr "PCNET32 chip version OK" + mov [pcnet32_private.fdx],0 + mov [pcnet32_private.mii],0 + mov [pcnet32_private.fset],0 + mov [pcnet32_private.dxsuflo],0 + mov [pcnet32_private.ltint],0 + mov eax,[pcnet32_private.chip_version] + cmp eax,0x2420 + je .L2 + cmp eax,0x2430 + je .L3 + cmp eax,0x2621 + je .L4 + cmp eax,0x2623 + je .L5 + cmp eax,0x2624 + je .L6 + cmp eax,0x2625 + je .L7 + cmp eax,0x2626 + je .L8 + cmp eax,0x2627 + je .L9 +; PutStr "Invalid chip rev" + jmp .no_dev +.L2: +; PutStr "PCnet/PCI 79C970" + jmp .L10 +.L3: +; PutStr "PCnet/PCI 79C970" + jmp .L10 +.L4: +; PutStr "PCnet/PCI II 79C970A" + mov [pcnet32_private.fdx],1 + jmp .L10 +.L5: +; PutStr "PCnet/FAST 79C971" + mov [pcnet32_private.fdx],1 + mov [pcnet32_private.mii],1 + mov [pcnet32_private.fset],1 + mov [pcnet32_private.ltint],1 + jmp .L10 +.L6: +; PutStr "PCnet/FAST+ 79C972" + mov [pcnet32_private.fdx],1 + mov [pcnet32_private.mii],1 + mov [pcnet32_private.fset],1 + jmp .L10 +.L7: +; PutStr "PCnet/FAST III 79C973" + mov [pcnet32_private.fdx],1 + mov [pcnet32_private.mii],1 + jmp .L10 +.L8: +; PutStr "PCnet/Home 79C978" + mov [pcnet32_private.fdx],1 + mov ebx,49 + call dword [pcnet32_access.read_bcr] + call dword [pcnet32_access.write_bcr] + jmp .L10 +.L9: +; PutStr "PCnet/FAST III 79C975" + mov [pcnet32_private.fdx],1 + mov [pcnet32_private.mii],1 +.L10: + cmp [pcnet32_private.fset],1 + jne .L11 + mov ebx,18 + call dword [pcnet32_access.read_bcr] + or eax,0x800 + call dword [pcnet32_access.write_bcr] + mov ebx,80 + call dword [pcnet32_access.read_csr] + and eax,0xc00 + or eax,0xc00 + call dword [pcnet32_access.write_csr] + mov [pcnet32_private.dxsuflo],1 + mov [pcnet32_private.ltint],1 +.L11: + ; read MAC + mov edi,node_addr + mov edx,ebp + mov ecx,6 +.Lmac: + in al,dx + stosb + inc edx + loop .Lmac +; PutStr "MAC read" + call pcnet32_adjust_pci_device +; PutStr "PCI done" + mov eax,PCNET32_PORT_ASEL + mov [pcnet32_private.options],eax + mov [pcnet32_private.mode],word 0x0003 + mov [pcnet32_private.tlen_rlen],word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) + mov esi,node_addr + mov edi,pcnet32_private.phys_addr + cld + movsd + movsw + mov [pcnet32_private.filter],dword 0 + mov [pcnet32_private.filter+4],dword 0 + mov dword [pcnet32_private.rx_ring],pcnet32_rx_ring + mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring +; PutStr "Switching to 32" + mov ebx,20 + mov eax,2 + call dword [pcnet32_access.write_bcr] + mov ebx,1 + mov eax,(pcnet32_private and 0xffff) + call dword [pcnet32_access.write_csr] + mov ebx,2 + mov eax,(pcnet32_private shr 16) and 0xffff + call dword [pcnet32_access.write_csr] + mov ebx,0 + mov eax,1 + call dword [pcnet32_access.write_csr] + mov esi,1 + call delay_ms + call pcnet32_reset + mov eax, [pci_data] + mov [eth_status], eax + ret +pcnet32_poll: + xor eax,eax + mov [eth_rx_data_len],ax + mov eax,[pcnet32_private.cur_rx] + and eax,PCNET32_RX_RING_MOD_MASK + mov ebx,eax + imul esi,eax,PCNET32_PKT_BUF_SZ + add esi,pcnet32_rxb + shl ebx,4 + add ebx,pcnet32_rx_ring + mov cx,[ebx+pcnet32_rx_head.status] + test cx,0x8000 + jnz .L1 + cmp ch,3 + jne .L1 +; PutStr "PCNETRX" + mov ecx,[ebx+pcnet32_rx_head.msg_length] + and ecx,0xfff + sub ecx,4 + mov [eth_rx_data_len],cx + push ecx + shr ecx,2 + mov edi,Ether_buffer + cld + rep movsd + pop ecx + and ecx,3 + rep movsb + mov [ebx+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG + or [ebx+pcnet32_rx_head.status],word 0x8000 + inc [pcnet32_private.cur_rx] +.L1: + ret +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +pcnet32_xmit: + push edi + push esi + push ebx + push ecx +; PutStr "PCNETTX" + mov esi,edi + mov edi,[pcnet32_private.cur_tx] + imul edi,PCNET32_PKT_BUF_SZ + add edi,pcnet32_txb ; edi=ptxb + mov eax,edi + cld ; copy MAC + movsd + movsw + mov esi,node_addr + cld + movsd + movsw + mov [edi],bx + add edi,2 + mov esi,[esp+8] + mov ecx,[esp] + push ecx + shr ecx,2 + cld + rep movsd + pop ecx + and ecx,3 + rep movsb +; mov ecx,[esp] +; add ecx,14 ; ETH_HLEN +; xor eax,eax +; pad to min length (60=ETH_ZLEN) +; cmp ecx,60 +; jae .L1 +; sub ecx,60 +; cld +; rep stosb +;.L1: + mov edi,pcnet32_tx_ring+0 ; entry=0 + mov ecx,[esp] + add ecx,14 + cmp cx,60 + jae .L1 + mov cx,60 +.L1: + neg cx + mov [edi+pcnet32_tx_head.length],cx + mov [edi+pcnet32_tx_head.misc],dword 0 + mov [edi+pcnet32_tx_head.base],eax + mov [edi+pcnet32_tx_head.status],word 0x8300 + ; trigger an immediate send poll + mov ebx,0 + mov eax,0x0008 ; 0x0048 + mov ebp,[io_addr] + call dword [pcnet32_access.write_csr] + mov dword [pcnet32_private.cur_tx],0 + ; wait for TX to complete + mov ecx,[timer_ticks];[0xfdf0] + add ecx,100 +.L2: + mov ax,[edi+pcnet32_tx_head.status] + test ax,0x8000 + jz .L3 + cmp ecx,[timer_ticks];[0xfdf0] + jb .L4 + mov esi,10 + call delay_ms + jnz .L2 +.L4: +; PutStr "PCNET: Send timeout" +.L3: + mov dword [edi+pcnet32_tx_head.base],0 + pop ecx + pop ebx + pop esi + pop edi + ret diff --git a/trunk/network/eth_drv/rtl8029.inc b/trunk/network/eth_drv/rtl8029.inc new file mode 100644 index 000000000..40683316b --- /dev/null +++ b/trunk/network/eth_drv/rtl8029.inc @@ -0,0 +1,955 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; RTL8029.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.2 31 July 2002 ;; +;; ;; +;; This driver is based on the ns8390 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2002 Mike Hibbett, ;; +;; mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; While this implementation handles only PCI bus RTL8029 ;; +;; hardware, it can be easily adapted to other NE2000 clone ;; +;; products. I just dont have any to try! ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +;******************************************************************** +; Interface +; rtl8029_reset +; rtl8029_probe +; rtl8029_poll +; rtl8029_transmit +; +;******************************************************************** + + + + +;************************************************************************** +; 8390 Register Definitions +;************************************************************************** +D8390_P0_COMMAND equ 0x00 +D8390_P0_PSTART equ 0x01 +D8390_P0_PSTOP equ 0x02 +D8390_P0_BOUND equ 0x03 +D8390_P0_TSR equ 0x04 +D8390_P0_TPSR equ 0x04 +D8390_P0_TBCR0 equ 0x05 +D8390_P0_TBCR1 equ 0x06 +D8390_P0_ISR equ 0x07 +D8390_P0_RSAR0 equ 0x08 +D8390_P0_RSAR1 equ 0x09 +D8390_P0_RBCR0 equ 0x0A +D8390_P0_RBCR1 equ 0x0B +D8390_P0_RSR equ 0x0C +D8390_P0_RCR equ 0x0C +D8390_P0_TCR equ 0x0D +D8390_P0_DCR equ 0x0E +D8390_P0_IMR equ 0x0F +D8390_P1_COMMAND equ 0x00 +D8390_P1_PAR0 equ 0x01 +D8390_P1_PAR1 equ 0x02 +D8390_P1_PAR2 equ 0x03 +D8390_P1_PAR3 equ 0x04 +D8390_P1_PAR4 equ 0x05 +D8390_P1_PAR5 equ 0x06 +D8390_P1_CURR equ 0x07 +D8390_P1_MAR0 equ 0x08 + +D8390_COMMAND_PS0 equ 0x0 ; Page 0 select +D8390_COMMAND_PS1 equ 0x40 ; Page 1 select +D8390_COMMAND_PS2 equ 0x80 ; Page 2 select +D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control +D8390_COMMAND_RD1 equ 0x10 +D8390_COMMAND_RD0 equ 0x08 +D8390_COMMAND_TXP equ 0x04 ; transmit packet +D8390_COMMAND_STA equ 0x02 ; start +D8390_COMMAND_STP equ 0x01 ; stop + +D8390_COMMAND_RD2_STA equ 0x22 +D8390_COMMAND_RD2_STP equ 0x21 +D8390_COMMAND_RD1_STA equ 0x12 +D8390_COMMAND_RD0_STA equ 0x0A +D8390_COMMAND_PS0_RD2_STP equ 0x21 +D8390_COMMAND_PS1_RD2_STP equ 0x61 +D8390_COMMAND_PS0_RD2_STA equ 0x22 +D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26 + +D8390_RCR_MON equ 0x20 ; monitor mode + +D8390_DCR_FT1 equ 0x40 +D8390_DCR_LS equ 0x08 ; Loopback select +D8390_DCR_WTS equ 0x01 ; Word transfer select + +D8390_DCR_FT1_LS equ 0x48 +D8390_DCR_WTS_FT1_LS equ 0x49 + +D8390_ISR_PRX equ 0x01 ; successful recv +D8390_ISR_PTX equ 0x02 ; successful xmit +D8390_ISR_RXE equ 0x04 ; receive error +D8390_ISR_TXE equ 0x08 ; transmit error +D8390_ISR_OVW equ 0x10 ; Overflow +D8390_ISR_CNT equ 0x20 ; Counter overflow +D8390_ISR_RDC equ 0x40 ; Remote DMA complete +D8390_ISR_RST equ 0x80 ; reset + +D8390_RSTAT_PRX equ 0x01 ; successful recv +D8390_RSTAT_CRC equ 0x02 ; CRC error +D8390_RSTAT_FAE equ 0x04 ; Frame alignment error +D8390_RSTAT_OVER equ 0x08 ; FIFO overrun + +D8390_TXBUF_SIZE equ 6 +D8390_RXBUF_END equ 32 +D8390_PAGE_SIZE equ 256 + +ETH_ALEN equ 6 +ETH_HLEN equ 14 +ETH_ZLEN equ 60 +ETH_FRAME_LEN equ 1514 + +FLAG_PIO equ 0x01 +FLAG_16BIT equ 0x02 +ASIC_PIO equ 0 + +VENDOR_NONE equ 0 +VENDOR_WD equ 1 +VENDOR_NOVELL equ 2 +VENDOR_3COM equ 3 + +NE_ASIC_OFFSET equ 0x10 +NE_RESET equ 0x0F ; Used to reset card +NE_DATA equ 0x00 ; Used to read/write NIC mem + +MEM_8192 equ 32 +MEM_16384 equ 64 +MEM_32768 equ 128 + +ISA_MAX_ADDR equ 0x400 + +uglobal +eth_flags: db 0 +eth_vendor: db 0 +eth_nic_base: dw 0 +eth_asic_base: dw 0 +eth_memsize: db 0 +eth_rx_start: db 0 +eth_tx_start: db 0 +eth_bmem: dd 0 +eth_rmem: dd 0 +romdata: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +endg + +iglobal +test_data: db 'NE*000 memory',0 +test_buffer: db ' ',0 +endg + +uglobal +eth_type: dw 0 +pkthdr: db 0,0,0,0 ; status, next, (short) len +pktoff: dw 0 +eth_rx_data_ptr: dd 0 +eth_tmp_len: dw 0 +endg + + + +;*************************************************************************** +; Function +; eth_pio_read +; +; Description +; Read a frame from the ethernet card via Programmed I/O +; src in ebx +; cnt in ecx +; dst in edi +;*************************************************************************** +eth_pio_read: + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epr_001 + + inc ecx + and ecx, 0xFFFFFFFE + +epr_001: + mov al, D8390_COMMAND_RD2_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov al, cl + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR0 + out dx, al + + mov al, ch + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR1 + out dx, al + + mov al, bl + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR0 + out dx, al + + mov al, bh + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR1 + out dx, al + + mov al, D8390_COMMAND_RD0_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov dx, [eth_asic_base] + add dx, ASIC_PIO + + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epr_003 + + shr ecx, 1 + +epr_002: + ; 2 bytes at a time + in ax, dx + mov [edi], ax + add edi, 2 + loop epr_002 + ret + +epr_003: + ; 1 byte at a time + in al, dx + mov [edi], al + inc edi + loop epr_003 + ret + + + + +;*************************************************************************** +; Function +; eth_pio_write +; +; Description +; writes a frame to the ethernet card via Programmed I/O +; dst in ebx +; cnt in ecx +; src in esi +;*************************************************************************** +eth_pio_write: + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epw_001 + + inc ecx + and ecx, 0xFFFFFFFE + +epw_001: + mov al, D8390_COMMAND_RD2_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov al, D8390_ISR_RDC + mov dx, [eth_nic_base] + add dx, D8390_P0_ISR + out dx, al + + + mov al, cl + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR0 + out dx, al + + mov al, ch + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR1 + out dx, al + + mov al, bl + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR0 + out dx, al + + mov al, bh + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR1 + out dx, al + + mov al, D8390_COMMAND_RD1_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov dx, [eth_asic_base] + add dx, ASIC_PIO + + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epw_003 + + shr ecx, 1 + +epw_002: + ; 2 bytes at a time + mov ax, [esi] + add esi, 2 + out dx, ax + + loop epw_002 + jmp epw_004 + +epw_003: + ; 1 byte at a time + mov al, [esi] + inc esi + out dx, al + loop epw_003 + +epw_004: + mov dx, [eth_nic_base] + add dx, D8390_P0_ISR + +epw_005: + in al, dx + and al, D8390_ISR_RDC + cmp al, D8390_ISR_RDC + jne epw_005 + + ret + + + +;*************************************************************************** +; Function +; rtl8029_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; No inputs +; All registers destroyed +; +;*************************************************************************** +rtl8029_reset: + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_RD2_STP + out dx, al + + mov dx, bx + add dx, D8390_P0_DCR + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, FLAG_16BIT + jne nsr_001 + + mov al, 0x49 + jmp nsr_002 + +nsr_001: + mov al, 0x48 + +nsr_002: + out dx, al + + xor al, al + + mov dx, bx + add dx, D8390_P0_RBCR0 + out dx, al + + mov dx, bx + add dx, D8390_P0_RBCR1 + out dx, al + + mov dx, bx + add dx, D8390_P0_RCR + mov al, 0x20 + out dx, al + + mov dx, bx + add dx, D8390_P0_TCR + mov al, 2 + out dx, al + + mov dx, bx + add dx, D8390_P0_TPSR + mov al, [eth_tx_start] + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTART + mov al, [eth_rx_start] + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTOP + mov al, [eth_memsize] + out dx, al + + mov dx, bx + add dx, D8390_P0_BOUND + mov al, [eth_memsize] + dec al + out dx, al + + mov dx, bx + add dx, D8390_P0_ISR + mov al, 0xff + out dx, al + + mov dx, bx + add dx, D8390_P0_IMR + xor al, al + out dx, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS1_RD2_STP + out dx, al + + mov dx, bx + add dx, D8390_P1_PAR0 + mov esi, node_addr + mov ecx, ETH_ALEN + +nsr_003: + mov al, [esi] + out dx, al + + inc esi + inc dx + loop nsr_003 + + mov dx, bx + add dx, D8390_P1_MAR0 + mov ecx, ETH_ALEN + + mov al, 0xff + +nsr_004: + out dx, al + inc dx + loop nsr_004 + + mov dx, bx + add dx, D8390_P1_CURR + mov al, [eth_rx_start] + out dx, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_RD2_STA + out dx, al + + mov dx, bx + add dx, D8390_P0_ISR + mov al, 0xff + out dx, al + + mov dx, bx + add dx, D8390_P0_TCR + mov al, 0 + out dx, al + + mov dx, bx + add dx, D8390_P0_RCR + mov al, 4 + out dx, al + + ret + + + +;*************************************************************************** +; Function +; rtl8029_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; +;*************************************************************************** +rtl8029_probe: + mov eax, [io_addr] + mov [eth_nic_base], ax ; The IO address space is 16 bit only + + mov al, VENDOR_NONE + mov [eth_vendor], al + + mov al, [eth_vendor] + cmp al, VENDOR_NONE + + jne ep_check_have_vendor + xor eax, eax + mov [eth_bmem], eax + + mov al, FLAG_PIO + mov [eth_flags], al + + mov ax, [eth_nic_base] + add ax, NE_ASIC_OFFSET + mov [eth_asic_base], ax + + mov al, MEM_16384 + mov [eth_memsize], al + + mov al, 32 + mov [eth_tx_start], al + + add al, D8390_TXBUF_SIZE + mov [eth_rx_start], al + + mov dx, [eth_asic_base] + add dx, NE_RESET + + in al, dx + out dx, al + + in al, 0x84 + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_RD2_STP + out dx, al + + mov dx, bx + add dx, D8390_P0_RCR + mov al, D8390_RCR_MON + out dx, al + + mov dx, bx + add dx, D8390_P0_DCR + mov al, D8390_DCR_FT1_LS + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTART + mov al, MEM_8192 + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTOP + mov al, MEM_16384 + out dx, al + + mov esi, test_data + mov ebx, 8192 + mov ecx, 14 + call eth_pio_write + + mov ebx, 8192 + mov ecx, 14 + mov edi, test_buffer + call eth_pio_read + + mov esi, test_buffer + mov edi, test_data + mov ecx, 13 + cld + rep cmpsb + + je ep_set_vendor + + mov al, [eth_flags] + or al, FLAG_16BIT + mov [eth_flags], al + + mov al, MEM_32768 + mov [eth_memsize], al + + mov al, 64 + mov [eth_tx_start], al + + add al, D8390_TXBUF_SIZE + mov [eth_rx_start], al + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_DCR + mov al, D8390_DCR_WTS_FT1_LS + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTART + mov al, MEM_16384 + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTOP + mov al, MEM_32768 + out dx, al + + mov esi, test_data + mov ebx, 16384 + mov ecx, 14 + call eth_pio_write + + mov ebx, 16384 + mov ecx, 14 + mov edi, test_buffer + call eth_pio_read + + mov esi, test_buffer + mov edi, test_data + mov ecx, 13 + cld + rep cmpsb + +ep_set_vendor: + ; this bit is odd - probably left over from my hacking + mov ax, [eth_nic_base] + cmp ax, 0 + je rtl8029_exit + cmp ax, ISA_MAX_ADDR + jbe ep_001 + mov al, [eth_flags] + or al, FLAG_16BIT + mov [eth_flags], al + +ep_001: + mov al, VENDOR_NOVELL + mov [eth_vendor], al + + mov ebx, 0 + mov ecx, 16 + mov edi, romdata + call eth_pio_read + + + mov ecx, ETH_ALEN + mov esi, romdata + mov edi, node_addr + + mov bl, [eth_flags] + and bl, FLAG_16BIT + +ep_002: + mov al, [esi] + mov [edi], al + + inc edi + inc esi + cmp bl, FLAG_16BIT + jne ep_003 + + inc esi + +ep_003: + loop ep_002 + +ep_check_have_vendor: + mov al, [eth_vendor] + cmp al, VENDOR_NONE + je rtl8029_exit + + cmp al, VENDOR_3COM + je ep_reset_card + + mov eax, [eth_bmem] + mov [eth_rmem], eax + +ep_reset_card: + ; Reset the card + call rtl8029_reset + + ; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + +rtl8029_exit: + ret + + + +;*************************************************************************** +; Function +; rtl8029_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; +;*************************************************************************** +rtl8029_poll: + mov eax, Ether_buffer + mov [eth_rx_data_ptr], eax + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_RSR + in al, dx + + and al, D8390_RSTAT_PRX + cmp al, D8390_RSTAT_PRX + jne nsp_exit + + mov dx, bx + add dx, D8390_P0_BOUND + in al, dx + inc al + + cmp al, [eth_memsize] + jb nsp_001 + + mov al, [eth_rx_start] + +nsp_001: + mov ch, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS1 + out dx, al + + mov dx, bx + add dx, D8390_P1_CURR + in al, dx ; get current page + mov cl, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0 + out dx, al + + cmp cl, [eth_memsize] + jb nsp_002 + + mov cl, [eth_rx_start] + +nsp_002: + cmp cl, ch + je nsp_exit + + xor ax, ax + mov ah, ch + + mov [pktoff], ax + + mov al, [eth_flags] + and al, FLAG_PIO + cmp al, FLAG_PIO + jne nsp_003 + + movzx ebx, word [pktoff] + mov edi, pkthdr + mov ecx, 4 + call eth_pio_read + jmp nsp_004 + +nsp_003: + mov edi, [eth_rmem] + movzx eax, word [pktoff] + add edi, eax + mov eax, [edi] + mov [pkthdr], eax + +nsp_004: + mov ax, [pktoff] + add ax, 4 + mov [pktoff], ax + + mov ax, [pkthdr + 2] + sub ax, 4 + + mov [eth_tmp_len], ax + + cmp ax, ETH_ZLEN + jb nsp_exit + + cmp ax, ETH_FRAME_LEN + ja nsp_exit + + mov al, [pkthdr] + and al, D8390_RSTAT_PRX + cmp al, D8390_RSTAT_PRX + jne nsp_exit + + ; Right, we can now get the data + + mov ax, [eth_tmp_len] + mov [eth_rx_data_len], ax + + xor ebx, ebx + mov bh, [eth_memsize] + sub bx, [pktoff] + + cmp [eth_tmp_len], bx + jbe nsp_005 + + mov al, [eth_flags] + and al, FLAG_PIO + cmp al, FLAG_PIO + jne nsp_006 + + push ebx + mov ecx, ebx + xor ebx, ebx + mov bx, [pktoff] + mov edi, [eth_rx_data_ptr] + call eth_pio_read + pop ebx + jmp nsp_007 + +nsp_006: + ; Not implemented, as we are using PIO mode on this card + +nsp_007: + xor ax, ax + mov ah, [eth_rx_start] + mov [pktoff], ax + + mov eax, [eth_rx_data_ptr] + add eax, ebx + mov [eth_rx_data_ptr], eax + + mov ax, [eth_tmp_len] + sub ax, bx + mov [eth_tmp_len], ax + +nsp_005: + mov al, [eth_flags] + and al, FLAG_PIO + cmp al, FLAG_PIO + jne nsp_008 + + xor ebx, ebx + mov bx, [pktoff] + xor ecx, ecx + mov cx, [eth_tmp_len] + mov edi, [eth_rx_data_ptr] + call eth_pio_read + jmp nsp_009 + +nsp_008: + ; Not implemented, as we are using PIO mode on this card + +nsp_009: + mov al, [pkthdr+1] + cmp al, [eth_rx_start] + jne nsp_010 + + mov al, [eth_memsize] + +nsp_010: + mov dx, [eth_nic_base] + add dx, D8390_P0_BOUND + dec al + out dx, al + +nsp_exit: + ret + + + +;*************************************************************************** +; Function +; rtl8029_transmit +; +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +;*************************************************************************** +rtl8029_transmit: + mov [eth_type], bx + + pusha + + mov esi, edi + xor bx, bx + mov bh, [eth_tx_start] + mov ecx, ETH_ALEN + call eth_pio_write + + mov esi, node_addr + xor bx, bx + mov bh, [eth_tx_start] + add bx, ETH_ALEN + mov ecx, ETH_ALEN + call eth_pio_write + + mov esi, eth_type + xor bx, bx + mov bh, [eth_tx_start] + add bx, ETH_ALEN + add bx, ETH_ALEN + mov ecx, 2 + call eth_pio_write + + popa + + xor bx, bx + mov bh, [eth_tx_start] + add bx, ETH_HLEN + push ecx + call eth_pio_write + pop ecx + + add ecx, ETH_HLEN + cmp ecx, ETH_ZLEN + jae nst_001 + + mov ecx, ETH_ZLEN + +nst_001: + push ecx + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_RD2_STA + out dx, al + + mov dx, bx + add dx, D8390_P0_TPSR + mov al, [eth_tx_start] + out dx, al + + pop ecx + + mov dx, bx + add dx, D8390_P0_TBCR0 + mov al, cl + out dx, al + + mov dx, bx + add dx, D8390_P0_TBCR1 + mov al, ch + out dx, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_TXP_RD2_STA + out dx, al + + ret diff --git a/trunk/network/eth_drv/rtl8139.inc b/trunk/network/eth_drv/rtl8139.inc new file mode 100644 index 000000000..d4e50b422 --- /dev/null +++ b/trunk/network/eth_drv/rtl8139.inc @@ -0,0 +1,595 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; RTL8139.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.2 11 August 2003 ;; +;; ;; +;; Driver for chips of RealTek 8139 family ;; +;; References: ;; +;; www.realtek.com.hw - data sheets ;; +;; rtl8139.c - linux driver ;; +;; 8139too.c - linux driver ;; +;; ethernet driver template by Mike Hibbett ;; +;; ;; +;; The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; Copyright 2003 Endre Kozma, ;; +;; endre.kozma@axelero.hu ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ETH_ALEN equ 6 + ETH_HLEN equ (2 * ETH_ALEN + 2) + ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length + + PCI_REG_COMMAND equ 0x04 ; command register + PCI_BIT_PIO equ 0 ; bit0: io space control + PCI_BIT_MMIO equ 1 ; bit1: memory space control + PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master + + RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0 + RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4 + RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor + RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor + RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address + RTL8139_REG_COMMAND equ 0x37 ; command register + RTL8139_REG_CAPR equ 0x38 ; current address of packet read + RTL8139_REG_IMR equ 0x3c ; interrupt mask register + RTL8139_REG_ISR equ 0x3e ; interrupt status register + RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register + RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0 + RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1 + RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2 + RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3 + RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0 + RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0 + RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1 + RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2 + RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3 + RTL8139_REG_MPC equ 0x4c ; missed packet counter + RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register + RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1 + RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4 + RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register + RTL8139_REG_BMCR equ 0x62 ; basic mode control register + RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register + +; 5.1 packet header + RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes + RTL8139_BIT_LONG equ 3 ; total packet length > 4k + RTL8139_BIT_CRC equ 2 ; crc error occured + RTL8139_BIT_FAE equ 1 ; frame alignment error occured + RTL8139_BIT_ROK equ 0 ; received packet is ok +; 5.4 command register + RTL8139_BIT_RST equ 4 ; reset bit + RTL8139_BIT_RE equ 3 ; receiver enabled + RTL8139_BIT_TE equ 2 ; transmitter enabled + RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored +; 5.6 interrupt status register + RTL8139_BIT_ISR_TOK equ 2 ; transmit ok + RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt + RTL8139_BIT_ISR_ROK equ 0 ; receive ok +; 5.7 transmit configyration register + RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst + RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16) +; 5.8 receive configuration register + RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold + RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator + RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst + RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping + RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356 + RTL8139_BIT_AER equ 5 ; accept error packets + RTL8139_BIT_AR equ 4 ; accept runt packets + RTL8139_BIT_AB equ 3 ; accept broadcast packets + RTL8139_BIT_AM equ 2 ; accept multicast packets + RTL8139_BIT_APM equ 1 ; accept physical match packets + RTL8139_BIT_AAP equ 0 ; accept all packets +; 5.9 93C46/93C56 command register + RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1 + RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0 + RTL8139_BIT_93C46_EECS equ 3 ; chip select + RTL8139_BIT_93C46_EESK equ 2 ; serial data clock + RTL8139_BIT_93C46_EEDI equ 1 ; serial data input + RTL8139_BIT_93C46_EEDO equ 0 ; serial data output +; 5.11 configuration register 1 + RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1 + RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips + RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips + RTL8139_BIT_PMEn equ 0 ; power management enabled +; 5.14 configuration register 4 + RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4 +; 6.2 transmit status register + RTL8139_BIT_ERTXTH equ 16 ; early TX threshold + RTL8139_BIT_TOK equ 15 ; transmit ok + RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed +; 6.18 basic mode control register + RTL8139_BIT_ANE equ 12 ; auto negotiation enable +; 6.20 auto negotiation advertisement register + RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex + RTL8139_BIT_TX equ 7 ; 100base-T + RTL8139_BIT_10FD equ 6 ; 10base-T full duplex + RTL8139_BIT_10 equ 5 ; 10base-T + RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001 +; RX/TX buffer size + RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k + RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN) + MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC + RTL8139_NUM_TX_DESC equ 4 + RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC) + RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16) + RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128 + ; 4==256 5==512 6==1024 7==2048 + RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256 + RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128 + ; 4==256 5==512 6==1024 7==unlimited + RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128 + ; 4==256 5==512 6==1024 7==no threshold + RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \ + or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \ + or (1 shl RTL8139_BIT_NOWRAP) \ + or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \ + or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \ + or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \ + or (1 shl RTL8139_BIT_AM)) + RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout + + EE_93C46_REG_ETH_ID equ 7 ; MAC offset + EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address + EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address + EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address + EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress + + VER_RTL8139 equ 1100000b + VER_RTL8139A equ 1110000b +; VER_RTL8139AG equ 1110100b + VER_RTL8139B equ 1111000b + VER_RTL8130 equ VER_RTL8139B + VER_RTL8139C equ 1110100b + VER_RTL8100 equ 1111010b + VER_RTL8100B equ 1110101b + VER_RTL8139D equ VER_RTL8100B + VER_RTL8139CP equ 1110110b + VER_RTL8101 equ 1110111b + + IDX_RTL8139 equ 0 + IDX_RTL8139A equ 1 + IDX_RTL8139B equ 2 + IDX_RTL8139C equ 3 + IDX_RTL8100 equ 4 + IDX_RTL8139D equ 5 + IDX_RTL8139D equ 6 + IDX_RTL8101 equ 7 + + +; These two must be 4 byte aligned ( which they are ) +rtl8139_rx_buff equ eth_data_start +rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE) + +uglobal + align 4 +rtl8139_rx_buff_offset: dd 0 +curr_tx_desc: dd 0 +endg + +iglobal +hw_ver_array: db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C + db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101 +HW_VER_ARRAY_SIZE = $-hw_ver_array +endg + +uglobal +hw_ver_id: db 0 +endg + +;*************************************************************************** +; Function +; rtl8139_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; Destroyed registers +; eax, ebx, ecx, edx +; +;*************************************************************************** +rtl8139_probe: +; enable the device + mov al, 2 + mov ah, [pci_bus] + mov bh, [pci_dev] + mov bl, PCI_REG_COMMAND + call pci_read_reg + mov cx, ax + or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) + and cl, not (1 shl PCI_BIT_MMIO) + mov al, 2 + mov ah, [pci_bus] + mov bh, [pci_dev] + mov bl, PCI_REG_COMMAND + call pci_write_reg +; get chip version + mov edx, [io_addr] + add edx, RTL8139_REG_TXCONFIG_2 + in ax, dx + shr ah, 2 + shr ax, 6 + and al, 01111111b + mov ecx, HW_VER_ARRAY_SIZE-1 +.chip_ver_loop: + cmp al, [hw_ver_array+ecx] + je .chip_ver_found + dec ecx + jns .chip_ver_loop + xor cl, cl ; default RTL8139 +.chip_ver_found: + mov [hw_ver_id], cl +; wake up the chip + mov edx, [io_addr] + add edx, RTL8139_REG_HLTCLK + mov al, 'R' ; run the clock + out dx, al +; unlock config and BMCR registers + add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) + out dx, al +; enable power management + add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR + in al, dx + cmp byte [hw_ver_id], IDX_RTL8139B + jl .old_chip +; set LWAKE pin to active high (default value). +; it is for Wake-On-LAN functionality of some motherboards. +; this signal is used to inform the motherboard to execute a wake-up process. +; only at newer chips. + or al, (1 shl RTL8139_BIT_PMEn) + and al, not (1 shl RTL8139_BIT_LWACT) + out dx, al + add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1 + in al, dx + and al, not (1 shl RTL8139_BIT_LWPTN) + out dx, al + jmp .finish_wake_up +.old_chip: +; wake up older chips + and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN)) + out dx, al +.finish_wake_up: +; lock config and BMCR registers + xor al, al + mov edx, [io_addr] + add edx, RTL8139_REG_9346CR + out dx, al +;*************************************************************************** +; Function +; rt8139_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; Destroyed registers +; eax, ebx, ecx, edx +; +;*************************************************************************** +rtl8139_reset: + mov edx, [io_addr] + add edx, RTL8139_REG_COMMAND + mov al, 1 shl RTL8139_BIT_RST + out dx, al + mov cx, 1000 ; wait no longer for the reset +.wait_for_reset: + in al, dx + test al, 1 shl RTL8139_BIT_RST + jz .reset_completed ; RST remains 1 during reset + dec cx + jns .wait_for_reset +.reset_completed: +; get MAC (hardware address) + mov ecx, 2 +.mac_read_loop: + lea eax, [EE_93C46_REG_ETH_ID+ecx] + push ecx + call rtl8139_read_eeprom + pop ecx + mov [node_addr+ecx*2], ax + dec ecx + jns .mac_read_loop +; unlock config and BMCR registers + mov edx, [io_addr] + add edx, RTL8139_REG_9346CR + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) + out dx, al +; initialize multicast registers (no filtering) + mov eax, 0xffffffff + add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR + out dx, eax + add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0 + out dx, eax +; enable Rx/Tx + mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE) + add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4 + out dx, al +; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold +; accept broadcast packets, accept physical match packets + mov ax, RTL8139_RX_CONFIG + add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND + out dx, ax +; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 + mov ax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \ + or (RTL8139_TXRR shl RTL8139_BIT_TXRR) + add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG + out dx, ax +; enable auto negotiation + add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG + in ax, dx + or ax, (1 shl RTL8139_BIT_ANE) + out dx, ax +; set auto negotiation advertisement + add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR + in ax, dx + or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \ + or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \ + or (1 shl RTL8139_BIT_TXFD) + out dx, ax +; lock config and BMCR registers + xor eax, eax + add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR + out dx, al +; init RX/TX pointers + mov [rtl8139_rx_buff_offset], eax + mov [curr_tx_desc], eax +; clear missing packet counter + add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR + out dx, eax +; disable all interrupts + add edx, RTL8139_REG_IMR - RTL8139_REG_MPC + out dx, ax +; set RxBuffer address, init RX buffer offset, init TX ring + mov eax, rtl8139_rx_buff + add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR + out dx, eax +; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + ret + +;*************************************************************************** +; Function +; rtl8139_read_eeprom +; Description +; reads eeprom type 93c46 and 93c56 +; Parameters +; al - word to be read (6bit in case of 93c46 and 8bit otherwise) +; Return value +; ax - word read in +; Destroyed register(s) +; eax, cx, ebx, edx +; +;*************************************************************************** +rtl8139_read_eeprom: + movzx ebx, al + mov edx, [io_addr] + add edx, RTL8139_REG_RXCONFIG + in al, dx + test al, (1 shl RTL8139_BIT_9356SEL) + jz .type_93c46 +; and bl, 01111111b ; don't care first bit + or bx, EE_93C56_READ_CMD ; it contains start bit + mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter + jmp .read_eeprom +.type_93c46: + and bl, 00111111b + or bx, EE_93C46_READ_CMD ; it contains start bit + mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter +.read_eeprom: + add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0 +; mov al, (1 shl RTL8139_BIT_93C46_EEM1) +; out dx, al + mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ + or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom + out dx, al +.cmd_loop: + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) + bt bx, cx + jnc .zero_bit + or al, (1 shl RTL8139_BIT_93C46_EEDI) +.zero_bit: + out dx, al +; push eax +; in eax, dx ; eeprom delay +; pop eax + or al, (1 shl RTL8139_BIT_93C46_EESK) + out dx, al +; in eax, dx ; eeprom delay + dec cx + jns .cmd_loop +; in eax, dx ; eeprom delay + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) + out dx, al + mov cl, 0xf +.read_loop: + shl ebx, 1 + mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ + or (1 shl RTL8139_BIT_93C46_EECS) \ + or (1 shl RTL8139_BIT_93C46_EESK) + out dx, al +; in eax, dx ; eeprom delay + in al, dx + and al, (1 shl RTL8139_BIT_93C46_EEDO) + jz .dont_set + inc ebx +.dont_set: + mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ + or (1 shl RTL8139_BIT_93C46_EECS) + out dx, al +; in eax, dx ; eeprom delay + dec cl + jns .read_loop + xor al, al + out dx, al + mov ax, bx + ret + +;*************************************************************************** +; Function +; rtl8139_transmit +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; Destroyed registers +; eax, edx, esi, edi +; ToDo +; for waiting of timeout the rtl8139 internal timer +; should be used +; +;*************************************************************************** +rtl8139_transmit: + cmp ecx, MAX_ETH_FRAME_SIZE + jg .finish ; packet is too long + push ecx +; check descriptor + mov ecx, [curr_tx_desc] + mov edx, [io_addr] + lea edx, [edx+ecx*4+RTL8139_REG_TSD0] + push edx ebx + in ax, dx + and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + jz .send_packet + test ax, 0x1fff ; or no size given + jz .send_packet +; wait for timeout + mov ebx, RTL8139_TX_TIMEOUT + mov eax, 0x5 ; delay x/100 secs + int 0x40 + in ax, dx + and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + jz .send_packet +; chip hung, reset it + call rtl8139_reset +; reset the card +.send_packet: +; calculate tx_buffer address + pop ebx + push esi + mov eax, MAX_ETH_FRAME_SIZE + mul dword [curr_tx_desc] + mov esi, edi + lea edi, [rtl8139_tx_buff+eax] + mov eax, edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy the packet data + pop esi edx ecx + push ecx + shr ecx, 2 + rep movsd + pop ecx + push ecx + and ecx, 3 + rep movsb +; set address + add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0 + out dx, eax +; set size and early threshold + pop eax ; pick up the size + add eax, ETH_HLEN + cmp eax, ETH_ZLEN + jnc .no_pad + mov eax, ETH_ZLEN +.no_pad: + or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH) + add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0 + out dx, eax +; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... + inc dword [curr_tx_desc] + and dword [curr_tx_desc], 3 +.finish: + ret + +;*************************************************************************** +; Function +; rtl8139_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Destroyed register(s) +; eax, edx, ecx +; +;*************************************************************************** +rtl8139_poll: + mov word [eth_rx_data_len], 0 + mov edx, [io_addr] + add edx, RTL8139_REG_COMMAND + in al, dx + test al, (1 shl RTL8139_BIT_BUFE) + jnz .finish +; new packet received copy it from rx_buffer into Ether_buffer + mov eax, rtl8139_rx_buff + add eax, [rtl8139_rx_buff_offset] +; check if packet is ok + test byte [eax], (1 shl RTL8139_BIT_ROK) + jz .reset_rx +; packet is ok copy it into the Ether_buffer + movzx ecx, word [eax+2] ; packet length + sub ecx, 4 ; don't copy CRC + mov word [eth_rx_data_len], cx + push ecx + shr ecx, 2 ; first copy dword-wise + lea esi, [eax+4] ; don't copy the packet header + mov edi, Ether_buffer + cld + rep movsd ; copy the dwords + pop ecx + and ecx, 3 + rep movsb ; copy the rest bytes +; update rtl8139_rx_buff_offset + movzx eax, word [eax+2] ; packet length + add eax, [rtl8139_rx_buff_offset] + add eax, 4+3 ; packet header is 4 bytes long + dword alignment + and eax, not 3 ; dword alignment + cmp eax, RTL8139_RX_BUFFER_SIZE + jl .no_wrap + sub eax, RTL8139_RX_BUFFER_SIZE +.no_wrap: + mov [rtl8139_rx_buff_offset], eax +; update CAPR register + sub eax, 0x10 ; value 0x10 is a constant for CAPR + add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND + out dx, ax +.finish: +; clear active interrupt sources + mov edx, [io_addr] + add edx, RTL8139_REG_ISR + in ax, dx + out dx, ax + ret +.reset_rx: + in al, dx ; read command register + push eax + and al, not (1 shl RTL8139_BIT_RE) + out dx, al + pop eax + out dx, al + add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND + mov ax, RTL8139_RX_CONFIG + out dx, ax + ret diff --git a/trunk/network/eth_drv/sis900.inc b/trunk/network/eth_drv/sis900.inc new file mode 100644 index 000000000..af54313b9 --- /dev/null +++ b/trunk/network/eth_drv/sis900.inc @@ -0,0 +1,1148 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SIS900.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.4 26 April 2004 ;; +;; ;; +;; This driver is based on the SIS900 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2004 Jason Delozier, ;; +;; cordata51@hotmail.com ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; Updates: ;; +;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;******************************************************************** +; Interface +; SIS900_reset +; SIS900_probe +; SIS900_poll +; SIS900_transmit +; +;******************************************************************** +;******************************************************************** +; Comments: +; Known to work with the following SIS900 ethernet cards: +; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91 +; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90 +; +; If your card is not listed, try it and let me know if it +; functions properly and it will be aded to the list. If not +; we may be able to add support for it. +; +; How To Use: +; Add the following lines to Ethernet.inc in their appropriate locations +; +; include "Sis900.INC" +; dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, +; SIS900_transmit +; dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, +; SIS900_transmit ;untested +; +; ToDo: +; - Enable MII interface for reading speed +; and duplex settings. +; +; - Update Poll routine to support packet fragmentation. +; +; - Add additional support for other sis900 based cards +; +;******************************************************************** + +; comment the next line out if you don't want debug info printed +; on the debug board. This option adds a lot of bytes to the driver +; so it's worth to comment it out. +; SIS900_DEBUG equ 1 + + +;* buffers and descriptors +cur_rx db 0 +NUM_RX_DESC equ 4 ;* Number of RX descriptors * +NUM_TX_DESC equ 1 ;* Number of TX descriptors * +RX_BUFF_SZ equ 1520 ;* Buffer size for each Rx buffer * +TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer * + +uglobal +align 4 +txd: times (3 * NUM_TX_DESC) dd 0 +rxd: times (3 * NUM_RX_DESC) dd 0 +endg + +txb equ eth_data_start +rxb equ txb + (NUM_TX_DESC * TX_BUFF_SZ) +SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address * +SIS900_ETH_HLEN equ 14 ;* Size of ethernet header * +SIS900_ETH_ZLEN equ 60 ;* Minimum packet length * +SIS900_DSIZE equ 0x00000fff +SIS900_CRC_SIZE equ 4 +SIS900_RFADDR_shift equ 16 +;SIS900 Symbolic offsets to registers. + SIS900_cr equ 0x0 ; Command Register + SIS900_cfg equ 0x4 ; Configuration Register + SIS900_mear equ 0x8 ; EEPROM Access Register + SIS900_ptscr equ 0xc ; PCI Test Control Register + SIS900_isr equ 0x10 ; Interrupt Status Register + SIS900_imr equ 0x14 ; Interrupt Mask Register + SIS900_ier equ 0x18 ; Interrupt Enable Register + SIS900_epar equ 0x18 ; Enhanced PHY Access Register + SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register + SIS900_txcfg equ 0x24 ; Transmit Configuration Register + SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register + SIS900_rxcfg equ 0x34 ; Receive Configuration Register + SIS900_flctrl equ 0x38 ; Flow Control Register + SIS900_rxlen equ 0x3c ; Receive Packet Length Register + SIS900_rfcr equ 0x48 ; Receive Filter Control Register + SIS900_rfdr equ 0x4C ; Receive Filter Data Register + SIS900_pmctrl equ 0xB0 ; Power Management Control Register + SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register +;SIS900 Command Register Bits + SIS900_RELOAD equ 0x00000400 + SIS900_ACCESSMODE equ 0x00000200 + SIS900_RESET equ 0x00000100 + SIS900_SWI equ 0x00000080 + SIS900_RxRESET equ 0x00000020 + SIS900_TxRESET equ 0x00000010 + SIS900_RxDIS equ 0x00000008 + SIS900_RxENA equ 0x00000004 + SIS900_TxDIS equ 0x00000002 + SIS900_TxENA equ 0x00000001 +;SIS900 Configuration Register Bits + SIS900_DESCRFMT equ 0x00000100 ; 7016 specific + SIS900_REQALG equ 0x00000080 + SIS900_SB equ 0x00000040 + SIS900_POW equ 0x00000020 + SIS900_EXD equ 0x00000010 + SIS900_PESEL equ 0x00000008 + SIS900_LPM equ 0x00000004 + SIS900_BEM equ 0x00000001 + SIS900_RND_CNT equ 0x00000400 + SIS900_FAIR_BACKOFF equ 0x00000200 + SIS900_EDB_MASTER_EN equ 0x00002000 +;SIS900 Eeprom Access Reigster Bits + SIS900_MDC equ 0x00000040 + SIS900_MDDIR equ 0x00000020 + SIS900_MDIO equ 0x00000010 ; 7016 specific + SIS900_EECS equ 0x00000008 + SIS900_EECLK equ 0x00000004 + SIS900_EEDO equ 0x00000002 + SIS900_EEDI equ 0x00000001 +;SIS900 TX Configuration Register Bits + SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding + SIS900_MLB equ 0x20000000 ;Mac Loopback Enable + SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup) + SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du +;SIS900 RX Configuration Register Bits + SIS900_AJAB equ 0x08000000 ; + SIS900_ATX equ 0x10000000 ;Accept Transmit Packets + SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes) + SIS900_AEP equ 0x80000000 ;accept error packets +;SIS900 Interrupt Reigster Bits + SIS900_WKEVT equ 0x10000000 + SIS900_TxPAUSEEND equ 0x08000000 + SIS900_TxPAUSE equ 0x04000000 + SIS900_TxRCMP equ 0x02000000 + SIS900_RxRCMP equ 0x01000000 + SIS900_DPERR equ 0x00800000 + SIS900_SSERR equ 0x00400000 + SIS900_RMABT equ 0x00200000 + SIS900_RTABT equ 0x00100000 + SIS900_RxSOVR equ 0x00010000 + SIS900_HIBERR equ 0x00008000 + SIS900_SWINT equ 0x00001000 + SIS900_MIBINT equ 0x00000800 + SIS900_TxURN equ 0x00000400 + SIS900_TxIDLE equ 0x00000200 + SIS900_TxERR equ 0x00000100 + SIS900_TxDESC equ 0x00000080 + SIS900_TxOK equ 0x00000040 + SIS900_RxORN equ 0x00000020 + SIS900_RxIDLE equ 0x00000010 + SIS900_RxEARLY equ 0x00000008 + SIS900_RxERR equ 0x00000004 + SIS900_RxDESC equ 0x00000002 + SIS900_RxOK equ 0x00000001 +;SIS900 Interrupt Enable Reigster Bits + SIS900_IE equ 0x00000001 +;SIS900 Revision ID + SIS900B_900_REV equ 0x03 + SIS630A_900_REV equ 0x80 + SIS630E_900_REV equ 0x81 + SIS630S_900_REV equ 0x82 + SIS630EA1_900_REV equ 0x83 + SIS630ET_900_REV equ 0x84 + SIS635A_900_REV equ 0x90 + SIS900_960_REV equ 0x91 +;SIS900 Receive Filter Control Register Bits + SIS900_RFEN equ 0x80000000 + SIS900_RFAAB equ 0x40000000 + SIS900_RFAAM equ 0x20000000 + SIS900_RFAAP equ 0x10000000 + SIS900_RFPromiscuous equ 0x70000000 +;SIS900 Reveive Filter Data Mask + SIS900_RFDAT equ 0x0000FFFF +;SIS900 Eeprom Address + SIS900_EEPROMSignature equ 0x00 + SIS900_EEPROMVendorID equ 0x02 + SIS900_EEPROMDeviceID equ 0x03 + SIS900_EEPROMMACAddr equ 0x08 + SIS900_EEPROMChecksum equ 0x0b +;The EEPROM commands include the alway-set leading bit. +;SIS900 Eeprom Command + SIS900_EEread equ 0x0180 + SIS900_EEwrite equ 0x0140 + SIS900_EEerase equ 0x01C0 + SIS900_EEwriteEnable equ 0x0130 + SIS900_EEwriteDisable equ 0x0100 + SIS900_EEeraseAll equ 0x0120 + SIS900_EEwriteAll equ 0x0110 + SIS900_EEaddrMask equ 0x013F + SIS900_EEcmdShift equ 16 +;For SiS962 or SiS963, request the eeprom software access + SIS900_EEREQ equ 0x00000400 + SIS900_EEDONE equ 0x00000200 + SIS900_EEGNT equ 0x00000100 +;General Varibles + SIS900_pci_revision: db 0 + SIS900_Status dd 0x03000000 +sis900_specific_table: +; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0 +; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0 + dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0 + dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0 + dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN + dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0 + dd SIS900_960_REV,SIS960_get_mac_addr,0 + dd SIS900B_900_REV,SIS900_get_mac_addr,0 + dd 0,0,0,0 ; end of list +sis900_get_mac_func: dd 0 +sis900_special_func: dd 0 +sis900_table_entries: db 8 + +;*************************************************************************** +; Function +; SIS900_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +;not done - still need to probe mii transcievers +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0 +end if +SIS900_probe: +;******Wake Up Chip******* + mov al, 4 + mov bh, [pci_dev] + mov ecx, 0 + mov ah, [pci_bus] + mov bl, 0x40 + call pci_write_reg +;*******Set some PCI Settings********* + call SIS900_adjust_pci_device +;*****Get Card Revision****** + mov al, 1 ;one byte to read + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x08 ;Revision Register + call pci_read_reg + mov [SIS900_pci_revision], al ;save the revision for later use +;****** Look up through the sis900_specific_table + mov esi,sis900_specific_table +.probe_loop: + cmp dword [esi],0 ; Check if we reached end of the list + je .probe_loop_failed + cmp al,[esi] ; Check if revision is OK + je .probe_loop_ok + add esi,12 ; Advance to next entry + jmp .probe_loop +.probe_loop_failed: + jmp SIS900_Probe_Unsupported +;*********Find Get Mac Function********* +.probe_loop_ok: + mov eax,[esi+4] ; Get pointer to "get MAC" function + mov [sis900_get_mac_func],eax + mov eax,[esi+8] ; Get pointer to special initialization fn + mov [sis900_special_func],eax +;******** Get MAC ******** + call dword [sis900_get_mac_func] +;******** Call special initialization fn if requested ******** + cmp dword [sis900_special_func],0 + je .no_special_init + call dword [sis900_special_func] +.no_special_init: +;******** Set table entries ******** + mov al,[SIS900_pci_revision] + cmp al,SIS635A_900_REV + jae .ent16 + cmp al,SIS900B_900_REV + je .ent16 + jmp .ent8 +.ent16: + mov byte [sis900_table_entries],16 +.ent8: +;*******Probe for mii transceiver******* +;TODO!!********************* +;*******Initialize Device******* + call sis900_init + ret + +SIS900_Probe_Unsupported: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_Unsupported + call sys_msg_board_str +end if + ret +;*************************************************************************** +; Function: sis900_init +; +; Description: resets the ethernet controller chip and various +; data structures required for sending and receiving packets. +; +; Arguments: +; +; returns: none +;not done +;*************************************************************************** +sis900_init: + call SIS900_reset ;Done + call SIS900_init_rxfilter ;Done + call SIS900_init_txd ;Done + call SIS900_init_rxd ;Done + call SIS900_set_rx_mode ;done + call SIS900_set_tx_mode + ;call SIS900_check_mode + ret + +;*************************************************************************** +; Function +; SIS900_reset +; Description +; disables interrupts and soft resets the controller chip +; +;done+ +;*************************************************************************** +if defined SIS900_DEBUG + SIS900_Debug_Reset_Failed db 'Reset Failed ',0 +end if +SIS900_reset: + ;******Disable Interrupts and reset Receive Filter******* + mov ebp, [io_addr] ; base address + xor eax, eax ; 0 to initialize + lea edx,[ebp+SIS900_ier] + out dx, eax ; Write 0 to location + lea edx,[ebp+SIS900_imr] + out dx, eax ; Write 0 to location + lea edx,[ebp+SIS900_rfcr] + out dx, eax ; Write 0 to location + ;*******Reset Card*********************************************** + lea edx,[ebp+SIS900_cr] + in eax, dx ; Get current Command Register + or eax, SIS900_RESET ; set flags + or eax, SIS900_RxRESET ; + or eax, SIS900_TxRESET ; + out dx, eax ; Write new Command Register + ;*******Wait Loop************************************************ + lea edx,[ebp+SIS900_isr] + mov ecx, [SIS900_Status] ; Status we would like to see from card + mov ebx, 2001 ; only loop 1000 times +SIS900_Wait: + dec ebx ; 1 less loop + jz SIS900_DoneWait_e ; 1000 times yet? + in eax, dx ; move interrup status to eax + and eax, ecx + xor ecx, eax + jz SIS900_DoneWait + jmp SIS900_Wait +SIS900_DoneWait_e: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Reset_Failed + call sys_msg_board_str +end if +SIS900_DoneWait: + ;*******Set Configuration Register depending on Card Revision******** + lea edx,[ebp+SIS900_cfg] + mov eax, SIS900_PESEL ; Configuration Register Bit + mov bl, [SIS900_pci_revision] ; card revision + mov cl, SIS635A_900_REV ; Check card revision + cmp bl, cl + je SIS900_RevMatch + mov cl, SIS900B_900_REV ; Check card revision + cmp bl, cl + je SIS900_RevMatch + out dx, eax ; no revision match + jmp SIS900_Reset_Complete +SIS900_RevMatch: ; Revision match + or eax, SIS900_RND_CNT ; Configuration Register Bit + out dx, eax +SIS900_Reset_Complete: + mov eax, [pci_data] + mov [eth_status], eax + ret + +;*************************************************************************** +; Function: sis_init_rxfilter +; +; Description: sets receive filter address to our MAC address +; +; Arguments: +; +; returns: +;done+ +;*************************************************************************** +SIS900_init_rxfilter: + ;****Get Receive Filter Control Register ******** + mov ebp, [io_addr] ; base address + lea edx,[ebp+SIS900_rfcr] + in eax, dx ; get register + push eax + ;****disable packet filtering before setting filter******* + mov eax, SIS900_RFEN ;move receive filter enable flag + not eax ;1s complement + pop ebx ;and with our saved register + and eax, ebx ;disable receiver + push ebx ;save filter for another use + out dx, eax ;set receive disabled + ;********load MAC addr to filter data register********* + xor ecx, ecx +SIS900_RXINT_Mac_Write: + ;high word of eax tells card which mac byte to write + mov eax, ecx + lea edx,[ebp+SIS900_rfcr] + shl eax, 16 ; + out dx, eax ; + lea edx,[ebp+SIS900_rfdr] + mov ax, word [node_addr+ecx*2] ; Get Mac ID word + out dx, ax ; Send Mac ID + inc cl ; send next word + cmp cl, 3 ; more to send? + jne SIS900_RXINT_Mac_Write + ;********enable packet filitering ***** + pop eax ;old register value + lea edx,[ebp+SIS900_rfcr] + or eax, SIS900_RFEN ;enable filtering + out dx, eax ;set register + ret + +;*************************************************************************** +;* +;* Function: sis_init_txd +;* +;* Description: initializes the Tx descriptor +;* +;* Arguments: +;* +;* returns: +;*done +;*************************************************************************** +SIS900_init_txd: + ;********** initialize TX descriptor ************** + mov [txd], dword 0 ;put link to next descriptor in link field + mov [txd+4],dword 0 ;clear status field + mov [txd+8], dword txb ;save address to buffer ptr field + ;*************** load Transmit Descriptor Register *************** + mov dx, [io_addr] ; base address + add dx, SIS900_txdp ; TX Descriptor Pointer + mov eax, txd ; First Descriptor + out dx, eax ; move the pointer + ret + +;*************************************************************************** +;* Function: sis_init_rxd +;* +;* Description: initializes the Rx descriptor ring +;* +;* Arguments: +;* +;* Returns: +;*done +;*************************************************************************** +SIS900_init_rxd: + xor ecx,ecx + mov [cur_rx], cl ;Set cuurent rx discriptor to 0 + ;******** init RX descriptors ******** +SIS900_init_rxd_Loop: + mov eax, ecx ;current descriptor + imul eax, 12 ; + mov ebx, ecx ;determine next link descriptor + inc ebx ; + cmp ebx, NUM_RX_DESC ; + jne SIS900_init_rxd_Loop_0 ; + xor ebx, ebx ; +SIS900_init_rxd_Loop_0: ; + imul ebx, 12 ; + add ebx, rxd ; + mov [rxd+eax], ebx ;save link to next descriptor + mov [rxd+eax+4],dword RX_BUFF_SZ ;status bits init to buf size + mov ebx, ecx ;find where the buf is located + imul ebx,RX_BUFF_SZ ; + add ebx, rxb ; + mov [rxd+eax+8], ebx ;save buffer pointer + inc ecx ;next descriptor + cmp ecx, NUM_RX_DESC ; + jne SIS900_init_rxd_Loop ; + ;********* load Receive Descriptor Register with address of first + ; descriptor********* + mov dx, [io_addr] + add dx, SIS900_rxdp + mov eax, rxd + out dx, eax + ret + +;*************************************************************************** +;* Function: sis900_set_tx_mode +;* +;* Description: +;* sets the transmit mode to allow for full duplex +;* +;* +;* Arguments: +;* +;* Returns: +;* +;* Comments: +;* If you are having problems transmitting packet try changing the +;* Max DMA Burst, Possible settings are as follows: +;* 0x00000000 = 512 bytes +;* 0x00100000 = 4 bytes +;* 0x00200000 = 8 bytes +;* 0x00300000 = 16 bytes +;* 0x00400000 = 32 bytes +;* 0x00500000 = 64 bytes +;* 0x00600000 = 128 bytes +;* 0x00700000 = 256 bytes +;*************************************************************************** +SIS900_set_tx_mode: + mov ebp,[io_addr] + lea edx,[ebp+SIS900_cr] + in eax, dx ; Get current Command Register + or eax, SIS900_TxENA ;Enable Receive + out dx, eax + lea edx,[ebp+SIS900_txcfg]; Transmit config Register offset + mov eax, SIS900_ATP ;allow automatic padding + or eax, SIS900_HBI ;allow heartbeat ignore + or eax, SIS900_CSI ;allow carrier sense ignore + or eax, 0x00600000 ;Max DMA Burst + or eax, 0x00000100 ;TX Fill Threshold + or eax, 0x00000020 ;TX Drain Threshold + out dx, eax + ret + +;*************************************************************************** +;* Function: sis900_set_rx_mode +;* +;* Description: +;* sets the receive mode to accept all broadcast packets and packets +;* with our MAC address, and reject all multicast packets. Also allows +;* full-duplex +;* +;* Arguments: +;* +;* Returns: +;* +;* Comments: +;* If you are having problems receiving packet try changing the +;* Max DMA Burst, Possible settings are as follows: +;* 0x00000000 = 512 bytes +;* 0x00100000 = 4 bytes +;* 0x00200000 = 8 bytes +;* 0x00300000 = 16 bytes +;* 0x00400000 = 32 bytes +;* 0x00500000 = 64 bytes +;* 0x00600000 = 128 bytes +;* 0x00700000 = 256 bytes +;*************************************************************************** +SIS900_mc_filter: times 16 dw 0 +SIS900_set_rx_mode: + mov ebp,[io_addr] + ;**************update Multicast Hash Table in Receive Filter + mov ebx, 0xffff + xor cl, cl +SIS900_set_rx_mode_Loop: + mov eax, ecx + shl eax, 1 + mov [SIS900_mc_filter+eax], ebx + lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Reg offset + mov eax, 4 ;determine table entry + add al, cl + shl eax, 16 + out dx, eax ;tell card which entry to modify + lea edx,[ebp+SIS900_rfdr] ; Receive Filter Control Reg offset + mov eax, ebx ;entry value + out dx, ax ;write value to table in card + inc cl ;next entry + cmp cl,[sis900_table_entries] ; + jl SIS900_set_rx_mode_Loop + ;*******Set Receive Filter Control Register************* + lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Register offset + mov eax, SIS900_RFAAB ;accecpt all broadcast packets + or eax, SIS900_RFAAM ;accept all multicast packets + or eax, SIS900_RFAAP ;Accept all packets + or eax, SIS900_RFEN ;enable receiver filter + out dx, eax + ;******Enable Receiver************ + lea edx,[ebp+SIS900_cr] ; Command Register offset + in eax, dx ; Get current Command Register + or eax, SIS900_RxENA ;Enable Receive + out dx, eax + ;*********Set + lea edx,[ebp+SIS900_rxcfg] ; Receive Config Register offset + mov eax, SIS900_ATX ;Accept Transmit Packets + ; (Req for full-duplex and PMD Loopback) + or eax, 0x00600000 ;Max DMA Burst + or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes + out dx, eax ; + ret + +;*************************************************************************** +; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model +; * @pci_dev: the sis900 pci device +; * @net_dev: the net device to get address for +; * +; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM +; * is shared by +; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first +; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access +; * by LAN, otherwise is not. After MAC address is read from EEPROM, send +; * EEDONE signal to refuse EEPROM access by LAN. +; * The EEPROM map of SiS962 or SiS963 is different to SiS900. +; * The signature field in SiS962 or SiS963 spec is meaningless. +; * MAC address is read into @net_dev->dev_addr. +; *done +;* +;* Return 0 is EAX = failure +;*Done+ +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0 +SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0 +SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0 +SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0 +end if +SIS960_get_mac_addr: + mov ebp,[io_addr] + ;**********Send Request for eeprom access********************* + lea edx,[ebp+SIS900_mear] ; Eeprom access register + mov eax, SIS900_EEREQ ; Request access to eeprom + out dx, eax ; Send request + xor ebx,ebx ; + ;******Loop 4000 times and if access not granted error out***** +SIS96X_Get_Mac_Wait: + in eax, dx ;get eeprom status + and eax, SIS900_EEGNT ;see if eeprom access granted flag is set + jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom + inc ebx ;else keep waiting + cmp ebx, 4000 ;have we tried 4000 times yet? + jl SIS96X_Get_Mac_Wait ;if not ask again + xor eax, eax ;return zero in eax indicating failure + ;*******Debug ********************** +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Failed + call sys_msg_board_str +end if + jmp SIS960_get_mac_addr_done + ;**********EEprom access granted, read MAC from card************* +SIS900_Got_EEP_Access: + ; zero based so 3-16 bit reads will take place + mov ecx, 2 +SIS96x_mac_read_loop: + mov eax, SIS900_EEPROMMACAddr ;Base Mac Address + add eax, ecx ;Current Mac Byte Offset + push ecx + call sis900_read_eeprom ;try to read 16 bits + pop ecx + mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID varible + dec ecx ;one less word to read + jns SIS96x_mac_read_loop ;if more read more + mov eax, 1 ;return non-zero indicating success + ;*******Debug Print MAC ID to debug window********************** +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Address2 + call sys_msg_board_str + mov edx, node_addr + call Create_Mac_String +end if + ;**********Tell EEPROM We are Done Accessing It********************* +SIS960_get_mac_addr_done: + lea edx,[ebp+SIS900_mear] ; Eeprom access register + mov eax, SIS900_EEDONE ;tell eeprom we are done + out dx,eax + ret +;*************************************************************************** +;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model +;* @pci_dev: the sis900 pci device +;* @net_dev: the net device to get address for +;* +;* Older SiS900 and friends, use EEPROM to store MAC address. +;* MAC address is read from read_eeprom() into @net_dev->dev_addr. +;* done/untested +;*************************************************************************** +SIS900_get_mac_addr: + ;*******Debug ********************** +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Start + call sys_msg_board_str +end if + ;******** check to see if we have sane EEPROM ******* + mov eax, SIS900_EEPROMSignature ;Base Eeprom Signature + call sis900_read_eeprom ;try to read 16 bits + cmp ax, 0xffff + je SIS900_Bad_Eeprom + cmp ax, 0 + je SIS900_Bad_Eeprom + ;**************Read MacID************** + ; zero based so 3-16 bit reads will take place + mov ecx, 2 +SIS900_mac_read_loop: + mov eax, SIS900_EEPROMMACAddr ;Base Mac Address + add eax, ecx ;Current Mac Byte Offset + push ecx + call sis900_read_eeprom ;try to read 16 bits + pop ecx + mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID storage + dec ecx ;one less word to read + jns SIS900_mac_read_loop ;if more read more + mov eax, 1 ;return non-zero indicating success + ;*******Debug Print MAC ID to debug window********************** +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Address + call sys_msg_board_str + mov edx, node_addr + call Create_Mac_String +end if + ret + +SIS900_Bad_Eeprom: + xor eax, eax + ;*******Debug ********************** +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Failed + call sys_msg_board_str +end if + ret +;*************************************************************************** +;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635 +;* +;* +;*************************************************************************** +Get_Mac_SIS635_900_REV: +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Start + call sys_msg_board_str +end if + mov ebp,[io_addr] + lea edx,[ebp+SIS900_rfcr] + in eax,dx + mov edi,eax ; EDI=rfcrSave + lea edx,[ebp+SIS900_cr] + or eax,SIS900_RELOAD + out dx,eax + xor eax,eax + out dx,eax + ; Disable packet filtering before setting filter + lea edx,[ebp+SIS900_rfcr] + mov eax,edi + and edi,not SIS900_RFEN + out dx,eax + ; Load MAC to filter data register + xor ecx,ecx + mov esi,node_addr +.get_mac_loop: + lea edx,[ebp+SIS900_rfcr] + mov eax,ecx + shl eax,SIS900_RFADDR_shift + out dx,eax + lea edx,[ebp+SIS900_rfdr] + in eax,dx + mov [esi],ax + add esi,2 + inc ecx + cmp ecx,3 + jne .get_mac_loop + ; Enable packet filtering + ;lea edx,[ebp+SIS900_rfcr] + ;mov eax,edi + ;or eax,SIS900_RFEN + ;out dx, eax + ;*******Debug Print MAC ID to debug window********************** +if defined SIS900_DEBUG + mov esi,SIS900_Debug_Str_GetMac_Address + call sys_msg_board_str + mov edx, node_addr + call Create_Mac_String +end if + ret +;*************************************************************************** +;* Function: sis900_read_eeprom +;* +;* Description: reads and returns a given location from EEPROM +;* +;* Arguments: eax - location: requested EEPROM location +;* +;* Returns: eax : contents of requested EEPROM location +;* +; Read Serial EEPROM through EEPROM Access Register, Note that location is +; in word (16 bits) unit */ +;done+ +;*************************************************************************** +sis900_read_eeprom: + push esi + push edx + push ecx + push ebx + mov ebp,[io_addr] + mov ebx, eax ;location of Mac byte to read + or ebx, SIS900_EEread ; + lea edx,[ebp+SIS900_mear] ; Eeprom access register + xor eax, eax ; start send + out dx,eax + call SIS900_Eeprom_Delay_1 + mov eax, SIS900_EECLK + out dx, eax + call SIS900_Eeprom_Delay_1 + ;************ Shift the read command (9) bits out. ********* + mov cl, 8 ; +sis900_read_eeprom_Send: + mov eax, 1 + shl eax, cl + and eax, ebx + jz SIS900_Read_Eeprom_8 + mov eax, 9 + jmp SIS900_Read_Eeprom_9 +SIS900_Read_Eeprom_8: + mov eax, 8 +SIS900_Read_Eeprom_9: + out dx, eax + call SIS900_Eeprom_Delay_1 + or eax, SIS900_EECLK + out dx, eax + call SIS900_Eeprom_Delay_1 + cmp cl, 0 + je sis900_read_eeprom_Send_Done + dec cl + jmp sis900_read_eeprom_Send + ;********************* +sis900_read_eeprom_Send_Done: + mov eax, SIS900_EECS ; + out dx, eax + call SIS900_Eeprom_Delay_1 + ;********** Read 16-bits of data in *************** + mov cx, 16 ;16 bits to read +sis900_read_eeprom_Send2: + mov eax, SIS900_EECS + out dx, eax + call SIS900_Eeprom_Delay_1 + or eax, SIS900_EECLK + out dx, eax + call SIS900_Eeprom_Delay_1 + in eax, dx + shl ebx, 1 + and eax, SIS900_EEDO + jz SIS900_Read_Eeprom_0 + or ebx, 1 +SIS900_Read_Eeprom_0: + dec cx + jnz sis900_read_eeprom_Send2 + ;************** Terminate the EEPROM access. ************** + xor eax, eax + out dx, eax + call SIS900_Eeprom_Delay_1 + mov eax, SIS900_EECLK + out dx, eax + mov eax, ebx + and eax, 0x0000ffff ;return only 16 bits + pop ebx + pop ecx + pop edx + pop esi + ret +;*************************************************************************** +; Function +; SIS900_Eeprom_Delay_1 +; Description +; +; +; +; +;*************************************************************************** +SIS900_Eeprom_Delay_1: + push eax + in eax, dx + pop eax + ret + +;*************************************************************************** +; Function +; SIS900_poll +; Description +; polls card to see if there is a packet waiting +; +; Currently only supports one descriptor per packet, if packet is fragmented +; between multiple descriptors you will lose part of the packet +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0 +SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0 +SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0 +end if +SIS900_poll: + ;**************Get Status ************** + xor eax, eax ;get RX_Status + mov [eth_rx_data_len], ax + mov al, [cur_rx] ;find current discriptor + imul eax, 12 ; + mov ecx, [rxd+eax+4] ; get receive status + ;**************Check Status ************** + mov ebx, ecx ;move status + ;Check RX_Status to see if packet is waiting + and ebx, 0x80000000 + jnz SIS900_poll_IS_packet + ret + ;**********There is a packet waiting check it for errors************** +SIS900_poll_IS_packet: + mov ebx, ecx ;move status + and ebx, 0x67C0000 ;see if there are any errors + jnz SIS900_Poll_Error_Status + ;**************Check size of packet************* + and ecx, SIS900_DSIZE ;get packet size minus CRC + cmp cx, SIS900_CRC_SIZE + ;make sure packet contains data + jle SIS900_Poll_Error_Size + ;*******Copy Good Packet to receive buffer****** + sub cx, SIS900_CRC_SIZE ;dont want crc + mov word [eth_rx_data_len], cx ;save size of packet + ;**********Continue copying packet**************** + push ecx + ; first copy dword-wise, divide size by 4 + shr ecx, 2 + mov esi, [rxd+eax+8] ; set source + mov edi, Ether_buffer ; set destination + cld ; clear direction + rep movsd ; copy the dwords + pop ecx + and ecx, 3 ; + rep movsb + ;********Debug, tell user we have a good packet************* +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Pull_Packet_good + call sys_msg_board_str +end if + jmp SIS900_Poll_Cnt ; + ;*************Error occured let user know through debug window*********** +SIS900_Poll_Error_Status: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Pull_Bad_Packet_Status + call sys_msg_board_str +end if + jmp SIS900_Poll_Cnt +SIS900_Poll_Error_Size: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Pull_Bad_Packet_Size + call sys_msg_board_str +end if + ;*************Increment to next available descriptor************** +SIS900_Poll_Cnt: + ;Reset status, allow ethernet card access to descriptor + mov ecx, RX_BUFF_SZ + mov [rxd+eax+4], ecx ; + inc [cur_rx] ;get next descriptor + and [cur_rx],3 ;only 4 descriptors 0-3 + ;******Enable Receiver************ + mov ebp, [io_addr] ; Base Address + lea edx,[ebp+SIS900_cr] ; Command Register offset + in eax, dx ; Get current Command Register + or eax, SIS900_RxENA ;Enable Receive + out dx, eax + ret +;*************************************************************************** +; Function +; SIS900_transmit +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +; only one transmit descriptor is used +; +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0 +SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0 +end if +SIS900_transmit: + mov ebp, [io_addr] ; Base Address + ;******** Stop the transmitter ******** + lea edx,[ebp+SIS900_cr] ; Command Register offset + in eax, dx ; Get current Command Register + or eax, SIS900_TxDIS ; Disable Transmitter + out dx, eax + ;*******load Transmit Descriptor Register ******* + lea edx,[ebp+SIS900_txdp] + mov eax, txd + out dx, eax + ;******* copy packet to descriptor******* + push esi + mov esi, edi ;copy destination addess + mov edi, txb + cld + movsd + movsw + mov esi, node_addr ;copy my mac address + movsd + movsw + mov [edi], bx ;copy packet type + add edi, 2 + pop esi ;restore pointer to source of packet + push ecx ;save packet size + shr ecx, 2 ;divide by 4, size in bytes send in dwords + rep movsd ;copy data to decriptor + pop ecx ;restore packet size + push ecx ;save packet size + and ecx, 3 ;last three bytes if not a multiple of 4 + rep movsb + ;**************set length tag************** + pop ecx ;restore packet size + add ecx, SIS900_ETH_HLEN ;add header to length + and ecx, SIS900_DSIZE ; + ;**************pad to minimum packet size **************not needed + ;cmp ecx, SIS900_ETH_ZLEN + ;jge SIS900_transmit_Size_Ok + ;push ecx + ;mov ebx, SIS900_ETH_ZLEN + ;sub ebx, ecx + ;mov ecx, ebx + ;rep movsb + ;pop ecx +SIS900_transmit_Size_Ok: + mov [txd+4], dword 0x80000000 ;card owns descriptor + or [txd+4], ecx ;set size of packet +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Transmit_Packet + call sys_msg_board_str +end if + ;***************restart the transmitter ******** + lea edx,[ebp+SIS900_cr] + in eax, dx ; Get current Command Register + or eax, SIS900_TxENA ; Enable Transmitter + out dx, eax + ;****make sure packet transmitted successfully**** +; mov esi,10 +; call delay_ms + mov eax, [txd+4] + and eax, 0x6200000 + jz SIS900_transmit_OK + ;**************Tell user there was an error through debug window +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Transmit_Packet_Err + call sys_msg_board_str +end if +SIS900_transmit_OK: + ;******** Disable interrupts by clearing the interrupt mask. ******** + lea edx,[ebp+SIS900_imr] ; Interupt Mask Register + xor eax, eax + out dx,eax + ret + +;*************************************************************************** +;* Function: Create_Mac_String +;* +;* Description: Converts the 48 bit value to a string for display +;* +;* String Format: XX:XX:XX:XX:XX:XX +;* +;* Arguments: node_addr is location of 48 bit MAC ID +;* +;* Returns: Prints string to general debug window +;* +;* +;done +;*************************************************************************** +if defined SIS900_DEBUG + +SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9' + db 'A','B','C','D','E','F' +Mac_str_build: times 20 db 0 +Create_Mac_String: + pusha + xor ecx, ecx +Create_Mac_String_loop: + mov al,byte [edx+ecx];[node_addr+ecx] + push eax + shr eax, 4 + and eax, 0x0f + mov bl, byte [SIS900_Char_String+eax] + mov [Mac_str_build+ecx*3], bl + pop eax + and eax, 0x0f + mov bl, byte [SIS900_Char_String+eax] + mov [Mac_str_build+1+ecx*3], bl + cmp ecx, 5 + je Create_Mac_String_done + mov bl, ':' + mov [Mac_str_build+2+ecx*3], bl + inc ecx + jmp Create_Mac_String_loop +Create_Mac_String_done: ;Insert CR and Zero Terminate + mov [Mac_str_build+2+ecx*3],byte 13 + mov [Mac_str_build+3+ecx*3],byte 10 + mov [Mac_str_build+4+ecx*3],byte 0 + mov esi, Mac_str_build + call sys_msg_board_str ;Print String to message board + popa + ret +end if +;*************************************************************************** +;* Set device to be a busmaster in case BIOS neglected to do so. +;* Also adjust PCI latency timer to a reasonable value, 64. +;*************************************************************************** +SIS900_adjust_pci_device: + ;*******Get current setting************************ + mov al, 2 ;read a word + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x04 ;from command Register + call pci_read_reg + ;******see if its already set as bus master******** + mov bx, ax + and bx,5 + cmp bx,5 + je SIS900_adjust_pci_device_Latency + ;******Make card a bus master******* + mov cx, ax ;value to write + mov bh, [pci_dev] + mov al, 2 ;write a word + or cx,5 + mov ah, [pci_bus] + mov bl, 0x04 ;to command register + call pci_write_reg + ;******Check latency setting*********** +SIS900_adjust_pci_device_Latency: + ;*******Get current latency setting************************ + mov al, 1 ;read a byte + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x0D ;from Lantency Timer Register + call pci_read_reg + ;******see if its aat least 64 clocks******** + cmp ax,64 + jge SIS900_adjust_pci_device_Done + ;******Set latency to 32 clocks******* + mov cx, 64 ;value to write + mov bh, [pci_dev] + mov al, 1 ;write a byte + mov ah, [pci_bus] + mov bl, 0x0D ;to Lantency Timer Register + call pci_write_reg + ;******Check latency setting*********** +SIS900_adjust_pci_device_Done: + ret diff --git a/trunk/network/ip.inc b/trunk/network/ip.inc new file mode 100644 index 000000000..36d46cff7 --- /dev/null +++ b/trunk/network/ip.inc @@ -0,0 +1,202 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; IP.INC ;; +;; ;; +;; IP Processes for Menuet OS TCP/IP stack ;; +;; ;; +;; Version 0.3 29 August 2002 ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;******************************************************************* +; Interface +; +; ip_rx processes all packets received by the network layer +; It calls the appropriate protocol handler +; +; +; +;******************************************************************* + + +;*************************************************************************** +; Function +; ip_rx +; +; Description +; Handles received IP packets +; This is a kernel function, called by stack_handler +; +;*************************************************************************** +ip_rx: + ; Look for a buffer to tx + mov eax, IPIN_QUEUE + call dequeue + cmp ax, NO_BUFFER + je ipr_exit ; Exit if no buffer available + + push eax + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax ; Save the address in edx for use by future processes + + ; Validate the IP checksum + mov ebx, edx + mov ah, [ebx + 10] + mov al, [ebx + 11] ; Get the checksum in intel format + mov [ebx + 10], word 0 ; clear checksum field - need to when + ; recalculating checksum + + ; this needs two data pointers and two size #. + ; 2nd pointer can be of length 0 + mov ebx, edx + mov [checkAdd1], ebx + mov [checkSize1], word 20 + mov [checkAdd2], dword 0 + mov [checkSize2], word 0 + + call checksum ; Recalculate IP checksum + cmp ax, [checkResult] + jnz ipr_dump + + ; If the IP address is 255.255.255.255, accept it + ; - it is a broadcast packet, which we need for dhcp + mov eax, [edx + 16] + cmp eax, 0xffffffff + je ipr_p0 + + ; Validate the IP address, if it isn't broadcast + cmp eax, [stack_ip] + jnz ipr_dump + +ipr_p0: + mov al, [edx] + and al, 0x0f + cmp al, 0x05 + jnz ipr_dump + + cmp [edx+8], byte 0 + jz ipr_dump + + mov ax, [edx + 6] + and ax, 0xFFBF + cmp ax, 0 + jnz ipr_dump + + ; Check the protocol, and call the appropriate handler + ; Each handler will re-use or free the queue buffer as appropriate + mov al, [edx + 9] + cmp al , PROTOCOL_ICMP + jnz ipr_p1 + pop eax + call icmp_rx + jmp ipr_exit + +ipr_p1: + cmp al , PROTOCOL_TCP + jnz ipr_p2 + pop eax + call tcp_rx + jmp ipr_exit + +ipr_p2: + cmp al , PROTOCOL_UDP + jnz ipr_dump + pop eax + call udp_rx + jmp ipr_exit + +ipr_dump: + ; No protocol handler available, so + ; silently dump the packet, freeing up the queue buffer + +; inc dword [dumped_rx_count] + + pop eax + call freeBuff + +ipr_exit: + ret + + + +;*************************************************************************** +; Function +; icmp_rx +; +; Description +; ICMP protocol handler +; This is a kernel function, called by ip_rx +; edx contains the address of the buffer in use. +; This buffer must be reused or marked as empty afterwards +; +;*************************************************************************** +icmp_rx: + cmp [edx + 20], byte 8 ; Is this an echo request? discard if not + jz icmp_echo + + call freeBuff + jmp icmp_exit + +icmp_echo: + push eax + mov [edx + 10], word 0 ; I think this was already done by IP rx + + ; swap the source and destination addresses + mov ecx, [edx + 16] + mov eax, [edx + 12] + mov [edx + 16], eax + mov [edx + 12], ecx + + ; recaluculate the IP header checksum + + mov ebx, edx + mov [checkAdd1], ebx + mov [checkSize1], word 20 + mov [checkAdd2], dword 0 + mov [checkSize2], word 0 + + call checksum + mov ax, [checkResult] + mov [edx + 10], ah + mov [edx + 11], al ; ?? correct byte order? + + mov [edx + 20], byte 0 ; change the request to a response + mov [edx + 22], word 0 ; clear ICMP checksum prior to re-calc + + ; Calculate the length of the ICMP data ( IP payload) + mov ah, [edx + 2] + mov al, [edx + 3] + sub ax, 20 + + mov [checkSize1], ax + mov ebx, edx + add ebx, 20 + + mov [checkAdd1], ebx + mov [checkAdd2], dword 0 + mov [checkSize2], word 0 + + call checksum + + mov ax, [checkResult] + mov [edx + 22], ah + mov [edx + 23], al + + ; Queue packet for transmission + + pop ebx + mov eax, NET1OUT_QUEUE + call queue + +icmp_exit: + ret \ No newline at end of file diff --git a/trunk/network/queue.inc b/trunk/network/queue.inc new file mode 100644 index 000000000..6dc6a0003 --- /dev/null +++ b/trunk/network/queue.inc @@ -0,0 +1,214 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; QUEUE.INC ;; +;; ;; +;; Buffer queue management for Menuet OS TCP/IP Stack ;; +;; ;; +;; Version 0.3 29 August 2002 ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;******************************************************************* +; Interface +; +; queueInit Configures the queues to empty +; dequeue Removes a buffer pointer from a queue +; queue Inserts a buffer pointer into a queue +; freeBuff Adds the buffer pointer to the list of free buffers +; queueSize Returns the number of entries in a queue +; +; The various defines for queue names can be found in stack.inc +; +;******************************************************************* + + +;*************************************************************************** +; Function +; freeBuff +; +; Description +; Adds a buffer number to the beginning of the free list. +; buffer number in eax ( ms word zeroed ) +; all other registers preserved +; This always works, so no error returned +;*************************************************************************** +freeBuff: + push ebx + push ecx + mov ebx, EMPTY_QUEUE + shl ebx, 1 + add ebx, queues + cli ; Ensure that another process does not interfer + movzx ecx, word [ebx] + mov [ebx], ax + shl eax, 1 + add eax, queueList + mov [eax], cx + sti + pop ecx + pop ebx + + ret + + +;*************************************************************************** +; Function +; queueSize +; +; Description +; Counts the number of entries in a queue +; queue number in ebx ( ms word zeroed ) +; Queue size returned in eax +; This always works, so no error returned +;*************************************************************************** +queueSize: + xor eax, eax + shl ebx, 1 + add ebx, queues + movzx ecx, word [ebx] + cmp cx, NO_BUFFER + je qs_exit + +qs_001: + inc eax + shl ecx, 1 + add ecx, queueList + movzx ecx, word [ecx] + cmp cx, NO_BUFFER + je qs_exit + jmp qs_001 + +qs_exit: + ret + + +;*************************************************************************** +; Function +; queue +; +; Description +; Adds a buffer number to the *end* of a queue +; This is quite quick because these queues will be short +; queue number in eax ( ms word zeroed ) +; buffer number in ebx ( ms word zeroed ) +; all other registers preserved +; This always works, so no error returned +;*************************************************************************** +queue: + push ebx + shl ebx, 1 + add ebx, queueList ; eax now holds address of queue entry + mov [ebx], word NO_BUFFER ; This buffer will be the last + + cli + shl eax, 1 + add eax, queues ; eax now holds address of queue + movzx ebx, word [eax] + + cmp bx, NO_BUFFER + jne qu_001 + + pop ebx + ; The list is empty, so add this to the head + mov [eax], bx + jmp qu_exit + +qu_001: + ; Find the last entry + shl ebx, 1 + add ebx, queueList + mov eax, ebx + movzx ebx, word [ebx] + cmp bx, NO_BUFFER + jne qu_001 + + mov ebx, eax + pop eax + mov [ebx], ax + +qu_exit: + sti + ret + + + +;*************************************************************************** +; Function +; dequeue +; +; Description +; removes a buffer number from the head of a queue +; This is fast, as it unlinks the first entry in the list +; queue number in eax ( ms word zeroed ) +; buffer number returned in eax ( ms word zeroed ) +; all other registers preserved +; +;*************************************************************************** +dequeue: + push ebx + shl eax, 1 + add eax, queues ; eax now holds address of queue + mov ebx, eax + cli + movzx eax, word [eax] + cmp ax, NO_BUFFER + je dq_exit + push eax + shl eax, 1 + add eax, queueList ; eax now holds address of queue entry + mov ax, [eax] + mov [ebx], ax + pop eax + +dq_exit: + sti + pop ebx + ret + + +;*************************************************************************** +; Function +; queueInit +; +; Description +; Initialises the queues to empty, and creates the free queue +; list. +; +;*************************************************************************** +queueInit: + mov esi, queues + mov ecx, NUMQUEUES + mov ax, NO_BUFFER + +qi001: + mov [esi], ax + inc esi + inc esi + loop qi001 + + mov esi, queues + ( 2 * EMPTY_QUEUE ) + + ; Initialise empty queue list + + xor ax, ax + mov [esi], ax + + mov ecx, NUMQUEUEENTRIES - 1 + mov esi, queueList + +qi002: + inc ax + mov [esi], ax + inc esi + inc esi + loop qi002 + + mov ax, NO_BUFFER + mov [esi], ax + + ret diff --git a/trunk/network/stack.inc b/trunk/network/stack.inc new file mode 100644 index 000000000..dc0611509 --- /dev/null +++ b/trunk/network/stack.inc @@ -0,0 +1,1784 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; STACK.INC ;; +;; ;; +;; TCP/IP stack for Menuet OS ;; +;; ;; +;; Version 0.7 4th July 2004 ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; Version 0.7 ;; +;; Added a timer per socket to allow delays when rx window ;; +;; gets below 1KB ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;******************************************************************* +; Interface +; The interfaces defined in ETHERNET.INC plus: +; stack_init +; stack_handler +; app_stack_handler +; app_socket_handler +; checksum +; +;******************************************************************* + + + +; +; IP Packet after reception - Normal IP packet format +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;0 |Version| IHL |Type of Service| Total Length | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;4 | Identification |Flags| Fragment Offset | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;8 | Time to Live | Protocol | Header Checksum | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;12 | Source Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;16 | Destination Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Data | +; +-+-+-.......... -+ + + +; TCP Payload ( Data field in IP datagram ) +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;20 | Source Port | Destination Port | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;24 | Sequence Number | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;28 | Acknowledgment Number | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;32 | Data | |U|A|P|R|S|F| | +; | Offset| Reserved |R|C|S|S|Y|I| Window | +; | | |G|K|H|T|N|N| | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;36 | Checksum | Urgent Pointer | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;40 | Options | Padding | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | data + + +; +; UDP Payload ( Data field in IP datagram ) +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Source Port | Destination Port | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Length ( UDP Header + Data ) | Checksum | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | UDP Data | +; +-+-+-.......... -+ +; + + +; +; Socket Descriptor + Buffer +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Status ( of this buffer ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Application Process ID | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Local IP Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Local IP Port | Unused ( set to 0 ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Remote IP Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Remote IP Port | Unused ( set to 0 ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 24| Rx Data Count INTEL format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 28| TCB STATE INTEL format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 32| TCB Timer (seconds) INTEL format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 36| ISS (Inital Sequence # used by this connection ) INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 40| IRS ( Inital Receive Sequence # ) INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 44| SND.UNA Seq # of unack'ed sent packets INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 48| SND.NXT Next send seq # to use INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 52| SND.WND Send window INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 56| RCV.NXT Next expected receive sequence # INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 60| RCV.WND Receive window INET format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 64| SEG.LEN Segment length INTEL format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 68| SEG.WND Segment window INTEL format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 72| Retransmit queue # NOW WINDOW SIZE TIMER INTEL format| +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; 76| RX Data | +; +-+-+-.......... -+ + + + +; IP protocol numbers +PROTOCOL_ICMP equ 1 +PROTOCOL_TCP equ 6 +PROTOCOL_UDP equ 17 + + +; TIPBUFF status values +BUFF_EMPTY equ 0 +BUFF_RX_FULL equ 1 +BUFF_ALLOCATED equ 2 +BUFF_TX_FULL equ 3 + +NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX + +SOCK_EMPTY equ 0 ; socket not in use +SOCK_OPEN equ 1 ; open issued, but no data sent + +; TCP opening modes +SOCKET_PASSIVE equ 0 +SOCKET_ACTIVE equ 1 + +; TCP TCB states +TCB_LISTEN equ 1 +TCB_SYN_SENT equ 2 +TCB_SYN_RECEIVED equ 3 +TCB_ESTABLISHED equ 4 +TCB_FIN_WAIT_1 equ 5 +TCB_FIN_WAIT_2 equ 6 +TCB_CLOSE_WAIT equ 7 +TCB_CLOSING equ 8 +TCB_LAST_ACK equ 9 +TCB_TIME_WAIT equ 10 +TCB_CLOSED equ 11 + +TWOMSL equ 10 ; # of secs to wait before closing socket + +; socket buffers +SOCKETBUFFSIZE equ 4096 ; state + config + buffer. +SOCKETHEADERSIZE equ 76 ; thus 4096 - SOCKETHEADERSIZE bytes data + +NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 + + +NUMQUEUES equ 4 +EMPTY_QUEUE equ 0 +IPIN_QUEUE equ 1 +IPOUT_QUEUE equ 2 +NET1OUT_QUEUE equ 3 + +NO_BUFFER equ 0xFFFF +IPBUFFSIZE equ 1500 ; MTU of an ethernet packet +NUMQUEUEENTRIES equ NUM_IPBUFFERS +NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets +TCP_RETRIES equ 5 ; Number of times to resend a packet +TCP_TIMEOUT equ 10 ; resend if not replied to in x hs + +; These are the 0x40 function codes for application access to the stack +STACK_DRIVER_STATUS equ 52 +SOCKET_INTERFACE equ 53 + + +; 128KB allocated for the stack and network driver buffers and other +; data requirements +stack_data_start equ 0x700000 +eth_data_start equ 0x700000 +stack_data equ 0x704000 +stack_data_end equ 0x71ffff + +; 32 bit word +stack_config equ stack_data +; 32 bit word - IP Address in network format +stack_ip equ stack_data + 4 +; 1 byte. 0 == inactive, 1 = active +slip_active equ stack_data + 8 ; no longer used +; 1 byte. 0 == inactive, 1 = active +ethernet_active equ stack_data + 9 +unused equ stack_data + 10 +; word. Buffer number, -1 if none +rx_buff_ptr equ stack_data + 12 +; dword. Buffer number, -1 if none +tx_buff_ptr equ stack_data + 16 +; byte. +slip_rx_state equ stack_data + 20 ; no longer used +; byte +slip_tx_state equ stack_data + 21 ; no longer used +; dword. Index into data +rx_data_ptr equ stack_data + 22 +; dword. Index into data +tx_data_ptr equ stack_data + 26 +; word. Count of bytes to send +tx_msg_len equ stack_data + 30 +; Address of selected socket +sktAddr equ stack_data + 32 +; Parameter to checksum routine - data ptr +checkAdd1 equ stack_data + 36 +; Parameter to checksum routine - 2nd data ptr +checkAdd2 equ stack_data + 40 +; Parameter to checksum routine - data size +checkSize1 equ stack_data + 44 +; Parameter to checksum routine - 2nd data size +checkSize2 equ stack_data + 46 +; result of checksum routine +checkResult equ stack_data + 48 + +; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len| +pseudoHeader equ stack_data + 50 + +; receive and transmit IP buffer allocation +sockets equ stack_data + 62 +Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) +; 1560 byte buffer for rx / tx ethernet packets +Ether_buffer equ Next_free2 +Next_free3 equ Ether_buffer + 1560 +last_1sTick equ Next_free3 +IPbuffs equ Next_free3 + 1 +queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE ) +queueList equ queues + (2 * NUMQUEUES) +last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) + +;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES ) +;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP +; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES ) + + + +resendQ equ 0x770000 +resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP + + +;*************************************************************************** +; Function +; stack_init +; +; Description +; Clear all allocated memory to zero. This ensures that +; on startup, the stack is inactive, and consumes no resources +; This is a kernel function, called prior to the OS main loop +; in set_variables +; +;*************************************************************************** +stack_init: + xor eax,eax + mov edi,stack_data_start + mov ecx,0x20000 / 4 ; Assume that we have 128KB of data + cld + rep stosd + + ; Initialise TCP resend queue data structures + mov eax, 0xFFFFFFFF + mov edi, resendQ + mov ecx, NUMRESENDENTRIES ; 1 dword per entry + cld + rep stosd + + + mov eax, 0xFFFFFFFF + mov [rx_buff_ptr], eax + mov [tx_buff_ptr], eax + + ; Put in some defaults : slip, 0x3f8, 4, ip=192.168.1.22 + ; Saves me entering them each boot up when debugging + mov eax, 0x03f80401 + mov [stack_config], eax + mov eax, 0xc801a8c0 + mov [stack_ip], eax + + call queueInit + + ; The following block sets up the 1s timer + mov al,0x0 + out 0x70,al + in al,0x71 + mov [last_1sTick], al + + ret + + + +;*************************************************************************** +; Function +; stack_handler +; +; Description +; The kernel loop routine for the stack +; This is a kernel function, called in the main loop +; +;*************************************************************************** +stack_handler: + + call ethernet_driver + call ip_rx + + + ; Test for 10ms tick, call tcp timer + mov eax, [timer_ticks] ;[0xfdf0] + cmp eax, [last_1hsTick] + je sh_001 + + mov [last_1hsTick], eax + call tcp_tx_handler + +sh_001: + + ; Test for 1 second event, call 1s timer functions + mov al,0x0 ;second + out 0x70,al + in al,0x71 + cmp al, [last_1sTick] + je sh_exit + + mov [last_1sTick], al + + call arp_timer + call tcp_tcb_handler + +sh_exit: + ret + + + + +;*************************************************************************** +; Function +; is_localport_unused +; +; Description +; scans through all the active sockets , looking to see if the +; port number specified in bx is in use as a localport number. +; This is useful when you want a to generate a unique local port +; number. +; On return, eax = 1 for free, 0 for in use +; +;*************************************************************************** +is_localport_unused: + mov al, bh + mov ah, bl + mov bx, ax + + mov edx, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS + mov eax, 0 ; Assume the return value is 'in use' + +ilu1: + sub edx, SOCKETBUFFSIZE + cmp [edx + sockets + 12], bx + loopnz ilu1 ; Return back if the socket is occupied + + jz ilu_exit + inc eax ; return port not in use + +ilu_exit: + ret + + + +;*************************************************************************** +; Function +; get_free_socket +; +; Description +; +;*************************************************************************** +get_free_socket: + push ecx + mov eax, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS + +gfs1: + sub eax, SOCKETBUFFSIZE + cmp [eax + sockets], dword SOCK_EMPTY + loopnz gfs1 ; Return back if the socket is occupied + mov eax, ecx + pop ecx + jz gfs_exit + mov eax, 0xFFFFFFFF + +gfs_exit: + ret + + + +;*************************************************************************** +; Function +; checksum +; +; Description +; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult +; Dont break anything; Most registers are used by the caller +; This code is derived from the 'C' source, cksum.c, in the book +; Internetworking with TCP/IP Volume II by D.E. Comer +; +;*************************************************************************** +checksum: + pusha + + xor edx, edx ; edx is the accumulative checksum + xor ebx, ebx + mov cx, [checkSize1] + shr cx, 1 + jz cs1_1 + + mov eax, [checkAdd1] + +cs1: + mov bh, [eax] + mov bl, [eax + 1] + + add eax, 2 + add edx, ebx + + loopw cs1 + +cs1_1: + and word [checkSize1], 0x01 + jz cs_test2 + + mov bh, [eax] + xor bl, bl + + add edx, ebx + +cs_test2: + mov cx, [checkSize2] + cmp cx, 0 + jz cs_exit ; Finished if no 2nd buffer + + shr cx, 1 + jz cs2_1 + + mov eax, [checkAdd2] + +cs2: + mov bh, [eax] + mov bl, [eax + 1] + + add eax, 2 + add edx, ebx + + loopw cs2 + +cs2_1: + and word [checkSize2], 0x01 + jz cs_exit + + mov bh, [eax] + xor bl, bl + + add edx, ebx + +cs_exit: + mov ebx, edx + + shr ebx, 16 + and edx, 0xffff + add edx, ebx + mov eax, edx + shr eax, 16 + add edx, eax + not dx + + mov [checkResult], dx + popa + ret + + + + +;*************************************************************************** +; Function +; app_stack_handler +; +; Description +; This is an application service, called by int 0x40 fn 52 +; It provides application access to the network interface layer +; +;*************************************************************************** +app_stack_handler: + cmp eax, 0 + jnz not0 + ; Read the configuartion word + mov eax, [stack_config] + ret + +not0: + cmp eax, 1 + jnz not1 + ; read the IP address + + mov eax, [stack_ip] + ret + +not1: + cmp eax, 2 + jnz not2 + + ; write the configuration word + mov [stack_config], ebx + + ; + ; If ethernet now enabled, probe for the card, reset it and empty + ; the packet buffer + ; If all successfull, enable the card. + ; If ethernet now disabled, set it as disabled. Should really + ; empty the tcpip data area too. + + ; ethernet interface is '3' in ls 7 bits + and bl, 0x7f + cmp bl, 3 + + je ash_eth_enable + ; Ethernet isn't enabled, so make sure that the card is disabled + mov [ethernet_active], byte 0 + + ret + +ash_eth_enable: + ; Probe for the card. This will reset it and enable the interface + ; if found + call eth_probe + cmp eax, 0 + je ash_eth_done ; Abort if no hardware found + + mov [ethernet_active], byte 1 + +ash_eth_done: + ret + +not2: + cmp eax, 3 + jnz not3 + ; write the IP Address + mov [stack_ip], ebx + ret + +not3: + cmp eax, 4 + jnz not4 + ; Enabled the slip driver on the comm port + ; slip removed + ret + +not4: + cmp eax, 5 + jnz not5 + ; Disable the slip driver on the comm port + ; slip removed + +not5: + cmp eax, 6 + jnz not6 + + ; Insert an IP packet into the stacks received packet queue + call stack_insert_packet + ret + +not6: + cmp eax, 7 + jnz not7 + + ; Test for any packets queued for transmission over the network + +not7: + cmp eax, 8 + jnz not8 + + call stack_get_packet + ; Extract a packet queued for transmission by the network + ret + +not8: + cmp eax, 9 + jnz not9 + + ; read the gateway IP address + + mov eax, [gateway_ip] + ret + +not9: + cmp eax, 10 + jnz not10 + + ; read the subnet mask + + mov eax, [subnet_mask] + ret + +not10: + cmp eax, 11 + jnz not11 + + ; write the gateway IP Address + mov [gateway_ip], ebx + + ret + +not11: + cmp eax, 12 + jnz not12 + + ; write the subnet mask + mov [subnet_mask], ebx + + +not12: + cmp eax, 13 + jnz not13 + + ; read the dns + + mov eax, [dns_ip] + ret + +not13: + cmp eax, 14 + jnz stack_driver_end + + ; write the dns IP Address + mov [dns_ip], ebx + + ret + +stack_driver_end: + ret + + + +;*************************************************************************** +; Function +; app_socket_handler +; +; Description +; This is an application service, called by int 0x40 +; It provides application access to stack socket services +; such as opening sockets +; +;*************************************************************************** +app_socket_handler: + cmp eax, 0 + jnz nots0 + + call socket_open + ret + +nots0: + cmp eax, 1 + jnz nots1 + + call socket_close + ret + +nots1: + cmp eax, 2 + jnz nots2 + + call socket_poll + ret + +nots2: + cmp eax, 3 + jnz nots3 + + call socket_read + ret + +nots3: + cmp eax, 4 + jnz nots4 + + call socket_write + ret + +nots4: + cmp eax, 5 + jnz nots5 + + call socket_open_tcp + ret + +nots5: + cmp eax, 6 + jnz nots6 + + call socket_status + ret + +nots6: + cmp eax, 7 + jnz nots7 + + call socket_write_tcp + ret + +nots7: + cmp eax, 8 + jnz nots8 + + call socket_close_tcp + ret + +nots8: + cmp eax, 9 + jnz nots9 + + call is_localport_unused + ret + +nots9: + cmp eax, 254 + jnz notdump + + ret + +notdump: + cmp eax, 255 + jnz notsdebug + + ; This sub function allows access to debugging information on the stack + ; ebx holds the request: + ; 100 : return length of empty queue + ; 101 : return length of IPOUT QUEUE + ; 102 : return length of IPIN QUEUE + ; 103 : return length of NET1OUT QUEUE + ; 200 : return # of ARP entries + ; 201 : return size of ARP table ( max # entries ) + ; 202 : select ARP table entry # + ; 203 : return IP of selected table entry + ; 204 : return High 4 bytes of MAC address of selected table entry + ; 205 : return low 2 bytes of MAC address of selected table entry + ; 206 : return status word of selected table entry + ; 207 : return Time to live of selected table entry + + + ; 2 : return number of IP packets received + ; 3 : return number of packets transmitted + ; 4 : return number of received packets dumped + ; 5 : return number of arp packets received + ; 6 : return status of packet driver + ; ( 0 == not active, FFFFFFFF = successful ) + + call stack_internal_status + ret + +notsdebug: + ; Invalid Option + ret + + +uglobal + ARPTmp: + times 14 db 0 +endg + +;*************************************************************************** +; Function +; stack_internal_status +; +; Description +; Returns information about the internal status of the stack +; This is only useful for debugging +; It works with the ethernet driver +; sub function in ebx +; return requested data in eax +; +;*************************************************************************** +stack_internal_status: + cmp ebx, 100 + jnz notsis100 + + ; 100 : return length of EMPTY QUEUE + mov ebx, EMPTY_QUEUE + call queueSize + ret + +notsis100: + cmp ebx, 101 + jnz notsis101 + + ; 101 : return length of IPOUT QUEUE + mov ebx, IPOUT_QUEUE + call queueSize + ret + +notsis101: + cmp ebx, 102 + jnz notsis102 + + ; 102 : return length of IPIN QUEUE + mov ebx, IPIN_QUEUE + call queueSize + ret + +notsis102: + cmp ebx, 103 + jnz notsis103 + + ; 103 : return length of NET1OUT QUEUE + mov ebx, NET1OUT_QUEUE + call queueSize + ret + +notsis103: + cmp ebx, 200 + jnz notsis200 + + ; 200 : return num entries in arp table + movzx eax, byte [NumARP] + ret + +notsis200: + cmp ebx, 201 + jnz notsis201 + + ; 201 : return arp table size + mov eax, 20 ; ARP_TABLE_SIZE + ret + +notsis201: + cmp ebx, 202 + jnz notsis202 + + ; 202 - read the requested table entry + ; into a temporary buffer + ; ecx holds the entry number + + mov eax, ecx + mov ecx, 14 ; ARP_ENTRY_SIZE + mul ecx + + mov ecx, [eax + ARPTable] + mov [ARPTmp], ecx + mov ecx, [eax + ARPTable+4] + mov [ARPTmp+4], ecx + mov ecx, [eax + ARPTable+8] + mov [ARPTmp+8], ecx + mov cx, [eax + ARPTable+12] + mov [ARPTmp+12], cx + ret + +notsis202: + cmp ebx, 203 + jnz notsis203 + + ; 203 - return IP address + mov eax, [ARPTmp] + ret + +notsis203: + cmp ebx, 204 + jnz notsis204 + + ; 204 - return MAC high dword + mov eax, [ARPTmp+4] + ret + +notsis204: + cmp ebx, 205 + jnz notsis205 + + ; 205 - return MAC ls word + movzx eax, word [ARPTmp+8] + ret + +notsis205: + cmp ebx, 206 + jnz notsis206 + + ; 206 - return status word + movzx eax, word [ARPTmp+10] + ret + +notsis206: + cmp ebx, 207 + jnz notsis207 + + ; 207 - return ttl word + movzx eax, word [ARPTmp+12] + ret + +notsis207: + cmp ebx, 2 + jnz notsis2 + + ; 2 : return number of IP packets received + mov eax, [ip_rx_count] + ret + +notsis2: + cmp ebx, 3 + jnz notsis3 + + ; 3 : return number of packets transmitted + mov eax, [ip_tx_count] + ret + +notsis3: + cmp ebx, 4 + jnz notsis4 + + ; 4 : return number of received packets dumped + mov eax, [dumped_rx_count] + ret + +notsis4: + cmp ebx, 5 + jnz notsis5 + + ; 5 : return number of arp packets received + mov eax, [arp_rx_count] + ret + +notsis5: + cmp ebx, 6 + jnz notsis6 + + ; 6 : return status of packet driver + ; ( 0 == not active, FFFFFFFF = successful ) + mov eax, [eth_status] + ret + +notsis6: + xor eax, eax + ret + + + +;*************************************************************************** +; Function +; stack_get_packet +; +; Description +; extracts an IP packet from the NET1 output queue +; and sends the data to the calling process +; pointer to data in edx +; returns number of bytes read in eax +; +;*************************************************************************** +stack_get_packet: + ; Look for a buffer to tx + mov eax, NET1OUT_QUEUE + call dequeue + cmp ax, NO_BUFFER + je sgp_non_exit ; Exit if no buffer available + + push eax ; Save buffer number for freeing at end + + push edx + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + pop edx + + push eax ; save address of IP data + + ; Get the address of the callers data + mov edi,[0x3010] + add edi,0x10 + add edx,[edi] + mov edi, edx + + pop eax + + mov ecx, 1500 ; should get the actual number of bytes to write + mov esi, eax + cld + rep movsb ; copy the data across + + ; And finally, return the buffer to the free queue + pop eax + call freeBuff + + mov eax, 1500 + ret + +sgp_non_exit: + xor eax, eax + ret + + + +;*************************************************************************** +; Function +; stack_insert_packet +; +; Description +; writes an IP packet into the stacks receive queue +; # of bytes to write in ecx +; pointer to data in edx +; returns 0 in eax ok, -1 == failed +; +;*************************************************************************** +stack_insert_packet: + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je sip_err_exit + + push eax + + ; save the pointers to the data buffer & size + push edx + push ecx + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax + + ; So, edx holds the IPbuffer ptr + + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + pop eax ; get callers ptr to data to send + + ; Get the address of the callers data + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + mov esi, eax + + mov edi, edx + cld + rep movsb ; copy the data across + + pop ebx + + mov eax, IPIN_QUEUE + call queue + + inc dword [ip_rx_count] + + mov eax, 0 + ret + +sip_err_exit: + mov eax, 0xFFFFFFFF + ret + + + +;*************************************************************************** +; Function +; socket_open +; +; Description +; find a free socket +; local port in ebx +; remote port in ecx +; remote ip in edx +; return socket # in eax, -1 if none available +; +;*************************************************************************** +socket_open: + call get_free_socket + + cmp eax, 0xFFFFFFFF + jz so_exit + + ; ax holds the socket number that is free. Get real address + push eax + shl eax, 12 + add eax, sockets + + mov [eax], dword SOCK_OPEN + + mov [eax + 12], byte bh ; Local port ( LS 16 bits ) + mov [eax + 13], byte bl ; Local port ( LS 16 bits ) + mov ebx, [stack_ip] + mov [eax + 8], ebx ; Local IP + mov [eax + 20], ch ; Remote Port ( LS 16 bits ) + mov [eax + 21], cl ; Remote Port ( LS 16 bits ) + mov [eax + 16], edx ; Remote IP ( in Internet order ) + mov [eax + 24], dword 0 ; recieved data count + + mov esi, [0x3010] + mov ebx, [esi+0x4] + mov [eax + 4], ebx ; save the process ID + pop eax ; Get the socket number back, so we can return it + +so_exit: + ret + + + +;*************************************************************************** +; Function +; socket_open_tcp +; +; Description +; Opens a TCP socket in PASSIVE or ACTIVE mode +; find a free socket +; local port in ebx ( intel format ) +; remote port in ecx ( intel format ) +; remote ip in edx ( in Internet byte order ) +; Socket open mode in esi ( SOCKET_PASSIVE or SOCKET_ACTIVE ) +; return socket # in eax, -1 if none available +; +;*************************************************************************** +socket_open_tcp: + call get_free_socket + + cmp eax, 0xFFFFFFFF + jz so_exit + + ; ax holds the socket number that is free. Get real address + push eax + shl eax, 12 + add eax, sockets + + mov [sktAddr], eax + mov [eax], dword SOCK_OPEN + + ; TODO - check this works! + mov [eax + 72], dword 0 ; Reset the window timer. + + mov [eax + 12], byte bh ; Local port ( LS 16 bits ) + mov [eax + 13], byte bl ; Local port ( LS 16 bits ) + mov ebx, [stack_ip] + mov [eax + 8], ebx ; Local IP + mov [eax + 20], ch ; Remote Port ( LS 16 bits ) + mov [eax + 21], cl ; Remote Port ( LS 16 bits ) + mov [eax + 16], edx ; Remote IP ( in Internet order ) + mov [eax + 24], dword 0 ; recieved data count + + ; Now fill in TCB state + mov ebx, TCB_LISTEN + cmp esi, SOCKET_PASSIVE + jz sot_001 + mov ebx, TCB_SYN_SENT + +sot_001: + mov [eax + 28], ebx ; Indicate the state of the TCB + + mov esi, [0x3010] + mov ecx, [esi+0x4] + mov [eax + 4], ecx ; save the process ID + + cmp ebx, TCB_LISTEN + je sot_done + + ; Now, if we are in active mode, then we have to send a SYN to the specified remote port + + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je sot_done + + push eax + + mov bl, 0x02 ; SYN + mov ecx, 0 + + call buildTCPPacket + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne sot_notlocal + mov eax, IPIN_QUEUE + +sot_notlocal: + ; Send it. + pop ebx + call queue + + mov esi, [sktAddr] + + ; increment SND.NXT in socket + add esi, 48 + call inc_inet_esi + +sot_done: + pop eax ; Get the socket number back, so we can return it + +sot_exit: + ret + + + +;*************************************************************************** +; Function +; socket_close +; +; Description +; socket # in ebx +; returns 0 for ok, -1 for socket not open (fail) +; +;*************************************************************************** +socket_close: + shl ebx, 12 + add ebx, sockets + mov eax, 0xFFFFFFFF ; assume this operation will fail.. + cmp [ebx], dword SOCK_EMPTY + jz sc_exit + + ; Clear the socket varaibles + xor eax, eax + mov edi,ebx + mov ecx,SOCKETHEADERSIZE + cld + rep stosb + +sc_exit: + ret + + + +;*************************************************************************** +; Function +; socket_close_tcp +; +; Description +; socket # in ebx +; returns 0 for ok, -1 for socket not open (fail) +; +;*************************************************************************** +socket_close_tcp: + ; first, remove any resend entries + pusha + + mov esi, resendQ + mov ecx, 0 + +sct001: + cmp ecx, NUMRESENDENTRIES + je sct003 ; None left + cmp [esi], bl + je sct002 ; found one + inc ecx + add esi, 4 + jmp sct001 + +sct002: + dec dword [arp_rx_count] ; ************ TEST ONLY! + + mov [esi], byte 0xFF + jmp sct001 + +sct003: + popa + + shl ebx, 12 + add ebx, sockets + mov [sktAddr], ebx + mov eax, 0xFFFFFFFF ; assume this operation will fail.. + cmp [ebx], dword SOCK_EMPTY + jz sct_exit + + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je stl_exit + + push eax + + mov bl, 0x11 ; FIN + ACK + mov ecx, 0 + mov esi, 0 + + call buildTCPPacket + + mov ebx, [sktAddr] + + ; increament SND.NXT in socket + mov esi, 48 + add esi, ebx + call inc_inet_esi + + + ; Get the socket state + mov eax, [ebx + 28] + cmp eax, TCB_LISTEN + je destroyTCB + cmp eax, TCB_SYN_SENT + je destroyTCB + cmp eax, TCB_SYN_RECEIVED + je sct_finwait1 + cmp eax, TCB_ESTABLISHED + je sct_finwait1 + + ; assume CLOSE WAIT + ; Send a fin, then enter last-ack state + mov eax, TCB_LAST_ACK + mov [ebx + 28], eax + xor eax, eax + jmp sct_send + +sct_finwait1: + ; Send a fin, then enter finwait2 state + mov eax, TCB_FIN_WAIT_1 + mov [ebx + 28], eax + xor eax, eax + +sct_send: + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne sct_notlocal + mov eax, IPIN_QUEUE + +sct_notlocal: + ; Send it. + pop ebx + call queue + jmp sct_exit + +destroyTCB: + pop eax + ; Clear the socket varaibles + xor eax, eax + mov edi,ebx + mov ecx,SOCKETHEADERSIZE + cld + rep stosb + +sct_exit: + ret + + + +;*************************************************************************** +; Function +; socket_poll +; +; Description +; socket # in ebx +; returns count in eax. +; +;*************************************************************************** +socket_poll: + shl ebx, 12 + add ebx, sockets + mov eax, [ebx + 24] + + ret + + + +;*************************************************************************** +; Function +; socket_status +; +; Description +; socket # in ebx +; returns TCB state in eax. +; +;*************************************************************************** +socket_status: + shl ebx, 12 + add ebx, sockets + mov eax, [ebx + 28] + + ret + + + +;*************************************************************************** +; Function +; socket_read +; +; Description +; socket # in ebx +; returns # of bytes remaining in eax, data in bl +; +;*************************************************************************** +socket_read: + shl ebx, 12 + add ebx, sockets + mov eax, [ebx + 24] ; get count of bytes + mov ecx,1 + test eax, eax + jz sr2 + + dec eax + mov esi, ebx ; esi is address of socket + mov [ebx + 24], eax ; store new count + movzx ebx, byte [ebx + SOCKETHEADERSIZE] ; get the byte + add esi, SOCKETHEADERSIZE + mov edi, esi + inc esi + + mov ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4 + cld + rep movsd + xor ecx, ecx + +sr1: + jmp sor_exit + +sr2: + xor bl, bl + +sor_exit: + ret + + + +;*************************************************************************** +; Function +; socket_write +; +; Description +; socket in ebx +; # of bytes to write in ecx +; pointer to data in edx +; returns 0 in eax ok, -1 == failed ( invalid socket, or +; could not queue IP packet ) +; +;*************************************************************************** +socket_write: + ; First, find the address of the socket descriptor + shl ebx, 12 + add ebx, sockets ; ebx = address of actual socket + + mov eax, 0xFFFFFFFF + ; If the socket is invalid, return with an error code + cmp [ebx], dword SOCK_EMPTY + je sw_exit + + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je sw_exit + + ; Save the queue entry number + push eax + + ; save the pointers to the data buffer & size + push edx + push ecx + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax + + ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr + + ; Fill in the IP header ( some data is in the socket descriptor) + mov eax, [ebx + 8] + mov [edx + 12], eax ; source IP + mov eax, [ebx + 16] + mov [edx + 16], eax ; Destination IP + + mov al, 0x45 + mov [edx], al ; Version, IHL + xor al, al + mov [edx + 1], al ; Type of service + + pop eax ; Get the UDP data length + push eax + + add eax, 20 + 8 ; add IP header and UDP header lengths + mov [edx + 2], ah + mov [edx + 3], al + xor al, al + mov [edx + 4], al + mov [edx + 5], al + mov al, 0x40 + mov [edx + 6], al + xor al, al + mov [edx + 7], al + mov al, 0x20 + mov [edx + 8], al + mov al, 17 + mov [edx + 9], al + + ; Checksum left unfilled + xor ax, ax + mov [edx + 10], ax + + ; Fill in the UDP header ( some data is in the socket descriptor) + mov ax, [ebx + 12] + mov [edx + 20], ax + + mov ax, [ebx + 20] + mov [edx + 20 + 2], ax + + pop eax + push eax + + add eax, 8 + mov [edx + 20 + 4], ah + mov [edx + 20 + 5], al + + ; Checksum left unfilled + xor ax, ax + mov [edx + 20 + 6], ax + + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + pop eax ; get callers ptr to data to send + + ; Get the address of the callers data + mov edi,[0x3010] + add edi,0x10 + add eax,[edi] + mov esi, eax + + mov edi, edx + add edi, 28 + cld + rep movsb ; copy the data across + + ; we have edx as IPbuffer ptr. + ; Fill in the UDP checksum + ; First, fill in pseudoheader + mov eax, [edx + 12] + mov [pseudoHeader], eax + mov eax, [edx + 16] + mov [pseudoHeader+4], eax + mov ax, 0x1100 ; 0 + protocol + mov [pseudoHeader+8], ax + add ebx, 8 + mov eax, ebx + mov [pseudoHeader+10], ah + mov [pseudoHeader+11], al + + mov eax, pseudoHeader + mov [checkAdd1], eax + mov [checkSize1], word 12 + mov eax, edx + add eax, 20 + mov [checkAdd2], eax + mov eax, ebx + mov [checkSize2], ax ; was eax!! mjh 8/7/02 + + call checksum + + ; store it in the UDP checksum ( in the correct order! ) + mov ax, [checkResult] + + ; If the UDP checksum computes to 0, we must make it 0xffff + ; (0 is reserved for 'not used') + cmp ax, 0 + jne sw_001 + mov ax, 0xffff + +sw_001: + mov [edx + 20 + 6], ah + mov [edx + 20 + 7], al + + ; Fill in the IP header checksum + mov eax, edx + mov [checkAdd1], eax + mov [checkSize1], word 20 + mov [checkAdd2], dword 0 + mov [checkSize2], word 0 + + call checksum + + mov ax, [checkResult] + mov [edx + 10], ah + mov [edx + 11], al + + ; Check destination IP address. + ; If it is the local host IP, route it back to IP_RX + + pop ebx + mov eax, NET1OUT_QUEUE + + mov ecx, [ edx + 16] + mov edx, [stack_ip] + cmp edx, ecx + jne sw_notlocal + mov eax, IPIN_QUEUE + +sw_notlocal: + ; Send it. + call queue + + xor eax, eax + +sw_exit: + ret + + + +;*************************************************************************** +; Function +; socket_write_tcp +; +; Description +; socket in ebx +; # of bytes to write in ecx +; pointer to data in edx +; returns 0 in eax ok, -1 == failed ( invalid socket, or +; could not queue IP packet ) +; +;*************************************************************************** +socket_write_tcp: + ; First, find the address of the socket descriptor + shl ebx, 12 + add ebx, sockets ; ebx = address of actual socket + + mov [sktAddr], ebx + + mov eax, 0xFFFFFFFF + ; If the socket is invalid, return with an error code + cmp [ebx], dword SOCK_EMPTY + je swt_exit + + ; If the sockets window timer is nonzero, do not queue packet + ; TODO - done + cmp [ebx + 72], dword 0 + jne swt_exit + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je swt_exit + + push eax + + mov bl, 0x10 ; ACK + + ; Get the address of the callers data + mov edi,[0x3010] + add edi,0x10 + add edx,[edi] + mov esi, edx + + pop eax + push eax + + push ecx + call buildTCPPacket + pop ecx + + ; Check destination IP address. + ; If it is the local host IP, route it back to IP_RX + + pop ebx + push ecx + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne swt_notlocal + mov eax, IPIN_QUEUE + +swt_notlocal: + pop ecx + + push ebx ; save ipbuffer number + + call queue + + mov esi, [sktAddr] + + ; increament SND.NXT in socket + ; Amount to increment by is in ecx + add esi, 48 + call add_inet_esi + + pop ebx + + ; Copy the IP buffer to a resend queue + ; If there isn't one, dont worry about it for now + mov esi, resendQ + mov ecx, 0 + +swt003: + cmp ecx, NUMRESENDENTRIES + je swt001 ; None found + cmp [esi], byte 0xFF + je swt002 ; found one + inc ecx + add esi, 4 + jmp swt003 + +swt002: + push ebx + + ; OK, we have a buffer descriptor ptr in esi. + ; resend entry # in ecx + ; Populate it + ; socket # + ; retries count + ; retry time + ; fill IP buffer associated with this descriptor + + mov eax, [sktAddr] + sub eax, sockets + shr eax, 12 ; get skt # + mov [esi], al + mov [esi + 1], byte TCP_RETRIES + mov [esi + 2], word TCP_TIMEOUT + + inc ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + mov edi, resendBuffer - IPBUFFSIZE +swt002a: + add edi, IPBUFFSIZE + loop swt002a + + ; we have dest buffer location in edi + pop eax + ; convert source buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + mov esi, eax + + ; do copy + mov ecx, IPBUFFSIZE + cld + rep movsb + + inc dword [arp_rx_count] ; ************ TEST ONLY! + +swt001: + xor eax, eax + +swt_exit: + ret + + + +; Below, the main network layer source code is included +; + +include "queue.inc" +include "ip.inc" +include "tcp.inc" +include "udp.inc" +include "eth_drv/ethernet.inc" diff --git a/trunk/network/tcp.inc b/trunk/network/tcp.inc new file mode 100644 index 000000000..b27106c19 --- /dev/null +++ b/trunk/network/tcp.inc @@ -0,0 +1,1243 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; TCP.INC ;; +;; ;; +;; TCP Processes for Menuet OS TCP/IP stack ;; +;; ;; +;; Version 0.6 4th July 2004 ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; v0.6 : Added reset handling in the established state ;; +;; Added a timer per socket to allow delays when rx window ;; +;; gets below 1KB ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;******************************************************************* +; Interface +; +; tcp_tx_handler Handles the TCP transmit queue +; tcp_rx The protocol handler for received data +; buildTCPPacket fills in the packet headers and data +; tcpStateMachine Main state machine for received TCP packets +; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state +; +;******************************************************************* + + + +;*************************************************************************** +; Function +; tcp_tcb_handler +; +; Description +; Handles sockets in the timewait state, closing them +; when the TCB timer expires +; +;*************************************************************************** +tcp_tcb_handler: + ; scan through all the sockets, decrementing active timers + + mov eax, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS + +tth1: + sub eax, SOCKETBUFFSIZE + cmp [eax + sockets + 32], dword 0 + jne tth2 + +tth1a: + cmp [eax + sockets + 72], dword 0 + jne tth4 + + loop tth1 + ret + +tth2: + ; decrement it, delete socket if TCB timer = 0 & socket in timewait state + pusha + dec dword [eax + sockets + 32] + cmp [eax + sockets + 32], dword 0 + jne tth3 + + cmp [eax + sockets + 28], dword TCB_TIME_WAIT + jne tth3 + + ; OK, delete socket + mov edi, eax + add edi, sockets + + xor eax, eax + mov ecx, SOCKETHEADERSIZE + cld + rep stosb + +tth3: + popa + + jmp tth1a + + loop tth1 + ret + + ; TODO - prove it works! +tth4: + dec dword [eax + sockets + 72] + loop tth1 + ret + + + + +tth_exit: + ret + + +;*************************************************************************** +; Function +; tcp_tx_handler +; +; Description +; Handles queued TCP data +; This is a kernel function, called by stack_handler +; +;*************************************************************************** +tcp_tx_handler: + ; decrement all resend buffers timers. If they + ; expire, queue them for sending, and restart the timer. + ; If the retries counter reach 0, delete the entry + + mov esi, resendQ + mov ecx, 0 + +tth001: + cmp ecx, NUMRESENDENTRIES + je tth003 ; None left + cmp [esi], byte 0xFF + jne tth002 ; found one + inc ecx + add esi, 4 + jmp tth001 + +tth002: + ; we have one. decrement it's timer by 1 + dec word [esi+2] + mov ax, [esi+2] + cmp ax, 0 + je tth002a + inc ecx + add esi, 4 + jmp tth001 ; Timer not zero, so move on + +tth002a: + mov bl, 0xff + ; restart timer, and decrement retries + ; After the first resend, back of on next, by a factor of 5 + mov [esi+2], word TCP_TIMEOUT * 5 + dec byte [esi+1] + mov al, [esi+1] + cmp al, 0 + jne tth004 + + ; retries now 0, so delete from queue + xchg [esi], bl +tth004: + + ; resend packet + pusha + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + jne tth004z + + ; TODO - try again in 10ms. + cmp bl, 0xff + jne tth004za + mov [esi], bl + +tth004za: + ; Mark it to expire in 10ms - 1 tick + mov [esi+1], byte 1 + mov [esi+2], word 1 + jmp tth005 + +tth004z: + ; we have a buffer # in ax + + push eax + push ecx + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + ; we have the buffer address in eax + mov edi, eax + pop ecx + ; get resend data address + inc ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + mov esi, resendBuffer - IPBUFFSIZE +tth004a: + add esi, IPBUFFSIZE + loop tth004a + + ; we have resend buffer location in esi + mov ecx, IPBUFFSIZE + + ; copy data across + cld + rep movsb + + ; queue packet + + + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ edi + 16 ] + cmp edx, ecx + jne tth004b + mov eax, IPIN_QUEUE + +tth004b: + pop ebx + + call queue + + +tth005: + popa + + inc ecx + add esi, 4 + jmp tth001 + +tth003: + ret + + + + +;*************************************************************************** +; Function +; tcp_rx +; +; Description +; TCP protocol handler +; This is a kernel function, called by ip_rx +; IP buffer address given in edx +; IP buffer number in eax +; Free up (or re-use) IP buffer when finished +; +;*************************************************************************** +tcp_rx: + ; The process is as follows. + ; Look for a socket with matching remote IP, remote port, local port + ; if not found, then + ; look for remote IP + local port match ( where sockets remote port = 0) + ; if not found, then + ; look for a socket where local socket port == IP packets remote port + ; where sockets remote port, remote IP = 0 + ; discard if not found + ; Call sockets tcbStateMachine, with pointer to packet. + ; the state machine will not delete the packet, so do that here. + + push eax + + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; IP Packet SA = Remote IP + ; IP Packet TCP Source Port = remote Port + + mov eax, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS +ss1: + sub eax, SOCKETBUFFSIZE + movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr + cmp [eax + sockets + 12], bx ; compare with socket's local port + jnz nxttst1 ; different - try next socket + + movzx ebx, word [edx + 20] ; get the source port from the TCP hdr + cmp [eax + sockets + 20], bx ; compare with socket's remote port + jnz nxttst1 ; different - try next socket + + + mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr + cmp [eax + sockets + 16], ebx ; compare with socket's remote IP + jnz nxttst1 ; different - try next socket + + ; We have a complete match - use this socket + jmp tcprx_001 + +nxttst1: + loop ss1 ; Return back if no match + + ; If we got here, there was no match + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; IP Packet SA = Remote IP + ; socket remote Port = 0 + + mov eax, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS + +ss2: + sub eax, SOCKETBUFFSIZE + + movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr + cmp [eax + sockets + 12], bx ; compare with socket's local port + jnz nxttst2 ; different - try next socket + + mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr + cmp [eax + sockets + 16], ebx ; compare with socket's remote IP + jnz nxttst2 ; different - try next socket + + mov ebx, 0 + cmp [eax + sockets + 20], bx ; only match a remote socket of 0 + jnz nxttst2 ; different - try next socket + + ; We have a complete match - use this socket + jmp tcprx_001 + +nxttst2: + loop ss2 ; Return back if no match + + ; If we got here, there was no match + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; socket Remote IP = 0 + ; socket remote Port = 0 + + mov eax, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS + +ss3: + sub eax, SOCKETBUFFSIZE + + movzx ebx, word [edx + 22] ; get destination port from the TCP hdr + cmp [eax + sockets + 12], bx ; compare with socket's local port + jnz nxttst3 ; different - try next socket + + mov ebx, 0 + cmp [eax + sockets + 20], bx ; only match a remote socket of 0 + jnz nxttst3 ; different - try next socket + + mov ebx, 0 + cmp [eax + sockets + 16], ebx ; only match a socket remote IP of 0 + jnz nxttst3 ; different - try next socket + + ; We have a complete match - use this socket + jmp tcprx_001 + +nxttst3: + loop ss3 ; Return back if no match + + ; If we got here, we need to reject the packet + inc dword [dumped_rx_count] + jmp tcprx_exit + +tcprx_001: + ; We have a valid socket/TCB, so call the TCB State Machine for that skt. + ; socket is pointed to by [eax + sockets] + ; IP packet is pointed to by [edx] + ; IP buffer number is on stack ( it will be popped at the end) + call tcpStateMachine + +tcprx_exit: + pop eax + call freeBuff + + ret + + + +;*************************************************************************** +; Function +; buildTCPPacket +; +; Description +; builds an IP Packet with TCP data fully populated for transmission +; You may destroy any and all registers +; TCP control flags specified in bl +; This TCB is in [sktAddr] +; User data pointed to by esi +; Data length in ecx +; Transmit buffer number in eax +; +;*************************************************************************** +buildTCPPacket: + push ecx ; Save data length + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax + + mov [edx + 33], bl ; TCP flags + + mov ebx, [sktAddr] + + ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr + + ; Fill in the IP header ( some data is in the socket descriptor) + mov eax, [ebx + 8] + mov [edx + 12], eax ; source IP + mov eax, [ebx + 16] + mov [edx + 16], eax ; Destination IP + + mov al, 0x45 + mov [edx], al ; Version, IHL + xor al, al + mov [edx + 1], al ; Type of service + + pop eax ; Get the TCP data length + push eax + + add eax, 20 + 20 ; add IP header and TCP header lengths + mov [edx + 2], ah + mov [edx + 3], al + xor al, al + mov [edx + 4], al + mov [edx + 5], al + mov al, 0x40 + mov [edx + 6], al + xor al, al + mov [edx + 7], al + mov al, 0x20 + mov [edx + 8], al + mov al, 6 ; TCP protocol + mov [edx + 9], al + + ; Checksum left unfilled + xor ax, ax + mov [edx + 10], ax + + ; Fill in the TCP header ( some data is in the socket descriptor) + mov ax, [ebx + 12] + mov [edx + 20], ax ; Local Port + + mov ax, [ebx + 20] + mov [edx + 20 + 2], ax ; desitination Port + + ; Checksum left unfilled + xor ax, ax + mov [edx + 20 + 16], ax + + ; sequence number + mov eax, [ebx + 48] + mov [edx + 20 + 4], eax + + ; ack number + mov eax, [ebx + 56] + mov [edx + 20 + 8], eax + + ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) + ; 768 bytes seems better + mov ax, 0x0003 + mov [edx + 20 + 14], ax + + ; Urgent pointer (0) + mov ax, 0 + mov [edx + 20 + 18], ax + + ; data offset ( 0x50 ) + mov al, 0x50 + mov [edx + 20 + 12], al + + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + + cmp ebx, 0 + jz btp_001 + + mov edi, edx + add edi, 40 + cld + rep movsb ; copy the data across + +btp_001: + ; we have edx as IPbuffer ptr. + ; Fill in the TCP checksum + ; First, fill in pseudoheader + mov eax, [edx + 12] + mov [pseudoHeader], eax + mov eax, [edx + 16] + mov [pseudoHeader+4], eax + mov ax, 0x0600 ; 0 + protocol + mov [pseudoHeader+8], ax + add ebx, 20 + mov eax, ebx + mov [pseudoHeader+10], ah + mov [pseudoHeader+11], al + + mov eax, pseudoHeader + mov [checkAdd1], eax + mov [checkSize1], word 12 + mov eax, edx + add eax, 20 + mov [checkAdd2], eax + mov eax, ebx + mov [checkSize2], ax + + call checksum + + ; store it in the TCP checksum ( in the correct order! ) + mov ax, [checkResult] + + mov [edx + 20 + 16], ah + mov [edx + 20 + 17], al + + ; Fill in the IP header checksum + mov eax, edx + mov [checkAdd1], eax + mov [checkSize1], word 20 + mov [checkAdd2], dword 0 + mov [checkSize2], word 0 + + call checksum + + mov ax, [checkResult] + mov [edx + 10], ah + mov [edx + 11], al + + ret + + +; Increments the 32 bit value pointed to by esi in internet order +inc_inet_esi: + push eax + add esi, 3 + mov al, byte[esi] + inc al + mov byte[esi], al + cmp al, 0 + jnz iie_exit + dec esi + mov al, byte[esi] + inc al + mov byte[esi], al + cmp al, 0 + jnz iie_exit + dec esi + mov al, byte[esi] + inc al + mov byte[esi], al + cmp al, 0 + jnz iie_exit + dec esi + mov al, byte[esi] + inc al + mov byte[esi], al + +iie_exit: + pop eax + ret + + +; Increments the 32 bit value pointed to by esi in internet order +; by the value in ecx +add_inet_esi: + push eax + + mov al, [esi] + shl eax, 8 + inc esi + mov al, [esi] + shl eax, 8 + inc esi + mov al, [esi] + shl eax, 8 + inc esi + mov al, [esi] + add eax, ecx + mov [esi], al + dec esi + shr eax, 8 + mov [esi], al + dec esi + shr eax, 8 + mov [esi], al + dec esi + shr eax, 8 + mov [esi], al + pop eax + ret + + +iglobal + TCBStateHandler: + dd stateTCB_LISTEN + dd stateTCB_SYN_SENT + dd stateTCB_SYN_RECEIVED + dd stateTCB_ESTABLISHED + dd stateTCB_FIN_WAIT_1 + dd stateTCB_FIN_WAIT_2 + dd stateTCB_CLOSE_WAIT + dd stateTCB_CLOSING + dd stateTCB_LAST_ACK + dd stateTCB_TIME_WAIT + dd stateTCB_CLOSED +endg + +;*************************************************************************** +; Function +; tcpStateMachine +; +; Description +; TCP state machine +; This is a kernel function, called by tcp_rx +; +; IP buffer address given in edx +; Socket/TCB address in [eax + sockets] +; +; The IP buffer will be released by the caller +;*************************************************************************** +tcpStateMachine: + mov ebx, sockets + add ebx, eax + mov [sktAddr], ebx + + ; as a packet has been received, update the TCB timer + mov ecx, TWOMSL + mov [ebx + 32], ecx + + ; If the received packet has an ACK bit set, + ; remove any packets in the resend queue that this + ; received packet acknowledges + pusha + mov cl, [edx + 33] + and cl, 0x10 + cmp cl, 0x10 + jne tsm001 ; No ACK, so no data yet + + + ; get skt number in al + shr eax, 12 + + ; The ack number is in [edx + 28], inet format + ; skt in al + + mov esi, resendQ + mov ecx, 0 + +t001: + cmp ecx, NUMRESENDENTRIES + je t003 ; None left + cmp [esi], al + je t002 ; found one + inc ecx + add esi, 4 + jmp t001 + +t002: ; Can we delete this buffer? + + ; If yes, goto t004. No, goto t001 + ; Get packet data address + + push ecx + inc ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + mov edi, resendBuffer - IPBUFFSIZE +t002a: + add edi, IPBUFFSIZE + loop t002a + + ; we have dest buffer location in edi. incoming packet in edx. + ; Get this packets sequence number + ; preserve al, ecx, esi, edx + + mov cl, [edi + 24] + shl ecx, 8 + mov cl, [edi + 25] + shl ecx, 8 + mov cl, [edi + 26] + shl ecx, 8 + mov cl, [edi + 27] + movzx ebx, byte [edi + 3] + mov bh, [edi + 2] + sub ebx, 40 + add ecx, ebx ; ecx is now seq# of last byte +1, intel format + + ; get recievd ack #, in intel format + mov bl, [edx + 28] + shl ebx, 8 + mov bl, [edx + 29] + shl ebx, 8 + mov bl, [edx + 30] + shl ebx, 8 + mov bl, [edx + 31] + + cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que + ; DANGER! need to handle case that we have just + ; passed the 2**32, and wrapped round! + pop ecx + + jae t004 ; if rx > old, delete old + inc ecx + add esi, 4 + jmp t001 + + +t004: + dec dword [arp_rx_count] ; ************ TEST ONLY! + + mov [esi], byte 0xFF + inc ecx + add esi, 4 + jmp t001 + +t003: + +tsm001: + popa + + ; Call handler for given TCB state + mov ebx, [eax + sockets+28] + cmp ebx, TCB_LISTEN + jb tsm_exit + cmp ebx, TCB_CLOSED + ja tsm_exit + + dec ebx + call dword [TCBStateHandler+ebx*4] + +tsm_exit: + ret + + + +stateTCB_LISTEN: + ; In this case, we are expecting a SYN packet + ; For now, if the packet is a SYN, process it, and send a response + ; If not, ignore it + + ; Look at control flags + mov bl, [edx + 33] + and bl, 0x02 + cmp bl, 0x02 + jnz stl_exit + + ; We have a SYN. update the socket with this IP packets details, + ; And send a response + + mov ebx, [edx + 12] ; IP source address + mov [eax + sockets + 16], ebx + mov bx, [edx + 20] ; IP source port + mov [eax + sockets + 20], bx + mov ebx, [edx + 24] ; IRS + mov [eax + sockets + 40], ebx + mov [eax + sockets + 56], ebx + mov esi, sockets + add esi, eax + add esi, 56 + call inc_inet_esi ; RCV.NXT + mov ebx, [eax + sockets + 36] ; ISS + mov [eax + sockets + 48], ebx ; SND.NXT + + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je stl_exit + + push eax + mov bl, 0x12 ; SYN + ACK + mov ecx, 0 + mov esi, 0 + + call buildTCPPacket + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne stl_notlocal + mov eax, IPIN_QUEUE + +stl_notlocal: + ; Send it. + pop ebx + call queue + + + mov ebx, TCB_SYN_RECEIVED + mov esi, [sktAddr] + mov [esi + 28], ebx + + ; increament SND.NXT in socket + add esi, 48 + call inc_inet_esi + +stl_exit: + ret + + + +stateTCB_SYN_SENT: + ; We are awaiting an ACK to our SYN, with a SYM + ; Look at control flags - expecting an ACK + mov bl, [edx + 33] + and bl, 0x12 + cmp bl, 0x12 + jnz stss_exit + + mov ebx, TCB_ESTABLISHED + mov esi, [sktAddr] + mov [esi + 28], ebx + + ; Store the recv.nxt field + mov eax, [edx + 24] + + ; Update our recv.nxt field + mov esi, [sktAddr] + add esi, 56 + mov [esi], eax + call inc_inet_esi + + ; Send an ACK + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je stss_exit + + push eax + + mov bl, 0x10 ; ACK + mov ecx, 0 + mov esi, 0 + + call buildTCPPacket + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne stss_notlocal + mov eax, IPIN_QUEUE + +stss_notlocal: + ; Send it. + pop ebx + call queue + +stss_exit: + ret + + + +stateTCB_SYN_RECEIVED: + ; In this case, we are expecting an ACK packet + ; For now, if the packet is an ACK, process it, + ; If not, ignore it + + ; Look at control flags - expecting an ACK + mov bl, [edx + 33] + and bl, 0x10 + cmp bl, 0x10 + jnz stsr_exit + + mov ebx, TCB_ESTABLISHED + mov esi, [sktAddr] + mov [esi + 28], ebx + +stsr_exit: + ret + + + +stateTCB_ESTABLISHED: + ; Here we are expecting data, or a request to close + ; OR both... + + ; Did we receive a FIN or RST? + mov bl, [edx + 33] + and bl, 0x05 + cmp bl, 0 + je ste_chkack + + ; It was a fin or reset. + + ; Remove resend entries from the queue - I dont want to send any more data + pusha + + mov ebx, [sktAddr] + sub ebx, sockets + shr ebx, 12 ; get skt # + + mov esi, resendQ + mov ecx, 0 + +ste001: + cmp ecx, NUMRESENDENTRIES + je ste003 ; None left + cmp [esi], bl + je ste002 ; found one + inc ecx + add esi, 4 + jmp ste001 + +ste002: + dec dword [arp_rx_count] ; ************ TEST ONLY! + + mov [esi], byte 0xFF + jmp ste001 + +ste003: + popa + + ; was it a reset? + mov bl, [edx + 33] + and bl, 0x04 + cmp bl, 0x04 + jne ste003a + + mov esi, [sktAddr] + mov ebx, TCB_CLOSED + mov [esi + 28], ebx + jmp ste_exit + +ste003a: + ; Send an ACK to that fin, and enter closewait state + + mov esi, [sktAddr] + mov ebx, TCB_CLOSE_WAIT + mov [esi + 28], ebx + add esi, 56 + mov eax, [esi] ; save original + call inc_inet_esi + ;; jmp ste_ack - NO, there may be data + +ste_chkack: + ; Check that we received an ACK + mov bl, [edx + 33] + and bl, 0x10 + cmp bl, 0x10 + jnz ste_exit + + + ; TODO - done, I think! + ; First, look at the incoming window. If this is less than or equal to 1024, + ; Set the socket window timer to 1. This will stop an additional packets being + ; queued. + ; ** I may need to tweak this value, since I do not know how many packets are already queued + mov ch, [edx + 34] + mov cl, [edx + 35] + cmp cx, 1024 + ja ste004 + + mov ecx, [sktAddr] + mov [ecx+72], dword 1 + +ste004: + + ; OK, here is the deal + ; My recv.nct field holds the seq of the expected next rec byte + ; if the recevied sequence number is not equal to this, do not + ; increment the recv.nxt field, do not copy data - just send a + ; repeat ack. + + ; recv.nxt is in dword [edx+24], in inext format + ; recv seq is in [sktAddr]+56, in inet format + ; just do a comparision + mov ecx, [sktAddr] + add ecx, 56 + + cmp [ecx - 56 + 28], dword TCB_CLOSE_WAIT + mov ecx, [ecx] + jne stenofin + mov ecx, eax + +stenofin: + cmp ecx, [edx+24] + jne ste_ack + + + ; Read the data bytes, store in socket buffer + xor ecx, ecx + mov ch, [edx + 2] + mov cl, [edx + 3] + sub ecx, 40 ; Discard 40 bytes of header + + cmp ecx, 0 + jnz ste_data ; Read data, if any + + ; If we had received a fin, we need to ACK it. + mov esi, [sktAddr] + mov ebx, [esi + 28] + cmp ebx, TCB_CLOSE_WAIT + jz ste_ack + jnz ste_exit + +ste_data: + push ecx + mov esi, [sktAddr] + + add [esi + 24], ecx ; increment the count of bytes in buffer + + mov eax, [esi + 4] ; get socket owner PID + push eax + + mov eax, [esi + 24] ; get # of bytes already in buffer + + ; point to the location to store the data + add esi, eax + sub esi, ecx + add esi, SOCKETHEADERSIZE + + add edx, 40 ; edx now points to the data + mov edi, esi + mov esi, edx + + cld + rep movsb ; copy the data across + + ; flag an event to the application + pop eax + mov ecx,1 + mov esi,0x3020+0x4 + +news: + cmp [esi],eax + je foundPID1 + inc ecx + add esi,0x20 + cmp ecx,[0x3004] + jbe news + +foundPID1: + shl ecx,8 + or dword [ecx+0x80000+0xA8],dword 10000000b ; stack event + + pop ecx + + ; Update our recv.nxt field + mov esi, [sktAddr] + add esi, 56 + call add_inet_esi + +ste_ack: + ; Send an ACK + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je ste_exit + + push eax + + mov bl, 0x10 ; ACK + mov ecx, 0 + mov esi, 0 + + call buildTCPPacket + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne ste_notlocal + mov eax, IPIN_QUEUE +ste_notlocal: + + ; Send it. + pop ebx + call queue + +ste_exit: + ret + + + +stateTCB_FIN_WAIT_1: + ; We can either receive an ACK of a fin, or a fin + mov bl, [edx + 33] + and bl, 0x10 + cmp bl, 0x10 + jnz stfw1_001 + + ; It was an ACK + mov esi, [sktAddr] + mov ebx, TCB_FIN_WAIT_2 + mov [esi + 28], ebx + jmp stfw1_exit + +stfw1_001: + ; It must be a fin then + mov esi, [sktAddr] + mov ebx, TCB_CLOSING + mov [esi + 28], ebx + add esi, 56 + call inc_inet_esi + + ; Send an ACK + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je stfw1_exit + + push eax + + mov bl, 0x10 ; ACK + mov ecx, 0 + mov esi, 0 + + call buildTCPPacket + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne stfw1_notlocal + mov eax, IPIN_QUEUE + +stfw1_notlocal: + ; Send it. + pop ebx + call queue + +stfw1_exit: + ret + + + +stateTCB_FIN_WAIT_2: + mov esi, [sktAddr] + + ; Get data length + xor ecx, ecx + mov ch, [edx+2] + mov cl, [edx+3] + sub ecx, 40 + + mov bl, [edx + 33] + and bl, 0x01 + cmp bl, 0x01 + jne stfw2001 + + ; Change state, as we have a fin + mov ebx, TCB_TIME_WAIT + mov [esi + 28], ebx + + inc ecx ; FIN is part of the sequence space + +stfw2001: + add esi, 56 + call add_inet_esi + + ; Send an ACK + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je stfw2_exit + + push eax + + mov bl, 0x10 ; ACK + mov ecx, 0 + mov esi, 0 + + call buildTCPPacket + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [ sktAddr ] + mov ecx, [ ecx + 16 ] + cmp edx, ecx + jne stfw2_notlocal + mov eax, IPIN_QUEUE + +stfw2_notlocal: + ; Send it. + pop ebx + call queue + + ; Only delete the socket if we received the FIN + + mov bl, [edx + 33] + and bl, 0x01 + cmp bl, 0x01 + jne stfw2_exit + +; mov edi, [sktAddr] + + ; delete the socket. Should really wait for 2MSL +; xor eax, eax +; mov ecx,SOCKETHEADERSIZE +; cld +; rep stosb + +stfw2_exit: + ret + + + +stateTCB_CLOSE_WAIT: + ; Intentionally left empty + ; socket_close_tcp handles this + ret + + + +stateTCB_CLOSING: + ; We can either receive an ACK of a fin, or a fin + mov bl, [edx + 33] + and bl, 0x10 + cmp bl, 0x10 + jnz stc_exit + + ; It was an ACK + + mov edi, [sktAddr] + + ; delete the socket + xor eax, eax + mov ecx,SOCKETHEADERSIZE + cld + rep stosb + +stc_exit: + ret + + + +stateTCB_LAST_ACK: + ; Look at control flags - expecting an ACK + mov bl, [edx + 33] + and bl, 0x10 + cmp bl, 0x10 + jnz stla_exit + + mov edi, [sktAddr] + + ; delete the socket + xor eax, eax + mov ecx,SOCKETHEADERSIZE + cld + rep stosb + +stla_exit: + ret + + + +stateTCB_TIME_WAIT: + ret + + + +stateTCB_CLOSED: + ret diff --git a/trunk/network/udp.inc b/trunk/network/udp.inc new file mode 100644 index 000000000..1ac2d4a3a --- /dev/null +++ b/trunk/network/udp.inc @@ -0,0 +1,137 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; UDP.INC ;; +;; ;; +;; UDP Processes for Menuet OS TCP/IP stack ;; +;; ;; +;; Version 0.3 29 August 2002 ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;******************************************************************* +; Interface +; +; udp_rx Handles received IP packets with the UDP protocol +; +;******************************************************************* + + + + +;*************************************************************************** +; Function +; udp_rx +; +; Description +; UDP protocol handler +; This is a kernel function, called by ip_rx +; IP buffer address given in edx +; Free up (or re-use) IP buffer when finished +; +;*************************************************************************** +udp_rx: + push eax + + ; First validate the header & checksum. Discard buffer if error + + ; Look for a socket where + ; IP Packet UDP Destination Port = local Port + ; IP Packet SA = Remote IP + + movzx ebx, word [edx + 22] ; get the local port from + ; the IP packet's UDP header + mov eax, SOCKETBUFFSIZE * NUM_SOCKETS + mov ecx, NUM_SOCKETS + +fs1: + sub eax, SOCKETBUFFSIZE + cmp [eax + sockets + 12], bx ; bx will hold the 'wrong' value, + ; but the comparision is correct + loopnz fs1 ; Return back if no match + jz fs_done + + ; No match, so exit + jmp udprx_001 + +fs_done: + ; For dhcp, we must allow any remote server to respond. + ; I will accept the first incoming response to be the one + ; I bind to, if the socket is opened with a destination IP address of + ; 255.255.255.255 + mov ebx, [eax + sockets + 16] + cmp ebx, 0xffffffff + je udprx_002 + + mov ebx, [edx + 12] ; get the Source address from the IP packet + cmp [eax + sockets + 16], ebx + jne udprx_001 ; Quit if the source IP is not valid + +udprx_002: + ; OK - we have a valid UDP packet for this socket. + ; First, update the sockets remote port number with the incoming msg + ; - it will have changed + ; from the original ( 69 normally ) to allow further connects + movzx ebx, word [edx + 20] ; get the UDP source port + ; ( was 69, now new ) + mov [eax + sockets + 20], bx + + ; Now, copy data to socket. We have socket address as [eax + sockets]. + ; We have IP packet in edx + + ; get # of bytes in ecx + movzx ecx, byte [edx + 3] ; total length of IP packet. Subtract + mov ch, byte [edx + 2] ; 20 + 8 gives data length + sub ecx, 28 + + mov ebx, eax + add ebx, sockets ; ebx = address of actual socket + + mov eax, [ebx+ 4] ; get socket owner PID + push eax + + mov eax, [ebx + 24] ; get # of bytes already in buffer + add [ebx + 24], ecx ; increment the count of bytes in buffer + + ; point to the location to store the data + add ebx, eax + add ebx, SOCKETHEADERSIZE + + ; ebx = location for first byte, ecx has count, + ; edx points to data + + add edx, 28 ; edx now points to the data + mov edi, ebx + mov esi, edx + + cld + rep movsb ; copy the data across + + ; flag an event to the application + pop eax + mov ecx,1 + mov esi,0x3020+0x4 + +newsearch: + cmp [esi],eax + je foundPID + inc ecx + add esi,0x20 + cmp ecx,[0x3004] + jbe newsearch + +foundPID: + shl ecx,8 + or dword [ecx+0x80000+0xA8],dword 10000000b ; stack event + + mov [check_idle_semaphore],200 + +udprx_001: + pop eax + call freeBuff ; Discard the packet + ret + \ No newline at end of file diff --git a/trunk/sound/playnote.inc b/trunk/sound/playnote.inc new file mode 100644 index 000000000..79548434a --- /dev/null +++ b/trunk/sound/playnote.inc @@ -0,0 +1,135 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; PLAYNOTE.INC version 1.1 22 November 2003 ;; +;; ;; +;; Player Notes for Speaker PC ;; +;; subfunction #55 from function #55 Menuet OS ;; +;; ;; +;; Copyright 2003 VaStaNi ;; +;; vastani@ukr.net ;; +;; >>>- SIMPLY - QUICKLY - SHORTLY -<<< ;; +;; ;; +;; Note: playnote.txt ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +kontrOctave dw 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562 + dw 0x3264, 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF +memAdrNote dd 0 +pidProcessNote dd 0 +slotProcessNote dd 0 +count_timer_Note dd 1 +mem8253r42 dw 0 +countDelayNote db 0 + +playNote: +; jmp NotPlayNotes + mov esi, [memAdrNote] + or esi, esi ; ESI = 0 ? - OFF Notes Play ? + jz NotPlayNotes ; if ESI = 0 -> ignore play pocedure + cmp eax, [count_timer_Note] + jb NotPlayNotes + push eax + inc eax + mov [count_timer_Note], eax + mov al, [countDelayNote] + dec al ; decrement counter Delay for Playing Note + jz NewLoadNote@Delay + cmp al, 0xFF ; this is first Note Play ? + jne NextDelayNote + ;This is FIRST Note, save counter channel 2 chip 8253 + mov al, 0xB6 ; control byte to timer chip 8253 + out 0x43, al ; Send it to the control port chip 8253 + in al, 0x42 ; Read Lower byte counter channel 2 chip 8253 + mov ah, al ; AH = Lower byte counter channel 2 + in al, 0x42 ; Read Upper byte counter channel 2 chip 8253 + mov [mem8253r42], ax ; Save counter channel 2 timer chip 8253 + NewLoadNote@Delay: + cld +; lodsb ; load AL - counter Delay + call ReadNoteByte + or al, al ; THE END ? + jz EndPlayNote + cmp al, 0x81 + jnc NoteforOctave + mov [countDelayNote], al +; lodsw ; load AX - counter for Note! + call ReadNoteByte + mov ah,al + call ReadNoteByte + xchg al,ah + jmp pokeNote + + EndPlayNote: ; THE END Play Notes! + in al, 0x61 ; Get contents of system port B chip 8255 + and al, 0xFC ; Turn OFF timer and speaker + out 0x61, al ; Send out new values to port B chip 8255 + mov ax, [mem8253r42] ; memorize counter channel 2 timer chip 8253 + xchg al, ah ; reverse byte in word + out 0x42, al ; restore Lower byte counter channel 2 + mov al, ah ; AL = Upper byte counter channel 2 + out 0x42, al ; restore Upper byte channel 2 + xor eax, eax ; EAX = 0 + mov [memAdrNote], eax ; clear header control Delay-Note string + NextDelayNote: + mov [countDelayNote], al ; save new counter delay Note + pop eax + NotPlayNotes: + RET + + NoteforOctave: + sub al, 0x81 ; correction value for delay Note + mov [countDelayNote], al ; save counter delay this new Note +; lodsb ; load pack control code + call ReadNoteByte + cmp al, 0xFF ; this is PAUSE ? + jne packCode ; no, this is PACK CODE + in al, 0x61 ; Get contents of system port B chip 8255 + and al, 0xFC ; Turn OFF timer and speaker + out 0x61, al ; Send out new values to port B chip 8255 + jmp saveESI + + packCode: + mov cl, al ; save code + and al, 0xF ; clear upper bits + dec al ; correction + add al, al ; transform number to offset constant + movsx eax, al ; EAX - offset + add eax, dword kontrOctave ; EAX - address from constant + mov ax, [eax] ; read constant + shr cl, 4 ; transform for number Octave + shr ax, cl ; calculate from Note this Octave! + pokeNote: + out 0x42, al ; Lower byte Out to channel 2 timer chip 8253 + mov al, ah + out 0x42, al ; Upper byte Out to channel 2 timer chip 8253 + in al, 0x61 ; Get contents of system port B chip 8255 + or al, 3 ; Turn ON timer and speaker + out 0x61, al ; Send out new values to port B chip 8255 + saveESI: +; mov [memAdrNote], esi ; save new header control Delay-Note string + pop eax + RET +ReadNoteByte: +;result: +; al - note + push eax + push ebx + push ecx + push edx + mov eax,[pidProcessNote] + call pid_to_slot + test eax,eax + jz .failed + lea ebx,[esp+12] + mov ecx,1 + mov edx,[memAdrNote] + inc [memAdrNote] + call read_process_memory +.failed: + pop edx + pop ecx + pop ebx + pop eax + ret +;------------------- END CODE ------------------- diff --git a/trunk/sound/sb16.inc b/trunk/sound/sb16.inc new file mode 100644 index 000000000..21f6f70dc --- /dev/null +++ b/trunk/sound/sb16.inc @@ -0,0 +1,350 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SB16.INC ;; +;; ;; +;; Sound Blaster 16 functions for MenuetOS ;; +;; ;; +;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; - 11.07.2002 8 bit stereo mode - Ville Turjanmaa ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +SB16_load_music equ 0xc0000000 +SB16_play_music equ 0xc0000001 +DMAPage equ 0x2A +Rate equ 44100 +SB16Buffer equ 0x2A0000 +SB16_Status equ SB16Buffer+65536 + +iglobal + sound_data_format dd 0x1 + sound_data_length dd 65536 + sound_data_freq dd 44100 +endg + +sound_interface: + + cmp eax,0 ; Load data + jne no_SB16_load_music + mov edi,[0x3010] + add edi,0x10 + add ebx,[edi] + call code_SB16_load_music + ret + no_SB16_load_music: + + cmp eax,1 ; Play data + jne no_SB16_play_music + call code_SB16_play_music + ret + no_SB16_play_music: + + cmp eax,2 ; Set data formats + jne no_SB16_data_format + cmp ebx,0 ; ebx=0 play format + jne no_sound_format + mov [sound_data_format],ecx ; 1=8b mono, 2=8b stereo + ret + no_sound_format: + cmp ebx,1 ; ebx=1 data length + jne no_sound_length + mov [sound_data_length],ecx ; + ret + no_sound_length: + cmp ebx,2 ; ebx=2 sound data frequency + jne no_sound_freq + mov [sound_data_freq],ecx + ret + no_sound_freq: + ret + + no_SB16_data_format: + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + cmp eax, edi ; this is subfunction #55 ? + jne retFunc55 ; if no then return. + cmp byte [sound_flag],0 + jne retFunc55 + movzx eax, byte [countDelayNote] + or al, al ; player is busy ? + jnz retFunc55 ; return counter delay Note +; mov eax, [0x3010] +; mov eax, [eax+0x10] ; address application im memory +; add eax, edx ; add offset Delay-Note string +; mov [memAdrNote], eax + mov [memAdrNote],edx + mov eax,[0x3010] + mov eax,[eax+4] + mov [pidProcessNote],eax + xor eax, eax ; Ok! EAX = 0 + retFunc55: + mov [esp+36], eax ; return value EAX for application +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + ret + + + + +code_SB16_play_music: + + cmp [sound_data_format],1 + jne no_sound_8bm + call sb_play_8b_mono + ret + no_sound_8bm: + + cmp [sound_data_format],2 + jne no_sound_8bs + call sb_play_8b_stereo + ret + no_sound_8bs: + + ret + + + + + +Blaster_command: + + push eax + push ecx + push edx + + mov dx,word [sb16] + add dx,0xc + mov cx,1000 + bcl1: + in al,dx + and al,128 + jz bcl2 + loop bcl1 + bcl2: + mov al,[esp+8] + mov dx,[esp+0] + add dx,word [sb16] + out dx,al + + pop edx + pop ecx + pop eax + + ret + + +sb_play_8b_stereo: + + pusha + + call sb_set_dma + + call sb_set_stereo + + mov dx,0xc + mov al,0xa8 + call Blaster_command + + mov al,0x40 + call Blaster_command + + mov al,245 + call Blaster_command + + mov al,0x48 + call Blaster_command + + mov al,0xff + call Blaster_command + call Blaster_command + + mov al,0x91 + call Blaster_command + + popa + ret + + + +sb_set_stereo: + + push eax + push edx + + call sb_wait + + mov dx,word [sb16] + add dx,0x4 + mov al,0xe + out dx,al + inc dx + in al,dx + and al,253 + or al,2 ; stereo + out dx,al + + pop edx + pop eax + ret + + + +code_SB16_load_music: + + cmp byte [SB16_Status],1 + je nol + mov edi,SB16Buffer + mov esi,ebx + mov ecx,65536/4 + cld + rep movsd +nol: ret + + +iglobal + dma_table db 0x87,0x83,0x81,0x82 +endg + + + +;-------------------------------- +; program dma +;-------------------------------- + +sb_set_dma: + + pusha + + mov eax,[sound_dma] + add eax,4 + out 0xa,al + + mov al,0 + out 0xc,al + + mov eax,[sound_dma] + add eax,0x48 + out 0xb,al + + mov edx,[sound_dma] + shl edx,1 + mov al,0 + out dx,al + + mov al,0 + out dx,al + + mov edx,[sound_dma] + add edx,dma_table + movzx edx,byte [edx] + mov al,DMAPage + out dx,al + + mov edx,[sound_dma] + shl edx,1 + inc edx + mov eax,[sound_data_length] + dec eax + and eax,0xff + ; mov al,(DataLength-1) and 0xff + out dx,al + + mov eax,[sound_data_length] + dec eax + shr eax,8 + ; mov al,(DataLength-1) shr 8 + out dx,al + + mov eax,[sound_dma] ; DMA + out 0xa,al + + popa + ret + + + +sb_play_8b_mono: + + + call sb_set_dma + + cmp byte [SB16_Status],1 + jne contsb16 + jmp retserve + contsb16: + + mov dx,word [sb16] + add dx,4 + mov ecx,[sound_dma] + mov ax,0x01 + shl ax,cl + shl ax,8 + add ax,0x81 + out dx,ax + + mov ax,0f280h ;enable irq5 + out dx,ax + + +adr1_SB: mov dx,word [sb16] + add dx,0ch + in al,dx + and al,080h + jnz adr1_SB + + call sb_set_stereo + + mov al,0d1h + out dx,al + + + mov dx,word [sb16] + add dx,0ch + + call sb_wait + + mov al,40h ; Rate + out dx,al + call sb_wait + mov al,256-1000000/Rate + out dx,al + + call sb_wait + + mov al,14h ; Datalength + out dx,al + call sb_wait + + mov eax,[sound_data_length] + dec eax + and eax,0xff + ;mov al,(DataLength-1) and 0xff + out dx,al + call sb_wait + mov eax,[sound_data_length] + dec eax + shr eax,8 + ;mov al,(DataLength-1) shr 8 + out dx,al + + retserve: + + ret + + +sb_wait: in al,dx ;wait + and al,080h + jnz sb_wait + + ret + + + + +;**************************************** +; END CODE SB16 by Minazzi Paolo +;*************************************** diff --git a/trunk/video/vesa12.inc b/trunk/video/vesa12.inc new file mode 100644 index 000000000..bc82b4033 --- /dev/null +++ b/trunk/video/vesa12.inc @@ -0,0 +1,973 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; VESA12.INC ;; +;; ;; +;; Vesa 1.2 functions for MenuetOS ;; +;; ;; +;; Copyright 2002 Ville Turjanmaa ;; +;; ;; +;; quickcode@mail.ru - bankswitch for S3 cards ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; A complete video driver should include the following types of function +; +; Putpixel +; Getpixel +; +; Drawimage +; Drawbar +; +; Drawbackground +; +; +; Modifying the set_bank -function is mostly enough +; for different Vesa 1.2 setups. + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!{ + +; set_bank modified by kmeaw +set_bank: +cli +cmp al,[0xfff2] +je retsb +mov [0xfff2],al +push ax +push dx +push cx +mov cl, al +mov dx, 0x3D4 +mov al, 0x38 +out dx, al ;CR38 Register Lock 1 ;Note: Traditionally 48h is used to + ;unlock and 00h to lock +inc dx +mov al, 0x48 +out dx, al ;3d5 -? +dec dx +mov al, 0x31 +out dx, al ;CR31 Memory Configuration Register +;0 Enable Base Address Offset (CPUA BASE). Enables bank operation if set, ;disables if clear. +;4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index 51h, +;for the 864/964 see index 69h. + +inc dx +in al, dx +dec dx +mov ah, al +mov al, 0x31 +out dx, ax +mov al, ah +or al, 9 +inc dx +out dx, al +dec dx +mov al, 0x35 +out dx, al ;CR35 CRT Register Lock +inc dx +in al, dx +dec dx +and al, 0xF0 +mov ch, cl +and ch, 0x0F +or ch, al +mov al, 0x35 +out dx, al +inc dx +mov al, ch +out dx, ax +dec dx +mov al, 0x51 ;Extended System Control 2 Register +out dx, al +inc dx +in al, dx +dec dx +and al, 0xF3 +shr cl, 2 +and cl, 0x0C +or cl, al +mov al, 0x51 +out dx, al +inc dx +mov al, cl +out dx, al +dec dx +mov al, 0x38 +out dx, al +inc dx +xor al, al +out dx, al +dec dx +pop cx +pop dx +pop ax +retsb: +sti +ret + +;Set bank function for Intel 810/815 chipsets +; *****Modified by Protopopius, Russia.***** +; ********* http://menuetos.hut.ru ************** +; ************************************************ +; +;set_bank: +;cli +;cmp al,[0xfff2] +;je retsb +;mov [0xfff2],al +;push ax +;push dx +;mov dx,3CEh +;mov ah,al ; Save value for later use +;mov al,10h ; Index GR10 (Address Mapping) +;out dx,al ; Select GR10 +;inc dl +;mov al,3 ; Set bits 0 and 1 (Enable linear page mapping) +;out dx,al ; Write value +;dec dl +;mov al,11h ; Index GR11 (Page Selector) +;out dx,al ; Select GR11 +;inc dl +;mov al,ah ; Write address +;out dx,al ; Write the value +;pop dx +;pop ax +;retsb: +;sti +;ret + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} + +;set_bank: +; cli +; cmp al,[0xfff2] +; je retsb +; mov [0xfff2],al +; push ax +; push dx +; mov ah,al +; mov dx,0x03D4 +; mov al,0x39 +; out dx,al +; inc dl +; mov al,0xA5 +; out dx,al +; dec dl +; mov al,6Ah +; out dx,al +; inc dl +; mov al,ah +; out dx,al +; dec dl +; mov al,0x39 +; out dx,al +; inc dl +; mov al,0x5A +; out dx,al +; dec dl +; pop dx +; pop ax +; +; retsb: +; ret + + +vesa12_drawbackground: + + call [disable_mouse] + + push eax + push ebx + push ecx + push edx + + xor edx,edx + mov eax,dword[WinMapAddress-8] + mov ebx,dword[WinMapAddress-4] + mul ebx + mov ebx,3 + mul ebx + mov [imax],eax + mov eax,[draw_data+32+0] + mov ebx,[draw_data+32+4] + mov edi,0 ;no force + + v12dp3: + + push eax + push ebx + mov esi,0x300000 + + cmp [WinMapAddress-12],dword 1 ; tiled background + jne no_vesa12_tiled_bgr + + push edx + + xor edx,edx + mov ecx,[WinMapAddress-8] + div ecx + mov eax,edx + + push eax + mov eax,ebx + xor edx,edx + mov ecx,[WinMapAddress-4] + div ecx + mov ebx,edx + pop eax + + pop edx + + no_vesa12_tiled_bgr: + + cmp [WinMapAddress-12],dword 2 ; stretched background + jne no_vesa12_stretched_bgr + + push edx + + imul eax,dword [WinMapAddress-8] + xor edx,edx + mov ecx,[0xfe00] + inc ecx + div ecx + + push eax + mov eax,ebx + imul eax,dword [WinMapAddress-4] + xor edx,edx + mov ecx,[0xfe04] + inc ecx + div ecx + mov ebx,eax + pop eax + + pop edx + + no_vesa12_stretched_bgr: + + + push eax + mov eax,ebx + xor edx,edx + mov ebx,[WinMapAddress-8] + add ebx,[WinMapAddress-8] + add ebx,[WinMapAddress-8] + mul ebx + mov esi,eax + pop eax + add esi,eax + add esi,eax + add esi,eax + add esi,0x300000 + pop ebx + pop eax + + v12di4: + + mov ecx,[esi] + pusha + mov esi,eax + mov edi,ebx + mov eax,[0xfe00] + add eax,1 + mul ebx + add eax,esi + add eax,WinMapAddress + cmp [eax],byte 1 + jnz v12nbgp + mov eax,[0xfe08] + mov ebx,edi + mul ebx + add eax,esi + add eax,esi + add eax,esi + cmp [0xFBF1],byte 24 + jz v12bgl3 + add eax,esi + + v12bgl3: + + push ebx + push eax + + sub eax,[0xfe80] + + shr eax,16 + call set_bank + pop eax + and eax,65535 + add eax,0xa0000 + pop ebx + + mov [eax],cx + add eax,2 + shr ecx,16 + mov [eax],cl + sti + + v12nbgp: + + popa + add esi,3 + inc eax + cmp eax,[draw_data+32+8] + jg v12nodp31 + jmp v12dp3 + + v12nodp31: + + mov eax,[draw_data+32+0] + inc ebx + cmp ebx,[draw_data+32+12] + jg v12dp4 + jmp v12dp3 + + v12dp4: + + pop edx + pop ecx + pop ebx + pop eax + ret + + +vesa12_drawbar: + + call [disable_mouse] + +;; mov [novesachecksum],dword 0 + sub edx,ebx + sub ecx,eax + push esi + push edi + push eax + push ebx + push ecx + push edx + mov ecx,[0x3010] + add eax,[ecx-twdw] + add ebx,[ecx-twdw+4] + push eax + mov eax,ebx ; y + mov ebx,[0xfe08] + mul ebx + pop ecx + add eax,ecx ; x + add eax,ecx + add eax,ecx + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x start + jz dbpi2412 + add eax,ecx + + dbpi2412: + + add eax,[0xfe80] + mov edi,eax + + ; x size + + mov eax,[esp+4] ; [esp+6] + mov ecx,eax + add ecx,eax + add ecx,eax + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x size + jz dbpi24312 + add ecx,eax + + dbpi24312: + + mov ebx,[esp+0] + + ; check limits ? + + push eax + push ecx + mov eax,[0x3010] + mov ecx,[eax+draw_data-0x3000+0] + cmp ecx,0 + jnz dbcblimitlset12 + mov ecx,[eax+draw_data-0x3000+4] + cmp ecx,0 + jnz dbcblimitlset12 + mov ecx,[eax+draw_data-0x3000+8] + cmp ecx,[0xfe00] + jnz dbcblimitlset12 + mov ecx,[eax+draw_data-0x3000+12] + cmp ecx,[0xfe04] + jnz dbcblimitlset12 + pop ecx + pop eax + push dword 0 + jmp dbcblimitlno12 + + dbcblimitlset12: + + pop ecx + pop eax + push dword 1 + + dbcblimitlno12: + + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? + jz dbpi24bit12 + jmp dbpi32bit12 + + +; DRAWBAR 24 BBP + + +dbpi24bit12: + + push eax + push ebx + push edx + mov eax,ecx + mov ebx,3 + div ebx + mov ecx,eax + pop edx + pop ebx + pop eax + cld + + dbnewpi12: + + push ebx + push edi + push ecx + + xor edx,edx + mov eax,edi + sub eax,[0xfe80] + mov ebx,3 + div ebx + add eax,WinMapAddress + mov ebx,[0x3010] + movzx ebx,byte[ebx+0xe] + cld + + dbnp2412: + + mov dl,[eax] + push eax + push ecx + cmp dl,bl + jnz dbimp24no12 + cmp [esp+5*4],dword 0 + jz dbimp24yes12 +; call dbcplimit +; jnz dbimp24no12 + + dbimp24yes12: + + push edi + mov eax,edi + sub eax,[0xfe80] + shr eax,16 + call set_bank + and edi,0xffff + add edi,0xa0000 + mov eax,[esp+8+3*4+16+4+4] + stosw + shr eax,16 + stosb + sti + pop edi + add edi,3 + pop ecx + pop eax + inc eax + loop dbnp2412 + jmp dbnp24d12 + + dbimp24no12: + + pop ecx + pop eax + cld + add edi,3 + inc eax + loop dbnp2412 + + dbnp24d12: + + mov eax,[esp+3*4+16+4] + test eax,0x80000000 + jz nodbgl2412 + cmp al,0 + jz nodbgl2412 + dec eax + mov [esp+3*4+16+4],eax + + nodbgl2412: + + pop ecx + pop edi + pop ebx + add edi,[0xfe08] + dec ebx + jz dbnonewpi12 + jmp dbnewpi12 + + dbnonewpi12: + + add esp,7*4 + + ret + + +; DRAWBAR 32 BBP + + + dbpi32bit12: + + cld + shr ecx,2 + + dbnewpi3212: + + push ebx + push edi + push ecx + + mov eax,edi + sub eax,[0xfe80] + shr eax,2 + add eax,WinMapAddress + mov ebx,[0x3010] + movzx ebx,byte[ebx+0xe] + cld + + dbnp3212: + + mov dl,[eax] + push eax + push ecx + cmp dl,bl + jnz dbimp32no12 + cmp [esp+5*4],dword 0 + jz dbimp32yes12 +; call dbcplimit +; jnz dbimp32no12 + + dbimp32yes12: + + push edi + mov eax,edi + sub eax,[0xfe80] + shr eax,16 + call set_bank + and edi,0xffff + add edi,0xa0000 + mov eax,[esp+8+3*4+16+4+4] + stosw + shr eax,16 + stosb + sti + pop edi + add edi,4 + inc ebp + pop ecx + pop eax + inc eax + loop dbnp3212 + jmp dbnp32d12 + + dbimp32no12: + + pop ecx + pop eax + inc eax + add edi,4 + inc ebp + loop dbnp3212 + + dbnp32d12: + + mov eax,[esp+12+16+4] + test eax,0x80000000 + jz nodbgl3212 + cmp al,0 + jz nodbgl3212 + dec eax + mov [esp+12+16+4],eax + + nodbgl3212: + + pop ecx + pop edi + pop ebx + add edi,[0xfe08] + dec ebx + jz nodbnewpi3212 + jmp dbnewpi3212 + + nodbnewpi3212: + + add esp,7*4 + ret + + +Vesa12_putpixel24: + + mov edi,eax ; x + mov eax,ebx ; y + lea edi,[edi+edi*2] + mov ebx,[0xfe08] + mul ebx + add edi,eax + mov eax,edi + shr eax,16 + call set_bank + and edi,65535 + add edi,0xa0000 + mov eax,[esp+28] + stosw + shr eax,16 + mov [edi],al + sti + ret + + + +Vesa12_putpixel32: + + mov edi,eax ; x + mov eax,ebx ; y + shl edi,2 + mov ebx,[0xfe08] + mul ebx + add edi,eax + mov eax,edi + shr eax,16 + call set_bank + and edi,65535 + add edi,0xa0000 + mov ecx,[esp+28] + mov [edi],ecx + sti + ret + + +Vesa12_getpixel24: + + mov edi,eax ; x + mov eax,ebx ; y + lea edi,[edi+edi*2] + mov ebx,[0xfe08] + mul ebx + add edi,eax + mov eax,edi + shr eax,16 + call set_bank + and edi,65535 + add edi,0xa0000 + mov ecx,[edi] + and ecx,255*256*256+255*256+255 + sti + ret + + +Vesa12_getpixel32: + + mov edi,eax ; x + mov eax,ebx ; y + shl edi,2 + mov ebx,[0xfe08] + xor edx,edx + mul ebx + add edi,eax + mov eax,edi + shr eax,16 + call set_bank + and edi,65535 + add edi,0xa0000 + mov ecx,[edi] + and ecx,255*256*256+255*256+255 + sti + + ret + + + +vesa12_putimage: + +; mov ebx,image +; mov ecx,320*65536+240 +; mov edx,20*65536+20 + + call [disable_mouse] + + mov [novesachecksum],dword 0 + push esi + push edi + push eax + push ebx + push ecx + push edx + movzx eax,word [esp+2] + movzx ebx,word [esp+0] + mov ecx,[0x3010] + add eax,[ecx-twdw] + add ebx,[ecx-twdw+4] + push eax + mov eax,ebx ; y + mov ebx,[0xfe08] + mul ebx + pop ecx + add eax,ecx ; x + add eax,ecx + add eax,ecx + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x start + jz pi2412 + add eax,ecx + + pi2412: + + add eax,[0xfe80] + mov edi,eax + + ; x size + + movzx eax,word [esp+6] + mov ecx,eax + add ecx,eax + add ecx,eax + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? - x size + jz pi24312 + add ecx,eax + + pi24312: + + mov esi,[esp+8] + movzx ebx,word [esp+4] + + ; check limits while draw ? + + push eax + push ecx + mov eax,[0x3010] + mov ecx,[eax+draw_data-0x3000+0] + cmp ecx,0 + jnz dbcblimitlset212 + mov ecx,[eax+draw_data-0x3000+4] + cmp ecx,0 + jnz dbcblimitlset212 + mov ecx,[eax+draw_data-0x3000+8] + cmp ecx,[0xfe00] + jnz dbcblimitlset212 + mov ecx,[eax+draw_data-0x3000+12] + cmp ecx,[0xfe04] + jnz dbcblimitlset212 + pop ecx + pop eax + push dword 0 + jmp dbcblimitlno212 + + dbcblimitlset212: + + pop ecx + pop eax + push dword 1 + + dbcblimitlno212: + + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? + jz pi24bit12 + jmp pi32bit12 + + pi24bit12: + + cld + push eax + push ebx + push edx + xor edx,edx + mov eax,ecx + mov ebx,3 + div ebx + mov ecx,eax + pop edx + pop ebx + pop eax + + newpi12: + + push edi + push esi + push ecx + push ebx + + xor edx,edx + mov eax,edi + sub eax,[0xfe80] + mov ebx,3 + div ebx + add eax,WinMapAddress + mov ebx,[0x3010] + mov bl,[ebx+0xe] + mov bh,[esp+4*4] + + np2412: + + cmp bl,[eax] + jnz imp24no12 + mov edx,[esi] + cmp bh,0 + jz imp24yes12 +; call dbcplimit +; jnz imp24no12 + + imp24yes12: + + push eax + push edi + mov eax,edi + sub eax,[0xfe80] + shr eax,16 + call set_bank + and edi,0xffff + add edi,0xa0000 + mov [edi],edx + shr edx,2 + mov [edi+2],dl + sti + pop edi + pop eax + + imp24no12: + + inc eax + add esi,3 + add edi,3 + dec ecx + jnz np2412 + + np24d12: + + pop ebx + pop ecx + pop esi + pop edi + + add edi,[0xfe08] + xor eax,eax + mov ax,[esp+4+2+4] + lea eax,[eax+eax*2] + add esi,eax + dec ebx + jz nonewpi12 + jmp newpi12 + + nonewpi12: + + add esp,7*4 + mov eax,0 + ret + + + pi32bit12: + + cld + shr ecx,2 + + newpi3212: + + push edi + push esi + push ecx + push ebx + + mov eax,edi + sub eax,[0xfe80] + shr eax,2 + add eax,WinMapAddress + mov ebx,[0x3010] + mov bl,[ebx+0xe] + mov bh,[esp+4*4] + + np3212: + + cmp bl,[eax] + jnz imp32no12 + mov edx,[esi] + cmp bh,0 + jz imp32yes12 +; call dbcplimit +; jnz imp32no12 + + imp32yes12: + + push eax + push edi + mov eax,edi + sub eax,[0xfe80] + shr eax,16 + call set_bank + and edi,0xffff + add edi,0xa0000 + mov [edi],edx + sti + pop edi + pop eax + + imp32no12: + + inc eax + add esi,3 + add edi,4 + dec ecx + jnz np3212 + + np32d12: + + pop ebx + pop ecx + pop esi + pop edi + + add edi,[0xfe08] + movzx eax,word [esp+4+2+4] + lea eax,[eax+eax*2] + add esi,eax + dec ebx + jz nonewpi3212 + jmp newpi3212 + + nonewpi3212: + + add esp,7*4 + mov eax,0 + ret + + +vesa12_read_screen_pixel: + + and eax,0x3FFFFF + cmp [0xfbf1],byte 24 ; 24 or 32 bpp ? + jz v12rsp24 + mov edi,eax + shl edi,2 + mov eax,edi + shr eax,16 + call set_bank + and edi,65535 + add edi,0xa0000 + mov eax,[edi] + and eax,0x00ffffff + ret + v12rsp24: + + imul eax,3 + mov edi,eax + shr eax,16 + call set_bank + and edi,65535 + add edi,0xa0000 + mov eax,[edi] + and eax,0x00ffffff + ret + + diff --git a/trunk/video/vesa20.inc b/trunk/video/vesa20.inc new file mode 100644 index 000000000..4985bb8c5 --- /dev/null +++ b/trunk/video/vesa20.inc @@ -0,0 +1,1107 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; VESA20.INC ;; +;; ;; +;; Vesa 2.0 functions for MenuetOS ;; +;; ;; +;; Copyright 2002 Ville Turjanmaa ;; +;; Alexey, kgaz@crosswindws.net ;; +;; - Voodoo compatible graphics ;; +;; Juan M. Caravaca ;; +;; - Graphics optimimizations eg. drawline ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; If you're planning to write your own video driver I suggest +; you replace the VESA12.INC file and see those instructions. + +ScreenWidth equ 0xfe00 +ScreenHeight equ 0xfe04 +BytesPerScanLine equ 0xfe08 +LFBAddress equ 0xfe80 +ScreenBPP equ 0xfbf1 +WinMapAddress equ 0x460000 + + + +;************************************************* +; getpixel +; +; in: +; eax = x coordinate +; ebx = y coordinate +; +; ret: +; ecx = 00 RR GG BB + +getpixel: + push eax ebx edx edi + call dword [0xe024] + pop edi edx ebx eax + ret + +Vesa20_getpixel24: + ; eax = x + ; ebx = y + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [eax+eax*2] ; edi = x*3 + add edi, ebx ; edi = x*3+(y*y multiplier) + add edi, [LFBAddress] ; ebx = where pixel is in memory + mov ecx, [edi] + and ecx, 0xffffff + ret + + +Vesa20_getpixel32: + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) + add edi, [LFBAddress] ; ebx = where pixel is in memory + mov ecx, [edi] + and ecx, 0xffffff + ret + +;************************************************* + +virtual at esp + putimg: + .real_sx dd ? + .real_sy dd ? + .image_sx dd ? + .image_sy dd ? + .image_cx dd ? + .image_cy dd ? + .pti dd ? + .abs_cx dd ? + .abs_cy dd ? + .line_increment dd ? + .source_bpp dd ? + .winmap_newline dd ? + .screen_newline dd ? + .stack_data = 4*13 +end virtual + +align 4 +; ebx = pointer +; ecx = size [x|y] +; edx = coordinates [x|y] +vesa20_putimage: + pushad + call [disable_mouse] + + sub esp, putimg.stack_data + + mov [putimg.source_bpp], 3 +; test ebx, 0x80000000 +; jz @f +; inc [putimg.source_bpp] +; @@: +; and ebx, 0x7FFFFFFF + + ; save pointer to image + mov [putimg.pti], ebx + + ; unpack the size + mov eax, ecx + and ecx, 0xFFFF + shr eax, 16 + mov [putimg.image_sx], eax + mov [putimg.image_sy], ecx + + ; unpack the coordinates + mov eax, edx + and edx, 0xFFFF + shr eax, 16 + mov [putimg.image_cx], eax + mov [putimg.image_cy], edx + + ; calculate absolute (i.e. screen) coordinates + mov eax, [0x3010] + mov ebx, [eax-twdw + 0] + add ebx, [putimg.image_cx] + mov [putimg.abs_cx], ebx + mov ebx, [eax-twdw + 4] + add ebx, [putimg.image_cy] + mov [putimg.abs_cy], ebx + + ; real_sx = MIN(wnd_sx-image_cx, image_sx); + mov ebx, [eax-twdw + 8] ; ebx = wnd_sx + sub ebx, [putimg.image_cx] + ja @f + add esp, putimg.stack_data + popad + xor eax, eax + inc eax + ret + @@: + cmp ebx, [putimg.image_sx] + jbe .end_x + mov ebx, [putimg.image_sx] + dec ebx + .end_x: + inc ebx + mov [putimg.real_sx], ebx + + ; init real_sy + mov ebx, [eax-twdw + 12] ; ebx = wnd_sy + sub ebx, [putimg.image_cy] + ja @f + add esp, putimg.stack_data + popad + xor eax, eax + inc eax + ret + @@: + cmp ebx, [putimg.image_sy] + jbe .end_y + mov ebx, [putimg.image_sy] + dec ebx + .end_y: + inc ebx + mov [putimg.real_sy], ebx + + ; line increment + mov eax, [putimg.image_sx] + sub eax, [putimg.real_sx] +;; imul eax, [putimg.source_bpp] + lea eax, [eax + eax * 2] + mov [putimg.line_increment], eax + + ; winmap new line increment + mov eax, [ScreenWidth] + inc eax + sub eax, [putimg.real_sx] + mov [putimg.winmap_newline], eax + + ; screen new line increment + mov eax, [BytesPerScanLine] + mov ecx, [putimg.real_sx] + movzx ebx, byte [ScreenBPP] + shr ebx, 3 + imul ecx, ebx + sub eax, ecx + mov [putimg.screen_newline], eax + + ; pointer to image + mov ecx, [putimg.pti] + + ; pointer to screen + mov edx, [putimg.abs_cy] + imul edx, [BytesPerScanLine] + mov eax, [putimg.abs_cx] + movzx ebx, byte [ScreenBPP] + shr ebx, 3 + imul eax, ebx + add edx, eax + add edx, [LFBAddress] + + ; pointer to pixel map + mov eax, [putimg.abs_cy] + imul eax, [ScreenWidth] + add eax, [putimg.abs_cy] + add eax, [putimg.abs_cx] + add eax, WinMapAddress + xchg eax, ebp + + ; get process number + mov eax, [0x3010] + mov bl, [eax+0xE] + + cmp byte [ScreenBPP], 32 + je put_image_end_32 + +;put_image_end_24: + ;cli ; !!!!!!!!!!!!!!!!!!!!!! + mov edi, [putimg.real_sy] + align 4 + .new_line: + mov esi, [putimg.real_sx] + +; push ebp edx + align 4 + .new_x: + + cmp [ebp], bl + jne .skip + mov eax, [ecx] ; ecx = RRBBGGRR + mov [edx], ax + shr eax, 16 + mov [edx+2], al + .skip: + + add ecx, 3 ;[putimg.source_bpp] + add edx, 3 + inc ebp + + dec esi + jnz .new_x +; pop edx ebp + + add ecx, [putimg.line_increment] + add edx, [putimg.screen_newline] ;[BytesPerScanLine] + add ebp, [putimg.winmap_newline] ;[ScreenWidth] + ;inc ebp + + dec edi + jnz .new_line + .finish: + add esp, putimg.stack_data + popad + xor eax, eax + ;sti ; !!!!!!!!!!!!!!!!!!!!! +ret + +put_image_end_32: + mov edi, [putimg.real_sy] + align 4 + .new_line: + mov esi, [putimg.real_sx] + +; push ebp edx + align 4 + .new_x: + + cmp [ebp], bl + jne .skip + mov eax, [ecx] ; ecx = RRBBGGRR + mov [edx], eax + .skip: + + add ecx, [putimg.source_bpp] + add edx, 4 + inc ebp + + dec esi + jnz .new_x +; pop edx ebp + + add ecx, [putimg.line_increment] + add edx, [putimg.screen_newline] ;[BytesPerScanLine] + add ebp, [putimg.winmap_newline] ;[ScreenWidth] + ;inc ebp + + dec edi + jnz .new_line + .finish: + add esp, putimg.stack_data + popad + xor eax, eax +ret + + +;************************************************* +align 4 +__sys_putpixel: + +; eax = x coordinate +; ebx = y coordinate +; ecx = ?? RR GG BB ; 0x01000000 negation +; edi = 0x00000001 force + +;;; mov [novesachecksum], dword 0 + + pushad + test edi,1 ; force ? + jnz .forced + ; not forced: + call checkpixel + test ecx,ecx + jnz .exit + .forced: + cmp [ScreenWidth], eax + jb .exit + cmp [ScreenHeight], ebx + jb .exit + .ok: + ; check if negation + test ecx,0x01000000 + jz .noneg + call getpixel + not ecx + mov [esp+32-8],ecx + .noneg: + ; OK to set pixel + call dword [0xe020] ; call the real put_pixel function + .exit: + popad + ret + +align 4 +Vesa20_putpixel24: + + ; eax = x + ; ebx = y + + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [eax+eax*2] ; edi = x*3 + mov eax, [esp+32-8+4] + add edi, [LFBAddress] + add edi, ebx ; ebx = where to put pixel in memory + mov [edi], ax + shr eax, 16 + mov [edi+2], al + + ret + + +align 4 +Vesa20_putpixel32: + + ; eax = x + ; ebx = y + + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) + mov eax, [esp+32-8+4] ; eax = color + add edi, [LFBAddress] ; ebx = where to put pixel in memory + mov [edi], eax + + ret + + +;************************************************* + +;align 4 +calculate_edi: + mov edi, ebx + imul edi, [ScreenWidth] + add edi, ebx + add edi, eax +ret + +;************************************************* + +; DRAWLINE + +align 4 +__sys_draw_line: + + call [disable_mouse] + +; draw a line +; eax = HIWORD = x1 +; LOWORD = x2 +; ebx = HIWORD = y1 +; LOWORD = y2 +; ecx = color +; edi = force ? + pusha + +dl_x1 equ esp+20 +dl_y1 equ esp+16 +dl_x2 equ esp+12 +dl_y2 equ esp+8 +dl_dx equ esp+4 +dl_dy equ esp+0 + + xor edx, edx ; clear edx + xor esi, esi ; unpack arguments + xor ebp, ebp + mov si, ax ; esi = x2 + mov bp, bx ; ebp = y2 + shr eax, 16 ; eax = x1 + shr ebx, 16 ; ebx = y1 + + push eax ; save x1 + push ebx ; save y1 + push esi ; save x2 + push ebp ; save y2 + + ; checking x-axis... + sub esi, eax ; esi = x2-x1 + push esi ; save y2-y1 + jl .x2lx1 ; is x2 less than x1 ? + jg .no_vline ; x1 > x2 ? + mov edx, ebp ; else (if x1=x2) + call vline + push edx ; necessary to rightly restore stack frame at .exit + jmp .exit +.x2lx1: + neg esi ; get esi absolute value +.no_vline: + + ; checking y-axis... + sub ebp, ebx ; ebp = y2-y1 + push ebp ; save y2-y1 + jl .y2ly1 ; is y2 less than y1 ? + jg .no_hline ; y1 > y2 ? + mov edx, [dl_x2] ; else (if y1=y2) + call hline + jmp .exit +.y2ly1: + neg ebp ; get ebp absolute value +.no_hline: + + + cmp ebp, esi + jle .x_rules ; |y2-y1| < |x2-x1| ? + + cmp [dl_y2], ebx ; make sure y1 is at the begining + jge .no_reverse1 + + neg dword [dl_dx] + mov edx, [dl_x2] + mov [dl_x2], eax + mov [dl_x1], edx + mov edx, [dl_y2] + mov [dl_y2], ebx + mov [dl_y1], edx + +.no_reverse1: + + mov eax, [dl_dx] + cdq ; extend eax sing to edx + shl eax, 16 ; using 16bit fix-point maths + idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1) + mov edx, ebp ; edx = counter (number of pixels to draw) + mov ebp, 1 *65536 ; <<16 ; ebp = dy = 1.0 + mov esi, eax ; esi = dx + + jmp .y_rules +.x_rules: + + cmp [dl_x2], eax ; make sure x1 is at the begining + jge .no_reverse2 + + neg dword [dl_dy] + mov edx, [dl_x2] + mov [dl_x2], eax + mov [dl_x1], edx + mov edx, [dl_y2] + mov [dl_y2], ebx + mov [dl_y1], edx + +.no_reverse2: + + xor edx, edx + mov eax, [dl_dy] + cdq ; extend eax sing to edx + shl eax, 16 ; using 16bit fix-point maths + idiv esi ; eax = ((y2-y1)*65536)/(x2-x1) + mov edx, esi ; edx = counter (number of pixels to draw) + mov esi, 1 *65536 ;<< 16 ; esi = dx = 1.0 + mov ebp, eax ; ebp = dy + +.y_rules: + + mov eax, [dl_x1] + mov ebx, [dl_y1] + shl eax, 16 + shl ebx, 16 + +align 4 + +.draw: + push eax ebx + shr eax, 16 + shr ebx, 16 + call [putpixel] + pop ebx eax + + add ebx, ebp ; y = y+dy + add eax, esi ; x = x+dx + + dec edx + jnz .draw + + ; force last drawn pixel to be at (x2,y2) + mov eax, [dl_x2] + mov ebx, [dl_y2] + call [putpixel] +.exit: + add esp, 6*4 + popa +ret + + +hline: +; draw an horizontal line +; eax = x1 +; edx = x2 +; ebx = y +; ecx = color +; edi = force ? + push eax edx + + cmp edx, eax ; make sure x2 is above x1 + jge @f + xchg eax, edx + align 4 + @@: + call [putpixel] + inc eax + cmp eax, edx + jle @b + + pop edx eax +ret + + +vline: +; draw a vertical line +; eax = x +; ebx = y1 +; edx = y2 +; ecx = color +; edi = force ? + push ebx edx + + cmp edx, ebx ; make sure y2 is above y1 + jge @f + xchg ebx, edx + align 4 + @@: + call [putpixel] + inc ebx + cmp ebx, edx + jle @b + + pop edx ebx +ret + + +;************************************************* + + +virtual at esp + drbar: + .bar_sx dd ? + .bar_sy dd ? + .bar_cx dd ? + .bar_cy dd ? + .abs_cx dd ? + .abs_cy dd ? + .real_sx dd ? + .real_sy dd ? + .color dd ? + .line_inc_scr dd ? + .line_inc_map dd ? + .stack_data = 4*11 +end virtual + +align 4 +; eax cx +; ebx cy +; ecx xe +; edx ye +; edi color +vesa20_drawbar: + pushad + call [disable_mouse] + + sub esp, drbar.stack_data + + mov [drbar.color], edi + + sub edx, ebx + sub ecx, eax + mov [drbar.bar_sy], edx + mov [drbar.bar_sx], ecx + + mov [drbar.bar_cx], eax + mov [drbar.bar_cy], ebx + + mov edi, [0x3010] + add eax, [edi-twdw + 0] ; win_cx + add ebx, [edi-twdw + 4] ; win_cy + mov [drbar.abs_cx], eax + mov [drbar.abs_cy], ebx + + ; real_sx = MIN(wnd_sx-bar_cx, bar_sx); + mov ebx, [edi-twdw + 8] ; ebx = wnd_sx + sub ebx, [drbar.bar_cx] + ja @f + add esp, drbar.stack_data + popad + xor eax, eax + inc eax + ret + @@: + cmp ebx, [drbar.bar_sx] + jbe .end_x + mov ebx, [drbar.bar_sx] + .end_x: + mov [drbar.real_sx], ebx + + ; real_sy = MIN(wnd_sy-bar_cy, bar_sy); + mov ebx, [edi-twdw + 12] ; ebx = wnd_sy + sub ebx, [drbar.bar_cy] + ja @f + add esp, drbar.stack_data + popad + xor eax, eax + inc eax + ret + @@: + cmp ebx, [drbar.bar_sy] + jbe .end_y + mov ebx, [drbar.bar_sy] + .end_y: + mov [drbar.real_sy], ebx + + ; line_inc_map + mov eax, [ScreenWidth] + sub eax, [drbar.real_sx] + inc eax + mov [drbar.line_inc_map], eax + + ; line_inc_scr + mov eax, [drbar.real_sx] + movzx ebx, byte [ScreenBPP] + shr ebx, 3 + imul eax, ebx + neg eax + add eax, [BytesPerScanLine] + mov [drbar.line_inc_scr], eax + + ; pointer to screen + mov edx, [drbar.abs_cy] + imul edx, [BytesPerScanLine] + mov eax, [drbar.abs_cx] +; movzx ebx, byte [ScreenBPP] +; shr ebx, 3 + imul eax, ebx + add edx, eax + add edx, [LFBAddress] + + ; pointer to pixel map + mov eax, [drbar.abs_cy] + imul eax, [ScreenWidth] + add eax, [drbar.abs_cy] + add eax, [drbar.abs_cx] + add eax, WinMapAddress + xchg eax, ebp + + ; get process number + mov eax, [0x3010] + mov bl, [eax+0xE] + + cmp byte [ScreenBPP], 24 + jne draw_bar_end_32 +draw_bar_end_24: + ;cli ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + mov eax, [drbar.color] ;; BBGGRR00 + mov bh, al ;; bh = BB + shr eax, 8 ;; eax = RRGG +; eax - color high RRGG +; bl - process num +; bh - color low BB +; ecx - temp +; edx - pointer to screen +; esi - counter +; edi - counter + + mov esi, [drbar.real_sy] + align 4 + .new_y: + mov edi, [drbar.real_sx] + align 4 + .new_x: + + cmp byte [ebp], bl + jne .skip + mov [edx], bh + mov [edx + 1], ax + .skip: + + ; add pixel + add edx, 3 + inc ebp + + dec edi + jnz .new_x + + ; add line + add edx, [drbar.line_inc_scr] + add ebp, [drbar.line_inc_map] + + ; drawing gradient bars + test eax, 0x00800000 + jz @f + test bh, bh + jz @f + dec bh + @@: + ; + + dec esi + jnz .new_y + + add esp, drbar.stack_data + popad + xor eax, eax + ;sti ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +ret + +draw_bar_end_32: + mov eax, [drbar.color] ;; BBGGRR00 + + mov esi, [drbar.real_sy] + align 4 + .new_y: + mov edi, [drbar.real_sx] + align 4 + .new_x: + + cmp byte [ebp], bl + jne .skip + mov [edx], eax + .skip: + + ; add pixel + add edx, 4 + inc ebp + + dec edi + jnz .new_x + + ; add line + add edx, [drbar.line_inc_scr] + add ebp, [drbar.line_inc_map] + + ; drawing gradient bars + test eax, 0x80000000 + jz @f + test al, al + jz @f + dec al + @@: + ; + + dec esi + jnz .new_y + + add esp, drbar.stack_data + popad + xor eax, eax +ret + + +;voodoodbcplimit: + +; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer + + +; pusha + +; xor edx,edx +; mov eax,ebp +; mov ebx,[ScreenWidth] ; Screen_X_size +; inc ebx ; +1 +; sub eax,WinMapAddress ; -AddrBuffer +; div ebx ; +; mov ebx,eax ; ebx:=Y +; mov eax,edx ; eax:=X +; call cplimit + +; test ecx,ecx +; jne dbcpl12 +; popa +; clc +; ret +; dbcpl12: +; popa +; stc +; ret + + + + +;dbcplimit: + +; pusha + +; xor edx,edx +; mov ebx,[ScreenWidth] +; inc ebx +; sub eax,WinMapAddress +; div ebx +; mov ebx,eax +; mov eax,edx +; call cplimit + +; test ecx,ecx +; jne dbcpl1 +; popa +; clc +; ret +; dbcpl1: +; popa +; stc +; ret + + + + + + +;--------------vbe voodoo ------------------------------------------------ +vesa20_drawbackground_tiled: + + call [disable_mouse] + + push ebp + push eax + push ebx + push ecx + push edx + + mov edx,dword [WinMapAddress-8] ; B + add edx,dword [WinMapAddress-8] ; +B + add edx,dword [WinMapAddress-8] ; +B + push edx + + mov ebp,[draw_data+32+0] ; x start:=(x+Xwin) + mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) + + mov eax,[BytesPerScanLine] + mul ebx + xchg ebp, eax ; BytesPerScanLine*(Ywin+y) + add ebp, eax ; +X + add ebp, eax ; +X + add ebp, eax ; +X + + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + add ebp,eax ; +X + @@: + add ebp,[LFBAddress] ; +LFB + + ; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB + + call calculate_edi + + + dp3: ; MAIN LOOP + + cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) +; je ybgp +; +; jmp nbgp +; +; ybgp: + jne nbgp + + push eax + push ebx + + mov ecx,dword [WinMapAddress-8] ; B + xor edx,edx ; edx:=0 + div ecx ; Xstart/B + + ; eax=Int(qn) edx:=Rem + + lea esi,[edx+edx*2] ; esi:=edx*3 + + mov ecx,dword [WinMapAddress-4] ; ecx:=H + mov eax,[esp+0] ; eax:=Ystart + xor edx,edx ; + div ecx ; Ystart/H + + mov eax,edx ; eax:=Rem + xor edx,edx ; + mov ebx,[esp+8] ; ebx:=B*3 + mul ebx ; + add esi,eax ; + mov eax,[esi+0x300000] + and eax,0xffffff + + xchg edi, ebp + stosw + shr eax,16 + stosb + xchg ebp, edi ; ebp+=3 + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + inc ebp ; +1 + @@: + + pop ebx + pop eax + + jmp hook1 + + nbgp: + add ebp,3 ; +3 + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + inc ebp ; +1 + @@: + + hook1: + + inc edi ; ptrBuffer++ + add esi,3 ; ptrImage+=3 + inc eax + cmp eax,[draw_data+32+8] ; X > xend? +; jg nodp3 +; jmp dp3 +; +; nodp3: + jle dp3 + + mov ebp,[draw_data+32+0] + + inc ebx + + mov eax,[BytesPerScanLine] + mul ebx + xchg ebp, eax ; BytesPerScanLine*(Ywin+y) + add ebp, eax ; +X + add ebp, eax ; +X=X*2 + add ebp, eax ; +X=X*3 + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + add ebp,eax ; +X=X*4 + @@: + add ebp,[LFBAddress] ; +LFB + + ; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB + + call calculate_edi + + cmp ebx,[draw_data+32+12] +; jg dp4 +; +; jmp dp3 +; +; dp4: + jle dp3 + + add esp,4 + + pop edx + pop ecx + pop ebx + pop eax + pop ebp + + ret + +; ---------- + + +vesa20_drawbackground_stretch: + + call [disable_mouse] + + push ebp + push eax + push ebx + push ecx + push edx + + mov edx,dword [WinMapAddress-8] ; B + add edx,dword [WinMapAddress-8] ; +B + add edx,dword [WinMapAddress-8] ; +B + push edx + + mov ebp,[draw_data+32+0] ; x start:=(x+Xwin) + mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) + + mov eax,[BytesPerScanLine] + mul ebx + xchg ebp, eax ; BytesPerScanLine*(Ywin+y) + add ebp, eax ; +X + add ebp, eax ; +X + add ebp, eax ; +X + + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + add ebp,eax ; +X + @@: + add ebp,[LFBAddress] ; +LFB + + ; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB + + call calculate_edi + + + sdp3: ; MAIN LOOP + + cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) + jne snbgp + + push eax + push ebx + + mov eax,dword [WinMapAddress-8] + imul eax, [esp+4] ;4 + xor edx,edx + mov ebx,[ScreenWidth] + div ebx + lea esi,[eax+eax*2] + mov eax,dword [WinMapAddress-4] + imul eax, [esp+0] ;0 + xor edx,edx + mov ebx,[ScreenHeight] + div ebx + imul eax, [esp+8] ;8 + add esi,eax + + mov eax,[esi+0x300000] + and eax,0xffffff + + xchg edi, ebp + stosw + shr eax,16 + stosb + xchg ebp, edi ; ebp+=3 + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + inc ebp ; +1 + @@: + + pop ebx + pop eax + + jmp shook1 + + snbgp: + add ebp,3 ; +3 + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + inc ebp ; +1 + @@: + + shook1: + + inc edi ; ptrBuffer++ + add esi,3 ; ptrImage+=3 + inc eax + cmp eax,[draw_data+32+8] ; X > xend? + jle sdp3 + + mov ebp,[draw_data+32+0] + + inc ebx + + mov eax,[BytesPerScanLine] + mul ebx + xchg ebp, eax ; BytesPerScanLine*(Ywin+y) + add ebp, eax ; +X + add ebp, eax ; +X=X*2 + add ebp, eax ; +X=X*3 + cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size + jz @f + add ebp,eax ; +X=X*4 + @@: + add ebp,[LFBAddress] ; +LFB + + ; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB + + call calculate_edi + + cmp ebx,[draw_data+32+12] + jle sdp3 + + add esp,4 + + pop edx + pop ecx + pop ebx + pop eax + pop ebp + + ret diff --git a/trunk/video/vga.inc b/trunk/video/vga.inc new file mode 100644 index 000000000..8ef2471d3 --- /dev/null +++ b/trunk/video/vga.inc @@ -0,0 +1,781 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; VGA.INC ;; +;; ;; +;; 640x480 mode 0x12 VGA functions for MenuetOS ;; +;; ;; +;; Paul Butcher, paul.butcher@asa.co.uk ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +paletteVGA: + +;16 colour palette + mov dx,0x3c8 + mov al,0 + out dx,al + + mov ecx,16 + mov dx,0x3c9 + xor eax,eax + + palvganew: + + mov al,0 + test ah,4 + jz palvgalbl1 + add al,31 + test ah,8 + jz palvgalbl1 + add al,32 + palvgalbl1: + out dx,al ; red 0,31 or 63 + mov al,0 + test ah,2 + jz palvgalbl2 + add al,31 + test ah,8 + jz palvgalbl2 + add al,32 + palvgalbl2: + out dx,al ; blue 0,31 or 63 + mov al,0 + test ah,1 + jz palvgalbl3 + add al,31 + test ah,8 + jz palvgalbl3 + add al,32 + palvgalbl3: + out dx,al ; green 0,31 or 63 + add ah,1 + loop palvganew + + ret + + +vga_putimage: + + push ebp ; + push esi ; + push edi ; + + push eax ; + push ebx ; +8 [ptrImage] + push ecx ; +4 [BH] + push edx ; +0 [xy] + + movzx eax,word [esp+2] ; eax:=x + movzx ebx,word [esp+0] ; ebx:=y + mov ecx,[0x3010] ; + add eax,[ecx-twdw] ; eax+=Xwin + add ebx,[ecx-twdw+4] ; ebx+=Ywin + mov ecx,ebx ; ecx = y+Ywin + mov edx,eax ; edx = x+Xwin + + imul ebx, 640*4 ; (y+Ywin)*BytesPerScanLine + shl eax,2 ; (x+Xwin)*BytesPerPixel + add eax,ebx ; + mov edi,eax ; store copy + add eax,[0xfe80] ; +AddrLFB + ;entry point in LFB >> EAX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrLFB + + shr edi,5 ; change from 4 to 1/8 BytesPerPixel + add edi,0xa0000 ; + VGABasePtr + ;VGA start address >> EDI:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrVGA + + mov ebx, [0xfe00] ; ScreenXSize + inc ebx ; +1 + imul ebx,ecx ; *(y+Ywin) + mov ebp, ebx ; + add ebp, edx ; +(x+Xwin) + add ebp, WinMapAddress ; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer + + mov esi,[esp+8] ; esi:=AddrImg + movzx ecx,word [esp+6] ; ecx:=B + movzx ebx,word [esp+4] ; ebx:=H + + ; check limits while draw ? + + push ecx ; B + push eax ; LFB address + + mov eax,[0x3010] + mov ecx,[eax+draw_data-0x3000+0] + cmp ecx,0 + jnz dbcblimitlset_vga + + mov ecx,[eax+draw_data-0x3000+4] + cmp ecx,0 + jnz dbcblimitlset_vga + + mov ecx,[eax+draw_data-0x3000+8] + cmp ecx,[0xfe00] ; ecx <> Screen X size + jnz dbcblimitlset_vga + + mov ecx,[eax+draw_data-0x3000+12] + cmp ecx,[0xfe04] ; ecx <> Screen Y size + jnz dbcblimitlset_vga + + pop eax ; LFB address + pop ecx ; B + + push dword 0 + + jmp pimvga + + dbcblimitlset_vga: + + pop eax ; LFB address + pop ecx ; B + + push dword 1 + +pimvga: + push edi + push esi + push eax ; LFB address + push ecx ; B + push ebx ; H + push edx ; x+Xwin + + mov ebx,[0x3010] + mov bl,[ebx+0xe] + mov bh,[esp+6*4] + + cld + + npvga: + + cmp bl,[ds:ebp] + jnz impvgano + +; cmp bh,0 +; jz impvgayes + +; call voodoodbcplimit +; jnz impvgano + +; impvgayes: + + push eax ; LFB address + push ebx ; app no. + push ecx ; B + push edx ; x+Xwin + + mov edx,[esi] ; color + mov [eax],dx + shr edx,16 + mov [eax+2],dl + + mov eax,[esi] ; color + mov ecx,[esp] ; x+Xwin + and ecx,0x07 ; modulo 8 + call setvgapixel ; eax=color, ecx=x%8, edi=VGA address + + pop edx + pop ecx + pop ebx + pop eax + + impvgano: + + add esi,3 ; esi+=3 ptrImage+=3 + add eax,4 ; eax+=4 LFBaddr +=4 + inc ebp + inc edx ; x+Xwin+n + + test edx,0x07 ; test modulo 8 + jnz impvgacont + inc edi + + impvgacont: + dec ecx ; B-- + jnz npvga + + pop edx + pop ebx + pop ecx + pop eax + pop esi + pop edi + + add edi,640/8 ; add one VGA line + add eax,640*4 ; add one LFB line + + sub ebp, ecx ; -B + add ebp, [0xfe00] ; + inc ebp ; ptrBuffer:=ptrBuffer-B+Screen_Xsize+1 + + push ecx + lea ecx,[ecx+ecx*2] ; + add esi,ecx ; ptrImage:=ptrImage+B*3 + pop ecx + + dec ebx ; H-- + jnz near pimvga + + add esp,4 ; jump saved limit byte + pop edx + pop ecx + pop ebx + pop eax + pop edi + pop esi + pop ebp + + ret + + +VGA_putpixel: + + ; eax = x + ; ebx = y + + mov ecx,eax + mov eax, [esp+32-8+4] ; color + + imul ebx, 640*4 ; y*BytesPerLine (Vesa2.0 32) + lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32) + + mov edi,edx + add edi, [0xfe80] ; + LFB address + mov [edi], eax ; write to LFB for Vesa2.0 + + shr edx,5 ; change BytesPerPixel to 1/8 + mov edi,edx + add edi, 0x0a0000 ; address of pixel in VGA area + + and ecx,0x07 ; bit no. (modulo 8) + +setvgapixel: + + ; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8) + + push eax + mov ebx,eax ; color + + ;mov al,0x08 + ;mov dx,0x03ce + ;out dx,al ; select GDC bit mask register + + inc cl + mov ax, 0x100 + shr ax,cl + mov dx,0x03cf + out dx,al ; set bit mask for pixel + + mov dl,0 + mov eax,ebx + and eax,0x000000ff ; blue + cmp eax,85 + jle p13green + or dl,0x01 + cmp eax,170 + jle p13green + or dl,0x08 + +p13green: + and ebx,0x0000ff00 ; green + cmp ebx,85*256 + jle p13red + or dl,0x02 + cmp ebx,170*256 + jle p13red + or dl,0x08 + +p13red: + pop ebx + and ebx,0x00ff0000 ; red + cmp ebx,85*256*256 + jle p13cont + or dl,0x04 + cmp ebx,170*256*256 + jle p13cont + or dl,0x08 + +p13cont: + mov al,[edi] ; dummy read + mov [edi],dl + + ret + + +vga_drawbar: + + sub edx,ebx ; edx:=Yend-Ystart=H + sub ecx,eax ; ecx:=Xend-Xstat=B + + push ebp ; +24 + push esi ; +20 + push edi ; +16 + push eax ; +12 + push ebx ; +8 + push ecx ; +4 + push edx ; +0 + + mov ecx,[0x3010] ; + add eax,[ecx-twdw] ; eax:=Xwin+x + add ebx,[ecx-twdw+4] ; ebx:=Ywin+y + mov ecx, eax ; ecx:=(x+Xwin) + mov edx, ebx ; edx:=(y+Ywin) + + imul ebx, 640/8 ; + mov edi, ebx ; edi:=BytesPerScanLine*(y+Ywin) + shr eax, 3 ; + add edi, eax ; + (x+Xwin)*BytesPerPixel + add edi,0xa0000 ; + VGAbaseaddress + + mov eax, [0xfe00] ; ScreenXSize + inc eax ; +1 + imul eax,edx ; *(y+Ywin) + mov ebp, eax ; + add ebp, ecx ; +(x+Win) + add ebp, WinMapAddress ; +AddrBuffer + + mov eax, [0xfe08] ; BytesPerScanLine - LFB + mul edx ; *(y+Ywin) + mov esi,eax + add esi,ecx + add esi,ecx + add esi,ecx + add esi,ecx ; + 4*(x+Xwin) + add esi,[0xfe80] ; +AddrLFB + +; edi:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel + AddrVGA +; esi:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel + AddrLFB +; ebp:=(y+Ywin)*(ScreenXSize+1)+(x+Xwin)+AddrBuffer + +; x size + + mov eax,[esp+4] ; B [esp+4] + mov ebx,[esp+0] ; H + + mov edx,[esp+16] ; color + test edx,0x80000000 + jz nodbglvga + + ; no color glide for VGA - set to half glide + shr ebx,1 ; H/2 + sub edx,ebx + mov [esp+16],edx + mov ebx,[esp+0] ; reset to H + + nodbglvga: + ; check limits ? + + push eax + push ecx + + mov eax,[0x3010] + + mov ecx,[eax+draw_data-0x3000+0] + cmp ecx,0 + jnz dbcblimitlset_vga2 + + mov ecx,[eax+draw_data-0x3000+4] + cmp ecx,0 + jnz dbcblimitlset_vga2 + + mov ecx,[eax+draw_data-0x3000+8] + cmp ecx,[0xfe00] + jnz dbcblimitlset_vga2 + + mov ecx,[eax+draw_data-0x3000+12] + cmp ecx,[0xfe04] + jnz dbcblimitlset_vga2 + + pop ecx + pop eax + + push dword 0 + + jmp dbnewpivga + + dbcblimitlset_vga2: + + pop ecx ; x+Xwin + pop eax ; B + + push dword 1 + + dbnewpivga: + + push eax; B + push ebx ; H + push edi + push esi + push ecx ; x+Xwin + + mov ebx,[0x3010] + movzx ebx,byte[ebx+0xe] + + cld + + dbnpvga: + + mov dl,[ds:ebp] + + cmp dl,bl + jnz dbimpvgano + +; mov edx,[esp+5*4] ; check limit? +; cmp edx,0 +; jz dbimpvgayes + +; call voodoodbcplimit +; jnz dbimpvgano + +; dbimpvgayes: + + push eax ; B + push ebx + push ecx ; x+Xwin + + mov eax,[esp+12+20+16+4] ; color + mov ebx,eax + + mov [esi],bx ; write LFB pixel + shr ebx,16 + mov [esi+2],bl + + and ecx,0x07 ; modulo 8 + call setvgapixel ; eax=color, ecx=x%8, edi=VGA address + + pop ecx + pop ebx + pop eax + + dbimpvgano: + + add esi,4 ; ptrLFB+=4 + inc ebp ; address buffer + inc ecx ; x posn++ + test ecx,0x07 ; test modulo 8 + jnz dbvgacont + inc edi ; VGA screen ptr++ + + dbvgacont: + dec eax ; B-- NB ecx in Vesa20 fn? + jnz dbnpvga + + dbnpvgad: + + pop ecx + pop esi + pop edi + pop ebx + pop eax + + add esi,[0xfe08] ; ptrLFB+=BytesPerScanLine + add edi,640/8 ; ptrScreen+=BytesPerScanLine + + add ebp,[0xfe00] ; + sub ebp, eax ; was ecx in vesa20 fn? + inc ebp ; ptrBuffer:=ptrBuffer-B+BytesPerLine+1 + + dec ebx ; H-- + jz nodbnewpivga ; H<>0 + + jmp dbnewpivga + + nodbnewpivga: + + add esp,7*4 ; NB includes limit check flag + ;pop ebx + ;pop eax + ;pop edi + ;pop esi + pop ebp + + ;pop edx + ;pop ecx + + ret + + +vga_drawbackground_tiled: + + push ebp + push eax + push ebx + push ecx + push edx + + mov edx,dword [0x400000-8] ; B + add edx,dword [WinMapAddress-8] ; +B + add edx,dword [WinMapAddress-8] ; +B + push edx + + mov eax,[draw_data+32+0] ; x start:=(x+Xwin) + mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) + mov ecx,eax + mov edx,ebx + + imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine + shl ecx,2 ; (x+Xwin)*BytesPerPixel + add ecx,edx ; + mov ebp,ecx ; store copy + add ecx,[0xfe80] ; +AddrLFB + ;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr + + shr ebp,5 ; change from 4 to 1/8 BytesPerPixel + add ebp,0xa0000 ; + VGABasePtr + ;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV + + + call calculate_edi + + dp3vga: ; MAIN LOOP + + cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) + je ybgpvga + + jmp nbgpvga + + ybgpvga: + + push eax ; x + push ebx ; y + push ecx ; LFB address + + mov ecx,dword [WinMapAddress-8] ; B + xor edx,edx ; edx:=0 + div ecx ; Xstart/B + + ; eax=Int(qn) edx:=Rem + + lea esi,[edx+edx*2] ; esi:=edx*3 + + mov ecx,dword [WinMapAddress-4] ; ecx:=H + mov eax,[esp+4] ; eax:=Ystart + xor edx,edx ; + div ecx ; Ystart/H + + mov eax,edx ; eax:=Rem + xor edx,edx ; + mov ebx,[esp+12] ; ebx:=B*3 + mul ebx ; + add esi,eax ; + + mov eax,[esi+0x300000] ; color + and eax,0xffffff + + mov ecx, [esp] ; LFB address + mov ebx,eax ; copy color + mov [ecx],bx + shr ebx,16 + mov [ecx+2],bl + + xchg edi, ebp + mov ecx,[esp+8] ; x position + and ecx,0x07 ; x modulo 8 + call setvgapixel ; eax=color, ecx=x%8, edi=VGA address + xchg ebp, edi + + pop ecx + pop ebx + pop eax + + nbgpvga: + + inc eax ; x++ + cmp eax,[draw_data+32+8] ; X > xend? + jg nodp3vga + + test eax,0x07 ; x test modulo 8 + jnz hook1vga + inc ebp ; VGA address++ + + hook1vga: + add ecx,4 ; LFB address += 4 + inc edi ; ptrBuffer++ + add esi,3 ; ptrImage+=3 + jmp dp3vga + + nodp3vga: + + mov eax,[draw_data+32+0] ; x+Xwin + inc ebx ; y position + mov ecx,eax + mov edx,ebx + + imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine + shl ecx,2 ; (x+Xwin)*BytesPerPixel + add ecx,edx ; + mov ebp,ecx ; store copy + add ecx,[0xfe80] ; +AddrLFB + ;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr + + + shr ebp,5 ; change from 4 to 1/8 BytesPerPixel + add ebp,0xa0000 ; + VGABasePtr + ;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV + + + call calculate_edi + + cmp ebx,[draw_data+32+12] ; Y > yend + jg dp4vga + + jmp dp3vga + + dp4vga: + + add esp,4 + + pop edx + pop ecx + pop ebx + pop eax + pop ebp + + ret + +; ---------- + + + +vga_drawbackground_stretch: + + + push ebp + push eax + push ebx + push ecx + push edx + + mov edx,dword [WinMapAddress-8] ; B + add edx,dword [WinMapAddress-8] ; +B + add edx,dword [WinMapAddress-8] ; +B + push edx + + mov eax,[draw_data+32+0] ; x start:=(x+Xwin) + mov ebx,[draw_data+32+4] ; y start:=(y+Ywin) + mov ecx,eax + mov edx,ebx + + imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine + shl ecx,2 ; (x+Xwin)*BytesPerPixel + add ecx,edx ; + mov ebp,ecx ; store copy + add ecx,[0xfe80] ; +AddrLFB + ;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr + + shr ebp,5 ; change from 4 to 1/8 BytesPerPixel + add ebp,0xa0000 ; + VGABasePtr + ;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+AddrV + + + call calculate_edi + + sdp3vga: ; MAIN LOOP + + cmp [edi+WinMapAddress],byte 1 ; ptrBuffer^<>byte(1) + je sybgpvga + + jmp snbgpvga + + sybgpvga: + + push eax ; x + push ebx ; y + push ecx ; LFB address + + mov eax,dword [WinMapAddress-8] ; B + xor edx,edx + mov ebx,[esp+8] ; Xstart + mul ebx ; B*Xstart + xor edx,edx + mov ebx,[0xfe00] ; x screen width + div ebx ; B*Xstart/xwidth + lea esi,[eax+eax*2] ; *3 + mov eax,dword [WinMapAddress-4] ; H + xor edx,edx + mov ebx,[esp+4] ; Ystart + mul ebx ; H*Ystart + xor edx,edx + mov ebx,[0xfe04] ; y screen height + div ebx ; H*Ystart/yheight + + xor edx,edx + mov ebx,[esp+12] ; B*3 + mul ebx ; + add esi,eax + mov eax,[esi+0x300000] ; color + and eax,0xffffff + + mov ecx, [esp] ; LFB address + mov ebx,eax ; copy color + mov [ecx],bx + shr ebx,16 + mov [ecx+2],bl + + xchg edi, ebp + mov ecx,[esp+8] ; x position + and ecx,0x07 ; x modulo 8 + call setvgapixel ; eax=color, ecx=x%8, edi=VGA address + xchg ebp, edi ; ebp+=3 + + pop ecx + pop ebx + pop eax + + snbgpvga: + + inc eax ; x++ + cmp eax,[draw_data+32+8] ; X > xend? + jg snodp3vga + + test eax,0x07 ; x test modulo 8 + jnz shook1vga + inc ebp ; VGA address++ + + shook1vga: + add ecx,4 ; LFB address += 4 + inc edi ; ptrBuffer++ + add esi,3 ; ptrImage+=3 + jmp sdp3vga + + snodp3vga: + + mov eax,[draw_data+32+0] ; x+Xwin + inc ebx ; y position + mov ecx,eax + mov edx,ebx + + imul edx, 640*4 ; (y+Ywin)*BytesPerScanLine + shl ecx,2 ; (x+Xwin)*BytesPerPixel + add ecx,edx ; + mov ebp,ecx ; store copy + add ecx,[0xfe80] ; +AddrLFB + ;entry point in LFB >> ECX:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+Addr + + + shr ebp,5 ; change from 4 to 1/8 BytesPerPixel + add ebp,0xa0000 ; + VGABasePtr + ;VGA start address >> EBP:=(y+Ywin)*BytesPerScanLine+X*BytesPerPixel+A + + + call calculate_edi + + cmp ebx,[draw_data+32+12] ; Y > yend + jg sdp4vga + + jmp sdp3vga + + sdp4vga: + + add esp,4 + + pop edx + pop ecx + pop ebx + pop eax + pop ebp + + ret + + diff --git a/trunk/vmodeint.inc b/trunk/vmodeint.inc new file mode 100644 index 000000000..f48b8a6c3 --- /dev/null +++ b/trunk/vmodeint.inc @@ -0,0 +1,20 @@ +; +; Call of videomode driver's functions +; +; (Add in System function 21 (and/or 26) as a subfunction 13) +; +; Author: Trans +; Date: 19.07.2003 +; +; Include in MeOS kernel and compile with FASM +; + cmp eax,13 ; CALL VIDEOMODE DRIVER FUNCTIONS + jne .no_vmode_drv_access + or eax,-1 ; If driver is absent then eax does not change + call 0x760100 ; Entry point of video driver + mov [esp+36],eax + mov [esp+24],ebx + mov [esp+32],ecx +; mov [esp+28],edx + ret + .no_vmode_drv_access: diff --git a/trunk/vmodeld.inc b/trunk/vmodeld.inc new file mode 100644 index 000000000..038222107 --- /dev/null +++ b/trunk/vmodeld.inc @@ -0,0 +1,27 @@ +; +; Load of videomode driver in memory +; +; (driver is located at 0x760000-0x768000 - 32kb) // if this area not occuped anything +; +; Author: Trans +; Date: 19.07.2003 +; +; Include in MeOS kernel and compile with FASM +; + + +;vmode db 'VMODE MDR' ; MDR - Menuet Driver +; must be located after fonts filenames in kernel.asm + +; LOAD VIDEOMODE DRIVER + ; If vmode.mdr file not found + or eax,-1 ; Driver ID = -1 (not present in system) + mov [0x760000],eax ; + mov [0x760100],byte 0xC3 ; Instruction RETN - driver loop + + mov eax,vmode ; File name of driver + mov esi,12 + mov ebx,0 + mov ecx,26000 + mov edx,0x760000 ; Memory position of driver + call fileread \ No newline at end of file