diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2008-03-12 20:33:15 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2008-03-12 20:33:15 -0400 |
commit | efde609a28f860fb1df2b0c6fe56ebd68a051f10 (patch) | |
tree | 09e476b031c399bcd51777d79e2b9dd4e978b1cd /src | |
parent | 28fe1bd0f096dbf0e49e97b11df1888f1deaf1e7 (diff) | |
download | seabios-hppa-efde609a28f860fb1df2b0c6fe56ebd68a051f10.zip seabios-hppa-efde609a28f860fb1df2b0c6fe56ebd68a051f10.tar.gz seabios-hppa-efde609a28f860fb1df2b0c6fe56ebd68a051f10.tar.bz2 |
Use 32bit absolute pointers for buffers in ATA code.
Using 32bit pointers makes the code a little simpler. It also allows
the code to be used from 32 bit mode. It does require all callers to
encode the segment/offset into an absolute address. The ins/outs
functions also need to know how to convert from 32bit back to
segment/offset addresses.
The change also includes a minor cleanup of the macros in farptr.h.
Diffstat (limited to 'src')
-rw-r--r-- | src/ata.c | 59 | ||||
-rw-r--r-- | src/ata.h | 18 | ||||
-rw-r--r-- | src/cdrom.c | 14 | ||||
-rw-r--r-- | src/disk.c | 16 | ||||
-rw-r--r-- | src/farptr.h | 112 |
5 files changed, 121 insertions, 98 deletions
@@ -186,10 +186,10 @@ send_cmd(struct ata_pio_command *cmd) int ata_transfer(struct ata_pio_command *cmd) { - DEBUGF("ata_transfer id=%d cmd=%d lba=%d count=%d seg=%x off=%x\n" + DEBUGF("ata_transfer id=%d cmd=%d lba=%d count=%d buf=%p\n" , cmd->biosid, cmd->command , (cmd->lba_high << 16) | (cmd->lba_mid << 8) | cmd->lba_low - , cmd->sector_count, cmd->segment, cmd->offset); + , cmd->sector_count, cmd->far_buffer); // Reset count of transferred data SET_EBDA(ata.trsfsectors,0); @@ -208,34 +208,28 @@ ata_transfer(struct ata_pio_command *cmd) irq_enable(); - u16 segment = cmd->segment; - u16 offset = cmd->offset; u8 current = 0; u16 count = cmd->sector_count; u8 status; + void *far_buffer = cmd->far_buffer; for (;;) { - if (offset >= 0xf800) { - offset -= 0x800; - segment += 0x80; - } - if (iswrite) { // Write data to controller - DEBUGF("Write sector id=%d dest=%x:%x\n", biosid, segment, offset); + DEBUGF("Write sector id=%d dest=%p\n", biosid, far_buffer); if (mode == ATA_MODE_PIO32) - outsl_seg(iobase1, segment, offset, 512 / 4); + outsl_far(iobase1, far_buffer, 512 / 4); else - outsw_seg(iobase1, segment, offset, 512 / 2); + outsw_far(iobase1, far_buffer, 512 / 2); } else { // Read data from controller - DEBUGF("Read sector id=%d dest=%x:%x\n", biosid, segment, offset); + DEBUGF("Read sector id=%d dest=%p\n", biosid, far_buffer); if (mode == ATA_MODE_PIO32) - insl_seg(iobase1, segment, offset, 512 / 4); + insl_far(iobase1, far_buffer, 512 / 4); else - insw_seg(iobase1, segment, offset, 512 / 2); + insw_far(iobase1, far_buffer, 512 / 2); await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); } - offset += 512; + far_buffer += 512; current++; SET_EBDA(ata.trsfsectors,current); @@ -280,12 +274,10 @@ ata_transfer(struct ata_pio_command *cmd) // 4 : not ready int ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen - , u16 header, u32 length, u16 bufseg, u16 bufoff) + , u16 header, u32 length, void *far_buffer) { - DEBUGF("ata_cmd_packet d=%d cmdlen=%d h=%d l=%d" - " seg=%x off=%x\n" - , biosid, cmdlen, header, length - , bufseg, bufoff); + DEBUGF("ata_cmd_packet d=%d cmdlen=%d h=%d l=%d buf=%p\n" + , biosid, cmdlen, header, length, far_buffer); u8 channel = biosid / 2; u8 slave = biosid % 2; @@ -321,7 +313,7 @@ ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen irq_enable(); // Send command to device - outsw_seg(iobase1, GET_SEG(SS), (u32)cmdbuf, cmdlen / 2); + outsw_far(iobase1, MAKE_32_PTR(GET_SEG(SS), (u32)cmdbuf), cmdlen / 2); u8 status; u16 loops = 0; @@ -346,10 +338,6 @@ ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen return 3; } - // Normalize address - bufseg += (bufoff / 16); - bufoff %= 16; - // Get the byte count u16 lcount = (((u16)(inb(iobase1 + ATA_CB_CH))<<8) + inb(iobase1 + ATA_CB_CL)); @@ -378,9 +366,8 @@ ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen // Save byte count u16 count = lcount; - DEBUGF("Trying to read %04x bytes (%04x %04x %04x) " - , lbefore+lcount+lafter, lbefore, lcount, lafter); - DEBUGF("to 0x%04x:0x%04x\n", bufseg, bufoff); + DEBUGF("Trying to read %04x bytes (%04x %04x %04x) to %p\n" + , lbefore+lcount+lafter, lbefore, lcount, lafter, far_buffer); // If counts not dividable by 4, use 16bits mode u8 lmode = mode; @@ -410,9 +397,9 @@ ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen inw(iobase1); if (lmode == ATA_MODE_PIO32) - insl_seg(iobase1, bufseg, bufoff, lcount); + insl_far(iobase1, far_buffer, lcount); else - insw_seg(iobase1, bufseg, bufoff, lcount); + insw_far(iobase1, far_buffer, lcount); for (i=0; i<lafter; i++) if (lmode == ATA_MODE_PIO32) @@ -421,7 +408,7 @@ ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen inw(iobase1); // Compute new buffer address - bufoff += count; + far_buffer += count; // Save transferred bytes count SET_EBDA(ata.trsfsectors, loops); @@ -442,7 +429,7 @@ ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen } int -cdrom_read(u16 biosid, u32 lba, u32 count, u16 segment, u16 offset, u16 skip) +cdrom_read(u16 biosid, u32 lba, u32 count, void *far_buffer, u16 skip) { u16 sectors = (count + 2048 - 1) / 2048; @@ -457,7 +444,7 @@ cdrom_read(u16 biosid, u32 lba, u32 count, u16 segment, u16 offset, u16 skip) atacmd[5]=(lba & 0x000000ff); return ata_cmd_packet(biosid, atacmd, sizeof(atacmd) - , skip, count, segment, offset); + , skip, count, far_buffer); } // --------------------------------------------------------------------------- @@ -568,7 +555,7 @@ ata_detect() u16 ret = ata_cmd_data_chs(device, ATA_CMD_IDENTIFY_DEVICE , 0, 0, 1, 1 - , GET_SEG(SS), (u32)buffer); + , MAKE_32_PTR(GET_SEG(SS), (u32)buffer)); if (ret) BX_PANIC("ata-detect: Failed to detect ATA device\n"); @@ -672,7 +659,7 @@ ata_detect() u16 ret = ata_cmd_data_chs(device, ATA_CMD_IDENTIFY_DEVICE_PACKET , 0, 0, 1, 1 - , GET_SEG(SS), (u32)buffer); + , MAKE_32_PTR(GET_SEG(SS), (u32)buffer)); if (ret != 0) BX_PANIC("ata-detect: Failed to detect ATAPI device\n"); @@ -12,8 +12,7 @@ #include "atabits.h" struct ata_pio_command { - u16 segment; - u16 offset; + void *far_buffer; u8 biosid; u8 feature; @@ -34,21 +33,19 @@ struct ata_pio_command { void ata_reset(u16 device); int ata_transfer(struct ata_pio_command *cmd); int ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen - , u16 header, u32 length, u16 bufseg, u16 bufoff); + , u16 header, u32 length, void *far_buffer); int cdrom_read(u16 device, u32 lba, u32 count - , u16 segment, u16 offset, u16 skip); + , void *far_buffer, u16 skip); void ata_detect(); static inline int -ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count - , u16 segment, u16 offset) +ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count, void *far_buffer) { u8 slave = biosid % 2; struct ata_pio_command cmd; + cmd.far_buffer = far_buffer; cmd.biosid = biosid; - cmd.segment = segment; - cmd.offset = offset; if (count >= (1<<8) || lba + count >= (1<<28)) { cmd.sector_count2 = count >> 8; @@ -73,14 +70,13 @@ ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count static inline int ata_cmd_data_chs(u16 biosid, u16 command, u16 cyl, u16 head, u16 sect, u16 count - , u16 segment, u16 offset) + , void *far_buffer) { u8 slave = biosid % 2; struct ata_pio_command cmd; + cmd.far_buffer = far_buffer; cmd.biosid = biosid; - cmd.segment = segment; - cmd.offset = offset; cmd.sector_count = count & 0xff; cmd.feature = 0; diff --git a/src/cdrom.c b/src/cdrom.c index 55db9b5..cf77584 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -296,7 +296,8 @@ atapi_get_sense(u16 device, u8 *asc, u8 *ascq) atacmd[0] = ATA_CMD_REQUEST_SENSE; atacmd[4] = sizeof(buffer); u16 ret = ata_cmd_packet(device, atacmd, sizeof(atacmd) - , 0, sizeof(buffer), GET_SEG(SS), (u32)buffer); + , 0, sizeof(buffer) + , MAKE_32_PTR(GET_SEG(SS), (u32)buffer)); if (ret != 0) return 0x0002; @@ -332,7 +333,8 @@ atapi_is_ready(u16 device) return -1; } u16 ret = ata_cmd_packet(device, packet, sizeof(packet) - , 0, sizeof(buf), GET_SEG(SS), (u32)buf); + , 0, sizeof(buf) + , MAKE_32_PTR(GET_SEG(SS), (u32)buf)); if (ret == 0) break; @@ -429,7 +431,8 @@ cdrom_boot() // Read the Boot Record Volume Descriptor u8 buffer[2048]; - ret = cdrom_read(device, 0x11, 2048, GET_SEG(SS), (u32)buffer, 0); + ret = cdrom_read(device, 0x11, 2048 + , MAKE_32_PTR(GET_SEG(SS), (u32)buffer), 0); if (ret) return 3; @@ -443,7 +446,8 @@ cdrom_boot() u32 lba = *(u32*)&buffer[0x47]; // And we read the Boot Catalog - ret = cdrom_read(device, lba, 2048, GET_SEG(SS), (u32)buffer, 0); + ret = cdrom_read(device, lba, 2048 + , MAKE_32_PTR(GET_SEG(SS), (u32)buffer), 0); if (ret) return 7; @@ -489,7 +493,7 @@ cdrom_boot() // And we read the image in memory ret = cdrom_read(device, lba, nbsectors*512 - , boot_segment, 0, 0); + , MAKE_32_PTR(boot_segment, 0), 0); if (ret) return 12; @@ -81,12 +81,13 @@ basic_access(struct bregs *regs, u8 device, u16 command) // translate lchs to lba lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) + (u32)sector - 1); - status = ata_cmd_data(device, command, lba, count, segment, offset); + status = ata_cmd_data(device, command, lba, count + , MAKE_32_PTR(segment, offset)); } else { // XXX - see if lba access can always be used. status = ata_cmd_data_chs(device, command - , cylinder, head, sector - , count, segment, offset); + , cylinder, head, sector, count + , MAKE_32_PTR(segment, offset)); } // Set nb of sector transferred @@ -145,7 +146,8 @@ emu_access(struct bregs *regs, u8 device, u16 command) u16 segment = regs->es; u16 offset = regs->bx; - u8 status = cdrom_read(device, lba, count*512, segment, offset, before*512); + u8 status = cdrom_read(device, lba, count*512 + , MAKE_32_PTR(segment, offset), before*512); if (status != 0) { BX_INFO("int13_harddisk: function %02x, error %02x !\n",regs->ah,status); regs->al = 0; @@ -190,9 +192,11 @@ extended_access(struct bregs *regs, u8 device, u16 command) u8 status; if (type == ATA_TYPE_ATA) - status = ata_cmd_data(device, command, lba, count, segment, offset); + status = ata_cmd_data(device, command, lba, count + , MAKE_32_PTR(segment, offset)); else - status = cdrom_read(device, lba, count*2048, segment, offset, 0); + status = cdrom_read(device, lba, count*2048 + , MAKE_32_PTR(segment, offset), 0); SET_INT13EXT(regs, count, GET_EBDA(ata.trsfsectors)); diff --git a/src/farptr.h b/src/farptr.h index 4759a08..1dea4b6 100644 --- a/src/farptr.h +++ b/src/farptr.h @@ -8,6 +8,7 @@ #include "ioport.h" // insb +// Low level macros for reading/writing memory via a segment selector. #define READ8_SEG(SEG, var) ({ \ u8 __value; \ __asm__ __volatile__("movb %%" #SEG ":%1, %b0" \ @@ -33,6 +34,16 @@ __asm__ __volatile__("movl %0, %%" #SEG ":%1" \ : : "r"(value), "m"(var)) +// Low level macros for getting/setting a segment register. +#define __SET_SEG(SEG, value) \ + __asm__ __volatile__("movw %w0, %%" #SEG : : "r"(value)) +#define __GET_SEG(SEG) ({ \ + u16 __seg; \ + __asm__ __volatile__("movw %%" #SEG ", %w0" : "=r"(__seg)); \ + __seg;}) + +// Macros for automatically choosing the appropriate memory size +// access method. extern void __force_link_error__unknown_type(); #define __GET_VAR(seg, var) ({ \ @@ -58,74 +69,95 @@ extern void __force_link_error__unknown_type(); __force_link_error__unknown_type(); \ } while (0) -#define __SET_SEG(SEG, value) \ - __asm__ __volatile__("movw %w0, %%" #SEG : : "r"(value)) -#define __GET_SEG(SEG) ({ \ - u16 __seg; \ - __asm__ __volatile__("movw %%" #SEG ", %w0" : "=r"(__seg)); \ - __seg;}) - -#define GET_FARVAR(seg, var) ({ \ +// Macros for accessing a variable in another segment. (They +// automatically update the %es segment and then make the appropriate +// access.) +#define __GET_FARVAR(seg, var) ({ \ SET_SEG(ES, (seg)); \ GET_VAR(ES, (var)); }) -#define SET_FARVAR(seg, var, val) do { \ +#define __SET_FARVAR(seg, var, val) do { \ typeof(var) __sfv_val = (val); \ SET_SEG(ES, (seg)); \ SET_VAR(ES, (var), __sfv_val); \ } while (0) -#define PTR_TO_SEG(p) ((((u32)(p)) >> 4) & 0xf000) -#define PTR_TO_OFFSET(p) (((u32)(p)) & 0xffff) - +// Macros for accesssing a 32bit pointer from 16bit mode. (They +// automatically update the %es segment, break the pointer into +// segment/offset, and then make the access.) #define __GET_FARPTR(ptr) ({ \ - typeof (&(ptr)) __ptr; \ + typeof (&(ptr)) __ptr = (ptr); \ GET_FARVAR(PTR_TO_SEG(__ptr), *(typeof __ptr)PTR_TO_OFFSET(__ptr)); }) -#define __SET_FARVAR(ptr, val) do { \ - typeof (&(ptr)) __ptr; \ +#define __SET_FARPTR(ptr, val) do { \ + typeof (&(ptr)) __ptr = (ptr); \ SET_FARVAR(PTR_TO_SEG(__ptr), *(typeof __ptr)PTR_TO_OFFSET(__ptr) \ , (val)); \ } while (0) +// Macros for converting to/from 32bit style pointers to their +// equivalent 16bit segment/offset values. +#define PTR_TO_SEG(p) (((u32)(p)) >> 4) +#define PTR_TO_OFFSET(p) (((u32)(p)) & 0xf) +#define MAKE_32_PTR(seg,off) ((void*)(((seg)<<4)+(off))) + + #ifdef MODE16 + +// Definitions when in 16 bit mode. +#define GET_FARVAR(seg, var) __GET_FARVAR((seg), (var)) +#define SET_FARVAR(seg, var, val) __SET_FARVAR((seg), (var), (val)) #define GET_VAR(seg, var) __GET_VAR(seg, (var)) #define SET_VAR(seg, var, val) __SET_VAR(seg, (var), (val)) #define SET_SEG(SEG, value) __SET_SEG(SEG, (value)) #define GET_SEG(SEG) __GET_SEG(SEG) #define GET_FARPTR(ptr) __GET_FARPTR(ptr) #define SET_FARPTR(ptr, val) __SET_FARPTR((ptr), (val)) + +static inline void insb_far(u16 port, void *farptr, u16 count) { + SET_SEG(ES, PTR_TO_SEG(farptr)); + insb(port, (u8*)PTR_TO_OFFSET(farptr), count); +} +static inline void insw_far(u16 port, void *farptr, u16 count) { + SET_SEG(ES, PTR_TO_SEG(farptr)); + insw(port, (u16*)PTR_TO_OFFSET(farptr), count); +} +static inline void insl_far(u16 port, void *farptr, u16 count) { + SET_SEG(ES, PTR_TO_SEG(farptr)); + insl(port, (u32*)PTR_TO_OFFSET(farptr), count); +} +static inline void outsb_far(u16 port, void *farptr, u16 count) { + SET_SEG(ES, PTR_TO_SEG(farptr)); + outsb(port, (u8*)PTR_TO_OFFSET(farptr), count); +} +static inline void outsw_far(u16 port, void *farptr, u16 count) { + SET_SEG(ES, PTR_TO_SEG(farptr)); + outsw(port, (u16*)PTR_TO_OFFSET(farptr), count); +} +static inline void outsl_far(u16 port, void *farptr, u16 count) { + SET_SEG(ES, PTR_TO_SEG(farptr)); + outsl(port, (u32*)PTR_TO_OFFSET(farptr), count); +} + #else + // In 32-bit mode there is no need to mess with the segments. +#define GET_FARVAR(seg, var) \ + (*((typeof(&(var)))MAKE_32_PTR((seg), (u32)&(var)))) +#define SET_FARVAR(seg, var, val) \ + do { GET_FARVAR((seg), (var)) = (val); } while (0) #define GET_VAR(seg, var) (var) #define SET_VAR(seg, var, val) do { (var) = (val); } while (0) #define SET_SEG(SEG, value) ((void)(value)) #define GET_SEG(SEG) 0 #define GET_FARPTR(ptr) (ptr) #define SET_FARPTR(ptr, val) do { (var) = (val); } while (0) -#endif -static inline void insb_seg(u16 port, u16 segment, u16 offset, u16 count) { - SET_SEG(ES, segment); - insb(port, (u8*)(offset+0), count); -} -static inline void insw_seg(u16 port, u16 segment, u16 offset, u16 count) { - SET_SEG(ES, segment); - insw(port, (u16*)(offset+0), count); -} -static inline void insl_seg(u16 port, u16 segment, u16 offset, u16 count) { - SET_SEG(ES, segment); - insl(port, (u32*)(offset+0), count); -} -static inline void outsb_seg(u16 port, u16 segment, u16 offset, u16 count) { - SET_SEG(ES, segment); - outsb(port, (u8*)(offset+0), count); -} -static inline void outsw_seg(u16 port, u16 segment, u16 offset, u16 count) { - SET_SEG(ES, segment); - outsw(port, (u16*)(offset+0), count); -} -static inline void outsl_seg(u16 port, u16 segment, u16 offset, u16 count) { - SET_SEG(ES, segment); - outsl(port, (u32*)(offset+0), count); -} +#define insb_far(port, farptr, count) insb(port, farptr, count) +#define insw_far(port, farptr, count) insw(port, farptr, count) +#define insl_far(port, farptr, count) insl(port, farptr, count) +#define outsb_far(port, farptr, count) outsb(port, farptr, count) +#define outsw_far(port, farptr, count) outsw(port, farptr, count) +#define outsl_far(port, farptr, count) outsl(port, farptr, count) + +#endif #endif // farptr.h |