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);
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);
// 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;
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;
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));
// 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;
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)
inw(iobase1);
// Compute new buffer address
- bufoff += count;
+ far_buffer += count;
// Save transferred bytes count
SET_EBDA(ata.trsfsectors, loops);
}
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;
atacmd[5]=(lba & 0x000000ff);
return ata_cmd_packet(biosid, atacmd, sizeof(atacmd)
- , skip, count, segment, offset);
+ , skip, count, far_buffer);
}
// ---------------------------------------------------------------------------
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");
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");
#include "atabits.h"
struct ata_pio_command {
- u16 segment;
- u16 offset;
+ void *far_buffer;
u8 biosid;
u8 feature;
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;
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;
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;
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;
// 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;
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;
// 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;
// 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
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;
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));
#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" \
__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) ({ \
__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