Replaced direct memory accesses with I/O memory access functions.
authorIan Abbott <abbotti@mev.co.uk>
Thu, 5 Jul 2007 17:15:59 +0000 (17:15 +0000)
committerIan Abbott <abbotti@mev.co.uk>
Thu, 5 Jul 2007 17:15:59 +0000 (17:15 +0000)
Anders Blomdell replaced bitfield types with enum types.

comedi/drivers/jr3_pci.c
comedi/drivers/jr3_pci.h

index 25174fe90e27e30cbe45c7c867cf0410370b457e..8937398ba2c4bf778ffbe5614ac2c318dbbad184 100644 (file)
@@ -175,7 +175,7 @@ static poll_delay_t poll_delay_min_max(int min, int max)
 
 static int is_complete(volatile jr3_channel_t *channel)
 {
-  return get_s16(channel->command_word0) == 0;
+  return get_s16(&channel->command_word0) == 0;
 }
  
 typedef struct {
@@ -253,24 +253,24 @@ static void set_full_scales(volatile jr3_channel_t *channel,
 static six_axis_t get_min_full_scales(volatile jr3_channel_t *channel)
 {
   six_axis_t result;
-  result.fx = get_s16(channel->min_full_scale.fx);
-  result.fy = get_s16(channel->min_full_scale.fy);
-  result.fz = get_s16(channel->min_full_scale.fz);
-  result.mx = get_s16(channel->min_full_scale.mx);
-  result.my = get_s16(channel->min_full_scale.my);
-  result.mz = get_s16(channel->min_full_scale.mz);
+  result.fx = get_s16(&channel->min_full_scale.fx);
+  result.fy = get_s16(&channel->min_full_scale.fy);
+  result.fz = get_s16(&channel->min_full_scale.fz);
+  result.mx = get_s16(&channel->min_full_scale.mx);
+  result.my = get_s16(&channel->min_full_scale.my);
+  result.mz = get_s16(&channel->min_full_scale.mz);
   return result;
 }
  
 static six_axis_t get_max_full_scales(volatile jr3_channel_t *channel)
 {
   six_axis_t result;
-  result.fx = get_s16(channel->max_full_scale.fx);
-  result.fy = get_s16(channel->max_full_scale.fy);
-  result.fz = get_s16(channel->max_full_scale.fz);
-  result.mx = get_s16(channel->max_full_scale.mx);
-  result.my = get_s16(channel->max_full_scale.my);
-  result.mz = get_s16(channel->max_full_scale.mz);
+  result.fx = get_s16(&channel->max_full_scale.fx);
+  result.fy = get_s16(&channel->max_full_scale.fy);
+  result.fz = get_s16(&channel->max_full_scale.fz);
+  result.mx = get_s16(&channel->max_full_scale.mx);
+  result.my = get_s16(&channel->max_full_scale.my);
+  result.mz = get_s16(&channel->max_full_scale.mz);
   return result;
 }
  
@@ -290,7 +290,8 @@ static int jr3_pci_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
 
     result = insn->n;
     if (p->state != state_jr3_done || 
-       (get_u16(p->channel->errors) & 0xe800) != 0) {
+       (get_u16(&p->channel->errors) & (watch_dog | watch_dog2 | 
+                                        sensor_change))) {
       /* No sensor or sensor changed */
       if (p->state == state_jr3_done) {
        /* Restart polling */
@@ -310,28 +311,28 @@ static int jr3_pci_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
          int F = 0;
          switch (axis) {
            case 0: {
-             F = get_s16(p->channel->filter[filter].fx);
+             F = get_s16(&p->channel->filter[filter].fx);
            } break;
            case 1: {
-             F = get_s16(p->channel->filter[filter].fy);
+             F = get_s16(&p->channel->filter[filter].fy);
            } break;
            case 2: {
-             F = get_s16(p->channel->filter[filter].fz);
+             F = get_s16(&p->channel->filter[filter].fz);
            } break;
            case 3: {
-             F = get_s16(p->channel->filter[filter].mx);
+             F = get_s16(&p->channel->filter[filter].mx);
            } break;
            case 4: {
-             F = get_s16(p->channel->filter[filter].my);
+             F = get_s16(&p->channel->filter[filter].my);
            } break;
            case 5: {
-             F = get_s16(p->channel->filter[filter].mz);
+             F = get_s16(&p->channel->filter[filter].mz);
            } break;
            case 6: {
-             F = get_s16(p->channel->filter[filter].v1);
+             F = get_s16(&p->channel->filter[filter].v1);
            } break;
            case 7: {
-             F = get_s16(p->channel->filter[filter].v2);
+             F = get_s16(&p->channel->filter[filter].v2);
            } break;
          }
          data[i] = F + 0x4000;
@@ -340,13 +341,13 @@ static int jr3_pci_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
        if (p->state != state_jr3_done) {
          data[i] = 0;
        } else {
-         data[i] = get_u16(p->channel->model_no);
+         data[i] = get_u16(&p->channel->model_no);
        }
       } else if (channel == 57) {
        if (p->state != state_jr3_done) {
          data[i] = 0;
        } else {
-         data[i] = get_u16(p->channel->serial_no);
+         data[i] = get_u16(&p->channel->serial_no);
        }
       }
     }
@@ -480,22 +481,23 @@ static poll_delay_t jr3_pci_poll_subdevice(comedi_subdevice *s)
 
   if (p) {
     volatile jr3_channel_t *channel = p->channel;
-    int errors = get_u16(channel->errors);
+    int errors = get_u16(&channel->errors);
     
     if (errors != p->errors) {
       printk("Errors: %x -> %x\n", p->errors, errors);
       p->errors = errors;
     }
-    if ((errors & 0xe800) != 0) {
+    if (errors & (watch_dog | watch_dog2 | sensor_change)) {
       // Sensor communication lost, force poll mode
       p->state = state_jr3_poll;
       
     }
     switch (p->state) {
       case state_jr3_poll: {
-       u16 model_no = get_u16(channel->model_no);
-       u16 serial_no = get_u16(channel->serial_no);
-       if ((errors & 0xe000) != 0 || model_no == 0 || serial_no == 0) {
+       u16 model_no = get_u16(&channel->model_no);
+       u16 serial_no = get_u16(&channel->serial_no);
+       if ((errors & (watch_dog | watch_dog2)) || 
+           model_no == 0 || serial_no == 0) {
          // Still no sensor, keep on polling. Since it takes up to 
          // 10 seconds for offsets to stabilize, polling each
          // second should suffice.
@@ -514,8 +516,8 @@ static poll_delay_t jr3_pci_poll_subdevice(comedi_subdevice *s)
        } else {
          transform_t transf;
   
-         p->model_no = get_u16(channel->model_no);
-         p->serial_no = get_u16(channel->serial_no);
+         p->model_no = get_u16(&channel->model_no);
+         p->serial_no = get_u16(&channel->serial_no);
 
          printk("Setting transform for channel %d\n", p->channel_no);
          printk("Sensor Model     = %i\n", p->model_no);
@@ -584,22 +586,22 @@ static poll_delay_t jr3_pci_poll_subdevice(comedi_subdevice *s)
 
          // Use ranges in kN or we will overflow arount 2000N!
          full_scale = &channel->full_scale;
-         p->range[0].range.min = -get_s16(full_scale->fx) * 1000;
-         p->range[0].range.max =  get_s16(full_scale->fx) * 1000;
-         p->range[1].range.min = -get_s16(full_scale->fy) * 1000;
-         p->range[1].range.max =  get_s16(full_scale->fy) * 1000;
-         p->range[2].range.min = -get_s16(full_scale->fz) * 1000;
-         p->range[2].range.max =  get_s16(full_scale->fz) * 1000;
-         p->range[3].range.min = -get_s16(full_scale->mx) * 100;
-         p->range[3].range.max =  get_s16(full_scale->mx) * 100;
-         p->range[4].range.min = -get_s16(full_scale->my) * 100;
-         p->range[4].range.max =  get_s16(full_scale->my) * 100;
-         p->range[5].range.min = -get_s16(full_scale->mz) * 100;
-         p->range[5].range.max =  get_s16(full_scale->mz) * 100;
-         p->range[6].range.min = -get_s16(full_scale->v1) * 100; // ??
-         p->range[6].range.max =  get_s16(full_scale->v1) * 100; // ??
-         p->range[7].range.min = -get_s16(full_scale->v2) * 100; // ??
-         p->range[7].range.max =  get_s16(full_scale->v2) * 100; // ??
+         p->range[0].range.min = -get_s16(&full_scale->fx) * 1000;
+         p->range[0].range.max =  get_s16(&full_scale->fx) * 1000;
+         p->range[1].range.min = -get_s16(&full_scale->fy) * 1000;
+         p->range[1].range.max =  get_s16(&full_scale->fy) * 1000;
+         p->range[2].range.min = -get_s16(&full_scale->fz) * 1000;
+         p->range[2].range.max =  get_s16(&full_scale->fz) * 1000;
+         p->range[3].range.min = -get_s16(&full_scale->mx) * 100;
+         p->range[3].range.max =  get_s16(&full_scale->mx) * 100;
+         p->range[4].range.min = -get_s16(&full_scale->my) * 100;
+         p->range[4].range.max =  get_s16(&full_scale->my) * 100;
+         p->range[5].range.min = -get_s16(&full_scale->mz) * 100;
+         p->range[5].range.max =  get_s16(&full_scale->mz) * 100;
+         p->range[6].range.min = -get_s16(&full_scale->v1) * 100; // ??
+         p->range[6].range.max =  get_s16(&full_scale->v1) * 100; // ??
+         p->range[7].range.min = -get_s16(&full_scale->v2) * 100; // ??
+         p->range[7].range.max =  get_s16(&full_scale->v2) * 100; // ??
          p->range[8].range.min = 0;
          p->range[8].range.max = 65535;
 
@@ -623,12 +625,12 @@ static poll_delay_t jr3_pci_poll_subdevice(comedi_subdevice *s)
          result = poll_delay_min_max(20, 100);
        } else {
          printk("Default offsets %d %d %d %d %d %d\n",
-                get_s16(channel->offsets.fx),
-                get_s16(channel->offsets.fy),
-                get_s16(channel->offsets.fz),
-                get_s16(channel->offsets.mx),
-                get_s16(channel->offsets.my),
-                get_s16(channel->offsets.mz));
+                get_s16(&channel->offsets.fx),
+                get_s16(&channel->offsets.fy),
+                get_s16(&channel->offsets.fz),
+                get_s16(&channel->offsets.mx),
+                get_s16(&channel->offsets.my),
+                get_s16(&channel->offsets.mz));
 
          set_s16(&channel->offsets.fx, 0);
          set_s16(&channel->offsets.fy, 0);
@@ -829,7 +831,7 @@ static int jr3_pci_attach(comedi_device *dev, comedi_devconfig *it)
   // as much as we can read firmware version
   msleep_interruptible(25);
   for (i=0 ; i < 0x18 ; i++){
-    printk("%c", get_u16(devpriv->iobase->channel[0].data.copyright[i])>>8);
+    printk("%c", get_u16(&devpriv->iobase->channel[0].data.copyright[i])>>8);
   }
 
   // Start card timer
index dcb0c9bf5328fd5abe04e18905f5ad75466eebe6..03b37bc0882d58f98b051126f9dfcacda6d2d453 100644 (file)
@@ -1,43 +1,27 @@
 // Helper types to take care of the fact that the DSP card memory
 //   is 16 bits, but aligned on a 32 bit PCI boundary
-typedef union {
-  u8 as_u8;
-  u16 as_u16;
-  u32 as_u32;
-} u_val_t;
-
-typedef union {
-  s8 as_s8;
-  s16 as_s16;
-  s32 as_s32;
-} s_val_t;
-
-static inline u16 get_u16(volatile u_val_t val) 
+typedef u32 u_val_t;
+
+typedef s32 s_val_t;
+
+static inline u16 get_u16(volatile const u_val_t *p) 
 {
-  u_val_t tmp;
-  tmp.as_u32 = le32_to_cpu(val.as_u32);
-  return tmp.as_u16;
+  return (u16)readl(p);
 } 
 
 static inline void set_u16(volatile u_val_t *p, u16 val) 
 {
-  u_val_t tmp;
-  tmp.as_u16 = val;
-  p->as_u32 = cpu_to_le32(tmp.as_u32);
+  writel(val, p);
 } 
 
-static inline s16 get_s16(volatile s_val_t val
+static inline s16 get_s16(volatile const s_val_t *p
 {
-  s_val_t tmp;
-  tmp.as_s32 = le32_to_cpu(val.as_s32);
-  return tmp.as_s16;
+  return (s16)readl(p);
 } 
 
 static inline void set_s16(volatile s_val_t *p, s16 val) 
 {
-  s_val_t tmp;
-  tmp.as_s16 = val;
-  p->as_s32 = cpu_to_le32(tmp.as_s32);
+  writel(val, p);
 } 
 
 // The raw data is stored in a format which facilitates rapid
@@ -90,75 +74,116 @@ typedef struct six_axis_array
   s_val_t mz;
 } six_axis_array_t;
 
-// VECT_BITS
-// Indicates which axis are to be used when computing the vectors. A vector
-// is composed by 3 components and its "magnitude" is placed in V1 and V2.
-// V1 defaults to a force vector and V2 defaults to a moment vector.
-// Setting changeV1 or changeV2 will change that vector to be the opposite of
-// its default.
-
-// *** Check this norby ***
-// This is badly defined at JR3 Manual. Correct definition follows:
-typedef struct vect_bits
-{
- unsigned fx : 1;
- unsigned fy : 1;
- unsigned fz : 1;
- unsigned mx : 1;
- unsigned my : 1;
- unsigned mz : 1;
- unsigned changeV1 : 1;
- unsigned changeV2 : 1;
- unsigned reserved : 8;
-} vect_bits;
-
-// WARNINGS
-// Bit pattern for the warning word: xx_near_sat means that a near saturation
-// has been reached or exceeded.
-typedef struct warning_bits
-{
- unsigned fx_near_sat : 1;
- unsigned fy_near_sat : 1;
- unsigned fz_near_sat : 1;
- unsigned mx_near_sat : 1;
- unsigned my_near_sat : 1;
- unsigned mz_near_sat : 1;
- unsigned reserved : 10;
-} warning_bits;
+// VECT_BITS 
+// The vect_bits structure shows the layout for indicating
+// which axes to use in computing the vectors. Each bit signifies
+// selection of a single axis. The V1x axis bit corresponds to a hex
+// value of 0x0001 and the V2z bit corresponds to a hex value of
+// 0x0020. Example: to specify the axes V1x, V1y, V2x, and V2z the
+// pattern would be 0x002b. Vector 1 defaults to a force vector and
+// vector 2 defaults to a moment vector. It is possible to change one
+// or the other so that two force vectors or two moment vectors are
+// calculated. Setting the changeV1 bit or the changeV2 bit will
+// change that vector to be the opposite of its default. Therefore to
+// have two force vectors, set changeV1 to 1.
+
+typedef enum {
+  fx = 0x0001,
+  fy = 0x0002,
+  fz = 0x0004,
+  mx = 0x0008,
+  my = 0x0010,
+  mz = 0x0020,
+  changeV2 = 0x0040,
+  changeV1 = 0x0080
+} vect_bits_t;
+
+// WARNING_BITS
+// The warning_bits structure shows the bit pattern for the warning
+// word. The bit fields are shown from bit 0 (lsb) to bit 15 (msb).
+//
+// XX_NEAR_SET
+// The xx_near_sat bits signify that the indicated axis has reached or
+// exceeded the near saturation value.
+
+typedef enum {
+  fx_near_sat = 0x0001,
+  fy_near_sat = 0x0002,
+  fz_near_sat = 0x0004,
+  mx_near_sat = 0x0008,
+  my_near_sat = 0x0010,
+  mz_near_sat = 0x0020
+} warning_bits_t;
 
 // ERROR_BITS
-// Bit pattern for the error word:
-// 1. xx_sat means that a near saturation has been reached or exceeded.
-// 2. memory_error indicates RAM memory error during power up.
-// 3. sensor_change indicates that the sensor plugged in (different from the
-//    original one) has passed CRC check. The user must reset this bit.
-// 4. system_busyindicates system busy: transf. change, new full scale or new
-//    sennsor plugged in.
-// 5. cal_crc_bad means that it was a problem transmiting the calibration data
-//    stored inside the sensor. If this bit does not come to zero 2s after the
-//    sensor has been plugged in, there is a problem with the sensor's calibra-
-//    tion data.
-// 6. watch_dog2 indicates that sensor data and clock are being received.
-// 7. watch_dog indicates that data line seems to be acting correctly.
-// If either watch dog barks, the sensor data is not beig receive correctly.
-#if 0
-typedef struct error_bits
-{
- unsigned fx_sat : 1;
- unsigned fy_sat : 1;
- unsigned fz_sat : 1;
- unsigned mx_sat : 1;
- unsigned my_sat : 1;
- unsigned mz_sat : 1;
- unsigned reserved : 4;
- unsigned memory_error : 1;
- unsigned sensor_change : 1;
- unsigned system_busy : 1;
- unsigned cal_crc_bad : 1;
- unsigned watch_dog2 : 1;
- unsigned watch_dog : 1;
-} error_bits;
-#endif
+// XX_SAT
+// MEMORY_ERROR
+// SENSOR_CHANGE
+// 
+// The error_bits structure shows the bit pattern for the error word.
+// The bit fields are shown from bit 0 (lsb) to bit 15 (msb). The
+// xx_sat bits signify that the indicated axis has reached or exceeded
+// the saturation value. The memory_error bit indicates that a problem
+// was detected in the on-board RAM during the power-up
+// initialization. The sensor_change bit indicates that a sensor other
+// than the one originally plugged in has passed its CRC check. This
+// bit latches, and must be reset by the user.
+//
+// SYSTEM_BUSY
+//
+// The system_busy bit indicates that the JR3 DSP is currently busy
+// and is not calculating force data. This occurs when a new
+// coordinate transformation, or new sensor full scale is set by the
+// user. A very fast system using the force data for feedback might
+// become unstable during the approximately 4 ms needed to accomplish
+// these calculations. This bit will also become active when a new
+// sensor is plugged in and the system needs to recalculate the
+// calibration CRC.
+//
+// CAL_CRC_BAD
+//
+// The cal_crc_bad bit indicates that the calibration CRC has not
+// calculated to zero. CRC is short for cyclic redundancy code. It is
+// a method for determining the integrity of messages in data
+// communication. The calibration data stored inside the sensor is
+// transmitted to the JR3 DSP along with the sensor data. The
+// calibration data has a CRC attached to the end of it, to assist in
+// determining the completeness and integrity of the calibration data
+// received from the sensor. There are two reasons the CRC may not
+// have calculated to zero. The first is that all the calibration data
+// has not yet been received, the second is that the calibration data
+// has been corrupted. A typical sensor transmits the entire contents
+// of its calibration matrix over 30 times a second. Therefore, if
+// this bit is not zero within a couple of seconds after the sensor
+// has been plugged in, there is a problem with the sensor's
+// calibration data.
+//
+// WATCH_DOG
+// WATCH_DOG2
+//
+// The watch_dog and watch_dog2 bits are sensor, not processor, watch
+// dog bits. Watch_dog indicates that the sensor data line seems to be
+// acting correctly, while watch_dog2 indicates that sensor data and
+// clock are being received. It is possible for watch_dog2 to go off
+// while watch_dog does not. This would indicate an improper clock
+// signal, while data is acting correctly. If either watch dog barks,
+// the sensor data is not being received correctly.
+
+typedef enum {
+  fx_sat = 0x0001,
+  fy_sat = 0x0002,
+  fz_sat = 0x0004,
+  mx_sat = 0x0008,
+  my_sat = 0x0010,
+  mz_sat = 0x0020,
+  memory_error = 0x0400,
+  sensor_change = 0x0800,
+  system_busy = 0x1000,
+  cal_crc_bad = 0x2000,
+  watch_dog2 = 0x4000,
+  watch_dog = 0x8000
+} error_bits_t;
+
 
 // THRESH_STRUCT
 // This structure shows the layout for a single threshold packet inside of a